You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
scroll config replaced by behaviors[]. Auto-scroll and scroll-sync are now Behavior plugins; built-in factories autoScroll() and scrollSync(), both included by default. Per-droppable override via sortable({ behaviors }) / target({ behaviors }). controller.setScrollConfig removed — use controller.setBehaviors. ScrollConfig type replaced by AutoScrollConfig.
Simulator API consolidated. simulateReturn, simulateDrop, simulateSwap, simulateBatchSwap are replaced by controller.animateItem and controller.animateLayout. SimulateOptions removed; new types AnimateItemOptions, AnimateLayoutOptions, ContainerPosition.
Animation config unified under animation. Top-level preview option on DndController removed. Renames: dropDuration → drop, returnDuration → return, slotCollapseDuration → slotCollapse, swapDuration → layout. Preview delays moved into animation.preview.show / animation.preview.hide as DelayedTransition ({ delay, duration, easing }). siblingShift and ghostResize take a Transition; drop, return, slotCollapse, layout, keyboardFlight take a number or Transition.
controller.previewConfig and setPreviewConfig removed. Read from controller.animation, patch via controller.setAnimation.
Ghost rotation no longer applied by the library. Removed CSS vars --dnd-ghost-rotation, --dnd-ghost-rotation-duration and the .dnd-ghost--returning reset rule. Implement rotation in custom CSS if needed.
PreviewConfig and ScrollConfig types are no longer exported. Use AnimationConfig / AutoScrollConfig instead.
Features
Sortable virtualization via sortable({ virtual }). New VirtualSource and SortableSource types let a virtualizer drive zone geometry from live slot rects. Tested with virtua; other virtualizers should work via the same interface but are unverified. Grid layout falls back to DOM mode.
scrollSync({ threshold }) — engagement gated by the destination slot's visible fraction.
Ghost & preview auto-resize to the destination's item size, mixing target-sibling and dragged-item dimensions per layout. Exposed reactively as controller.dropPreviewSize. CSS vars --dnd-ghost-resize-duration / --dnd-ghost-resize-easing driven by animation.ghostResize.
Keyboard navigation expansions. Home / End, cross-axis hops between sibling containers, same-row / same-column grid movement, per-keystroke ghost flight to the live slot rect, lockstep scroll-into-view for off-screen targets. Iterates the full position list, so virtualized slots stay reachable. Tunable via animation.keyboardFlight.
Configurable easing for every animation. rAF-driven steps accept a number or { duration, easing }; CSS-driven steps (preview show/hide, siblingShift, ghostResize) gain matching easing fields. scrollSync inherits the wrapped step's easing.
parseEasing(str) helper exported for custom AnimationStep implementations.
New CSS vars--dnd-preview-easing-in, --dnd-preview-easing-out, --dnd-ghost-resize-easing written from controller.animation; user CSS still overrides.
Runtime setters: setBehaviors, setAnimation (deep-merge), setSensors, setAnnouncements, setModifiers, setDebug. No need to recreate the controller.
Default flex direction for sortable DndDroppable via :where(.dnd-droppable[data-dnd-layout='vertical'|'horizontal']). Consumer classes (Tailwind, custom) win without !important. Grid sortables get no default.
Droppable.itemCount and Droppable.isVirtualized getters expose data length and virtualization mode.
Per-call behaviors / easing override on animateItem.
animateLayout({ morph: true }) copies missing classes from pre- to post-state element so class-driven CSS transitions run in lockstep with the FLIP transform.
New exports: GhostSnippet, GhostSnippetProps, ZonesInvalidatedCallback.
Bug Fixes
Honour explicit spacing={0} on DndDraggable.
Clamp sortable drop zones to the container's scroll viewport.
Siblings no longer jump during slot collapse in scrollable sources.
Drop no longer fights the virtualizer's scroll-jump compensation.
Ghost tracks the tail preview correctly when the source slot collapses.
Repeated preview.hide() calls no longer leak collapse timers.
Overlapping animateLayout invocations reject with a clear error instead of corrupting state silently.
scrollSync now engages on tail previews in empty containers (degenerate-rect case).
Keyboard ghost flight reads the post-update tail spacing, so the first key after a drop lands at the correct rect.
KeyboardSensor no longer activates twice when Enter / Space bubbles from nested draggables.
Keyboard navigation no longer triggers auto-scroll (auto-scroll was tied to pointer updates).
Reactive prop updates on DndDraggable / DndDroppable / DndPreview propagate from the first read — entities are no longer pinned to the initial snapshot.
Post-drop rect reads in animateLayout happen against the updated DOM, fixing stale FLIP transforms.
package.json gains exports.import and exports.default conditions for correct ESM resolution.
Removed aria-grabbed from the dragged element (deprecated in ARIA 1.1).
Performance
Droppables mounting or unmounting mid-drag update zone derivations reactively instead of going stale until the next pointermove.
First-slot rect cached per drag session, avoiding a synchronous layout on every pointermove when computing dropPreviewSize.
Docs
New examples: virtualization, target-zones, behaviors live demo.
New pages: behaviors, VirtualSource, SSR FAQ. Examples updated to the consolidated simulator API and runtime setters.