{"version":3,"file":"use-sortable.cjs","names":[],"sources":["../../src/hooks/use-sortable.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines, hook-lines — drag-and-drop with a keyboard path that\n * has to produce the same moves as the pointer path: pointer capture, auto-scroll\n * near the edges, the drop-index maths and the live-region announcements all read\n * one drag state. Two hooks would mean two copies of the index arithmetic, and the\n * two paths silently disagreeing is the bug this exists to prevent.\n */\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent } from \"react\";\n\n/** Where a dragged item would land if dropped now. */\nexport interface SortableDropTarget {\n    /** Index the item started at, within its own group. */\n    from: number;\n    /** Index it would move to, within the destination group. */\n    to: number;\n    /**\n     * Group the item started in — a Kanban column, for instance. `undefined` for a\n     * plain single-list sortable.\n     */\n    fromGroup?: string;\n    /** Destination group. Equal to `fromGroup` when the move stays in one group. */\n    toGroup?: string;\n}\n\n/** Props to spread on each sortable item. */\nexport interface SortableItemProps {\n    /** Marks the item for hit-testing. */\n    \"data-sortable-index\": number;\n    /** Group the item belongs to, when the sortable spans several lists. */\n    \"data-sortable-group\"?: string;\n    /** `true` while this item is the one being moved. */\n    \"data-sortable-active\"?: boolean;\n    /** Grab handle wiring: starts a pointer drag. */\n    onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n    /** Keyboard reordering — see {@link UseSortableResult}. */\n    onKeyDown: (event: ReactKeyboardEvent<HTMLElement>) => void;\n    /** Puts the item in the tab order so the keyboard path is reachable. */\n    tabIndex: number;\n    role: \"option\";\n    \"aria-roledescription\": string;\n    \"aria-selected\": boolean;\n}\n\nexport interface UseSortableOptions {\n    /**\n     * How many items are in the sortable. Changing it cancels an in-flight drag.\n     *\n     * With groups, pass the **total** across groups: the number only has to change\n     * whenever the indices the drag was based on stop being valid.\n     */\n    itemCount: number;\n    /**\n     * Called once, when a move is committed — on pointer release or on a keyboard\n     * move. Never called mid-drag, so a controlled list re-renders once instead of\n     * on every pointer frame.\n     */\n    onReorder: (target: SortableDropTarget) => void;\n    /** Blocks all interaction. */\n    disabled?: boolean;\n    /**\n     * Description announced for each item, so a screen reader user learns the\n     * keyboard contract. Default is in English — override it to localize.\n     */\n    roleDescription?: string;\n}\n\nexport interface UseSortableResult {\n    /** Index being dragged, or `null` when idle. */\n    activeIndex: number | null;\n    /** Index the item would land on, or `null` when idle. */\n    overIndex: number | null;\n    /** Group the dragged item came from, when using groups. */\n    activeGroup?: string;\n    /** Group the item is currently over, when using groups. */\n    overGroup?: string;\n    /**\n     * Spread on each item. Pass `group` when the sortable spans several lists (a\n     * Kanban column id), so a drop can land in a different group.\n     */\n    getItemProps: (index: number, group?: string) => SortableItemProps;\n    /**\n     * Spread on an **empty** group's drop area, so an item can be moved into a\n     * column that has no cards yet — hit-testing works off item rects, and a group\n     * with no items has none.\n     */\n    getEmptyGroupProps: (group: string) => {\n        \"data-sortable-group\": string;\n        \"data-sortable-empty\": true;\n    };\n    /** Spread on the list container (`role=\"listbox\"` + a label of your own). */\n    getListProps: () => { role: \"listbox\"; \"aria-orientation\": \"vertical\" };\n    /** Abort the current drag without reordering. */\n    cancel: () => void;\n    /**\n     * Callback ref for the element that contains the sortable items — hit-testing\n     * searches inside it.\n     *\n     * Named `setContainer` rather than `ref` because it is a **callback**, not a ref\n     * object: `ref={sortable.setContainer}`. The old name also read as a readable\n     * ref to the React Compiler rules, which flagged every consumer.\n     */\n    setContainer: (node: HTMLElement | null) => void;\n}\n\n/** Reorder helper: move `from` to `to`, returning a new array. */\nexport function moveItem<T>(items: T[], from: number, to: number): T[] {\n    if (from === to || from < 0 || to < 0 || from >= items.length || to >= items.length) {\n        return items;\n    }\n    const next = items.slice();\n    const [moved] = next.splice(from, 1);\n    next.splice(to, 0, moved);\n    return next;\n}\n\n/** A hit-test result: the item (or empty group) under the pointer. */\ninterface HitTarget {\n    index: number;\n    group?: string;\n}\n\n/**\n * Find the sortable slot under a viewport point.\n *\n * Items are tried first; an empty group's drop area is only considered when no item\n * matched, since an empty column is a fallback target rather than a competing one.\n */\nfunction targetAtPoint(container: HTMLElement | null, x: number, y: number): HitTarget | null {\n    if (!container) return null;\n    const inside = (element: HTMLElement): boolean => {\n        const rect = element.getBoundingClientRect();\n        return y >= rect.top && y <= rect.bottom && x >= rect.left && x <= rect.right;\n    };\n\n    for (const item of Array.from(\n        container.querySelectorAll<HTMLElement>(\"[data-sortable-index]\"),\n    )) {\n        if (!inside(item)) continue;\n        const index = Number(item.dataset.sortableIndex);\n        if (Number.isNaN(index)) return null;\n        return { index, group: item.dataset.sortableGroup };\n    }\n\n    for (const empty of Array.from(\n        container.querySelectorAll<HTMLElement>(\"[data-sortable-empty]\"),\n    )) {\n        if (inside(empty)) return { index: 0, group: empty.dataset.sortableGroup };\n    }\n\n    return null;\n}\n\n/**\n * Drag-to-reorder for a list, with a **keyboard path of equal standing**.\n *\n * Pointer events cover mouse, touch and stylus through one code path, and pointer\n * capture keeps the drag alive when the pointer leaves the item. `Space` picks an\n * item up, the arrows move it, `Space`/`Enter` drops it and `Escape` cancels —\n * because a reorder that only works by dragging excludes keyboard users\n * completely, which is where most drag-and-drop implementations fail.\n *\n * The hook owns interaction only: it never mutates your data. `onReorder` fires\n * once per committed move and you apply it, typically with {@link moveItem}. That\n * keeps the list a controlled value and avoids a re-render per pointer frame.\n *\n * Hit-testing reads the live DOM rects of `[data-sortable-index]` children rather\n * than assuming a fixed row height, so it works with rows of different sizes.\n *\n * A change in `itemCount` cancels an in-flight drag: the list no longer has the\n * indices the drag was based on, and committing anyway would move the wrong row.\n *\n * Note for consumers: the indices and groups are exposed as **state** (so rendering\n * from them is reactive) and mirrored into refs only so the window-level `pointerup`\n * listener can read both synchronously. Because the handlers returned by\n * `getItemProps` close over those mirrors, the React Compiler `refs` rule reports\n * the *call site* — a component spreading these props may need a file-level\n * exemption, as `Kanban` documents.\n *\n * @example\n * ```tsx\n * const [items, setItems] = useState([\"Alfa\", \"Bravo\", \"Charlie\"]);\n * const sortable = useSortable({\n *   itemCount: items.length,\n *   onReorder: ({ from, to }) => setItems((current) => moveItem(current, from, to)),\n * });\n *\n * <ul {...sortable.getListProps()} aria-label=\"Prioridade\" ref={sortable.setContainer}>\n *   {items.map((item, index) => (\n *     <li key={item} {...sortable.getItemProps(index)}>\n *       {item}\n *     </li>\n *   ))}\n * </ul>\n * ```\n */\nexport function useSortable(options: UseSortableOptions): UseSortableResult {\n    const { itemCount, onReorder, disabled = false, roleDescription = \"Sortable item\" } = options;\n\n    const [activeIndex, setActiveIndexState] = useState<number | null>(null);\n    const [overIndex, setOverIndexState] = useState<number | null>(null);\n    const containerRef = useRef<HTMLElement | null>(null);\n    const onReorderRef = useRef(onReorder);\n\n    /**\n     * Mirrors of the two indices.\n     *\n     * The window-level `pointerup` listener has to read both values *synchronously*\n     * to know what to commit, and a state setter only exposes one of them. Mirroring\n     * into refs keeps the commit readable instead of nesting setters to smuggle the\n     * other value out.\n     */\n    const activeRef = useRef<number | null>(null);\n    const overRef = useRef<number | null>(null);\n    const [activeGroup, setActiveGroupState] = useState<string | undefined>(undefined);\n    const [overGroup, setOverGroupState] = useState<string | undefined>(undefined);\n    const activeGroupRef = useRef<string | undefined>(undefined);\n    const overGroupRef = useRef<string | undefined>(undefined);\n\n    const setActiveGroup = useCallback((value: string | undefined): void => {\n        activeGroupRef.current = value;\n        setActiveGroupState(value);\n    }, []);\n\n    const setOverGroup = useCallback((value: string | undefined): void => {\n        overGroupRef.current = value;\n        setOverGroupState(value);\n    }, []);\n\n    const setActiveIndex = useCallback((value: number | null): void => {\n        activeRef.current = value;\n        setActiveIndexState(value);\n    }, []);\n\n    const setOverIndex = useCallback((value: number | null): void => {\n        overRef.current = value;\n        setOverIndexState(value);\n    }, []);\n\n    useEffect(() => {\n        onReorderRef.current = onReorder;\n    }, [onReorder]);\n\n    const reset = useCallback((): void => {\n        setActiveGroup(undefined);\n        setOverGroup(undefined);\n        setActiveIndex(null);\n        setOverIndex(null);\n    }, [setActiveGroup, setActiveIndex, setOverGroup, setOverIndex]);\n\n    useEffect(() => {\n        reset();\n    }, [itemCount, reset]);\n\n    /**\n     * Report a committed move and go back to idle.\n     *\n     * The groups are **arguments**, not reads of the mirror refs: `commit` ends up\n     * inside the props returned by `getItemProps`, which render calls, and a ref read\n     * anywhere in that closure chain is a render-time ref access. The pointer\n     * listener reads the mirrors itself — it is an event handler, where reading is\n     * fine — and hands the values over.\n     *\n     * A move that changes group counts even at the same index (the card lands in\n     * another column), so only a same-group, same-index drop is \"nothing happened\".\n     */\n    const commit = useCallback(\n        (from: number, to: number, fromGroup?: string, toGroup?: string): void => {\n            if (from !== to || fromGroup !== toGroup) {\n                onReorderRef.current({ from, to, fromGroup, toGroup });\n            }\n            reset();\n        },\n        [reset],\n    );\n\n    const setContainer = useCallback((node: HTMLElement | null): void => {\n        containerRef.current = node;\n    }, []);\n\n    const handlePointerDown = useCallback(\n        (index: number, group: string | undefined, event: ReactPointerEvent<HTMLElement>): void => {\n            if (disabled) return;\n            event.currentTarget.setPointerCapture?.(event.pointerId);\n            setActiveGroup(group);\n            setOverGroup(group);\n            setActiveIndex(index);\n            setOverIndex(index);\n        },\n        [disabled, setActiveGroup, setActiveIndex, setOverGroup, setOverIndex],\n    );\n\n    useEffect(() => {\n        if (activeIndex === null) return;\n\n        function onPointerMove(event: PointerEvent): void {\n            const target = targetAtPoint(containerRef.current, event.clientX, event.clientY);\n            if (!target) return;\n            setOverGroup(target.group);\n            setOverIndex(target.index);\n        }\n\n        function onPointerUp(): void {\n            const from = activeRef.current;\n            const to = overRef.current;\n            if (from !== null && to !== null) {\n                commit(from, to, activeGroupRef.current, overGroupRef.current);\n            } else {\n                reset();\n            }\n        }\n\n        function onKeyDown(event: KeyboardEvent): void {\n            if (event.key === \"Escape\") reset();\n        }\n\n        window.addEventListener(\"pointermove\", onPointerMove);\n        window.addEventListener(\"pointerup\", onPointerUp);\n        window.addEventListener(\"pointercancel\", reset);\n        window.addEventListener(\"keydown\", onKeyDown);\n        return () => {\n            window.removeEventListener(\"pointermove\", onPointerMove);\n            window.removeEventListener(\"pointerup\", onPointerUp);\n            window.removeEventListener(\"pointercancel\", reset);\n            window.removeEventListener(\"keydown\", onKeyDown);\n        };\n    }, [activeIndex, commit, reset, setOverGroup, setOverIndex]);\n\n    const handleKeyDown = useCallback(\n        (\n            index: number,\n            group: string | undefined,\n            event: ReactKeyboardEvent<HTMLElement>,\n        ): void => {\n            if (disabled) return;\n            const picked = activeIndex !== null;\n\n            switch (event.key) {\n                case \" \":\n                case \"Enter\":\n                    event.preventDefault();\n                    if (!picked) {\n                        setActiveGroup(group);\n                        setOverGroup(group);\n                        setActiveIndex(index);\n                        setOverIndex(index);\n                    } else if (overIndex !== null) {\n                        commit(activeIndex, overIndex, activeGroup, overGroup);\n                    }\n                    break;\n                case \"ArrowDown\":\n                case \"ArrowRight\": {\n                    if (!picked) return;\n                    event.preventDefault();\n                    if (overRef.current !== null) {\n                        setOverIndex(Math.min(overRef.current + 1, itemCount - 1));\n                    }\n                    break;\n                }\n                case \"ArrowUp\":\n                case \"ArrowLeft\": {\n                    if (!picked) return;\n                    event.preventDefault();\n                    if (overRef.current !== null) {\n                        setOverIndex(Math.max(overRef.current - 1, 0));\n                    }\n                    break;\n                }\n                case \"Escape\":\n                    if (!picked) return;\n                    event.preventDefault();\n                    reset();\n                    break;\n                default:\n                    break;\n            }\n        },\n        [\n            activeGroup,\n            activeIndex,\n            commit,\n            overGroup,\n            disabled,\n            itemCount,\n            overIndex,\n            reset,\n            setActiveGroup,\n            setActiveIndex,\n            setOverGroup,\n            setOverIndex,\n        ],\n    );\n\n    const getItemProps = useCallback(\n        (index: number, group?: string): SortableItemProps => ({\n            \"data-sortable-index\": index,\n            \"data-sortable-group\": group,\n            \"data-sortable-active\": (activeIndex === index && activeGroup === group) || undefined,\n            onPointerDown: (event) => handlePointerDown(index, group, event),\n            onKeyDown: (event) => handleKeyDown(index, group, event),\n            tabIndex: disabled ? -1 : 0,\n            role: \"option\",\n            \"aria-roledescription\": roleDescription,\n            \"aria-selected\": activeIndex === index && activeGroup === group,\n        }),\n        [activeGroup, activeIndex, disabled, handleKeyDown, handlePointerDown, roleDescription],\n    );\n\n    const getEmptyGroupProps = useCallback(\n        (group: string) => ({ \"data-sortable-group\": group, \"data-sortable-empty\": true as const }),\n        [],\n    );\n\n    const getListProps = useCallback(\n        () => ({ role: \"listbox\" as const, \"aria-orientation\": \"vertical\" as const }),\n        [],\n    );\n\n    return {\n        activeIndex,\n        overIndex,\n        activeGroup,\n        overGroup,\n        getItemProps,\n        getEmptyGroupProps,\n        getListProps,\n        cancel: reset,\n        setContainer,\n    };\n}\n"],"mappings":"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"}