framer-motion
Version:
A simple and powerful JavaScript animation library
1 lines • 6.63 kB
Source Map (JSON)
{"version":3,"file":"Item.mjs","sources":["../../../../src/components/Reorder/Item.tsx"],"sourcesContent":["\"use client\"\n\nimport { isMotionValue, visualElementStore } from \"motion-dom\"\nimport { invariant } from \"motion-utils\"\nimport * as React from \"react\"\nimport { forwardRef, FunctionComponent, useContext, useState } from \"react\"\nimport { ReorderContext } from \"../../context/ReorderContext\"\nimport type { MotionProxy } from \"../../render/components/create-proxy\"\nimport { HTMLMotionProps } from \"../../render/html/types\"\nimport { useConstant } from \"../../utils/use-constant\"\nimport { useMotionValue } from \"../../value/use-motion-value\"\nimport { useTransform } from \"../../value/use-transform\"\n\nimport { DefaultItemElement, ReorderElementTag } from \"./types\"\nimport { autoScrollIfNeeded, resetAutoScrollState } from \"./utils/auto-scroll\"\n\nexport interface Props<\n V,\n TagName extends ReorderElementTag = DefaultItemElement\n> {\n /**\n * A HTML element to render this component as. Defaults to `\"li\"`.\n *\n * @public\n */\n as?: TagName\n\n /**\n * The value in the list that this component represents.\n *\n * @public\n */\n value: V\n\n /**\n * A subset of layout options primarily used to disable layout=\"size\"\n *\n * @public\n * @default true\n */\n layout?: true | \"position\"\n}\n\nfunction useDefaultMotionValue(value: any, defaultValue: number = 0) {\n return isMotionValue(value) ? value : useMotionValue(defaultValue)\n}\n\ntype ReorderItemProps<\n V,\n TagName extends ReorderElementTag = DefaultItemElement\n> = Props<V, TagName> &\n Omit<HTMLMotionProps<TagName>, \"value\" | \"layout\"> &\n React.PropsWithChildren<{}>\n\nexport function ReorderItemComponent<\n V,\n TagName extends ReorderElementTag = DefaultItemElement\n>(\n {\n children,\n style = {},\n value,\n as = \"li\" as TagName,\n onDrag,\n onDragEnd,\n onKeyDown,\n onBlur,\n layout = true,\n ...props\n }: ReorderItemProps<V, TagName>,\n externalRef?: React.ForwardedRef<any>\n): React.JSX.Element {\n const context = useContext(ReorderContext)\n\n process.env.NODE_ENV !== \"production\" &&\n invariant(\n Boolean(context),\n \"Reorder.Item must be a child of Reorder.Group\",\n \"reorder-item-child\"\n )\n\n /**\n * Render the group's kind of component, `motion` or `m`.\n */\n const Component = useConstant(\n () => context!.proxy[as as keyof MotionProxy]\n ) as FunctionComponent<\n React.PropsWithChildren<HTMLMotionProps<any> & { ref?: React.Ref<any> }>\n >\n\n /**\n * The group's values when this item was grabbed with the keyboard, for\n * Escape to restore. Set only while grabbed.\n */\n const [grabbedFrom, setGrabbedFrom] = useState<V[]>()\n const point = {\n x: useDefaultMotionValue(style.x),\n y: useDefaultMotionValue(style.y),\n }\n\n const zIndex = useTransform([point.x, point.y], ([latestX, latestY]) =>\n latestX || latestY ? 1 : \"unset\"\n )\n\n const {\n axis,\n registerItem,\n updateOrder,\n groupRef,\n hasReordered,\n onKeyDown: handleKeyDown,\n } = context!\n const dragAxis = axis === \"xy\" ? true : axis\n\n /**\n * A keyboard grab is a drag without a pointer, so it shares whileDrag\n * (but not the drag callbacks, which need a pointer and PanInfo).\n */\n const grab = (element: Element, from?: V[]) => {\n setGrabbedFrom(from)\n visualElementStore\n .get(element)\n ?.animationState?.setActive(\"whileDrag\", !!from)\n }\n\n return (\n <Component\n drag={dragAxis}\n tabIndex={0}\n {...props}\n dragSnapToOrigin\n style={{ ...style, x: point.x, y: point.y, zIndex }}\n layout={layout}\n onDrag={(event, gesturePoint) => {\n const { velocity, point: pointerPoint } = gesturePoint\n const offset = { x: point.x.get(), y: point.y.get() }\n\n updateOrder(value, offset, velocity)\n\n const scrollAxis =\n axis === \"xy\"\n ? Math.abs(velocity.x) > Math.abs(velocity.y)\n ? \"x\"\n : \"y\"\n : axis\n autoScrollIfNeeded(\n groupRef.current,\n pointerPoint[scrollAxis],\n scrollAxis,\n velocity[scrollAxis]\n )\n\n onDrag && onDrag(event, gesturePoint)\n }}\n onDragEnd={(event, gesturePoint) => {\n // Runs a frame after release, so after the release's click\n hasReordered.current = false\n resetAutoScrollState()\n onDragEnd && onDragEnd(event, gesturePoint)\n }}\n onKeyDown={(event: React.KeyboardEvent<HTMLElement>) => {\n onKeyDown?.(event as any)\n handleKeyDown(event, value, grabbedFrom, grab)\n }}\n /**\n * A move blurs the item, but that blur is never dispatched:\n * React DOM disables its events while it commits, and restores\n * focus to the item before re-enabling them. So any blur that\n * reaches here is focus really leaving, which drops the item.\n */\n onBlur={(event: React.FocusEvent<HTMLElement>) => {\n onBlur?.(event as any)\n grabbedFrom && grab(event.currentTarget)\n }}\n onLayoutMeasure={(measured) => {\n registerItem(value, measured)\n }}\n ref={externalRef}\n ignoreStrict\n >\n {children}\n </Component>\n )\n}\n\nexport const ReorderItem = /*@__PURE__*/ forwardRef(ReorderItemComponent) as <\n V,\n TagName extends ReorderElementTag = DefaultItemElement\n>(\n props: ReorderItemProps<V, TagName> & { ref?: React.ForwardedRef<any> }\n) => ReturnType<typeof ReorderItemComponent>\n"],"names":[],"mappings":";;;;;;;;;;;AA2CA;AACI;AACJ;AASM;AAkBF;AAEA;;AAOA;;AAEG;AACH;AAMA;;;AAGG;;AAEH;AACI;AACA;;AAGJ;AAIA;AAQA;AAEA;;;AAGG;AACH;;;;;AAKA;;;;AAcY;AAEA;AAEQ;AACI;AACA;;AAEZ;AAOA;;;AAIA;AACA;AACA;AACJ;AAEI;;;AAGJ;;;;;AAKG;AACH;AACI;AACA;AACJ;AAEI;;AAQhB;AAEO;;"}