@vielzeug/dnd 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sortable.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./_shared.cjs"),t=require("./errors.cjs"),n=require("./_dev.cjs");var r=Symbol(`SortableScope`),i=`data-dnd-handle`,a=`data-dnd-item`,o=new WeakMap,s={container:!0,edgeThreshold:32,speed:18,viewport:!1};function c(e){let n=o.get(e);if(!n)throw new t.DndScopeError;return n}function l(e){return e===!1?null:e===!0||e===void 0?s:{container:e.container??!0,edgeThreshold:e.edgeThreshold??32,speed:e.speed??18,viewport:e.viewport??!1}}function u(e,t){return t.length!==e.length||t.some((t,n)=>t!==e[n])}function d(e){e.querySelectorAll(`[${i}]`).forEach(e=>{e.removeAttribute(i),e.removeAttribute(`draggable`),e.style.touchAction=``})}function f(e){typeof requestAnimationFrame==`function`&&(e.hideFrame=requestAnimationFrame(()=>{e.hideFrame=null,e.draggedEl.style.display=`none`}))}function p(e){e.hideFrame!==null&&(cancelAnimationFrame(e.hideFrame),e.hideFrame=null)}function m(e){p(e),e.draggedEl.style.display=e.originalDisplay,e.draggedEl.removeAttribute(`data-dragging`)}function h(e,t){e.initialOrders.has(t)||e.initialOrders.set(t,t.getOrderedIds())}function g(e,t){let n=e.active;n&&(m(n),n.originalParent.insertBefore(n.draggedEl,n.originalNextSibling),n.placeholder.remove(),e.active=null,n.source.notifyDragEnd(n.draggedId,t))}function _(e,t){let n=e.active;if(!n)return;let r=n.target,i=n.placeholder.parentElement;m(n),r&&e.handles.has(r)&&i?i.insertBefore(n.draggedEl,n.placeholder):n.originalParent.insertBefore(n.draggedEl,n.originalNextSibling),n.placeholder.remove(),e.active=null,n.source.notifyDragEnd(n.draggedId,t);for(let[t,r]of n.initialOrders){if(!e.handles.has(t))continue;let n=t.getOrderedIds();u(r,n)&&(t.notifyBeforeReorder(r,n),t.commitReorder(n))}}function v(e,t,n){if(!e.active)return;let{active:r}=e;n||!t.dataTransfer||t.dataTransfer.dropEffect===`none`||!r.target||!e.handles.has(r.target)||r.source.isDisabled()||r.target.isDisabled()?g(e,t):_(e,t)}function y(e,t,n,r){if(!r)return;let{container:i,edgeThreshold:a,speed:o,viewport:s}=r,c=t.getBoundingClientRect();if(n===`vertical`){i&&e.clientY<c.top+a?t.scrollTop-=o:i&&e.clientY>c.bottom-a&&(t.scrollTop+=o),s&&e.clientY<a?window.scrollBy({left:0,top:-o}):s&&e.clientY>window.innerHeight-a&&window.scrollBy({left:0,top:o});return}i&&e.clientX<c.left+a?t.scrollLeft-=o:i&&e.clientX>c.right-a&&(t.scrollLeft+=o),s&&e.clientX<a?window.scrollBy({left:-o,top:0}):s&&e.clientX>window.innerWidth-a&&window.scrollBy({left:o,top:0})}function b(e,t,n,r,i,a){let o=n(),s=o.indexOf(e);if(s<0)return null;let c=a===`vertical`?i===`ArrowDown`:i===`ArrowRight`,l=a===`vertical`?i===`ArrowUp`:i===`ArrowLeft`,u;if(c)u=Math.min(o.length-1,s+1);else if(l)u=Math.max(0,s-1);else if(i===`Home`)u=0;else if(i===`End`)u=o.length-1;else return null;if(u===s)return null;let d=o[u];return d?(t.insertBefore(e,u>s?d.nextSibling:d),e.focus(),r()):null}function x(){let t={active:null,disposables:new Set,handles:new Set},n=e.createDisposable(()=>{for(let e of t.disposables)e()}),i={get disposalSignal(){return n.disposalSignal},dispose:n.dispose,get disposed(){return n.disposed},get isDragging(){return t.active!==null},[r]:!0,[Symbol.dispose]:n[Symbol.dispose]};return o.set(i,t),i}function S(t){let{autoScroll:r=!0,axis:o=`vertical`,element:s,getKey:u,handle:p,keyboard:m=!0,placeholderClass:g=`dnd-placeholder`,scope:_=x()}=t,S=l(r),C=c(_);p!==void 0&&p.trim()===``&&n.warn(`handle option is an empty string — no handle elements will be found. Provide a valid CSS selector or omit the option.`);let w=()=>Array.from(s.children).filter(e=>e.hasAttribute(a)),T=()=>w().map(e=>u(e)),E=()=>{d(s),w().forEach(e=>{e.setAttribute(`role`,`listitem`),e.tabIndex=0,p?(e.removeAttribute(`draggable`),e.style.touchAction=``,e.querySelectorAll(p).forEach(e=>{e.setAttribute(i,``),e.setAttribute(`draggable`,`true`),e.style.touchAction=`none`})):(e.setAttribute(`draggable`,`true`),e.style.touchAction=`none`)})},D=()=>{let e=new Set;Array.from(s.children).forEach(t=>{let r=t;try{let t=u(r);t&&(e.has(t)?n.warn(`getKey returned the duplicate key "${t}" for two sibling items — onReorder's ids and applyReorder may become inconsistent. Ensure getKey returns a unique value per item.`):e.add(t),r.setAttribute(a,``))}catch(e){n.warn(`getKey threw for a child element — the item will not be sortable. Check your getKey implementation. ${String(e)}`)}}),E()},O=()=>{d(s),s.querySelectorAll(`[${a}]`).forEach(e=>{e.removeAttribute(a),e.removeAttribute(`draggable`),e.removeAttribute(`role`),e.removeAttribute(`tabindex`),e.style.touchAction=``})},k=e=>{let t=document.createElement(`div`);return t.className=g,t.setAttribute(`aria-hidden`,`true`),o===`horizontal`?t.style.width=`${e.offsetWidth}px`:t.style.height=`${e.offsetHeight}px`,t},A=null,j={commitReorder:e=>{if(!t.onReorder)return;let n={ids:e,setRevert(e){A=e}};t.onReorder(n)},getOrderedIds:T,isDisabled:()=>e.resolveDisabled(t.disabled),notifyBeforeReorder:(e,n)=>t.onBeforeReorder?.(e,n),notifyDragEnd:(e,n)=>t.onDragEnd?.(e,n),notifyDragStart:(e,n)=>t.onDragStart?.(e,n)};C.handles.add(j);let M=e=>{if(C.active||j.isDisabled())return;let n=e.target,r=n.closest(`[${a}]`);if(!r||p&&!n.closest(p))return;let i=r.parentElement;if(!i)return;let o=k(r),s=r.nextSibling,c=u(r),l=new Map;l.set(j,j.getOrderedIds()),r.setAttribute(`data-dragging`,``),i.insertBefore(o,s);let d={draggedEl:r,draggedId:c,hideFrame:null,initialOrders:l,originalDisplay:r.style.display,originalNextSibling:s,originalParent:i,placeholder:o,source:j,target:j};if(f(d),C.active=d,e.dataTransfer&&(e.dataTransfer.effectAllowed=`move`,e.dataTransfer.setData(`text/plain`,c),t.dragImage)){let n=typeof t.dragImage==`function`?t.dragImage(c,r,e):t.dragImage,[i,a]=t.dragImageOffset??[0,0];n&&e.dataTransfer.setDragImage(n,i,a)}j.notifyDragStart(d.draggedId,e)},N=e=>{let t=C.active;if(!t||t.source.isDisabled()||j.isDisabled())return;e.preventDefault(),y(e,s,o,S),h(t,j);let{draggedEl:n,placeholder:r}=t,i=e.target.closest(`[${a}]`);if(!i){r.parentElement!==s&&s.appendChild(r),t.target=j;return}if(i===n||i===r)return;let c=i.getBoundingClientRect(),l=o===`vertical`?e.clientY>=c.top+c.height/2:e.clientX>=c.left+c.width/2;s.insertBefore(r,l?i.nextSibling:i),t.target=j},P=e=>{let t=C.active;t&&(t.source.isDisabled()||j.isDisabled()||(e.preventDefault(),t.target=j))},F=e=>{C.active?.source===j&&v(C,e,!1)},I=e=>{if(!m||j.isDisabled())return;let t=e.target?.tagName;if(t===`INPUT`||t===`TEXTAREA`||t===`SELECT`)return;let n=e.target.closest(`[${a}]`);if(!n||!s.contains(n))return;let r=T(),i=b(n,s,w,T,e.key,o);i!==null&&(e.preventDefault(),j.notifyBeforeReorder(r,i),j.commitReorder(i))};D();let L=e.createDisposable(()=>{C.disposables.delete(L.dispose),C.active&&(C.active.source===j||C.active.target===j)&&v(C,new Event(`dragend`),!0),C.handles.delete(j),s.removeAttribute(`role`),O()});return s.setAttribute(`role`,`list`),s.addEventListener(`dragstart`,M,{signal:L.disposalSignal}),s.addEventListener(`dragover`,N,{signal:L.disposalSignal}),s.addEventListener(`drop`,P,{signal:L.disposalSignal}),s.addEventListener(`dragend`,F,{signal:L.disposalSignal}),s.addEventListener(`keydown`,I,{signal:L.disposalSignal}),C.disposables.add(L.dispose),{get disposalSignal(){return L.disposalSignal},dispose:L.dispose,get disposed(){return L.disposed},get isDragging(){return C.active?.source===j},revert:()=>{A?.(),A=null},[Symbol.dispose]:L[Symbol.dispose],sync:()=>{D()}}}function C(e,t,n){let r=new Map(e.map(e=>[n(e),e])),i=[];for(let e of t){if(!r.has(e))continue;let t=r.get(e);i.push(t),r.delete(e)}for(let e of r.values())i.push(e);return i}exports.applyReorder=C,exports.createSortable=S,exports.createSortableScope=x;
1
+ const e=require("./_shared.cjs"),t=require("./errors.cjs");require("./_dev.cjs");var n=Symbol(`SortableScope`),r=`data-dnd-handle`,i=`data-dnd-item`,a=new WeakMap,o={container:!0,edgeThreshold:32,speed:18,viewport:!1};function s(e){let n=a.get(e);if(!n)throw new t.DndScopeError;return n}function c(e){return e===!1?null:e===!0||e===void 0?o:{container:e.container??!0,edgeThreshold:e.edgeThreshold??32,speed:e.speed??18,viewport:e.viewport??!1}}function l(e,t){return t.length!==e.length||t.some((t,n)=>t!==e[n])}function u(e){e.querySelectorAll(`[${r}]`).forEach(e=>{e.removeAttribute(r),e.removeAttribute(`draggable`),e.style.touchAction=``})}function d(e){typeof requestAnimationFrame==`function`&&(e.hideFrame=requestAnimationFrame(()=>{e.hideFrame=null,e.draggedEl.style.display=`none`}))}function f(e){e.hideFrame!==null&&(cancelAnimationFrame(e.hideFrame),e.hideFrame=null)}function p(e){f(e),e.draggedEl.style.display=e.originalDisplay,e.draggedEl.removeAttribute(`data-dragging`)}function m(e,t){e.initialOrders.has(t)||e.initialOrders.set(t,t.getOrderedIds())}function h(e,t){let n=e.active;n&&(p(n),n.originalParent.insertBefore(n.draggedEl,n.originalNextSibling),n.placeholder.remove(),e.active=null,n.source.notifyDragEnd(n.draggedId,t))}function g(e,t){let n=e.active;if(!n)return;let r=n.target,i=n.placeholder.parentElement;p(n),r&&e.handles.has(r)&&i?i.insertBefore(n.draggedEl,n.placeholder):n.originalParent.insertBefore(n.draggedEl,n.originalNextSibling),n.placeholder.remove(),e.active=null,n.source.notifyDragEnd(n.draggedId,t);for(let[t,r]of n.initialOrders){if(!e.handles.has(t))continue;let n=t.getOrderedIds();l(r,n)&&(t.notifyBeforeReorder(r,n),t.commitReorder(n))}}function _(e,t,n){if(!e.active)return;let{active:r}=e;n||!t.dataTransfer||t.dataTransfer.dropEffect===`none`||!r.target||!e.handles.has(r.target)||r.source.isDisabled()||r.target.isDisabled()?h(e,t):g(e,t)}function v(e,t,n,r){if(!r)return;let{container:i,edgeThreshold:a,speed:o,viewport:s}=r,c=t.getBoundingClientRect();if(n===`vertical`){i&&e.clientY<c.top+a?t.scrollTop-=o:i&&e.clientY>c.bottom-a&&(t.scrollTop+=o),s&&e.clientY<a?window.scrollBy({left:0,top:-o}):s&&e.clientY>window.innerHeight-a&&window.scrollBy({left:0,top:o});return}i&&e.clientX<c.left+a?t.scrollLeft-=o:i&&e.clientX>c.right-a&&(t.scrollLeft+=o),s&&e.clientX<a?window.scrollBy({left:-o,top:0}):s&&e.clientX>window.innerWidth-a&&window.scrollBy({left:o,top:0})}function y(e,t,n,r,i,a){let o=n(),s=o.indexOf(e);if(s<0)return null;let c=a===`vertical`?i===`ArrowDown`:i===`ArrowRight`,l=a===`vertical`?i===`ArrowUp`:i===`ArrowLeft`,u;if(c)u=Math.min(o.length-1,s+1);else if(l)u=Math.max(0,s-1);else if(i===`Home`)u=0;else if(i===`End`)u=o.length-1;else return null;if(u===s)return null;let d=o[u];return d?(t.insertBefore(e,u>s?d.nextSibling:d),e.focus(),r()):null}function b(){let t={active:null,disposables:new Set,handles:new Set},r=e.createDisposable(()=>{for(let e of t.disposables)e()}),i={get disposalSignal(){return r.disposalSignal},dispose:r.dispose,get disposed(){return r.disposed},get isDragging(){return t.active!==null},[n]:!0,[Symbol.dispose]:r[Symbol.dispose]};return a.set(i,t),i}function x(t){let{autoScroll:n=!0,axis:a=`vertical`,element:o,getKey:l,handle:f,keyboard:p=!0,placeholderClass:h=`dnd-placeholder`,scope:g=b()}=t,x=c(n),S=s(g);f!==void 0&&f.trim();let C=()=>Array.from(o.children).filter(e=>e.hasAttribute(i)),w=()=>C().map(e=>l(e)),T=()=>{u(o),C().forEach(e=>{e.setAttribute(`role`,`listitem`),e.tabIndex=0,f?(e.removeAttribute(`draggable`),e.style.touchAction=``,e.querySelectorAll(f).forEach(e=>{e.setAttribute(r,``),e.setAttribute(`draggable`,`true`),e.style.touchAction=`none`})):(e.setAttribute(`draggable`,`true`),e.style.touchAction=`none`)})},E=()=>{let e=new Set;Array.from(o.children).forEach(t=>{let n=t;try{let t=l(n);t&&(e.has(t)?`${t}`:e.add(t),n.setAttribute(i,``))}catch(e){`${String(e)}`}}),T()},D=()=>{u(o),o.querySelectorAll(`[${i}]`).forEach(e=>{e.removeAttribute(i),e.removeAttribute(`draggable`),e.removeAttribute(`role`),e.removeAttribute(`tabindex`),e.style.touchAction=``})},O=e=>{let t=document.createElement(`div`);return t.className=h,t.setAttribute(`aria-hidden`,`true`),a===`horizontal`?t.style.width=`${e.offsetWidth}px`:t.style.height=`${e.offsetHeight}px`,t},k=null,A={commitReorder:e=>{if(!t.onReorder)return;let n={ids:e,setRevert(e){k=e}};t.onReorder(n)},getOrderedIds:w,isDisabled:()=>e.resolveDisabled(t.disabled),notifyBeforeReorder:(e,n)=>t.onBeforeReorder?.(e,n),notifyDragEnd:(e,n)=>t.onDragEnd?.(e,n),notifyDragStart:(e,n)=>t.onDragStart?.(e,n)};S.handles.add(A);let j=e=>{if(S.active||A.isDisabled())return;let n=e.target,r=n.closest(`[${i}]`);if(!r||f&&!n.closest(f))return;let a=r.parentElement;if(!a)return;let o=O(r),s=r.nextSibling,c=l(r),u=new Map;u.set(A,A.getOrderedIds()),r.setAttribute(`data-dragging`,``),a.insertBefore(o,s);let p={draggedEl:r,draggedId:c,hideFrame:null,initialOrders:u,originalDisplay:r.style.display,originalNextSibling:s,originalParent:a,placeholder:o,source:A,target:A};if(d(p),S.active=p,e.dataTransfer&&(e.dataTransfer.effectAllowed=`move`,e.dataTransfer.setData(`text/plain`,c),t.dragImage)){let n=typeof t.dragImage==`function`?t.dragImage(c,r,e):t.dragImage,[i,a]=t.dragImageOffset??[0,0];n&&e.dataTransfer.setDragImage(n,i,a)}A.notifyDragStart(p.draggedId,e)},M=e=>{let t=S.active;if(!t||t.source.isDisabled()||A.isDisabled())return;e.preventDefault(),v(e,o,a,x),m(t,A);let{draggedEl:n,placeholder:r}=t,s=e.target.closest(`[${i}]`);if(!s){r.parentElement!==o&&o.appendChild(r),t.target=A;return}if(s===n||s===r)return;let c=s.getBoundingClientRect(),l=a===`vertical`?e.clientY>=c.top+c.height/2:e.clientX>=c.left+c.width/2;o.insertBefore(r,l?s.nextSibling:s),t.target=A},N=e=>{let t=S.active;t&&(t.source.isDisabled()||A.isDisabled()||(e.preventDefault(),t.target=A))},P=e=>{S.active?.source===A&&_(S,e,!1)},F=e=>{if(!p||A.isDisabled())return;let t=e.target?.tagName;if(t===`INPUT`||t===`TEXTAREA`||t===`SELECT`)return;let n=e.target.closest(`[${i}]`);if(!n||!o.contains(n))return;let r=w(),s=y(n,o,C,w,e.key,a);s!==null&&(e.preventDefault(),A.notifyBeforeReorder(r,s),A.commitReorder(s))};E();let I=e.createDisposable(()=>{S.disposables.delete(I.dispose),S.active&&(S.active.source===A||S.active.target===A)&&_(S,new Event(`dragend`),!0),S.handles.delete(A),o.removeAttribute(`role`),D()});return o.setAttribute(`role`,`list`),o.addEventListener(`dragstart`,j,{signal:I.disposalSignal}),o.addEventListener(`dragover`,M,{signal:I.disposalSignal}),o.addEventListener(`drop`,N,{signal:I.disposalSignal}),o.addEventListener(`dragend`,P,{signal:I.disposalSignal}),o.addEventListener(`keydown`,F,{signal:I.disposalSignal}),S.disposables.add(I.dispose),{get disposalSignal(){return I.disposalSignal},dispose:I.dispose,get disposed(){return I.disposed},get isDragging(){return S.active?.source===A},revert:()=>{k?.(),k=null},[Symbol.dispose]:I[Symbol.dispose],sync:()=>{E()}}}function S(e,t,n){let r=new Map(e.map(e=>[n(e),e])),i=[];for(let e of t){if(!r.has(e))continue;let t=r.get(e);i.push(t),r.delete(e)}for(let e of r.values())i.push(e);return i}exports.applyReorder=S,exports.createSortable=x,exports.createSortableScope=b;
2
2
  //# sourceMappingURL=sortable.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sortable.cjs","names":[],"sources":["../src/sortable.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { createDisposable, resolveDisabled } from './_shared';\nimport { DndScopeError } from './errors';\nimport { type Disposable } from './types';\n\n// ─── Branded scope ────────────────────────────────────────────────────────────\n\nconst SCOPE_BRAND = Symbol('SortableScope');\n\nexport interface SortableScope extends Disposable {\n /** `true` while any sortable in this scope is actively dragging. */\n readonly isDragging: boolean;\n readonly [SCOPE_BRAND]: true;\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface AutoScrollOptions {\n /** Distance in pixels from an edge that triggers auto-scroll. @default 32 */\n edgeThreshold?: number;\n /** Pixels scrolled per dragover frame while near an edge. @default 18 */\n speed?: number;\n /** Scroll the sortable container while dragging near its edges. @default true */\n container?: boolean;\n /** Scroll the viewport while dragging near the window edges. @default false */\n viewport?: boolean;\n}\n\n/**\n * Passed to `onReorder` after every successful reorder (drag or keyboard).\n */\nexport interface ReorderEvent {\n /** The new ordered list of item keys after the reorder. */\n ids: string[];\n /**\n * Register a revert function that will be called when `sortable.revert()` is invoked.\n * Useful for rolling back optimistic UI updates on server error.\n * Only the most recent `setRevert` registration is retained — a new reorder overwrites it.\n *\n * @example\n * ```ts\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * ```\n */\n setRevert(fn: () => void): void;\n}\n\nexport interface SortableOptions {\n /** Container element whose direct-child items are sortable. */\n element: HTMLElement;\n /** Shared scope for connected sortable containers. Containers only exchange items within the same scope. */\n scope?: SortableScope;\n /**\n * Selector for the drag handle inside each item.\n * When omitted the whole item is the handle.\n */\n handle?: string;\n /**\n * Enables keyboard-based reordering using arrow keys plus Home/End.\n * @default true\n */\n keyboard?: boolean;\n /**\n * Returns the identity key for a given item element.\n * This separates the \"what is this item?\" concern (yours) from the \"which children\n * are sortable?\" concern (ours — marked with `data-dnd-item`).\n *\n * @example\n * ```ts\n * getKey: (el) => el.dataset.taskId!\n * ```\n */\n getKey: (element: HTMLElement) => string;\n /** Sorting axis used to compute insertion position. @default 'vertical' */\n axis?: 'vertical' | 'horizontal';\n /** Auto-scrolls the container (and viewport) near edges while dragging. @default true */\n autoScroll?: boolean | AutoScrollOptions;\n /** Optional custom drag preview element. */\n dragImage?: HTMLElement | ((id: string, item: HTMLElement, event: DragEvent) => HTMLElement | null | undefined);\n /** CSS class applied to the placeholder element. @default 'dnd-placeholder' */\n placeholderClass?: string;\n /**\n * Called with a {@link ReorderEvent} after a successful reorder, only when the order changed.\n *\n * @example\n * ```ts\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * ```\n */\n onReorder?: (event: ReorderEvent) => void;\n /**\n * Called just before a successful drag commit with the before and after order snapshots.\n * Use this hook to set up FLIP animations — the source items are still in their\n * pre-commit positions at the time of the call.\n *\n * @example\n * ```ts\n * onBeforeReorder: (from, to) => {\n * // record element positions here, then animate after the next microtask\n * }\n * ```\n */\n onBeforeReorder?: (from: string[], to: string[]) => void;\n /**\n * When `true`, drag interactions are ignored.\n *\n * Note: if `disabled` transitions to `true` while a drag is in progress the\n * drag is treated as a cancellation — the item snaps back to its original\n * position rather than committing the last placeholder location.\n */\n disabled?: boolean;\n /** Called when the user starts dragging an item. */\n onDragStart?: (id: string, event: DragEvent) => void;\n /** Called when a drag ends (whether dropped or cancelled). */\n onDragEnd?: (id: string, event: DragEvent) => void;\n /**\n * Hotspot offset `[x, y]` passed to `setDragImage`.\n * Controls which point of the preview image follows the cursor.\n * @default [0, 0]\n */\n dragImageOffset?: [number, number];\n}\n\nexport interface Sortable extends Disposable {\n readonly isDragging: boolean;\n /**\n * Calls the revert function registered via `setRevert` in the last `onReorder` invocation (if any) and clears it.\n * A no-op when no revert function was registered or has already been consumed.\n *\n * Works for both drag-based and keyboard-based reorders.\n * Note: only the most recent reorder can be reverted; a new reorder overwrites the stored function.\n *\n * @example\n * ```ts\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * // later, on server error:\n * sortable.revert();\n * ```\n */\n revert(): void;\n /**\n * Re-reads the container's children and reapplies `draggable`, ARIA roles,\n * and handle attributes. Call this after programmatically adding, removing,\n * or replacing items — e.g. after a framework render that replaces DOM nodes.\n *\n * Not needed when items are only reordered via drag or keyboard.\n */\n sync(): void;\n}\n\n// ─── Internal types ───────────────────────────────────────────────────────────\n\ninterface ResolvedAutoScrollOptions {\n container: boolean;\n edgeThreshold: number;\n speed: number;\n viewport: boolean;\n}\n\n/** Per-container closure passed into shared session functions. */\ninterface ContainerHandle {\n getOrderedIds: () => string[];\n isDisabled: () => boolean;\n commitReorder: (orderedIds: string[]) => void;\n notifyBeforeReorder: (from: string[], to: string[]) => void;\n notifyDragEnd: (id: string, event: DragEvent) => void;\n notifyDragStart: (id: string, event: DragEvent) => void;\n}\n\n/**\n * Encapsulates all mutable state for a single in-progress drag operation.\n * Created at dragstart, destroyed on dragend/cancel.\n */\ninterface DragSession {\n draggedEl: HTMLElement;\n draggedId: string;\n /**\n * Order snapshots captured lazily: snapshot is taken the first time a handle\n * becomes the active target (and always for the source at drag start).\n */\n initialOrders: Map<ContainerHandle, string[]>;\n originalDisplay: string;\n originalNextSibling: ChildNode | null;\n originalParent: HTMLElement;\n placeholder: HTMLElement;\n source: ContainerHandle;\n target: ContainerHandle | null;\n /** rAF handle for the deferred element-hide; null once fired or cancelled. */\n hideFrame: number | null;\n}\n\ninterface SortableScopeState {\n active: DragSession | null;\n handles: Set<ContainerHandle>;\n /** All sortables registered in this scope, kept for scope.dispose(). */\n disposables: Set<() => void>;\n}\n\n// ─── Internal constants ───────────────────────────────────────────────────────\n\nconst HANDLE_ATTR = 'data-dnd-handle';\nconst ITEM_ATTR = 'data-dnd-item';\nconst sortableScopeStates = new WeakMap<SortableScope, SortableScopeState>();\nconst DEFAULT_AUTO_SCROLL: ResolvedAutoScrollOptions = {\n container: true,\n edgeThreshold: 32,\n speed: 18,\n viewport: false,\n};\n\n// ─── Scope helpers ────────────────────────────────────────────────────────────\n\nfunction getSortableScopeState(scope: SortableScope): SortableScopeState {\n const state = sortableScopeStates.get(scope);\n\n if (!state) throw new DndScopeError();\n\n return state;\n}\n\n// ─── Option resolution ────────────────────────────────────────────────────────\n\nfunction resolveAutoScrollOptions(\n autoScroll: boolean | AutoScrollOptions | undefined,\n): ResolvedAutoScrollOptions | null {\n if (autoScroll === false) return null;\n\n if (autoScroll === true || autoScroll === undefined) return DEFAULT_AUTO_SCROLL;\n\n return {\n container: autoScroll.container ?? true,\n edgeThreshold: autoScroll.edgeThreshold ?? 32,\n speed: autoScroll.speed ?? 18,\n viewport: autoScroll.viewport ?? false,\n };\n}\n\n// ─── DOM helpers ──────────────────────────────────────────────────────────────\n\nfunction hasOrderChanged(before: string[], after: string[]): boolean {\n return after.length !== before.length || after.some((id, index) => id !== before[index]);\n}\n\nfunction clearHandleAttributes(element: HTMLElement): void {\n element.querySelectorAll<HTMLElement>(`[${HANDLE_ATTR}]`).forEach((handleEl) => {\n handleEl.removeAttribute(HANDLE_ATTR);\n handleEl.removeAttribute('draggable');\n handleEl.style.touchAction = '';\n });\n}\n\n// ─── Drag session helpers ─────────────────────────────────────────────────────\n\nfunction scheduleHide(session: DragSession): void {\n if (typeof requestAnimationFrame !== 'function') return;\n\n session.hideFrame = requestAnimationFrame(() => {\n session.hideFrame = null;\n session.draggedEl.style.display = 'none';\n });\n}\n\nfunction cancelHide(session: DragSession): void {\n if (session.hideFrame !== null) {\n cancelAnimationFrame(session.hideFrame);\n session.hideFrame = null;\n }\n}\n\nfunction restoreSessionElement(session: DragSession): void {\n cancelHide(session);\n session.draggedEl.style.display = session.originalDisplay;\n session.draggedEl.removeAttribute('data-dragging');\n}\n\n/**\n * Snapshot a handle's current order if not already recorded.\n * Called the first time a handle becomes an active target so we only capture\n * lists that actually participate in the drag.\n */\nfunction snapshotOrder(session: DragSession, handle: ContainerHandle): void {\n if (!session.initialOrders.has(handle)) {\n session.initialOrders.set(handle, handle.getOrderedIds());\n }\n}\n\n// ─── Session commit / cancel ──────────────────────────────────────────────────\n\nfunction cancelSession(scopeState: SortableScopeState, event: DragEvent): void {\n const session = scopeState.active;\n\n if (!session) return;\n\n restoreSessionElement(session);\n session.originalParent.insertBefore(session.draggedEl, session.originalNextSibling);\n session.placeholder.remove();\n scopeState.active = null;\n\n session.source.notifyDragEnd(session.draggedId, event);\n}\n\nfunction commitSession(scopeState: SortableScopeState, event: DragEvent): void {\n const session = scopeState.active;\n\n if (!session) return;\n\n const targetHandle = session.target;\n const targetElement = session.placeholder.parentElement;\n\n restoreSessionElement(session);\n\n if (targetHandle && scopeState.handles.has(targetHandle) && targetElement) {\n targetElement.insertBefore(session.draggedEl, session.placeholder);\n } else {\n session.originalParent.insertBefore(session.draggedEl, session.originalNextSibling);\n }\n\n session.placeholder.remove();\n scopeState.active = null;\n\n session.source.notifyDragEnd(session.draggedId, event);\n\n for (const [handle, beforeOrder] of session.initialOrders) {\n if (!scopeState.handles.has(handle)) continue;\n\n const afterOrder = handle.getOrderedIds();\n\n if (!hasOrderChanged(beforeOrder, afterOrder)) continue;\n\n handle.notifyBeforeReorder(beforeOrder, afterOrder);\n handle.commitReorder(afterOrder);\n }\n}\n\nfunction finishSession(scopeState: SortableScopeState, event: DragEvent, forceCancel: boolean): void {\n if (!scopeState.active) return;\n\n const { active } = scopeState;\n\n // If source or target became disabled during the drag, treat as cancellation.\n if (\n forceCancel ||\n !event.dataTransfer ||\n event.dataTransfer.dropEffect === 'none' ||\n !active.target ||\n !scopeState.handles.has(active.target) ||\n active.source.isDisabled() ||\n active.target.isDisabled()\n ) {\n cancelSession(scopeState, event);\n } else {\n commitSession(scopeState, event);\n }\n}\n\nfunction maybeAutoScroll(\n event: DragEvent,\n container: HTMLElement,\n axis: 'vertical' | 'horizontal',\n options: ResolvedAutoScrollOptions | null,\n): void {\n if (!options) return;\n\n const { container: scrollContainer, edgeThreshold: threshold, speed, viewport } = options;\n const rect = container.getBoundingClientRect();\n\n if (axis === 'vertical') {\n if (scrollContainer && event.clientY < rect.top + threshold) {\n container.scrollTop -= speed;\n } else if (scrollContainer && event.clientY > rect.bottom - threshold) {\n container.scrollTop += speed;\n }\n\n if (viewport && event.clientY < threshold) {\n window.scrollBy({ left: 0, top: -speed });\n } else if (viewport && event.clientY > window.innerHeight - threshold) {\n window.scrollBy({ left: 0, top: speed });\n }\n\n return;\n }\n\n if (scrollContainer && event.clientX < rect.left + threshold) {\n container.scrollLeft -= speed;\n } else if (scrollContainer && event.clientX > rect.right - threshold) {\n container.scrollLeft += speed;\n }\n\n if (viewport && event.clientX < threshold) {\n window.scrollBy({ left: -speed, top: 0 });\n } else if (viewport && event.clientX > window.innerWidth - threshold) {\n window.scrollBy({ left: speed, top: 0 });\n }\n}\n\n// ─── Keyboard reorder ─────────────────────────────────────────────────────────\n\nfunction applyKeyboardReorder(\n item: HTMLElement,\n element: HTMLElement,\n getItems: () => HTMLElement[],\n getOrderedIds: () => string[],\n key: string,\n axis: 'vertical' | 'horizontal',\n): string[] | null {\n const items = getItems();\n const currentIndex = items.indexOf(item);\n\n if (currentIndex < 0) return null;\n\n const isForward = axis === 'vertical' ? key === 'ArrowDown' : key === 'ArrowRight';\n const isBackward = axis === 'vertical' ? key === 'ArrowUp' : key === 'ArrowLeft';\n let targetIndex: number;\n\n if (isForward) {\n targetIndex = Math.min(items.length - 1, currentIndex + 1);\n } else if (isBackward) {\n targetIndex = Math.max(0, currentIndex - 1);\n } else if (key === 'Home') {\n targetIndex = 0;\n } else if (key === 'End') {\n targetIndex = items.length - 1;\n } else {\n return null;\n }\n\n // Already at the boundary — return null so the caller does not call preventDefault\n // and the browser can handle the key (e.g. scrolling the page).\n if (targetIndex === currentIndex) return null;\n\n const targetItem = items[targetIndex];\n\n if (!targetItem) return null;\n\n element.insertBefore(item, targetIndex > currentIndex ? targetItem.nextSibling : targetItem);\n item.focus();\n\n return getOrderedIds();\n}\n\n// ─── createSortableScope ──────────────────────────────────────────────────────\n\n/**\n * Create a shared scope for connected sortable containers.\n *\n * Items can be dragged between all sortables that share the same scope.\n * The scope exposes `isDragging` and `dispose()` — calling `dispose()` tears down\n * all member sortables at once.\n *\n * @example\n * ```ts\n * const scope = createSortableScope();\n * const left = createSortable({ element: leftEl, scope, getKey, onReorder });\n * const right = createSortable({ element: rightEl, scope, getKey, onReorder });\n *\n * // Tear down everything at once:\n * scope.dispose();\n * ```\n */\nexport function createSortableScope(): SortableScope {\n const state: SortableScopeState = { active: null, disposables: new Set(), handles: new Set() };\n const disposable = createDisposable(() => {\n // Dispose all registered sortables (each dispose() call is idempotent)\n for (const disposeFn of state.disposables) {\n disposeFn();\n }\n });\n\n const scope = {\n get disposalSignal() {\n return disposable.disposalSignal;\n },\n dispose: disposable.dispose,\n get disposed() {\n return disposable.disposed;\n },\n get isDragging() {\n return state.active !== null;\n },\n [SCOPE_BRAND]: true as const,\n [Symbol.dispose]: disposable[Symbol.dispose],\n } as SortableScope;\n\n sortableScopeStates.set(scope, state);\n\n return scope;\n}\n\n// ─── createSortable ───────────────────────────────────────────────────────────\n\n/**\n * Makes a list of items sortable via native HTML drag interactions.\n *\n * Provide `getKey` to map each item element to a stable string identity.\n * `createSortable` marks qualifying children with `data-dnd-item` and sets\n * `draggable=\"true\"` automatically.\n *\n * Style the drop indicator by targeting `.dnd-placeholder` in your CSS.\n * Supports keyboard reordering (arrow keys, Home/End) and auto-scrolling near edges.\n *\n * @example\n * ```ts\n * import { createSortable } from '@vielzeug/dnd';\n *\n * using sortable = createSortable({\n * element: listEl,\n * getKey: (el) => el.dataset.id!,\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * });\n * ```\n */\nexport function createSortable(options: SortableOptions): Sortable {\n const {\n autoScroll = true,\n axis = 'vertical',\n element,\n getKey,\n handle,\n keyboard = true,\n placeholderClass = 'dnd-placeholder',\n scope = createSortableScope(),\n } = options;\n const autoScrollOptions = resolveAutoScrollOptions(autoScroll);\n const scopeState = getSortableScopeState(scope);\n\n if (handle !== undefined && handle.trim() === '') {\n warn(\n 'handle option is an empty string — no handle elements will be found. Provide a valid CSS selector or omit the option.',\n );\n }\n\n const getItems = (): HTMLElement[] =>\n Array.from(element.children).filter((c) => (c as HTMLElement).hasAttribute(ITEM_ATTR)) as HTMLElement[];\n\n const getOrderedIds = (): string[] => getItems().map((el) => getKey(el));\n\n const syncItems = (): void => {\n clearHandleAttributes(element);\n\n getItems().forEach((el) => {\n el.setAttribute('role', 'listitem');\n el.tabIndex = 0;\n\n if (handle) {\n el.removeAttribute('draggable');\n el.style.touchAction = '';\n el.querySelectorAll<HTMLElement>(handle).forEach((handleEl) => {\n handleEl.setAttribute(HANDLE_ATTR, '');\n handleEl.setAttribute('draggable', 'true');\n // See the matching comment above `cleanupItems()` for why this matters at all.\n handleEl.style.touchAction = 'none';\n });\n } else {\n el.setAttribute('draggable', 'true');\n // A native mouse drag has no competing gesture to arbitrate; touch does. Without this,\n // a mobile browser can decide the very first bit of finger movement is a page\n // scroll/pan — a decision it makes independently of, and before, this library's own\n // touch-shim threshold/`preventDefault()` logic ever runs — and hand the rest of the\n // gesture to native scrolling. Once that happens the item never receives the\n // `dragover` sequence needed to update the drop target, so the session ends up\n // committing back to wherever it started: indistinguishable from the drop \"reverting\".\n // `touch-action: none` opts the element out of every default touch gesture from\n // `touchstart` onward, leaving the whole interaction to this library's own JS.\n el.style.touchAction = 'none';\n }\n });\n };\n\n const markItems = (): void => {\n const seenKeys = new Set<string>();\n\n // Mark all children that have a key as sortable items\n Array.from(element.children).forEach((child) => {\n const el = child as HTMLElement;\n\n try {\n const key = getKey(el);\n\n if (key) {\n if (seenKeys.has(key)) {\n warn(\n `getKey returned the duplicate key \"${key}\" for two sibling items — onReorder's ids and applyReorder may become inconsistent. Ensure getKey returns a unique value per item.`,\n );\n } else {\n seenKeys.add(key);\n }\n\n el.setAttribute(ITEM_ATTR, '');\n }\n } catch (err) {\n warn(\n `getKey threw for a child element — the item will not be sortable. Check your getKey implementation. ${String(err)}`,\n );\n }\n });\n\n syncItems();\n };\n\n const cleanupItems = (): void => {\n clearHandleAttributes(element);\n\n element.querySelectorAll<HTMLElement>(`[${ITEM_ATTR}]`).forEach((item) => {\n item.removeAttribute(ITEM_ATTR);\n item.removeAttribute('draggable');\n item.removeAttribute('role');\n item.removeAttribute('tabindex');\n item.style.touchAction = '';\n });\n };\n\n const createPlaceholder = (source: HTMLElement): HTMLElement => {\n const p = document.createElement('div');\n\n p.className = placeholderClass;\n p.setAttribute('aria-hidden', 'true');\n\n if (axis === 'horizontal') {\n p.style.width = `${source.offsetWidth}px`;\n } else {\n p.style.height = `${source.offsetHeight}px`;\n }\n\n return p;\n };\n\n let lastRevert: (() => void) | null = null;\n\n const handle_: ContainerHandle = {\n commitReorder: (orderedIds) => {\n if (!options.onReorder) return;\n\n const event: ReorderEvent = {\n ids: orderedIds,\n setRevert(fn) {\n lastRevert = fn;\n },\n };\n\n options.onReorder(event);\n },\n getOrderedIds,\n isDisabled: () => resolveDisabled(options.disabled),\n notifyBeforeReorder: (from, to) => options.onBeforeReorder?.(from, to),\n notifyDragEnd: (id, event) => options.onDragEnd?.(id, event),\n notifyDragStart: (id, event) => options.onDragStart?.(id, event),\n };\n\n scopeState.handles.add(handle_);\n\n const handleDragStart = (e: DragEvent): void => {\n if (scopeState.active) return;\n\n if (handle_.isDisabled()) return;\n\n const target = e.target as HTMLElement;\n const item = target.closest<HTMLElement>(`[${ITEM_ATTR}]`);\n\n if (!item) return;\n\n if (handle && !target.closest(handle)) return;\n\n const originalParent = item.parentElement;\n\n if (!originalParent) return;\n\n const placeholder = createPlaceholder(item);\n const originalNextSibling = item.nextSibling;\n const activeId = getKey(item);\n\n // Snapshot only the source handle at drag start; targets are snapshotted lazily.\n const initialOrders = new Map<ContainerHandle, string[]>();\n\n initialOrders.set(handle_, handle_.getOrderedIds());\n item.setAttribute('data-dragging', '');\n originalParent.insertBefore(placeholder, originalNextSibling);\n\n const session: DragSession = {\n draggedEl: item,\n draggedId: activeId,\n hideFrame: null,\n initialOrders,\n originalDisplay: item.style.display,\n originalNextSibling,\n originalParent,\n placeholder,\n source: handle_,\n target: handle_,\n };\n\n scheduleHide(session);\n scopeState.active = session;\n\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', activeId);\n\n if (options.dragImage) {\n const preview =\n typeof options.dragImage === 'function' ? options.dragImage(activeId, item, e) : options.dragImage;\n const [offsetX, offsetY] = options.dragImageOffset ?? [0, 0];\n\n if (preview) e.dataTransfer.setDragImage(preview, offsetX, offsetY);\n }\n }\n\n handle_.notifyDragStart(session.draggedId, e);\n };\n\n const handleDragOver = (e: DragEvent): void => {\n const session = scopeState.active;\n\n if (!session) return;\n\n if (session.source.isDisabled() || handle_.isDisabled()) return;\n\n e.preventDefault();\n maybeAutoScroll(e, element, axis, autoScrollOptions);\n\n // Lazily snapshot this handle's order the first time it becomes a target.\n snapshotOrder(session, handle_);\n\n const { draggedEl, placeholder } = session;\n const target = (e.target as HTMLElement).closest<HTMLElement>(`[${ITEM_ATTR}]`);\n\n if (!target) {\n // Only append placeholder when it isn't already inside this container.\n // Moving it to the end on every over-empty-space event causes the\n // placeholder to oscillate between positions as the cursor moves.\n if (placeholder.parentElement !== element) {\n element.appendChild(placeholder);\n }\n\n session.target = handle_;\n\n return;\n }\n\n if (target === draggedEl || target === placeholder) return;\n\n const rect = target.getBoundingClientRect();\n const insertAfter =\n axis === 'vertical' ? e.clientY >= rect.top + rect.height / 2 : e.clientX >= rect.left + rect.width / 2;\n\n element.insertBefore(placeholder, insertAfter ? target.nextSibling : target);\n session.target = handle_;\n };\n\n const handleDrop = (e: DragEvent): void => {\n const session = scopeState.active;\n\n if (!session) return;\n\n if (session.source.isDisabled() || handle_.isDisabled()) return;\n\n e.preventDefault();\n // Record the drop target; the actual commit happens in handleDragEnd where\n // dataTransfer.dropEffect tells us whether the browser accepted the operation.\n session.target = handle_;\n };\n\n const handleDragEnd = (e: DragEvent): void => {\n if (scopeState.active?.source !== handle_) return;\n\n finishSession(scopeState, e, false);\n };\n\n const handleKeydown = (e: KeyboardEvent): void => {\n if (!keyboard || handle_.isDisabled()) return;\n\n const tagName = (e.target as HTMLElement | null)?.tagName;\n\n if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') return;\n\n const item = (e.target as HTMLElement).closest<HTMLElement>(`[${ITEM_ATTR}]`);\n\n if (!item || !element.contains(item)) return;\n\n const prevOrder = getOrderedIds();\n const newOrder = applyKeyboardReorder(item, element, getItems, getOrderedIds, e.key, axis);\n\n // null means unrecognized key or boundary — let the browser handle it (e.g. page scroll)\n if (newOrder === null) return;\n\n e.preventDefault();\n handle_.notifyBeforeReorder(prevOrder, newOrder);\n handle_.commitReorder(newOrder);\n };\n\n markItems();\n\n const disposable = createDisposable(() => {\n scopeState.disposables.delete(disposable.dispose);\n\n if (scopeState.active && (scopeState.active.source === handle_ || scopeState.active.target === handle_)) {\n finishSession(scopeState, new Event('dragend') as DragEvent, true);\n }\n\n scopeState.handles.delete(handle_);\n element.removeAttribute('role');\n cleanupItems();\n });\n\n element.setAttribute('role', 'list');\n element.addEventListener('dragstart', handleDragStart, { signal: disposable.disposalSignal });\n element.addEventListener('dragover', handleDragOver, { signal: disposable.disposalSignal });\n element.addEventListener('drop', handleDrop, { signal: disposable.disposalSignal });\n element.addEventListener('dragend', handleDragEnd, { signal: disposable.disposalSignal });\n element.addEventListener('keydown', handleKeydown, { signal: disposable.disposalSignal });\n\n // Register with scope so scope.dispose() can tear this down\n scopeState.disposables.add(disposable.dispose);\n\n return {\n get disposalSignal() {\n return disposable.disposalSignal;\n },\n dispose: disposable.dispose,\n get disposed() {\n return disposable.disposed;\n },\n get isDragging() {\n return scopeState.active?.source === handle_;\n },\n revert: () => {\n lastRevert?.();\n lastRevert = null;\n },\n [Symbol.dispose]: disposable[Symbol.dispose],\n sync: () => {\n markItems();\n },\n };\n}\n\n// ─── applyReorder ─────────────────────────────────────────────────────────────\n\n/**\n * Applies a sorted key array to a backing data array.\n * Unknown keys are ignored; items not present in `ids` are appended in original order.\n */\nexport function applyReorder<T>(items: T[], ids: string[], getKey: (item: T) => string): T[] {\n const byId = new Map(items.map((item) => [getKey(item), item] as const));\n const ordered: T[] = [];\n\n for (const id of ids) {\n if (!byId.has(id)) continue;\n\n const item = byId.get(id) as T;\n\n ordered.push(item);\n byId.delete(id);\n }\n\n for (const item of byId.values()) ordered.push(item);\n\n return ordered;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sortable.cjs","names":[],"sources":["../src/sortable.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { createDisposable, resolveDisabled } from './_shared';\nimport { DndScopeError } from './errors';\nimport { type Disposable } from './types';\n\n// ─── Branded scope ────────────────────────────────────────────────────────────\n\nconst SCOPE_BRAND = Symbol('SortableScope');\n\nexport interface SortableScope extends Disposable {\n /** `true` while any sortable in this scope is actively dragging. */\n readonly isDragging: boolean;\n readonly [SCOPE_BRAND]: true;\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface AutoScrollOptions {\n /** Distance in pixels from an edge that triggers auto-scroll. @default 32 */\n edgeThreshold?: number;\n /** Pixels scrolled per dragover frame while near an edge. @default 18 */\n speed?: number;\n /** Scroll the sortable container while dragging near its edges. @default true */\n container?: boolean;\n /** Scroll the viewport while dragging near the window edges. @default false */\n viewport?: boolean;\n}\n\n/**\n * Passed to `onReorder` after every successful reorder (drag or keyboard).\n */\nexport interface ReorderEvent {\n /** The new ordered list of item keys after the reorder. */\n ids: string[];\n /**\n * Register a revert function that will be called when `sortable.revert()` is invoked.\n * Useful for rolling back optimistic UI updates on server error.\n * Only the most recent `setRevert` registration is retained — a new reorder overwrites it.\n *\n * @example\n * ```ts\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * ```\n */\n setRevert(fn: () => void): void;\n}\n\nexport interface SortableOptions {\n /** Container element whose direct-child items are sortable. */\n element: HTMLElement;\n /** Shared scope for connected sortable containers. Containers only exchange items within the same scope. */\n scope?: SortableScope;\n /**\n * Selector for the drag handle inside each item.\n * When omitted the whole item is the handle.\n */\n handle?: string;\n /**\n * Enables keyboard-based reordering using arrow keys plus Home/End.\n * @default true\n */\n keyboard?: boolean;\n /**\n * Returns the identity key for a given item element.\n * This separates the \"what is this item?\" concern (yours) from the \"which children\n * are sortable?\" concern (ours — marked with `data-dnd-item`).\n *\n * @example\n * ```ts\n * getKey: (el) => el.dataset.taskId!\n * ```\n */\n getKey: (element: HTMLElement) => string;\n /** Sorting axis used to compute insertion position. @default 'vertical' */\n axis?: 'vertical' | 'horizontal';\n /** Auto-scrolls the container (and viewport) near edges while dragging. @default true */\n autoScroll?: boolean | AutoScrollOptions;\n /** Optional custom drag preview element. */\n dragImage?: HTMLElement | ((id: string, item: HTMLElement, event: DragEvent) => HTMLElement | null | undefined);\n /** CSS class applied to the placeholder element. @default 'dnd-placeholder' */\n placeholderClass?: string;\n /**\n * Called with a {@link ReorderEvent} after a successful reorder, only when the order changed.\n *\n * @example\n * ```ts\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * ```\n */\n onReorder?: (event: ReorderEvent) => void;\n /**\n * Called just before a successful drag commit with the before and after order snapshots.\n * Use this hook to set up FLIP animations — the source items are still in their\n * pre-commit positions at the time of the call.\n *\n * @example\n * ```ts\n * onBeforeReorder: (from, to) => {\n * // record element positions here, then animate after the next microtask\n * }\n * ```\n */\n onBeforeReorder?: (from: string[], to: string[]) => void;\n /**\n * When `true`, drag interactions are ignored.\n *\n * Note: if `disabled` transitions to `true` while a drag is in progress the\n * drag is treated as a cancellation — the item snaps back to its original\n * position rather than committing the last placeholder location.\n */\n disabled?: boolean;\n /** Called when the user starts dragging an item. */\n onDragStart?: (id: string, event: DragEvent) => void;\n /** Called when a drag ends (whether dropped or cancelled). */\n onDragEnd?: (id: string, event: DragEvent) => void;\n /**\n * Hotspot offset `[x, y]` passed to `setDragImage`.\n * Controls which point of the preview image follows the cursor.\n * @default [0, 0]\n */\n dragImageOffset?: [number, number];\n}\n\nexport interface Sortable extends Disposable {\n readonly isDragging: boolean;\n /**\n * Calls the revert function registered via `setRevert` in the last `onReorder` invocation (if any) and clears it.\n * A no-op when no revert function was registered or has already been consumed.\n *\n * Works for both drag-based and keyboard-based reorders.\n * Note: only the most recent reorder can be reverted; a new reorder overwrites the stored function.\n *\n * @example\n * ```ts\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * // later, on server error:\n * sortable.revert();\n * ```\n */\n revert(): void;\n /**\n * Re-reads the container's children and reapplies `draggable`, ARIA roles,\n * and handle attributes. Call this after programmatically adding, removing,\n * or replacing items — e.g. after a framework render that replaces DOM nodes.\n *\n * Not needed when items are only reordered via drag or keyboard.\n */\n sync(): void;\n}\n\n// ─── Internal types ───────────────────────────────────────────────────────────\n\ninterface ResolvedAutoScrollOptions {\n container: boolean;\n edgeThreshold: number;\n speed: number;\n viewport: boolean;\n}\n\n/** Per-container closure passed into shared session functions. */\ninterface ContainerHandle {\n getOrderedIds: () => string[];\n isDisabled: () => boolean;\n commitReorder: (orderedIds: string[]) => void;\n notifyBeforeReorder: (from: string[], to: string[]) => void;\n notifyDragEnd: (id: string, event: DragEvent) => void;\n notifyDragStart: (id: string, event: DragEvent) => void;\n}\n\n/**\n * Encapsulates all mutable state for a single in-progress drag operation.\n * Created at dragstart, destroyed on dragend/cancel.\n */\ninterface DragSession {\n draggedEl: HTMLElement;\n draggedId: string;\n /**\n * Order snapshots captured lazily: snapshot is taken the first time a handle\n * becomes the active target (and always for the source at drag start).\n */\n initialOrders: Map<ContainerHandle, string[]>;\n originalDisplay: string;\n originalNextSibling: ChildNode | null;\n originalParent: HTMLElement;\n placeholder: HTMLElement;\n source: ContainerHandle;\n target: ContainerHandle | null;\n /** rAF handle for the deferred element-hide; null once fired or cancelled. */\n hideFrame: number | null;\n}\n\ninterface SortableScopeState {\n active: DragSession | null;\n handles: Set<ContainerHandle>;\n /** All sortables registered in this scope, kept for scope.dispose(). */\n disposables: Set<() => void>;\n}\n\n// ─── Internal constants ───────────────────────────────────────────────────────\n\nconst HANDLE_ATTR = 'data-dnd-handle';\nconst ITEM_ATTR = 'data-dnd-item';\nconst sortableScopeStates = new WeakMap<SortableScope, SortableScopeState>();\nconst DEFAULT_AUTO_SCROLL: ResolvedAutoScrollOptions = {\n container: true,\n edgeThreshold: 32,\n speed: 18,\n viewport: false,\n};\n\n// ─── Scope helpers ────────────────────────────────────────────────────────────\n\nfunction getSortableScopeState(scope: SortableScope): SortableScopeState {\n const state = sortableScopeStates.get(scope);\n\n if (!state) throw new DndScopeError();\n\n return state;\n}\n\n// ─── Option resolution ────────────────────────────────────────────────────────\n\nfunction resolveAutoScrollOptions(\n autoScroll: boolean | AutoScrollOptions | undefined,\n): ResolvedAutoScrollOptions | null {\n if (autoScroll === false) return null;\n\n if (autoScroll === true || autoScroll === undefined) return DEFAULT_AUTO_SCROLL;\n\n return {\n container: autoScroll.container ?? true,\n edgeThreshold: autoScroll.edgeThreshold ?? 32,\n speed: autoScroll.speed ?? 18,\n viewport: autoScroll.viewport ?? false,\n };\n}\n\n// ─── DOM helpers ──────────────────────────────────────────────────────────────\n\nfunction hasOrderChanged(before: string[], after: string[]): boolean {\n return after.length !== before.length || after.some((id, index) => id !== before[index]);\n}\n\nfunction clearHandleAttributes(element: HTMLElement): void {\n element.querySelectorAll<HTMLElement>(`[${HANDLE_ATTR}]`).forEach((handleEl) => {\n handleEl.removeAttribute(HANDLE_ATTR);\n handleEl.removeAttribute('draggable');\n handleEl.style.touchAction = '';\n });\n}\n\n// ─── Drag session helpers ─────────────────────────────────────────────────────\n\nfunction scheduleHide(session: DragSession): void {\n if (typeof requestAnimationFrame !== 'function') return;\n\n session.hideFrame = requestAnimationFrame(() => {\n session.hideFrame = null;\n session.draggedEl.style.display = 'none';\n });\n}\n\nfunction cancelHide(session: DragSession): void {\n if (session.hideFrame !== null) {\n cancelAnimationFrame(session.hideFrame);\n session.hideFrame = null;\n }\n}\n\nfunction restoreSessionElement(session: DragSession): void {\n cancelHide(session);\n session.draggedEl.style.display = session.originalDisplay;\n session.draggedEl.removeAttribute('data-dragging');\n}\n\n/**\n * Snapshot a handle's current order if not already recorded.\n * Called the first time a handle becomes an active target so we only capture\n * lists that actually participate in the drag.\n */\nfunction snapshotOrder(session: DragSession, handle: ContainerHandle): void {\n if (!session.initialOrders.has(handle)) {\n session.initialOrders.set(handle, handle.getOrderedIds());\n }\n}\n\n// ─── Session commit / cancel ──────────────────────────────────────────────────\n\nfunction cancelSession(scopeState: SortableScopeState, event: DragEvent): void {\n const session = scopeState.active;\n\n if (!session) return;\n\n restoreSessionElement(session);\n session.originalParent.insertBefore(session.draggedEl, session.originalNextSibling);\n session.placeholder.remove();\n scopeState.active = null;\n\n session.source.notifyDragEnd(session.draggedId, event);\n}\n\nfunction commitSession(scopeState: SortableScopeState, event: DragEvent): void {\n const session = scopeState.active;\n\n if (!session) return;\n\n const targetHandle = session.target;\n const targetElement = session.placeholder.parentElement;\n\n restoreSessionElement(session);\n\n if (targetHandle && scopeState.handles.has(targetHandle) && targetElement) {\n targetElement.insertBefore(session.draggedEl, session.placeholder);\n } else {\n session.originalParent.insertBefore(session.draggedEl, session.originalNextSibling);\n }\n\n session.placeholder.remove();\n scopeState.active = null;\n\n session.source.notifyDragEnd(session.draggedId, event);\n\n for (const [handle, beforeOrder] of session.initialOrders) {\n if (!scopeState.handles.has(handle)) continue;\n\n const afterOrder = handle.getOrderedIds();\n\n if (!hasOrderChanged(beforeOrder, afterOrder)) continue;\n\n handle.notifyBeforeReorder(beforeOrder, afterOrder);\n handle.commitReorder(afterOrder);\n }\n}\n\nfunction finishSession(scopeState: SortableScopeState, event: DragEvent, forceCancel: boolean): void {\n if (!scopeState.active) return;\n\n const { active } = scopeState;\n\n // If source or target became disabled during the drag, treat as cancellation.\n if (\n forceCancel ||\n !event.dataTransfer ||\n event.dataTransfer.dropEffect === 'none' ||\n !active.target ||\n !scopeState.handles.has(active.target) ||\n active.source.isDisabled() ||\n active.target.isDisabled()\n ) {\n cancelSession(scopeState, event);\n } else {\n commitSession(scopeState, event);\n }\n}\n\nfunction maybeAutoScroll(\n event: DragEvent,\n container: HTMLElement,\n axis: 'vertical' | 'horizontal',\n options: ResolvedAutoScrollOptions | null,\n): void {\n if (!options) return;\n\n const { container: scrollContainer, edgeThreshold: threshold, speed, viewport } = options;\n const rect = container.getBoundingClientRect();\n\n if (axis === 'vertical') {\n if (scrollContainer && event.clientY < rect.top + threshold) {\n container.scrollTop -= speed;\n } else if (scrollContainer && event.clientY > rect.bottom - threshold) {\n container.scrollTop += speed;\n }\n\n if (viewport && event.clientY < threshold) {\n window.scrollBy({ left: 0, top: -speed });\n } else if (viewport && event.clientY > window.innerHeight - threshold) {\n window.scrollBy({ left: 0, top: speed });\n }\n\n return;\n }\n\n if (scrollContainer && event.clientX < rect.left + threshold) {\n container.scrollLeft -= speed;\n } else if (scrollContainer && event.clientX > rect.right - threshold) {\n container.scrollLeft += speed;\n }\n\n if (viewport && event.clientX < threshold) {\n window.scrollBy({ left: -speed, top: 0 });\n } else if (viewport && event.clientX > window.innerWidth - threshold) {\n window.scrollBy({ left: speed, top: 0 });\n }\n}\n\n// ─── Keyboard reorder ─────────────────────────────────────────────────────────\n\nfunction applyKeyboardReorder(\n item: HTMLElement,\n element: HTMLElement,\n getItems: () => HTMLElement[],\n getOrderedIds: () => string[],\n key: string,\n axis: 'vertical' | 'horizontal',\n): string[] | null {\n const items = getItems();\n const currentIndex = items.indexOf(item);\n\n if (currentIndex < 0) return null;\n\n const isForward = axis === 'vertical' ? key === 'ArrowDown' : key === 'ArrowRight';\n const isBackward = axis === 'vertical' ? key === 'ArrowUp' : key === 'ArrowLeft';\n let targetIndex: number;\n\n if (isForward) {\n targetIndex = Math.min(items.length - 1, currentIndex + 1);\n } else if (isBackward) {\n targetIndex = Math.max(0, currentIndex - 1);\n } else if (key === 'Home') {\n targetIndex = 0;\n } else if (key === 'End') {\n targetIndex = items.length - 1;\n } else {\n return null;\n }\n\n // Already at the boundary — return null so the caller does not call preventDefault\n // and the browser can handle the key (e.g. scrolling the page).\n if (targetIndex === currentIndex) return null;\n\n const targetItem = items[targetIndex];\n\n if (!targetItem) return null;\n\n element.insertBefore(item, targetIndex > currentIndex ? targetItem.nextSibling : targetItem);\n item.focus();\n\n return getOrderedIds();\n}\n\n// ─── createSortableScope ──────────────────────────────────────────────────────\n\n/**\n * Create a shared scope for connected sortable containers.\n *\n * Items can be dragged between all sortables that share the same scope.\n * The scope exposes `isDragging` and `dispose()` — calling `dispose()` tears down\n * all member sortables at once.\n *\n * @example\n * ```ts\n * const scope = createSortableScope();\n * const left = createSortable({ element: leftEl, scope, getKey, onReorder });\n * const right = createSortable({ element: rightEl, scope, getKey, onReorder });\n *\n * // Tear down everything at once:\n * scope.dispose();\n * ```\n */\nexport function createSortableScope(): SortableScope {\n const state: SortableScopeState = { active: null, disposables: new Set(), handles: new Set() };\n const disposable = createDisposable(() => {\n // Dispose all registered sortables (each dispose() call is idempotent)\n for (const disposeFn of state.disposables) {\n disposeFn();\n }\n });\n\n const scope = {\n get disposalSignal() {\n return disposable.disposalSignal;\n },\n dispose: disposable.dispose,\n get disposed() {\n return disposable.disposed;\n },\n get isDragging() {\n return state.active !== null;\n },\n [SCOPE_BRAND]: true as const,\n [Symbol.dispose]: disposable[Symbol.dispose],\n } as SortableScope;\n\n sortableScopeStates.set(scope, state);\n\n return scope;\n}\n\n// ─── createSortable ───────────────────────────────────────────────────────────\n\n/**\n * Makes a list of items sortable via native HTML drag interactions.\n *\n * Provide `getKey` to map each item element to a stable string identity.\n * `createSortable` marks qualifying children with `data-dnd-item` and sets\n * `draggable=\"true\"` automatically.\n *\n * Style the drop indicator by targeting `.dnd-placeholder` in your CSS.\n * Supports keyboard reordering (arrow keys, Home/End) and auto-scrolling near edges.\n *\n * @example\n * ```ts\n * import { createSortable } from '@vielzeug/dnd';\n *\n * using sortable = createSortable({\n * element: listEl,\n * getKey: (el) => el.dataset.id!,\n * onReorder: ({ ids, setRevert }) => {\n * const prev = order;\n * setOrder(ids);\n * setRevert(() => setOrder(prev));\n * },\n * });\n * ```\n */\nexport function createSortable(options: SortableOptions): Sortable {\n const {\n autoScroll = true,\n axis = 'vertical',\n element,\n getKey,\n handle,\n keyboard = true,\n placeholderClass = 'dnd-placeholder',\n scope = createSortableScope(),\n } = options;\n const autoScrollOptions = resolveAutoScrollOptions(autoScroll);\n const scopeState = getSortableScopeState(scope);\n\n if (handle !== undefined && handle.trim() === '') {\n warn(\n 'handle option is an empty string — no handle elements will be found. Provide a valid CSS selector or omit the option.',\n );\n }\n\n const getItems = (): HTMLElement[] =>\n Array.from(element.children).filter((c) => (c as HTMLElement).hasAttribute(ITEM_ATTR)) as HTMLElement[];\n\n const getOrderedIds = (): string[] => getItems().map((el) => getKey(el));\n\n const syncItems = (): void => {\n clearHandleAttributes(element);\n\n getItems().forEach((el) => {\n el.setAttribute('role', 'listitem');\n el.tabIndex = 0;\n\n if (handle) {\n el.removeAttribute('draggable');\n el.style.touchAction = '';\n el.querySelectorAll<HTMLElement>(handle).forEach((handleEl) => {\n handleEl.setAttribute(HANDLE_ATTR, '');\n handleEl.setAttribute('draggable', 'true');\n // See the matching comment above `cleanupItems()` for why this matters at all.\n handleEl.style.touchAction = 'none';\n });\n } else {\n el.setAttribute('draggable', 'true');\n // A native mouse drag has no competing gesture to arbitrate; touch does. Without this,\n // a mobile browser can decide the very first bit of finger movement is a page\n // scroll/pan — a decision it makes independently of, and before, this library's own\n // touch-shim threshold/`preventDefault()` logic ever runs — and hand the rest of the\n // gesture to native scrolling. Once that happens the item never receives the\n // `dragover` sequence needed to update the drop target, so the session ends up\n // committing back to wherever it started: indistinguishable from the drop \"reverting\".\n // `touch-action: none` opts the element out of every default touch gesture from\n // `touchstart` onward, leaving the whole interaction to this library's own JS.\n el.style.touchAction = 'none';\n }\n });\n };\n\n const markItems = (): void => {\n const seenKeys = new Set<string>();\n\n // Mark all children that have a key as sortable items\n Array.from(element.children).forEach((child) => {\n const el = child as HTMLElement;\n\n try {\n const key = getKey(el);\n\n if (key) {\n if (seenKeys.has(key)) {\n warn(\n `getKey returned the duplicate key \"${key}\" for two sibling items — onReorder's ids and applyReorder may become inconsistent. Ensure getKey returns a unique value per item.`,\n );\n } else {\n seenKeys.add(key);\n }\n\n el.setAttribute(ITEM_ATTR, '');\n }\n } catch (err) {\n warn(\n `getKey threw for a child element — the item will not be sortable. Check your getKey implementation. ${String(err)}`,\n );\n }\n });\n\n syncItems();\n };\n\n const cleanupItems = (): void => {\n clearHandleAttributes(element);\n\n element.querySelectorAll<HTMLElement>(`[${ITEM_ATTR}]`).forEach((item) => {\n item.removeAttribute(ITEM_ATTR);\n item.removeAttribute('draggable');\n item.removeAttribute('role');\n item.removeAttribute('tabindex');\n item.style.touchAction = '';\n });\n };\n\n const createPlaceholder = (source: HTMLElement): HTMLElement => {\n const p = document.createElement('div');\n\n p.className = placeholderClass;\n p.setAttribute('aria-hidden', 'true');\n\n if (axis === 'horizontal') {\n p.style.width = `${source.offsetWidth}px`;\n } else {\n p.style.height = `${source.offsetHeight}px`;\n }\n\n return p;\n };\n\n let lastRevert: (() => void) | null = null;\n\n const handle_: ContainerHandle = {\n commitReorder: (orderedIds) => {\n if (!options.onReorder) return;\n\n const event: ReorderEvent = {\n ids: orderedIds,\n setRevert(fn) {\n lastRevert = fn;\n },\n };\n\n options.onReorder(event);\n },\n getOrderedIds,\n isDisabled: () => resolveDisabled(options.disabled),\n notifyBeforeReorder: (from, to) => options.onBeforeReorder?.(from, to),\n notifyDragEnd: (id, event) => options.onDragEnd?.(id, event),\n notifyDragStart: (id, event) => options.onDragStart?.(id, event),\n };\n\n scopeState.handles.add(handle_);\n\n const handleDragStart = (e: DragEvent): void => {\n if (scopeState.active) return;\n\n if (handle_.isDisabled()) return;\n\n const target = e.target as HTMLElement;\n const item = target.closest<HTMLElement>(`[${ITEM_ATTR}]`);\n\n if (!item) return;\n\n if (handle && !target.closest(handle)) return;\n\n const originalParent = item.parentElement;\n\n if (!originalParent) return;\n\n const placeholder = createPlaceholder(item);\n const originalNextSibling = item.nextSibling;\n const activeId = getKey(item);\n\n // Snapshot only the source handle at drag start; targets are snapshotted lazily.\n const initialOrders = new Map<ContainerHandle, string[]>();\n\n initialOrders.set(handle_, handle_.getOrderedIds());\n item.setAttribute('data-dragging', '');\n originalParent.insertBefore(placeholder, originalNextSibling);\n\n const session: DragSession = {\n draggedEl: item,\n draggedId: activeId,\n hideFrame: null,\n initialOrders,\n originalDisplay: item.style.display,\n originalNextSibling,\n originalParent,\n placeholder,\n source: handle_,\n target: handle_,\n };\n\n scheduleHide(session);\n scopeState.active = session;\n\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', activeId);\n\n if (options.dragImage) {\n const preview =\n typeof options.dragImage === 'function' ? options.dragImage(activeId, item, e) : options.dragImage;\n const [offsetX, offsetY] = options.dragImageOffset ?? [0, 0];\n\n if (preview) e.dataTransfer.setDragImage(preview, offsetX, offsetY);\n }\n }\n\n handle_.notifyDragStart(session.draggedId, e);\n };\n\n const handleDragOver = (e: DragEvent): void => {\n const session = scopeState.active;\n\n if (!session) return;\n\n if (session.source.isDisabled() || handle_.isDisabled()) return;\n\n e.preventDefault();\n maybeAutoScroll(e, element, axis, autoScrollOptions);\n\n // Lazily snapshot this handle's order the first time it becomes a target.\n snapshotOrder(session, handle_);\n\n const { draggedEl, placeholder } = session;\n const target = (e.target as HTMLElement).closest<HTMLElement>(`[${ITEM_ATTR}]`);\n\n if (!target) {\n // Only append placeholder when it isn't already inside this container.\n // Moving it to the end on every over-empty-space event causes the\n // placeholder to oscillate between positions as the cursor moves.\n if (placeholder.parentElement !== element) {\n element.appendChild(placeholder);\n }\n\n session.target = handle_;\n\n return;\n }\n\n if (target === draggedEl || target === placeholder) return;\n\n const rect = target.getBoundingClientRect();\n const insertAfter =\n axis === 'vertical' ? e.clientY >= rect.top + rect.height / 2 : e.clientX >= rect.left + rect.width / 2;\n\n element.insertBefore(placeholder, insertAfter ? target.nextSibling : target);\n session.target = handle_;\n };\n\n const handleDrop = (e: DragEvent): void => {\n const session = scopeState.active;\n\n if (!session) return;\n\n if (session.source.isDisabled() || handle_.isDisabled()) return;\n\n e.preventDefault();\n // Record the drop target; the actual commit happens in handleDragEnd where\n // dataTransfer.dropEffect tells us whether the browser accepted the operation.\n session.target = handle_;\n };\n\n const handleDragEnd = (e: DragEvent): void => {\n if (scopeState.active?.source !== handle_) return;\n\n finishSession(scopeState, e, false);\n };\n\n const handleKeydown = (e: KeyboardEvent): void => {\n if (!keyboard || handle_.isDisabled()) return;\n\n const tagName = (e.target as HTMLElement | null)?.tagName;\n\n if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') return;\n\n const item = (e.target as HTMLElement).closest<HTMLElement>(`[${ITEM_ATTR}]`);\n\n if (!item || !element.contains(item)) return;\n\n const prevOrder = getOrderedIds();\n const newOrder = applyKeyboardReorder(item, element, getItems, getOrderedIds, e.key, axis);\n\n // null means unrecognized key or boundary — let the browser handle it (e.g. page scroll)\n if (newOrder === null) return;\n\n e.preventDefault();\n handle_.notifyBeforeReorder(prevOrder, newOrder);\n handle_.commitReorder(newOrder);\n };\n\n markItems();\n\n const disposable = createDisposable(() => {\n scopeState.disposables.delete(disposable.dispose);\n\n if (scopeState.active && (scopeState.active.source === handle_ || scopeState.active.target === handle_)) {\n finishSession(scopeState, new Event('dragend') as DragEvent, true);\n }\n\n scopeState.handles.delete(handle_);\n element.removeAttribute('role');\n cleanupItems();\n });\n\n element.setAttribute('role', 'list');\n element.addEventListener('dragstart', handleDragStart, { signal: disposable.disposalSignal });\n element.addEventListener('dragover', handleDragOver, { signal: disposable.disposalSignal });\n element.addEventListener('drop', handleDrop, { signal: disposable.disposalSignal });\n element.addEventListener('dragend', handleDragEnd, { signal: disposable.disposalSignal });\n element.addEventListener('keydown', handleKeydown, { signal: disposable.disposalSignal });\n\n // Register with scope so scope.dispose() can tear this down\n scopeState.disposables.add(disposable.dispose);\n\n return {\n get disposalSignal() {\n return disposable.disposalSignal;\n },\n dispose: disposable.dispose,\n get disposed() {\n return disposable.disposed;\n },\n get isDragging() {\n return scopeState.active?.source === handle_;\n },\n revert: () => {\n lastRevert?.();\n lastRevert = null;\n },\n [Symbol.dispose]: disposable[Symbol.dispose],\n sync: () => {\n markItems();\n },\n };\n}\n\n// ─── applyReorder ─────────────────────────────────────────────────────────────\n\n/**\n * Applies a sorted key array to a backing data array.\n * Unknown keys are ignored; items not present in `ids` are appended in original order.\n */\nexport function applyReorder<T>(items: T[], ids: string[], getKey: (item: T) => string): T[] {\n const byId = new Map(items.map((item) => [getKey(item), item] as const));\n const ordered: T[] = [];\n\n for (const id of ids) {\n if (!byId.has(id)) continue;\n\n const item = byId.get(id) as T;\n\n ordered.push(item);\n byId.delete(id);\n }\n\n for (const item of byId.values()) ordered.push(item);\n\n return ordered;\n}\n"],"mappings":"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"}
package/dist/sortable.js CHANGED
@@ -1,69 +1,69 @@
1
1
  import { createDisposable as e, resolveDisabled as t } from "./_shared.js";
2
2
  import { DndScopeError as n } from "./errors.js";
3
- import { warn as r } from "./_dev.js";
3
+ import "./_dev.js";
4
4
  //#region src/sortable.ts
5
- var i = Symbol("SortableScope"), a = "data-dnd-handle", o = "data-dnd-item", s = /* @__PURE__ */ new WeakMap(), c = {
5
+ var r = Symbol("SortableScope"), i = "data-dnd-handle", a = "data-dnd-item", o = /* @__PURE__ */ new WeakMap(), s = {
6
6
  container: !0,
7
7
  edgeThreshold: 32,
8
8
  speed: 18,
9
9
  viewport: !1
10
10
  };
11
- function l(e) {
12
- let t = s.get(e);
11
+ function c(e) {
12
+ let t = o.get(e);
13
13
  if (!t) throw new n();
14
14
  return t;
15
15
  }
16
- function u(e) {
17
- return e === !1 ? null : e === !0 || e === void 0 ? c : {
16
+ function l(e) {
17
+ return e === !1 ? null : e === !0 || e === void 0 ? s : {
18
18
  container: e.container ?? !0,
19
19
  edgeThreshold: e.edgeThreshold ?? 32,
20
20
  speed: e.speed ?? 18,
21
21
  viewport: e.viewport ?? !1
22
22
  };
23
23
  }
24
- function d(e, t) {
24
+ function u(e, t) {
25
25
  return t.length !== e.length || t.some((t, n) => t !== e[n]);
26
26
  }
27
- function f(e) {
28
- e.querySelectorAll(`[${a}]`).forEach((e) => {
29
- e.removeAttribute(a), e.removeAttribute("draggable"), e.style.touchAction = "";
27
+ function d(e) {
28
+ e.querySelectorAll(`[${i}]`).forEach((e) => {
29
+ e.removeAttribute(i), e.removeAttribute("draggable"), e.style.touchAction = "";
30
30
  });
31
31
  }
32
- function p(e) {
32
+ function f(e) {
33
33
  typeof requestAnimationFrame == "function" && (e.hideFrame = requestAnimationFrame(() => {
34
34
  e.hideFrame = null, e.draggedEl.style.display = "none";
35
35
  }));
36
36
  }
37
- function m(e) {
37
+ function p(e) {
38
38
  e.hideFrame !== null && (cancelAnimationFrame(e.hideFrame), e.hideFrame = null);
39
39
  }
40
- function h(e) {
41
- m(e), e.draggedEl.style.display = e.originalDisplay, e.draggedEl.removeAttribute("data-dragging");
40
+ function m(e) {
41
+ p(e), e.draggedEl.style.display = e.originalDisplay, e.draggedEl.removeAttribute("data-dragging");
42
42
  }
43
- function g(e, t) {
43
+ function h(e, t) {
44
44
  e.initialOrders.has(t) || e.initialOrders.set(t, t.getOrderedIds());
45
45
  }
46
- function _(e, t) {
46
+ function g(e, t) {
47
47
  let n = e.active;
48
- n && (h(n), n.originalParent.insertBefore(n.draggedEl, n.originalNextSibling), n.placeholder.remove(), e.active = null, n.source.notifyDragEnd(n.draggedId, t));
48
+ n && (m(n), n.originalParent.insertBefore(n.draggedEl, n.originalNextSibling), n.placeholder.remove(), e.active = null, n.source.notifyDragEnd(n.draggedId, t));
49
49
  }
50
- function v(e, t) {
50
+ function _(e, t) {
51
51
  let n = e.active;
52
52
  if (!n) return;
53
53
  let r = n.target, i = n.placeholder.parentElement;
54
- h(n), r && e.handles.has(r) && i ? i.insertBefore(n.draggedEl, n.placeholder) : n.originalParent.insertBefore(n.draggedEl, n.originalNextSibling), n.placeholder.remove(), e.active = null, n.source.notifyDragEnd(n.draggedId, t);
54
+ m(n), r && e.handles.has(r) && i ? i.insertBefore(n.draggedEl, n.placeholder) : n.originalParent.insertBefore(n.draggedEl, n.originalNextSibling), n.placeholder.remove(), e.active = null, n.source.notifyDragEnd(n.draggedId, t);
55
55
  for (let [t, r] of n.initialOrders) {
56
56
  if (!e.handles.has(t)) continue;
57
57
  let n = t.getOrderedIds();
58
- d(r, n) && (t.notifyBeforeReorder(r, n), t.commitReorder(n));
58
+ u(r, n) && (t.notifyBeforeReorder(r, n), t.commitReorder(n));
59
59
  }
60
60
  }
61
- function y(e, t, n) {
61
+ function v(e, t, n) {
62
62
  if (!e.active) return;
63
63
  let { active: r } = e;
64
- n || !t.dataTransfer || t.dataTransfer.dropEffect === "none" || !r.target || !e.handles.has(r.target) || r.source.isDisabled() || r.target.isDisabled() ? _(e, t) : v(e, t);
64
+ n || !t.dataTransfer || t.dataTransfer.dropEffect === "none" || !r.target || !e.handles.has(r.target) || r.source.isDisabled() || r.target.isDisabled() ? g(e, t) : _(e, t);
65
65
  }
66
- function b(e, t, n, r) {
66
+ function y(e, t, n, r) {
67
67
  if (!r) return;
68
68
  let { container: i, edgeThreshold: a, speed: o, viewport: s } = r, c = t.getBoundingClientRect();
69
69
  if (n === "vertical") {
@@ -84,7 +84,7 @@ function b(e, t, n, r) {
84
84
  top: 0
85
85
  });
86
86
  }
87
- function x(e, t, n, r, i, a) {
87
+ function b(e, t, n, r, i, a) {
88
88
  let o = n(), s = o.indexOf(e);
89
89
  if (s < 0) return null;
90
90
  let c = a === "vertical" ? i === "ArrowDown" : i === "ArrowRight", l = a === "vertical" ? i === "ArrowUp" : i === "ArrowLeft", u;
@@ -97,14 +97,14 @@ function x(e, t, n, r, i, a) {
97
97
  let d = o[u];
98
98
  return d ? (t.insertBefore(e, u > s ? d.nextSibling : d), e.focus(), r()) : null;
99
99
  }
100
- function S() {
100
+ function x() {
101
101
  let t = {
102
102
  active: null,
103
103
  disposables: /* @__PURE__ */ new Set(),
104
104
  handles: /* @__PURE__ */ new Set()
105
105
  }, n = e(() => {
106
106
  for (let e of t.disposables) e();
107
- }), r = {
107
+ }), i = {
108
108
  get disposalSignal() {
109
109
  return n.disposalSignal;
110
110
  },
@@ -115,65 +115,65 @@ function S() {
115
115
  get isDragging() {
116
116
  return t.active !== null;
117
117
  },
118
- [i]: !0,
118
+ [r]: !0,
119
119
  [Symbol.dispose]: n[Symbol.dispose]
120
120
  };
121
- return s.set(r, t), r;
121
+ return o.set(i, t), i;
122
122
  }
123
- function C(n) {
124
- let { autoScroll: i = !0, axis: s = "vertical", element: c, getKey: d, handle: m, keyboard: h = !0, placeholderClass: _ = "dnd-placeholder", scope: v = S() } = n, C = u(i), w = l(v);
125
- m !== void 0 && m.trim() === "" && r("handle option is an empty string — no handle elements will be found. Provide a valid CSS selector or omit the option.");
126
- let T = () => Array.from(c.children).filter((e) => e.hasAttribute(o)), E = () => T().map((e) => d(e)), D = () => {
127
- f(c), T().forEach((e) => {
128
- e.setAttribute("role", "listitem"), e.tabIndex = 0, m ? (e.removeAttribute("draggable"), e.style.touchAction = "", e.querySelectorAll(m).forEach((e) => {
129
- e.setAttribute(a, ""), e.setAttribute("draggable", "true"), e.style.touchAction = "none";
123
+ function S(n) {
124
+ let { autoScroll: r = !0, axis: o = "vertical", element: s, getKey: u, handle: p, keyboard: m = !0, placeholderClass: g = "dnd-placeholder", scope: _ = x() } = n, S = l(r), C = c(_);
125
+ p !== void 0 && p.trim();
126
+ let w = () => Array.from(s.children).filter((e) => e.hasAttribute(a)), T = () => w().map((e) => u(e)), E = () => {
127
+ d(s), w().forEach((e) => {
128
+ e.setAttribute("role", "listitem"), e.tabIndex = 0, p ? (e.removeAttribute("draggable"), e.style.touchAction = "", e.querySelectorAll(p).forEach((e) => {
129
+ e.setAttribute(i, ""), e.setAttribute("draggable", "true"), e.style.touchAction = "none";
130
130
  })) : (e.setAttribute("draggable", "true"), e.style.touchAction = "none");
131
131
  });
132
- }, O = () => {
132
+ }, D = () => {
133
133
  let e = /* @__PURE__ */ new Set();
134
- Array.from(c.children).forEach((t) => {
134
+ Array.from(s.children).forEach((t) => {
135
135
  let n = t;
136
136
  try {
137
- let t = d(n);
138
- t && (e.has(t) ? r(`getKey returned the duplicate key "${t}" for two sibling items — onReorder's ids and applyReorder may become inconsistent. Ensure getKey returns a unique value per item.`) : e.add(t), n.setAttribute(o, ""));
137
+ let t = u(n);
138
+ t && (e.has(t) ? `${t}` : e.add(t), n.setAttribute(a, ""));
139
139
  } catch (e) {
140
- r(`getKey threw for a child element — the item will not be sortable. Check your getKey implementation. ${String(e)}`);
140
+ `${String(e)}`;
141
141
  }
142
- }), D();
143
- }, k = () => {
144
- f(c), c.querySelectorAll(`[${o}]`).forEach((e) => {
145
- e.removeAttribute(o), e.removeAttribute("draggable"), e.removeAttribute("role"), e.removeAttribute("tabindex"), e.style.touchAction = "";
142
+ }), E();
143
+ }, O = () => {
144
+ d(s), s.querySelectorAll(`[${a}]`).forEach((e) => {
145
+ e.removeAttribute(a), e.removeAttribute("draggable"), e.removeAttribute("role"), e.removeAttribute("tabindex"), e.style.touchAction = "";
146
146
  });
147
- }, A = (e) => {
147
+ }, k = (e) => {
148
148
  let t = document.createElement("div");
149
- return t.className = _, t.setAttribute("aria-hidden", "true"), s === "horizontal" ? t.style.width = `${e.offsetWidth}px` : t.style.height = `${e.offsetHeight}px`, t;
150
- }, j = null, M = {
149
+ return t.className = g, t.setAttribute("aria-hidden", "true"), o === "horizontal" ? t.style.width = `${e.offsetWidth}px` : t.style.height = `${e.offsetHeight}px`, t;
150
+ }, A = null, j = {
151
151
  commitReorder: (e) => {
152
152
  if (!n.onReorder) return;
153
153
  let t = {
154
154
  ids: e,
155
155
  setRevert(e) {
156
- j = e;
156
+ A = e;
157
157
  }
158
158
  };
159
159
  n.onReorder(t);
160
160
  },
161
- getOrderedIds: E,
161
+ getOrderedIds: T,
162
162
  isDisabled: () => t(n.disabled),
163
163
  notifyBeforeReorder: (e, t) => n.onBeforeReorder?.(e, t),
164
164
  notifyDragEnd: (e, t) => n.onDragEnd?.(e, t),
165
165
  notifyDragStart: (e, t) => n.onDragStart?.(e, t)
166
166
  };
167
- w.handles.add(M);
168
- let N = (e) => {
169
- if (w.active || M.isDisabled()) return;
170
- let t = e.target, r = t.closest(`[${o}]`);
171
- if (!r || m && !t.closest(m)) return;
167
+ C.handles.add(j);
168
+ let M = (e) => {
169
+ if (C.active || j.isDisabled()) return;
170
+ let t = e.target, r = t.closest(`[${a}]`);
171
+ if (!r || p && !t.closest(p)) return;
172
172
  let i = r.parentElement;
173
173
  if (!i) return;
174
- let a = A(r), s = r.nextSibling, c = d(r), l = /* @__PURE__ */ new Map();
175
- l.set(M, M.getOrderedIds()), r.setAttribute("data-dragging", ""), i.insertBefore(a, s);
176
- let u = {
174
+ let o = k(r), s = r.nextSibling, c = u(r), l = /* @__PURE__ */ new Map();
175
+ l.set(j, j.getOrderedIds()), r.setAttribute("data-dragging", ""), i.insertBefore(o, s);
176
+ let d = {
177
177
  draggedEl: r,
178
178
  draggedId: c,
179
179
  hideFrame: null,
@@ -181,66 +181,66 @@ function C(n) {
181
181
  originalDisplay: r.style.display,
182
182
  originalNextSibling: s,
183
183
  originalParent: i,
184
- placeholder: a,
185
- source: M,
186
- target: M
184
+ placeholder: o,
185
+ source: j,
186
+ target: j
187
187
  };
188
- if (p(u), w.active = u, e.dataTransfer && (e.dataTransfer.effectAllowed = "move", e.dataTransfer.setData("text/plain", c), n.dragImage)) {
188
+ if (f(d), C.active = d, e.dataTransfer && (e.dataTransfer.effectAllowed = "move", e.dataTransfer.setData("text/plain", c), n.dragImage)) {
189
189
  let t = typeof n.dragImage == "function" ? n.dragImage(c, r, e) : n.dragImage, [i, a] = n.dragImageOffset ?? [0, 0];
190
190
  t && e.dataTransfer.setDragImage(t, i, a);
191
191
  }
192
- M.notifyDragStart(u.draggedId, e);
193
- }, P = (e) => {
194
- let t = w.active;
195
- if (!t || t.source.isDisabled() || M.isDisabled()) return;
196
- e.preventDefault(), b(e, c, s, C), g(t, M);
197
- let { draggedEl: n, placeholder: r } = t, i = e.target.closest(`[${o}]`);
192
+ j.notifyDragStart(d.draggedId, e);
193
+ }, N = (e) => {
194
+ let t = C.active;
195
+ if (!t || t.source.isDisabled() || j.isDisabled()) return;
196
+ e.preventDefault(), y(e, s, o, S), h(t, j);
197
+ let { draggedEl: n, placeholder: r } = t, i = e.target.closest(`[${a}]`);
198
198
  if (!i) {
199
- r.parentElement !== c && c.appendChild(r), t.target = M;
199
+ r.parentElement !== s && s.appendChild(r), t.target = j;
200
200
  return;
201
201
  }
202
202
  if (i === n || i === r) return;
203
- let a = i.getBoundingClientRect(), l = s === "vertical" ? e.clientY >= a.top + a.height / 2 : e.clientX >= a.left + a.width / 2;
204
- c.insertBefore(r, l ? i.nextSibling : i), t.target = M;
203
+ let c = i.getBoundingClientRect(), l = o === "vertical" ? e.clientY >= c.top + c.height / 2 : e.clientX >= c.left + c.width / 2;
204
+ s.insertBefore(r, l ? i.nextSibling : i), t.target = j;
205
+ }, P = (e) => {
206
+ let t = C.active;
207
+ t && (t.source.isDisabled() || j.isDisabled() || (e.preventDefault(), t.target = j));
205
208
  }, F = (e) => {
206
- let t = w.active;
207
- t && (t.source.isDisabled() || M.isDisabled() || (e.preventDefault(), t.target = M));
209
+ C.active?.source === j && v(C, e, !1);
208
210
  }, I = (e) => {
209
- w.active?.source === M && y(w, e, !1);
210
- }, L = (e) => {
211
- if (!h || M.isDisabled()) return;
211
+ if (!m || j.isDisabled()) return;
212
212
  let t = e.target?.tagName;
213
213
  if (t === "INPUT" || t === "TEXTAREA" || t === "SELECT") return;
214
- let n = e.target.closest(`[${o}]`);
215
- if (!n || !c.contains(n)) return;
216
- let r = E(), i = x(n, c, T, E, e.key, s);
217
- i !== null && (e.preventDefault(), M.notifyBeforeReorder(r, i), M.commitReorder(i));
214
+ let n = e.target.closest(`[${a}]`);
215
+ if (!n || !s.contains(n)) return;
216
+ let r = T(), i = b(n, s, w, T, e.key, o);
217
+ i !== null && (e.preventDefault(), j.notifyBeforeReorder(r, i), j.commitReorder(i));
218
218
  };
219
- O();
220
- let R = e(() => {
221
- w.disposables.delete(R.dispose), w.active && (w.active.source === M || w.active.target === M) && y(w, new Event("dragend"), !0), w.handles.delete(M), c.removeAttribute("role"), k();
219
+ D();
220
+ let L = e(() => {
221
+ C.disposables.delete(L.dispose), C.active && (C.active.source === j || C.active.target === j) && v(C, new Event("dragend"), !0), C.handles.delete(j), s.removeAttribute("role"), O();
222
222
  });
223
- return c.setAttribute("role", "list"), c.addEventListener("dragstart", N, { signal: R.disposalSignal }), c.addEventListener("dragover", P, { signal: R.disposalSignal }), c.addEventListener("drop", F, { signal: R.disposalSignal }), c.addEventListener("dragend", I, { signal: R.disposalSignal }), c.addEventListener("keydown", L, { signal: R.disposalSignal }), w.disposables.add(R.dispose), {
223
+ return s.setAttribute("role", "list"), s.addEventListener("dragstart", M, { signal: L.disposalSignal }), s.addEventListener("dragover", N, { signal: L.disposalSignal }), s.addEventListener("drop", P, { signal: L.disposalSignal }), s.addEventListener("dragend", F, { signal: L.disposalSignal }), s.addEventListener("keydown", I, { signal: L.disposalSignal }), C.disposables.add(L.dispose), {
224
224
  get disposalSignal() {
225
- return R.disposalSignal;
225
+ return L.disposalSignal;
226
226
  },
227
- dispose: R.dispose,
227
+ dispose: L.dispose,
228
228
  get disposed() {
229
- return R.disposed;
229
+ return L.disposed;
230
230
  },
231
231
  get isDragging() {
232
- return w.active?.source === M;
232
+ return C.active?.source === j;
233
233
  },
234
234
  revert: () => {
235
- j?.(), j = null;
235
+ A?.(), A = null;
236
236
  },
237
- [Symbol.dispose]: R[Symbol.dispose],
237
+ [Symbol.dispose]: L[Symbol.dispose],
238
238
  sync: () => {
239
- O();
239
+ D();
240
240
  }
241
241
  };
242
242
  }
243
- function w(e, t, n) {
243
+ function C(e, t, n) {
244
244
  let r = new Map(e.map((e) => [n(e), e])), i = [];
245
245
  for (let e of t) {
246
246
  if (!r.has(e)) continue;
@@ -251,6 +251,6 @@ function w(e, t, n) {
251
251
  return i;
252
252
  }
253
253
  //#endregion
254
- export { w as applyReorder, C as createSortable, S as createSortableScope };
254
+ export { C as applyReorder, S as createSortable, x as createSortableScope };
255
255
 
256
256
  //# sourceMappingURL=sortable.js.map