CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-shopify--draggable

The JavaScript Drag & Drop library your grandparents warned you about.

Pending
Overview
Eval results
Files

core-draggable.mddocs/

Core Draggable

The base Draggable class provides fundamental drag-and-drop functionality with container management, event handling, and plugin system. It serves as the foundation for all specialized draggable types.

Capabilities

Draggable Constructor

Creates a new draggable instance with specified containers and options.

/**
 * Creates a new draggable instance
 * @param containers - Elements that contain draggable items
 * @param options - Configuration options for drag behavior
 */
constructor(containers: DraggableContainer, options?: DraggableOptions);

type DraggableContainer = HTMLElement | HTMLElement[] | NodeList;

Usage Example:

import { Draggable } from "@shopify/draggable";

// Single container
const draggable = new Draggable(document.querySelector('.container'), {
  draggable: '.item',
  delay: 150
});

// Multiple containers
const containers = document.querySelectorAll('.drag-container');
const multiContainer = new Draggable(containers, {
  draggable: '.draggable-item'
});

Instance Management

Methods for managing the draggable instance lifecycle.

/**
 * Destroys the draggable instance and removes all event listeners
 */
destroy(): void;

/**
 * Cancels the current drag operation immediately
 */
cancel(): void;

/**
 * Returns true if currently dragging an element
 */
isDragging(): boolean;

Event Handling

Methods for managing event listeners and triggering custom events.

/**
 * Adds an event listener for drag events
 * @param eventName - Name of the event to listen for
 * @param callback - Function to call when event occurs
 * @returns This draggable instance for chaining
 */
on<T extends TEventListType>(eventName: T, callback: (event: GetEventByEventName<T>) => void): this;

/**
 * Removes an event listener
 * @param eventName - Name of the event
 * @param callback - Function to remove
 * @returns This draggable instance for chaining
 */
off<T extends TEventListType>(eventName: T, callback: (event: GetEventByEventName<T>) => void): this;

/**
 * Triggers a custom event
 * @param event - Event instance to trigger
 * @returns This draggable instance for chaining
 */
trigger(event: AbstractEvent): void;

Usage Example:

const draggable = new Draggable(containers, options);

// Add event listeners
draggable.on('drag:start', (event) => {
  console.log('Drag started:', event.source);
  // Optionally cancel the drag
  // event.cancel();
});

draggable.on('drag:move', (event) => {
  console.log('Dragging over:', event.over);
});

// Remove event listener
const handleDragStop = (event) => {
  console.log('Drag stopped');
};
draggable.on('drag:stop', handleDragStop);
draggable.off('drag:stop', handleDragStop);

Container Management

Methods for managing draggable containers after initialization.

/**
 * Adds containers to the draggable instance
 * @param containers - Container elements to add
 * @returns This draggable instance for chaining
 */
addContainer(...containers: HTMLElement[]): this;

/**
 * Removes containers from the draggable instance
 * @param containers - Container elements to remove
 * @returns This draggable instance for chaining
 */
removeContainer(...containers: HTMLElement[]): this;

/**
 * Returns all draggable elements across all containers
 */
getDraggableElements(): HTMLElement[];

/**
 * Returns draggable elements for a specific container
 * @param container - Container to get elements from
 */
getDraggableElementsForContainer(container: HTMLElement): HTMLElement[];

Plugin Management

Methods for adding and removing plugins dynamically.

/**
 * Adds plugins to the draggable instance
 * @param plugins - Plugin classes to add
 * @returns This draggable instance for chaining
 */
addPlugin(...plugins: (typeof AbstractPlugin)[]): this;

/**
 * Removes plugins from the draggable instance
 * @param plugins - Plugin classes to remove
 * @returns This draggable instance for chaining
 */
removePlugin(...plugins: (typeof AbstractPlugin)[]): this;

Sensor Management

Methods for managing input sensors.

/**
 * Adds sensors to the draggable instance
 * @param sensors - Sensor classes to add
 * @returns This draggable instance for chaining
 */
addSensor(...sensors: (typeof Sensor)[]): this;

/**
 * Removes sensors from the draggable instance
 * @param sensors - Sensor classes to remove
 * @returns This draggable instance for chaining
 */
removeSensor(...sensors: (typeof Sensor)[]): this;

CSS Class Management

Methods for working with CSS classes applied during drag operations.

/**
 * Returns the first CSS class name for a class identifier
 * @param name - Class identifier name
 */
getClassNameFor(name: DraggableClassNames): string;

/**
 * Returns all CSS class names for a class identifier
 * @param name - Class identifier name
 */
getClassNamesFor(name: DraggableClassNames): string[];

Static Properties

Static properties available on the Draggable class.

class Draggable {
  static Plugins: {
    Announcement: typeof Announcement;
    Focusable: typeof Focusable;
    Mirror: typeof Mirror;
    Scrollable: typeof Scrollable;
  };

  static Sensors: {
    MouseSensor: typeof MouseSensor;
    TouchSensor: typeof TouchSensor;
  };
}

Options Interface

interface DraggableOptions {
  /** CSS selector for draggable elements within containers */
  draggable?: string;
  /** Minimum distance in pixels before drag starts */
  distance?: number;
  /** CSS selector, elements, or function defining drag handles */
  handle?: string | NodeList | HTMLElement[] | HTMLElement | ((currentElement: HTMLElement) => HTMLElement);
  /** Delay before drag starts (number or per-input delays) */
  delay?: number | DelayOptions;
  /** Timeout in milliseconds for removing placed classes after drop */
  placedTimeout?: number;
  /** Array of plugin classes to add */
  plugins?: (typeof AbstractPlugin)[];
  /** Array of sensor instances to use */
  sensors?: Sensor[];
  /** Plugins and sensors to exclude from defaults */
  exclude?: {
    plugins?: (typeof AbstractPlugin)[];
    sensors?: (typeof Sensor)[];
  };
  /** CSS class names for different drag states */
  classes?: {[key in DraggableClassNames]: string | string[]};
  /** Accessibility announcement options */
  announcements?: AnnouncementOptions;
  /** Collidable elements for collision detection */
  collidables?: Collidables;
  /** Mirror plugin options */
  mirror?: MirrorOptions;
  /** Scrollable plugin options */
  scrollable?: ScrollableOptions;
  /** Swap animation options */
  swapAnimation?: SwapAnimationOptions;
  /** Sort animation options */
  sortAnimation?: SortAnimationOptions;
}

interface DelayOptions {
  mouse?: number;
  drag?: number;  
  touch?: number;
}

type DraggableClassNames =
  | 'body:dragging'
  | 'container:dragging'
  | 'source:dragging'
  | 'source:placed'
  | 'container:placed'
  | 'draggable:over'
  | 'container:over'
  | 'source:original'
  | 'mirror';

Usage Example:

const draggable = new Draggable(containers, {
  draggable: '.drag-item',
  handle: '.drag-handle',
  delay: { mouse: 100, touch: 150 },
  distance: 10,
  placedTimeout: 1000,
  exclude: {
    sensors: [TouchSensor], // Exclude touch sensor on desktop
    plugins: [Announcement] // Exclude announcement plugin
  },
  classes: {
    'source:dragging': 'my-dragging-class',
    'body:dragging': 'drag-in-progress'
  },
  mirror: {
    constrainDimensions: true,
    xAxis: true,
    yAxis: true
  },
  scrollable: {
    speed: 15,
    sensitivity: 50
  }
});

Install with Tessl CLI

npx tessl i tessl/npm-shopify--draggable

docs

core-draggable.md

droppable.md

events.md

index.md

plugins.md

sensors.md

sortable.md

swappable.md

tile.json