← All @molecule/* packages · App templates
@molecule/app-drag-drop-dndkitProvider bond · drag-drop · App (browser) · v1.0.1 · Apache-2.0
Headless dnd-kit-style drag-drop state provider for @molecule/app-drag-drop (no @dnd-kit dependency; app owns the drag listeners)
npm install @molecule/app-drag-drop-dndkitnpm · Source on GitHub · Implements @molecule/app-drag-drop
@molecule/app-drag-drop-dndkit is a provider bond on the app (browser) side: it implements the drag-drop core interface (@molecule/app-drag-drop) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
import { provider } from '@molecule/app-drag-drop-dndkit'
import { setProvider } from '@molecule/app-drag-drop'
setProvider(provider)Works with: @molecule/app-drag-drop
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Real @dnd-kit drag-drop provider for molecule.dev.
Implements DragDropProvider from @molecule/app-drag-drop against
@dnd-kit/*. Two layers ship here:
createSortable/createDraggable/createDroppable — whose reorders use
@dnd-kit's own arrayMove.DndContext / SortableContext / useSortable with pointer and
keyboard sensors and, on drop, reorders and invokes the core onReorder
with the new order. This is the shipped DOM-event bridge; a drag actually
reorders the list (mouse, touch, or keyboard).import { provider } from '@molecule/app-drag-drop-dndkit'
import { setProvider } from '@molecule/app-drag-drop'
setProvider(provider)
import { SortableList, useSortableItem } from '@molecule/app-drag-drop-dndkit'
// Dropping a row calls onReorder(newOrder); Space + arrow keys reorder too.
;<SortableList items={items} onReorder={setItems}>
<ul>
{items.map((item) => (
<Row key={item.id} item={item} />
))}
</ul>
</SortableList>
provider
npm install @molecule/app-drag-drop-dndkit @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities @molecule/app-drag-drop react react-dom
npm install -D @types/react
DndKitConfigConfiguration options for the dnd-kit drag-drop provider. activationDelay
and activationDistance are honored by the React binding's pointer sensor
(see SortableList / createSortableSensors).
interface DndKitConfig {
/**
* Activation delay in milliseconds before a drag starts. A positive value
* makes the pointer sensor use a delay+tolerance constraint — useful for
* distinguishing between click/tap and drag on touch devices. Takes
* precedence over `activationDistance`. Defaults to `0` (immediate).
*/
activationDelay?: number
/**
* Distance in pixels a pointer must travel before a drag starts. A positive
* value makes the pointer sensor use a distance constraint (ignored when
* `activationDelay` is set). Defaults to `0` (immediate).
*/
activationDistance?: number
/**
* Whether Escape cancels a drag. `@dnd-kit`'s keyboard sensor cancels on Escape
* by default, so this is effectively `true`. Defaults to `true`.
*/
cancelOnEscape?: boolean
}
DndKitDraggableInstanceExtended draggable instance with internal methods for framework bindings.
interface DndKitDraggableInstance extends DraggableInstance {
/**
* Sets the dragging state. Called by framework bindings.
*
* @param value - Whether the item is being dragged.
*/
_setDragging(value: boolean): void
/**
* Returns the current data payload.
*
* @returns The data associated with this draggable.
*/
_getData(): unknown
/**
* Returns whether dragging is disabled.
*
* @returns `true` if disabled.
*/
_isDisabled(): boolean
}
DndKitDroppableInstanceExtended droppable instance with internal methods for framework bindings.
interface DndKitDroppableInstance extends DroppableInstance {
/**
* Sets the hover state. Called by framework bindings.
*
* @param value - Whether a draggable is over this zone.
*/
_setOver(value: boolean): void
/**
* Checks if this zone accepts a given type.
*
* @param type - The draggable type to check.
* @returns `true` if the type is accepted.
*/
_accepts(type?: string): boolean
/**
* Invokes the onDrop handler. Called by framework bindings on drop.
*
* @param data - The data payload from the dropped draggable.
* @param draggableId - The identifier of the dropped draggable.
*/
_handleDrop(data: unknown, draggableId: string): void
/**
* Returns whether the droppable is disabled.
*
* @returns `true` if disabled.
*/
_isDisabled(): boolean
}
DndKitSortableInstanceExtended sortable instance with internal methods for framework bindings.
interface DndKitSortableInstance<T extends { id: string }> extends SortableInstance<T> {
/**
* Sets the active drag id. Called by framework bindings when a drag starts.
*
* @param id - The id of the item being dragged, or `null` when drag ends.
*/
_setActiveId(id: string | null): void
/**
* Completes a reorder from one index to another. Called by framework
* bindings on drag end.
*
* @param fromIndex - The source index.
* @param toIndex - The destination index.
*/
_reorder(fromIndex: number, toIndex: number): void
/**
* Returns whether sorting is disabled.
*
* @returns `true` if disabled.
*/
_isDisabled(): boolean
}
SortableDragEndContextInputs for {@link handleSortableDragEnd}.
interface SortableDragEndContext<T extends { id: string }> {
/** The current ordered items. */
items: T[]
/** Core reorder callback, invoked with the new order after a real move. */
onReorder: (items: T[]) => void
/** Whether sorting is disabled — suppresses the reorder. Defaults to `false`. */
disabled?: boolean
/** Optional passthrough of the core drag-end event. */
onDragEnd?: (event: DragEndEvent) => void
}
SortableItemStateThe wiring returned by {@link useSortableItem} for a single sortable row.
interface SortableItemState {
/** Ref for the row element (the sortable node). */
setNodeRef: (node: HTMLElement | null) => void
/** Ref for an optional drag handle — spread `listeners` on this element for handle-only dragging. */
setActivatorNodeRef: (element: HTMLElement | null) => void
/** Accessibility attributes (role/tabindex/aria) — spread onto the row for keyboard support. */
attributes: DraggableAttributes
/** Pointer/keyboard drag listeners — spread onto the row body or the handle. */
listeners: DraggableSyntheticListeners
/** Inline transform/transition styles that animate the row while sorting. */
style: CSSProperties
/** `true` while this row is being dragged. */
isDragging: boolean
/** `true` while another dragged row is over this one. */
isOver: boolean
}
SortableListPropsProps for {@link SortableList}.
interface SortableListProps<T extends { id: string }> {
/** Ordered items to render. Each must have a stable string `id`. */
items: T[]
/**
* Called with the full reordered array when a drag completes a move. This is
* the core `SortableOptions['onReorder']` callback — persist the new order.
*
* @param items - The reordered items.
*/
onReorder: (items: T[]) => void
/** Sort axis. Selects the default sorting strategy. Defaults to `'vertical'`. */
axis?: SortableAxis
/** Explicit sorting strategy override. */
strategy?: SortableStrategy
/** Disable all drag interactions. Defaults to `false`. */
disabled?: boolean
/** Sensor activation thresholds (pointer delay / distance). */
config?: DndKitConfig
/** Optional passthrough: fired when a drag starts. */
onDragStart?: (event: DragStartEvent) => void
/** Optional passthrough: fired while dragging over a target. */
onDragOver?: (event: DragOverEvent) => void
/** Optional passthrough: fired when a drag ends (before/besides `onReorder`). */
onDragEnd?: (event: DragEndEvent) => void
/** The rendered list — items using {@link useSortableItem} for their rows. */
children: ReactNode
}
UseSortableItemOptionsOptions for {@link useSortableItem}.
interface UseSortableItemOptions {
/** The sortable item's id — must match the `id` of the corresponding item. */
id: string
/** Arbitrary data carried with the drag (surfaced on drag events). */
data?: Record<string, unknown>
/** Whether this specific item is undraggable. Defaults to `false`. */
disabled?: boolean
}
createDndKitProvider(_config)Creates a dnd-kit-based drag-drop provider.
function createDndKitProvider(_config?: DndKitConfig): DragDropProvider
_config — Optional dnd-kit-specific configuration.Returns: A DragDropProvider backed by dnd-kit state management.
createSortableSensors(config)Builds the sensor descriptor list used by {@link SortableList}: a pointer
sensor (mouse/touch) and a keyboard sensor wired to
sortableKeyboardCoordinates so a sortable list is keyboard-accessible.
Exported so callers/tests can assert both sensors are present.
function createSortableSensors(
config?: DndKitConfig,
): (SensorDescriptor<PointerSensorOptions> | SensorDescriptor<KeyboardSensorOptions>)[]
config — dnd-kit provider configuration (activation thresholds).Returns: The pointer + keyboard sensor descriptors.
handleSortableDragEnd(event, context)Bridges a @dnd-kit drag-end to the core drag-drop contract. Emits the core
onDragEnd event, then — unless sorting is disabled, the drop landed nowhere,
or the item was dropped in place — reorders items with @dnd-kit's
arrayMove and invokes onReorder with the new order. This is the exact
handler {@link SortableList} passes to DndContext.onDragEnd, so a real drop
runs this code and onReorder fires with the reordered array.
function handleSortableDragEnd(event: DndKitDragEndEvent, context: SortableDragEndContext<T>): void
event — The @dnd-kit drag-end event (active / over).context — Items, callbacks, and disabled flag.resolveSortingStrategy(axis, strategy)Maps a molecule {@link SortableAxis}/{@link SortableStrategy} to a concrete
@dnd-kit sorting strategy. An explicit strategy wins; otherwise the axis
selects it (horizontal → horizontal list, both → grid, else vertical).
function resolveSortingStrategy(axis?: SortableAxis, strategy?: SortableStrategy): SortingStrategy
axis — The sort axis. Defaults to 'vertical'.strategy — An explicit strategy override.Returns: The @dnd-kit sorting strategy to pass to SortableContext.
SortableList(props)A real @dnd-kit sortable list. Wraps DndContext + SortableContext with a
pointer and a keyboard sensor and, on drop, reorders items and calls
onReorder with the new order (via {@link handleSortableDragEnd}). Render
the list itself as children, using {@link useSortableItem} for each row.
function SortableList(props: SortableListProps<T>): JSX.Element
props — {@link SortableListProps}.Returns: The drag-and-drop context wrapping the sortable list.
useSortableItem(options)Wraps @dnd-kit's useSortable for a single row inside a {@link SortableList}.
Spread attributes + listeners onto the row (or listeners onto a handle
bound with setActivatorNodeRef), attach setNodeRef, and apply style.
function useSortableItem(options: UseSortableItemOptions): SortableItemState
options — {@link UseSortableItemOptions}.Returns: The refs, attributes, listeners, and transform style for the row.
providerDefault dnd-kit drag-drop provider instance.
const provider: DragDropProvider
Implements @molecule/app-drag-drop interface.
Setup function to register this provider with the core interface:
import { setProvider } from '@molecule/app-drag-drop'
import { provider } from '@molecule/app-drag-drop-dndkit'
export function setupDragDropDndkit(): void {
setProvider(provider)
}
Peer dependencies:
@molecule/app-drag-drop >=1.0.1react ^18.0.0 || ^19.0.0react-dom ^18.0.0 || ^19.0.0@dnd-kit/core@dnd-kit/sortable@dnd-kit/utilities@molecule/app-drag-dropreactreact-domThe React binding requires react / react-dom (peer dependencies) since
@dnd-kit is React-only. The imperative store's extended instance types
(_-prefixed methods) remain available for consumers wiring their own
(non-@dnd-kit) drag events. DndKitConfig.activationDelay /
activationDistance are honored by the React binding's pointer sensor.
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual sortable lists / drop zones, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:
accept set takes only the draggable types it lists
and rejects the rest — a disallowed item does not land there and no onDrop
fires for it.disabled: true (on the item or
the whole sortable) a drag attempt does nothing, the order is unchanged, and
no reorder/drop callback fires.handle: true, only the drag-handle element starts a drag —
grabbing the item body anywhere else does not move it.