svelte-dnd is a Svelte 5 drag-and-drop library for editor-style interfaces. It gives you a controller for interaction state plus Svelte attachments for draggable nodes, droppable regions, and resize handles.
It is built for cases like:
svelte-dnd has a peer dependency on svelte@^5.
Publishing is not live yet.
https://coming-soon.invalid/svelte-dnd<script lang="ts">
import {
createEditorController,
draggable,
droppable,
resizeHandle,
type CommittedInteraction
} from 'svelte-dnd';
const controller = createEditorController({
initialTransforms: {
card: { x: 48, y: 48 }
}
});
let commits = $state<CommittedInteraction[]>([]);
function handleCommit(commit: CommittedInteraction) {
commits = [commit, ...commits];
}
</script>
<div class="canvas" {@attach droppable({ controller, id: 'canvas' })}>
<div
class="card"
{@attach draggable({
controller,
id: 'card',
onCommit: handleCommit
})}
>
Drag me
<button
type="button"
class="handle"
aria-label="Resize card"
{@attach resizeHandle({
controller,
id: 'card',
handle: 'se',
onCommit: handleCommit
})}
></button>
</div>
</div>
createEditorController(...).draggable(...).droppable(...).resizeHandle(...) attachments when an item should be resizable.onCommit or controller.subscribe(...) to react to completed interactions and live state.During pointer movement the library maintains preview transforms for immediate visual feedback. On release it commits the interaction and reports the final transform plus the active droppable target, if any.
createEditorController(options?)Creates the controller used by all attachments.
Options:
pixelSnap?: booleaninitialTransforms?: Record<string, TransformInput>Useful instance methods:
subscribe(listener) for live interaction stategetSnapshot() for current transforms and hover stategetTransform(id) to read the committed transform for a nodegetLiveTransform(id) to read the current preview transform during interactionsetTransform(id, transform) to update a node programmaticallycommitActive() and cancelActive() for manual controldraggable(options)Makes an element draggable and registers it with the controller.
Options:
controlleridinitialTransform?data?disabled?lockAspectRatio?onCommit?droppable(options)Registers an element as a drop target.
Options:
controlleriddata?The element receives data-dnd-over="true" while it is the active hover target.
resizeHandle(options)Turns an element into a resize handle for a draggable node.
Options:
controlleridhandle: 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw'disabled?lockAspectRatio?onCommit?The package also exports lower-level helpers for custom integrations:
createEditorEnginecreateDefaultTransformcreateEditorPresetupdateTransformSessionidentityTransformtransformToCssmatrixToCss, translateMatrix, pointInRect, and rectFromDomRect