{"version":3,"file":"Group.mjs","sources":["../../../../src/components/Reorder/Group.tsx"],"sourcesContent":["\"use client\"\n\nimport { invariant } from \"motion-utils\"\nimport * as React from \"react\"\nimport {\n    forwardRef,\n    FunctionComponent,\n    JSX,\n    useEffect,\n    useRef,\n    useState,\n} from \"react\"\nimport { ReorderContext } from \"../../context/ReorderContext\"\nimport { motion } from \"../../render/components/motion/proxy\"\nimport { HTMLMotionProps } from \"../../render/html/types\"\nimport { useConstant } from \"../../utils/use-constant\"\nimport {\n    DefaultGroupElement,\n    ItemData,\n    ReorderAxis,\n    ReorderContextProps,\n    ReorderElementTag,\n} from \"./types\"\nimport { checkReorder } from \"./utils/check-reorder\"\nimport { detectAxis } from \"./utils/detect-axis\"\n\nexport interface Props<\n    V,\n    TagName extends ReorderElementTag = DefaultGroupElement\n> {\n    /**\n     * A HTML element to render this component as. Defaults to `\"ul\"`.\n     *\n     * @public\n     */\n    as?: TagName\n\n    /**\n     * The axis to reorder along. By default, this is detected from the item\n     * layout. Use `\"xy\"` to explicitly enable wrapped layout reordering.\n     *\n     * @public\n     */\n    axis?: ReorderAxis\n\n    /**\n     * A callback to fire with the new value order. For instance, if the values\n     * are provided as a state from `useState`, this could be the set state function.\n     *\n     * @public\n     */\n    onReorder: (newOrder: V[]) => void\n\n    /**\n     * The latest values state.\n     *\n     * ```jsx\n     * function Component() {\n     *   const [items, setItems] = useState([0, 1, 2])\n     *\n     *   return (\n     *     <Reorder.Group values={items} onReorder={setItems}>\n     *         {items.map((item) => <Reorder.Item key={item} value={item} />)}\n     *     </Reorder.Group>\n     *   )\n     * }\n     * ```\n     *\n     * @public\n     */\n    values: V[]\n}\n\ntype ReorderGroupProps<\n    V,\n    TagName extends ReorderElementTag = DefaultGroupElement\n> = Props<V, TagName> &\n    Omit<HTMLMotionProps<TagName>, \"values\"> &\n    React.PropsWithChildren<{}>\n\nexport function ReorderGroupComponent<\n    V,\n    TagName extends ReorderElementTag = DefaultGroupElement\n>(\n    {\n        children,\n        as = \"ul\" as TagName,\n        axis: axisOverride,\n        onReorder,\n        values,\n        ...props\n    }: ReorderGroupProps<V, TagName>,\n    externalRef?: React.ForwardedRef<any>\n): JSX.Element {\n    const Component = useConstant(\n        () => motion[as as keyof typeof motion]\n    ) as FunctionComponent<\n        React.PropsWithChildren<HTMLMotionProps<any> & { ref?: React.Ref<any> }>\n    >\n\n    const itemLayouts = useRef(new Map<V, ItemData<V>[\"layout\"]>())\n    const [detectedAxis, setDetectedAxis] = useState<ReorderAxis>(\"y\")\n    const isReordering = useRef(false)\n    const groupRef = useRef<Element>(null)\n    const axis = axisOverride || detectedAxis\n\n    invariant(\n        Boolean(values),\n        \"Reorder.Group must be provided a values prop\",\n        \"reorder-values\"\n    )\n\n    const valuesSet = new Set(values)\n    itemLayouts.current.forEach((_, value) => {\n        if (!valuesSet.has(value)) itemLayouts.current.delete(value)\n    })\n\n    const context: ReorderContextProps<V> = {\n        axis,\n        groupRef,\n        registerItem: (value, layout) => {\n            itemLayouts.current.set(value, layout)\n\n            if (!axisOverride) {\n                const nextAxis = detectAxis(\n                    values.flatMap((itemValue) => {\n                        const itemLayout = itemLayouts.current.get(itemValue)\n                        return itemLayout ? [itemLayout] : []\n                    })\n                )\n\n                if (nextAxis !== detectedAxis) setDetectedAxis(nextAxis)\n            }\n        },\n        updateOrder: (item, offset, velocity) => {\n            if (isReordering.current) return\n\n            const order = values.flatMap((value) => {\n                const layout = itemLayouts.current.get(value)\n                return layout ? [{ value, layout }] : []\n            })\n            const direction =\n                groupRef.current?.ownerDocument.defaultView?.getComputedStyle(\n                    groupRef.current\n                ).direction === \"rtl\"\n                    ? \"rtl\"\n                    : \"ltr\"\n            const newOrder = checkReorder(\n                order,\n                item,\n                offset,\n                velocity,\n                axis,\n                direction\n            )\n\n            if (order !== newOrder) {\n                isReordering.current = true\n\n                const newValues = [...values]\n                const measuredIndexes = order.map(({ value }) =>\n                    values.indexOf(value)\n                )\n                newOrder.forEach(({ value }, index) => {\n                    newValues[measuredIndexes[index]] = value\n                })\n                onReorder(newValues)\n            }\n        },\n    }\n\n    useEffect(() => {\n        isReordering.current = false\n    })\n\n    // Combine refs if external ref is provided\n    const setRef = (element: Element | null) => {\n        ;(groupRef as React.MutableRefObject<Element | null>).current = element\n        if (typeof externalRef === \"function\") {\n            externalRef(element)\n        } else if (externalRef) {\n            ;(externalRef as React.MutableRefObject<Element | null>).current =\n                element\n        }\n    }\n\n    /**\n     * Disable browser scroll anchoring on the group container.\n     * When items reorder, scroll anchoring can cause the browser to adjust\n     * the scroll position, which interferes with drag position calculations.\n     */\n    const groupStyle = {\n        overflowAnchor: \"none\" as const,\n        ...props.style,\n    }\n\n    return (\n        <Component {...props} style={groupStyle} ref={setRef} ignoreStrict>\n            <ReorderContext.Provider value={context}>\n                {children}\n            </ReorderContext.Provider>\n        </Component>\n    )\n}\n\nexport const ReorderGroup = /*@__PURE__*/ forwardRef(ReorderGroupComponent) as <\n    Values extends any[],\n    TagName extends ReorderElementTag = DefaultGroupElement\n>(\n    props: Omit<\n        ReorderGroupProps<Values[number], TagName>,\n        \"values\" | \"onReorder\"\n    > & {\n        values: Values\n        onReorder: (newOrder: Values) => void\n    } & { ref?: React.ForwardedRef<any> }\n) => ReturnType<typeof ReorderGroupComponent>\n"],"names":[],"mappings":";;;;;;;;;;AAgFM;AAcF;;;AAQA;AACA;AACA;;AAQA;;AAEI;AAA2B;AAC/B;AAEA;;;AAGI;;;;;;;;;;;;;;;;AAmBQ;AACJ;AACA;AAIQ;;AAER;AASA;AACI;AAEA;;;;AAMA;;;;;;AAOR;AACJ;;AAGA;AACM;AACF;;;;AAGM;AACE;;AAEZ;AAEA;;;;AAIG;AACH;AACI;;;AAIJ;AAOJ;AAEO;;"}