Skip to content

v1.0.0

Choose a tag to compare

@Horuse Horuse released this 11 May 16:36
· 7 commits to main since this release

Breaking Changes

  • 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: dropDurationdrop, returnDurationreturn, slotCollapseDurationslotCollapse, swapDurationlayout. 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.
  • Pluggable Behavior plugins. Custom plugins implement wrapDropAnimation(next, ctx) and/or expose autoScrollConfig. New exports: Behavior, BehaviorContext, AutoScrollConfig, autoScroll, scrollSync, ScrollSyncOptions.
  • 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.