solidjs-motion 0.1.2 → 0.1.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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Context","createContext","createMemo","JSX","useContext","MotionConfigContextValue","MotionConfigProps","defaultMotionConfig","reducedMotion","transition","undefined","nonce","MotionConfigContext","useMotionConfig","MotionConfig","props","Element","value","_$createComponent","Provider","children","mergeRefs","isMotionValue","MotionValue","Accessor","Component","JSX","mergeProps","onMount","untrack","createStore","usePresenceContext","asVariantLabels","createMotion","resolveTarget","GestureStateName","snapshotValue","TRANSFORM_KEYS","targetToStyle","ElementProps","MotionElement","MotionMergedProps","MotionOptions","MotionStyle","Target","Transition","UseMotionResult","VariantContextValue","Variants","isControllingVariants","useVariantContext","VariantContext","useMotion","opts","getOpts","actualParentCtx","isControlling","parentVariantCtx","variants","undefined","initial","animate","hover","press","focus","inView","exit","custom","transition","presenceCtx","initialOpts","initialTarget","computeInitialTarget","activeStore","Record","whileInView","whileHover","whilePress","whileFocus","whileDrag","active","styleMotionValues","Map","styleStaticTransforms","styleCaptured","motionRef","el","initialAppliedBySSR","parentContext","renderedOnce","captureStyleEntries","style","key","value","set","has","snap","stripStyleEntriesOwnedByRegistry","CSSProperties","out","composeFirstPaintStyle","userStyle","merged","hasAny","Object","assign","mv","get","v","getProps","userProps","P","wroteFirstPaintStyle","cleaned","composed","ref","myVariantCtx","Provider","children","Element","props","_$createComponent","presenceInitial","animateValue","inheritedInitial","inheritedAnimate","effective","mergeRefs","Component","JSX","mergeProps","onMount","splitProps","Dynamic","ElementProps","MotionElement","MotionOptions","MotionStyle","useMotion","MotionOptKey","MOTION_OPT_KEYS","const","_MissingMotionOptKeys","Exclude","_ensureExhaustive","_missing","Motion","IntrinsicElements","Omit","Tag","style","create","Record","P","AnyComponent","tagComponentCache","Map","motionComponents","WeakSet","makeMotionTag","tag","cached","get","props","motionOpts","rest","m","_$createComponent","Provider","children","_$mergeProps","component","stored","set","add","motionCreate","process","env","NODE_ENV","has","console","warn","Wrapped","refFired","detector","_el","userRef","ref","el","mergedUserRef","restWithDetector","queueMicrotask","motion","Proxy","_target","key","undefined","resolveElements","createListTransition","createSwitchTransition","Component","createEffect","createMemo","createSignal","JSX","Match","onCleanup","Switch","PresenceContext","MotionElement","PresenceContextValue","switchMode","mode","PresenceProps","collectSubtreeExits","root","runExits","Map","Promise","Array","out","el","fn","contains","push","initial","exitMethod","children","Element","Presence","props","runEnters","presenceInitial","setPresenceInitial","queueMicrotask","ctx","register","runExit","set","unregister","delete","beforeUnmount","exiting","length","resolve","all","map","pair","then","exitedEl","registerEnter","runEnter","beforeMount","get","_$createComponent","Provider","value","PresenceCore","source","appear","PresenceCoreProps","p","resolved","path","prev","v","isArray","process","env","NODE_ENV","console","warn","when","keyed","_v","onExit","done","motionEl","HTMLElement","SVGElement","style","CSSStyleDeclaration","pointerEvents","onEnter","toArray","onChange","added","removed","finishRemoved","UseAnimatePresenceOptions","UseAnimatePresenceResult","exit","useAnimatePresence","options","clear","snapshot","values"],"sources":["../src/motion-config.tsx","../src/presence-context.ts","../src/reduced-motion.ts","../src/style.ts","../src/variants.ts","../src/primitives/createDragControls.ts","../src/primitives/motion-value.ts","../src/primitives/createPan.ts","../src/primitives/createDrag.ts","../src/primitives/createInView.ts","../src/primitives/createGestures.ts","../src/default-values.ts","../src/primitives/gesture-state.ts","../src/primitives/value-registry.ts","../src/primitives/createMotion.ts","../src/use-motion.tsx","../src/motion-proxy.tsx","../src/presence.tsx","../src/primitives/createScroll.ts"],"sourcesContent":["import { type Context, createContext, createMemo, type JSX, useContext } from \"solid-js\"\nimport type { MotionConfigContextValue, MotionConfigProps } from \"./types\"\n\n/**\n * Default context — no reduced motion override, no inherited transition, no\n * CSP nonce. Descendants without a `<MotionConfig>` ancestor get this.\n */\nconst defaultMotionConfig: MotionConfigContextValue = {\n reducedMotion: () => \"never\",\n transition: () => undefined,\n nonce: () => undefined,\n}\n\nexport const MotionConfigContext: Context<MotionConfigContextValue> =\n createContext<MotionConfigContextValue>(defaultMotionConfig)\n\nexport function useMotionConfig(): MotionConfigContextValue {\n return useContext(MotionConfigContext)\n}\n\n/**\n * Provider that flows reduced-motion mode, default transition, and CSP nonce\n * to every descendant motion element.\n *\n * @example\n * <MotionConfig reducedMotion=\"user\" transition={{ duration: 0.4 }}>\n * <App />\n * </MotionConfig>\n */\nexport function MotionConfig(props: MotionConfigProps): JSX.Element {\n const value: MotionConfigContextValue = {\n reducedMotion: createMemo(() => props.reducedMotion ?? \"never\"),\n transition: createMemo(() => props.transition),\n nonce: createMemo(() => props.nonce),\n }\n return <MotionConfigContext.Provider value={value}>{props.children}</MotionConfigContext.Provider>\n}\n","import { type Context, createContext, useContext } from \"solid-js\"\nimport type { PresenceContextValue } from \"./types\"\n\n/**\n * No-op default. `useMotion` consumers wire their `exit` targets through this\n * context, but without an enclosing `<Presence>` or `useAnimatePresence()`\n * the registration is silently dropped. The real implementations live in\n * `presence.tsx` (Phase 3).\n *\n * The shape is the inverted one (see types.ts JSDoc): children register a\n * `runExit` callable; Presence dispatches via `beforeUnmount`. The no-op\n * accepts the registration and resolves `beforeUnmount` immediately so\n * motion children outside a `<Presence>` unmount instantly without trying\n * to animate.\n */\nconst noopPresenceContext: PresenceContextValue = {\n register: () => {},\n unregister: () => {},\n beforeUnmount: () => Promise.resolve(),\n // `registerEnter` / `beforeMount` / `initial` intentionally LEFT UNDEFINED.\n // createMotion detects \"in a real Presence\" by `presence.initial !== undefined`\n // (the no-op leaves it undefined). Without that signal it animates first-\n // mount immediately — outside a Presence the element is always already in\n // the DOM by the time createMotion runs, so no defer is needed.\n}\n\nexport const PresenceContext: Context<PresenceContextValue> =\n createContext<PresenceContextValue>(noopPresenceContext)\n\nexport function usePresenceContext(): PresenceContextValue {\n return useContext(PresenceContext)\n}\n","import { type Accessor, from } from \"solid-js\"\n\n/**\n * A reactive `Accessor<boolean>` tracking the user's\n * `prefers-reduced-motion: reduce` media query.\n *\n * Returns `false` server-side (no `window.matchMedia`). On the client, it seeds\n * with the current match state and updates as the system preference toggles.\n * The matchMedia listener is removed automatically on owner disposal via\n * `from`'s teardown callback.\n *\n * @example\n * const reduced = createReducedMotion()\n * createEffect(() => {\n * if (reduced()) console.log(\"user prefers reduced motion\")\n * })\n */\nexport function createReducedMotion(): Accessor<boolean> {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return () => false\n }\n const mql = window.matchMedia(\"(prefers-reduced-motion: reduce)\")\n // `from` produces an Accessor<T | undefined>; we seed synchronously inside the\n // producer so the cast to Accessor<boolean> is sound.\n return from<boolean>((set) => {\n set(mql.matches)\n const handler = (e: MediaQueryListEvent) => set(e.matches)\n mql.addEventListener(\"change\", handler)\n return () => mql.removeEventListener(\"change\", handler)\n }) as Accessor<boolean>\n}\n\n/**\n * Compute the effective reduced-motion state by combining a {@link MotionConfig}\n * `reducedMotion` setting with the system preference.\n *\n * - `\"always\"` — forced reduced, regardless of system pref\n * - `\"never\"` — never reduced, regardless of system pref\n * - `\"user\"` — respect system pref\n *\n * @example\n * const reduced = shouldReduceMotion(\"user\", createReducedMotion()())\n */\nexport function shouldReduceMotion(\n configValue: \"always\" | \"never\" | \"user\",\n systemReduced: boolean,\n): boolean {\n if (configValue === \"always\") return true\n if (configValue === \"never\") return false\n return systemReduced\n}\n","import { isMotionValue, type MotionValue } from \"motion\"\nimport type { JSX } from \"solid-js\"\nimport type { Target } from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Tables (Q5 locked decisions)\n// ---------------------------------------------------------------------------\n\n/**\n * Set of CSS shortcut keys motion treats as transform components. Re-used by\n * `createMotion`'s Stage 3 animate bridge to decide whether an animate-target\n * key should be routed through the value registry (composed via the writer's\n * `el.style.transform =`) or sent down the existing WAA path.\n */\nexport const TRANSFORM_KEYS = /* @__PURE__ */ new Set([\n \"x\",\n \"y\",\n \"z\",\n \"scale\",\n \"scaleX\",\n \"scaleY\",\n \"scaleZ\",\n \"rotate\",\n \"rotateX\",\n \"rotateY\",\n \"rotateZ\",\n \"skew\",\n \"skewX\",\n \"skewY\",\n \"transformPerspective\",\n])\n\n/** Order matters — motion composes transforms in this sequence (Q5 sub-1). */\nconst TRANSFORM_ORDER = [\n \"x\",\n \"y\",\n \"z\",\n \"scale\",\n \"scaleX\",\n \"scaleY\",\n \"scaleZ\",\n \"rotate\",\n \"rotateX\",\n \"rotateY\",\n \"rotateZ\",\n \"skew\",\n \"skewX\",\n \"skewY\",\n \"transformPerspective\",\n] as const\n\nconst PX_PROPERTIES = /* @__PURE__ */ new Set([\n \"width\",\n \"minWidth\",\n \"maxWidth\",\n \"height\",\n \"minHeight\",\n \"maxHeight\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n \"padding\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"paddingInline\",\n \"paddingBlock\",\n \"paddingInlineStart\",\n \"paddingInlineEnd\",\n \"paddingBlockStart\",\n \"paddingBlockEnd\",\n \"margin\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"marginInline\",\n \"marginBlock\",\n \"marginInlineStart\",\n \"marginInlineEnd\",\n \"marginBlockStart\",\n \"marginBlockEnd\",\n \"borderWidth\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderRadius\",\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomLeftRadius\",\n \"borderBottomRightRadius\",\n \"gap\",\n \"rowGap\",\n \"columnGap\",\n \"fontSize\",\n \"outlineWidth\",\n \"outlineOffset\",\n])\n\n// ---------------------------------------------------------------------------\n// Snapshot — unwrap MotionValue / Accessor / keyframe-array to a leaf value.\n// Returns `undefined` when the leaf is null or undefined; callers omit those.\n// ---------------------------------------------------------------------------\n\ntype Leaf = string | number\n\n/**\n * Reduce a target-value (which may be raw, a MotionValue, an Accessor, or a\n * keyframe array) to a concrete leaf value the writer can apply to the DOM\n * or use to initialize a transient MotionValue. The cascade follows motion's\n * own semantics:\n *\n * - `null` / `undefined` → `undefined` (caller drops the key)\n * - keyframe array → first frame (consistent with motion-vanilla's\n * initial-style snapshot)\n * - `MotionValue` → its current `.get()`\n * - `Accessor` (a bare zero-arg function) → its invocation result\n * - primitive (string / number) → returned as-is\n *\n * Exported for the MV-in-style Stage 4 work: createMotion uses it to\n * snapshot initial-target entries when registering them into the value\n * registry as transient MVs.\n */\nexport function snapshotValue(value: unknown): Leaf | undefined {\n if (value === null || value === undefined) return undefined\n if (Array.isArray(value)) return snapshotValue(value[0])\n if (isMotionValue(value)) return snapshotValue((value as MotionValue<Leaf>).get())\n if (typeof value === \"function\") return snapshotValue((value as () => unknown)())\n if (typeof value === \"string\" || typeof value === \"number\") return value\n // Anything else (objects, booleans) isn't a renderable CSS value — skip it.\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Transform composition — produce a single `transform: ...` string from the\n// shorthand keys present in the target.\n// ---------------------------------------------------------------------------\n\n/**\n * Per-key transform formatter functions. Pre-built once at module load and\n * shared across all elements. Used by `createMotion`'s specialized writer\n * to avoid evaluating the transform-key switch on every single-key write —\n * at Sierpinski-scale fan-out (thousands of writes per frame) the switch's\n * 15 case-comparisons add up to non-trivial CPU.\n *\n * Pre-pick the formatter with `pickTransformFormatter(key)` ONCE at writer-\n * compile time, then the per-call cost in the hot path is just `formatter(v)`.\n */\ntype TransformFormatter = (value: Leaf) => string\n\nconst TRANSFORM_FORMATTERS: Readonly<Record<string, TransformFormatter>> = {\n // Translate: number → \"px\", string passes through verbatim.\n x: (v) => `translateX(${typeof v === \"string\" ? v : `${v}px`})`,\n y: (v) => `translateY(${typeof v === \"string\" ? v : `${v}px`})`,\n z: (v) => `translateZ(${typeof v === \"string\" ? v : `${v}px`})`,\n // Scale: dimensionless. Skip the type check entirely.\n scale: (v) => `scale(${v})`,\n scaleX: (v) => `scaleX(${v})`,\n scaleY: (v) => `scaleY(${v})`,\n scaleZ: (v) => `scaleZ(${v})`,\n // Rotate / skew: number → \"deg\", string passes through.\n rotate: (v) => `rotate(${typeof v === \"string\" ? v : `${v}deg`})`,\n rotateX: (v) => `rotateX(${typeof v === \"string\" ? v : `${v}deg`})`,\n rotateY: (v) => `rotateY(${typeof v === \"string\" ? v : `${v}deg`})`,\n rotateZ: (v) => `rotateZ(${typeof v === \"string\" ? v : `${v}deg`})`,\n skew: (v) => `skew(${typeof v === \"string\" ? v : `${v}deg`})`,\n skewX: (v) => `skewX(${typeof v === \"string\" ? v : `${v}deg`})`,\n skewY: (v) => `skewY(${typeof v === \"string\" ? v : `${v}deg`})`,\n transformPerspective: (v) => `perspective(${typeof v === \"string\" ? v : `${v}px`})`,\n}\n\n/**\n * Look up the formatter for a transform-shortcut key. Returns `undefined`\n * for non-transform keys; callers should check `TRANSFORM_KEYS.has(key)`\n * before assuming a formatter exists.\n */\nexport function pickTransformFormatter(key: string): TransformFormatter | undefined {\n return TRANSFORM_FORMATTERS[key]\n}\n\n/**\n * Format a motion transform-shortcut key + value as the corresponding CSS\n * transform function string (e.g. `transformFunctionFor(\"scale\", 1.05)`\n * → `\"scale(1.05)\"`). One-shot variant — for hot paths, use\n * `pickTransformFormatter(key)` once at compile time and reuse.\n */\nexport function transformFunctionFor(key: string, value: Leaf): string {\n return TRANSFORM_FORMATTERS[key]?.(value) ?? \"\"\n}\n\n// ---------------------------------------------------------------------------\n// Property formatting — apply unit table for non-transform CSS properties.\n// ---------------------------------------------------------------------------\n\n/**\n * Format a non-transform CSS property's value (e.g. `formatProperty(\"width\", 100)`\n * → `\"100px\"`, `formatProperty(\"opacity\", 0.5)` → `0.5`). Applies motion's\n * default-unit table (PX for dimensional CSS, dimensionless otherwise);\n * leaves CSS variables alone. Exported for `createMotion`'s writer fast path.\n */\nexport function formatProperty(key: string, value: Leaf): string | number {\n if (typeof value === \"string\") return value\n // CSS variables: stringify the number, never auto-unit (Q5 sub-4).\n if (key.startsWith(\"--\")) return String(value)\n if (PX_PROPERTIES.has(key)) return `${value}px`\n // Dimensionless or unknown — emit the bare number.\n return value\n}\n\n// ---------------------------------------------------------------------------\n// targetToStyle — the SSR/hydration linchpin. Pure, deterministic, no DOM\n// reads, no time-dependent values, no input mutation. Same inputs → same\n// outputs on server and client.\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a {@link Target} to a Solid {@link JSX.CSSProperties} object.\n *\n * - Composes transform shorthand (`x`, `y`, `scale`, `rotate`, etc.) into a\n * single `transform: \"...\"` string in motion's canonical order.\n * - Applies the default-unit table (px for dimensional CSS, deg for rotate/\n * skew, dimensionless for scale/opacity/etc.).\n * - For keyframe arrays, uses the first frame; a leading `null`/`undefined`\n * keyframe omits the property entirely.\n * - MotionValues and Solid Accessors are snapshotted at call time. Callers\n * wrap in `untrack` if they don't want the read to subscribe.\n * - Skips the `transition` key (animation config, not style).\n * - CSS variables (`--foo`) emit raw values, no unit guess.\n *\n * @example\n * targetToStyle({ x: 100, scale: 0.9, opacity: 0.5 })\n * // { transform: \"translateX(100px) scale(0.9)\", opacity: 0.5 }\n */\nexport function targetToStyle(target: Target): JSX.CSSProperties {\n const out: Record<string, string | number> = {}\n const transforms: Record<string, Leaf> = {}\n\n for (const key in target) {\n if (key === \"transition\") continue\n const raw = target[key as keyof Target]\n const snapshot = snapshotValue(raw)\n if (snapshot === undefined) continue\n\n if (TRANSFORM_KEYS.has(key)) {\n transforms[key] = snapshot\n } else {\n out[key] = formatProperty(key, snapshot)\n }\n }\n\n // Compose transform string in motion's canonical order.\n const parts: string[] = []\n for (const key of TRANSFORM_ORDER) {\n if (key in transforms) {\n parts.push(transformFunctionFor(key, transforms[key] as Leaf))\n }\n }\n if (parts.length > 0) {\n out.transform = parts.join(\" \")\n }\n\n return out as JSX.CSSProperties\n}\n","import { type Context, createContext, useContext } from \"solid-js\"\nimport type {\n AnimateValue,\n MotionOptions,\n Target,\n VariantContextValue,\n VariantLabels,\n Variants,\n} from \"./types\"\n\n/**\n * Empty default — descendants without an enclosing motion wrapper get a\n * cleanly-typed \"no propagation\" context.\n */\nconst emptyVariantContext: VariantContextValue = {}\n\n/**\n * Solid context propagating variant state from a motion ancestor to its\n * descendants. Only the wrapper components (`<motion.div>`, `motion(...)`)\n * provide a value. Bare `useMotion` consumers can opt in via the `Provider`\n * returned alongside the getter.\n */\nexport const VariantContext: Context<VariantContextValue> =\n createContext<VariantContextValue>(emptyVariantContext)\n\nexport function useVariantContext(): VariantContextValue {\n return useContext(VariantContext)\n}\n\n/**\n * Resolve a variant label (or array of labels) against a variants map and the\n * current `custom` value. Returns a {@link Target} object, or `null` if nothing\n * resolves.\n *\n * Resolution rules locked in Phase 1 Q4:\n *\n * - Child's own `variants` always wins for a given name (sub-1A).\n * - No cascade: if a child has no `variants` of its own, parent's are NOT\n * consulted (sub-1B / Pattern X). Callers pass `variants = undefined` in\n * that case and this returns `null`.\n * - String + array forms both supported; array variants merge in order\n * (later wins on conflicting keys).\n * - Function variants are invoked with `custom`; the value can be any type.\n *\n * @example\n * const variants = { visible: { opacity: 1 }, hidden: { opacity: 0 } }\n * resolveVariant(\"visible\", variants, undefined)\n * // { opacity: 1 }\n *\n * resolveVariant([\"visible\", \"highlighted\"], variants, undefined)\n * // merged in order, last variant's keys override\n *\n * resolveVariant(\"visible\", { visible: (i: number) => ({ x: i * 10 }) }, 3)\n * // { x: 30 }\n */\nexport function resolveVariant(\n names: VariantLabels | undefined,\n variants: Variants | undefined,\n custom: unknown,\n): Target | null {\n if (!names || !variants) return null\n\n const list = Array.isArray(names) ? names : [names]\n let merged: Target | null = null\n\n for (const name of list) {\n const variant = variants[name]\n if (!variant) continue\n const resolved: Target = typeof variant === \"function\" ? variant(custom) : variant\n // Object.assign sidesteps TS's \"spread types may only be created from object\n // types\" error caused by Target's index signature including `undefined`.\n merged = merged ? Object.assign({}, merged, resolved) : Object.assign({}, resolved)\n }\n\n return merged\n}\n\n/**\n * Determine the effective variant name for a given motion state. If the caller\n * provided an explicit value (string, array, or Target object), that wins.\n * Otherwise the parent context's value (per gesture/state) is used as a fall-\n * back.\n *\n * Returns the explicit value as-is when it's a Target object (used by callers\n * to detect \"explicit target — skip variant lookup entirely\").\n */\nexport function effectiveLabels(\n own: VariantLabels | Target | undefined,\n parent: VariantLabels | undefined,\n): VariantLabels | Target | undefined {\n if (own !== undefined) return own\n return parent\n}\n\n/**\n * Determine whether an `AnimateValue` is a variant *label* (string or array\n * of strings) — as opposed to a `Target` object or `false` / `undefined`.\n *\n * Mirrors motion-dom's `isVariantLabel`. Used by `isControllingVariants`\n * to decide whether a prop opts the node into the \"controlling\" role.\n */\nfunction isVariantLabelValue(v: AnimateValue | false | undefined): boolean {\n if (typeof v === \"string\") return true\n if (Array.isArray(v)) return true\n return false\n}\n\n/**\n * A motion node is \"controlling variants\" when any of its variant slots\n * (`initial`, `animate`, `hover`, `press`, `focus`, `inView`, `exit`) carries\n * a variant *label* (string or array of strings).\n *\n * Mirrors motion-dom's same-named check. A controlling node opts OUT of\n * inheriting its parent's variant cascade — it provides its own. Descendants\n * with no controlling props of their own DO inherit from the nearest\n * controlling ancestor.\n *\n * Behavior is binary (any single controlling-slot label flips the node into\n * controlling mode); not per-slot.\n *\n * Object-shaped values (`animate: \\{ x: 100 \\}`) do NOT make a node\n * controlling — they're treated as targets, not as variant references.\n */\nexport function isControllingVariants(opts: MotionOptions): boolean {\n return (\n isVariantLabelValue(opts.initial) ||\n isVariantLabelValue(opts.animate) ||\n isVariantLabelValue(opts.hover) ||\n isVariantLabelValue(opts.press) ||\n isVariantLabelValue(opts.focus) ||\n isVariantLabelValue(opts.inView) ||\n isVariantLabelValue(opts.exit)\n )\n}\n","import type { DragControls, DragControlsStartOptions } from \"../types\"\n\n// ---------------------------------------------------------------------------\n// createDragControls — imperative drag-controls factory (Q9).\n//\n// Architecture:\n// - A controls instance has one public method: `start(event, options?)`.\n// - createDrag (when its `opts.dragControls === thisInstance`) registers a\n// handler via the symbol-keyed internal property defined below. The\n// handler synthesizes a drag session from the externally-captured pointer\n// event, bypassing the usual threshold gate.\n// - One controls instance binds to one motion element at a time (Q9d).\n// When a second element registers, the first is silently replaced. On\n// unmount, only unregister if we're still the registered handler — avoid\n// clobbering a later registration.\n//\n// Internal registration:\n// - We attach a `_register(handler)` method to a non-enumerable symbol-keyed\n// property (Q9e), keeping the public `DragControls` type clean. The\n// symbol is exported as `DRAG_CONTROLS_REGISTER` for createDrag to find,\n// but users importing only `DragControls` never see it.\n// ---------------------------------------------------------------------------\n\n/**\n * Symbol used to attach the registration method on the controls object.\n * `createDrag` imports this symbol to find/register its handler. Userland\n * code never touches it — exported only for library-internal use.\n */\nexport const DRAG_CONTROLS_REGISTER = Symbol(\"solidjs-motion.dragControls.register\")\n\n/**\n * Internal registration signature — the handler that createDrag installs.\n * Returns an unregister function (called on owner disposal).\n */\ntype RegistrationFn = (\n handler: (event: PointerEvent, options: DragControlsStartOptions) => void,\n) => () => void\n\n/** Public + internal shape of the controls returned by `createDragControls`. */\ntype DragControlsInternal = DragControls & {\n [DRAG_CONTROLS_REGISTER]: RegistrationFn\n}\n\n/**\n * Create a controls instance for imperatively starting a drag on a motion\n * element from a different element (e.g., a drag-handle button).\n *\n * Pattern (Q9):\n *\n * @example\n * function Card() {\n * const controls = createDragControls()\n * const m = useMotion({ drag: \"y\", dragControls: controls })\n * return (\n * <div {...m()}>\n * <button onPointerDown={(e) => controls.start(e)}>handle</button>\n * Card body\n * </div>\n * )\n * }\n *\n * The handle's pointerdown fires `controls.start(event)`. createDrag is\n * registered with the controls and translates the call into a pan-session\n * synthesized from the handle's event, bypassing the threshold gate.\n */\nexport function createDragControls(): DragControls {\n let handler: ((event: PointerEvent, options: DragControlsStartOptions) => void) | null = null\n\n // Public surface — `start` is the only enumerable property.\n const controls: DragControlsInternal = {\n start(event: PointerEvent, options: DragControlsStartOptions = {}) {\n // No-op when no motion element is currently registered. Matches\n // motion/react's behavior: the user's pointerdown handler can be\n // attached unconditionally, and start() is harmless until binding.\n handler?.(event, options)\n },\n // Placeholder — filled in immediately below via Object.defineProperty\n // so the property is non-enumerable.\n [DRAG_CONTROLS_REGISTER]: undefined as unknown as RegistrationFn,\n }\n\n // Q9e — registration internals on a non-enumerable property keyed by\n // Symbol. Type-level the property is on DragControlsInternal, but the\n // public DragControls type omits it — userland sees only `.start`.\n Object.defineProperty(controls, DRAG_CONTROLS_REGISTER, {\n value: ((newHandler) => {\n handler = newHandler\n // Q9d — return an unregister that only nulls out if we're still the\n // active handler. Prevents a stale unmount from clobbering a later\n // registration on the same controls instance.\n return () => {\n if (handler === newHandler) handler = null\n }\n }) satisfies RegistrationFn,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return controls\n}\n","import {\n cancelFrame,\n frame,\n isMotionValue,\n type MotionValue,\n transform as motionTransform,\n motionValue,\n type SpringOptions,\n springValue,\n} from \"motion\"\nimport { type Accessor, createComputed, createSignal, onCleanup } from \"solid-js\"\nimport type { MotionValueAccessor } from \"../types\"\n\n// ---------------------------------------------------------------------------\n// MotionValue events the engine can fire — kept narrow so TypeScript autocomplete\n// surfaces only the documented surface.\n// ---------------------------------------------------------------------------\n\ntype MotionValueEvent = \"change\" | \"animationStart\" | \"animationComplete\" | \"animationCancel\"\n\n// ---------------------------------------------------------------------------\n// makeAccessor — wrap a raw motion.MotionValue as a callable hybrid. Invoking\n// `mv()` returns a Solid-tracked read; every MotionValue method (.get, .set,\n// .jump, .on, .getVelocity, etc.) forwards to the underlying value. Both\n// `isMotionValue(mv)` (duck-typed on .getVelocity) and `typeof mv === \"function\"`\n// are true; createMotion's splitTarget checks isMotionValue first, so the engine\n// treats hybrids as MotionValues.\n// ---------------------------------------------------------------------------\n\nfunction makeAccessor<T>(mv: MotionValue<T>): MotionValueAccessor<T> {\n // Solid signal bridge — kept in sync via `mv.on(\"change\", ...)`.\n const [signal, setSignal] = createSignal<T>(mv.get())\n // Wrap in updater form so Setter accepts T regardless of its shape (T could\n // include Function for callback-like motion values).\n onCleanup(mv.on(\"change\", (v) => setSignal(() => v)))\n\n // The callable: invoking returns the tracked signal value.\n const fn = (() => signal()) as MotionValueAccessor<T>\n\n return new Proxy(fn, {\n get(target, prop, receiver) {\n // Function intrinsics (call/apply/bind) stay on the function itself so\n // `fn.call(...)` etc. behave normally.\n if (prop === \"call\" || prop === \"apply\" || prop === \"bind\") {\n return Reflect.get(target, prop, receiver)\n }\n // If we ever attach our own properties to `fn`, prefer those.\n if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver)\n // Forward to the MotionValue. Methods are bound so `this` is the MV.\n const value = Reflect.get(mv as object, prop, mv)\n return typeof value === \"function\" ? value.bind(mv) : value\n },\n has(target, prop) {\n return Reflect.has(target, prop) || prop in (mv as object)\n },\n })\n}\n\n// ---------------------------------------------------------------------------\n// createMotionValue — callable-hybrid MotionValue auto-disposed on cleanup.\n// ---------------------------------------------------------------------------\n\n/**\n * Create a {@link MotionValueAccessor} bound to the current reactive scope.\n *\n * The returned value has two access patterns:\n *\n * - `mv()` — invoke as a Solid Accessor. Tracks in JSX, `createEffect`,\n * `createMemo`, etc.\n * - `mv.get()` / `mv.set(v)` / `mv.jump(v)` / `mv.on(...)` — the full upstream\n * {@link MotionValue} surface. Matches motion/react idioms.\n *\n * The same value can be passed as a target in\n * `useMotion({ animate: { x: mv } })` (motion engine sees `.getVelocity` via\n * the Proxy and treats it as a motion value) or directly as the target of\n * `animate(mv, 100)`.\n *\n * Auto-destroyed via `onCleanup` when the owner is disposed.\n *\n * @example\n * const x = createMotionValue(0)\n * x.set(100)\n * animate(x, 200, { duration: 0.5 })\n * <p>{x()}</p> // reactive read in JSX\n */\nexport function createMotionValue<T>(initial: T): MotionValueAccessor<T> {\n const mv = motionValue(initial)\n const accessor = makeAccessor(mv)\n // Route the cleanup call through the accessor so test-time spies on\n // `accessor.destroy` are invoked (the Proxy forwards to the underlying mv).\n onCleanup(() => accessor.destroy())\n return accessor\n}\n\n// ---------------------------------------------------------------------------\n// toSignal — adapt any raw MotionValue (e.g. from motion's `motionValue()`\n// factory) to a Solid Accessor. Useful when interoperating with motion APIs\n// that return raw MotionValues outside our hybrid factories.\n// ---------------------------------------------------------------------------\n\n/**\n * Bridge a raw {@link MotionValue} (from motion's `motionValue()` factory or\n * any other motion API that doesn't return our hybrid) to a Solid\n * {@link Accessor}. Seeds with the current value and updates on every\n * `change` event.\n *\n * **You usually don't need this.** Values returned by `createMotionValue`,\n * `createTransform`, `createSpring`, `createTime`, `createVelocity`, and\n * `createTemplate` are already callable — you can do `mv()` directly. Reach\n * for `toSignal` only when you receive a raw MotionValue from an external API.\n *\n * @example\n * import { motionValue } from \"motion\"\n * const rawMv = motionValue(0)\n * const xSignal = toSignal(rawMv)\n */\nexport function toSignal<T>(mv: MotionValue<T>): Accessor<T> {\n const [value, setValue] = createSignal<T>(mv.get())\n onCleanup(mv.on(\"change\", (v) => setValue(() => v)))\n return value\n}\n\n// ---------------------------------------------------------------------------\n// createMotionValueEvent — register a listener with automatic cleanup.\n// ---------------------------------------------------------------------------\n\n/**\n * Subscribe to a {@link MotionValue} event with automatic cleanup. Convenience\n * wrapper around `mv.on(event, cb)` for parity with motion/react's\n * `useMotionValueEvent`. For per-change reactivity, prefer\n * `createComputed(() => fn(mv()))` since hybrids are directly callable.\n *\n * @example\n * const x = createMotionValue(0)\n * createMotionValueEvent(x, \"animationComplete\", () => console.log(\"done\"))\n */\nexport function createMotionValueEvent<T>(\n mv: MotionValue<T>,\n event: MotionValueEvent,\n callback: (latest: T) => void,\n): void {\n onCleanup(mv.on(event, callback))\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction readInputValue<T>(input: MotionValue<T> | Accessor<T>): T {\n if (isMotionValue(input)) return (input as MotionValue<T>).get()\n return (input as Accessor<T>)()\n}\n\nfunction subscribeInput<T>(\n input: MotionValue<T> | Accessor<T>,\n onChange: (value: T) => void,\n): void {\n if (isMotionValue(input)) {\n onCleanup((input as MotionValue<T>).on(\"change\", onChange))\n } else {\n createComputed(() => onChange((input as Accessor<T>)()))\n }\n}\n\n// ---------------------------------------------------------------------------\n// createTransform — interpolate one MotionValue/Accessor through a range.\n// Returns a MotionValueAccessor so callable behavior is preserved end-to-end.\n// ---------------------------------------------------------------------------\n\ntype TransformOptions = NonNullable<Parameters<typeof motionTransform>[2]>\n\n/**\n * Create a {@link MotionValueAccessor} that maps an input through a range/\n * output pair. Mirrors motion/react's `useTransform`. The input can be a\n * MotionValue, our hybrid, or any Solid Accessor; the output composes with\n * `animate()`, `useMotion`'s targets, and JSX reactivity.\n *\n * @example\n * const { scrollY } = createScroll()\n * const opacity = createTransform(scrollY, [0, 200], [1, 0])\n * <div style={{ opacity: opacity() }}>...</div>\n */\nexport function createTransform<I extends number, O>(\n input: MotionValue<I> | Accessor<I>,\n inputRange: I[],\n outputRange: O[],\n options?: TransformOptions,\n): MotionValueAccessor<O> {\n const mapper = motionTransform(inputRange, outputRange, options)\n const mv = motionValue(mapper(readInputValue(input)))\n onCleanup(() => mv.destroy())\n subscribeInput(input, (v) => mv.set(mapper(v)))\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createSpring — produce a MotionValueAccessor that spring-tracks an input.\n// ---------------------------------------------------------------------------\n\n/**\n * Spring-smoothed mirror of a numeric input. Returns a\n * {@link MotionValueAccessor} that tracks the source with physics-based easing.\n *\n * @example\n * const x = createMotionValue(0)\n * const smoothX = createSpring(x, { stiffness: 100, damping: 20 })\n */\nexport function createSpring(\n source: MotionValue<number> | Accessor<number>,\n options?: SpringOptions,\n): MotionValueAccessor<number> {\n if (isMotionValue(source)) {\n const mv = springValue(source as MotionValue<number>, options)\n onCleanup(() => mv.destroy())\n return makeAccessor(mv)\n }\n // Accessor input — bridge through an intermediate MotionValue that mirrors it.\n const bridge = motionValue((source as Accessor<number>)())\n onCleanup(() => bridge.destroy())\n createComputed(() => bridge.set((source as Accessor<number>)()))\n const mv = springValue(bridge, options)\n onCleanup(() => mv.destroy())\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createTime — MotionValueAccessor that advances each frame with elapsed ms.\n// ---------------------------------------------------------------------------\n\n/**\n * {@link MotionValueAccessor} that advances every animation frame, holding\n * the milliseconds elapsed since this primitive was called. Driver for\n * time-based animations and {@link createTransform}-derived values.\n *\n * @example\n * const t = createTime()\n * const wobble = createTransform(t, [0, 1000, 2000], [0, 10, 0])\n */\nexport function createTime(): MotionValueAccessor<number> {\n const mv = motionValue(0)\n onCleanup(() => mv.destroy())\n const startedAt = performance.now()\n const tick = () => mv.set(performance.now() - startedAt)\n frame.update(tick, true)\n onCleanup(() => cancelFrame(tick))\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createVelocity — MotionValueAccessor mirroring an input's instantaneous velocity.\n// ---------------------------------------------------------------------------\n\n/**\n * {@link MotionValueAccessor} reporting the velocity of a source motion value.\n * Updated whenever the source changes.\n *\n * @example\n * const x = createMotionValue(0)\n * const xVelocity = createVelocity(x)\n */\nexport function createVelocity(source: MotionValue<number>): MotionValueAccessor<number> {\n const mv = motionValue(source.getVelocity())\n onCleanup(() => mv.destroy())\n onCleanup(source.on(\"change\", () => mv.set(source.getVelocity())))\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createTemplate — tagged template producing a MotionValueAccessor<string>.\n// ---------------------------------------------------------------------------\n\n// biome-ignore lint/suspicious/noExplicitAny: MotionValue is invariant in T; `any` lets the template accept MotionValues of any value type.\ntype TemplateInput = MotionValue<any> | Accessor<unknown> | string | number\n\n/**\n * Tagged template producing a {@link MotionValueAccessor}\\<string\\>.\n * Interpolated {@link MotionValue}s, hybrids, and Solid Accessors recompute\n * the output string on change; primitives and static strings are baked in.\n *\n * @example\n * const x = createMotionValue(0)\n * const y = createMotionValue(0)\n * const transform = createTemplate`translate(${x}px, ${y}px) scale(1.1)`\n * <div style={{ transform: transform() }} />\n */\nexport function createTemplate(\n strings: TemplateStringsArray,\n ...values: TemplateInput[]\n): MotionValueAccessor<string> {\n const compute = (): string => {\n let out = \"\"\n for (let i = 0; i < strings.length; i++) {\n out += strings[i]\n if (i < values.length) {\n const v = values[i]\n if (isMotionValue(v)) {\n out += String((v as MotionValue<unknown>).get())\n } else if (typeof v === \"function\") {\n out += String((v as Accessor<unknown>)())\n } else {\n out += String(v)\n }\n }\n }\n return out\n }\n\n const mv = motionValue(compute())\n onCleanup(() => mv.destroy())\n\n for (const v of values) {\n if (isMotionValue(v)) {\n onCleanup((v as MotionValue<unknown>).on(\"change\", () => mv.set(compute())))\n }\n }\n\n const hasAccessor = values.some((v) => typeof v === \"function\" && !isMotionValue(v))\n if (hasAccessor) {\n createComputed(() => {\n for (const v of values) {\n if (typeof v === \"function\" && !isMotionValue(v)) (v as Accessor<unknown>)()\n }\n mv.set(compute())\n })\n }\n\n return makeAccessor(mv)\n}\n","import { isPrimaryPointer, time } from \"motion-dom\"\nimport { type Accessor, createEffect, createSignal, onCleanup } from \"solid-js\"\nimport type { MotionValueAccessor, PanInfo } from \"../types\"\nimport { createMotionValue } from \"./motion-value\"\n\n// ---------------------------------------------------------------------------\n// createPan — standalone pan-session primitive (Q11/c).\n//\n// Phase 2 Commit 5 (Q11/D3): pointer-session machinery that createDrag uses\n// as its underlying event source. Drag IS a pan that owns the element's\n// transform; pan on its own is callback-only (no `whilePan` state).\n//\n// Return shape — a SEMANTIC split between animate-able numeric values\n// (MotionValueAccessors) and non-animate-able state (a plain Accessor):\n//\n// - `point.x/y`, `delta.x/y`, `offset.x/y`, `velocity.x/y` → each is a\n// {@link MotionValueAccessor}<number>. Calling them (`pan.point.x()`) is\n// Solid-tracked; the full MotionValue surface (`.get`, `.set`, `.on`,\n// `.getVelocity`) is available; they compose directly with `animate()`,\n// `createTransform`, `useMotion` targets, and JSX reactivity.\n// - `isPanning` → a plain `Accessor<boolean>`. Booleans aren't animate-able,\n// so wrapping in an MV would only add weight.\n//\n// Why MotionValues for the numeric fields? Composability. Users can pipe\n// `pan.point.x` straight into `createTransform`, `animate()`, or use it as\n// a target in `useMotion({ animate: { x: pan.point.x } })` — same surface\n// Phase 1 established for every animate-able value in the library.\n//\n// The session:\n// pointerdown → reset per-session MVs to start point / zeros, attach\n// window listeners\n// pointermove(s) → update MVs every move (Option X — pre-threshold too,\n// so consumers can render threshold-progress or\n// early-detect fast pans); once cumulative offset\n// crosses `threshold`, isPanning flips true and\n// onPanStart fires; subsequent moves fire onPan\n// pointerup → flip isPanning false; if pan happened, fire onPanEnd;\n// point/delta/offset/velocity MVs RETAINED (useful for\n// snap-to-end animations)\n// pointercancel → same as pointerup, but the user's gesture was aborted\n//\n// Velocity tracking (Q15a): sliding window of pointer samples, 200ms wide.\n// Velocity = (latest.point − oldest.point) / Δt × 1000 (px/sec). Uses\n// motion-dom's `time.now()` so timestamps stay frame-synchronous with the\n// rest of motion's pipeline.\n// ---------------------------------------------------------------------------\n\n/** Sliding-window width for velocity computation (Q15a). */\nconst VELOCITY_WINDOW_MS = 200\n/** Default movement threshold before onPanStart fires (Q11a, matches motion). */\nconst DEFAULT_THRESHOLD = 3\n\ntype Point = { x: number; y: number }\n\nexport type CreatePanOptions = {\n /** Fires once after pointer movement crosses the threshold. */\n onPanStart?: (event: PointerEvent, info: PanInfo) => void\n /** Fires on every pointermove after onPanStart, until pointerup/cancel. */\n onPan?: (event: PointerEvent, info: PanInfo) => void\n /**\n * Fires on pointerup OR pointercancel after onPanStart has fired.\n * If the pointer was released before the threshold was crossed, onPanEnd\n * is NOT fired (no pan ever happened).\n */\n onPanEnd?: (event: PointerEvent, info: PanInfo) => void\n /**\n * Minimum cumulative offset (in px) before onPanStart fires. Distinguishes\n * pan from click. Default: 3px (motion's default).\n */\n threshold?: number\n}\n\n/** Per-axis pair of {@link MotionValueAccessor}s — `pan.point`, `pan.delta`, etc. */\nexport type PanAxisPair = {\n x: MotionValueAccessor<number>\n y: MotionValueAccessor<number>\n}\n\n/**\n * Returned by {@link createPan}. `isPanning` is a plain Accessor (booleans\n * aren't animate-able). The four numeric pairs are MotionValueAccessors,\n * each composable with `animate()`, `createTransform`, and `useMotion`.\n */\nexport type CreatePanResult = {\n isPanning: Accessor<boolean>\n point: PanAxisPair\n delta: PanAxisPair\n offset: PanAxisPair\n velocity: PanAxisPair\n}\n\n/**\n * Observe pointer-driven pan gestures on an element.\n *\n * Returns `{ isPanning, point, delta, offset, velocity }`:\n *\n * - `pan.isPanning()` — Solid Accessor; `true` between onPanStart and onPanEnd.\n * - `pan.point.x`, `pan.point.y` — current pointer position in client coords.\n * Each is a {@link MotionValueAccessor}: call `pan.point.x()` for a tracked\n * read, `pan.point.x.get()` for an untracked snapshot, and pass it directly\n * to `animate()`, `createTransform`, or `useMotion` targets.\n * - `pan.delta.x/y` — delta since last pointermove.\n * - `pan.offset.x/y` — cumulative offset since the current pointerdown.\n * - `pan.velocity.x/y` — sliding-window velocity in px/sec.\n *\n * Fields update from `pointerdown` forward (including pre-threshold moves)\n * — gate reads on `pan.isPanning()` if you only care about real pans.\n *\n * The `options` argument accepts either a static object or a function form\n * (matching `useMotion`'s convention). The function form is read INSIDE\n * each pointer-event handler, so reactive option changes apply on the next\n * relevant event without re-attaching listeners.\n *\n * @example Static options\n * const pan = createPan(el, {\n * onPanStart: (e, info) => console.log(\"start\", info.point),\n * threshold: 3,\n * })\n *\n * @example Reactive options (function form — signals tracked)\n * const [threshold, setThreshold] = createSignal(3)\n * const pan = createPan(el, () => ({\n * threshold: threshold(),\n * onPanStart: (e, info) => console.log(info),\n * }))\n *\n * @example Composing pan.point.x with createTransform\n * const pan = createPan(el)\n * const rotation = createTransform(pan.point.x, [0, 300], [0, 90])\n * <div ref={setEl} style={{ transform: `rotate(${rotation()}deg)` }} />\n *\n * @example Reading reactively in JSX\n * const pan = createPan(el)\n * <Show when={pan.isPanning()}>\n * Position: {pan.point.x()}, {pan.point.y()}\n * </Show>\n */\nexport function createPan(\n ref: () => HTMLElement | null | undefined,\n options: CreatePanOptions | (() => CreatePanOptions) = {},\n): CreatePanResult {\n // Normalize to a function form. All option reads inside event handlers\n // call this so the latest reactive values are seen on each event.\n const getOpts: () => CreatePanOptions = typeof options === \"function\" ? options : () => options\n\n // ---- State surface ----\n // isPanning is a plain signal — booleans aren't animate-able, so a full\n // MotionValue would be dead weight.\n const [isPanning, setIsPanning] = createSignal(false)\n // Eight MVs for the four numeric pairs. Each becomes a callable hybrid via\n // createMotionValue: invokable as a tracked Accessor AND has the full\n // MotionValue surface so consumers can pipe them into `animate()`,\n // `createTransform`, or `useMotion` targets.\n const pointX = createMotionValue(0)\n const pointY = createMotionValue(0)\n const deltaX = createMotionValue(0)\n const deltaY = createMotionValue(0)\n const offsetX = createMotionValue(0)\n const offsetY = createMotionValue(0)\n const velocityX = createMotionValue(0)\n const velocityY = createMotionValue(0)\n\n // createEffect — Solid-idiomatic for side-effect setup (DOM listeners).\n // First iteration runs in the next microtask, which is harmless here: a\n // freshly-mounted element can't receive pointer events between the ref\n // callback firing and the next microtask. Re-runs (ref changes) carry the\n // same harmless delay.\n createEffect(() => {\n const el = ref()\n if (!el) return\n\n // NOTE: threshold and callbacks are read INSIDE the event handlers via\n // getOpts(), not captured here. That way reactive opts changes apply on\n // the next relevant event without re-attaching listeners (which would\n // require this effect to depend on getOpts and re-run on opt changes).\n\n // Session state — reset on each pointerdown. Scoped per effect iteration;\n // cleanup below reaches all listeners regardless of phase.\n let startPoint: Point | null = null\n let lastPoint: Point | null = null\n let pointerId: number | null = null\n let panning = false\n let samples: Array<{ t: number; point: Point }> = []\n\n function pointOf(event: PointerEvent): Point {\n return { x: event.clientX, y: event.clientY }\n }\n\n function computeVelocity(): Point {\n if (samples.length < 2) return { x: 0, y: 0 }\n // biome-ignore lint/style/noNonNullAssertion: length >= 2 guarantees both indices exist\n const first = samples[0]!\n // biome-ignore lint/style/noNonNullAssertion: length >= 2 guarantees both indices exist\n const last = samples[samples.length - 1]!\n const dt = last.t - first.t\n if (dt <= 0) return { x: 0, y: 0 }\n return {\n x: ((last.point.x - first.point.x) / dt) * 1000,\n y: ((last.point.y - first.point.y) / dt) * 1000,\n }\n }\n\n function buildInfo(event: PointerEvent): PanInfo {\n const point = pointOf(event)\n const delta = lastPoint\n ? { x: point.x - lastPoint.x, y: point.y - lastPoint.y }\n : { x: 0, y: 0 }\n const offset = startPoint\n ? { x: point.x - startPoint.x, y: point.y - startPoint.y }\n : { x: 0, y: 0 }\n const velocity = computeVelocity()\n return { point, delta, offset, velocity }\n }\n\n /** Push a freshly-computed info snapshot into the MVs. Each `.set` fires\n * the MV's change subscription, which the callable-hybrid bridge\n * forwards to Solid; consumers reading e.g. only `pan.velocity.x()` only\n * re-run when velocity.x actually changes — pre-existing MotionValue\n * granularity, not Store path-tracking. */\n function writeInfo(info: PanInfo): void {\n pointX.set(info.point.x)\n pointY.set(info.point.y)\n deltaX.set(info.delta.x)\n deltaY.set(info.delta.y)\n offsetX.set(info.offset.x)\n offsetY.set(info.offset.y)\n velocityX.set(info.velocity.x)\n velocityY.set(info.velocity.y)\n }\n\n function onPointerDown(event: PointerEvent): void {\n // motion-dom's isPrimaryPointer filters secondary buttons (mouse) and\n // secondary touch points. Same gating Q13c established for press.\n if (!isPrimaryPointer(event)) return\n\n startPoint = pointOf(event)\n lastPoint = startPoint\n pointerId = event.pointerId\n panning = false\n samples = [{ t: time.now(), point: startPoint }]\n\n // Reset per-session fields. Point goes to start; delta/offset/velocity\n // zero. isPanning false (threshold not crossed yet).\n setIsPanning(false)\n pointX.set(startPoint.x)\n pointY.set(startPoint.y)\n deltaX.set(0)\n deltaY.set(0)\n offsetX.set(0)\n offsetY.set(0)\n velocityX.set(0)\n velocityY.set(0)\n\n // Listen on window so events keep firing even when the pointer leaves\n // the element (e.g., during a fast drag). Mirrors motion-dom's press.\n window.addEventListener(\"pointermove\", onPointerMove)\n window.addEventListener(\"pointerup\", onPointerEnd)\n window.addEventListener(\"pointercancel\", onPointerEnd)\n }\n\n function onPointerMove(event: PointerEvent): void {\n // Multi-touch / unrelated pointers ignored.\n if (event.pointerId !== pointerId) return\n\n const point = pointOf(event)\n const now = time.now()\n\n // Append sample, drop everything outside the 200ms window.\n samples.push({ t: now, point })\n const cutoff = now - VELOCITY_WINDOW_MS\n while (samples.length > 1 && (samples[0]?.t ?? 0) < cutoff) {\n samples.shift()\n }\n\n const info = buildInfo(event)\n // Option X — info updates on EVERY move, including pre-threshold.\n // Consumers gate on `isPanning()` for \"real pan\" semantics.\n writeInfo(info)\n\n if (!panning) {\n // Threshold gate: pan hasn't started yet. Read threshold fresh from\n // getOpts() so reactive changes apply (a session in progress sticks\n // with the threshold it saw when this branch first crossed).\n const threshold = getOpts().threshold ?? DEFAULT_THRESHOLD\n const distance = Math.hypot(info.offset.x, info.offset.y)\n if (distance >= threshold) {\n panning = true\n setIsPanning(true)\n getOpts().onPanStart?.(event, info)\n }\n } else {\n getOpts().onPan?.(event, info)\n }\n lastPoint = point\n }\n\n function onPointerEnd(event: PointerEvent): void {\n if (event.pointerId !== pointerId) return\n // onPanEnd only fires if onPanStart fired — pan-cancelled-before-start\n // (mere clicks) shouldn't emit lifecycle callbacks.\n if (panning) {\n getOpts().onPanEnd?.(event, buildInfo(event))\n }\n panning = false\n // Flip isPanning. Point/delta/offset/velocity MVs are RETAINED\n // (option Q5/3) so consumers can read the final state for\n // snap-to-end animations. Next pointerdown will reset them.\n setIsPanning(false)\n startPoint = null\n lastPoint = null\n pointerId = null\n samples = []\n window.removeEventListener(\"pointermove\", onPointerMove)\n window.removeEventListener(\"pointerup\", onPointerEnd)\n window.removeEventListener(\"pointercancel\", onPointerEnd)\n }\n\n el.addEventListener(\"pointerdown\", onPointerDown)\n\n // Iteration-scoped cleanup: fires when the ref changes (effect re-runs)\n // AND when the owner disposes. Removes all listeners regardless of\n // whether a session was in progress.\n onCleanup(() => {\n el.removeEventListener(\"pointerdown\", onPointerDown)\n window.removeEventListener(\"pointermove\", onPointerMove)\n window.removeEventListener(\"pointerup\", onPointerEnd)\n window.removeEventListener(\"pointercancel\", onPointerEnd)\n })\n })\n\n return {\n isPanning,\n point: { x: pointX, y: pointY },\n delta: { x: deltaX, y: deltaY },\n offset: { x: offsetX, y: offsetY },\n velocity: { x: velocityX, y: velocityY },\n }\n}\n","import { type AnimationPlaybackControls, animate } from \"motion\"\nimport { HTMLVisualElement, type MotionValue, time, visualElementStore } from \"motion-dom\"\nimport { createEffect, onCleanup } from \"solid-js\"\nimport type {\n DragConstraints,\n DragControls,\n DragControlsStartOptions,\n MotionOptions,\n PanInfo,\n} from \"../types\"\nimport { DRAG_CONTROLS_REGISTER } from \"./createDragControls\"\nimport { createPan } from \"./createPan\"\nimport type { SetActive } from \"./gesture-state\"\n\n// ---------------------------------------------------------------------------\n// createDrag — pointer-driven drag with motion-dom VisualElement composition\n// (Q5/C-lean + Q15).\n//\n// Architecture:\n// - Layered on top of createPan (Q11/D3). Pan handles the pointer session\n// (down → threshold-gated start → moves → up/cancel) and exposes its\n// PanInfo via callbacks. Drag adds the side-effects on top: transform\n// writes, body/touchAction styling, pointer capture, state-machine\n// activation, and (Stage 4) momentum.\n// - Translation flows through motion-dom's VisualElement system: drag writes\n// to the element's `x`/`y` MotionValues, and motion's render pipeline\n// composes the final transform string. This is why `whileDrag: { scale }`\n// works for free — the scale animation writes a sibling MV and the VE\n// composes all transform-class values into one output (Q5/C-lean).\n//\n// State machine integration:\n// - On pan-start (only if drag is enabled), `setActive(\"whileDrag\", true)`\n// fires. The state machine's `winners` memo then claims whileDrag's\n// target keys, EXCEPT x and y which are filtered (drag owns them).\n// - On pan-end, `setActive(\"whileDrag\", false)`. Momentum (Stage 4) runs\n// AFTER whileDrag deactivates — visual gesture state ends with the\n// pointerup, not when the animation settles.\n// ---------------------------------------------------------------------------\n\n/**\n * Get or create a motion-dom VisualElement for an HTMLElement. Required\n * because we write to the VE's `x`/`y` MotionValues during drag, and motion\n * only auto-creates the VE inside `animate(el, target)` calls — if a user\n * configures drag without any animate target, no VE would exist.\n *\n * Mirrors framer-motion's `createDOMVisualElement` (which isn't reachable\n * from a non-React context — framer-motion's main entry requires React).\n * The options shape and `mount` + `visualElementStore.set` calls match the\n * upstream implementation. SVG support is omitted for v0.1 — drag on SVG\n * is an unusual case.\n */\nfunction ensureVisualElement(el: HTMLElement): InstanceType<typeof HTMLVisualElement> {\n const existing = visualElementStore.get(el)\n if (existing) return existing as InstanceType<typeof HTMLVisualElement>\n\n // motion-dom's VisualElement options type expects more fields than we\n // can sensibly provide without React-flavored MotionProps. The runtime\n // needs only the visualState shape and an empty props bag.\n const options = {\n presenceContext: null,\n props: {},\n visualState: {\n renderState: {\n transform: {},\n transformOrigin: {},\n style: {},\n vars: {},\n attrs: {},\n },\n latestValues: {},\n },\n }\n // biome-ignore lint/suspicious/noExplicitAny: VisualElement options type expects React-flavored MotionProps we can't supply.\n const ve = new HTMLVisualElement(options as any)\n ve.mount(el)\n visualElementStore.set(el, ve)\n return ve as InstanceType<typeof HTMLVisualElement>\n}\n\n/**\n * Parse the visible translate from an element's transform — reads both\n * `getComputedStyle(el).transform` (which real browsers normalize to\n * matrix form) AND `el.style.transform` (which preserves the raw syntax\n * motion-dom's writer emits, e.g. `translate3d(50px, 0px, 0)`). Used by\n * drag's pan-start to sync the x/y MotionValues to what the user is\n * actually seeing.\n *\n * Why both sources: motion's `animate(el, target)` interpolates style.\n * transform via WAAPI but DOESN'T update the VE's MVs during the tween,\n * so after `initial: {x:-300} → animate: {x:0}` the MV still holds -300.\n * Reading the current transform recovers the truth. We prefer computed\n * (post-animation, post-WAAPI-commit value) and fall back to inline\n * (covers jsdom + cases where motion's writer wrote inline but the\n * browser hasn't run a style-resolve pass yet).\n *\n * Supported syntaxes:\n * - `\"none\"` / empty → {0, 0}\n * - `matrix(a, b, c, d, tx, ty)`\n * - `matrix3d(..., tx, ty, ...)`\n * - `translateX(Npx)` / `translateY(Npx)` / `translate(tx, ty)`\n * - `translate3d(tx, ty, tz)`\n * - Any of the above mixed with other transform functions (regex-\n * based extraction picks just the translate components).\n */\nfunction readVisibleTranslate(el: HTMLElement): { x: number; y: number } {\n const fromString = (transform: string): { x: number; y: number } | null => {\n if (!transform || transform === \"none\") return null\n\n if (transform.startsWith(\"matrix3d(\")) {\n const values = transform.slice(9, -1).split(\",\")\n const tx = Number.parseFloat(values[12] ?? \"0\")\n const ty = Number.parseFloat(values[13] ?? \"0\")\n if (!Number.isFinite(tx) && !Number.isFinite(ty)) return null\n return { x: Number.isFinite(tx) ? tx : 0, y: Number.isFinite(ty) ? ty : 0 }\n }\n if (transform.startsWith(\"matrix(\")) {\n const values = transform.slice(7, -1).split(\",\")\n const tx = Number.parseFloat(values[4] ?? \"0\")\n const ty = Number.parseFloat(values[5] ?? \"0\")\n if (!Number.isFinite(tx) && !Number.isFinite(ty)) return null\n return { x: Number.isFinite(tx) ? tx : 0, y: Number.isFinite(ty) ? ty : 0 }\n }\n\n // motion-dom's writer emits the keyword form: `translate3d(...)`,\n // `translateX(...)`, etc. — usually as the first segment of a\n // composed transform like `translate3d(50px, 0px, 0) scale(1)`.\n let x = 0\n let y = 0\n let found = false\n const translate3d = transform.match(/translate3d\\(\\s*([-\\d.]+)px\\s*,\\s*([-\\d.]+)px/)\n if (translate3d) {\n x = Number.parseFloat(translate3d[1] ?? \"0\")\n y = Number.parseFloat(translate3d[2] ?? \"0\")\n found = true\n } else {\n const translate2d = transform.match(/translate\\(\\s*([-\\d.]+)px\\s*(?:,\\s*([-\\d.]+)px)?/)\n if (translate2d) {\n x = Number.parseFloat(translate2d[1] ?? \"0\")\n y = Number.parseFloat(translate2d[2] ?? \"0\")\n found = true\n }\n const translateX = transform.match(/translateX\\(\\s*([-\\d.]+)px/)\n if (translateX) {\n x = Number.parseFloat(translateX[1] ?? \"0\")\n found = true\n }\n const translateY = transform.match(/translateY\\(\\s*([-\\d.]+)px/)\n if (translateY) {\n y = Number.parseFloat(translateY[1] ?? \"0\")\n found = true\n }\n }\n if (!found) return null\n return { x: Number.isFinite(x) ? x : 0, y: Number.isFinite(y) ? y : 0 }\n }\n\n return fromString(getComputedStyle(el).transform) ?? fromString(el.style.transform) ?? { x: 0, y: 0 }\n}\n\n/**\n * Compute the `touch-action` CSS value for an element being dragged.\n * Disabling touch-action prevents the browser from interpreting the gesture\n * as a scroll. Axis-locked drags leave the unused axis available for scroll\n * (so a horizontally-draggable card can still be scrolled vertically by the\n * surrounding page).\n */\nfunction touchActionFor(drag: MotionOptions[\"drag\"]): string {\n if (drag === \"x\") return \"pan-y\"\n if (drag === \"y\") return \"pan-x\"\n return \"none\"\n}\n\n/**\n * Resolved drag bounds expressed as absolute MotionValue bounds (Q5/C-lean —\n * drag writes absolute values, so we clamp in MV-space, not offset-space).\n * `Infinity` / `-Infinity` represent \"unbounded in that direction.\"\n */\ntype ResolvedBounds = {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\n/**\n * Resolve a {@link DragConstraints} value into absolute MotionValue bounds at\n * drag-start. Two input shapes (Q8):\n *\n * - **Numeric** (`{ top, left, right, bottom }`): bounds are absolute MV\n * values. `left: -100` means x cannot go below -100.\n * - **HTMLElement or `() => HTMLElement | null`**: container that the\n * dragged element must stay inside. Bounds are computed from the\n * container's bounding rect vs the dragged element's current rect, then\n * re-centered around the current MV values.\n *\n * The element form is resolved ONCE at drag-start (current viewport rects).\n * Reactive constraint changes mid-drag aren't honored in v0.1 — they'd\n * require re-measuring on each pointermove. Acceptable corner case.\n *\n * Returns `null` when constraints are unset or the accessor returns null —\n * caller treats as \"no clamping, no elastic resistance.\"\n */\nfunction resolveConstraints(\n constraints: DragConstraints | undefined,\n el: HTMLElement,\n dragStartX: number,\n dragStartY: number,\n): ResolvedBounds | null {\n if (!constraints) return null\n\n // Discriminate variants with `instanceof HTMLElement` first — this rules\n // out HTMLElement so the `typeof === \"function\"` check below narrows\n // cleanly to the accessor variant. (TS gets confused if we test the\n // function form first; HTMLElement instances have many methods on their\n // prototype, which can muddle TS's narrowing logic.)\n let container: HTMLElement | null = null\n if (constraints instanceof HTMLElement) {\n container = constraints\n } else if (typeof constraints === \"function\") {\n container = constraints()\n }\n\n if (container) {\n // Element-form: compute offset bounds from rects, then add dragStart\n // so we get absolute MV bounds. Subtle but important: the element's\n // current rect already includes any applied transform (including the\n // current dragStart translation), so we add dragStart back to convert\n // \"allowable offset from current position\" to \"allowable absolute MV\n // value.\"\n const containerRect = container.getBoundingClientRect()\n const elementRect = el.getBoundingClientRect()\n return {\n minX: dragStartX + (containerRect.left - elementRect.left),\n maxX: dragStartX + (containerRect.right - elementRect.right),\n minY: dragStartY + (containerRect.top - elementRect.top),\n maxY: dragStartY + (containerRect.bottom - elementRect.bottom),\n }\n }\n\n // Numeric form. Missing keys → unbounded on that side.\n const numeric = constraints as { top?: number; left?: number; right?: number; bottom?: number }\n return {\n minX: numeric.left ?? -Infinity,\n maxX: numeric.right ?? Infinity,\n minY: numeric.top ?? -Infinity,\n maxY: numeric.bottom ?? Infinity,\n }\n}\n\n/**\n * Apply elastic resistance past a boundary (Q15c — linear).\n *\n * Within bounds: `value` passes through unchanged. Past a bound by `Δ`: the\n * displayed value is `boundary + elastic × Δ`. With `elastic: 0` the value\n * clamps hard at the boundary; with `elastic: 1` resistance vanishes\n * (motion's default is `0.5`, halving the overflow).\n *\n * The function is symmetric — overflow on either side resists with the\n * same coefficient.\n */\nfunction applyElastic(value: number, min: number, max: number, elastic: number): number {\n if (value < min) return min + (value - min) * elastic\n if (value > max) return max + (value - max) * elastic\n return value\n}\n\nconst DEFAULT_ELASTIC = 0.5\n\n/**\n * Default `dragTransition` (Q15d — matches motion's inertia preset).\n *\n * `type: \"inertia\"` decays from the release point using `velocity`, with\n * spring physics at `min`/`max` boundaries. The defaults are the values\n * the user signed off on during Phase 2 grilling; passing a custom\n * `dragTransition` shallow-merges over these.\n */\nconst DEFAULT_DRAG_TRANSITION = {\n type: \"inertia\" as const,\n power: 0.8,\n timeConstant: 750,\n bounceStiffness: 500,\n bounceDamping: 10,\n restDelta: 1,\n restSpeed: 10,\n}\n\n/**\n * Bind pointer-driven drag to an element. Layers on top of createPan for the\n * pointer session; adds transform writes, body styles, pointer capture, and\n * state-machine activation.\n *\n * Drag is enabled when `opts.drag` is truthy (`true`, `\"x\"`, or `\"y\"`).\n * createDrag always wires the pointer session — the enable check is per-\n * gesture-start, so toggling `opts.drag` on/off doesn't churn listeners.\n *\n * Phase 2 Commit 6 — Stage 2 scope: VE bootstrap, translation, axis lock,\n * body/pointer styles, callbacks, cleanup. Constraints + elastic resistance\n * land in Stage 3; momentum + dragSnapToOrigin in Stage 4.\n */\nexport function createDrag(\n el: HTMLElement,\n getOpts: () => MotionOptions,\n setActive: SetActive,\n): void {\n // Drag-session state. These are reset on each pan-start; null between\n // sessions. Holding references in the closure is fine — the createPan\n // handlers below close over them.\n let xMV: MotionValue<number> | null = null\n let yMV: MotionValue<number> | null = null\n /** Drag-start position of the x/y MotionValues (the values that existed\n * before the user grabbed). offsets from PanInfo accumulate from this. */\n let dragStartX = 0\n let dragStartY = 0\n /** Resolved bounds for this session — computed once at drag-start and\n * reused across all pointermoves to avoid repeat layout reads. `null`\n * means no constraints. */\n let sessionBounds: ResolvedBounds | null = null\n /** Saved before applying drag's `user-select` / `touch-action` overrides\n * so we can restore them exactly on session end. */\n let savedUserSelect = \"\"\n let savedTouchAction = \"\"\n let capturedPointerId: number | null = null\n /** In-flight momentum animations (one per axis when active). Stopped on\n * owner disposal AND on a fresh pointerdown (to interrupt a settling\n * momentum if the user grabs again mid-decay). */\n let momentumControls: AnimationPlaybackControls[] = []\n\n function isDragEnabled(): boolean {\n return Boolean(getOpts().drag)\n }\n\n function restoreBodyAndElementStyles(): void {\n document.body.style.userSelect = savedUserSelect\n el.style.touchAction = savedTouchAction\n }\n\n function releasePointerCaptureSafely(): void {\n if (capturedPointerId === null) return\n try {\n el.releasePointerCapture(capturedPointerId)\n } catch {\n // jsdom doesn't fully implement setPointerCapture; tolerate.\n }\n capturedPointerId = null\n }\n\n function stopMomentum(): void {\n for (const ctrl of momentumControls) ctrl.stop()\n momentumControls = []\n }\n\n // Stable handler references — they close over getOpts so reactive opts\n // are read at event time. Hoisted out of the createPan call so the\n // function-form options below doesn't re-allocate them per getOpts() call.\n const handlePanStart = (event: PointerEvent, info: PanInfo, mvIsAuthoritative = false) => {\n // The pan session always fires onPanStart once movement crosses the\n // threshold. Drag's enable check is here, not at the createPan-setup\n // site, so toggling `drag` off mid-life immediately stops drag\n // engagement without re-attaching pointer listeners.\n if (!isDragEnabled()) return\n\n // If momentum from a previous drag is still settling, cancel it now —\n // the user has grabbed again, and they expect the element to follow\n // their pointer from its current position, not continue decaying.\n stopMomentum()\n\n const ve = ensureVisualElement(el)\n xMV = ve.getValue(\"x\", 0) as MotionValue<number>\n yMV = ve.getValue(\"y\", 0) as MotionValue<number>\n\n // dragStart capture — two modes:\n //\n // (1) Default: sync the MV to the element's CURRENT visible translate\n // before capturing. motion's `animate(el, target)` interpolates\n // `style.transform` via WAAPI but DOESN'T update the\n // visualElement's x/y MVs in lockstep, so after an entrance\n // animation (e.g. `initial: {x:-300} → animate: {x:0}`) the MV\n // would still hold the start value. Reading the painted transform\n // recovers the truth and seeds dragStart correctly.\n //\n // (2) `mvIsAuthoritative=true` (e.g. dragControls.start with\n // snapToCursor): the caller wrote the MV synchronously RIGHT\n // before reaching us, but motion-dom's writer is frame-scheduled,\n // so `el.style.transform` may not reflect that write yet. Trust\n // the MV in this path — visible would be stale.\n //\n // Only the axis drag actually uses is touched — touching the locked\n // axis would generate spurious MV writes that callers + tests notice.\n const axis = getOpts().drag\n if (mvIsAuthoritative) {\n dragStartX = xMV.get()\n dragStartY = yMV.get()\n } else {\n const visible = readVisibleTranslate(el)\n if (axis !== \"y\") {\n if (visible.x !== xMV.get()) xMV.set(visible.x)\n dragStartX = visible.x\n } else {\n dragStartX = xMV.get()\n }\n if (axis !== \"x\") {\n if (visible.y !== yMV.get()) yMV.set(visible.y)\n dragStartY = visible.y\n } else {\n dragStartY = yMV.get()\n }\n }\n\n // Resolve constraints once per session. Reading layout rects mid-drag\n // would cost a forced reflow per pointermove; one read at drag-start\n // is enough for v0.1 (reactive constraint changes during a drag are\n // a rare corner case — they re-apply on the NEXT session).\n sessionBounds = resolveConstraints(getOpts().dragConstraints, el, dragStartX, dragStartY)\n\n // Body + touch-action overrides — saved so the exact prior values\n // restore on session end (don't assume defaults).\n savedUserSelect = document.body.style.userSelect\n savedTouchAction = el.style.touchAction\n document.body.style.userSelect = \"none\"\n el.style.touchAction = touchActionFor(getOpts().drag)\n\n // Pointer capture keeps move events flowing to the element even when\n // the pointer leaves it during a fast drag. setPointerCapture can\n // throw in some browsers (e.g., already captured); swallow.\n try {\n el.setPointerCapture(event.pointerId)\n capturedPointerId = event.pointerId\n } catch {\n // Safe — window listeners in createPan continue to fire regardless.\n }\n\n setActive(\"whileDrag\", true)\n getOpts().onDragStart?.(event, info)\n }\n\n const handlePan = (event: PointerEvent, info: PanInfo) => {\n if (!isDragEnabled() || !xMV || !yMV) return\n\n const axis = getOpts().drag\n // Axis lock: when drag is \"x\" or \"y\", we SKIP writes to the locked axis\n // entirely — matches motion/react's per-axis shouldDrag short-circuit.\n // Writing dragStartY+0 to yMV when y is locked would generate\n // no-op-but-non-empty writes that consumers and tests both observe.\n const writeX = axis !== \"y\"\n const writeY = axis !== \"x\"\n const elastic = getOpts().dragElastic ?? DEFAULT_ELASTIC\n\n if (writeX) {\n const candidateX = dragStartX + info.offset.x\n const finalX = sessionBounds\n ? applyElastic(candidateX, sessionBounds.minX, sessionBounds.maxX, elastic)\n : candidateX\n xMV.set(finalX)\n }\n if (writeY) {\n const candidateY = dragStartY + info.offset.y\n const finalY = sessionBounds\n ? applyElastic(candidateY, sessionBounds.minY, sessionBounds.maxY, elastic)\n : candidateY\n yMV.set(finalY)\n }\n\n getOpts().onDrag?.(event, info)\n }\n\n const handlePanEnd = (event: PointerEvent, info: PanInfo) => {\n if (!isDragEnabled() || !xMV || !yMV) return\n\n // Visual gesture state ends with the pointerup; momentum is a separate\n // animation that continues after whileDrag deactivates. This matches\n // motion/react semantic: `whileDrag: { scale: 1.05 }` un-scales at\n // release, while the position settles independently.\n setActive(\"whileDrag\", false)\n restoreBodyAndElementStyles()\n releasePointerCaptureSafely()\n\n getOpts().onDragEnd?.(event, info)\n\n // Capture refs locally — the closure clears xMV/yMV below before the\n // momentum promise can resolve, but the inertia animation needs stable\n // references through its lifetime.\n const xRef = xMV\n const yRef = yMV\n const boundsRef = sessionBounds\n const opts = getOpts()\n const snapToOrigin = opts.dragSnapToOrigin ?? false\n const momentum = opts.dragMomentum ?? true\n const userTransition = opts.dragTransition ?? {}\n\n // Axis lock: the release path must mirror the same write-gate the drag\n // loop uses (handlePan). Without this, pointer velocity on the locked\n // axis feeds an inertia animation on that axis's MV — drifting the\n // element along an axis the user explicitly locked. The cursor still\n // has Y velocity when `drag: \"x\"` (any non-perfectly-horizontal motion\n // moves the pointer through Y), so this matters in practice.\n const dragAxis = opts.drag\n const releaseX = dragAxis !== \"y\"\n const releaseY = dragAxis !== \"x\"\n\n // Reset the tracked momentum array — we'll push 1 or 2 controls below\n // depending on axis. (handlePanStart's stopMomentum already cleared any\n // prior session's controls, but we re-initialize here for clarity since\n // the per-axis branches below append rather than replace.)\n momentumControls = []\n\n // Q15c follow-up: couple bounce physics to `dragElastic`. With elastic\n // 0 (hard clamp), inertia's spring-back at the boundary uses default\n // stiffness/damping that visibly overshoots before settling — even\n // though the drag itself is clamped. Mirror motion-react's pattern\n // (VisualElementDragControls.startAnimation): overdamp the spring with\n // very high stiffness + damping so the snap-back is effectively\n // instantaneous. With elastic > 0 we keep the soft spring so the\n // rubber-band feel is preserved.\n //\n // Numerical choices (200/40 soft, 1e6/1e7 hard) come from motion-react.\n const elastic = opts.dragElastic ?? DEFAULT_ELASTIC\n const bounceParams = elastic\n ? { bounceStiffness: 200, bounceDamping: 40 }\n : { bounceStiffness: 1_000_000, bounceDamping: 10_000_000 }\n\n // Flicker fix for elastic=0: motion-react's source acknowledges that\n // overdamping the spring still computes one frame of overshoot before\n // the snap-back. When the user releases AT a boundary with velocity\n // pointing OUT of that boundary, there's nothing for inertia to\n // usefully decay toward — feeding it the outward velocity produces\n // exactly the visible flicker. Zero those release velocities and\n // inertia settles silently at the bound. Inward velocities are\n // preserved so a release moving back toward center still glides.\n const xAtMax = boundsRef !== null && boundsRef.maxX !== Infinity && xRef.get() >= boundsRef.maxX\n const xAtMin =\n boundsRef !== null && boundsRef.minX !== -Infinity && xRef.get() <= boundsRef.minX\n const yAtMax = boundsRef !== null && boundsRef.maxY !== Infinity && yRef.get() >= boundsRef.maxY\n const yAtMin =\n boundsRef !== null && boundsRef.minY !== -Infinity && yRef.get() <= boundsRef.minY\n const xVelocity =\n !elastic && ((xAtMax && info.velocity.x > 0) || (xAtMin && info.velocity.x < 0))\n ? 0\n : info.velocity.x\n const yVelocity =\n !elastic && ((yAtMax && info.velocity.y > 0) || (yAtMin && info.velocity.y < 0))\n ? 0\n : info.velocity.y\n\n /** Fire onDragTransitionEnd via getOpts so reactive callback swaps see\n * the latest value (the user may have swapped handlers between pan-end\n * and momentum-settle). */\n const fireTransitionEnd = () => getOpts().onDragTransitionEnd?.()\n\n if (snapToOrigin) {\n // Spring back to (0, 0). motion's pattern (Q15e): use the inertia\n // transition but clamp min/max to 0 so the spring physics carries\n // the value home from wherever the user released it.\n const transitionX = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: xVelocity,\n min: 0,\n max: 0,\n }\n const transitionY = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: yVelocity,\n min: 0,\n max: 0,\n }\n const settles: Array<Promise<unknown> | AnimationPlaybackControls> = []\n if (releaseX) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct. Target arg is a placeholder — inertia computes the actual settle point from velocity + min/max.\n const ctrlX = animate(xRef, 0, transitionX as any)\n momentumControls.push(ctrlX)\n settles.push(ctrlX)\n }\n if (releaseY) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct.\n const ctrlY = animate(yRef, 0, transitionY as any)\n momentumControls.push(ctrlY)\n settles.push(ctrlY)\n }\n if (settles.length > 0) Promise.all(settles).then(fireTransitionEnd)\n else fireTransitionEnd()\n } else {\n // Inertia release path — runs regardless of `dragMomentum`. When\n // momentum is true, we feed the (heuristic-clamped) release velocity\n // so the element glides naturally. When momentum is false, we feed\n // velocity 0 — there's no decay, but the bounce physics still spring\n // the element back to the bound if elastic let it overshoot during\n // the drag. Skipping the animate entirely (the prior behavior) left\n // the user stranded outside the container with no way to reach the\n // element. Matches motion-react's pattern (VisualElementDragControls\n // .startAnimation always runs inertia, zeroing velocity when\n // dragMomentum is false).\n const releaseVelocityX = momentum ? xVelocity : 0\n const releaseVelocityY = momentum ? yVelocity : 0\n const transitionX = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: releaseVelocityX,\n min: boundsRef?.minX,\n max: boundsRef?.maxX,\n }\n const transitionY = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: releaseVelocityY,\n min: boundsRef?.minY,\n max: boundsRef?.maxY,\n }\n const settles: Array<Promise<unknown> | AnimationPlaybackControls> = []\n if (releaseX) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct.\n const ctrlX = animate(xRef, 0, transitionX as any)\n momentumControls.push(ctrlX)\n settles.push(ctrlX)\n }\n if (releaseY) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct.\n const ctrlY = animate(yRef, 0, transitionY as any)\n momentumControls.push(ctrlY)\n settles.push(ctrlY)\n }\n if (settles.length > 0) Promise.all(settles).then(fireTransitionEnd)\n else fireTransitionEnd()\n }\n\n xMV = null\n yMV = null\n sessionBounds = null\n }\n\n // Function-form options so createPan reads `panThreshold` reactively.\n // Handler references are stable — only the threshold (and the wrapping\n // object) is recreated per call from createPan.\n createPan(\n () => el,\n () => ({\n threshold: getOpts().panThreshold,\n onPanStart: handlePanStart,\n onPan: handlePan,\n onPanEnd: handlePanEnd,\n }),\n )\n\n // ---------- External drag (Q9 — createDragControls integration) ----------\n // When the user wires `dragControls: someControls` into MotionOptions, an\n // external pointerdown elsewhere in the UI (a \"drag handle\" button) can\n // start a drag on this element via `controls.start(event)`. Bypasses the\n // threshold gate — the user explicitly said \"drag,\" no hysteresis needed.\n //\n // We synthesize our own pan session here rather than re-using createPan's\n // because:\n // 1. The originating element is the drag handle, not `el`. createPan's\n // pointerdown listener is bound to `el` and wouldn't see the event.\n // 2. We need to skip threshold; createPan's threshold gate is private.\n //\n // The session-tracking logic (pointerId match, sample buffer for velocity,\n // window listener attach/cleanup) is duplicated from createPan. A future\n // refactor could extract a shared \"pan session runner\" if a third caller\n // emerges; for v0.1 the duplication is contained.\n function startExternalDrag(event: PointerEvent, options: DragControlsStartOptions): void {\n if (!isDragEnabled()) return\n\n // Snap-to-cursor (Q9b): move the element so its center sits under the\n // pointer BEFORE the drag-start info captures dragStartX/Y. Otherwise\n // the offset chain would start from the original position and the\n // visible jump-to-cursor would be lost on first pointermove.\n if (options.snapToCursor) {\n const ve = ensureVisualElement(el)\n const snapXMV = ve.getValue(\"x\", 0) as MotionValue<number>\n const snapYMV = ve.getValue(\"y\", 0) as MotionValue<number>\n const elRect = el.getBoundingClientRect()\n const centerX = elRect.left + elRect.width / 2\n const centerY = elRect.top + elRect.height / 2\n const axis = getOpts().drag\n if (axis !== \"y\") snapXMV.set(snapXMV.get() + (event.clientX - centerX))\n if (axis !== \"x\") snapYMV.set(snapYMV.get() + (event.clientY - centerY))\n }\n\n // Fire handlePanStart with a synthesized initial PanInfo. This\n // initializes xMV/yMV/dragStartX/Y, resolves bounds, sets body styles,\n // captures pointer, activates whileDrag, and fires onDragStart.\n //\n // `mvIsAuthoritative=true` when the snap path just wrote the MVs\n // above — handlePanStart should read FROM the MV (not from\n // getComputedStyle) because motion-dom's writer is frame-scheduled\n // and `el.style.transform` may not yet reflect the snap write.\n const initialInfo: PanInfo = {\n point: { x: event.clientX, y: event.clientY },\n delta: { x: 0, y: 0 },\n offset: { x: 0, y: 0 },\n velocity: { x: 0, y: 0 },\n }\n handlePanStart(event, initialInfo, Boolean(options.snapToCursor))\n\n // Track the session locally — these would normally live inside\n // createPan's closure. Velocity samples use motion-dom's `time.now()`\n // to stay frame-synchronous with the rest of the pipeline.\n const sessionStartPoint = { x: event.clientX, y: event.clientY }\n let sessionLastPoint = { ...sessionStartPoint }\n const sessionPointerId = event.pointerId\n const sessionSamples: Array<{ t: number; point: { x: number; y: number } }> = [\n { t: time.now(), point: { ...sessionStartPoint } },\n ]\n\n function computeSessionVelocity(): { x: number; y: number } {\n if (sessionSamples.length < 2) return { x: 0, y: 0 }\n const first = sessionSamples[0]\n const last = sessionSamples[sessionSamples.length - 1]\n if (!first || !last) return { x: 0, y: 0 }\n const dt = last.t - first.t\n if (dt <= 0) return { x: 0, y: 0 }\n return {\n x: ((last.point.x - first.point.x) / dt) * 1000,\n y: ((last.point.y - first.point.y) / dt) * 1000,\n }\n }\n\n function buildSessionInfo(e: PointerEvent): PanInfo {\n const point = { x: e.clientX, y: e.clientY }\n return {\n point,\n delta: { x: point.x - sessionLastPoint.x, y: point.y - sessionLastPoint.y },\n offset: { x: point.x - sessionStartPoint.x, y: point.y - sessionStartPoint.y },\n velocity: computeSessionVelocity(),\n }\n }\n\n function onSessionMove(e: PointerEvent): void {\n if (e.pointerId !== sessionPointerId) return\n const point = { x: e.clientX, y: e.clientY }\n const now = time.now()\n sessionSamples.push({ t: now, point })\n const cutoff = now - 200\n while (sessionSamples.length > 1 && (sessionSamples[0]?.t ?? 0) < cutoff) {\n sessionSamples.shift()\n }\n const info = buildSessionInfo(e)\n sessionLastPoint = point\n handlePan(e, info)\n }\n\n function onSessionEnd(e: PointerEvent): void {\n if (e.pointerId !== sessionPointerId) return\n const info = buildSessionInfo(e)\n handlePanEnd(e, info)\n window.removeEventListener(\"pointermove\", onSessionMove)\n window.removeEventListener(\"pointerup\", onSessionEnd)\n window.removeEventListener(\"pointercancel\", onSessionEnd)\n }\n\n window.addEventListener(\"pointermove\", onSessionMove)\n window.addEventListener(\"pointerup\", onSessionEnd)\n window.addEventListener(\"pointercancel\", onSessionEnd)\n }\n\n // Register with the controls instance whenever opts.dragControls changes.\n // createEffect re-runs on swap; the previous registration unmounts via\n // the symbol-keyed unregister function. Q9d — last mount wins; the\n // unregister only nulls out if we're still the active handler.\n createEffect(() => {\n const controls = getOpts().dragControls as DragControls | undefined\n if (!controls) return\n const internal = controls as DragControls & {\n [DRAG_CONTROLS_REGISTER]?: (\n handler: (event: PointerEvent, options: DragControlsStartOptions) => void,\n ) => () => void\n }\n const register = internal[DRAG_CONTROLS_REGISTER]\n if (!register) return\n const unregister = register(startExternalDrag)\n onCleanup(unregister)\n })\n\n // Owner-disposal cleanup. Three layers:\n // 1. Stop any settling momentum animations (they hold MV references that\n // keep ticking after disposal otherwise).\n // 2. Restore the body/touch styles if we're in mid-drag.\n // 3. Release any captured pointer.\n // createPan's own onCleanup handles removing its listeners separately.\n onCleanup(() => {\n stopMomentum()\n if (xMV || yMV) {\n restoreBodyAndElementStyles()\n releasePointerCaptureSafely()\n }\n })\n}\n","import { type Accessor, createEffect, createSignal, onCleanup } from \"solid-js\"\nimport type { ViewportOptions } from \"../types\"\n\n// ---------------------------------------------------------------------------\n// createInView — observe an element's intersection with a viewport.\n//\n// Standalone hook, distinct from the `inView` *gesture* on MotionOptions\n// (which animates a target when in view). Returns a pair of Solid Accessors\n// for the boolean and the raw IntersectionObserverEntry — booleans and\n// objects aren't animate-able, so a MotionValueAccessor would only add weight\n// (compare with createPan, where numeric fields ARE MVs because they're\n// animate-able and composable).\n// ---------------------------------------------------------------------------\n\nexport type CreateInViewOptions = ViewportOptions & {\n /**\n * Fires with the raw {@link IntersectionObserverEntry} on every\n * visibility transition (enter AND leave). Convenience hook for callers\n * who prefer event-driven access to the entry — the entry is also\n * available reactively via the returned `view.entry()` accessor.\n */\n onChange?: (entry: IntersectionObserverEntry) => void\n}\n\n/** Returned by {@link createInView}. Two Solid Accessors — call them to track. */\nexport type CreateInViewResult = {\n /** Solid Accessor; `true` while the element intersects the viewport per the configured threshold. */\n isInView: Accessor<boolean>\n /** Solid Accessor; the most recent {@link IntersectionObserverEntry}, or `null` before any. */\n entry: Accessor<IntersectionObserverEntry | null>\n}\n\n/**\n * Observe an element via {@link IntersectionObserver} and expose its\n * in-view state as a pair of Solid Accessors.\n *\n * Pass a ref-style accessor that returns the element. The observer\n * attaches once the accessor returns a non-null element and re-attaches\n * if it changes. The observer is disconnected on owner disposal.\n *\n * Options can be a static object or a function form (matching `useMotion`\n * and `createPan`'s convention). The function form is tracked inside the\n * effect — option changes (e.g., switching `root`) re-attach the observer.\n *\n * @example Static options\n * const [el, setEl] = createSignal<HTMLElement>()\n * const view = createInView(el, { once: true })\n * createEffect(() => {\n * if (view.isInView()) console.log(\"now in view\")\n * })\n *\n * @example Function-form options (reactive)\n * const [root, setRoot] = createSignal<HTMLElement>()\n * const view = createInView(el, () => ({ root, margin: \"100px\" }))\n *\n * @example Reading the raw entry reactively\n * const view = createInView(el)\n * createEffect(() => {\n * const e = view.entry()\n * if (e) console.log(\"ratio:\", e.intersectionRatio)\n * })\n *\n * <div ref={setEl}>watch me</div>\n */\nexport function createInView(\n ref: () => Element | null | undefined,\n options: CreateInViewOptions | (() => CreateInViewOptions) = {},\n): CreateInViewResult {\n const [isInView, setIsInView] = createSignal(false)\n const [entry, setEntry] = createSignal<IntersectionObserverEntry | null>(null)\n\n // createEffect — Solid-idiomatic for side-effect setup (attaching the\n // IntersectionObserver). First iteration runs in the next microtask,\n // which is harmless: a freshly-mounted element can't be in or out of\n // the viewport before the microtask flushes. Option reads inside the\n // effect's body are tracked — function-form options that read signals\n // will re-run the effect (and re-attach the observer) on change.\n createEffect(() => {\n const el = ref()\n if (!el) return\n const opts = typeof options === \"function\" ? options() : options\n\n const threshold = resolveThreshold(opts.amount)\n const observer = new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n // Fire onChange first so callers can synchronously inspect the\n // entry before any downstream signal-effects see the new state.\n opts.onChange?.(e)\n // Update the entry signal either way — consumers reading\n // `view.entry()` reactively see both enter and leave.\n setEntry(e)\n if (e.isIntersecting) {\n setIsInView(true)\n if (opts.once) observer.disconnect()\n } else if (!opts.once) {\n setIsInView(false)\n }\n }\n },\n {\n root: opts.root?.() ?? null,\n rootMargin: opts.margin ?? \"0px\",\n threshold,\n },\n )\n observer.observe(el)\n\n onCleanup(() => observer.disconnect())\n })\n\n return { isInView, entry }\n}\n\nfunction resolveThreshold(amount: ViewportOptions[\"amount\"]): number | number[] {\n // Pass arrays through unchanged so callers can request continuous\n // `intersectionRatio` updates (the underlying IntersectionObserver fires\n // once per threshold crossing, so a fine array → near-live ratio).\n if (Array.isArray(amount)) return amount\n if (typeof amount === \"number\") return amount\n if (amount === \"all\") return 1\n // \"some\" or undefined → minimal threshold (any pixel intersecting)\n return 0\n}\n","import { addDomEvent, hover, press } from \"motion-dom\"\nimport { createEffect, onCleanup } from \"solid-js\"\nimport type { MotionElement, MotionOptions } from \"../types\"\nimport { createInView } from \"./createInView\"\nimport type { SetActive } from \"./gesture-state\"\n\n// ---------------------------------------------------------------------------\n// createGestures — wires pointer-driven gestures (hover, press, focus, inView)\n// to the gesture state machine's `setActive`. Phase 2 Commit 2 wires hover and\n// press only; focus and inView land in Commit 3.\n//\n// Q1/C — hover and press are routed through motion-dom's primitives directly,\n// not re-implemented. ADR 0001 documents the dependency.\n//\n// Q13/a — listeners attach unconditionally on mount and clean up on owner\n// disposal. We do NOT re-attach when `opts.hover` / `opts.press` flip between\n// defined and undefined: the state machine's per-key winners memo naturally\n// produces an empty diff when an active state has no target, so the extra\n// DOM listener pair costs nothing in practice.\n// ---------------------------------------------------------------------------\n\n/**\n * Bind pointer-event-driven gestures (hover, press) to the motion element.\n * Toggles the state machine's `whileHover` / `whilePress` flags and forwards\n * events to the user's `MotionCallbacks`.\n */\nexport function createGestures(\n el: MotionElement,\n getOpts: () => MotionOptions,\n setActive: SetActive,\n): void {\n // ---------- Hover ----------\n // motion-dom's hover(): start callback shape is `(element, event) => onEnd?`.\n // We ignore `element` (always equal to `el` since we pass the element rather\n // than a selector). The optional returned function fires on hover-end.\n //\n // Why motion-dom's hover() rather than addEventListener(\"pointerenter\")?\n // Subtle behaviors handled inside motion-dom we'd otherwise re-derive:\n // - Press-in-progress defers hover-end until pointer-up (mobile UX).\n // - Secondary pointer events filtered via isPrimaryPointer.\n // - pointercancel cleanup parallel to pointerup.\n const stopHover = hover(el, (_element, event) => {\n setActive(\"whileHover\", true)\n getOpts().onHoverStart?.(event)\n return (event) => {\n setActive(\"whileHover\", false)\n getOpts().onHoverEnd?.(event)\n }\n })\n onCleanup(stopHover)\n\n // ---------- Press ----------\n // motion-dom's press(): same callback shape, plus the end callback receives\n // `(event, { success: boolean })`. `success === true` when the pointer was\n // still over the element at pointer-up (completed press); `false` when it\n // moved away or was cancelled.\n //\n // Q13/c — branch on `info.success`:\n // onPressStart fires at pointerdown (no success info yet — Q13 tightened\n // the signature to drop the info param).\n // onPress fires on completed press.\n // onPressCancel fires on aborted press.\n const stopPress = press(el, (_element, event) => {\n setActive(\"whilePress\", true)\n getOpts().onPressStart?.(event)\n return (event, info) => {\n setActive(\"whilePress\", false)\n if (info.success) {\n getOpts().onPress?.(event, info)\n } else {\n getOpts().onPressCancel?.(event, info)\n }\n }\n })\n onCleanup(stopPress)\n\n // ---------- Focus (Q12) ----------\n // Activation (`whileFocus` state) is gated by `:focus-visible` — mouse\n // clicks that incidentally focus an element should NOT trigger the visual\n // state, only keyboard navigation does. The native `onFocus`/`onBlur`\n // callbacks fire for every focus event regardless (Q12b — programmatic\n // listeners shouldn't be filtered).\n //\n // The `:focus-visible` selector throws in older browsers — we fall back\n // to always-active, matching motion/react's behavior in that scenario.\n //\n // We use motion-dom's `addDomEvent` (rather than el.addEventListener\n // directly) for consistency with the rest of Phase 2's motion-dom usage,\n // and because it returns a tidy cleanup function we can hand to onCleanup.\n let focusActiveByVisible = false\n const stopFocus = addDomEvent(el, \"focus\", (event) => {\n let isFocusVisible = false\n try {\n isFocusVisible = el.matches(\":focus-visible\")\n } catch {\n isFocusVisible = true\n }\n if (isFocusVisible) {\n setActive(\"whileFocus\", true)\n focusActiveByVisible = true\n }\n getOpts().onFocus?.(event as FocusEvent)\n })\n const stopBlur = addDomEvent(el, \"blur\", (event) => {\n if (focusActiveByVisible) {\n setActive(\"whileFocus\", false)\n focusActiveByVisible = false\n }\n getOpts().onBlur?.(event as FocusEvent)\n })\n onCleanup(stopFocus)\n onCleanup(stopBlur)\n\n // ---------- inView (Q10/A1) ----------\n // The gesture reuses `createInView` — same observer setup. The `onChange`\n // merges into the options object so the gesture's onViewportEnter/Leave\n // hooks receive the raw entry.\n //\n // The element is wrapped in `() => el` because createInView takes a ref\n // accessor; we pass a constant accessor since `el` is fixed for the\n // gesture's lifetime. The options are function-form so reactive\n // inViewOptions changes (e.g., a reactive `root` accessor) re-attach\n // the observer naturally.\n //\n // A createEffect bridges createInView's `isInView` Accessor to the state\n // machine's setActive. When `once: true`, createInView keeps isInView=true\n // after first intersection (observer disconnected); the gesture's\n // whileInView stays active forever — motion/react parity.\n const view = createInView(\n () => el,\n () => ({\n ...getOpts().inViewOptions,\n onChange: (entry: IntersectionObserverEntry) => {\n if (entry.isIntersecting) {\n getOpts().onViewportEnter?.(entry)\n } else {\n getOpts().onViewportLeave?.(entry)\n }\n },\n }),\n )\n createEffect(() => {\n setActive(\"whileInView\", view.isInView())\n })\n}\n","// ---------------------------------------------------------------------------\n// Default value table for transform-class and a few well-known CSS properties.\n// Used by the gesture state machine's \"removed keys\" fallback (Q7): when a\n// higher-priority gesture deactivates and no lower-priority state defines a\n// key, we animate the key back to:\n// 1. the user's `initial` target (captured at mount) — handled at call site\n// 2. otherwise the value from this table\n// 3. otherwise `null` (motion's animate() reads from computed style)\n//\n// The values here mirror motion-dom's conventions (scale → 1, x/y/z → 0,\n// rotate/skew → 0, opacity → 1). We don't import motion-dom's defaultValueTypes\n// directly because (a) it's a value-type system, not a defaults table, and\n// (b) keeping a stable local source insulates us from motion-dom internal churn.\n// ---------------------------------------------------------------------------\n\nconst TRANSFORM_DEFAULTS: Readonly<Record<string, number>> = {\n // Translate\n x: 0,\n y: 0,\n z: 0,\n translateX: 0,\n translateY: 0,\n translateZ: 0,\n // Scale (multiplicative identity)\n scale: 1,\n scaleX: 1,\n scaleY: 1,\n scaleZ: 1,\n // Rotate\n rotate: 0,\n rotateX: 0,\n rotateY: 0,\n rotateZ: 0,\n // Skew\n skew: 0,\n skewX: 0,\n skewY: 0,\n // Perspective\n perspective: 0,\n transformPerspective: 0,\n // Opacity (the one non-transform key with a strong default)\n opacity: 1,\n}\n\n/**\n * Look up the canonical fallback value for a property key. Returns the table\n * value if known, else `null` — which motion's `animate()` interprets as\n * \"read from computed style at animation start.\"\n */\nexport function getMotionDefault(key: string): number | null {\n return TRANSFORM_DEFAULTS[key] ?? null\n}\n","import { type AnimationPlaybackControls, animate, isMotionValue, type MotionValue } from \"motion\"\nimport { type Accessor, createEffect, createMemo, onCleanup, untrack } from \"solid-js\"\nimport { createStore, type SetStoreFunction, type Store } from \"solid-js/store\"\nimport { getMotionDefault } from \"../default-values\"\nimport { shouldReduceMotion } from \"../reduced-motion\"\nimport type {\n AnimateValue,\n MotionConfigContextValue,\n MotionElement,\n MotionOptions,\n ResolvedValues,\n Target,\n Transition,\n VariantContextValue,\n} from \"../types\"\nimport { asVariantLabels, mergeTransition, resolveTarget } from \"./createMotion\"\n\n// ---------------------------------------------------------------------------\n// Solid-native fine-grained gesture state machine (ADR 0002).\n//\n// Implements three of the four jobs motion's createAnimationState handles:\n// 1. Priority resolution — high-to-low among active states\n// 2. Per-key handoff — when a higher-priority state deactivates, lower-priority\n// states (or fallbacks) take over each key it was animating\n// 3. Variant resolution — reuses Phase 1's resolveTarget for label→Target lookup\n//\n// Job 4 (parent-child variant inheritance via variantChildren) is handled\n// reactively through Phase 1's VariantContext + Q4's active-gated label slots,\n// NOT via this state machine — keeping the inheritance tree Solid-owned.\n// ---------------------------------------------------------------------------\n\n/** State names, ordered low → high priority. Matches motion-dom's variantPriorityOrder. */\nconst STATE_NAMES = [\n \"animate\",\n \"whileInView\",\n \"whileHover\",\n \"whilePress\",\n \"whileFocus\",\n \"whileDrag\",\n \"exit\",\n] as const\n\nexport type GestureStateName = (typeof STATE_NAMES)[number]\n\n/** High → low priority for the winners walk. Materialized once. */\nconst PRIORITY_HIGH_TO_LOW: readonly GestureStateName[] = [...STATE_NAMES].reverse()\n\n/** A key's resolved value plus the (optional) per-target transition that produced it. */\ntype WinnerEntry = {\n value: unknown\n transition: Transition | undefined\n /** Which state contributed this key — used by the diff effect's onAnimationComplete bookkeeping. */\n stateName: GestureStateName\n}\n\nexport type SetActive = (state: GestureStateName, isActive: boolean) => void\n\n/** The reactive store of active gesture flags, lifted to the caller for sharing. */\nexport type ActiveStore = Store<Record<GestureStateName, boolean>>\nexport type SetActiveStore = SetStoreFunction<Record<GestureStateName, boolean>>\nexport type ActiveStoreTuple = [ActiveStore, SetActiveStore]\n\nexport type CreateGestureStateMachineDeps = {\n el: MotionElement\n getOpts: () => MotionOptions\n parentVariantCtx: VariantContextValue\n motionConfig: MotionConfigContextValue\n systemReducedMotion: Accessor<boolean>\n /** Captured at construction. Used as the first stop in the removed-key fallback chain (Q7). */\n initialTarget: Target | null\n /**\n * Optional external active store (Q4 — useMotion lifts this up so its\n * `myVariantCtx` can read the same flags it propagates to descendants).\n * When omitted, the state machine creates its own internal store —\n * backward-compatible for `createMotion` direct users.\n */\n externalActiveStore?: ActiveStoreTuple\n /**\n * Phase 3 — when an enclosing `<Presence initial={false}>` is active, this\n * is passed through to suppress the first-mount animate (mirrors the\n * existing `initial: false` user-opt-out, but driven from above by\n * Presence instead of by the user's own options).\n */\n suppressFirstMount?: boolean\n /**\n * Phase 3 — readiness gate for the first-mount animate when this motion\n * element is wrapped in a real `<Presence>`. The state machine reads this\n * on each iteration; when it's `false` AND we haven't run yet, the diff\n * effect short-circuits (no animate dispatch, no MV subscriptions sealed).\n * Presence flips it to `true` from its `onEnter` / `onChange.added`\n * callback, at which point the effect re-runs and treats THAT iteration\n * as the first.\n *\n * Outside a Presence (no-op default context), createMotion leaves this\n * `undefined` — the state machine treats absence as `ready=true` and the\n * existing eager-first-iteration behavior is unchanged.\n *\n * Rationale: real `motion.animate()` is a Web Animations API call that\n * runs even on a disconnected element, but its terminal `commitStyles`\n * silently no-ops when the element is off-DOM. For a `mode: \"wait\"` swap\n * the new child is created BEFORE the old child's exit completes, so\n * dispatching the first animate eagerly would let it complete in the\n * detached state and the element would paint at its `initial` target\n * when it finally enters the DOM. Deferring until `onEnter` (when\n * transition-group has synchronously inserted the element via\n * `setReturned`) closes that gap.\n */\n enterReady?: Accessor<boolean>\n /**\n * MV-in-style Stage 3 bridge. When provided, the diff effect calls this\n * per animate-target key. A returned `MotionValue` routes the animation\n * through that MV (`animate(mv, value, opts)`) — its change-subscription\n * (in createMotion) composes `el.style` from the registry. `undefined`\n * routes the key down the existing `animate(el, target, opts)` WAA path.\n *\n * createMotion only activates this when at least one external MV is\n * registered (i.e., the user supplied `style: { scale: mv }`-shaped\n * options). Inactive in the common case → 293 baseline tests stay on\n * the original code path, their animateSpy assertions unaffected.\n */\n getValueForAnimate?: (key: string, fallback: unknown) => MotionValue<unknown> | undefined\n}\n\nexport type GestureStateMachine = {\n /** Imperatively toggle a gesture state. Triggers re-resolution + animate(). */\n setActive: SetActive\n /**\n * Resolves when the next animate dispatched while `exit` is the highest-\n * priority active driver state completes. If no exit animation is in\n * flight AND no exit target is defined, resolves immediately.\n *\n * Used by `createMotion`'s presence registration: the registered\n * `runExit` callable does `setActive(\"exit\", true)` then awaits this.\n * When the exit animation settles, `<Presence>` (or the hook) gets a\n * resolved Promise and proceeds with DOM removal.\n *\n * Multiple concurrent waiters are supported — they all resolve from the\n * same animation's completion.\n */\n onceExitComplete: () => Promise<void>\n}\n\n/**\n * Construct the per-element gesture state machine.\n *\n * Wired primitives:\n * - `createStore` for the seven active flags — Solid tracks per-path, so\n * toggling `whileHover` doesn't dirty memos reading `whilePress`.\n * - `createMemo` for `stateTargets` — cached, re-runs only when opts/parent\n * context change.\n * - `createMemo` for `winners` — same caching, re-runs when `active` flags or\n * `stateTargets` change.\n * - `createEffect` for the diff-and-animate loop — fires on `winners` change;\n * compares against `lastApplied` to compute changed/removed keys.\n * - `onCleanup` inside the effect for per-iteration MV subscriptions — scoped\n * to each effect run (fires on re-run AND owner disposal). Same iteration-\n * scoped cleanup pattern Phase 1 established.\n */\nexport function createGestureStateMachine(\n deps: CreateGestureStateMachineDeps,\n): GestureStateMachine {\n const {\n el,\n getOpts,\n parentVariantCtx,\n motionConfig,\n systemReducedMotion,\n initialTarget,\n externalActiveStore,\n suppressFirstMount,\n enterReady,\n getValueForAnimate,\n } = deps\n\n // ---------- Active flags ----------\n // `animate` defaults true: it's the baseline state (mirrors motion's\n // createTypeState(true) for animate). All other states start inactive.\n // If the caller provided an external store (Q4 — useMotion lifts this up\n // so myVariantCtx can read the same flags), reuse it; else create our own.\n const [active, setActiveStore] =\n externalActiveStore ??\n createStore<Record<GestureStateName, boolean>>({\n animate: true,\n whileInView: false,\n whileHover: false,\n whilePress: false,\n whileFocus: false,\n whileDrag: false,\n exit: false,\n })\n\n // ---------- Per-state resolved targets ----------\n // createMemo (not createComputed): reads only run when opts/parent change,\n // and the value is cached for downstream consumers. The animate call is\n // frame-async tolerant — the side-effect createEffect below handles timing.\n const stateTargets = createMemo<Record<GestureStateName, Target | null>>(() => {\n const opts = getOpts()\n const variants = opts.variants\n const custom = opts.custom ?? parentVariantCtx.custom?.()\n return {\n animate: resolveTarget(\n opts.animate,\n variants,\n asVariantLabels(parentVariantCtx.animate?.()),\n custom,\n ),\n whileInView: resolveTarget(\n opts.inView,\n variants,\n asVariantLabels(parentVariantCtx.inView?.()),\n custom,\n ),\n whileHover: resolveTarget(\n opts.hover,\n variants,\n asVariantLabels(parentVariantCtx.hover?.()),\n custom,\n ),\n whilePress: resolveTarget(\n opts.press,\n variants,\n asVariantLabels(parentVariantCtx.press?.()),\n custom,\n ),\n whileFocus: resolveTarget(\n opts.focus,\n variants,\n asVariantLabels(parentVariantCtx.focus?.()),\n custom,\n ),\n // whileDrag — resolved like any other gesture state's target. Drag's\n // visual state composes with drag's translation through the shared\n // VisualElement (Q5/C-lean).\n whileDrag: resolveTarget(opts.whileDrag, variants, undefined, custom),\n exit: resolveTarget(opts.exit, variants, asVariantLabels(parentVariantCtx.exit?.()), custom),\n }\n })\n\n // ---------- Per-key winners (priority resolution + per-key claim) ----------\n // Walks PRIORITY_HIGH_TO_LOW. A state is considered active if EITHER its\n // own flag is true OR the parent's VariantContext provides a label for it\n // (Q4 — gesture inheritance through context). The first active state that\n // defines a key claims it; lower-priority states are skipped for that key.\n //\n // Q5/C-lean exclusion: while drag is ACTIVE (pointer engaged), `x` and `y`\n // are owned by\n // createDrag (it writes them to the VisualElement's MotionValues during\n // pointer phase). Filter them out of the winners map so motion's animate\n // (called from this effect) doesn't fight drag's writes. Other transform\n // keys (scale, rotate, etc.) still flow normally — they compose with\n // drag's translation through the shared VisualElement.\n //\n // EXCEPTION: when `exit` is active, exit's x/y MUST override drag's claim.\n // Otherwise an element being dragged at the moment of unmount would\n // exit-animate without translation (drag would silently win every frame),\n // which contradicts the priority chain's stated semantic (exit is highest).\n // Drag's pointer listeners will release anyway when the element unmounts;\n // exit's translation reaches DOM until that happens.\n const winners = createMemo<Record<string, WinnerEntry>>(() => {\n const targets = stateTargets()\n // Drag claims x/y only while the user is ACTIVELY dragging (pointer\n // engaged → `active.whileDrag === true`). When drag is merely\n // configured-but-idle, initial/animate/exit and other states get\n // normal access to x/y — matching motion-react. Reading from `active`\n // tracks the store; the winners memo re-runs when whileDrag flips.\n const dragActive = active.whileDrag\n const out: Record<string, WinnerEntry> = {}\n for (const stateName of PRIORITY_HIGH_TO_LOW) {\n if (!isStateActive(stateName, active, parentVariantCtx)) continue\n const target = targets[stateName]\n if (!target) continue\n for (const key in target) {\n // `transition` is animation config, not a style key — never a winner.\n if (key === \"transition\") continue\n // Higher-priority state already won this key.\n if (key in out) continue\n // x/y are drag-owned during active drag — unless exit is also\n // active, in which case exit's translation wins.\n if (!active.exit && dragActive && (key === \"x\" || key === \"y\")) continue\n out[key] = {\n value: (target as Record<string, unknown>)[key],\n transition: target.transition,\n stateName,\n }\n }\n }\n return out\n })\n\n // ---------- Diff-and-animate effect ----------\n // The single site that calls motion's animate(). Diffs winners against\n // lastApplied to compute changed keys (a) and removed keys (b). Removed keys\n // walk Q7's fallback chain: initial → motion default → null.\n let prevControls: AnimationPlaybackControls | null = null\n let lastApplied: Record<string, unknown> = {}\n let isFirstRun = true\n\n // ---------- onceExitComplete plumbing (Phase 3 — Presence integration) ----------\n // Resolvers queued by `onceExitComplete()` waiters. Drain happens when an\n // exit-driven animate dispatched from this effect resolves. Multiple waiters\n // for the same exit batch all resolve from one drain.\n let pendingExitResolvers: Array<() => void> = []\n function drainPendingExitResolvers(): void {\n const resolvers = pendingExitResolvers\n pendingExitResolvers = []\n for (const r of resolvers) r()\n }\n\n createEffect(() => {\n const next = winners()\n const opts = getOpts()\n\n // Presence-aware readiness gate: when the surrounding `<Presence>` is\n // still holding this element off-DOM (the new child during a mode=\"wait\"\n // swap, or the initial child before appear's enterTransition runs),\n // we MUST NOT dispatch the first animate. Web Animations API will run\n // it to completion off-DOM, then silently drop the final commitStyles —\n // the element would paint at its `initial` target when it eventually\n // enters the DOM. Skip the entire iteration (winners() above subscribed\n // us to future changes); when Presence flips enterReady this effect\n // re-runs and the iteration below treats THAT pass as the first.\n if (isFirstRun && enterReady && !enterReady()) {\n return\n }\n\n // First-mount guard: either the user opted out via `initial: false` OR\n // an enclosing `<Presence initial={false}>` propagated suppression via\n // `suppressFirstMount`. Either path seeds lastApplied so the next\n // iteration treats current winners as already-applied. We fall through\n // to the MV subscription loop so subsequent MV.set() drives animate.\n let skipAnimate = false\n if (isFirstRun && (untrack(() => opts.initial) === false || suppressFirstMount)) {\n lastApplied = snapshotValues(next)\n skipAnimate = true\n }\n isFirstRun = false\n\n // Bail out completely only when there is nothing to do AND nothing has\n // been applied yet (no lastApplied to revert). The previous version of\n // this guard also bailed when `next` was empty even if lastApplied still\n // held values from a previous gesture — preventing the removed-key\n // fallback from reverting. The looser condition keeps the same early-out\n // for the initial idle case while letting deactivation reverts run.\n const bailOnNoTarget =\n !skipAnimate &&\n Object.keys(next).length === 0 &&\n Object.keys(lastApplied).length === 0 &&\n opts.animate === undefined &&\n parentVariantCtx.animate?.() === undefined\n if (bailOnNoTarget) return\n\n // Compute changes: (a) keys with new/changed values, (b) removed keys.\n const changes: Record<string, unknown> = {}\n let mergedPerTargetTransition: Transition | undefined\n\n if (!skipAnimate) {\n for (const key in next) {\n const entry = next[key]\n // `noUncheckedIndexedAccess` widens record reads to `T | undefined`,\n // but `for (key in obj)` only yields present keys — entry is real.\n if (!entry) continue\n if (lastApplied[key] !== entry.value) {\n changes[key] = entry.value\n // First non-undefined per-target transition wins. (If multiple winners\n // contribute conflicting transitions, the highest-priority one already\n // took precedence in the priority walk.)\n mergedPerTargetTransition ??= entry.transition\n }\n }\n for (const key in lastApplied) {\n if (key in next) continue\n // x/y aren't \"removed\" when drag is active — drag is CLAIMING them.\n // Falling back to initial here would dispatch animate(el, {x:-W})\n // on pointerdown and snap the element back to its initial state\n // before the user's first move could reach the DOM.\n if (active.whileDrag && (key === \"x\" || key === \"y\")) continue\n // Removed-key fallback: own initial → motion default → null.\n const initialValue =\n initialTarget && key in (initialTarget as Record<string, unknown>)\n ? (initialTarget as Record<string, unknown>)[key]\n : undefined\n changes[key] = initialValue !== undefined ? initialValue : getMotionDefault(key)\n }\n }\n\n // Transition merge: MotionConfig default < user's transition < per-target\n // transition < reduced-motion override (Phase 1's mergeTransition).\n const reduced = shouldReduceMotion(motionConfig.reducedMotion(), systemReducedMotion())\n const transition = mergeTransition(\n motionConfig.transition(),\n opts.transition,\n mergedPerTargetTransition,\n reduced,\n )\n\n // Track which animate value triggered this — used by onAnimationComplete.\n // If `next` has any key from `animate` state, the effective value is opts.animate.\n // If only gesture states are active, the highest-priority active state's value drives.\n const driverState = highestActiveDriverState(next)\n const effectiveAnimateValue = animateValueForState(driverState, opts, parentVariantCtx)\n\n // Animate options builder — read at fire-time so reactive callback swaps\n // apply between calls (per Phase 1 semantics). Closed over by the\n // MV-on-change subscriptions below as well as the diff dispatch.\n const buildAnimateOptions = () => ({\n ...transition,\n onPlay: opts.onAnimationStart ? () => untrack(() => opts.onAnimationStart?.()) : undefined,\n onComplete: opts.onAnimationComplete\n ? () =>\n untrack(() => {\n if (effectiveAnimateValue != null) {\n opts.onAnimationComplete?.(effectiveAnimateValue)\n }\n })\n : undefined,\n onStop: opts.onAnimationCancel ? () => untrack(() => opts.onAnimationCancel?.()) : undefined,\n onUpdate: opts.onUpdate\n ? (latest: ResolvedValues) => untrack(() => opts.onUpdate?.(latest))\n : undefined,\n })\n\n if (!skipAnimate && Object.keys(changes).length > 0) {\n // Update lastApplied to the new winner snapshot (NOT including removed-\n // key fallback values — those become \"applied\" only after the animation\n // lands, but tracking that requires onUpdate plumbing. For diff purposes,\n // we consider them applied immediately; if the user re-activates a state\n // that brings the key back, the diff sees `lastApplied[key] = fallback`\n // vs `next[key] = newValue` and animates correctly).\n lastApplied = { ...lastApplied, ...changes }\n // Then drop keys that don't appear in `next` from lastApplied so future\n // re-removals don't compare against stale fallback values.\n for (const key in lastApplied) {\n if (!(key in next) && !(key in changes)) delete lastApplied[key]\n }\n\n // ---------- splitTarget: separate MotionValue refs from plain values ----------\n // Preserved from Phase 1: motion's vanilla animate(el, target) doesn't\n // subscribe to MotionValue refs in target values. We split and seed the\n // animate call with snapshots; per-MV subscription happens below.\n const { plain } = splitTarget(changes)\n\n // ---------- Stage 3 bridge: split `plain` by routing destination ----------\n // When createMotion's `getValueForAnimate` returns an MV for a key, the\n // tween runs against that MV (transient or external) and the registry's\n // writer composes el.style.transform. When it returns undefined (the\n // common case — no style MVs), the key falls through to the existing\n // `animate(el, target, opts)` WAA path. With NO routed keys, we make a\n // single WAA call exactly like before, preserving the call shape that\n // baseline tests assert against.\n const routed: Array<{ mv: MotionValue<unknown>; value: unknown }> = []\n const waaPlain: Record<string, unknown> = {}\n for (const key in plain) {\n const value = plain[key]\n const fallback =\n initialTarget && key in (initialTarget as Record<string, unknown>)\n ? (initialTarget as Record<string, unknown>)[key]\n : getMotionDefault(key)\n const routedMV = getValueForAnimate?.(key, fallback)\n if (routedMV) {\n routed.push({ mv: routedMV, value })\n } else {\n waaPlain[key] = value\n }\n }\n\n // Cancel any in-flight animation before kicking off the next one.\n prevControls?.stop()\n const animOpts = buildAnimateOptions()\n if (routed.length === 0) {\n // Pure WAA path — identical to the pre-Stage-3 behavior.\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape we can't tighten generically; the runtime call is correct.\n prevControls = animate(el, waaPlain as any, animOpts)\n } else {\n // Bridge path — one tween per routed MV plus (optionally) a single\n // WAA call for non-routed keys. `aggregateControls` combines them\n // into a thenable that .stop()s each and resolves when all settle,\n // so the exit-drain logic below works uniformly across both shapes.\n const controls: AnimationPlaybackControls[] = []\n for (const { mv, value } of routed) {\n // biome-ignore lint/suspicious/noExplicitAny: same as above\n controls.push(animate(mv as any, value as any, animOpts as any))\n }\n if (Object.keys(waaPlain).length > 0) {\n // biome-ignore lint/suspicious/noExplicitAny: same as above\n controls.push(animate(el, waaPlain as any, animOpts))\n }\n prevControls = aggregateControls(controls)\n }\n\n // Drain `onceExitComplete()` waiters when this dispatch is driven by\n // the exit state — i.e., Presence is awaiting the unmount animation.\n // motion's AnimationPlaybackControls is thenable at runtime (motion\n // returns a thenable handle) but the public type doesn't surface\n // `.then` — narrow via PromiseLike. The promise settles on natural\n // completion OR cancellation (`.stop()` from a subsequent effect\n // run). Both should drain — from the caller's perspective the exit\n // animation is \"done\" either way. The freshness check ensures a stale\n // dispatch doesn't drain a newer animation's waiters.\n if (driverState === \"exit\") {\n const dispatched = prevControls\n const thenable = dispatched as unknown as PromiseLike<unknown>\n thenable.then(() => {\n if (prevControls === dispatched) drainPendingExitResolvers()\n })\n }\n } else if (driverState === \"exit\") {\n // Exit is the driver but no animate ran (target absent or no key diff).\n // Drain immediately so any awaiting `runExit` callers don't hang.\n drainPendingExitResolvers()\n }\n\n // ---------- MotionValue-in-target subscriptions ----------\n // Walk `next` (the FULL winner set) rather than `changes` (the diff) and\n // subscribe a per-key animate callback to each MV's `change` event. This\n // loop runs on EVERY effect iteration that gets past the bailOnNoTarget\n // guard above, including iterations that produced no diff.\n //\n // Bug fix: previously this loop lived inside the \"has changes\" branch.\n // Sibling effects in createGestures (notably the inView wiring's\n // setActive call after IntersectionObserver's first emission) can\n // invalidate the winners memo without changing any actual value. On\n // those re-runs, the iteration-scoped `onCleanup` from the prior run\n // unsubscribed the MV listeners and we never reattached, dropping all\n // future MV.set() → animate plumbing. Walking `next` here keeps the\n // subscriptions in lockstep with the effect's lifetime.\n for (const key in next) {\n const entry = next[key]\n if (!entry) continue\n if (isMotionValue(entry.value)) {\n const targetMV = entry.value as MotionValue<unknown>\n onCleanup(\n targetMV.on(\"change\", (v) => {\n // Stage 3: route through the registry the same way the main\n // dispatch does, so a style MV the user also wrote into\n // `animate` doesn't bypass the writer's transform composition.\n const fallback =\n initialTarget && key in (initialTarget as Record<string, unknown>)\n ? (initialTarget as Record<string, unknown>)[key]\n : getMotionDefault(key)\n const routedMV = getValueForAnimate?.(key, fallback)\n if (routedMV && routedMV !== targetMV) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate overload soup; runtime correct\n animate(routedMV as any, v as any, buildAnimateOptions() as any)\n } else {\n // biome-ignore lint/suspicious/noExplicitAny: same as above\n animate(el, { [key]: v } as any, buildAnimateOptions())\n }\n }),\n )\n }\n }\n })\n\n // Owner-disposal cleanup: stop any in-flight animation.\n onCleanup(() => prevControls?.stop())\n\n function setActive(state: GestureStateName, isActive: boolean): void {\n setActiveStore(state, isActive)\n }\n\n /**\n * Phase 3 — Presence integration. Returns a Promise that resolves when the\n * NEXT exit-driven animate dispatched by the diff effect completes, OR\n * immediately if no exit target is configured (nothing to wait for).\n *\n * The typical caller is `createMotion`'s presence-registered `runExit`:\n * it flips `setActive(\"exit\", true)` then awaits this. The diff effect\n * runs in the next microtask, dispatches the exit animation, and on its\n * completion drains the pending resolvers.\n *\n * Multiple concurrent waiters are supported — they all resolve from the\n * same animation's completion.\n *\n * Edge case: if the user reactively removes `opts.exit` AFTER this call\n * but before the effect runs, the resolver will still be drained the\n * next time exit drives a dispatch (or by the \"no-animate but exit-\n * driven\" branch in the effect).\n */\n function onceExitComplete(): Promise<void> {\n const exitTarget = untrack(() => stateTargets().exit)\n if (exitTarget === null) return Promise.resolve()\n return new Promise<void>((resolve) => {\n pendingExitResolvers.push(resolve)\n })\n }\n\n return { setActive, onceExitComplete }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Q4 — a state is considered active if EITHER its own flag is set OR the\n * parent's VariantContext carries a label for it (the parent's gesture is\n * active and propagating). The parent slots are themselves active-gated in\n * `useMotion`'s `myVariantCtx`, so a defined return value here means the\n * parent's gesture really is firing right now.\n *\n * `animate` and `exit` are special — their inheritance happens through the\n * normal label-resolution path in `resolveTarget`, not through the active\n * flag. We treat `animate` as always-active (matches motion's\n * createTypeState(true)). `exit` is driven by the Presence context; the\n * flag-based check is fine.\n */\nfunction isStateActive(\n state: GestureStateName,\n active: ActiveStore,\n parent: VariantContextValue,\n): boolean {\n if (active[state]) return true\n switch (state) {\n case \"whileHover\":\n return parent.hover?.() !== undefined\n case \"whilePress\":\n return parent.press?.() !== undefined\n case \"whileFocus\":\n return parent.focus?.() !== undefined\n case \"whileInView\":\n return parent.inView?.() !== undefined\n // Drag inheritance through context isn't wired in Phase 1's\n // VariantContextValue (no `drag` slot). Commit 6 will revisit if needed.\n case \"whileDrag\":\n return false\n case \"animate\":\n case \"exit\":\n return false\n }\n}\n\n/** Convert a winners map into the flat value snapshot used by `lastApplied`. */\nfunction snapshotValues(winners: Record<string, WinnerEntry>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const key in winners) {\n const entry = winners[key]\n if (entry) out[key] = entry.value\n }\n return out\n}\n\n/**\n * Phase 1's splitTarget: separate MotionValue refs in a target from plain\n * values. Motion-vanilla `animate(el, target)` doesn't subscribe to MV refs\n * passed in target — we handle that bridge ourselves.\n */\nfunction splitTarget(target: Record<string, unknown>): {\n plain: Record<string, unknown>\n motionValues: Array<{ key: string; mv: MotionValue<unknown> }>\n} {\n const plain: Record<string, unknown> = {}\n const motionValues: Array<{ key: string; mv: MotionValue<unknown> }> = []\n for (const key in target) {\n const value = target[key]\n if (value === undefined || value === null) {\n plain[key] = value\n continue\n }\n if (isMotionValue(value)) {\n motionValues.push({ key, mv: value as MotionValue<unknown> })\n plain[key] = (value as MotionValue<unknown>).get()\n } else if (typeof value === \"function\") {\n plain[key] = (value as () => unknown)()\n } else if (Array.isArray(value)) {\n plain[key] = value.map((v) => {\n if (isMotionValue(v)) return (v as MotionValue<unknown>).get()\n if (typeof v === \"function\") return (v as () => unknown)()\n return v\n })\n } else {\n plain[key] = value\n }\n }\n return { plain, motionValues }\n}\n\n/**\n * Return the highest-priority active state that contributed any key in the\n * current winners map. Used to identify the \"driver\" for onAnimationComplete\n * (which receives the AnimateValue that drove the animation).\n *\n * `animate` is the fallback when no gesture is contributing — matches Phase 1's\n * effectiveAnimateValue semantic.\n */\nfunction highestActiveDriverState(winners: Record<string, WinnerEntry>): GestureStateName {\n // Walk PRIORITY_HIGH_TO_LOW and find the first state name that appears.\n for (const stateName of PRIORITY_HIGH_TO_LOW) {\n for (const key in winners) {\n const entry = winners[key]\n if (entry && entry.stateName === stateName) return stateName\n }\n }\n return \"animate\"\n}\n\n/**\n * Look up the AnimateValue (Target | string | string[]) that corresponds to a\n * given state — for onAnimationComplete's argument.\n */\nfunction animateValueForState(\n state: GestureStateName,\n opts: MotionOptions,\n parentVariantCtx: VariantContextValue,\n): AnimateValue | undefined {\n switch (state) {\n case \"animate\":\n return opts.animate ?? parentVariantCtx.animate?.()\n case \"whileHover\":\n return opts.hover ?? parentVariantCtx.hover?.()\n case \"whilePress\":\n return opts.press ?? parentVariantCtx.press?.()\n case \"whileFocus\":\n return opts.focus ?? parentVariantCtx.focus?.()\n case \"whileInView\":\n return opts.inView ?? parentVariantCtx.inView?.()\n case \"exit\":\n return opts.exit ?? parentVariantCtx.exit?.()\n case \"whileDrag\":\n return opts.whileDrag\n }\n}\n\n/**\n * Combine N AnimationPlaybackControls into a single Thenable+stoppable handle.\n *\n * Used by the Stage 3 bridge when an animate dispatch fans out across per-MV\n * `animate(mv, value, opts)` calls (one per routed key) plus an optional\n * single `animate(el, target, opts)` for keys still on the WAA path. The\n * gesture state machine treats `prevControls` as one handle: subsequent diff\n * runs call `.stop()` on it to cancel the in-flight animation, and the exit\n * drain awaits `.then(...)` to settle Presence's `onceExitComplete()` waiters.\n * Aggregating lets both code paths stay uniform whether bridging fired one\n * underlying motion call or six.\n *\n * The other AnimationPlaybackControls methods (pause/play/cancel/complete)\n * fan out unchanged. `time`/`speed`/`duration` aren't aggregated — they're\n * read-rare in our codebase and a meaningful aggregate isn't well-defined\n * across heterogeneous animations.\n */\nfunction aggregateControls(\n controls: readonly AnimationPlaybackControls[],\n): AnimationPlaybackControls {\n // Cache the settle promise so multiple `.then` consumers don't each spawn a\n // fresh Promise.all over the same controls. motion's AnimationPlaybackControls\n // is thenable at runtime (the public type omits `.then`, hence the casts).\n let settled: Promise<unknown[]> | null = null\n const settle = (): Promise<unknown[]> => {\n if (!settled) {\n settled = Promise.all(controls.map((c) => c as unknown as PromiseLike<unknown>))\n }\n return settled\n }\n const forAll = (fn: (c: AnimationPlaybackControls) => void): void => {\n for (const c of controls) fn(c)\n }\n const handle: Record<string, unknown> = {\n stop: () => {\n forAll((c) => c.stop())\n },\n pause: () => {\n forAll((c) => c.pause())\n },\n play: () => {\n forAll((c) => c.play())\n },\n cancel: () => {\n forAll((c) => c.cancel())\n },\n complete: () => {\n forAll((c) => c.complete())\n },\n speed: 1,\n time: 0,\n duration: controls.reduce(\n (acc, c) => Math.max(acc, (c as { duration?: number }).duration ?? 0),\n 0,\n ),\n // biome-ignore lint/suspicious/noThenProperty: structurally mirroring motion's AnimationPlaybackControls, which is intentionally thenable.\n then: (onFulfilled?: unknown, onRejected?: unknown) =>\n settle().then(onFulfilled as never, onRejected as never),\n }\n return handle as unknown as AnimationPlaybackControls\n}\n","import { type MotionValue, motionValue } from \"motion\"\n\n// ---------------------------------------------------------------------------\n// Per-element value registry.\n//\n// One `ValueRegistry` per element managed by `createMotion`. It maps style /\n// transform-shortcut keys (`scale`, `y`, `opacity`, etc.) to the\n// `MotionValue` that authoritatively drives the corresponding CSS or\n// transform component for that element.\n//\n// This is the motion-react `visualElement.values` shape, slimmed down. It\n// exists to unify two write paths that currently disagree about who owns a\n// CSS key on the element:\n//\n// 1. **User-provided MVs in `style`** — `<motion.div style={{ scale: mv }}>`.\n// mv is the source of truth for `scale`; subscribing to it and writing\n// `el.style.transform` is the only way the new value reaches the DOM.\n// 2. **animate-target writes** — `useMotion({ animate: { scale: 1.5 } })`.\n// Today these go directly via WAA (`animate(el, target, opts)`). After\n// Stage 3 they will be routed through the registry: if a key has a\n// registered MV, the animation tweens that MV (which writes the DOM\n// via its subscription) instead of writing the element directly.\n//\n// Stage 1 introduces only the data structure. No code reads from or writes\n// to it yet — `createMotion` instantiates an empty registry, attaches a\n// disposal hook, and stops there. Subsequent stages wire it up.\n//\n// Two ownership classes:\n//\n// - **External** — MVs the user created via `createMotionValue` / motion's\n// `motionValue()` and handed us via `style`. The registry tracks them so\n// we know \"this key is MV-backed\" but does NOT dispose them. The user\n// owns their MV's lifetime.\n//\n// - **Transient** — MVs the registry creates internally (Stage 3) because\n// an animate target referenced a key with no existing MV. The registry\n// owns these and clears them on `dispose()`. motion's MotionValue has no\n// imperative teardown method; releasing references is what lets GC\n// collect them once all subscribers have cleaned up.\n// ---------------------------------------------------------------------------\n\nexport type ValueRegistry = {\n /** Returns the MV registered for `key`, or `undefined` if none. */\n get(key: string): MotionValue<unknown> | undefined\n /** Has any MV been registered for `key`? */\n has(key: string): boolean\n /**\n * Number of entries currently registered. Used by `createMotion` to decide\n * whether the per-element writer can take a specialized single-key path\n * (size === 1) or needs the general-purpose `applyStaticStyle` walk.\n */\n readonly size: number\n /**\n * Register a user-provided MV. The registry will NOT dispose it on\n * teardown. If a transient MV exists for the key, it is replaced (the\n * external MV becomes the new source of truth).\n */\n setExternal(key: string, mv: MotionValue<unknown>): void\n /**\n * Get the MV for `key`, creating a transient one initialized to\n * `fallback` if absent. Transient MVs are disposed on `dispose()`.\n */\n getOrCreateTransient(key: string, fallback: unknown): MotionValue<unknown>\n /** Iterate every (key, MV) pair currently registered. */\n entries(): IterableIterator<[string, MotionValue<unknown>]>\n /**\n * Drop registry-owned (transient) MVs. External MVs are untouched.\n * Subscription cleanups are owned by whoever called `mv.on(...)`; they\n * tie to the surrounding Solid owner via `onCleanup` in Stage 2+ so we\n * don't unsubscribe imperatively here.\n */\n dispose(): void\n}\n\nexport function createValueRegistry(): ValueRegistry {\n const values = new Map<string, MotionValue<unknown>>()\n const transient = new Set<MotionValue<unknown>>()\n\n return {\n get(key) {\n return values.get(key)\n },\n has(key) {\n return values.has(key)\n },\n setExternal(key, mv) {\n const existing = values.get(key)\n if (existing && transient.has(existing)) {\n // Replacing a transient with an external takes the transient out\n // of the owned-set so dispose() doesn't pretend to manage it.\n transient.delete(existing)\n }\n values.set(key, mv)\n },\n getOrCreateTransient(key, fallback) {\n const existing = values.get(key)\n if (existing) return existing\n const mv = motionValue(fallback) as MotionValue<unknown>\n values.set(key, mv)\n transient.add(mv)\n return mv\n },\n entries() {\n return values.entries()\n },\n get size() {\n return values.size\n },\n dispose() {\n transient.clear()\n values.clear()\n },\n }\n}\n","import { animate, type MotionValue } from \"motion\"\nimport { createSignal, onCleanup, untrack } from \"solid-js\"\nimport { useMotionConfig } from \"../motion-config\"\nimport { usePresenceContext } from \"../presence-context\"\nimport { createReducedMotion, shouldReduceMotion } from \"../reduced-motion\"\nimport {\n formatProperty,\n pickTransformFormatter,\n snapshotValue,\n TRANSFORM_KEYS,\n targetToStyle,\n} from \"../style\"\nimport type {\n AnimateValue,\n MotionElement,\n MotionOptions,\n Target,\n Transition,\n VariantContextValue,\n VariantLabels,\n Variants,\n} from \"../types\"\nimport { effectiveLabels, resolveVariant, useVariantContext } from \"../variants\"\nimport { createDrag } from \"./createDrag\"\nimport { createGestures } from \"./createGestures\"\nimport { type ActiveStoreTuple, createGestureStateMachine } from \"./gesture-state\"\nimport { createValueRegistry, type ValueRegistry } from \"./value-registry\"\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Detect whether an animate-value is a variant name (string or string[]) vs.\n * an explicit target object. Returns the labels or undefined.\n */\nexport function asVariantLabels(value: AnimateValue | undefined): VariantLabels | undefined {\n if (value === undefined) return undefined\n if (typeof value === \"string\") return value\n if (Array.isArray(value)) return value\n return undefined\n}\n\n/**\n * Resolve a per-state animate value into a {@link Target}. Implements the\n * Q4 sub-2 priority table:\n *\n * - explicit Target object → use as-is (parent context ignored)\n * - variant name → look up in own variants only (no cascade)\n * - undefined → fall back to parent context's variant name, then look up in\n * own variants\n */\nexport function resolveTarget(\n ownValue: AnimateValue | undefined,\n ownVariants: Variants | undefined,\n parentLabel: VariantLabels | undefined,\n custom: unknown,\n): Target | null {\n // Explicit Target object — variant lookup is skipped entirely.\n if (ownValue !== undefined && typeof ownValue !== \"string\" && !Array.isArray(ownValue)) {\n return ownValue as Target\n }\n\n const labels = effectiveLabels(ownValue, parentLabel)\n if (labels === undefined) return null\n // After the explicit-object check above, `labels` is VariantLabels or a\n // Target that came from `parentLabel` slot — but parent context only\n // propagates labels, never Targets, so it's safe to treat as labels here.\n return resolveVariant(labels as VariantLabels, ownVariants, custom)\n}\n\n/**\n * Merge transition specs in priority order: MotionConfig default <\n * user's `transition` < per-target `transition`. When reduced motion is\n * active, returns `{ duration: 0 }` and drops everything else (Q11 sub-4).\n */\nexport function mergeTransition(\n configDefault: Transition | undefined,\n ownTransition: Transition | undefined,\n perTargetTransition: Transition | undefined,\n reduced: boolean,\n): Transition {\n if (reduced) return { duration: 0 } as Transition\n return {\n ...(configDefault ?? {}),\n ...(ownTransition ?? {}),\n ...(perTargetTransition ?? {}),\n } as Transition\n}\n\n/**\n * Apply a static target to an element's inline style before paint. Used on\n * mount when no SSR style was emitted. The ref callback fires before the\n * browser yields, so this avoids a frame of flicker.\n */\nfunction applyStaticStyle(el: MotionElement, target: Target): void {\n const style = targetToStyle(target)\n for (const key in style) {\n const value = (style as Record<string, string | number | undefined>)[key]\n if (value === undefined) continue\n if (key.startsWith(\"--\")) {\n el.style.setProperty(key, String(value))\n } else {\n // ElementCSSInlineStyle.style is indexable for camelCase property names.\n // Available on both HTMLElement and SVGElement (Phase 4 SVG support).\n ;(el.style as unknown as Record<string, string | number>)[key] = value\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// createMotion — the imperative primitive that drives one element's motion\n// state. useMotion wraps this; <motion.*> and motion() will wrap it too.\n// ---------------------------------------------------------------------------\n\nexport type CreateMotionConfig = {\n /**\n * When true, `createMotion` skips applying the initial style — the server\n * already emitted it inline, and re-applying on hydration would shift the\n * paint. Detected via the `data-motion-hydrated` marker in useMotion.\n */\n initialAppliedBySSR?: boolean\n /**\n * Q4 — useMotion lifts the gesture-state active store one level up so its\n * `myVariantCtx` can read the same flags it propagates to descendants.\n * When omitted (standalone createMotion use), the state machine creates\n * its own internal store.\n */\n activeStore?: ActiveStoreTuple\n /**\n * Q4 follow-up — useMotion passes a shadowed parent context here so the\n * controlling-variants check is applied uniformly. When omitted, createMotion\n * falls back to `useVariantContext()` directly (the standalone path).\n */\n parentContext?: VariantContextValue\n /**\n * MV-in-style Stage 2 — useMotion scrapes `MotionValue`-valued keys out of\n * the user's `style` prop and passes them here. createMotion registers\n * each as an external (user-owned) entry in the value registry and\n * subscribes a writer that re-composes `el.style` from the registry\n * snapshot on every change.\n */\n styleMotionValues?: Map<string, MotionValue<unknown>>\n /**\n * MV-in-style Stage 4 — static transform-shortcut entries in the user's\n * `style` (e.g., `style={{ x: 10, scale: mv }}`'s `x: 10`). useMotion scrapes\n * these alongside MVs so createMotion can seed transient registry entries\n * for them. Without this, the writer would drop the static keys on every\n * recompose since they wouldn't appear in the registry.\n *\n * Map values are the resolved leaf (number or string) — no MVs, no\n * keyframe arrays, no accessor functions. useMotion runs the\n * `snapshotValue` reduction before passing them in.\n */\n styleStaticTransforms?: Map<string, number | string>\n}\n\n/**\n * The imperative primitive: bind an element to a reactive motion-options\n * source. Caller is responsible for keeping the element alive (refs in a\n * component, drag controls, etc.).\n *\n * Phase 1 scope: animate + initial + transition + lifecycle hooks +\n * reduced-motion override + presence registration. Phase 2 layers gesture\n * states (hover/press/focus/inView) and drag on top.\n */\nexport function createMotion(\n el: MotionElement,\n getOpts: () => MotionOptions,\n config?: CreateMotionConfig,\n): void {\n // Q4 follow-up: useMotion passes a shadowed (controlling-aware) context;\n // standalone callers fall back to the live VariantContext.\n const parentVariantCtx: VariantContextValue = config?.parentContext ?? useVariantContext()\n const presence = usePresenceContext()\n const motionConfig = useMotionConfig()\n const systemReducedMotion = createReducedMotion()\n\n // ---------- Per-element value registry (lazy — Stage 4.5) ----------\n // Most elements never need a registry: they have no MV in style, no static\n // transform shortcut in style, and no Stage 3 transient is ever required\n // because the WAA dispatch path stays active throughout. For those elements\n // (the bulk of typical motion usage), allocating an empty registry was pure\n // waste. We now create it on first use via `ensureRegistry()`.\n //\n // No `onCleanup(() => valueRegistry?.dispose())` — `dispose()` was just\n // `transient.clear() + values.clear()`. When createMotion's closure dies,\n // GC reclaims the Map+Set + their MV references; user-provided MVs survive\n // because they have other references; transient MVs that no longer have\n // any subscriber will GC naturally. Calling dispose() explicitly bought\n // nothing.\n let valueRegistry: ValueRegistry | undefined\n const ensureRegistry = (): ValueRegistry => {\n if (!valueRegistry) valueRegistry = createValueRegistry()\n return valueRegistry\n }\n\n // Snapshot once at construction. Subsequent reactivity goes through\n // the createEffect below, so we don't subscribe in the body of this fn.\n const initialOpts = untrack(getOpts)\n\n // ---------- Resolve the initial target (used for BOTH static-style write AND\n // the state machine's removed-key fallback chain, Q7) ----------\n // Priority chain (matches use-motion's computeInitialStyle):\n // own.initial > parent.initial > own.animate > parent.animate\n //\n // We resolve this regardless of `initialAppliedBySSR` because the state\n // machine needs it even when SSR already wrote the inline style — the user's\n // explicit `initial` value is part of their intent and should anchor the\n // removed-key fallback regardless of who painted it.\n let capturedInitialTarget: Target | null = null\n if (initialOpts.initial !== false) {\n const inheritedInitial = parentVariantCtx.initial?.()\n const inheritedAnimate = parentVariantCtx.animate?.()\n const effective =\n initialOpts.initial !== undefined\n ? initialOpts.initial\n : inheritedInitial !== undefined\n ? inheritedInitial\n : initialOpts.animate !== undefined\n ? initialOpts.animate\n : inheritedAnimate\n if (effective !== undefined) {\n capturedInitialTarget = resolveTarget(\n effective,\n initialOpts.variants,\n undefined, // priority chain already consumed parent's labels\n initialOpts.custom ?? parentVariantCtx.custom?.(),\n )\n }\n }\n\n // ---------- Apply the initial style pre-paint, unless SSR already did it ----------\n // An enclosing `<Presence initial={false}>` ALSO suppresses the static\n // style application — the descendant should mount at the animate target,\n // not the initial. Done via the same path as the state machine's\n // `suppressFirstMount` flag below; consistent semantic across both.\n const suppressFirstMount = untrack(() => presence.initial?.()) === false\n if (!config?.initialAppliedBySSR && !suppressFirstMount && capturedInitialTarget) {\n applyStaticStyle(el, capturedInitialTarget)\n }\n\n // ---------- MV-in-style: register external MVs + the registry writer ----------\n // Stage 2/3 of the MV-in-style work. useMotion has scraped `MotionValue` refs\n // out of `style` (e.g., `<motion.div style={{ scale: mv }}>`) and handed\n // them to us in `config.styleMotionValues`. We register each as an external\n // entry in the registry and subscribe a single writer that rebuilds the\n // inline style from a fresh registry snapshot via `applyStaticStyle`.\n //\n // The writer is also subscribed to transient MVs Stage 3's animate bridge\n // creates on demand. Composition cost on each MV change is bounded by\n // registry size — for the common `style: { scale: mv }` case it's a single\n // transform-shortcut walk and one `el.style.transform =` write\n // (bench 04 / bench 08 — ~600 ns per subscriber).\n //\n // Bridge activation rule (Stage 3): the state machine routes animate-target\n // dispatches through the registry ONLY when at least one external MV has\n // been registered. Without a style MV, bridging is inactive and the state\n // machine falls back to the existing `animate(el, target, opts)` WAA path.\n // This keeps the 293 baseline tests on their original code path — their\n // `animateSpy.mock.calls[*][1]` assertions still see a target object.\n // ---------- Specialized writer (Stage 4.5b) ----------\n // `writeFromRegistry` is the subscription target: every MV in the registry\n // is hooked to it via `mv.on(\"change\", writeFromRegistry)`. Internally it\n // dispatches to a `writer` closure that's COMPILED based on the registry's\n // current shape:\n //\n // - 0 entries → noop (the registry is empty; nothing to paint)\n // - 1 entry → SPECIALIZED closure that captures (key, mv) in scope.\n // Per-call cost is just mv.get() → snapshotValue → format →\n // DOM write. No iterator allocations, no TRANSFORM_KEYS\n // lookup, no branching on key shape — the shape is baked\n // into the closure choice.\n // - 2+ ents → `multiKeyWriter`, which walks the registry, composes a\n // Target, and runs the full applyStaticStyle path.\n //\n // The closure is recompiled by `refreshWriter()` whenever the registry's\n // size changes (called from every registration site: Stage 2 styleMV\n // loop, Stage 4 initial-target walk, Stage 4 static-transforms walk, and\n // Stage 3 `getValueForAnimate`'s transient-creation branch).\n //\n // Why this matters at scale: Sierpinski at depth 8 has 6,561 dots × one\n // style MV each = 6,561 calls per scale.set, × 60 Hz = 393k calls/sec.\n // The previous fast path allocated 3 IteratorResults per call → 1.2M\n // allocations/sec of GC pressure. The specialized closure has zero per-\n // call allocations.\n const noop = (): void => {}\n let writer: () => void = noop\n const writeFromRegistry = (): void => writer()\n\n const multiKeyWriter = (): void => {\n if (!valueRegistry) return\n const target: Record<string, unknown> = {}\n for (const [k, mv] of valueRegistry.entries()) {\n target[k] = mv.get()\n }\n if (Object.keys(target).length === 0) return\n applyStaticStyle(el, target as Target)\n }\n\n const compileSingleKeyWriter = (): (() => void) => {\n // Safe: caller guarantees size === 1.\n const [key, mv] = (valueRegistry as ValueRegistry).entries().next().value as [\n string,\n MotionValue<unknown>,\n ]\n if (TRANSFORM_KEYS.has(key)) {\n // Pre-pick the formatter so the per-call hot path skips the\n // transform-key switch entirely. Captured in the closure scope; the\n // switch happens ONCE per element at compile time, never per write.\n const formatter = pickTransformFormatter(key)\n if (formatter !== undefined) {\n return () => {\n const v = snapshotValue(mv.get())\n if (v !== undefined) el.style.transform = formatter(v)\n }\n }\n }\n if (key.startsWith(\"--\")) {\n return () => {\n const v = snapshotValue(mv.get())\n if (v !== undefined) el.style.setProperty(key, String(v))\n }\n }\n return () => {\n const v = snapshotValue(mv.get())\n if (v === undefined) return\n const formatted = formatProperty(key, v)\n ;(el.style as unknown as Record<string, string | number>)[key] = formatted\n }\n }\n\n const refreshWriter = (): void => {\n const size = valueRegistry?.size ?? 0\n if (size === 0) {\n writer = noop\n return\n }\n if (size === 1) {\n writer = compileSingleKeyWriter()\n return\n }\n writer = multiKeyWriter\n }\n // Bridge activates whenever the user supplied ANY registry-owned style\n // entry — an MV in style OR a static transform shortcut. The transform\n // string then becomes the registry-writer's exclusive responsibility,\n // composing from the union of (initial transforms, style MVs, static\n // style transforms, animate-target transients). With NO registry-owned\n // entries, transforms stay on the pre-existing WAA dispatch path.\n let bridgeActive = false\n if (config?.styleMotionValues && config.styleMotionValues.size > 0) {\n const registry = ensureRegistry()\n for (const [key, mv] of config.styleMotionValues) {\n registry.setExternal(key, mv)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n }\n bridgeActive = true\n }\n if (config?.styleStaticTransforms && config.styleStaticTransforms.size > 0) {\n bridgeActive = true\n }\n\n // ---------- Stage 4: register initial + static-style transforms as transients ----------\n // When bridging is active, ALL transform-shortcut keys need to flow through\n // the registry so the writer composes the full transform string. Animate\n // targets get routed via Stage 3's bridge (transients created on demand);\n // style MVs get registered as external in the Stage 2 block above. This block\n // closes the remaining two gaps:\n //\n // (a) Initial transform values (from own.initial / parent.initial /\n // own.animate / parent.animate priority chain). Without these,\n // initial.y=20 + style.scale=mv would compose only `scale(<v>)` —\n // initial.y would be lost when the writer fires.\n //\n // (b) Static transform shortcuts in the user's `style` prop (e.g.,\n // `style={{ x: 10, scale: mv }}`'s `x: 10`). These don't enter via\n // Stage 2's MV scrape; useMotion forwards them in\n // `styleStaticTransforms`. Same fate as (a) if not registered:\n // composeFirstPaintStyle gets them onto the SSR HTML, but the writer\n // wouldn't know about them on subsequent recomposes.\n //\n // Both (a) and (b) seed transients in the registry; the bridge function above\n // returns them on subsequent animate dispatches, and the writer composes\n // them with style MVs into one transform string. Non-transform initial\n // values (opacity, etc.) stay on applyStaticStyle's one-shot path — the\n // writer doesn't touch keys it doesn't own.\n //\n // We snapshot the raw value with `snapshotValue` because initial targets can\n // carry keyframe arrays, MotionValues, or accessor functions; the transient\n // needs a concrete leaf to start from. styleStaticTransforms is already\n // pre-snapshotted by useMotion.\n if (bridgeActive && capturedInitialTarget) {\n const registry = ensureRegistry()\n for (const key in capturedInitialTarget) {\n if (key === \"transition\") continue\n if (!TRANSFORM_KEYS.has(key)) continue\n if (registry.has(key)) continue\n const raw = (capturedInitialTarget as Record<string, unknown>)[key]\n const snapshot = snapshotValue(raw)\n if (snapshot === undefined) continue\n const mv = registry.getOrCreateTransient(key, snapshot)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n }\n }\n if (bridgeActive && config?.styleStaticTransforms) {\n const registry = ensureRegistry()\n for (const [key, value] of config.styleStaticTransforms) {\n // Static style entries WIN over initial on key collision — style is\n // the runtime source of truth for any key it specifies. Replace any\n // transient just seeded from initialTarget with this value's transient.\n const existing = registry.get(key)\n if (existing) {\n existing.set(value)\n } else {\n const mv = registry.getOrCreateTransient(key, value)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n }\n }\n }\n\n // Initial paint from the registry — composes initial transforms + style MVs\n // + static-style transforms into a single transform string. Skipped when\n // nothing is registered.\n if (bridgeActive) {\n // All initial registrations complete; compile the specialized writer\n // based on the final registry size before firing the first paint.\n // Subsequent transient additions (via getValueForAnimate) call\n // refreshWriter themselves.\n refreshWriter()\n writeFromRegistry()\n }\n\n // ---------- Stage 3 bridge function — animate target → registered MV ----------\n // Returns the MV the state machine should animate for `key`:\n // • external (user-provided) MV in registry → return it; animate's tween\n // drives this MV directly, and our writer composes the transform.\n // • registry doesn't have an MV but key is a transform shortcut → create\n // a transient MV initialized to `fallback`, subscribe the writer, return\n // the new MV.\n // • non-transform key with no external MV → return undefined; state machine\n // falls back to WAA.\n // Inactive when no external MV exists — preserves the existing dispatch\n // shape end-to-end for non-MV-in-style users.\n const getValueForAnimate = (key: string, fallback: unknown): MotionValue<unknown> | undefined => {\n if (!bridgeActive) return undefined\n // `bridgeActive=true` implies the registry was ensured by one of the\n // registration blocks above, but TypeScript can't see that correlation.\n // Re-resolve through `ensureRegistry()` — idempotent and free if already\n // created.\n const registry = ensureRegistry()\n const existing = registry.get(key)\n if (existing) return existing\n if (!TRANSFORM_KEYS.has(key)) return undefined\n const mv = registry.getOrCreateTransient(key, fallback)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n // Registry size just grew — recompile the writer so the next paint uses\n // the multi-key path that composes all transforms together. (Transitions\n // 1→2 swap from specialized single-key to multiKeyWriter; 2+→N+1 stays\n // on multiKeyWriter, refreshWriter is then idempotent.)\n refreshWriter()\n return mv\n }\n\n // ---------- Presence-aware enter-readiness gate ----------\n // We detect \"inside a real <Presence>\" by the absence of `registerEnter` on\n // the no-op default context. When we ARE inside one, the element may be\n // off-DOM at the moment the state machine first iterates (the new child\n // during a mode=\"wait\" swap is created before the old child's exit\n // settles, and even the initial child is briefly created off-DOM during\n // appear). Dispatching motion's `animate()` then would run the animation\n // on a disconnected element and silently fail commitStyles — the element\n // would paint at its `initial` target when it finally enters the DOM.\n //\n // Solution: start `enterReady = false` while in a Presence, register a\n // `runEnter` callable that flips it true, and let Presence call it from\n // its `onEnter` / `onChange.added` hook (when transition-group has\n // synchronously inserted the element via `setReturned`). Outside a\n // Presence we leave `enterReady` undefined; the state machine treats\n // absence as ready=true and the existing eager-first-iteration behavior\n // is unchanged.\n const inPresence = presence.registerEnter !== undefined\n const [enterReady, setEnterReady] = createSignal(!inPresence)\n if (inPresence && presence.registerEnter) {\n presence.registerEnter(el, () => setEnterReady(true))\n // Fallback: transition-group's onEnter / onChange.added only fires for\n // elements that are NEW to the source list. The initial children of a\n // `<Presence initial={false}>` (appear=false case) are already in the\n // signal at construction and never trigger an enter callback. We flip\n // readiness from a microtask if the element is connected by then —\n // Solid's synchronous render of `returned()` has run, and any element\n // that was meant to be on screen is in the DOM. For wait-mode swaps\n // where the new child is still off-DOM (the old one's exit is in\n // flight), the `isConnected` check fails and we leave readiness false;\n // Presence will fire beforeMount through onEnter when the exit settles.\n queueMicrotask(() => {\n if (el.isConnected) setEnterReady(true)\n })\n }\n\n // ---------- Gesture state machine (Q3b, ADR 0002) ----------\n // Constructed BEFORE presence registration so the registered `runExit`\n // callable can close over `setActive` + `onceExitComplete`. Owns target\n // resolution, priority winners, and the diff-and-animate loop. Returns\n // `setActive` which gesture wiring uses to toggle active flags, and\n // `onceExitComplete` which Presence awaits during unmount.\n // (For drag's typing constraint, see the createDrag call below.)\n const stateMachine = createGestureStateMachine({\n el,\n getOpts,\n parentVariantCtx,\n motionConfig,\n systemReducedMotion,\n initialTarget: capturedInitialTarget,\n externalActiveStore: config?.activeStore,\n suppressFirstMount,\n enterReady,\n getValueForAnimate,\n })\n const { setActive, onceExitComplete } = stateMachine\n\n // ---------- Presence registration (Phase 3 — inverted shape) ----------\n // Child registers a `runExit` callable that dispatches the exit animate\n // DIRECTLY (bypassing the state-machine effect). Direct dispatch is\n // necessary because by the time Presence's `onExit` callback fires,\n // Solid has already disposed the surrounding owner — the state machine's\n // diff effect is gone. `runExit` therefore captures the exit-relevant\n // options at construction time and uses motion's `animate()` itself.\n //\n // We do NOT call `presence.unregister(el)` on owner cleanup — that would\n // race ahead of Presence's onExit. Instead, Presence/hook unregisters\n // after the exit settles. See ADR 0003 for the timing rationale.\n // Register a runExit for this element if EITHER:\n // (a) it has its own `exit` prop, OR\n // (b) an ancestor's exit label cascades down via VariantContext AND this\n // element has a `variants` map that could resolve against it.\n //\n // (b) is the motion-react canonical orchestration pattern: a parent shell\n // declares `exit: \"closed\"` (a label), wraps children in `m.Provider`, and\n // children are passive consumers — they have ONLY a `variants` map keyed\n // by `\"closed\"` (and other labels). Without (b), the children would never\n // register a runExit and Presence's subtree-walk wouldn't find them; the\n // cascade would work on enter but vanish on exit.\n //\n // The check uses parentVariantCtx.exit?.() which (per use-motion.tsx's\n // `myVariantCtx.exit`) returns the parent's exit prop unconditionally —\n // not gated on the parent's active.exit flag — so this snapshot at\n // construction sees the static cascaded label, not a transient runtime\n // value.\n const inheritedExitLabel = untrack(() => parentVariantCtx.exit?.())\n const hasOwnExit = initialOpts.exit !== undefined\n const hasCascadedExit = inheritedExitLabel !== undefined && initialOpts.variants !== undefined\n\n if (hasOwnExit || hasCascadedExit) {\n const runExit = async (): Promise<void> => {\n // Re-read opts at exit time. The previous design snapshotted them at\n // construction, which broke any pattern where `exit` is reactive — a\n // swipe-card whose exit direction depends on which way the user just\n // flicked, for example, would always exit using the PREVIOUS card's\n // direction (the value that was live when THIS card mounted). We\n // untrack the read because we don't want to subscribe anything that\n // would still be alive after the surrounding owner has been disposed\n // by Solid's `<Show>` / `<For>` swap. The props proxy itself survives\n // disposal — it's just a JS object that the runExit closure keeps\n // referenced — so reading `props.X` here returns the latest value\n // the parent passed in.\n const opts = untrack(getOpts)\n // `resolveTarget` walks own.exit, then the inherited cascade. When\n // neither produces a target there's nothing to animate — return\n // without setActive so we don't hang on the (potentially dead)\n // state machine's onceExitComplete.\n const exitTarget = resolveTarget(\n opts.exit,\n opts.variants,\n asVariantLabels(untrack(() => parentVariantCtx.exit?.())),\n opts.custom ?? parentVariantCtx.custom?.(),\n )\n if (!exitTarget) {\n // Resolved to null (e.g., the user passed a label that doesn't\n // exist in variants). Cooperate with the state machine for cases\n // where the user expects an \"exit\" gesture without specific keys.\n setActive(\"exit\", true)\n await onceExitComplete()\n return\n }\n\n // Merge transition: MotionConfig default < user.transition <\n // exit-target.transition < reduced-motion override.\n const reduced = shouldReduceMotion(motionConfig.reducedMotion(), systemReducedMotion())\n const transition = mergeTransition(\n motionConfig.transition(),\n opts.transition,\n exitTarget.transition,\n reduced,\n )\n\n // Strip `transition` from the target before passing to animate.\n const animTarget: Record<string, unknown> = {}\n for (const k in exitTarget) {\n if (k !== \"transition\") {\n animTarget[k] = (exitTarget as Record<string, unknown>)[k]\n }\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape we can't tighten generically; the runtime call is correct.\n const controls = animate(el, animTarget as any, transition as any)\n // AnimationPlaybackControls is thenable at runtime (motion 12.x).\n // The public type doesn't expose `.then` — narrow via PromiseLike.\n await (controls as unknown as PromiseLike<unknown>)\n }\n\n presence.register(el, runExit)\n // No `onCleanup(() => presence.unregister(el))` — that would fire\n // synchronously when Solid disposes the child's owner, BEFORE\n // transition-group's `onExit` callback runs. Presence/hook calls\n // `unregister` itself after the exit settles. For the no-op default\n // context (no enclosing Presence), `register` is a silent drop —\n // nothing to clean up.\n }\n\n // ---------- Pointer-event gestures (hover, press, focus, inView) ----------\n // Listeners attach unconditionally on mount; the state machine no-ops when\n // an active state has no target.\n createGestures(el, getOpts, setActive)\n\n // ---------- Drag + pan (Q5/C-lean + Q11/D3) ----------\n // createDrag layers on createPan for the pointer session and writes to the\n // element's VisualElement x/y MotionValues during drag. Drag is HTML-only\n // for v0.1 — motion-dom's HTMLVisualElement is HTML-specific. Users who\n // wire `drag` onto an SVG element get a no-op at construction; we could\n // surface a dev warning here later if needed.\n if (el instanceof HTMLElement) {\n createDrag(el, getOpts, setActive)\n }\n}\n\n// Re-export for useMotion to consume the same helpers without circular deps.\nexport { applyStaticStyle }\n","import { mergeRefs } from \"@solid-primitives/refs\"\nimport { isMotionValue, type MotionValue } from \"motion\"\nimport { type Accessor, type Component, type JSX, mergeProps, onMount, untrack } from \"solid-js\"\nimport { createStore } from \"solid-js/store\"\nimport { usePresenceContext } from \"./presence-context\"\nimport { asVariantLabels, createMotion, resolveTarget } from \"./primitives/createMotion\"\nimport type { GestureStateName } from \"./primitives/gesture-state\"\nimport { snapshotValue, TRANSFORM_KEYS, targetToStyle } from \"./style\"\nimport type {\n ElementProps,\n MotionElement,\n MotionMergedProps,\n MotionOptions,\n MotionStyle,\n Target,\n Transition,\n UseMotionResult,\n VariantContextValue,\n Variants,\n} from \"./types\"\nimport { isControllingVariants, useVariantContext, VariantContext } from \"./variants\"\n\n// ---------------------------------------------------------------------------\n// useMotion — the canonical public API. Returns a getter that merges user\n// props with motion's (style, ref, hydration marker) and a Provider for\n// opt-in variant context propagation (Q4 sub-3 Option B).\n// ---------------------------------------------------------------------------\n\n/**\n * Wire motion to an element via a getter function.\n *\n * ```tsx\n * const motion = useMotion({\n * initial: { opacity: 0, y: 20 },\n * animate: { opacity: 1, y: 0 },\n * transition: { duration: 0.6 },\n * })\n *\n * <div {...motion({ class: \"card\" })}>Hello</div>\n * ```\n *\n * **Reactive form**: pass a function to track signals.\n * ```tsx\n * useMotion(() => ({ animate: { x: x() } }))\n * ```\n *\n * **Variant context propagation**: `useMotion` only *consumes* the parent\n * variant context. To propagate to descendants, wrap them in `motion.Provider`:\n * ```tsx\n * const m = useMotion({ animate: \"visible\", variants })\n * <div {...m()}>\n * <m.Provider>\n * <ChildMotion />\n * </m.Provider>\n * </div>\n * ```\n *\n * For the common \"JSX wrapper does propagation automatically\" pattern, use\n * `<motion.div>` (Phase 4).\n */\nexport function useMotion(opts: MotionOptions | (() => MotionOptions)): UseMotionResult {\n const getOpts: () => MotionOptions = typeof opts === \"function\" ? opts : () => opts\n\n // ---------- Parent context (with controlling-variants shadowing) ----------\n // Mirrors motion-dom's isControllingVariants check: when THIS node has any\n // variant *label* prop (initial/animate/hover/press/focus/inView/exit as a\n // string), it opts OUT of inheriting from its parent. The wrapped context's\n // slots return undefined while controlling, so the state machine and the\n // initial-target resolver see no inherited values to fall back on.\n //\n // The wrap is reactive — if opts toggle in/out of controlling state, the\n // slots automatically flip between actual-parent and undefined.\n const actualParentCtx: VariantContextValue = useVariantContext()\n const isControlling = (): boolean => isControllingVariants(getOpts())\n const parentVariantCtx: VariantContextValue = {\n variants: () => (isControlling() ? undefined : actualParentCtx.variants?.()),\n initial: () => (isControlling() ? undefined : actualParentCtx.initial?.()),\n animate: () => (isControlling() ? undefined : actualParentCtx.animate?.()),\n hover: () => (isControlling() ? undefined : actualParentCtx.hover?.()),\n press: () => (isControlling() ? undefined : actualParentCtx.press?.()),\n focus: () => (isControlling() ? undefined : actualParentCtx.focus?.()),\n inView: () => (isControlling() ? undefined : actualParentCtx.inView?.()),\n exit: () => (isControlling() ? undefined : actualParentCtx.exit?.()),\n custom: () => (isControlling() ? undefined : actualParentCtx.custom?.()),\n transition: () => (isControlling() ? undefined : actualParentCtx.transition?.()),\n }\n\n // ---------- Compute the SSR-emittable initial target ----------\n // untrack so reading getOpts() during render doesn't subscribe a Solid\n // computation; the createMotion effect inside motionRef owns reactivity.\n //\n // We also peek at the surrounding `<Presence>` (if any). When `initial`\n // is propagated as `false`, the descendant should mount painted at the\n // animate target — not the initial — because we WANT the visual end state\n // to match a normal post-animation appearance, just without the animation.\n // computeInitialTarget reads `presence.initial` once at construction; the\n // signal flips to true on a microtask, but by then the SSR style has\n // been computed and merged into the JSX props.\n //\n // Stage 4 split: this returns the RAW resolved Target rather than the\n // composed CSS. The style getter below composes initialTarget + style MV\n // snapshots together so SSR HTML and client first paint both reflect the\n // MVs the user supplied. Without this split, SSR HTML carries only the\n // initial target and the MV value lands only after the client's ref fires\n // — producing a brief paint discontinuity.\n const presenceCtx = usePresenceContext()\n const initialOpts = untrack(getOpts)\n const initialTarget = computeInitialTarget(initialOpts, parentVariantCtx, presenceCtx.initial)\n\n // ---------- Active gesture flags (Q4) ----------\n // Lifted from inside the state machine so myVariantCtx below can gate its\n // gesture label slots on these flags. createMotion (via the ref) threads\n // this same store into the state machine so both sides share state.\n const activeStore = createStore<Record<GestureStateName, boolean>>({\n animate: true,\n whileInView: false,\n whileHover: false,\n whilePress: false,\n whileFocus: false,\n whileDrag: false,\n exit: false,\n })\n const [active] = activeStore\n\n // ---------- MV-in-style scrape (Stage 2) ----------\n // Walked once on the first m() call (see `getProps` below) and threaded\n // into createMotion via `styleMotionValues`. The contract (locked in the\n // grill): MV references in `style` are STATIC — captured once, not\n // re-scanned on subsequent m() calls. Users who want a reactive MV swap\n // can't do `style: { scale: cond() ? mvA : mvB }`; they animate the MV's\n // value instead.\n //\n // Why capture in m() and not in motionRef: m()'s call is the only point\n // where the user's `style` prop is observable from useMotion's body.\n // motionRef fires later (after JSX evaluates), at which time we no\n // longer have a handle on userProps.\n // Stage 4.5: lazy-allocate both maps. Most elements have no MV-in-style\n // and no static transform shortcut, so allocating these eagerly per\n // `useMotion` call was pure waste. The `??=` in `captureStyleEntries`\n // creates them only on first add; downstream consumers handle the\n // `undefined` case via optional chaining.\n let styleMotionValues: Map<string, MotionValue<unknown>> | undefined\n let styleStaticTransforms: Map<string, number | string> | undefined\n let styleCaptured = false\n\n // ---------- Build the motion ref ----------\n // Pass the shadowed parent context to createMotion so its state machine\n // and initial-target resolver consume the same controlling-aware view.\n //\n // Stage 4: `initialAppliedBySSR` is now true when EITHER we emitted an\n // initial target into the SSR style OR at least one style MV's snapshot\n // landed in the SSR HTML via the style getter below. createMotion uses\n // this flag to skip its own applyStaticStyle pass — without the\n // styleMotionValues branch it would re-apply only the initialTarget half\n // and clobber the MV-snapshot half that's already in the inline style.\n const motionRef = (el: MotionElement) => {\n createMotion(el, getOpts, {\n initialAppliedBySSR:\n initialTarget !== null ||\n styleMotionValues !== undefined ||\n styleStaticTransforms !== undefined,\n activeStore,\n parentContext: parentVariantCtx,\n styleMotionValues,\n styleStaticTransforms,\n })\n }\n\n // ---------- The getter that merges user props with motion's ----------\n // Built on Solid's `mergeProps` rather than an eager object spread. The\n // returned value is a reactive proxy: reads against any property defer to\n // its source, so reactive non-motion props the user spreads through `m()`\n // (e.g. `<div {...m({ class: signal() ? \"on\" : \"off\" })}>`) keep their\n // reactivity through to the rendered element. The previous spread-based\n // implementation snapshotted userProps at call time, which broke this\n // path for the Phase 4 motion proxy.\n //\n // `initialStyle` is included in the `style` getter ONLY before the\n // first render completes. After onMount fires, motion's WAA owns the\n // animated properties on the element — if we kept layering initialStyle\n // into m()'s reactive output, Solid's style fn (which re-applies every\n // tracked key via setProperty on each render — its first-loop deletes\n // every prev entry, so the second loop's `v !== prev[s]` is always true)\n // would re-write the static initial values back into the inline style on\n // every reactive prop change, clobbering whatever WAA committed. Server-\n // side, onMount never fires, so renderedOnce stays false and initialStyle\n // always reaches the SSR HTML for first-paint correctness. Client first\n // render runs BEFORE the onMount microtask, so initialStyle is also in\n // the JSX for hydration consistency with the SSR HTML.\n //\n // `ref` is computed once and snapshotted — refs are conventionally\n // callbacks set once per mount; re-running mergeRefs on each read is\n // wasted work.\n let renderedOnce = false\n onMount(() => {\n renderedOnce = true\n })\n\n /**\n * Walk `style` once and pull `MotionValue` refs into `styleMotionValues`.\n * Idempotent across re-renders — Stage 2's contract is \"MV refs in style\n * are captured on first call and never re-scraped.\" Subsequent m()\n * invocations that pass a different style with new MVs won't pick them\n * up; that pattern wasn't in scope for v0.1.\n *\n * The read is `untrack`ed because m() is typically called from inside a\n * JSX spread, which Solid evaluates within a tracked owner. Without\n * untrack we'd subscribe to whatever signals the user's `style` object\n * references and re-fire this useMotion's owner-level effects on every\n * change.\n */\n const captureStyleEntries = (style: unknown): void => {\n if (styleCaptured) return\n styleCaptured = true\n if (!style || typeof style !== \"object\") return\n for (const key in style) {\n const value = (style as Record<string, unknown>)[key]\n if (isMotionValue(value)) {\n if (!styleMotionValues) styleMotionValues = new Map()\n styleMotionValues.set(key, value as MotionValue<unknown>)\n } else if (TRANSFORM_KEYS.has(key)) {\n // Static transform shortcut. Stage 4 lands these in the registry as\n // transients so the writer composes them with style MVs and initial\n // transforms into one transform string. Reduce MV/accessor/array\n // wrappers to a leaf — though by this branch we already know it's\n // not an MV. The reduction also rejects boolean/object junk values.\n const snap = snapshotValue(value)\n if (snap !== undefined) {\n if (!styleStaticTransforms) styleStaticTransforms = new Map()\n styleStaticTransforms.set(key, snap)\n }\n }\n }\n }\n\n /**\n * Produce a style object with MV-valued keys (and transform-shortcut keys —\n * see below) removed. Solid's style binding would otherwise either write the\n * MotionValue instance as a literal (coercing it via String() to\n * \"[object Object]\") for MV-valued entries, or apply transform shortcuts\n * directly as bogus CSS properties for static-shortcut entries. createMotion\n * handles both via the registry-write path; we strip them here so the\n * Solid-bound `cleaned` style only contains regular CSS keys.\n */\n const stripStyleEntriesOwnedByRegistry = (style: MotionStyle | undefined): JSX.CSSProperties => {\n if (!style) return {}\n const out: Record<string, unknown> = {}\n for (const key in style) {\n if (styleMotionValues?.has(key)) continue\n if (TRANSFORM_KEYS.has(key)) continue\n out[key] = (style as Record<string, unknown>)[key]\n }\n return out as JSX.CSSProperties\n }\n\n /**\n * Stage 4 — compose the first-paint inline style from:\n * 1. `initialTarget` (resolved via the priority chain at construction)\n * 2. MotionValue snapshots from `style: { key: mv }`\n * 3. Static transform shortcuts in `style: { x: 10, scale: 0.5 }`\n *\n * Style entries (2, 3) override `initialTarget` (1) on the same key because\n * `style` is the runtime source-of-truth for those keys. Returns the composed\n * `JSX.CSSProperties` or null when nothing applies (no initial + no style\n * registry contributions).\n *\n * Called only before `onMount` flips `renderedOnce`. After mount, the\n * registry's writer (in createMotion) owns el.style directly and this\n * function isn't consulted.\n */\n const composeFirstPaintStyle = (userStyle: MotionStyle | undefined): JSX.CSSProperties | null => {\n const merged: Record<string, unknown> = {}\n let hasAny = false\n if (initialTarget) {\n Object.assign(merged, initialTarget)\n hasAny = true\n }\n // MV snapshots from style override initialTarget for the same key.\n if (styleMotionValues) {\n for (const [key, mv] of styleMotionValues) {\n merged[key] = mv.get()\n hasAny = true\n }\n }\n // Static transform shortcuts in style (NOT captured as MVs) override too.\n if (userStyle) {\n for (const key in userStyle) {\n if (styleMotionValues?.has(key)) continue\n if (!TRANSFORM_KEYS.has(key)) continue\n const v = (userStyle as Record<string, unknown>)[key]\n if (typeof v === \"number\" || typeof v === \"string\") {\n merged[key] = v\n hasAny = true\n }\n }\n }\n return hasAny ? targetToStyle(merged as Target) : null\n }\n\n function getProps<P extends ElementProps>(userProps?: P): MotionMergedProps<P> {\n untrack(() => captureStyleEntries(userProps?.style))\n // Decide marker presence at call time. Determining this from\n // `getProps` (rather than recomputing per style-getter read) keeps it\n // a stable attribute key on the mergeProps source object.\n const wroteFirstPaintStyle =\n initialTarget !== null ||\n styleMotionValues !== undefined ||\n styleStaticTransforms !== undefined\n return mergeProps(userProps ?? {}, {\n get style() {\n const cleaned = stripStyleEntriesOwnedByRegistry(userProps?.style)\n if (renderedOnce) return cleaned\n const composed = composeFirstPaintStyle(userProps?.style)\n return composed ? { ...cleaned, ...composed } : cleaned\n },\n ref: mergeRefs(userProps?.ref, motionRef),\n ...(wroteFirstPaintStyle ? { \"data-motion-hydrated\": \"\" } : {}),\n }) as MotionMergedProps<P>\n }\n\n // ---------- Provider for opt-in variant context propagation ----------\n // Accessors recompute on each call so the provided context tracks the live\n // options (variant name changes propagate to descendants).\n //\n // Q4 — gesture slots (hover, press, focus, inView) are ACTIVE-GATED:\n // they return the label only when the corresponding gesture flag is true.\n // When inactive, they return undefined — so descendants' priority chains\n // correctly skip the inherited entry. The non-gesture slots (animate,\n // initial, exit, custom, transition, variants) propagate unconditionally.\n const myVariantCtx: VariantContextValue = {\n variants: () => getOpts().variants,\n // `initial: false` is a parent-only opt-out — don't propagate it. Only\n // variant names (string / string[]) propagate to descendants.\n initial: () => {\n const v = getOpts().initial\n return v === false ? undefined : asVariantLabels(v)\n },\n animate: () => asVariantLabels(getOpts().animate),\n hover: () => (active.whileHover ? asVariantLabels(getOpts().hover) : undefined),\n press: () => (active.whilePress ? asVariantLabels(getOpts().press) : undefined),\n focus: () => (active.whileFocus ? asVariantLabels(getOpts().focus) : undefined),\n inView: () => (active.whileInView ? asVariantLabels(getOpts().inView) : undefined),\n exit: () => asVariantLabels(getOpts().exit),\n custom: () => getOpts().custom,\n transition: () => getOpts().transition,\n }\n\n const Provider: Component<{ children: JSX.Element }> = (props) => (\n <VariantContext.Provider value={myVariantCtx}>{props.children}</VariantContext.Provider>\n )\n\n // Attach Provider to the callable function. Object.assign merges types\n // cleanly for callable-with-properties — TS infers the intersection.\n return Object.assign(getProps, { Provider })\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction computeInitialTarget(\n opts: MotionOptions,\n parentVariantCtx: VariantContextValue,\n presenceInitial?: Accessor<boolean>,\n): Target | null {\n // `<Presence initial={false}>` propagates \"skip the enter animation\" down\n // to every motion descendant. The intent is \"render at the animate target\"\n // — NOT \"render at the initial target with no animation\" (the latter would\n // leave the element looking like it failed to mount). So when the surrounding\n // Presence says \"suppress\", we resolve the animate target as the initial\n // instead of walking the initial chain. The state machine separately skips\n // the first-mount animate dispatch via the same `suppressFirstMount` path.\n if (presenceInitial?.() === false) {\n const animateValue = opts.animate !== undefined ? opts.animate : parentVariantCtx.animate?.()\n if (animateValue === undefined) return null\n return resolveTarget(\n animateValue,\n opts.variants as Variants | undefined,\n undefined,\n opts.custom ?? parentVariantCtx.custom?.(),\n )\n }\n\n if (opts.initial === false) return null\n\n // Priority chain for the initial-state target:\n // own.initial > parent.initial > own.animate > parent.animate\n // Each level is consulted only if the previous is undefined. This matches\n // motion/react's variant-context behavior — children without their own\n // initial/animate props inherit from the ancestor motion element.\n const inheritedInitial = parentVariantCtx.initial?.()\n const inheritedAnimate = parentVariantCtx.animate?.()\n const effective =\n opts.initial !== undefined\n ? opts.initial\n : inheritedInitial !== undefined\n ? inheritedInitial\n : opts.animate !== undefined\n ? opts.animate\n : inheritedAnimate\n if (effective === undefined) return null\n\n return resolveTarget(\n effective,\n opts.variants as Variants | undefined,\n undefined, // priority chain already consumed parent's labels\n opts.custom ?? parentVariantCtx.custom?.(),\n )\n}\n\n// Re-export Transition for downstream consumers that destructure from useMotion's module.\nexport type { Transition }\n","import { mergeRefs } from \"@solid-primitives/refs\"\nimport { type Component, type JSX, mergeProps, onMount, splitProps } from \"solid-js\"\nimport { Dynamic } from \"solid-js/web\"\nimport type { ElementProps, MotionElement, MotionOptions, MotionStyle } from \"./types\"\nimport { useMotion } from \"./use-motion\"\n\n// ---------------------------------------------------------------------------\n// motion proxy — Phase 4.\n//\n// `motion` is a Proxy whose property accesses return cached, memoized\n// tag-components: `motion.div`, `motion.svg`, `motion.path`, etc. Each\n// tag-component:\n//\n// 1. Splits incoming props into motion options (fed to useMotion) and\n// element attributes (forwarded to the underlying element reactively).\n// 2. Wires useMotion in its function form so reactive options propagate\n// through to the gesture state machine.\n// 3. Wraps the rendered element in `m.Provider` UNCONDITIONALLY so a\n// variant cascade reaches every motion descendant — the canonical\n// motion-react ergonomic (B1 in ADR 0004).\n// 4. Renders the actual element through <Dynamic>, which transparently\n// handles SVG-vs-HTML namespace resolution.\n//\n// The HOC entry point (`motion.create`) lands in the follow-up commit. This\n// commit ships only the indexable surface for tag-components.\n// ---------------------------------------------------------------------------\n\n/**\n * The exhaustive list of keys that `motion.X` (and `motion.create`,\n * landing next) route to `useMotion` rather than the underlying element.\n * Anything not in this array falls through to `rest` and is spread onto\n * the DOM element via Solid's reactive spread — keeping things like\n * `class`, `onClick`, dynamic style, etc. reactive end-to-end.\n *\n * The `satisfies` clause ensures every entry IS a valid `MotionOptions`\n * key (typos fail to compile). The `_ensureExhaustive` constant below\n * asserts the converse — every `MotionOptions` key appears in this\n * array — so adding a new option to types.ts without registering here\n * fails to compile with the missing key surfaced in the error.\n */\n/**\n * Union of every `MotionOptions` key the proxy splits off from element\n * attributes. Hardcoded as a literal union — NOT derived from\n * `typeof MOTION_OPT_KEYS[number]` — so JSR's \"slow types\" rule can\n * resolve the public type without inferring it from a const.\n *\n * Two compile-time exhaustiveness directions guarantee consistency\n * between this type and the runtime `MOTION_OPT_KEYS` array:\n *\n * 1. `_MissingMotionOptKeys` (below) verifies the union covers every\n * key in `keyof MotionOptions`.\n * 2. The `satisfies` clause on `MOTION_OPT_KEYS` verifies every array\n * entry IS a `MotionOptKey` (typo-proof at the runtime layer).\n *\n * If `MotionOptions` grows a new key, both `_MissingMotionOptKeys`\n * AND `splitProps` at runtime break — the type check surfaces the\n * specific missing key by name.\n */\nexport type MotionOptKey =\n // Variant slots\n | \"initial\"\n | \"animate\"\n | \"exit\"\n // Gesture targets\n | \"hover\"\n | \"press\"\n | \"focus\"\n | \"inView\"\n | \"inViewOptions\"\n // Drag config\n | \"drag\"\n | \"dragConstraints\"\n | \"dragElastic\"\n | \"dragMomentum\"\n | \"dragTransition\"\n | \"dragSnapToOrigin\"\n | \"dragControls\"\n | \"whileDrag\"\n // Pan\n | \"panThreshold\"\n // Variants + transition\n | \"variants\"\n | \"custom\"\n | \"transition\"\n // Animation lifecycle\n | \"onAnimationStart\"\n | \"onAnimationComplete\"\n | \"onAnimationCancel\"\n | \"onUpdate\"\n // Gesture lifecycle\n | \"onHoverStart\"\n | \"onHoverEnd\"\n | \"onPressStart\"\n | \"onPress\"\n | \"onPressCancel\"\n | \"onFocus\"\n | \"onBlur\"\n | \"onPanStart\"\n | \"onPan\"\n | \"onPanEnd\"\n | \"onViewportEnter\"\n | \"onViewportLeave\"\n // Drag lifecycle\n | \"onDragStart\"\n | \"onDrag\"\n | \"onDragEnd\"\n | \"onDragTransitionEnd\"\n\n/**\n * Frozen list of `MotionOptKey`s — fed to `splitProps` at every\n * tag-component render to separate motion options from element\n * attributes. The `satisfies` clause checks every entry against\n * `MotionOptKey` at compile time so typos / drift between the union\n * and the array surface as errors.\n */\nexport const MOTION_OPT_KEYS: readonly MotionOptKey[] = [\n // Variant slots\n \"initial\",\n \"animate\",\n \"exit\",\n // Gesture targets\n \"hover\",\n \"press\",\n \"focus\",\n \"inView\",\n \"inViewOptions\",\n // Drag config\n \"drag\",\n \"dragConstraints\",\n \"dragElastic\",\n \"dragMomentum\",\n \"dragTransition\",\n \"dragSnapToOrigin\",\n \"dragControls\",\n \"whileDrag\",\n // Pan\n \"panThreshold\",\n // Variants + transition\n \"variants\",\n \"custom\",\n \"transition\",\n // Animation lifecycle\n \"onAnimationStart\",\n \"onAnimationComplete\",\n \"onAnimationCancel\",\n \"onUpdate\",\n // Gesture lifecycle\n \"onHoverStart\",\n \"onHoverEnd\",\n \"onPressStart\",\n \"onPress\",\n \"onPressCancel\",\n \"onFocus\",\n \"onBlur\",\n \"onPanStart\",\n \"onPan\",\n \"onPanEnd\",\n \"onViewportEnter\",\n \"onViewportLeave\",\n // Drag lifecycle\n \"onDragStart\",\n \"onDrag\",\n \"onDragEnd\",\n \"onDragTransitionEnd\",\n] as const satisfies readonly MotionOptKey[]\n\n// Compile-time exhaustiveness check (union → keys direction). If a new\n// MotionOptions key is added without being registered in MotionOptKey,\n// TypeScript surfaces the missing key by name here.\ntype _MissingMotionOptKeys = Exclude<keyof MotionOptions, MotionOptKey>\n// Variable prefixed with `_` so biome's noUnusedVariables exempts it —\n// the const exists purely so TypeScript evaluates its type and surfaces\n// the missing key when the constraint fails.\nconst _ensureExhaustive: [_MissingMotionOptKeys] extends [never]\n ? true\n : { _missing: _MissingMotionOptKeys } = true\n\n/**\n * The shape of the `motion` proxy: every HTML/SVG intrinsic element name\n * maps to a typed `Component` whose props are that element's native\n * attribute set intersected with {@link MotionOptions}.\n *\n * The intersected `{ create: ... }` member adds the HOC entry point. The\n * intersection's explicit `create` field wins over the mapped type's\n * lookup (and there's no HTML/SVG tag named `create`), so `motion.create`\n * is unambiguously typed as the HOC.\n */\nexport type Motion = {\n // Override each intrinsic element's `style` to accept `MotionStyle` (which\n // adds transform shortcuts + MotionValue variants on top of standard CSS).\n // Without this override, `<motion.div style={{ scale: mv }} />` wouldn't\n // typecheck — the intrinsic `style: JSX.CSSProperties` doesn't know about\n // motion's transform-shortcut keys or MV values.\n [Tag in keyof JSX.IntrinsicElements]: Component<\n Omit<JSX.IntrinsicElements[Tag], \"style\"> & { style?: MotionStyle } & MotionOptions\n >\n} & {\n /**\n * Wrap a custom Component with motion's behavior. The wrapped Component\n * must forward props (specifically `ref` and `style`) to a single DOM\n * element root — either by spreading `{...props}` on its root or by\n * explicitly setting `ref={props.ref}` and `style={props.style}`. Solid\n * doesn't have `forwardRef`; the contract is enforced by convention and\n * a dev-mode runtime warning if motion's ref never reaches the DOM.\n *\n * @example\n * ```tsx\n * function MyCard(props) {\n * return <div {...props}>{props.children}</div>\n * }\n * const Animated = motion.create(MyCard)\n * <Animated animate={{ x: 100 }} hover={{ scale: 1.05 }} class=\"card\" />\n * ```\n */\n // biome-ignore lint/suspicious/noExplicitAny: Solid's Component<P> requires P extends Record<string, any>\n create: <P extends Record<string, any>>(Component: Component<P>) => Component<P & MotionOptions>\n}\n\n// Module-level cache. `motion.div` returns the SAME component instance\n// across reads, which (a) lets Solid's reconciler skip redundant work and\n// (b) keeps component identity stable for HMR + dev tooling.\n// Solid's `Component<P>` is constrained to `P extends Record<string, any>`,\n// so we use `any` here. The Motion type narrows the per-tag prop shape at\n// the call site (motion.div has DivProps & MotionOptions); this storage\n// uniformity is purely internal.\n// biome-ignore lint/suspicious/noExplicitAny: Component<P> requires P extends Record<string, any>\ntype AnyComponent = Component<any>\n\nconst tagComponentCache = new Map<string, AnyComponent>()\n\n// WeakSet of every component the proxy has manufactured (tag-components AND\n// HOC-wrapped components). Used for the dev-mode `motion.create(motion.X)`\n// double-wrap warning. WeakSet so HMR-replaced components don't pin their\n// predecessors alive.\nconst motionComponents = new WeakSet<object>()\n\nfunction makeMotionTag(tag: string): AnyComponent {\n const cached = tagComponentCache.get(tag)\n if (cached) return cached\n\n const Tag: Component<ElementProps & MotionOptions> = (props) => {\n const [motionOpts, rest] = splitProps(props, MOTION_OPT_KEYS)\n const m = useMotion(() => motionOpts)\n return (\n <m.Provider>\n <Dynamic component={tag} {...m(rest as ElementProps)} />\n </m.Provider>\n )\n }\n const stored = Tag as AnyComponent\n tagComponentCache.set(tag, stored)\n motionComponents.add(stored)\n return stored\n}\n\n/**\n * `motion.create(Component)` — wraps a custom Component with motion's\n * behavior. The wrapped Component must forward props to a single DOM\n * element root; the contract is documented in the {@link Motion.create}\n * JSDoc above and enforced at runtime (in dev mode) by detecting whether\n * motion's ref ever reaches the DOM after mount.\n */\n// biome-ignore lint/suspicious/noExplicitAny: matches Motion.create's generic constraint\nfunction motionCreate<P extends Record<string, any>>(\n Component: Component<P>,\n): Component<P & MotionOptions> {\n // Dev-mode `motion.create(motion.X)` warning. Double-wrapping puts two\n // motion state machines on the SAME root element — both register with\n // Presence, both dispatch animate() writes, and the resulting writes\n // race. Users almost always meant to compose options at one layer.\n if (\n process.env.NODE_ENV !== \"production\" &&\n motionComponents.has(Component as unknown as object)\n ) {\n console.warn(\n \"[solidjs-motion] motion.create(motion.X) double-wraps the same element \" +\n \"with two motion state machines. Compose options on a single layer instead.\",\n )\n }\n\n const Wrapped: Component<P & MotionOptions> = (props) => {\n const [motionOpts, rest] = splitProps(\n props as unknown as Record<string, unknown>,\n MOTION_OPT_KEYS,\n )\n const m = useMotion(() => motionOpts as MotionOptions)\n\n // Dev-mode wrap-validity check (Q7 in the design grill / future ADR\n // 0004): the wrapped Component must forward props.ref to a DOM\n // element so motion's animations and exit registration can actually\n // wire up. We can't enforce this at the type level in Solid (refs\n // are conventionally optional, indistinguishable from \"missing\"), so\n // we detect at runtime by riding a sentinel through the user-ref\n // slot. `m()`'s internal mergeRefs combines this sentinel with\n // motion's own ref — both fire together when the wrapped Component\n // forwards props.ref to a DOM element. If neither fires after the\n // mount cycle, the wrap is broken.\n //\n // The sentinel-merged ref is computed eagerly (not as a getter) so\n // Solid's spread equality check doesn't churn — refs are stable\n // callbacks set once per mount.\n let refFired = false\n const detector = (_el: MotionElement) => {\n refFired = true\n }\n const userRef = (rest as { ref?: ((el: MotionElement) => void) | MotionElement }).ref\n const mergedUserRef =\n process.env.NODE_ENV !== \"production\"\n ? mergeRefs(userRef as ((el: MotionElement) => void) | undefined, detector)\n : userRef\n const restWithDetector =\n process.env.NODE_ENV !== \"production\" ? mergeProps(rest, { ref: mergedUserRef }) : rest\n\n if (process.env.NODE_ENV !== \"production\") {\n onMount(() => {\n // Defer one microtask so any synchronous-but-deep ref chain has\n // had a chance to fire. Solid's createRenderEffect runs refs\n // during the synchronous mount, but the Component might wrap\n // its DOM root in another <Show>-like deferral.\n queueMicrotask(() => {\n if (!refFired) {\n console.warn(\n \"[solidjs-motion] motion.create wrapped a Component whose root \" +\n \"didn't receive motion's ref. The wrapped Component must \" +\n \"either spread {...props} on a single DOM element OR \" +\n \"explicitly forward `props.ref` to its root. Motion's \" +\n \"animations and exit registration won't run until this \" +\n \"is fixed.\",\n )\n }\n })\n })\n }\n\n return (\n <m.Provider>\n <Component {...(m(restWithDetector as ElementProps) as unknown as P)} />\n </m.Provider>\n )\n }\n motionComponents.add(Wrapped)\n return Wrapped\n}\n\n/**\n * `motion` — the indexable proxy. Every property access returns a cached\n * motion-aware component for the given HTML/SVG tag. The reserved\n * `motion.create` key returns the HOC entry point.\n *\n * @example HTML element\n * ```tsx\n * <motion.div animate={{ x: 100 }} hover={{ scale: 1.05 }}>\n * draggable card\n * </motion.div>\n * ```\n *\n * @example SVG element (handled transparently via <Dynamic>)\n * ```tsx\n * <motion.path d=\"M0 0 L100 100\" animate={{ pathLength: 1 }} />\n * ```\n *\n * @example Wrapping a custom Component via the HOC\n * ```tsx\n * const Animated = motion.create(MyCard)\n * <Animated animate={{ scale: 1.05 }} class=\"my-card\" />\n * ```\n *\n * Non-string keys (Symbols, well-known properties) return `undefined` so\n * debugging tools and `typeof` checks see a sane shape.\n */\nexport const motion: Motion = new Proxy({} as Motion, {\n get(_target, key) {\n if (typeof key !== \"string\") return undefined\n if (key === \"create\") return motionCreate\n return makeMotionTag(key) as never\n },\n}) as Motion\n","import { resolveElements } from \"@solid-primitives/refs\"\nimport { createListTransition, createSwitchTransition } from \"@solid-primitives/transition-group\"\nimport {\n type Component,\n createEffect,\n createMemo,\n createSignal,\n type JSX,\n Match,\n onCleanup,\n Switch,\n} from \"solid-js\"\nimport { PresenceContext } from \"./presence-context\"\nimport type { MotionElement, PresenceContextValue } from \"./types\"\n\n// ---------------------------------------------------------------------------\n// <Presence> — exit-animation coordinator for motion children.\n//\n// Architecture (see ADR 0003):\n// - Wraps a conditional JSX subtree (typically `<Show>`, `<For>`, or\n// `<Index>` containing `<motion.*>` elements with `exit` declared).\n// - Resolves children via @solid-primitives/refs (`resolveFirst` /\n// `resolveElements`), then routes them through\n// @solid-primitives/transition-group's `createSwitchTransition` (single)\n// or `createListTransition` (list) which keeps exiting elements in the\n// DOM until we explicitly call `done()`.\n// - Each motion child registers a `runExit` callable via PresenceContext\n// when its `createMotion` runs. The callable flips the state machine's\n// `exit` slot and resolves when the resulting animate settles.\n// - On removal, transition-group calls our `onExit(el, done)`. We look up\n// the registered `runExit` and chain `done` onto its promise. If no\n// `runExit` is registered (a non-motion child, or a motion child with no\n// `exit` prop), `done()` fires immediately and the element disappears.\n//\n// SSR: same JSX shape as client (Provider + PresenceCore + Switch/Match).\n// transition-group's helpers are SSR-safe — they pass children through when\n// no DOM refs have fired — so structural divergence (which would break\n// Solid's hydration marker alignment) is avoided. Each child's initial\n// style is still emitted via the existing `useMotion` SSR contract.\n//\n// Single-vs-list dispatch is decided at first resolution and stable for the\n// Presence instance's lifetime — switching mid-life would require torn-down\n// transition-group state, which neither helper supports. Document the\n// constraint (rare in practice; conditional rendering rarely flips between\n// \"one item\" and \"many items\" without unmount).\n// ---------------------------------------------------------------------------\n\n/**\n * Internal helper: maps the public `mode` prop to the value\n * `createSwitchTransition` expects. `popLayout` is intentionally deferred\n * (layout animations are v0.2+); `wait` maps to `out-in`; `sync` is the\n * default and corresponds to transition-group's `parallel`.\n */\nfunction switchMode(mode: PresenceProps[\"mode\"]): \"out-in\" | \"parallel\" {\n return mode === \"wait\" ? \"out-in\" : \"parallel\"\n}\n\n/**\n * Find every motion child registered under `root` (or root itself) and\n * return their [element, runExit] pairs. Walks the `runExits` map and\n * tests containment via `Node.contains`, which is O(depth) per check —\n * cheap because n is bounded by the number of motion children Presence\n * is tracking. Order isn't load-bearing; callers Promise.all the runExits.\n */\nfunction collectSubtreeExits(\n root: MotionElement,\n runExits: Map<MotionElement, () => Promise<void>>,\n): Array<[MotionElement, () => Promise<void>]> {\n const out: Array<[MotionElement, () => Promise<void>]> = []\n for (const [el, fn] of runExits) {\n if (el === root || root.contains(el)) out.push([el, fn])\n }\n return out\n}\n\nexport type PresenceProps = {\n /**\n * Exit/enter coordination.\n * - `\"sync\"` (default) — exit and enter overlap (transition-group's\n * `parallel`). Best for list animations and independent items.\n * - `\"wait\"` — old child fully exits before the new one enters\n * (transition-group's `out-in`). Single-child only; ignored (with a\n * dev-mode warning) when wrapping a list.\n */\n mode?: \"sync\" | \"wait\"\n /**\n * Animate children on first mount. Defaults to `true` (matches motion-\n * react). Set `false` to suppress the entry animation for the very first\n * child(ren); subsequent mounts mid-life still animate.\n */\n initial?: boolean\n /**\n * List-path only — controls what transition-group does with an exiting\n * element while its `exit` animation is playing. Forwarded directly to\n * `@solid-primitives/transition-group`'s `createListTransition`.\n *\n * - `\"move-to-end\"` (default) — the exiting element is appended to the\n * end of the rendered array so its DOM position changes during exit.\n * Fine for grids/cascades; surprising for vertically-stacked toasts\n * because surviving siblings JUMP up while the dismissed item is\n * still fading out below them.\n * - `\"keep-index\"` — the exiting element stays at its original index\n * until exit completes. Surviving siblings don't reflow until the\n * slot is released. Best default for notification stacks.\n * - `\"remove\"` — no exit transition; the element is gone from the\n * rendered array immediately. Useful when the exit is purely visual\n * on the child (e.g., it self-animates via opacity transitions\n * instead of `exit`).\n */\n exitMethod?: \"move-to-end\" | \"keep-index\" | \"remove\"\n children: JSX.Element\n}\n\n/**\n * Wraps a conditional or iterated JSX subtree and runs the descendants'\n * `exit` targets before they unmount. Matches motion-react's\n * `<AnimatePresence>` shape but with Solid's `<Show>` / `<For>` /\n * `<Index>` patterns instead of conditional children.\n *\n * Nested motion children are first-class: when an ancestor unmounts,\n * Presence walks the subtree from each resolved child and fires every\n * registered `runExit` it finds in parallel — including motion children\n * nested inside plain wrappers, or descendants whose `exit` label was\n * cascaded down via `m.Provider`. Each motion descendant animates with\n * its own variant/target; transition-group only releases the DOM once\n * the combined `Promise.all` settles. Mirrors motion-react's behavior\n * where a `<motion.div exit={...}>` inside an `<AnimatePresence>` boundary\n * animates correctly regardless of depth.\n *\n * @example Single (conditional unmount)\n * <Presence>\n * <Show when={open()}>\n * <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>\n * saved\n * </motion.div>\n * </Show>\n * </Presence>\n *\n * @example List (items entering and exiting independently)\n * <Presence>\n * <For each={items()}>\n * {(item) => (\n * <motion.li exit={{ opacity: 0, x: 20 }}>{item.text}</motion.li>\n * )}\n * </For>\n * </Presence>\n */\nexport const Presence: Component<PresenceProps> = (props) => {\n // SSR: render the SAME JSX shape as the client (Provider + PresenceCore +\n // <Switch>+<Match>) so Solid's hydration markers align. The transition-\n // group helpers ARE SSR-safe — they return the source elements unchanged\n // when no DOM refs have fired (i.e. during renderToString) — so calling\n // them server-side is harmless and avoids the structural divergence that\n // would otherwise produce hydration mismatches.\n //\n // The only server-time wrinkle is `<Presence initial={false}>`:\n // useMotion's first-paint composition reads `PresenceContext.initial`\n // and, when false, emits the ANIMATE target style instead of the\n // initial. We honor that by setting the signal's seed value below.\n //\n // ---------- PresenceContext value supplied to descendants ----------\n const runExits = new Map<MotionElement, () => Promise<void>>()\n // Enter callbacks — symmetric to runExits. createMotion registers a\n // `runEnter` when it's inside this Presence; we fire it the moment the\n // element is actually inserted into the DOM (from transition-group's\n // onEnter / onChange.added). One-shot — deleted after firing so we don't\n // re-trigger the enter animate on subsequent renders.\n const runEnters = new Map<MotionElement, () => void>()\n // `initial` is read at construction. We flip it to `true` after the first\n // microtask so mid-life inserts DO animate even if the user set\n // `initial={false}`. Matches motion-react's behavior.\n const [presenceInitial, setPresenceInitial] = createSignal(props.initial ?? true)\n queueMicrotask(() => setPresenceInitial(true))\n\n const ctx: PresenceContextValue = {\n register: (el, runExit) => {\n runExits.set(el, runExit)\n },\n unregister: (el) => {\n runExits.delete(el)\n },\n beforeUnmount: (el) => {\n // Walk the subtree rooted at `el` and fire every registered runExit\n // we find — the root's own (if registered) plus every descendant\n // that's a motion child. They all run concurrently; we await the\n // combined Promise.all so transition-group only releases the DOM\n // once every motion descendant has finished its exit, then prune\n // the entries from the registry.\n //\n // This is the mechanism that makes motion-react's parent-cascade\n // exit pattern work for us: when an ancestor unmounts, each nested\n // motion child still runs its OWN exit (its runExit closure already\n // captures the element, `getOpts`, and the state-machine handles,\n // so it doesn't matter that Solid has disposed the surrounding\n // owner). Callers don't need to unregister individually — this\n // method finishes the bookkeeping for the whole subtree.\n const exiting = collectSubtreeExits(el, runExits)\n if (exiting.length === 0) return Promise.resolve()\n return Promise.all(exiting.map((pair) => pair[1]())).then(() => {\n for (const [exitedEl] of exiting) runExits.delete(exitedEl)\n })\n },\n registerEnter: (el, runEnter) => {\n runEnters.set(el, runEnter)\n },\n beforeMount: (el) => {\n const fn = runEnters.get(el)\n runEnters.delete(el)\n fn?.()\n },\n initial: presenceInitial,\n }\n\n // CRITICAL — the children-resolution dance lives INSIDE the Provider's\n // JSX scope so that:\n // (a) motion descendants' refs fire under the Provider's owner and\n // `usePresenceContext` resolves to our `ctx` (not the no-op).\n // (b) resolveElements is called from a stable, single-execution scope.\n // solid-motionone's Presence (1.0.4) achieves this by inlining the\n // transition-group call as the Provider's only child; we extend\n // that to two paths by routing through a tiny `PresenceCore`\n // subcomponent so the resolveElements memo isn't recreated.\n return (\n <PresenceContext.Provider value={ctx}>\n <PresenceCore\n source={() => props.children}\n mode={props.mode}\n exitMethod={props.exitMethod}\n appear={presenceInitial}\n ctx={ctx}\n />\n </PresenceContext.Provider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Internal subcomponent that owns the transition-group machinery. Running\n// the resolution + transition-group setup inside a Solid component (rather\n// than inline JSX or an IIFE) gives us a clean single-execution scope: the\n// component's body runs ONCE per <Presence> instance, the resolveElements\n// memo is set up ONCE, and the transition's createComputed is owned by this\n// component's lifetime. The Provider's value still flows down because this\n// component is rendered AS A CHILD of the Provider.\n// ---------------------------------------------------------------------------\ntype PresenceCoreProps = {\n source: () => JSX.Element\n mode: PresenceProps[\"mode\"]\n exitMethod: PresenceProps[\"exitMethod\"]\n appear: () => boolean\n ctx: PresenceContextValue\n}\n\nconst PresenceCore: Component<PresenceCoreProps> = (p) => {\n // One resolveElements call — both paths read from it. Calling it twice\n // (e.g. resolveFirst + resolveElements) would create two children-\n // resolution memos and mount the motion descendants twice.\n const resolved = resolveElements(p.source)\n\n // Sticky single-vs-list decision — DEFERRED until the source resolves\n // to actual data. The earlier \"decide at construction\" approach silently\n // broke any `<For>` that started empty: `Array.isArray(null)` is false,\n // so we'd lock into switch mode and drop every list item past the first.\n // Using a memo with a self-prev short-circuit makes the decision sticky\n // once a non-null value arrives, while still reacting to the first\n // populated read whenever that happens.\n const path = createMemo<\"switch\" | \"list\" | null>((prev) => {\n if (prev) return prev\n const v = resolved()\n if (v == null) return null\n return Array.isArray(v) ? \"list\" : \"switch\"\n })\n\n if (process.env.NODE_ENV !== \"production\") {\n createEffect(() => {\n if (path() === \"list\" && p.mode === \"wait\") {\n console.warn(\n '[solidjs-motion] <Presence mode=\"wait\"> has no meaningful effect with a list of children — \"wait\" sequences a single exiting element before a single entering one. Use it with `<Show>`-style conditional rendering.',\n )\n }\n })\n }\n\n // transition-group's helpers return Accessor<Element[]>. Solid renders\n // accessor functions inline (calls them in a tracking scope), but TS\n // sees Accessor, not JSX.Element. The cast is a no-op at runtime.\n //\n // <Switch> + keyed <Match> renders nothing until the path is decided\n // (the children render as null when both Match `when`s are false). The\n // child function form on Match guarantees the create*Transition call\n // happens AT MOST ONCE, on the branch that wins — both paths can't be\n // set up against the same resolveElements memo.\n return (\n <Switch>\n <Match when={path() === \"switch\"} keyed>\n {(_v) =>\n createSwitchTransition(\n () => {\n const v = resolved()\n return Array.isArray(v) ? (v[0] ?? null) : v\n },\n {\n appear: p.appear(),\n mode: switchMode(p.mode),\n onExit(el, done) {\n // Disable pointer events on the exiting element. In sync\n // mode transition-group keeps the old node in the DOM as\n // a sibling of the new one (with the old one LATER in\n // source order, putting it on top in z-stacking). Without\n // this, the exiting node — even at opacity:0 mid-exit —\n // intercepts pointer events intended for the incoming\n // card, breaking drag and hover on the new element until\n // the exit settles.\n const motionEl = el as MotionElement\n if (motionEl instanceof HTMLElement || motionEl instanceof SVGElement) {\n ;(motionEl.style as CSSStyleDeclaration).pointerEvents = \"none\"\n }\n // beforeUnmount walks the subtree, fires every descendant\n // motion child's runExit in parallel, awaits the combined\n // Promise.all, AND prunes the registry. We just chain\n // done() onto it.\n p.ctx.beforeUnmount(motionEl).then(done)\n },\n onEnter(el, done) {\n // The element was just inserted into the DOM via\n // setReturned (transition-group's createSwitchTransition\n // does this synchronously before invoking onEnter). Fire\n // the child's registered runEnter callback so its state\n // machine can dispatch the first animate against a\n // connected element — without this step, motion's\n // `animate()` would have already completed off-DOM during\n // the surrounding exit (or before the appear-driven\n // insertion). Then unblock transition-group.\n p.ctx.beforeMount?.(el as MotionElement)\n done()\n },\n },\n ) as unknown as JSX.Element\n }\n </Match>\n <Match when={path() === \"list\"} keyed>\n {(_v) =>\n createListTransition(() => resolved.toArray(), {\n appear: p.appear(),\n exitMethod: p.exitMethod,\n onChange({ added, removed, finishRemoved }) {\n // Fire enter callbacks for added elements first —\n // createListTransition has already updated the source array\n // (and Solid's render diff has inserted the new nodes)\n // before `onChange` runs, so this is the analogue of the\n // switch path's onEnter timing. Without it the new motion\n // children's first animate would have dispatched off-DOM at\n // template instantiation and lost their commitStyles.\n for (const el of added) {\n p.ctx.beforeMount?.(el as MotionElement)\n }\n if (removed.length === 0) return\n // Disable pointer events on every exiting node (see\n // switch-path onExit for the rationale — same z-stacking\n // trap applies when a removed list item lingers as a\n // sibling of new/unchanged ones).\n for (const el of removed as MotionElement[]) {\n if (el instanceof HTMLElement || el instanceof SVGElement) {\n ;(el.style as CSSStyleDeclaration).pointerEvents = \"none\"\n }\n }\n // beforeUnmount handles the subtree walk + unregister\n // bookkeeping per root.\n Promise.all((removed as MotionElement[]).map((el) => p.ctx.beforeUnmount(el))).then(\n () => finishRemoved(removed),\n )\n },\n }) as unknown as JSX.Element\n }\n </Match>\n </Switch>\n )\n}\n\n// ---------------------------------------------------------------------------\n// useAnimatePresence — imperative hook variant for library authors.\n//\n// Returns `{ Provider, exit }`. The user wraps their own conditional\n// rendering in the returned Provider and calls `exit()` to trigger exit\n// animations on every motion child currently registered. Resolves when all\n// settle.\n//\n// Use this when:\n// - You're a library author whose internal mount state can't be a Solid\n// `<Show>` (e.g., route transitions controlled by an external state\n// machine; toast queues with non-Solid lifecycle).\n// - You need imperative control over WHEN exits trigger (e.g., await\n// network completion before unmounting).\n//\n// For 95% of application code, prefer `<Presence>` — it handles the\n// children-resolver dance and list semantics automatically.\n// ---------------------------------------------------------------------------\n\nexport type UseAnimatePresenceOptions = {\n /** Same semantics as `<Presence initial>`. Defaults to `true`. */\n initial?: boolean\n}\n\nexport type UseAnimatePresenceResult = {\n /**\n * Provider component to wrap your conditional rendering. Every motion\n * descendant inside this Provider registers with the hook's internal\n * registry and is reachable via `exit()`.\n */\n Provider: Component<{ children: JSX.Element }>\n /**\n * Trigger exit on every motion child currently registered with this\n * hook. Resolves when all exit animations have settled. Calling `exit()`\n * does NOT unmount anything — the caller is responsible for flipping\n * their mount signal once the promise resolves.\n */\n exit: () => Promise<void>\n}\n\nexport function useAnimatePresence(options?: UseAnimatePresenceOptions): UseAnimatePresenceResult {\n const runExits = new Map<MotionElement, () => Promise<void>>()\n const [presenceInitial, setPresenceInitial] = createSignal(options?.initial ?? true)\n // Flip to true after the first microtask so mid-life mounts always animate,\n // regardless of the initial setting.\n queueMicrotask(() => setPresenceInitial(true))\n\n const ctx: PresenceContextValue = {\n register: (el, runExit) => {\n runExits.set(el, runExit)\n },\n unregister: (el) => {\n runExits.delete(el)\n },\n beforeUnmount: (el) => {\n // Mirrors `<Presence>`'s subtree-walk semantics (see its\n // beforeUnmount JSDoc). The hook's own `exit()` API instead\n // iterates the full registry directly — but anyone who hands\n // this ctx to a transition-coordinator that calls `beforeUnmount`\n // gets the same descendant-cascade behavior.\n const exiting = collectSubtreeExits(el, runExits)\n if (exiting.length === 0) return Promise.resolve()\n return Promise.all(exiting.map((pair) => pair[1]())).then(() => {\n for (const [exitedEl] of exiting) runExits.delete(exitedEl)\n })\n },\n initial: presenceInitial,\n }\n\n // Free the registry on owner disposal. Motion children deliberately do NOT\n // unregister in their own onCleanup (see ADR 0003 — that would race ahead\n // of the exit window), so when the hook's owner unmounts without ever\n // calling exit(), this is the only path that drops the entries.\n onCleanup(() => runExits.clear())\n\n const Provider: Component<{ children: JSX.Element }> = (p) => (\n <PresenceContext.Provider value={ctx}>{p.children}</PresenceContext.Provider>\n )\n\n const exit = async (): Promise<void> => {\n // Snapshot the registry at call time so concurrent registrations during\n // the await don't get added to this batch.\n const snapshot = [...runExits.values()]\n await Promise.all(snapshot.map((fn) => fn()))\n }\n\n return { Provider, exit }\n}\n","import { scroll as motionScroll } from \"motion\"\nimport { createEffect, onCleanup } from \"solid-js\"\nimport type { MotionValueAccessor } from \"../types\"\nimport { createMotionValue } from \"./motion-value\"\n\n// ---------------------------------------------------------------------------\n// Scroll progress info — motion's `OnScrollWithInfo` callback receives this\n// shape per scroll tick. Sticking to the small subset we wire into our\n// MotionValues to keep our public types narrow.\n// ---------------------------------------------------------------------------\n\ntype ScrollAxisInfo = {\n current: number\n progress: number\n}\n\ntype MotionScrollInfo = {\n x: ScrollAxisInfo\n y: ScrollAxisInfo\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: motion's offset format is internal; we re-expose it as opaque\ntype ScrollOffset = any[]\n\nexport type CreateScrollOptions = {\n /** Accessor returning the scroll container element. Defaults to window. */\n container?: () => Element | null\n /** Accessor returning the scroll target. Defaults to the container itself. */\n target?: () => Element | null\n /** Primary scroll axis (both axes are still populated regardless). */\n axis?: \"x\" | \"y\"\n /** Intersection offsets controlling when progress reaches 0/1. */\n offset?: ScrollOffset\n}\n\nexport type CreateScrollResult = {\n /** Current scroll-x position in px. Callable: `scrollX()` for reactive read. */\n scrollX: MotionValueAccessor<number>\n /** Current scroll-y position in px. Callable: `scrollY()` for reactive read. */\n scrollY: MotionValueAccessor<number>\n /** Normalized scroll-x progress in `[0, 1]` (or `[0, n]` for multi-offset). */\n scrollXProgress: MotionValueAccessor<number>\n /** Normalized scroll-y progress in `[0, 1]`. */\n scrollYProgress: MotionValueAccessor<number>\n}\n\n/**\n * Bind four {@link MotionValueAccessor}s to a scroll source. Mirrors\n * motion/react's `useScroll`; defaults to the window when no container is\n * supplied. Each returned value is callable as a Solid Accessor AND has the\n * full MotionValue surface, so it composes with `useMotion`'s target,\n * `animate()`, `createTransform`, and direct JSX reactivity.\n *\n * @example\n * const { scrollY, scrollYProgress } = createScroll()\n * const opacity = createTransform(scrollYProgress, [0, 1], [1, 0])\n *\n * @example\n * const [el, setEl] = createSignal<HTMLElement>()\n * const { scrollY } = createScroll({ container: el })\n * <div ref={setEl} style={{ overflow: \"auto\" }}>...</div>\n */\nexport function createScroll(options?: CreateScrollOptions): CreateScrollResult {\n const scrollX = createMotionValue(0)\n const scrollY = createMotionValue(0)\n const scrollXProgress = createMotionValue(0)\n const scrollYProgress = createMotionValue(0)\n\n // motion's scroll callback signature has two forms (OnScrollProgress and\n // OnScrollWithInfo). With two parameters, info is passed.\n const handler = (_progress: number, info?: MotionScrollInfo) => {\n if (!info) return\n scrollX.set(info.x.current)\n scrollY.set(info.y.current)\n scrollXProgress.set(info.x.progress)\n scrollYProgress.set(info.y.progress)\n }\n\n // createEffect — Solid-idiomatic for side-effect setup (attaching the\n // motion scroll subscription). First iteration runs in the next\n // microtask, which is harmless: scroll events can't fire before the\n // microtask flushes after mount. Accessors inside the body (container,\n // target) are tracked — re-init happens when refs change.\n //\n // Each iteration's onCleanup is scoped to that iteration — Solid fires\n // it when the effect re-runs (tearing down the previous subscription)\n // and again when the outer owner disposes (tearing down the final one).\n createEffect(() => {\n const container = options?.container?.() ?? undefined\n const target = options?.target?.() ?? undefined\n const cleanup = motionScroll(handler, {\n container: container as HTMLElement | undefined,\n target: target as HTMLElement | undefined,\n axis: options?.axis,\n offset: options?.offset,\n } as Parameters<typeof motionScroll>[1])\n onCleanup(cleanup)\n })\n\n return { scrollX, scrollY, scrollXProgress, scrollYProgress }\n}\n"],"mappings":";;;;;;;AAaA,IAAaY,sBACXX,cAAwCM;CANxCC,qBAAqB;CACrBC,kBAAkBC,KAAAA;CAClBC,aAAaD,KAAAA;AAI2BH,CAAmB;AAE7D,SAAgBM,kBAA4C;CAC1D,OAAOT,WAAWQ,mBAAmB;AACvC;;;;;;;;;;AAWA,SAAgBE,aAAaC,OAAuC;CAClE,MAAME,QAAkC;EACtCT,eAAeN,iBAAiBa,MAAMP,iBAAiB,OAAO;EAC9DC,YAAYP,iBAAiBa,MAAMN,UAAU;EAC7CE,OAAOT,iBAAiBa,MAAMJ,KAAK;CACrC;CACA,OAAAO,gBAAQN,oBAAoBO,UAAQ;EAAQF;EAAK,IAAAG,WAAA;GAAA,OAAGL,MAAMK;EAAQ;CAAA,CAAA;AACpE;ACVA,IAAa,kBACX,cAAoC;CAXpC,gBAAgB,CAAC;CACjB,kBAAkB,CAAC;CACnB,qBAAqB,QAAQ,QAAQ;AASD,CAAmB;AAEzD,SAAgB,qBAA2C;CACzD,OAAO,WAAW,eAAe;AACnC;;;;;;;;;;;;;;;;;;ACdA,SAAgB,sBAAyC;CACvD,IAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAChE,aAAa;CAEf,MAAM,MAAM,OAAO,WAAW,kCAAkC;CAGhE,OAAO,MAAe,QAAQ;EAC5B,IAAI,IAAI,OAAO;EACf,MAAM,WAAW,MAA2B,IAAI,EAAE,OAAO;EACzD,IAAI,iBAAiB,UAAU,OAAO;EACtC,aAAa,IAAI,oBAAoB,UAAU,OAAO;CACxD,CAAC;AACH;;;;;;;;;;;;AAaA,SAAgB,mBACd,aACA,eACS;CACT,IAAI,gBAAgB,UAAU,OAAO;CACrC,IAAI,gBAAgB,SAAS,OAAO;CACpC,OAAO;AACT;;;;;;;;;ACpCA,IAAa,iCAAiC,IAAI,IAAI;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAGD,IAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,IAAM,gCAAgC,IAAI,IAAI;CAC5C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;;;;;;;;AA0BD,SAAgB,cAAc,OAAkC;CAC9D,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO,KAAA;CAClD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,cAAc,MAAM,EAAE;CACvD,IAAI,gBAAc,KAAK,GAAG,OAAO,cAAe,MAA4B,IAAI,CAAC;CACjF,IAAI,OAAO,UAAU,YAAY,OAAO,cAAe,MAAwB,CAAC;CAChF,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU,OAAO;AAGrE;AAmBA,IAAM,uBAAqE;CAEzE,IAAI,MAAM,cAAc,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,IAAI;CAC7D,IAAI,MAAM,cAAc,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,IAAI;CAC7D,IAAI,MAAM,cAAc,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,IAAI;CAE7D,QAAQ,MAAM,SAAS,EAAE;CACzB,SAAS,MAAM,UAAU,EAAE;CAC3B,SAAS,MAAM,UAAU,EAAE;CAC3B,SAAS,MAAM,UAAU,EAAE;CAE3B,SAAS,MAAM,UAAU,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CAC/D,UAAU,MAAM,WAAW,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CACjE,UAAU,MAAM,WAAW,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CACjE,UAAU,MAAM,WAAW,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CACjE,OAAO,MAAM,QAAQ,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CAC3D,QAAQ,MAAM,SAAS,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CAC7D,QAAQ,MAAM,SAAS,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,KAAK;CAC7D,uBAAuB,MAAM,eAAe,OAAO,MAAM,WAAW,IAAI,GAAG,EAAE,IAAI;AACnF;;;;;;AAOA,SAAgB,uBAAuB,KAA6C;CAClF,OAAO,qBAAqB;AAC9B;;;;;;;AAQA,SAAgB,qBAAqB,KAAa,OAAqB;CACrE,OAAO,qBAAqB,OAAO,KAAK,KAAK;AAC/C;;;;;;;AAYA,SAAgB,eAAe,KAAa,OAA8B;CACxE,IAAI,OAAO,UAAU,UAAU,OAAO;CAEtC,IAAI,IAAI,WAAW,IAAI,GAAG,OAAO,OAAO,KAAK;CAC7C,IAAI,cAAc,IAAI,GAAG,GAAG,OAAO,GAAG,MAAM;CAE5C,OAAO;AACT;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,cAAc,QAAmC;CAC/D,MAAM,MAAuC,CAAC;CAC9C,MAAM,aAAmC,CAAC;CAE1C,KAAK,MAAM,OAAO,QAAQ;EACxB,IAAI,QAAQ,cAAc;EAC1B,MAAM,MAAM,OAAO;EACnB,MAAM,WAAW,cAAc,GAAG;EAClC,IAAI,aAAa,KAAA,GAAW;EAE5B,IAAI,eAAe,IAAI,GAAG,GACxB,WAAW,OAAO;OAElB,IAAI,OAAO,eAAe,KAAK,QAAQ;CAE3C;CAGA,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,OAAO,iBAChB,IAAI,OAAO,YACT,MAAM,KAAK,qBAAqB,KAAK,WAAW,IAAY,CAAC;CAGjE,IAAI,MAAM,SAAS,GACjB,IAAI,YAAY,MAAM,KAAK,GAAG;CAGhC,OAAO;AACT;;;;;;;ACnPA,IAAa,iBACX,cAAmC,CAAA,CAAmB;AAExD,SAAgB,oBAAyC;CACvD,OAAO,WAAW,cAAc;AAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eACd,OACA,UACA,QACe;CACf,IAAI,CAAC,SAAS,CAAC,UAAU,OAAO;CAEhC,MAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;CAClD,IAAI,SAAwB;CAE5B,KAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS;EACd,MAAM,WAAmB,OAAO,YAAY,aAAa,QAAQ,MAAM,IAAI;EAG3E,SAAS,SAAS,OAAO,OAAO,CAAC,GAAG,QAAQ,QAAQ,IAAI,OAAO,OAAO,CAAC,GAAG,QAAQ;CACpF;CAEA,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,gBACd,KACA,QACoC;CACpC,IAAI,QAAQ,KAAA,GAAW,OAAO;CAC9B,OAAO;AACT;;;;;;;;AASA,SAAS,oBAAoB,GAA8C;CACzE,IAAI,OAAO,MAAM,UAAU,OAAO;CAClC,IAAI,MAAM,QAAQ,CAAC,GAAG,OAAO;CAC7B,OAAO;AACT;;;;;;;;;;;;;;;;;AAkBA,SAAgB,sBAAsB,MAA8B;CAClE,OACE,oBAAoB,KAAK,OAAO,KAChC,oBAAoB,KAAK,OAAO,KAChC,oBAAoB,KAAK,KAAK,KAC9B,oBAAoB,KAAK,KAAK,KAC9B,oBAAoB,KAAK,KAAK,KAC9B,oBAAoB,KAAK,MAAM,KAC/B,oBAAoB,KAAK,IAAI;AAEjC;;;;;;;;ACzGA,IAAa,yBAAyB,OAAO,sCAAsC;;;;;;;;;;;;;;;;;;;;;;;AAqCnF,SAAgB,qBAAmC;CACjD,IAAI,UAAqF;CAGzF,MAAM,WAAiC;EACrC,MAAM,OAAqB,UAAoC,CAAC,GAAG;GAIjE,UAAU,OAAO,OAAO;EAC1B;GAGC,yBAAyB,KAAA;CAC5B;CAKA,OAAO,eAAe,UAAU,wBAAwB;EACtD,SAAS,eAAe;GACtB,UAAU;GAIV,aAAa;IACX,IAAI,YAAY,YAAY,UAAU;GACxC;EACF;EACA,YAAY;EACZ,UAAU;EACV,cAAc;CAChB,CAAC;CAED,OAAO;AACT;;;ACvEA,SAAS,aAAgB,IAA4C;CAEnE,MAAM,CAAC,QAAQ,aAAa,aAAgB,GAAG,IAAI,CAAC;CAGpD,UAAU,GAAG,GAAG,WAAW,MAAM,gBAAgB,CAAC,CAAC,CAAC;CAGpD,MAAM,YAAY,OAAO;CAEzB,OAAO,IAAI,MAAM,IAAI;EACnB,IAAI,QAAQ,MAAM,UAAU;GAG1B,IAAI,SAAS,UAAU,SAAS,WAAW,SAAS,QAClD,OAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;GAG3C,IAAI,QAAQ,IAAI,QAAQ,IAAI,GAAG,OAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;GAExE,MAAM,QAAQ,QAAQ,IAAI,IAAc,MAAM,EAAE;GAChD,OAAO,OAAO,UAAU,aAAa,MAAM,KAAK,EAAE,IAAI;EACxD;EACA,IAAI,QAAQ,MAAM;GAChB,OAAO,QAAQ,IAAI,QAAQ,IAAI,KAAK,QAAS;EAC/C;CACF,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,kBAAqB,SAAoC;CAEvE,MAAM,WAAW,aADN,cAAY,OACO,CAAE;CAGhC,gBAAgB,SAAS,QAAQ,CAAC;CAClC,OAAO;AACT;;;;;;;;;;;;;;;;;AAwBA,SAAgB,SAAY,IAAiC;CAC3D,MAAM,CAAC,OAAO,YAAY,aAAgB,GAAG,IAAI,CAAC;CAClD,UAAU,GAAG,GAAG,WAAW,MAAM,eAAe,CAAC,CAAC,CAAC;CACnD,OAAO;AACT;;;;;;;;;;;AAgBA,SAAgB,uBACd,IACA,OACA,UACM;CACN,UAAU,GAAG,GAAG,OAAO,QAAQ,CAAC;AAClC;AAMA,SAAS,eAAkB,OAAwC;CACjE,IAAI,gBAAc,KAAK,GAAG,OAAQ,MAAyB,IAAI;CAC/D,OAAQ,MAAsB;AAChC;AAEA,SAAS,eACP,OACA,UACM;CACN,IAAI,gBAAc,KAAK,GACrB,UAAW,MAAyB,GAAG,UAAU,QAAQ,CAAC;MAE1D,qBAAqB,SAAU,MAAsB,CAAC,CAAC;AAE3D;;;;;;;;;;;;AAoBA,SAAgB,gBACd,OACA,YACA,aACA,SACwB;CACxB,MAAM,SAAS,UAAgB,YAAY,aAAa,OAAO;CAC/D,MAAM,KAAK,cAAY,OAAO,eAAe,KAAK,CAAC,CAAC;CACpD,gBAAgB,GAAG,QAAQ,CAAC;CAC5B,eAAe,QAAQ,MAAM,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;CAC9C,OAAO,aAAa,EAAE;AACxB;;;;;;;;;AAcA,SAAgB,aACd,QACA,SAC6B;CAC7B,IAAI,gBAAc,MAAM,GAAG;EACzB,MAAM,KAAK,YAAY,QAA+B,OAAO;EAC7D,gBAAgB,GAAG,QAAQ,CAAC;EAC5B,OAAO,aAAa,EAAE;CACxB;CAEA,MAAM,SAAS,cAAa,OAA4B,CAAC;CACzD,gBAAgB,OAAO,QAAQ,CAAC;CAChC,qBAAqB,OAAO,IAAK,OAA4B,CAAC,CAAC;CAC/D,MAAM,KAAK,YAAY,QAAQ,OAAO;CACtC,gBAAgB,GAAG,QAAQ,CAAC;CAC5B,OAAO,aAAa,EAAE;AACxB;;;;;;;;;;AAeA,SAAgB,aAA0C;CACxD,MAAM,KAAK,cAAY,CAAC;CACxB,gBAAgB,GAAG,QAAQ,CAAC;CAC5B,MAAM,YAAY,YAAY,IAAI;CAClC,MAAM,aAAa,GAAG,IAAI,YAAY,IAAI,IAAI,SAAS;CACvD,MAAM,OAAO,MAAM,IAAI;CACvB,gBAAgB,YAAY,IAAI,CAAC;CACjC,OAAO,aAAa,EAAE;AACxB;;;;;;;;;AAcA,SAAgB,eAAe,QAA0D;CACvF,MAAM,KAAK,cAAY,OAAO,YAAY,CAAC;CAC3C,gBAAgB,GAAG,QAAQ,CAAC;CAC5B,UAAU,OAAO,GAAG,gBAAgB,GAAG,IAAI,OAAO,YAAY,CAAC,CAAC,CAAC;CACjE,OAAO,aAAa,EAAE;AACxB;;;;;;;;;;;;AAoBA,SAAgB,eACd,SACA,GAAG,QAC0B;CAC7B,MAAM,gBAAwB;EAC5B,IAAI,MAAM;EACV,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACvC,OAAO,QAAQ;GACf,IAAI,IAAI,OAAO,QAAQ;IACrB,MAAM,IAAI,OAAO;IACjB,IAAI,gBAAc,CAAC,GACjB,OAAO,OAAQ,EAA2B,IAAI,CAAC;SAC1C,IAAI,OAAO,MAAM,YACtB,OAAO,OAAQ,EAAwB,CAAC;SAExC,OAAO,OAAO,CAAC;GAEnB;EACF;EACA,OAAO;CACT;CAEA,MAAM,KAAK,cAAY,QAAQ,CAAC;CAChC,gBAAgB,GAAG,QAAQ,CAAC;CAE5B,KAAK,MAAM,KAAK,QACd,IAAI,gBAAc,CAAC,GACjB,UAAW,EAA2B,GAAG,gBAAgB,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC;CAK/E,IADoB,OAAO,MAAM,MAAM,OAAO,MAAM,cAAc,CAAC,gBAAc,CAAC,CAC9E,GACF,qBAAqB;EACnB,KAAK,MAAM,KAAK,QACd,IAAI,OAAO,MAAM,cAAc,CAAC,gBAAc,CAAC,GAAG,EAAyB;EAE7E,GAAG,IAAI,QAAQ,CAAC;CAClB,CAAC;CAGH,OAAO,aAAa,EAAE;AACxB;;;;ACvRA,IAAM,qBAAqB;;AAE3B,IAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuF1B,SAAgB,UACd,KACA,UAAuD,CAAC,GACvC;CAGjB,MAAM,UAAkC,OAAO,YAAY,aAAa,gBAAgB;CAKxF,MAAM,CAAC,WAAW,gBAAgB,aAAa,KAAK;CAKpD,MAAM,SAAS,kBAAkB,CAAC;CAClC,MAAM,SAAS,kBAAkB,CAAC;CAClC,MAAM,SAAS,kBAAkB,CAAC;CAClC,MAAM,SAAS,kBAAkB,CAAC;CAClC,MAAM,UAAU,kBAAkB,CAAC;CACnC,MAAM,UAAU,kBAAkB,CAAC;CACnC,MAAM,YAAY,kBAAkB,CAAC;CACrC,MAAM,YAAY,kBAAkB,CAAC;CAOrC,mBAAmB;EACjB,MAAM,KAAK,IAAI;EACf,IAAI,CAAC,IAAI;EAST,IAAI,aAA2B;EAC/B,IAAI,YAA0B;EAC9B,IAAI,YAA2B;EAC/B,IAAI,UAAU;EACd,IAAI,UAA8C,CAAC;EAEnD,SAAS,QAAQ,OAA4B;GAC3C,OAAO;IAAE,GAAG,MAAM;IAAS,GAAG,MAAM;GAAQ;EAC9C;EAEA,SAAS,kBAAyB;GAChC,IAAI,QAAQ,SAAS,GAAG,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;GAE5C,MAAM,QAAQ,QAAQ;GAEtB,MAAM,OAAO,QAAQ,QAAQ,SAAS;GACtC,MAAM,KAAK,KAAK,IAAI,MAAM;GAC1B,IAAI,MAAM,GAAG,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;GACjC,OAAO;IACL,IAAK,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,KAAM;IAC3C,IAAK,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,KAAM;GAC7C;EACF;EAEA,SAAS,UAAU,OAA8B;GAC/C,MAAM,QAAQ,QAAQ,KAAK;GAQ3B,OAAO;IAAE;IAAO,OAPF,YACV;KAAE,GAAG,MAAM,IAAI,UAAU;KAAG,GAAG,MAAM,IAAI,UAAU;IAAE,IACrD;KAAE,GAAG;KAAG,GAAG;IAAE;IAKM,QAJR,aACX;KAAE,GAAG,MAAM,IAAI,WAAW;KAAG,GAAG,MAAM,IAAI,WAAW;IAAE,IACvD;KAAE,GAAG;KAAG,GAAG;IAAE;IAEc,UADd,gBACc;GAAS;EAC1C;;;;;;EAOA,SAAS,UAAU,MAAqB;GACtC,OAAO,IAAI,KAAK,MAAM,CAAC;GACvB,OAAO,IAAI,KAAK,MAAM,CAAC;GACvB,OAAO,IAAI,KAAK,MAAM,CAAC;GACvB,OAAO,IAAI,KAAK,MAAM,CAAC;GACvB,QAAQ,IAAI,KAAK,OAAO,CAAC;GACzB,QAAQ,IAAI,KAAK,OAAO,CAAC;GACzB,UAAU,IAAI,KAAK,SAAS,CAAC;GAC7B,UAAU,IAAI,KAAK,SAAS,CAAC;EAC/B;EAEA,SAAS,cAAc,OAA2B;GAGhD,IAAI,CAAC,iBAAiB,KAAK,GAAG;GAE9B,aAAa,QAAQ,KAAK;GAC1B,YAAY;GACZ,YAAY,MAAM;GAClB,UAAU;GACV,UAAU,CAAC;IAAE,GAAG,KAAK,IAAI;IAAG,OAAO;GAAW,CAAC;GAI/C,aAAa,KAAK;GAClB,OAAO,IAAI,WAAW,CAAC;GACvB,OAAO,IAAI,WAAW,CAAC;GACvB,OAAO,IAAI,CAAC;GACZ,OAAO,IAAI,CAAC;GACZ,QAAQ,IAAI,CAAC;GACb,QAAQ,IAAI,CAAC;GACb,UAAU,IAAI,CAAC;GACf,UAAU,IAAI,CAAC;GAIf,OAAO,iBAAiB,eAAe,aAAa;GACpD,OAAO,iBAAiB,aAAa,YAAY;GACjD,OAAO,iBAAiB,iBAAiB,YAAY;EACvD;EAEA,SAAS,cAAc,OAA2B;GAEhD,IAAI,MAAM,cAAc,WAAW;GAEnC,MAAM,QAAQ,QAAQ,KAAK;GAC3B,MAAM,MAAM,KAAK,IAAI;GAGrB,QAAQ,KAAK;IAAE,GAAG;IAAK;GAAM,CAAC;GAC9B,MAAM,SAAS,MAAM;GACrB,OAAO,QAAQ,SAAS,MAAM,QAAQ,IAAI,KAAK,KAAK,QAClD,QAAQ,MAAM;GAGhB,MAAM,OAAO,UAAU,KAAK;GAG5B,UAAU,IAAI;GAEd,IAAI,CAAC,SAAS;IAIZ,MAAM,YAAY,QAAQ,EAAE,aAAa;IAEzC,IADiB,KAAK,MAAM,KAAK,OAAO,GAAG,KAAK,OAAO,CACnD,KAAY,WAAW;KACzB,UAAU;KACV,aAAa,IAAI;KACjB,QAAQ,EAAE,aAAa,OAAO,IAAI;IACpC;GACF,OACE,QAAQ,EAAE,QAAQ,OAAO,IAAI;GAE/B,YAAY;EACd;EAEA,SAAS,aAAa,OAA2B;GAC/C,IAAI,MAAM,cAAc,WAAW;GAGnC,IAAI,SACF,QAAQ,EAAE,WAAW,OAAO,UAAU,KAAK,CAAC;GAE9C,UAAU;GAIV,aAAa,KAAK;GAClB,aAAa;GACb,YAAY;GACZ,YAAY;GACZ,UAAU,CAAC;GACX,OAAO,oBAAoB,eAAe,aAAa;GACvD,OAAO,oBAAoB,aAAa,YAAY;GACpD,OAAO,oBAAoB,iBAAiB,YAAY;EAC1D;EAEA,GAAG,iBAAiB,eAAe,aAAa;EAKhD,gBAAgB;GACd,GAAG,oBAAoB,eAAe,aAAa;GACnD,OAAO,oBAAoB,eAAe,aAAa;GACvD,OAAO,oBAAoB,aAAa,YAAY;GACpD,OAAO,oBAAoB,iBAAiB,YAAY;EAC1D,CAAC;CACH,CAAC;CAED,OAAO;EACL;EACA,OAAO;GAAE,GAAG;GAAQ,GAAG;EAAO;EAC9B,OAAO;GAAE,GAAG;GAAQ,GAAG;EAAO;EAC9B,QAAQ;GAAE,GAAG;GAAS,GAAG;EAAQ;EACjC,UAAU;GAAE,GAAG;GAAW,GAAG;EAAU;CACzC;AACF;;;;;;;;;;;;;;;AC9RA,SAAS,oBAAoB,IAAyD;CACpF,MAAM,WAAW,mBAAmB,IAAI,EAAE;CAC1C,IAAI,UAAU,OAAO;CAoBrB,MAAM,KAAK,IAAI,kBAAkB;EAd/B,iBAAiB;EACjB,OAAO,CAAC;EACR,aAAa;GACX,aAAa;IACX,WAAW,CAAC;IACZ,iBAAiB,CAAC;IAClB,OAAO,CAAC;IACR,MAAM,CAAC;IACP,OAAO,CAAC;GACV;GACA,cAAc,CAAC;EACjB;CAG+B,CAAc;CAC/C,GAAG,MAAM,EAAE;CACX,mBAAmB,IAAI,IAAI,EAAE;CAC7B,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAS,qBAAqB,IAA2C;CACvE,MAAM,cAAc,cAAuD;EACzE,IAAI,CAAC,aAAa,cAAc,QAAQ,OAAO;EAE/C,IAAI,UAAU,WAAW,WAAW,GAAG;GACrC,MAAM,SAAS,UAAU,MAAM,GAAG,EAAE,EAAE,MAAM,GAAG;GAC/C,MAAM,KAAK,OAAO,WAAW,OAAO,OAAO,GAAG;GAC9C,MAAM,KAAK,OAAO,WAAW,OAAO,OAAO,GAAG;GAC9C,IAAI,CAAC,OAAO,SAAS,EAAE,KAAK,CAAC,OAAO,SAAS,EAAE,GAAG,OAAO;GACzD,OAAO;IAAE,GAAG,OAAO,SAAS,EAAE,IAAI,KAAK;IAAG,GAAG,OAAO,SAAS,EAAE,IAAI,KAAK;GAAE;EAC5E;EACA,IAAI,UAAU,WAAW,SAAS,GAAG;GACnC,MAAM,SAAS,UAAU,MAAM,GAAG,EAAE,EAAE,MAAM,GAAG;GAC/C,MAAM,KAAK,OAAO,WAAW,OAAO,MAAM,GAAG;GAC7C,MAAM,KAAK,OAAO,WAAW,OAAO,MAAM,GAAG;GAC7C,IAAI,CAAC,OAAO,SAAS,EAAE,KAAK,CAAC,OAAO,SAAS,EAAE,GAAG,OAAO;GACzD,OAAO;IAAE,GAAG,OAAO,SAAS,EAAE,IAAI,KAAK;IAAG,GAAG,OAAO,SAAS,EAAE,IAAI,KAAK;GAAE;EAC5E;EAKA,IAAI,IAAI;EACR,IAAI,IAAI;EACR,IAAI,QAAQ;EACZ,MAAM,cAAc,UAAU,MAAM,+CAA+C;EACnF,IAAI,aAAa;GACf,IAAI,OAAO,WAAW,YAAY,MAAM,GAAG;GAC3C,IAAI,OAAO,WAAW,YAAY,MAAM,GAAG;GAC3C,QAAQ;EACV,OAAO;GACL,MAAM,cAAc,UAAU,MAAM,kDAAkD;GACtF,IAAI,aAAa;IACf,IAAI,OAAO,WAAW,YAAY,MAAM,GAAG;IAC3C,IAAI,OAAO,WAAW,YAAY,MAAM,GAAG;IAC3C,QAAQ;GACV;GACA,MAAM,aAAa,UAAU,MAAM,4BAA4B;GAC/D,IAAI,YAAY;IACd,IAAI,OAAO,WAAW,WAAW,MAAM,GAAG;IAC1C,QAAQ;GACV;GACA,MAAM,aAAa,UAAU,MAAM,4BAA4B;GAC/D,IAAI,YAAY;IACd,IAAI,OAAO,WAAW,WAAW,MAAM,GAAG;IAC1C,QAAQ;GACV;EACF;EACA,IAAI,CAAC,OAAO,OAAO;EACnB,OAAO;GAAE,GAAG,OAAO,SAAS,CAAC,IAAI,IAAI;GAAG,GAAG,OAAO,SAAS,CAAC,IAAI,IAAI;EAAE;CACxE;CAEA,OAAO,WAAW,iBAAiB,EAAE,EAAE,SAAS,KAAK,WAAW,GAAG,MAAM,SAAS,KAAK;EAAE,GAAG;EAAG,GAAG;CAAE;AACtG;;;;;;;;AASA,SAAS,eAAe,MAAqC;CAC3D,IAAI,SAAS,KAAK,OAAO;CACzB,IAAI,SAAS,KAAK,OAAO;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAgCA,SAAS,mBACP,aACA,IACA,YACA,YACuB;CACvB,IAAI,CAAC,aAAa,OAAO;CAOzB,IAAI,YAAgC;CACpC,IAAI,uBAAuB,aACzB,YAAY;MACP,IAAI,OAAO,gBAAgB,YAChC,YAAY,YAAY;CAG1B,IAAI,WAAW;EAOb,MAAM,gBAAgB,UAAU,sBAAsB;EACtD,MAAM,cAAc,GAAG,sBAAsB;EAC7C,OAAO;GACL,MAAM,cAAc,cAAc,OAAO,YAAY;GACrD,MAAM,cAAc,cAAc,QAAQ,YAAY;GACtD,MAAM,cAAc,cAAc,MAAM,YAAY;GACpD,MAAM,cAAc,cAAc,SAAS,YAAY;EACzD;CACF;CAGA,MAAM,UAAU;CAChB,OAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ,SAAS;EACvB,MAAM,QAAQ,OAAO;EACrB,MAAM,QAAQ,UAAU;CAC1B;AACF;;;;;;;;;;;;AAaA,SAAS,aAAa,OAAe,KAAa,KAAa,SAAyB;CACtF,IAAI,QAAQ,KAAK,OAAO,OAAO,QAAQ,OAAO;CAC9C,IAAI,QAAQ,KAAK,OAAO,OAAO,QAAQ,OAAO;CAC9C,OAAO;AACT;AAEA,IAAM,kBAAkB;;;;;;;;;AAUxB,IAAM,0BAA0B;CAC9B,MAAM;CACN,OAAO;CACP,cAAc;CACd,iBAAiB;CACjB,eAAe;CACf,WAAW;CACX,WAAW;AACb;;;;;;;;;;;;;;AAeA,SAAgB,WACd,IACA,SACA,WACM;CAIN,IAAI,MAAkC;CACtC,IAAI,MAAkC;;;CAGtC,IAAI,aAAa;CACjB,IAAI,aAAa;;;;CAIjB,IAAI,gBAAuC;;;CAG3C,IAAI,kBAAkB;CACtB,IAAI,mBAAmB;CACvB,IAAI,oBAAmC;;;;CAIvC,IAAI,mBAAgD,CAAC;CAErD,SAAS,gBAAyB;EAChC,OAAO,QAAQ,QAAQ,EAAE,IAAI;CAC/B;CAEA,SAAS,8BAAoC;EAC3C,SAAS,KAAK,MAAM,aAAa;EACjC,GAAG,MAAM,cAAc;CACzB;CAEA,SAAS,8BAAoC;EAC3C,IAAI,sBAAsB,MAAM;EAChC,IAAI;GACF,GAAG,sBAAsB,iBAAiB;EAC5C,QAAQ,CAER;EACA,oBAAoB;CACtB;CAEA,SAAS,eAAqB;EAC5B,KAAK,MAAM,QAAQ,kBAAkB,KAAK,KAAK;EAC/C,mBAAmB,CAAC;CACtB;CAKA,MAAM,kBAAkB,OAAqB,MAAe,oBAAoB,UAAU;EAKxF,IAAI,CAAC,cAAc,GAAG;EAKtB,aAAa;EAEb,MAAM,KAAK,oBAAoB,EAAE;EACjC,MAAM,GAAG,SAAS,KAAK,CAAC;EACxB,MAAM,GAAG,SAAS,KAAK,CAAC;EAoBxB,MAAM,OAAO,QAAQ,EAAE;EACvB,IAAI,mBAAmB;GACrB,aAAa,IAAI,IAAI;GACrB,aAAa,IAAI,IAAI;EACvB,OAAO;GACL,MAAM,UAAU,qBAAqB,EAAE;GACvC,IAAI,SAAS,KAAK;IAChB,IAAI,QAAQ,MAAM,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,CAAC;IAC9C,aAAa,QAAQ;GACvB,OACE,aAAa,IAAI,IAAI;GAEvB,IAAI,SAAS,KAAK;IAChB,IAAI,QAAQ,MAAM,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,CAAC;IAC9C,aAAa,QAAQ;GACvB,OACE,aAAa,IAAI,IAAI;EAEzB;EAMA,gBAAgB,mBAAmB,QAAQ,EAAE,iBAAiB,IAAI,YAAY,UAAU;EAIxF,kBAAkB,SAAS,KAAK,MAAM;EACtC,mBAAmB,GAAG,MAAM;EAC5B,SAAS,KAAK,MAAM,aAAa;EACjC,GAAG,MAAM,cAAc,eAAe,QAAQ,EAAE,IAAI;EAKpD,IAAI;GACF,GAAG,kBAAkB,MAAM,SAAS;GACpC,oBAAoB,MAAM;EAC5B,QAAQ,CAER;EAEA,UAAU,aAAa,IAAI;EAC3B,QAAQ,EAAE,cAAc,OAAO,IAAI;CACrC;CAEA,MAAM,aAAa,OAAqB,SAAkB;EACxD,IAAI,CAAC,cAAc,KAAK,CAAC,OAAO,CAAC,KAAK;EAEtC,MAAM,OAAO,QAAQ,EAAE;EAKvB,MAAM,SAAS,SAAS;EACxB,MAAM,SAAS,SAAS;EACxB,MAAM,UAAU,QAAQ,EAAE,eAAe;EAEzC,IAAI,QAAQ;GACV,MAAM,aAAa,aAAa,KAAK,OAAO;GAC5C,MAAM,SAAS,gBACX,aAAa,YAAY,cAAc,MAAM,cAAc,MAAM,OAAO,IACxE;GACJ,IAAI,IAAI,MAAM;EAChB;EACA,IAAI,QAAQ;GACV,MAAM,aAAa,aAAa,KAAK,OAAO;GAC5C,MAAM,SAAS,gBACX,aAAa,YAAY,cAAc,MAAM,cAAc,MAAM,OAAO,IACxE;GACJ,IAAI,IAAI,MAAM;EAChB;EAEA,QAAQ,EAAE,SAAS,OAAO,IAAI;CAChC;CAEA,MAAM,gBAAgB,OAAqB,SAAkB;EAC3D,IAAI,CAAC,cAAc,KAAK,CAAC,OAAO,CAAC,KAAK;EAMtC,UAAU,aAAa,KAAK;EAC5B,4BAA4B;EAC5B,4BAA4B;EAE5B,QAAQ,EAAE,YAAY,OAAO,IAAI;EAKjC,MAAM,OAAO;EACb,MAAM,OAAO;EACb,MAAM,YAAY;EAClB,MAAM,OAAO,QAAQ;EACrB,MAAM,eAAe,KAAK,oBAAoB;EAC9C,MAAM,WAAW,KAAK,gBAAgB;EACtC,MAAM,iBAAiB,KAAK,kBAAkB,CAAC;EAQ/C,MAAM,WAAW,KAAK;EACtB,MAAM,WAAW,aAAa;EAC9B,MAAM,WAAW,aAAa;EAM9B,mBAAmB,CAAC;EAYpB,MAAM,UAAU,KAAK,eAAe;EACpC,MAAM,eAAe,UACjB;GAAE,iBAAiB;GAAK,eAAe;EAAG,IAC1C;GAAE,iBAAiB;GAAW,eAAe;EAAW;EAU5D,MAAM,SAAS,cAAc,QAAQ,UAAU,SAAS,YAAY,KAAK,IAAI,KAAK,UAAU;EAC5F,MAAM,SACJ,cAAc,QAAQ,UAAU,SAAS,aAAa,KAAK,IAAI,KAAK,UAAU;EAChF,MAAM,SAAS,cAAc,QAAQ,UAAU,SAAS,YAAY,KAAK,IAAI,KAAK,UAAU;EAC5F,MAAM,SACJ,cAAc,QAAQ,UAAU,SAAS,aAAa,KAAK,IAAI,KAAK,UAAU;EAChF,MAAM,YACJ,CAAC,YAAa,UAAU,KAAK,SAAS,IAAI,KAAO,UAAU,KAAK,SAAS,IAAI,KACzE,IACA,KAAK,SAAS;EACpB,MAAM,YACJ,CAAC,YAAa,UAAU,KAAK,SAAS,IAAI,KAAO,UAAU,KAAK,SAAS,IAAI,KACzE,IACA,KAAK,SAAS;;;;EAKpB,MAAM,0BAA0B,QAAQ,EAAE,sBAAsB;EAEhE,IAAI,cAAc;GAIhB,MAAM,cAAc;IAClB,GAAG;IACH,GAAG;IACH,GAAG;IACH,UAAU;IACV,KAAK;IACL,KAAK;GACP;GACA,MAAM,cAAc;IAClB,GAAG;IACH,GAAG;IACH,GAAG;IACH,UAAU;IACV,KAAK;IACL,KAAK;GACP;GACA,MAAM,UAA+D,CAAC;GACtE,IAAI,UAAU;IAEZ,MAAM,QAAQ,UAAQ,MAAM,GAAG,WAAkB;IACjD,iBAAiB,KAAK,KAAK;IAC3B,QAAQ,KAAK,KAAK;GACpB;GACA,IAAI,UAAU;IAEZ,MAAM,QAAQ,UAAQ,MAAM,GAAG,WAAkB;IACjD,iBAAiB,KAAK,KAAK;IAC3B,QAAQ,KAAK,KAAK;GACpB;GACA,IAAI,QAAQ,SAAS,GAAG,QAAQ,IAAI,OAAO,EAAE,KAAK,iBAAiB;QAC9D,kBAAkB;EACzB,OAAO;GAWL,MAAM,mBAAmB,WAAW,YAAY;GAChD,MAAM,mBAAmB,WAAW,YAAY;GAChD,MAAM,cAAc;IAClB,GAAG;IACH,GAAG;IACH,GAAG;IACH,UAAU;IACV,KAAK,WAAW;IAChB,KAAK,WAAW;GAClB;GACA,MAAM,cAAc;IAClB,GAAG;IACH,GAAG;IACH,GAAG;IACH,UAAU;IACV,KAAK,WAAW;IAChB,KAAK,WAAW;GAClB;GACA,MAAM,UAA+D,CAAC;GACtE,IAAI,UAAU;IAEZ,MAAM,QAAQ,UAAQ,MAAM,GAAG,WAAkB;IACjD,iBAAiB,KAAK,KAAK;IAC3B,QAAQ,KAAK,KAAK;GACpB;GACA,IAAI,UAAU;IAEZ,MAAM,QAAQ,UAAQ,MAAM,GAAG,WAAkB;IACjD,iBAAiB,KAAK,KAAK;IAC3B,QAAQ,KAAK,KAAK;GACpB;GACA,IAAI,QAAQ,SAAS,GAAG,QAAQ,IAAI,OAAO,EAAE,KAAK,iBAAiB;QAC9D,kBAAkB;EACzB;EAEA,MAAM;EACN,MAAM;EACN,gBAAgB;CAClB;CAKA,gBACQ,WACC;EACL,WAAW,QAAQ,EAAE;EACrB,YAAY;EACZ,OAAO;EACP,UAAU;CACZ,EACF;CAkBA,SAAS,kBAAkB,OAAqB,SAAyC;EACvF,IAAI,CAAC,cAAc,GAAG;EAMtB,IAAI,QAAQ,cAAc;GACxB,MAAM,KAAK,oBAAoB,EAAE;GACjC,MAAM,UAAU,GAAG,SAAS,KAAK,CAAC;GAClC,MAAM,UAAU,GAAG,SAAS,KAAK,CAAC;GAClC,MAAM,SAAS,GAAG,sBAAsB;GACxC,MAAM,UAAU,OAAO,OAAO,OAAO,QAAQ;GAC7C,MAAM,UAAU,OAAO,MAAM,OAAO,SAAS;GAC7C,MAAM,OAAO,QAAQ,EAAE;GACvB,IAAI,SAAS,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,MAAM,UAAU,QAAQ;GACvE,IAAI,SAAS,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,MAAM,UAAU,QAAQ;EACzE;EAgBA,eAAe,OAAO;GALpB,OAAO;IAAE,GAAG,MAAM;IAAS,GAAG,MAAM;GAAQ;GAC5C,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;GACpB,QAAQ;IAAE,GAAG;IAAG,GAAG;GAAE;GACrB,UAAU;IAAE,GAAG;IAAG,GAAG;GAAE;EAEH,GAAa,QAAQ,QAAQ,YAAY,CAAC;EAKhE,MAAM,oBAAoB;GAAE,GAAG,MAAM;GAAS,GAAG,MAAM;EAAQ;EAC/D,IAAI,mBAAmB,EAAE,GAAG,kBAAkB;EAC9C,MAAM,mBAAmB,MAAM;EAC/B,MAAM,iBAAwE,CAC5E;GAAE,GAAG,KAAK,IAAI;GAAG,OAAO,EAAE,GAAG,kBAAkB;EAAE,CACnD;EAEA,SAAS,yBAAmD;GAC1D,IAAI,eAAe,SAAS,GAAG,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;GACnD,MAAM,QAAQ,eAAe;GAC7B,MAAM,OAAO,eAAe,eAAe,SAAS;GACpD,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;GACzC,MAAM,KAAK,KAAK,IAAI,MAAM;GAC1B,IAAI,MAAM,GAAG,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;GACjC,OAAO;IACL,IAAK,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,KAAM;IAC3C,IAAK,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,KAAM;GAC7C;EACF;EAEA,SAAS,iBAAiB,GAA0B;GAClD,MAAM,QAAQ;IAAE,GAAG,EAAE;IAAS,GAAG,EAAE;GAAQ;GAC3C,OAAO;IACL;IACA,OAAO;KAAE,GAAG,MAAM,IAAI,iBAAiB;KAAG,GAAG,MAAM,IAAI,iBAAiB;IAAE;IAC1E,QAAQ;KAAE,GAAG,MAAM,IAAI,kBAAkB;KAAG,GAAG,MAAM,IAAI,kBAAkB;IAAE;IAC7E,UAAU,uBAAuB;GACnC;EACF;EAEA,SAAS,cAAc,GAAuB;GAC5C,IAAI,EAAE,cAAc,kBAAkB;GACtC,MAAM,QAAQ;IAAE,GAAG,EAAE;IAAS,GAAG,EAAE;GAAQ;GAC3C,MAAM,MAAM,KAAK,IAAI;GACrB,eAAe,KAAK;IAAE,GAAG;IAAK;GAAM,CAAC;GACrC,MAAM,SAAS,MAAM;GACrB,OAAO,eAAe,SAAS,MAAM,eAAe,IAAI,KAAK,KAAK,QAChE,eAAe,MAAM;GAEvB,MAAM,OAAO,iBAAiB,CAAC;GAC/B,mBAAmB;GACnB,UAAU,GAAG,IAAI;EACnB;EAEA,SAAS,aAAa,GAAuB;GAC3C,IAAI,EAAE,cAAc,kBAAkB;GAEtC,aAAa,GADA,iBAAiB,CACd,CAAI;GACpB,OAAO,oBAAoB,eAAe,aAAa;GACvD,OAAO,oBAAoB,aAAa,YAAY;GACpD,OAAO,oBAAoB,iBAAiB,YAAY;EAC1D;EAEA,OAAO,iBAAiB,eAAe,aAAa;EACpD,OAAO,iBAAiB,aAAa,YAAY;EACjD,OAAO,iBAAiB,iBAAiB,YAAY;CACvD;CAMA,mBAAmB;EACjB,MAAM,WAAW,QAAQ,EAAE;EAC3B,IAAI,CAAC,UAAU;EAMf,MAAM,WAAW,SAAS;EAC1B,IAAI,CAAC,UAAU;EAEf,UADmB,SAAS,iBAClB,CAAU;CACtB,CAAC;CAQD,gBAAgB;EACd,aAAa;EACb,IAAI,OAAO,KAAK;GACd,4BAA4B;GAC5B,4BAA4B;EAC9B;CACF,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACttBA,SAAgB,aACd,KACA,UAA6D,CAAC,GAC1C;CACpB,MAAM,CAAC,UAAU,eAAe,aAAa,KAAK;CAClD,MAAM,CAAC,OAAO,YAAY,aAA+C,IAAI;CAQ7E,mBAAmB;EACjB,MAAM,KAAK,IAAI;EACf,IAAI,CAAC,IAAI;EACT,MAAM,OAAO,OAAO,YAAY,aAAa,QAAQ,IAAI;EAEzD,MAAM,YAAY,iBAAiB,KAAK,MAAM;EAC9C,MAAM,WAAW,IAAI,sBAClB,YAAY;GACX,KAAK,MAAM,KAAK,SAAS;IAGvB,KAAK,WAAW,CAAC;IAGjB,SAAS,CAAC;IACV,IAAI,EAAE,gBAAgB;KACpB,YAAY,IAAI;KAChB,IAAI,KAAK,MAAM,SAAS,WAAW;IACrC,OAAO,IAAI,CAAC,KAAK,MACf,YAAY,KAAK;GAErB;EACF,GACA;GACE,MAAM,KAAK,OAAO,KAAK;GACvB,YAAY,KAAK,UAAU;GAC3B;EACF,CACF;EACA,SAAS,QAAQ,EAAE;EAEnB,gBAAgB,SAAS,WAAW,CAAC;CACvC,CAAC;CAED,OAAO;EAAE;EAAU;CAAM;AAC3B;AAEA,SAAS,iBAAiB,QAAsD;CAI9E,IAAI,MAAM,QAAQ,MAAM,GAAG,OAAO;CAClC,IAAI,OAAO,WAAW,UAAU,OAAO;CACvC,IAAI,WAAW,OAAO,OAAO;CAE7B,OAAO;AACT;;;;;;;;ACjGA,SAAgB,eACd,IACA,SACA,WACM;CAmBN,UARkB,MAAM,KAAK,UAAU,UAAU;EAC/C,UAAU,cAAc,IAAI;EAC5B,QAAQ,EAAE,eAAe,KAAK;EAC9B,QAAQ,UAAU;GAChB,UAAU,cAAc,KAAK;GAC7B,QAAQ,EAAE,aAAa,KAAK;EAC9B;CACF,CACU,CAAS;CAyBnB,UAZkB,MAAM,KAAK,UAAU,UAAU;EAC/C,UAAU,cAAc,IAAI;EAC5B,QAAQ,EAAE,eAAe,KAAK;EAC9B,QAAQ,OAAO,SAAS;GACtB,UAAU,cAAc,KAAK;GAC7B,IAAI,KAAK,SACP,QAAQ,EAAE,UAAU,OAAO,IAAI;QAE/B,QAAQ,EAAE,gBAAgB,OAAO,IAAI;EAEzC;CACF,CACU,CAAS;CAenB,IAAI,uBAAuB;CAC3B,MAAM,YAAY,YAAY,IAAI,UAAU,UAAU;EACpD,IAAI,iBAAiB;EACrB,IAAI;GACF,iBAAiB,GAAG,QAAQ,gBAAgB;EAC9C,QAAQ;GACN,iBAAiB;EACnB;EACA,IAAI,gBAAgB;GAClB,UAAU,cAAc,IAAI;GAC5B,uBAAuB;EACzB;EACA,QAAQ,EAAE,UAAU,KAAmB;CACzC,CAAC;CACD,MAAM,WAAW,YAAY,IAAI,SAAS,UAAU;EAClD,IAAI,sBAAsB;GACxB,UAAU,cAAc,KAAK;GAC7B,uBAAuB;EACzB;EACA,QAAQ,EAAE,SAAS,KAAmB;CACxC,CAAC;CACD,UAAU,SAAS;CACnB,UAAU,QAAQ;CAiBlB,MAAM,OAAO,mBACL,WACC;EACL,GAAG,QAAQ,EAAE;EACb,WAAW,UAAqC;GAC9C,IAAI,MAAM,gBACR,QAAQ,EAAE,kBAAkB,KAAK;QAEjC,QAAQ,EAAE,kBAAkB,KAAK;EAErC;CACF,EACF;CACA,mBAAmB;EACjB,UAAU,eAAe,KAAK,SAAS,CAAC;CAC1C,CAAC;AACH;;;ACjIA,IAAM,qBAAuD;CAE3D,GAAG;CACH,GAAG;CACH,GAAG;CACH,YAAY;CACZ,YAAY;CACZ,YAAY;CAEZ,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,QAAQ;CAER,QAAQ;CACR,SAAS;CACT,SAAS;CACT,SAAS;CAET,MAAM;CACN,OAAO;CACP,OAAO;CAEP,aAAa;CACb,sBAAsB;CAEtB,SAAS;AACX;;;;;;AAOA,SAAgB,iBAAiB,KAA4B;CAC3D,OAAO,mBAAmB,QAAQ;AACpC;;;;ACNA,IAAM,uBAAoD,CAAC,GAAG;CAZ5D;CACA;CACA;CACA;CACA;CACA;CACA;AAM4D,CAAW,EAAE,QAAQ;;;;;;;;;;;;;;;;;AAiHnF,SAAgB,0BACd,MACqB;CACrB,MAAM,EACJ,IACA,SACA,kBACA,cACA,qBACA,eACA,qBACA,oBACA,YACA,uBACE;CAOJ,MAAM,CAAC,QAAQ,kBACb,uBACA,YAA+C;EAC7C,SAAS;EACT,aAAa;EACb,YAAY;EACZ,YAAY;EACZ,YAAY;EACZ,WAAW;EACX,MAAM;CACR,CAAC;CAMH,MAAM,eAAe,iBAA0D;EAC7E,MAAM,OAAO,QAAQ;EACrB,MAAM,WAAW,KAAK;EACtB,MAAM,SAAS,KAAK,UAAU,iBAAiB,SAAS;EACxD,OAAO;GACL,SAAS,cACP,KAAK,SACL,UACA,gBAAgB,iBAAiB,UAAU,CAAC,GAC5C,MACF;GACA,aAAa,cACX,KAAK,QACL,UACA,gBAAgB,iBAAiB,SAAS,CAAC,GAC3C,MACF;GACA,YAAY,cACV,KAAK,OACL,UACA,gBAAgB,iBAAiB,QAAQ,CAAC,GAC1C,MACF;GACA,YAAY,cACV,KAAK,OACL,UACA,gBAAgB,iBAAiB,QAAQ,CAAC,GAC1C,MACF;GACA,YAAY,cACV,KAAK,OACL,UACA,gBAAgB,iBAAiB,QAAQ,CAAC,GAC1C,MACF;GAIA,WAAW,cAAc,KAAK,WAAW,UAAU,KAAA,GAAW,MAAM;GACpE,MAAM,cAAc,KAAK,MAAM,UAAU,gBAAgB,iBAAiB,OAAO,CAAC,GAAG,MAAM;EAC7F;CACF,CAAC;CAsBD,MAAM,UAAU,iBAA8C;EAC5D,MAAM,UAAU,aAAa;EAM7B,MAAM,aAAa,OAAO;EAC1B,MAAM,MAAmC,CAAC;EAC1C,KAAK,MAAM,aAAa,sBAAsB;GAC5C,IAAI,CAAC,cAAc,WAAW,QAAQ,gBAAgB,GAAG;GACzD,MAAM,SAAS,QAAQ;GACvB,IAAI,CAAC,QAAQ;GACb,KAAK,MAAM,OAAO,QAAQ;IAExB,IAAI,QAAQ,cAAc;IAE1B,IAAI,OAAO,KAAK;IAGhB,IAAI,CAAC,OAAO,QAAQ,eAAe,QAAQ,OAAO,QAAQ,MAAM;IAChE,IAAI,OAAO;KACT,OAAQ,OAAmC;KAC3C,YAAY,OAAO;KACnB;IACF;GACF;EACF;EACA,OAAO;CACT,CAAC;CAMD,IAAI,eAAiD;CACrD,IAAI,cAAuC,CAAC;CAC5C,IAAI,aAAa;CAMjB,IAAI,uBAA0C,CAAC;CAC/C,SAAS,4BAAkC;EACzC,MAAM,YAAY;EAClB,uBAAuB,CAAC;EACxB,KAAK,MAAM,KAAK,WAAW,EAAE;CAC/B;CAEA,mBAAmB;EACjB,MAAM,OAAO,QAAQ;EACrB,MAAM,OAAO,QAAQ;EAWrB,IAAI,cAAc,cAAc,CAAC,WAAW,GAC1C;EAQF,IAAI,cAAc;EAClB,IAAI,eAAe,cAAc,KAAK,OAAO,MAAM,SAAS,qBAAqB;GAC/E,cAAc,eAAe,IAAI;GACjC,cAAc;EAChB;EACA,aAAa;EAcb,IALE,CAAC,eACD,OAAO,KAAK,IAAI,EAAE,WAAW,KAC7B,OAAO,KAAK,WAAW,EAAE,WAAW,KACpC,KAAK,YAAY,KAAA,KACjB,iBAAiB,UAAU,MAAM,KAAA,GACf;EAGpB,MAAM,UAAmC,CAAC;EAC1C,IAAI;EAEJ,IAAI,CAAC,aAAa;GAChB,KAAK,MAAM,OAAO,MAAM;IACtB,MAAM,QAAQ,KAAK;IAGnB,IAAI,CAAC,OAAO;IACZ,IAAI,YAAY,SAAS,MAAM,OAAO;KACpC,QAAQ,OAAO,MAAM;KAIrB,8BAA8B,MAAM;IACtC;GACF;GACA,KAAK,MAAM,OAAO,aAAa;IAC7B,IAAI,OAAO,MAAM;IAKjB,IAAI,OAAO,cAAc,QAAQ,OAAO,QAAQ,MAAM;IAEtD,MAAM,eACJ,iBAAiB,OAAQ,gBACpB,cAA0C,OAC3C,KAAA;IACN,QAAQ,OAAO,iBAAiB,KAAA,IAAY,eAAe,iBAAiB,GAAG;GACjF;EACF;EAIA,MAAM,UAAU,mBAAmB,aAAa,cAAc,GAAG,oBAAoB,CAAC;EACtF,MAAM,aAAa,gBACjB,aAAa,WAAW,GACxB,KAAK,YACL,2BACA,OACF;EAKA,MAAM,cAAc,yBAAyB,IAAI;EACjD,MAAM,wBAAwB,qBAAqB,aAAa,MAAM,gBAAgB;EAKtF,MAAM,6BAA6B;GACjC,GAAG;GACH,QAAQ,KAAK,yBAAyB,cAAc,KAAK,mBAAmB,CAAC,IAAI,KAAA;GACjF,YAAY,KAAK,4BAEX,cAAc;IACZ,IAAI,yBAAyB,MAC3B,KAAK,sBAAsB,qBAAqB;GAEpD,CAAC,IACH,KAAA;GACJ,QAAQ,KAAK,0BAA0B,cAAc,KAAK,oBAAoB,CAAC,IAAI,KAAA;GACnF,UAAU,KAAK,YACV,WAA2B,cAAc,KAAK,WAAW,MAAM,CAAC,IACjE,KAAA;EACN;EAEA,IAAI,CAAC,eAAe,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;GAOnD,cAAc;IAAE,GAAG;IAAa,GAAG;GAAQ;GAG3C,KAAK,MAAM,OAAO,aAChB,IAAI,EAAE,OAAO,SAAS,EAAE,OAAO,UAAU,OAAO,YAAY;GAO9D,MAAM,EAAE,UAAU,YAAY,OAAO;GAUrC,MAAM,SAA8D,CAAC;GACrE,MAAM,WAAoC,CAAC;GAC3C,KAAK,MAAM,OAAO,OAAO;IACvB,MAAM,QAAQ,MAAM;IACpB,MAAM,WACJ,iBAAiB,OAAQ,gBACpB,cAA0C,OAC3C,iBAAiB,GAAG;IAC1B,MAAM,WAAW,qBAAqB,KAAK,QAAQ;IACnD,IAAI,UACF,OAAO,KAAK;KAAE,IAAI;KAAU;IAAM,CAAC;SAEnC,SAAS,OAAO;GAEpB;GAGA,cAAc,KAAK;GACnB,MAAM,WAAW,oBAAoB;GACrC,IAAI,OAAO,WAAW,GAGpB,eAAe,UAAQ,IAAI,UAAiB,QAAQ;QAC/C;IAKL,MAAM,WAAwC,CAAC;IAC/C,KAAK,MAAM,EAAE,IAAI,WAAW,QAE1B,SAAS,KAAK,UAAQ,IAAW,OAAc,QAAe,CAAC;IAEjE,IAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,GAEjC,SAAS,KAAK,UAAQ,IAAI,UAAiB,QAAQ,CAAC;IAEtD,eAAe,kBAAkB,QAAQ;GAC3C;GAWA,IAAI,gBAAgB,QAAQ;IAC1B,MAAM,aAAa;IAEnB,WAAS,WAAW;KAClB,IAAI,iBAAiB,YAAY,0BAA0B;IAC7D,CAAC;GACH;EACF,OAAO,IAAI,gBAAgB,QAGzB,0BAA0B;EAiB5B,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,QAAQ,KAAK;GACnB,IAAI,CAAC,OAAO;GACZ,IAAI,gBAAc,MAAM,KAAK,GAAG;IAC9B,MAAM,WAAW,MAAM;IACvB,UACE,SAAS,GAAG,WAAW,MAAM;KAI3B,MAAM,WACJ,iBAAiB,OAAQ,gBACpB,cAA0C,OAC3C,iBAAiB,GAAG;KAC1B,MAAM,WAAW,qBAAqB,KAAK,QAAQ;KACnD,IAAI,YAAY,aAAa,UAE3B,UAAQ,UAAiB,GAAU,oBAAoB,CAAQ;UAG/D,UAAQ,IAAI,GAAG,MAAM,EAAE,GAAU,oBAAoB,CAAC;IAE1D,CAAC,CACH;GACF;EACF;CACF,CAAC;CAGD,gBAAgB,cAAc,KAAK,CAAC;CAEpC,SAAS,UAAU,OAAyB,UAAyB;EACnE,eAAe,OAAO,QAAQ;CAChC;;;;;;;;;;;;;;;;;;;CAoBA,SAAS,mBAAkC;EAEzC,IADmB,cAAc,aAAa,EAAE,IAC5C,MAAe,MAAM,OAAO,QAAQ,QAAQ;EAChD,OAAO,IAAI,SAAe,YAAY;GACpC,qBAAqB,KAAK,OAAO;EACnC,CAAC;CACH;CAEA,OAAO;EAAE;EAAW;CAAiB;AACvC;;;;;;;;;;;;;;AAmBA,SAAS,cACP,OACA,QACA,QACS;CACT,IAAI,OAAO,QAAQ,OAAO;CAC1B,QAAQ,OAAR;EACE,KAAK,cACH,OAAO,OAAO,QAAQ,MAAM,KAAA;EAC9B,KAAK,cACH,OAAO,OAAO,QAAQ,MAAM,KAAA;EAC9B,KAAK,cACH,OAAO,OAAO,QAAQ,MAAM,KAAA;EAC9B,KAAK,eACH,OAAO,OAAO,SAAS,MAAM,KAAA;EAG/B,KAAK,aACH,OAAO;EACT,KAAK;EACL,KAAK,QACH,OAAO;CACX;AACF;;AAGA,SAAS,eAAe,SAA+D;CACrF,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,OAAO,SAAS;EACzB,MAAM,QAAQ,QAAQ;EACtB,IAAI,OAAO,IAAI,OAAO,MAAM;CAC9B;CACA,OAAO;AACT;;;;;;AAOA,SAAS,YAAY,QAGnB;CACA,MAAM,QAAiC,CAAC;CACxC,MAAM,eAAiE,CAAC;CACxE,KAAK,MAAM,OAAO,QAAQ;EACxB,MAAM,QAAQ,OAAO;EACrB,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM;GACzC,MAAM,OAAO;GACb;EACF;EACA,IAAI,gBAAc,KAAK,GAAG;GACxB,aAAa,KAAK;IAAE;IAAK,IAAI;GAA8B,CAAC;GAC5D,MAAM,OAAQ,MAA+B,IAAI;EACnD,OAAO,IAAI,OAAO,UAAU,YAC1B,MAAM,OAAQ,MAAwB;OACjC,IAAI,MAAM,QAAQ,KAAK,GAC5B,MAAM,OAAO,MAAM,KAAK,MAAM;GAC5B,IAAI,gBAAc,CAAC,GAAG,OAAQ,EAA2B,IAAI;GAC7D,IAAI,OAAO,MAAM,YAAY,OAAQ,EAAoB;GACzD,OAAO;EACT,CAAC;OAED,MAAM,OAAO;CAEjB;CACA,OAAO;EAAE;EAAO;CAAa;AAC/B;;;;;;;;;AAUA,SAAS,yBAAyB,SAAwD;CAExF,KAAK,MAAM,aAAa,sBACtB,KAAK,MAAM,OAAO,SAAS;EACzB,MAAM,QAAQ,QAAQ;EACtB,IAAI,SAAS,MAAM,cAAc,WAAW,OAAO;CACrD;CAEF,OAAO;AACT;;;;;AAMA,SAAS,qBACP,OACA,MACA,kBAC0B;CAC1B,QAAQ,OAAR;EACE,KAAK,WACH,OAAO,KAAK,WAAW,iBAAiB,UAAU;EACpD,KAAK,cACH,OAAO,KAAK,SAAS,iBAAiB,QAAQ;EAChD,KAAK,cACH,OAAO,KAAK,SAAS,iBAAiB,QAAQ;EAChD,KAAK,cACH,OAAO,KAAK,SAAS,iBAAiB,QAAQ;EAChD,KAAK,eACH,OAAO,KAAK,UAAU,iBAAiB,SAAS;EAClD,KAAK,QACH,OAAO,KAAK,QAAQ,iBAAiB,OAAO;EAC9C,KAAK,aACH,OAAO,KAAK;CAChB;AACF;;;;;;;;;;;;;;;;;;AAmBA,SAAS,kBACP,UAC2B;CAI3B,IAAI,UAAqC;CACzC,MAAM,eAAmC;EACvC,IAAI,CAAC,SACH,UAAU,QAAQ,IAAI,SAAS,KAAK,MAAM,CAAoC,CAAC;EAEjF,OAAO;CACT;CACA,MAAM,UAAU,OAAqD;EACnE,KAAK,MAAM,KAAK,UAAU,GAAG,CAAC;CAChC;CA2BA,OAAO;EAzBL,YAAY;GACV,QAAQ,MAAM,EAAE,KAAK,CAAC;EACxB;EACA,aAAa;GACX,QAAQ,MAAM,EAAE,MAAM,CAAC;EACzB;EACA,YAAY;GACV,QAAQ,MAAM,EAAE,KAAK,CAAC;EACxB;EACA,cAAc;GACZ,QAAQ,MAAM,EAAE,OAAO,CAAC;EAC1B;EACA,gBAAgB;GACd,QAAQ,MAAM,EAAE,SAAS,CAAC;EAC5B;EACA,OAAO;EACP,MAAM;EACN,UAAU,SAAS,QAChB,KAAK,MAAM,KAAK,IAAI,KAAM,EAA4B,YAAY,CAAC,GACpE,CACF;EAEA,OAAO,aAAuB,eAC5B,OAAO,EAAE,KAAK,aAAsB,UAAmB;CAEpD;AACT;;;ACpsBA,SAAgB,sBAAqC;CACnD,MAAM,yBAAS,IAAI,IAAkC;CACrD,MAAM,4BAAY,IAAI,IAA0B;CAEhD,OAAO;EACL,IAAI,KAAK;GACP,OAAO,OAAO,IAAI,GAAG;EACvB;EACA,IAAI,KAAK;GACP,OAAO,OAAO,IAAI,GAAG;EACvB;EACA,YAAY,KAAK,IAAI;GACnB,MAAM,WAAW,OAAO,IAAI,GAAG;GAC/B,IAAI,YAAY,UAAU,IAAI,QAAQ,GAGpC,UAAU,OAAO,QAAQ;GAE3B,OAAO,IAAI,KAAK,EAAE;EACpB;EACA,qBAAqB,KAAK,UAAU;GAClC,MAAM,WAAW,OAAO,IAAI,GAAG;GAC/B,IAAI,UAAU,OAAO;GACrB,MAAM,KAAK,cAAY,QAAQ;GAC/B,OAAO,IAAI,KAAK,EAAE;GAClB,UAAU,IAAI,EAAE;GAChB,OAAO;EACT;EACA,UAAU;GACR,OAAO,OAAO,QAAQ;EACxB;EACA,IAAI,OAAO;GACT,OAAO,OAAO;EAChB;EACA,UAAU;GACR,UAAU,MAAM;GAChB,OAAO,MAAM;EACf;CACF;AACF;;;;;;;AC7EA,SAAgB,gBAAgB,OAA4D;CAC1F,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO;AAEnC;;;;;;;;;;AAWA,SAAgB,cACd,UACA,aACA,aACA,QACe;CAEf,IAAI,aAAa,KAAA,KAAa,OAAO,aAAa,YAAY,CAAC,MAAM,QAAQ,QAAQ,GACnF,OAAO;CAGT,MAAM,SAAS,gBAAgB,UAAU,WAAW;CACpD,IAAI,WAAW,KAAA,GAAW,OAAO;CAIjC,OAAO,eAAe,QAAyB,aAAa,MAAM;AACpE;;;;;;AAOA,SAAgB,gBACd,eACA,eACA,qBACA,SACY;CACZ,IAAI,SAAS,OAAO,EAAE,UAAU,EAAE;CAClC,OAAO;EACL,GAAI,iBAAiB,CAAC;EACtB,GAAI,iBAAiB,CAAC;EACtB,GAAI,uBAAuB,CAAC;CAC9B;AACF;;;;;;AAOA,SAAS,iBAAiB,IAAmB,QAAsB;CACjE,MAAM,QAAQ,cAAc,MAAM;CAClC,KAAK,MAAM,OAAO,OAAO;EACvB,MAAM,QAAS,MAAsD;EACrE,IAAI,UAAU,KAAA,GAAW;EACzB,IAAI,IAAI,WAAW,IAAI,GACrB,GAAG,MAAM,YAAY,KAAK,OAAO,KAAK,CAAC;OAItC,GAAI,MAAqD,OAAO;CAErE;AACF;;;;;;;;;;AA0DA,SAAgB,aACd,IACA,SACA,QACM;CAGN,MAAM,mBAAwC,QAAQ,iBAAiB,kBAAkB;CACzF,MAAM,WAAW,mBAAmB;CACpC,MAAM,eAAe,gBAAgB;CACrC,MAAM,sBAAsB,oBAAoB;CAehD,IAAI;CACJ,MAAM,uBAAsC;EAC1C,IAAI,CAAC,eAAe,gBAAgB,oBAAoB;EACxD,OAAO;CACT;CAIA,MAAM,cAAc,QAAQ,OAAO;CAWnC,IAAI,wBAAuC;CAC3C,IAAI,YAAY,YAAY,OAAO;EACjC,MAAM,mBAAmB,iBAAiB,UAAU;EACpD,MAAM,mBAAmB,iBAAiB,UAAU;EACpD,MAAM,YACJ,YAAY,YAAY,KAAA,IACpB,YAAY,UACZ,qBAAqB,KAAA,IACnB,mBACA,YAAY,YAAY,KAAA,IACtB,YAAY,UACZ;EACV,IAAI,cAAc,KAAA,GAChB,wBAAwB,cACtB,WACA,YAAY,UACZ,KAAA,GACA,YAAY,UAAU,iBAAiB,SAAS,CAClD;CAEJ;CAOA,MAAM,qBAAqB,cAAc,SAAS,UAAU,CAAC,MAAM;CACnE,IAAI,CAAC,QAAQ,uBAAuB,CAAC,sBAAsB,uBACzD,iBAAiB,IAAI,qBAAqB;CA+C5C,MAAM,aAAmB,CAAC;CAC1B,IAAI,SAAqB;CACzB,MAAM,0BAAgC,OAAO;CAE7C,MAAM,uBAA6B;EACjC,IAAI,CAAC,eAAe;EACpB,MAAM,SAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,GAAG,OAAO,cAAc,QAAQ,GAC1C,OAAO,KAAK,GAAG,IAAI;EAErB,IAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;EACtC,iBAAiB,IAAI,MAAgB;CACvC;CAEA,MAAM,+BAA6C;EAEjD,MAAM,CAAC,KAAK,MAAO,cAAgC,QAAQ,EAAE,KAAK,EAAE;EAIpE,IAAI,eAAe,IAAI,GAAG,GAAG;GAI3B,MAAM,YAAY,uBAAuB,GAAG;GAC5C,IAAI,cAAc,KAAA,GAChB,aAAa;IACX,MAAM,IAAI,cAAc,GAAG,IAAI,CAAC;IAChC,IAAI,MAAM,KAAA,GAAW,GAAG,MAAM,YAAY,UAAU,CAAC;GACvD;EAEJ;EACA,IAAI,IAAI,WAAW,IAAI,GACrB,aAAa;GACX,MAAM,IAAI,cAAc,GAAG,IAAI,CAAC;GAChC,IAAI,MAAM,KAAA,GAAW,GAAG,MAAM,YAAY,KAAK,OAAO,CAAC,CAAC;EAC1D;EAEF,aAAa;GACX,MAAM,IAAI,cAAc,GAAG,IAAI,CAAC;GAChC,IAAI,MAAM,KAAA,GAAW;GACrB,MAAM,YAAY,eAAe,KAAK,CAAC;GACtC,GAAI,MAAqD,OAAO;EACnE;CACF;CAEA,MAAM,sBAA4B;EAChC,MAAM,OAAO,eAAe,QAAQ;EACpC,IAAI,SAAS,GAAG;GACd,SAAS;GACT;EACF;EACA,IAAI,SAAS,GAAG;GACd,SAAS,uBAAuB;GAChC;EACF;EACA,SAAS;CACX;CAOA,IAAI,eAAe;CACnB,IAAI,QAAQ,qBAAqB,OAAO,kBAAkB,OAAO,GAAG;EAClE,MAAM,WAAW,eAAe;EAChC,KAAK,MAAM,CAAC,KAAK,OAAO,OAAO,mBAAmB;GAChD,SAAS,YAAY,KAAK,EAAE;GAC5B,UAAU,GAAG,GAAG,UAAU,iBAAiB,CAAC;EAC9C;EACA,eAAe;CACjB;CACA,IAAI,QAAQ,yBAAyB,OAAO,sBAAsB,OAAO,GACvE,eAAe;CAgCjB,IAAI,gBAAgB,uBAAuB;EACzC,MAAM,WAAW,eAAe;EAChC,KAAK,MAAM,OAAO,uBAAuB;GACvC,IAAI,QAAQ,cAAc;GAC1B,IAAI,CAAC,eAAe,IAAI,GAAG,GAAG;GAC9B,IAAI,SAAS,IAAI,GAAG,GAAG;GACvB,MAAM,MAAO,sBAAkD;GAC/D,MAAM,WAAW,cAAc,GAAG;GAClC,IAAI,aAAa,KAAA,GAAW;GAE5B,UADW,SAAS,qBAAqB,KAAK,QACpC,EAAG,GAAG,UAAU,iBAAiB,CAAC;EAC9C;CACF;CACA,IAAI,gBAAgB,QAAQ,uBAAuB;EACjD,MAAM,WAAW,eAAe;EAChC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,uBAAuB;GAIvD,MAAM,WAAW,SAAS,IAAI,GAAG;GACjC,IAAI,UACF,SAAS,IAAI,KAAK;QAGlB,UADW,SAAS,qBAAqB,KAAK,KACpC,EAAG,GAAG,UAAU,iBAAiB,CAAC;EAEhD;CACF;CAKA,IAAI,cAAc;EAKhB,cAAc;EACd,kBAAkB;CACpB;CAaA,MAAM,sBAAsB,KAAa,aAAwD;EAC/F,IAAI,CAAC,cAAc,OAAO,KAAA;EAK1B,MAAM,WAAW,eAAe;EAChC,MAAM,WAAW,SAAS,IAAI,GAAG;EACjC,IAAI,UAAU,OAAO;EACrB,IAAI,CAAC,eAAe,IAAI,GAAG,GAAG,OAAO,KAAA;EACrC,MAAM,KAAK,SAAS,qBAAqB,KAAK,QAAQ;EACtD,UAAU,GAAG,GAAG,UAAU,iBAAiB,CAAC;EAK5C,cAAc;EACd,OAAO;CACT;CAmBA,MAAM,aAAa,SAAS,kBAAkB,KAAA;CAC9C,MAAM,CAAC,YAAY,iBAAiB,aAAa,CAAC,UAAU;CAC5D,IAAI,cAAc,SAAS,eAAe;EACxC,SAAS,cAAc,UAAU,cAAc,IAAI,CAAC;EAWpD,qBAAqB;GACnB,IAAI,GAAG,aAAa,cAAc,IAAI;EACxC,CAAC;CACH;CAqBA,MAAM,EAAE,WAAW,qBAZE,0BAA0B;EAC7C;EACA;EACA;EACA;EACA;EACA,eAAe;EACf,qBAAqB,QAAQ;EAC7B;EACA;EACA;CACF,CACwC;CA8BxC,MAAM,qBAAqB,cAAc,iBAAiB,OAAO,CAAC;CAClE,MAAM,aAAa,YAAY,SAAS,KAAA;CACxC,MAAM,kBAAkB,uBAAuB,KAAA,KAAa,YAAY,aAAa,KAAA;CAErF,IAAI,cAAc,iBAAiB;EACjC,MAAM,UAAU,YAA2B;GAYzC,MAAM,OAAO,QAAQ,OAAO;GAK5B,MAAM,aAAa,cACjB,KAAK,MACL,KAAK,UACL,gBAAgB,cAAc,iBAAiB,OAAO,CAAC,CAAC,GACxD,KAAK,UAAU,iBAAiB,SAAS,CAC3C;GACA,IAAI,CAAC,YAAY;IAIf,UAAU,QAAQ,IAAI;IACtB,MAAM,iBAAiB;IACvB;GACF;GAIA,MAAM,UAAU,mBAAmB,aAAa,cAAc,GAAG,oBAAoB,CAAC;GACtF,MAAM,aAAa,gBACjB,aAAa,WAAW,GACxB,KAAK,YACL,WAAW,YACX,OACF;GAGA,MAAM,aAAsC,CAAC;GAC7C,KAAK,MAAM,KAAK,YACd,IAAI,MAAM,cACR,WAAW,KAAM,WAAuC;GAQ5D,MAHiB,UAAQ,IAAI,YAAmB,UAGzC;EACT;EAEA,SAAS,SAAS,IAAI,OAAO;CAO/B;CAKA,eAAe,IAAI,SAAS,SAAS;CAQrC,IAAI,cAAc,aAChB,WAAW,IAAI,SAAS,SAAS;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9jBA,SAAgBgC,UAAUC,MAA8D;CACtF,MAAMC,UAA+B,OAAOD,SAAS,aAAaA,aAAaA;CAW/E,MAAME,kBAAuCL,kBAAkB;CAC/D,MAAMM,sBAA+BP,sBAAsBK,QAAQ,CAAC;CACpE,MAAMG,mBAAwC;EAC5CC,gBAAiBF,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBG,WAAW;EAC1EE,eAAgBJ,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBK,UAAU;EACxEC,eAAgBL,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBM,UAAU;EACxEC,aAAcN,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBO,QAAQ;EACpEC,aAAcP,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBQ,QAAQ;EACpEC,aAAcR,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBS,QAAQ;EACpEC,cAAeT,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBU,SAAS;EACtEC,YAAaV,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBW,OAAO;EAClEC,cAAeX,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBY,SAAS;EACtEC,kBAAmBZ,cAAc,IAAIG,KAAAA,IAAYJ,gBAAgBa,aAAa;CAChF;CAoBA,MAAMC,cAActC,mBAAmB;CAEvC,MAAMwC,gBAAgBC,qBADF3C,QAAQyB,OACegB,GAAab,kBAAkBY,YAAYT,OAAO;CAM7F,MAAMa,cAAc3C,YAA+C;EACjE+B,SAAS;EACTc,aAAa;EACbC,YAAY;EACZC,YAAY;EACZC,YAAY;EACZC,WAAW;EACXb,MAAM;CACR,CAAC;CACD,MAAM,CAACc,UAAUP;CAmBjB,IAAIQ;CACJ,IAAIE;CACJ,IAAIC,gBAAgB;CAYpB,MAAMC,aAAaC,OAAsB;EACvCrD,aAAaqD,IAAIhC,SAAS;GACxBiC,qBACEhB,kBAAkB,QAClBU,sBAAsBtB,KAAAA,KACtBwB,0BAA0BxB,KAAAA;GAC5Bc;GACAe,eAAe/B;GACfwB;GACAE;EACF,CAAC;CACH;CA2BA,IAAIM,eAAe;CACnB7D,cAAc;EACZ6D,eAAe;CACjB,CAAC;;;;;;;;;;;;;;CAeD,MAAMC,uBAAuBC,UAAyB;EACpD,IAAIP,eAAe;EACnBA,gBAAgB;EAChB,IAAI,CAACO,SAAS,OAAOA,UAAU,UAAU;EACzC,KAAK,MAAMC,OAAOD,OAAO;GACvB,MAAME,QAASF,MAAkCC;GACjD,IAAItE,gBAAcuE,KAAK,GAAG;IACxB,IAAI,CAACZ,mBAAmBA,oCAAoB,IAAIC,IAAI;IACpDD,kBAAkBa,IAAIF,KAAKC,KAA6B;GAC1D,OAAO,IAAIxD,eAAe0D,IAAIH,GAAG,GAAG;IAMlC,MAAMI,OAAO5D,cAAcyD,KAAK;IAChC,IAAIG,SAASrC,KAAAA,GAAW;KACtB,IAAI,CAACwB,uBAAuBA,wCAAwB,IAAID,IAAI;KAC5DC,sBAAsBW,IAAIF,KAAKI,IAAI;IACrC;GACF;EACF;CACF;;;;;;;;;;CAWA,MAAMC,oCAAoCN,UAAsD;EAC9F,IAAI,CAACA,OAAO,OAAO,CAAC;EACpB,MAAMQ,MAA+B,CAAC;EACtC,KAAK,MAAMP,OAAOD,OAAO;GACvB,IAAIV,mBAAmBc,IAAIH,GAAG,GAAG;GACjC,IAAIvD,eAAe0D,IAAIH,GAAG,GAAG;GAC7BO,IAAIP,OAAQD,MAAkCC;EAChD;EACA,OAAOO;CACT;;;;;;;;;;;;;;;;CAiBA,MAAMC,0BAA0BC,cAAiE;EAC/F,MAAMC,SAAkC,CAAC;EACzC,IAAIC,SAAS;EACb,IAAIhC,eAAe;GACjBiC,OAAOC,OAAOH,QAAQ/B,aAAa;GACnCgC,SAAS;EACX;EAEA,IAAItB,mBACF,KAAK,MAAM,CAACW,KAAKc,OAAOzB,mBAAmB;GACzCqB,OAAOV,OAAOc,GAAGC,IAAI;GACrBJ,SAAS;EACX;EAGF,IAAIF,WACF,KAAK,MAAMT,OAAOS,WAAW;GAC3B,IAAIpB,mBAAmBc,IAAIH,GAAG,GAAG;GACjC,IAAI,CAACvD,eAAe0D,IAAIH,GAAG,GAAG;GAC9B,MAAMgB,IAAKP,UAAsCT;GACjD,IAAI,OAAOgB,MAAM,YAAY,OAAOA,MAAM,UAAU;IAClDN,OAAOV,OAAOgB;IACdL,SAAS;GACX;EACF;EAEF,OAAOA,SAASjE,cAAcgE,MAAgB,IAAI;CACpD;CAEA,SAASO,SAAiCC,WAAqC;EAC7EjF,cAAc6D,oBAAoBoB,WAAWnB,KAAK,CAAC;EAInD,MAAMqB,uBACJzC,kBAAkB,QAClBU,sBAAsBtB,KAAAA,KACtBwB,0BAA0BxB,KAAAA;EAC5B,OAAOhC,aAAWmF,aAAa,CAAC,GAAG;GACjC,IAAInB,QAAQ;IACV,MAAMsB,UAAUhB,iCAAiCa,WAAWnB,KAAK;IACjE,IAAIF,cAAc,OAAOwB;IACzB,MAAMC,WAAWd,uBAAuBU,WAAWnB,KAAK;IACxD,OAAOuB,WAAW;KAAE,GAAGD;KAAS,GAAGC;IAAS,IAAID;GAClD;GACAE,KAAK9F,UAAUyF,WAAWK,KAAK9B,SAAS;GACxC,GAAI2B,uBAAuB,EAAE,wBAAwB,GAAG,IAAI,CAAC;EAC/D,CAAC;CACH;CAWA,MAAMI,eAAoC;EACxC1D,gBAAgBJ,QAAQ,EAAEI;EAG1BE,eAAe;GACb,MAAMgD,IAAItD,QAAQ,EAAEM;GACpB,OAAOgD,MAAM,QAAQjD,KAAAA,IAAY3B,gBAAgB4E,CAAC;EACpD;EACA/C,eAAe7B,gBAAgBsB,QAAQ,EAAEO,OAAO;EAChDC,aAAckB,OAAOJ,aAAa5C,gBAAgBsB,QAAQ,EAAEQ,KAAK,IAAIH,KAAAA;EACrEI,aAAciB,OAAOH,aAAa7C,gBAAgBsB,QAAQ,EAAES,KAAK,IAAIJ,KAAAA;EACrEK,aAAcgB,OAAOF,aAAa9C,gBAAgBsB,QAAQ,EAAEU,KAAK,IAAIL,KAAAA;EACrEM,cAAee,OAAOL,cAAc3C,gBAAgBsB,QAAQ,EAAEW,MAAM,IAAIN,KAAAA;EACxEO,YAAYlC,gBAAgBsB,QAAQ,EAAEY,IAAI;EAC1CC,cAAcb,QAAQ,EAAEa;EACxBC,kBAAkBd,QAAQ,EAAEc;CAC9B;CAEA,MAAMiD,YAAkDG,UAAKC,gBAC1DtE,eAAekE,UAAQ;EAACxB,OAAOuB;EAAY,IAAAE,WAAA;GAAA,OAAGE,MAAMF;EAAQ;CAAA,CAAA;CAK/D,OAAOd,OAAOC,OAAOI,UAAU,EAAEQ,SAAS,CAAC;AAC7C;AAMA,SAAS7C,qBACPnB,MACAI,kBACAiE,iBACe;CAQf,IAAIA,kBAAkB,MAAM,OAAO;EACjC,MAAMC,eAAetE,KAAKQ,YAAYF,KAAAA,IAAYN,KAAKQ,UAAUJ,iBAAiBI,UAAU;EAC5F,IAAI8D,iBAAiBhE,KAAAA,GAAW,OAAO;EACvC,OAAOzB,cACLyF,cACAtE,KAAKK,UACLC,KAAAA,GACAN,KAAKc,UAAUV,iBAAiBU,SAAS,CAC3C;CACF;CAEA,IAAId,KAAKO,YAAY,OAAO,OAAO;CAOnC,MAAMgE,mBAAmBnE,iBAAiBG,UAAU;CACpD,MAAMiE,mBAAmBpE,iBAAiBI,UAAU;CACpD,MAAMiE,YACJzE,KAAKO,YAAYD,KAAAA,IACbN,KAAKO,UACLgE,qBAAqBjE,KAAAA,IACnBiE,mBACAvE,KAAKQ,YAAYF,KAAAA,IACfN,KAAKQ,UACLgE;CACV,IAAIC,cAAcnE,KAAAA,GAAW,OAAO;CAEpC,OAAOzB,cACL4F,WACAzE,KAAKK,UACLC,KAAAA,GACAN,KAAKc,UAAUV,iBAAiBU,SAAS,CAC3C;AACF;;;;;;;;;;ACrSA,IAAayE,kBAA2C;CAEtD;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;AAAqB;AAiEvB,IAAMe,oCAAoB,IAAIC,IAA0B;AAMxD,IAAMC,mCAAmB,IAAIC,QAAgB;AAE7C,SAASC,cAAcC,KAA2B;CAChD,MAAMC,SAASN,kBAAkBO,IAAIF,GAAG;CACxC,IAAIC,QAAQ,OAAOA;CAEnB,MAAMZ,OAAgDc,UAAU;EAC9D,MAAM,CAACC,YAAYC,QAAQjC,WAAW+B,OAAOvB,eAAe;EAC5D,MAAM0B,IAAI5B,gBAAgB0B,UAAU;EACpC,OAAAG,gBACGD,EAAEE,UAAQ,EAAA,IAAAC,WAAA;GAAA,OAAAF,gBACRlC,SAAOqC,WAAA,EAACC,WAAWX,IAAG,SAAMM,EAAED,IAAoB,CAAC,CAAA;EAAA,EAAA,CAAA;CAG1D;CACA,MAAMO,SAASvB;CACfM,kBAAkBkB,IAAIb,KAAKY,MAAM;CACjCf,iBAAiBiB,IAAIF,MAAM;CAC3B,OAAOA;AACT;;;;;;;;AAUA,SAASG,aACP/C,WAC8B;CAK9B,IAAA,QAAA,IAAA,aAC2B,gBACzB6B,iBAAiBsB,IAAInD,SAA8B,GAEnDoD,QAAQC,KACN,mJAEF;CAGF,MAAMC,WAAyCnB,UAAU;EACvD,MAAM,CAACC,YAAYC,QAAQjC,WACzB+B,OACAvB,eACF;EACA,MAAM0B,IAAI5B,gBAAgB0B,UAA2B;EAgBrD,IAAImB,WAAW;EACf,MAAMC,YAAYC,QAAuB;GACvCF,WAAW;EACb;EACA,MAAMG,UAAWrB,KAAiEsB;EAClF,MAAME,gBAAAA,QAAAA,IAAAA,aACqB,eACrB9D,UAAU2D,SAAsDF,QAAQ,IACxEE;EACN,MAAMI,mBAAAA,QAAAA,IAAAA,aACqB,eAAe5D,aAAWmC,MAAM,EAAEsB,KAAKE,cAAc,CAAC,IAAIxB;EAErF,IAAA,QAAA,IAAA,aAA6B,cAC3BlC,cAAc;GAKZ4D,qBAAqB;IACnB,IAAI,CAACR,UACHH,QAAQC,KACN,gSAMF;GAEJ,CAAC;EACH,CAAC;EAGH,OAAAd,gBACGD,EAAEE,UAAQ,EAAA,IAAAC,WAAA;GAAA,OAAAF,gBACRvC,WAAS0C,iBAAMJ,EAAEwB,gBAAgC,CAAiB,CAAA;EAAA,EAAA,CAAA;CAGzE;CACAjC,iBAAiBiB,IAAIQ,OAAO;CAC5B,OAAOA;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,IAAaU,SAAiB,IAAIC,MAAM,CAAC,GAAa,EACpD/B,IAAIgC,SAASC,KAAK;CAChB,IAAI,OAAOA,QAAQ,UAAU,OAAOC,KAAAA;CACpC,IAAID,QAAQ,UAAU,OAAOpB;CAC7B,OAAOhB,cAAcoC,GAAG;AAC1B,EACF,CAAC;;;;;;;;;ACnUD,SAASgB,WAAWC,MAAoD;CACtE,OAAOA,SAAS,SAAS,WAAW;AACtC;;;;;;;;AASA,SAASE,oBACPC,MACAC,UAC6C;CAC7C,MAAMI,MAAmD,CAAA;CACzD,KAAK,MAAM,CAACC,IAAIC,OAAON,UACrB,IAAIK,OAAON,QAAQA,KAAKQ,SAASF,EAAE,GAAGD,IAAII,KAAK,CAACH,IAAIC,EAAE,CAAC;CAEzD,OAAOF;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,IAAaS,YAAsCC,UAAU;CAc3D,MAAMd,2BAAW,IAAIC,IAAwC;CAM7D,MAAMc,4BAAY,IAAId,IAA+B;CAIrD,MAAM,CAACe,iBAAiBC,sBAAsB9B,aAAa2B,MAAML,WAAW,IAAI;CAChFS,qBAAqBD,mBAAmB,IAAI,CAAC;CAE7C,MAAME,MAA4B;EAChCC,WAAWf,IAAIgB,YAAY;GACzBrB,SAASsB,IAAIjB,IAAIgB,OAAO;EAC1B;EACAE,aAAalB,OAAO;GAClBL,SAASwB,OAAOnB,EAAE;EACpB;EACAoB,gBAAgBpB,OAAO;GAerB,MAAMqB,UAAU5B,oBAAoBO,IAAIL,QAAQ;GAChD,IAAI0B,QAAQC,WAAW,GAAG,OAAOzB,QAAQ0B,QAAQ;GACjD,OAAO1B,QAAQ2B,IAAIH,QAAQI,KAAKC,SAASA,KAAK,GAAG,CAAC,CAAC,EAAEC,WAAW;IAC9D,KAAK,MAAM,CAACC,aAAaP,SAAS1B,SAASwB,OAAOS,QAAQ;GAC5D,CAAC;EACH;EACAC,gBAAgB7B,IAAI8B,aAAa;GAC/BpB,UAAUO,IAAIjB,IAAI8B,QAAQ;EAC5B;EACAC,cAAc/B,OAAO;GACnB,MAAMC,KAAKS,UAAUsB,IAAIhC,EAAE;GAC3BU,UAAUS,OAAOnB,EAAE;GACnBC,KAAK;EACP;EACAG,SAASO;CACX;CAWA,OAAAsB,gBACG9C,gBAAgB+C,UAAQ;EAACC,OAAOrB;EAAG,IAAAR,WAAA;GAAA,OAAA2B,gBACjCG,cAAY;IACXC,cAAc5B,MAAMH;IAAQ,IAC5Bf,OAAI;KAAA,OAAEkB,MAAMlB;IAAI;IAAA,IAChBc,aAAU;KAAA,OAAEI,MAAMJ;IAAU;IAC5BiC,QAAQ3B;IACHG;GAAG,CAAA;EAAA;CAAA,CAAA;AAIhB;AAmBA,IAAMsB,gBAA8CI,MAAM;CAIxD,MAAMC,WAAWjE,gBAAgBgE,EAAEH,MAAM;CASzC,MAAMK,OAAO7D,YAAsC8D,SAAS;EAC1D,IAAIA,MAAM,OAAOA;EACjB,MAAMC,IAAIH,SAAS;EACnB,IAAIG,KAAK,MAAM,OAAO;EACtB,OAAO9C,MAAM+C,QAAQD,CAAC,IAAI,SAAS;CACrC,CAAC;CAED,IAAA,QAAA,IAAA,aAA6B,cAC3BhE,mBAAmB;EACjB,IAAI8D,KAAK,MAAM,UAAUF,EAAEjD,SAAS,QAClC0D,QAAQC,KACN,0NACF;CAEJ,CAAC;CAYH,OAAAjB,gBACG/C,QAAM,EAAA,IAAAoB,WAAA;EAAA,OAAA,CAAA2B,gBACJjD,OAAK;GAAA,IAACmE,OAAI;IAAA,OAAET,KAAK,MAAM;GAAQ;GAAEU,OAAK;GAAA9C,WACnC+C,OACA3E,6BACQ;IACJ,MAAMkE,IAAIH,SAAS;IACnB,OAAO3C,MAAM+C,QAAQD,CAAC,IAAKA,EAAE,MAAM,OAAQA;GAC7C,GACA;IACEN,QAAQE,EAAEF,OAAO;IACjB/C,MAAMD,WAAWkD,EAAEjD,IAAI;IACvB+D,OAAOtD,IAAIuD,MAAM;KASf,MAAMC,WAAWxD;KACjB,IAAIwD,oBAAoBC,eAAeD,oBAAoBE,YACxD,SAAUC,MAA8BE,gBAAgB;KAM3DrB,EAAE1B,IAAIM,cAAcoC,QAAQ,EAAE7B,KAAK4B,IAAI;IACzC;IACAO,QAAQ9D,IAAIuD,MAAM;KAUhBf,EAAE1B,IAAIiB,cAAc/B,EAAmB;KACvCuD,KAAK;IACP;GACF,CACF;EAA2B,CAAA,GAAAtB,gBAG9BjD,OAAK;GAAA,IAACmE,OAAI;IAAA,OAAET,KAAK,MAAM;GAAM;GAAEU,OAAK;GAAA9C,WACjC+C,OACA5E,2BAA2BgE,SAASsB,QAAQ,GAAG;IAC7CzB,QAAQE,EAAEF,OAAO;IACjBjC,YAAYmC,EAAEnC;IACd2D,SAAS,EAAEC,OAAOC,SAASC,iBAAiB;KAQ1C,KAAK,MAAMnE,MAAMiE,OACfzB,EAAE1B,IAAIiB,cAAc/B,EAAmB;KAEzC,IAAIkE,QAAQ5C,WAAW,GAAG;KAK1B,KAAK,MAAMtB,MAAMkE,SACf,IAAIlE,cAAcyD,eAAezD,cAAc0D,YAC5C,GAAIC,MAA8BE,gBAAgB;KAKvDhE,QAAQ2B,IAAK0C,QAA4BzC,KAAKzB,OAAOwC,EAAE1B,IAAIM,cAAcpB,EAAE,CAAC,CAAC,EAAE2B,WACvEwC,cAAcD,OAAO,CAC7B;IACF;GACF,CAAC;EAA2B,CAAA,CAAA;CAAA,EAAA,CAAA;AAKtC;AA0CA,SAAgBK,mBAAmBC,SAA+D;CAChG,MAAM7E,2BAAW,IAAIC,IAAwC;CAC7D,MAAM,CAACe,iBAAiBC,sBAAsB9B,aAAa0F,SAASpE,WAAW,IAAI;CAGnFS,qBAAqBD,mBAAmB,IAAI,CAAC;CAE7C,MAAME,MAA4B;EAChCC,WAAWf,IAAIgB,YAAY;GACzBrB,SAASsB,IAAIjB,IAAIgB,OAAO;EAC1B;EACAE,aAAalB,OAAO;GAClBL,SAASwB,OAAOnB,EAAE;EACpB;EACAoB,gBAAgBpB,OAAO;GAMrB,MAAMqB,UAAU5B,oBAAoBO,IAAIL,QAAQ;GAChD,IAAI0B,QAAQC,WAAW,GAAG,OAAOzB,QAAQ0B,QAAQ;GACjD,OAAO1B,QAAQ2B,IAAIH,QAAQI,KAAKC,SAASA,KAAK,GAAG,CAAC,CAAC,EAAEC,WAAW;IAC9D,KAAK,MAAM,CAACC,aAAaP,SAAS1B,SAASwB,OAAOS,QAAQ;GAC5D,CAAC;EACH;EACAxB,SAASO;CACX;CAMA1B,gBAAgBU,SAAS8E,MAAM,CAAC;CAEhC,MAAMvC,YAAkDM,MAACP,gBACtD9C,gBAAgB+C,UAAQ;EAACC,OAAOrB;EAAG,IAAAR,WAAA;GAAA,OAAGkC,EAAElC;EAAQ;CAAA,CAAA;CAGnD,MAAMgE,OAAO,YAA2B;EAGtC,MAAMI,WAAW,CAAC,GAAG/E,SAASgF,OAAO,CAAC;EACtC,MAAM9E,QAAQ2B,IAAIkD,SAASjD,KAAKxB,OAAOA,GAAG,CAAC,CAAC;CAC9C;CAEA,OAAO;EAAEiC;EAAUoC;CAAK;AAC1B;;;;;;;;;;;;;;;;;;;ACnZA,SAAgB,aAAa,SAAmD;CAC9E,MAAM,UAAU,kBAAkB,CAAC;CACnC,MAAM,UAAU,kBAAkB,CAAC;CACnC,MAAM,kBAAkB,kBAAkB,CAAC;CAC3C,MAAM,kBAAkB,kBAAkB,CAAC;CAI3C,MAAM,WAAW,WAAmB,SAA4B;EAC9D,IAAI,CAAC,MAAM;EACX,QAAQ,IAAI,KAAK,EAAE,OAAO;EAC1B,QAAQ,IAAI,KAAK,EAAE,OAAO;EAC1B,gBAAgB,IAAI,KAAK,EAAE,QAAQ;EACnC,gBAAgB,IAAI,KAAK,EAAE,QAAQ;CACrC;CAWA,mBAAmB;EASjB,UANgB,SAAa,SAAS;GACzB,WAHK,SAAS,YAAY,KAAK,KAAA;GAIlC,QAHK,SAAS,SAAS,KAAK,KAAA;GAIpC,MAAM,SAAS;GACf,QAAQ,SAAS;EACnB,CACU,CAAO;CACnB,CAAC;CAED,OAAO;EAAE;EAAS;EAAS;EAAiB;CAAgB;AAC9D"}
1
+ {"version":3,"file":"index.js","names":["Context","createContext","createMemo","JSX","useContext","MotionConfigContextValue","MotionConfigProps","defaultMotionConfig","reducedMotion","transition","undefined","nonce","MotionConfigContext","useMotionConfig","MotionConfig","props","Element","value","_$createComponent","Provider","children","mergeRefs","isMotionValue","MotionValue","Accessor","Component","JSX","mergeProps","onMount","untrack","createStore","usePresenceContext","asVariantLabels","createMotion","resolveTarget","GestureStateName","snapshotValue","TRANSFORM_KEYS","targetToStyle","ElementProps","MotionElement","MotionMergedProps","MotionOptions","MotionStyle","Target","Transition","UseMotionResult","VariantContextValue","Variants","isControllingVariants","useVariantContext","VariantContext","useMotion","opts","getOpts","actualParentCtx","isControlling","parentVariantCtx","variants","undefined","initial","animate","hover","press","focus","inView","exit","custom","transition","presenceCtx","initialOpts","initialTarget","computeInitialTarget","activeStore","Record","whileInView","whileHover","whilePress","whileFocus","whileDrag","active","styleMotionValues","Map","styleStaticTransforms","styleCaptured","motionRef","el","initialAppliedBySSR","parentContext","renderedOnce","captureStyleEntries","style","key","value","set","has","snap","stripStyleEntriesOwnedByRegistry","CSSProperties","out","composeFirstPaintStyle","userStyle","merged","hasAny","Object","assign","mv","get","v","getProps","userProps","P","wroteFirstPaintStyle","cleaned","composed","ref","myVariantCtx","Provider","children","Element","props","_$createComponent","presenceInitial","animateValue","inheritedInitial","inheritedAnimate","effective","mergeRefs","Component","JSX","mergeProps","onMount","splitProps","Dynamic","ElementProps","MotionElement","MotionOptions","MotionStyle","useMotion","MotionOptKey","MOTION_OPT_KEYS","const","_MissingMotionOptKeys","Exclude","_ensureExhaustive","_missing","Motion","IntrinsicElements","Omit","Tag","style","create","Record","P","AnyComponent","tagComponentCache","Map","motionComponents","WeakSet","makeMotionTag","tag","cached","get","props","motionOpts","rest","m","_$createComponent","Provider","children","_$mergeProps","component","stored","set","add","motionCreate","process","env","NODE_ENV","has","console","warn","Wrapped","refFired","detector","_el","userRef","ref","el","mergedUserRef","restWithDetector","queueMicrotask","motion","Proxy","_target","key","undefined","resolveElements","createListTransition","createSwitchTransition","Component","createEffect","createMemo","createSignal","JSX","Match","onCleanup","Switch","PresenceContext","MotionElement","PresenceContextValue","switchMode","mode","PresenceProps","collectSubtreeExits","root","runExits","Map","Promise","Array","out","el","fn","contains","push","initial","exitMethod","children","Element","Presence","props","runEnters","presenceInitial","setPresenceInitial","queueMicrotask","ctx","register","runExit","set","unregister","delete","beforeUnmount","exiting","length","resolve","all","map","pair","then","exitedEl","registerEnter","runEnter","beforeMount","get","_$createComponent","Provider","value","PresenceCore","source","appear","PresenceCoreProps","p","resolved","path","prev","v","isArray","process","env","NODE_ENV","console","warn","when","keyed","_v","onExit","done","motionEl","HTMLElement","SVGElement","style","CSSStyleDeclaration","pointerEvents","onEnter","toArray","onChange","added","removed","finishRemoved","UseAnimatePresenceOptions","UseAnimatePresenceResult","exit","useAnimatePresence","options","clear","snapshot","values"],"sources":["../src/motion-config.tsx","../src/presence-context.ts","../src/reduced-motion.ts","../src/style.ts","../src/variants.ts","../src/primitives/createDragControls.ts","../src/primitives/motion-value.ts","../src/primitives/createPan.ts","../src/primitives/createDrag.ts","../src/primitives/createInView.ts","../src/primitives/createGestures.ts","../src/default-values.ts","../src/primitives/gesture-state.ts","../src/primitives/value-registry.ts","../src/primitives/createMotion.ts","../src/use-motion.tsx","../src/motion-proxy.tsx","../src/presence.tsx","../src/primitives/createScroll.ts"],"sourcesContent":["import { type Context, createContext, createMemo, type JSX, useContext } from \"solid-js\"\nimport type { MotionConfigContextValue, MotionConfigProps } from \"./types\"\n\n/**\n * Default context — no reduced motion override, no inherited transition, no\n * CSP nonce. Descendants without a `<MotionConfig>` ancestor get this.\n */\nconst defaultMotionConfig: MotionConfigContextValue = {\n reducedMotion: () => \"never\",\n transition: () => undefined,\n nonce: () => undefined,\n}\n\nexport const MotionConfigContext: Context<MotionConfigContextValue> =\n createContext<MotionConfigContextValue>(defaultMotionConfig)\n\nexport function useMotionConfig(): MotionConfigContextValue {\n return useContext(MotionConfigContext)\n}\n\n/**\n * Provider that flows reduced-motion mode, default transition, and CSP nonce\n * to every descendant motion element.\n *\n * @example\n * <MotionConfig reducedMotion=\"user\" transition={{ duration: 0.4 }}>\n * <App />\n * </MotionConfig>\n */\nexport function MotionConfig(props: MotionConfigProps): JSX.Element {\n const value: MotionConfigContextValue = {\n reducedMotion: createMemo(() => props.reducedMotion ?? \"never\"),\n transition: createMemo(() => props.transition),\n nonce: createMemo(() => props.nonce),\n }\n return <MotionConfigContext.Provider value={value}>{props.children}</MotionConfigContext.Provider>\n}\n","import { type Context, createContext, useContext } from \"solid-js\"\nimport type { PresenceContextValue } from \"./types\"\n\n/**\n * No-op default. `useMotion` consumers wire their `exit` targets through this\n * context, but without an enclosing `<Presence>` or `useAnimatePresence()`\n * the registration is silently dropped. The real implementations live in\n * `presence.tsx` (Phase 3).\n *\n * The shape is the inverted one (see types.ts JSDoc): children register a\n * `runExit` callable; Presence dispatches via `beforeUnmount`. The no-op\n * accepts the registration and resolves `beforeUnmount` immediately so\n * motion children outside a `<Presence>` unmount instantly without trying\n * to animate.\n */\nconst noopPresenceContext: PresenceContextValue = {\n register: () => {},\n unregister: () => {},\n beforeUnmount: () => Promise.resolve(),\n // `registerEnter` / `beforeMount` / `initial` intentionally LEFT UNDEFINED.\n // createMotion detects \"in a real Presence\" by `presence.initial !== undefined`\n // (the no-op leaves it undefined). Without that signal it animates first-\n // mount immediately — outside a Presence the element is always already in\n // the DOM by the time createMotion runs, so no defer is needed.\n}\n\nexport const PresenceContext: Context<PresenceContextValue> =\n createContext<PresenceContextValue>(noopPresenceContext)\n\nexport function usePresenceContext(): PresenceContextValue {\n return useContext(PresenceContext)\n}\n","import { type Accessor, from } from \"solid-js\"\n\n/**\n * A reactive `Accessor<boolean>` tracking the user's\n * `prefers-reduced-motion: reduce` media query.\n *\n * Returns `false` server-side (no `window.matchMedia`). On the client, it seeds\n * with the current match state and updates as the system preference toggles.\n * The matchMedia listener is removed automatically on owner disposal via\n * `from`'s teardown callback.\n *\n * @example\n * const reduced = createReducedMotion()\n * createEffect(() => {\n * if (reduced()) console.log(\"user prefers reduced motion\")\n * })\n */\nexport function createReducedMotion(): Accessor<boolean> {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return () => false\n }\n const mql = window.matchMedia(\"(prefers-reduced-motion: reduce)\")\n // `from` produces an Accessor<T | undefined>; we seed synchronously inside the\n // producer so the cast to Accessor<boolean> is sound.\n return from<boolean>((set) => {\n set(mql.matches)\n const handler = (e: MediaQueryListEvent) => set(e.matches)\n mql.addEventListener(\"change\", handler)\n return () => mql.removeEventListener(\"change\", handler)\n }) as Accessor<boolean>\n}\n\n/**\n * Compute the effective reduced-motion state by combining a {@link MotionConfig}\n * `reducedMotion` setting with the system preference.\n *\n * - `\"always\"` — forced reduced, regardless of system pref\n * - `\"never\"` — never reduced, regardless of system pref\n * - `\"user\"` — respect system pref\n *\n * @example\n * const reduced = shouldReduceMotion(\"user\", createReducedMotion()())\n */\nexport function shouldReduceMotion(\n configValue: \"always\" | \"never\" | \"user\",\n systemReduced: boolean,\n): boolean {\n if (configValue === \"always\") return true\n if (configValue === \"never\") return false\n return systemReduced\n}\n","import { isMotionValue, type MotionValue } from \"motion\"\nimport type { JSX } from \"solid-js\"\nimport type { Target } from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Tables (Q5 locked decisions)\n// ---------------------------------------------------------------------------\n\n/**\n * Set of CSS shortcut keys motion treats as transform components. Re-used by\n * `createMotion`'s Stage 3 animate bridge to decide whether an animate-target\n * key should be routed through the value registry (composed via the writer's\n * `el.style.transform =`) or sent down the existing WAA path.\n */\nexport const TRANSFORM_KEYS = /* @__PURE__ */ new Set([\n \"x\",\n \"y\",\n \"z\",\n \"scale\",\n \"scaleX\",\n \"scaleY\",\n \"scaleZ\",\n \"rotate\",\n \"rotateX\",\n \"rotateY\",\n \"rotateZ\",\n \"skew\",\n \"skewX\",\n \"skewY\",\n \"transformPerspective\",\n])\n\n/** Order matters — motion composes transforms in this sequence (Q5 sub-1). */\nconst TRANSFORM_ORDER = [\n \"x\",\n \"y\",\n \"z\",\n \"scale\",\n \"scaleX\",\n \"scaleY\",\n \"scaleZ\",\n \"rotate\",\n \"rotateX\",\n \"rotateY\",\n \"rotateZ\",\n \"skew\",\n \"skewX\",\n \"skewY\",\n \"transformPerspective\",\n] as const\n\nconst PX_PROPERTIES = /* @__PURE__ */ new Set([\n \"width\",\n \"minWidth\",\n \"maxWidth\",\n \"height\",\n \"minHeight\",\n \"maxHeight\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n \"padding\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"paddingInline\",\n \"paddingBlock\",\n \"paddingInlineStart\",\n \"paddingInlineEnd\",\n \"paddingBlockStart\",\n \"paddingBlockEnd\",\n \"margin\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"marginInline\",\n \"marginBlock\",\n \"marginInlineStart\",\n \"marginInlineEnd\",\n \"marginBlockStart\",\n \"marginBlockEnd\",\n \"borderWidth\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderRadius\",\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomLeftRadius\",\n \"borderBottomRightRadius\",\n \"gap\",\n \"rowGap\",\n \"columnGap\",\n \"fontSize\",\n \"outlineWidth\",\n \"outlineOffset\",\n])\n\n// ---------------------------------------------------------------------------\n// Snapshot — unwrap MotionValue / Accessor / keyframe-array to a leaf value.\n// Returns `undefined` when the leaf is null or undefined; callers omit those.\n// ---------------------------------------------------------------------------\n\ntype Leaf = string | number\n\n/**\n * Reduce a target-value (which may be raw, a MotionValue, an Accessor, or a\n * keyframe array) to a concrete leaf value the writer can apply to the DOM\n * or use to initialize a transient MotionValue. The cascade follows motion's\n * own semantics:\n *\n * - `null` / `undefined` → `undefined` (caller drops the key)\n * - keyframe array → first frame (consistent with motion-vanilla's\n * initial-style snapshot)\n * - `MotionValue` → its current `.get()`\n * - `Accessor` (a bare zero-arg function) → its invocation result\n * - primitive (string / number) → returned as-is\n *\n * Exported for the MV-in-style Stage 4 work: createMotion uses it to\n * snapshot initial-target entries when registering them into the value\n * registry as transient MVs.\n */\nexport function snapshotValue(value: unknown): Leaf | undefined {\n if (value === null || value === undefined) return undefined\n if (Array.isArray(value)) return snapshotValue(value[0])\n if (isMotionValue(value)) return snapshotValue((value as MotionValue<Leaf>).get())\n if (typeof value === \"function\") return snapshotValue((value as () => unknown)())\n if (typeof value === \"string\" || typeof value === \"number\") return value\n // Anything else (objects, booleans) isn't a renderable CSS value — skip it.\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Transform composition — produce a single `transform: ...` string from the\n// shorthand keys present in the target.\n// ---------------------------------------------------------------------------\n\n/**\n * Per-key transform formatter functions. Pre-built once at module load and\n * shared across all elements. Used by `createMotion`'s specialized writer\n * to avoid evaluating the transform-key switch on every single-key write —\n * at Sierpinski-scale fan-out (thousands of writes per frame) the switch's\n * 15 case-comparisons add up to non-trivial CPU.\n *\n * Pre-pick the formatter with `pickTransformFormatter(key)` ONCE at writer-\n * compile time, then the per-call cost in the hot path is just `formatter(v)`.\n */\ntype TransformFormatter = (value: Leaf) => string\n\nconst TRANSFORM_FORMATTERS: Readonly<Record<string, TransformFormatter>> = {\n // Translate: number → \"px\", string passes through verbatim.\n x: (v) => `translateX(${typeof v === \"string\" ? v : `${v}px`})`,\n y: (v) => `translateY(${typeof v === \"string\" ? v : `${v}px`})`,\n z: (v) => `translateZ(${typeof v === \"string\" ? v : `${v}px`})`,\n // Scale: dimensionless. Skip the type check entirely.\n scale: (v) => `scale(${v})`,\n scaleX: (v) => `scaleX(${v})`,\n scaleY: (v) => `scaleY(${v})`,\n scaleZ: (v) => `scaleZ(${v})`,\n // Rotate / skew: number → \"deg\", string passes through.\n rotate: (v) => `rotate(${typeof v === \"string\" ? v : `${v}deg`})`,\n rotateX: (v) => `rotateX(${typeof v === \"string\" ? v : `${v}deg`})`,\n rotateY: (v) => `rotateY(${typeof v === \"string\" ? v : `${v}deg`})`,\n rotateZ: (v) => `rotateZ(${typeof v === \"string\" ? v : `${v}deg`})`,\n skew: (v) => `skew(${typeof v === \"string\" ? v : `${v}deg`})`,\n skewX: (v) => `skewX(${typeof v === \"string\" ? v : `${v}deg`})`,\n skewY: (v) => `skewY(${typeof v === \"string\" ? v : `${v}deg`})`,\n transformPerspective: (v) => `perspective(${typeof v === \"string\" ? v : `${v}px`})`,\n}\n\n/**\n * Look up the formatter for a transform-shortcut key. Returns `undefined`\n * for non-transform keys; callers should check `TRANSFORM_KEYS.has(key)`\n * before assuming a formatter exists.\n */\nexport function pickTransformFormatter(key: string): TransformFormatter | undefined {\n return TRANSFORM_FORMATTERS[key]\n}\n\n/**\n * Format a motion transform-shortcut key + value as the corresponding CSS\n * transform function string (e.g. `transformFunctionFor(\"scale\", 1.05)`\n * → `\"scale(1.05)\"`). One-shot variant — for hot paths, use\n * `pickTransformFormatter(key)` once at compile time and reuse.\n */\nexport function transformFunctionFor(key: string, value: Leaf): string {\n return TRANSFORM_FORMATTERS[key]?.(value) ?? \"\"\n}\n\n// ---------------------------------------------------------------------------\n// Property formatting — apply unit table for non-transform CSS properties.\n// ---------------------------------------------------------------------------\n\n/**\n * Format a non-transform CSS property's value (e.g. `formatProperty(\"width\", 100)`\n * → `\"100px\"`, `formatProperty(\"opacity\", 0.5)` → `0.5`). Applies motion's\n * default-unit table (PX for dimensional CSS, dimensionless otherwise);\n * leaves CSS variables alone. Exported for `createMotion`'s writer fast path.\n */\nexport function formatProperty(key: string, value: Leaf): string | number {\n if (typeof value === \"string\") return value\n // CSS variables: stringify the number, never auto-unit (Q5 sub-4).\n if (key.startsWith(\"--\")) return String(value)\n if (PX_PROPERTIES.has(key)) return `${value}px`\n // Dimensionless or unknown — emit the bare number.\n return value\n}\n\n// ---------------------------------------------------------------------------\n// targetToStyle — the SSR/hydration linchpin. Pure, deterministic, no DOM\n// reads, no time-dependent values, no input mutation. Same inputs → same\n// outputs on server and client.\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a {@link Target} to a Solid {@link JSX.CSSProperties} object.\n *\n * - Composes transform shorthand (`x`, `y`, `scale`, `rotate`, etc.) into a\n * single `transform: \"...\"` string in motion's canonical order.\n * - Applies the default-unit table (px for dimensional CSS, deg for rotate/\n * skew, dimensionless for scale/opacity/etc.).\n * - For keyframe arrays, uses the first frame; a leading `null`/`undefined`\n * keyframe omits the property entirely.\n * - MotionValues and Solid Accessors are snapshotted at call time. Callers\n * wrap in `untrack` if they don't want the read to subscribe.\n * - Skips the `transition` key (animation config, not style).\n * - CSS variables (`--foo`) emit raw values, no unit guess.\n *\n * @example\n * targetToStyle({ x: 100, scale: 0.9, opacity: 0.5 })\n * // { transform: \"translateX(100px) scale(0.9)\", opacity: 0.5 }\n */\nexport function targetToStyle(target: Target): JSX.CSSProperties {\n const out: Record<string, string | number> = {}\n const transforms: Record<string, Leaf> = {}\n\n for (const key in target) {\n if (key === \"transition\") continue\n const raw = target[key as keyof Target]\n const snapshot = snapshotValue(raw)\n if (snapshot === undefined) continue\n\n if (TRANSFORM_KEYS.has(key)) {\n transforms[key] = snapshot\n } else {\n out[key] = formatProperty(key, snapshot)\n }\n }\n\n // Compose transform string in motion's canonical order.\n const parts: string[] = []\n for (const key of TRANSFORM_ORDER) {\n if (key in transforms) {\n parts.push(transformFunctionFor(key, transforms[key] as Leaf))\n }\n }\n if (parts.length > 0) {\n out.transform = parts.join(\" \")\n }\n\n return out as JSX.CSSProperties\n}\n","import { type Context, createContext, useContext } from \"solid-js\"\nimport type {\n AnimateValue,\n MotionOptions,\n Target,\n VariantContextValue,\n VariantLabels,\n Variants,\n} from \"./types\"\n\n/**\n * Empty default — descendants without an enclosing motion wrapper get a\n * cleanly-typed \"no propagation\" context.\n */\nconst emptyVariantContext: VariantContextValue = {}\n\n/**\n * Solid context propagating variant state from a motion ancestor to its\n * descendants. Only the wrapper components (`<motion.div>`, `motion(...)`)\n * provide a value. Bare `useMotion` consumers can opt in via the `Provider`\n * returned alongside the getter.\n */\nexport const VariantContext: Context<VariantContextValue> =\n createContext<VariantContextValue>(emptyVariantContext)\n\nexport function useVariantContext(): VariantContextValue {\n return useContext(VariantContext)\n}\n\n/**\n * Resolve a variant label (or array of labels) against a variants map and the\n * current `custom` value. Returns a {@link Target} object, or `null` if nothing\n * resolves.\n *\n * Resolution rules locked in Phase 1 Q4:\n *\n * - Child's own `variants` always wins for a given name (sub-1A).\n * - No cascade: if a child has no `variants` of its own, parent's are NOT\n * consulted (sub-1B / Pattern X). Callers pass `variants = undefined` in\n * that case and this returns `null`.\n * - String + array forms both supported; array variants merge in order\n * (later wins on conflicting keys).\n * - Function variants are invoked with `custom`; the value can be any type.\n *\n * @example\n * const variants = { visible: { opacity: 1 }, hidden: { opacity: 0 } }\n * resolveVariant(\"visible\", variants, undefined)\n * // { opacity: 1 }\n *\n * resolveVariant([\"visible\", \"highlighted\"], variants, undefined)\n * // merged in order, last variant's keys override\n *\n * resolveVariant(\"visible\", { visible: (i: number) => ({ x: i * 10 }) }, 3)\n * // { x: 30 }\n */\nexport function resolveVariant(\n names: VariantLabels | undefined,\n variants: Variants | undefined,\n custom: unknown,\n): Target | null {\n if (!names || !variants) return null\n\n const list = Array.isArray(names) ? names : [names]\n let merged: Target | null = null\n\n for (const name of list) {\n const variant = variants[name]\n if (!variant) continue\n const resolved: Target = typeof variant === \"function\" ? variant(custom) : variant\n // Object.assign sidesteps TS's \"spread types may only be created from object\n // types\" error caused by Target's index signature including `undefined`.\n merged = merged ? Object.assign({}, merged, resolved) : Object.assign({}, resolved)\n }\n\n return merged\n}\n\n/**\n * Determine the effective variant name for a given motion state. If the caller\n * provided an explicit value (string, array, or Target object), that wins.\n * Otherwise the parent context's value (per gesture/state) is used as a fall-\n * back.\n *\n * Returns the explicit value as-is when it's a Target object (used by callers\n * to detect \"explicit target — skip variant lookup entirely\").\n */\nexport function effectiveLabels(\n own: VariantLabels | Target | undefined,\n parent: VariantLabels | undefined,\n): VariantLabels | Target | undefined {\n if (own !== undefined) return own\n return parent\n}\n\n/**\n * Determine whether an `AnimateValue` is a variant *label* (string or array\n * of strings) — as opposed to a `Target` object or `false` / `undefined`.\n *\n * Mirrors motion-dom's `isVariantLabel`. Used by `isControllingVariants`\n * to decide whether a prop opts the node into the \"controlling\" role.\n */\nfunction isVariantLabelValue(v: AnimateValue | false | undefined): boolean {\n if (typeof v === \"string\") return true\n if (Array.isArray(v)) return true\n return false\n}\n\n/**\n * A motion node is \"controlling variants\" when any of its variant slots\n * (`initial`, `animate`, `hover`, `press`, `focus`, `inView`, `exit`) carries\n * a variant *label* (string or array of strings).\n *\n * Mirrors motion-dom's same-named check. A controlling node opts OUT of\n * inheriting its parent's variant cascade — it provides its own. Descendants\n * with no controlling props of their own DO inherit from the nearest\n * controlling ancestor.\n *\n * Behavior is binary (any single controlling-slot label flips the node into\n * controlling mode); not per-slot.\n *\n * Object-shaped values (`animate: \\{ x: 100 \\}`) do NOT make a node\n * controlling — they're treated as targets, not as variant references.\n */\nexport function isControllingVariants(opts: MotionOptions): boolean {\n return (\n isVariantLabelValue(opts.initial) ||\n isVariantLabelValue(opts.animate) ||\n isVariantLabelValue(opts.hover) ||\n isVariantLabelValue(opts.press) ||\n isVariantLabelValue(opts.focus) ||\n isVariantLabelValue(opts.inView) ||\n isVariantLabelValue(opts.exit)\n )\n}\n","import type { DragControls, DragControlsStartOptions } from \"../types\"\n\n// ---------------------------------------------------------------------------\n// createDragControls — imperative drag-controls factory (Q9).\n//\n// Architecture:\n// - A controls instance has one public method: `start(event, options?)`.\n// - createDrag (when its `opts.dragControls === thisInstance`) registers a\n// handler via the symbol-keyed internal property defined below. The\n// handler synthesizes a drag session from the externally-captured pointer\n// event, bypassing the usual threshold gate.\n// - One controls instance binds to one motion element at a time (Q9d).\n// When a second element registers, the first is silently replaced. On\n// unmount, only unregister if we're still the registered handler — avoid\n// clobbering a later registration.\n//\n// Internal registration:\n// - We attach a `_register(handler)` method to a non-enumerable symbol-keyed\n// property (Q9e), keeping the public `DragControls` type clean. The\n// symbol is exported as `DRAG_CONTROLS_REGISTER` for createDrag to find,\n// but users importing only `DragControls` never see it.\n// ---------------------------------------------------------------------------\n\n/**\n * Symbol used to attach the registration method on the controls object.\n * `createDrag` imports this symbol to find/register its handler. Userland\n * code never touches it — exported only for library-internal use.\n */\nexport const DRAG_CONTROLS_REGISTER = Symbol(\"solidjs-motion.dragControls.register\")\n\n/**\n * Internal registration signature — the handler that createDrag installs.\n * Returns an unregister function (called on owner disposal).\n */\ntype RegistrationFn = (\n handler: (event: PointerEvent, options: DragControlsStartOptions) => void,\n) => () => void\n\n/** Public + internal shape of the controls returned by `createDragControls`. */\ntype DragControlsInternal = DragControls & {\n [DRAG_CONTROLS_REGISTER]: RegistrationFn\n}\n\n/**\n * Create a controls instance for imperatively starting a drag on a motion\n * element from a different element (e.g., a drag-handle button).\n *\n * Pattern (Q9):\n *\n * @example\n * function Card() {\n * const controls = createDragControls()\n * const m = useMotion({ drag: \"y\", dragControls: controls })\n * return (\n * <div {...m()}>\n * <button onPointerDown={(e) => controls.start(e)}>handle</button>\n * Card body\n * </div>\n * )\n * }\n *\n * The handle's pointerdown fires `controls.start(event)`. createDrag is\n * registered with the controls and translates the call into a pan-session\n * synthesized from the handle's event, bypassing the threshold gate.\n */\nexport function createDragControls(): DragControls {\n let handler: ((event: PointerEvent, options: DragControlsStartOptions) => void) | null = null\n\n // Public surface — `start` is the only enumerable property.\n const controls: DragControlsInternal = {\n start(event: PointerEvent, options: DragControlsStartOptions = {}) {\n // No-op when no motion element is currently registered. Matches\n // motion/react's behavior: the user's pointerdown handler can be\n // attached unconditionally, and start() is harmless until binding.\n handler?.(event, options)\n },\n // Placeholder — filled in immediately below via Object.defineProperty\n // so the property is non-enumerable.\n [DRAG_CONTROLS_REGISTER]: undefined as unknown as RegistrationFn,\n }\n\n // Q9e — registration internals on a non-enumerable property keyed by\n // Symbol. Type-level the property is on DragControlsInternal, but the\n // public DragControls type omits it — userland sees only `.start`.\n Object.defineProperty(controls, DRAG_CONTROLS_REGISTER, {\n value: ((newHandler) => {\n handler = newHandler\n // Q9d — return an unregister that only nulls out if we're still the\n // active handler. Prevents a stale unmount from clobbering a later\n // registration on the same controls instance.\n return () => {\n if (handler === newHandler) handler = null\n }\n }) satisfies RegistrationFn,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return controls\n}\n","import {\n cancelFrame,\n frame,\n isMotionValue,\n type MotionValue,\n transform as motionTransform,\n motionValue,\n type SpringOptions,\n springValue,\n} from \"motion\"\nimport { type Accessor, createComputed, createSignal, onCleanup } from \"solid-js\"\nimport type { MotionValueAccessor } from \"../types\"\n\n// ---------------------------------------------------------------------------\n// MotionValue events the engine can fire — kept narrow so TypeScript autocomplete\n// surfaces only the documented surface.\n// ---------------------------------------------------------------------------\n\ntype MotionValueEvent = \"change\" | \"animationStart\" | \"animationComplete\" | \"animationCancel\"\n\n// ---------------------------------------------------------------------------\n// makeAccessor — wrap a raw motion.MotionValue as a callable hybrid. Invoking\n// `mv()` returns a Solid-tracked read; every MotionValue method (.get, .set,\n// .jump, .on, .getVelocity, etc.) forwards to the underlying value. Both\n// `isMotionValue(mv)` (duck-typed on .getVelocity) and `typeof mv === \"function\"`\n// are true; createMotion's splitTarget checks isMotionValue first, so the engine\n// treats hybrids as MotionValues.\n// ---------------------------------------------------------------------------\n\nfunction makeAccessor<T>(mv: MotionValue<T>): MotionValueAccessor<T> {\n // Solid signal bridge — kept in sync via `mv.on(\"change\", ...)`.\n const [signal, setSignal] = createSignal<T>(mv.get())\n // Wrap in updater form so Setter accepts T regardless of its shape (T could\n // include Function for callback-like motion values).\n onCleanup(mv.on(\"change\", (v) => setSignal(() => v)))\n\n // The callable: invoking returns the tracked signal value.\n const fn = (() => signal()) as MotionValueAccessor<T>\n\n return new Proxy(fn, {\n get(target, prop, receiver) {\n // Function intrinsics (call/apply/bind) stay on the function itself so\n // `fn.call(...)` etc. behave normally.\n if (prop === \"call\" || prop === \"apply\" || prop === \"bind\") {\n return Reflect.get(target, prop, receiver)\n }\n // If we ever attach our own properties to `fn`, prefer those.\n if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver)\n // Forward to the MotionValue. Methods are bound so `this` is the MV.\n const value = Reflect.get(mv as object, prop, mv)\n return typeof value === \"function\" ? value.bind(mv) : value\n },\n has(target, prop) {\n return Reflect.has(target, prop) || prop in (mv as object)\n },\n })\n}\n\n// ---------------------------------------------------------------------------\n// createMotionValue — callable-hybrid MotionValue auto-disposed on cleanup.\n// ---------------------------------------------------------------------------\n\n/**\n * Create a {@link MotionValueAccessor} bound to the current reactive scope.\n *\n * The returned value has two access patterns:\n *\n * - `mv()` — invoke as a Solid Accessor. Tracks in JSX, `createEffect`,\n * `createMemo`, etc.\n * - `mv.get()` / `mv.set(v)` / `mv.jump(v)` / `mv.on(...)` — the full upstream\n * {@link MotionValue} surface. Matches motion/react idioms.\n *\n * The same value can be passed as a target in\n * `useMotion({ animate: { x: mv } })` (motion engine sees `.getVelocity` via\n * the Proxy and treats it as a motion value) or directly as the target of\n * `animate(mv, 100)`.\n *\n * Auto-destroyed via `onCleanup` when the owner is disposed.\n *\n * @example\n * const x = createMotionValue(0)\n * x.set(100)\n * animate(x, 200, { duration: 0.5 })\n * <p>{x()}</p> // reactive read in JSX\n */\nexport function createMotionValue<T>(initial: T): MotionValueAccessor<T> {\n const mv = motionValue(initial)\n const accessor = makeAccessor(mv)\n // Route the cleanup call through the accessor so test-time spies on\n // `accessor.destroy` are invoked (the Proxy forwards to the underlying mv).\n onCleanup(() => accessor.destroy())\n return accessor\n}\n\n// ---------------------------------------------------------------------------\n// toSignal — adapt any raw MotionValue (e.g. from motion's `motionValue()`\n// factory) to a Solid Accessor. Useful when interoperating with motion APIs\n// that return raw MotionValues outside our hybrid factories.\n// ---------------------------------------------------------------------------\n\n/**\n * Bridge a raw {@link MotionValue} (from motion's `motionValue()` factory or\n * any other motion API that doesn't return our hybrid) to a Solid\n * {@link Accessor}. Seeds with the current value and updates on every\n * `change` event.\n *\n * **You usually don't need this.** Values returned by `createMotionValue`,\n * `createTransform`, `createSpring`, `createTime`, `createVelocity`, and\n * `createTemplate` are already callable — you can do `mv()` directly. Reach\n * for `toSignal` only when you receive a raw MotionValue from an external API.\n *\n * @example\n * import { motionValue } from \"motion\"\n * const rawMv = motionValue(0)\n * const xSignal = toSignal(rawMv)\n */\nexport function toSignal<T>(mv: MotionValue<T>): Accessor<T> {\n const [value, setValue] = createSignal<T>(mv.get())\n onCleanup(mv.on(\"change\", (v) => setValue(() => v)))\n return value\n}\n\n// ---------------------------------------------------------------------------\n// createMotionValueEvent — register a listener with automatic cleanup.\n// ---------------------------------------------------------------------------\n\n/**\n * Subscribe to a {@link MotionValue} event with automatic cleanup. Convenience\n * wrapper around `mv.on(event, cb)` for parity with motion/react's\n * `useMotionValueEvent`. For per-change reactivity, prefer\n * `createComputed(() => fn(mv()))` since hybrids are directly callable.\n *\n * @example\n * const x = createMotionValue(0)\n * createMotionValueEvent(x, \"animationComplete\", () => console.log(\"done\"))\n */\nexport function createMotionValueEvent<T>(\n mv: MotionValue<T>,\n event: MotionValueEvent,\n callback: (latest: T) => void,\n): void {\n onCleanup(mv.on(event, callback))\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction readInputValue<T>(input: MotionValue<T> | Accessor<T>): T {\n if (isMotionValue(input)) return (input as MotionValue<T>).get()\n return (input as Accessor<T>)()\n}\n\nfunction subscribeInput<T>(\n input: MotionValue<T> | Accessor<T>,\n onChange: (value: T) => void,\n): void {\n if (isMotionValue(input)) {\n onCleanup((input as MotionValue<T>).on(\"change\", onChange))\n } else {\n createComputed(() => onChange((input as Accessor<T>)()))\n }\n}\n\n// ---------------------------------------------------------------------------\n// createTransform — interpolate one MotionValue/Accessor through a range.\n// Returns a MotionValueAccessor so callable behavior is preserved end-to-end.\n// ---------------------------------------------------------------------------\n\ntype TransformOptions = NonNullable<Parameters<typeof motionTransform>[2]>\n\n/**\n * Create a {@link MotionValueAccessor} that maps an input through a range/\n * output pair. Mirrors motion/react's `useTransform`. The input can be a\n * MotionValue, our hybrid, or any Solid Accessor; the output composes with\n * `animate()`, `useMotion`'s targets, and JSX reactivity.\n *\n * @example\n * const { scrollY } = createScroll()\n * const opacity = createTransform(scrollY, [0, 200], [1, 0])\n * <div style={{ opacity: opacity() }}>...</div>\n */\nexport function createTransform<I extends number, O>(\n input: MotionValue<I> | Accessor<I>,\n inputRange: I[],\n outputRange: O[],\n options?: TransformOptions,\n): MotionValueAccessor<O> {\n const mapper = motionTransform(inputRange, outputRange, options)\n const mv = motionValue(mapper(readInputValue(input)))\n onCleanup(() => mv.destroy())\n subscribeInput(input, (v) => mv.set(mapper(v)))\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createSpring — produce a MotionValueAccessor that spring-tracks an input.\n// ---------------------------------------------------------------------------\n\n/**\n * Spring-smoothed mirror of a numeric input. Returns a\n * {@link MotionValueAccessor} that tracks the source with physics-based easing.\n *\n * @example\n * const x = createMotionValue(0)\n * const smoothX = createSpring(x, { stiffness: 100, damping: 20 })\n */\nexport function createSpring(\n source: MotionValue<number> | Accessor<number>,\n options?: SpringOptions,\n): MotionValueAccessor<number> {\n if (isMotionValue(source)) {\n const mv = springValue(source as MotionValue<number>, options)\n onCleanup(() => mv.destroy())\n return makeAccessor(mv)\n }\n // Accessor input — bridge through an intermediate MotionValue that mirrors it.\n const bridge = motionValue((source as Accessor<number>)())\n onCleanup(() => bridge.destroy())\n createComputed(() => bridge.set((source as Accessor<number>)()))\n const mv = springValue(bridge, options)\n onCleanup(() => mv.destroy())\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createTime — MotionValueAccessor that advances each frame with elapsed ms.\n// ---------------------------------------------------------------------------\n\n/**\n * {@link MotionValueAccessor} that advances every animation frame, holding\n * the milliseconds elapsed since this primitive was called. Driver for\n * time-based animations and {@link createTransform}-derived values.\n *\n * @example\n * const t = createTime()\n * const wobble = createTransform(t, [0, 1000, 2000], [0, 10, 0])\n */\nexport function createTime(): MotionValueAccessor<number> {\n const mv = motionValue(0)\n onCleanup(() => mv.destroy())\n const startedAt = performance.now()\n const tick = () => mv.set(performance.now() - startedAt)\n frame.update(tick, true)\n onCleanup(() => cancelFrame(tick))\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createVelocity — MotionValueAccessor mirroring an input's instantaneous velocity.\n// ---------------------------------------------------------------------------\n\n/**\n * {@link MotionValueAccessor} reporting the velocity of a source motion value.\n * Updated whenever the source changes.\n *\n * @example\n * const x = createMotionValue(0)\n * const xVelocity = createVelocity(x)\n */\nexport function createVelocity(source: MotionValue<number>): MotionValueAccessor<number> {\n const mv = motionValue(source.getVelocity())\n onCleanup(() => mv.destroy())\n onCleanup(source.on(\"change\", () => mv.set(source.getVelocity())))\n return makeAccessor(mv)\n}\n\n// ---------------------------------------------------------------------------\n// createTemplate — tagged template producing a MotionValueAccessor<string>.\n// ---------------------------------------------------------------------------\n\n// biome-ignore lint/suspicious/noExplicitAny: MotionValue is invariant in T; `any` lets the template accept MotionValues of any value type.\ntype TemplateInput = MotionValue<any> | Accessor<unknown> | string | number\n\n/**\n * Tagged template producing a {@link MotionValueAccessor}\\<string\\>.\n * Interpolated {@link MotionValue}s, hybrids, and Solid Accessors recompute\n * the output string on change; primitives and static strings are baked in.\n *\n * @example\n * const x = createMotionValue(0)\n * const y = createMotionValue(0)\n * const transform = createTemplate`translate(${x}px, ${y}px) scale(1.1)`\n * <div style={{ transform: transform() }} />\n */\nexport function createTemplate(\n strings: TemplateStringsArray,\n ...values: TemplateInput[]\n): MotionValueAccessor<string> {\n const compute = (): string => {\n let out = \"\"\n for (let i = 0; i < strings.length; i++) {\n out += strings[i]\n if (i < values.length) {\n const v = values[i]\n if (isMotionValue(v)) {\n out += String((v as MotionValue<unknown>).get())\n } else if (typeof v === \"function\") {\n out += String((v as Accessor<unknown>)())\n } else {\n out += String(v)\n }\n }\n }\n return out\n }\n\n const mv = motionValue(compute())\n onCleanup(() => mv.destroy())\n\n for (const v of values) {\n if (isMotionValue(v)) {\n onCleanup((v as MotionValue<unknown>).on(\"change\", () => mv.set(compute())))\n }\n }\n\n const hasAccessor = values.some((v) => typeof v === \"function\" && !isMotionValue(v))\n if (hasAccessor) {\n createComputed(() => {\n for (const v of values) {\n if (typeof v === \"function\" && !isMotionValue(v)) (v as Accessor<unknown>)()\n }\n mv.set(compute())\n })\n }\n\n return makeAccessor(mv)\n}\n","import { isPrimaryPointer, time } from \"motion-dom\"\nimport { type Accessor, createEffect, createSignal, onCleanup } from \"solid-js\"\nimport type { MotionValueAccessor, PanInfo } from \"../types\"\nimport { createMotionValue } from \"./motion-value\"\n\n// ---------------------------------------------------------------------------\n// createPan — standalone pan-session primitive (Q11/c).\n//\n// Phase 2 Commit 5 (Q11/D3): pointer-session machinery that createDrag uses\n// as its underlying event source. Drag IS a pan that owns the element's\n// transform; pan on its own is callback-only (no `whilePan` state).\n//\n// Return shape — a SEMANTIC split between animate-able numeric values\n// (MotionValueAccessors) and non-animate-able state (a plain Accessor):\n//\n// - `point.x/y`, `delta.x/y`, `offset.x/y`, `velocity.x/y` → each is a\n// {@link MotionValueAccessor}<number>. Calling them (`pan.point.x()`) is\n// Solid-tracked; the full MotionValue surface (`.get`, `.set`, `.on`,\n// `.getVelocity`) is available; they compose directly with `animate()`,\n// `createTransform`, `useMotion` targets, and JSX reactivity.\n// - `isPanning` → a plain `Accessor<boolean>`. Booleans aren't animate-able,\n// so wrapping in an MV would only add weight.\n//\n// Why MotionValues for the numeric fields? Composability. Users can pipe\n// `pan.point.x` straight into `createTransform`, `animate()`, or use it as\n// a target in `useMotion({ animate: { x: pan.point.x } })` — same surface\n// Phase 1 established for every animate-able value in the library.\n//\n// The session:\n// pointerdown → reset per-session MVs to start point / zeros, attach\n// window listeners\n// pointermove(s) → update MVs every move (Option X — pre-threshold too,\n// so consumers can render threshold-progress or\n// early-detect fast pans); once cumulative offset\n// crosses `threshold`, isPanning flips true and\n// onPanStart fires; subsequent moves fire onPan\n// pointerup → flip isPanning false; if pan happened, fire onPanEnd;\n// point/delta/offset/velocity MVs RETAINED (useful for\n// snap-to-end animations)\n// pointercancel → same as pointerup, but the user's gesture was aborted\n//\n// Velocity tracking (Q15a): sliding window of pointer samples, 200ms wide.\n// Velocity = (latest.point − oldest.point) / Δt × 1000 (px/sec). Uses\n// motion-dom's `time.now()` so timestamps stay frame-synchronous with the\n// rest of motion's pipeline.\n// ---------------------------------------------------------------------------\n\n/** Sliding-window width for velocity computation (Q15a). */\nconst VELOCITY_WINDOW_MS = 200\n/** Default movement threshold before onPanStart fires (Q11a, matches motion). */\nconst DEFAULT_THRESHOLD = 3\n\ntype Point = { x: number; y: number }\n\nexport type CreatePanOptions = {\n /** Fires once after pointer movement crosses the threshold. */\n onPanStart?: (event: PointerEvent, info: PanInfo) => void\n /** Fires on every pointermove after onPanStart, until pointerup/cancel. */\n onPan?: (event: PointerEvent, info: PanInfo) => void\n /**\n * Fires on pointerup OR pointercancel after onPanStart has fired.\n * If the pointer was released before the threshold was crossed, onPanEnd\n * is NOT fired (no pan ever happened).\n */\n onPanEnd?: (event: PointerEvent, info: PanInfo) => void\n /**\n * Minimum cumulative offset (in px) before onPanStart fires. Distinguishes\n * pan from click. Default: 3px (motion's default).\n */\n threshold?: number\n}\n\n/** Per-axis pair of {@link MotionValueAccessor}s — `pan.point`, `pan.delta`, etc. */\nexport type PanAxisPair = {\n x: MotionValueAccessor<number>\n y: MotionValueAccessor<number>\n}\n\n/**\n * Returned by {@link createPan}. `isPanning` is a plain Accessor (booleans\n * aren't animate-able). The four numeric pairs are MotionValueAccessors,\n * each composable with `animate()`, `createTransform`, and `useMotion`.\n */\nexport type CreatePanResult = {\n isPanning: Accessor<boolean>\n point: PanAxisPair\n delta: PanAxisPair\n offset: PanAxisPair\n velocity: PanAxisPair\n}\n\n/**\n * Observe pointer-driven pan gestures on an element.\n *\n * Returns `{ isPanning, point, delta, offset, velocity }`:\n *\n * - `pan.isPanning()` — Solid Accessor; `true` between onPanStart and onPanEnd.\n * - `pan.point.x`, `pan.point.y` — current pointer position in client coords.\n * Each is a {@link MotionValueAccessor}: call `pan.point.x()` for a tracked\n * read, `pan.point.x.get()` for an untracked snapshot, and pass it directly\n * to `animate()`, `createTransform`, or `useMotion` targets.\n * - `pan.delta.x/y` — delta since last pointermove.\n * - `pan.offset.x/y` — cumulative offset since the current pointerdown.\n * - `pan.velocity.x/y` — sliding-window velocity in px/sec.\n *\n * Fields update from `pointerdown` forward (including pre-threshold moves)\n * — gate reads on `pan.isPanning()` if you only care about real pans.\n *\n * The `options` argument accepts either a static object or a function form\n * (matching `useMotion`'s convention). The function form is read INSIDE\n * each pointer-event handler, so reactive option changes apply on the next\n * relevant event without re-attaching listeners.\n *\n * @example Static options\n * const pan = createPan(el, {\n * onPanStart: (e, info) => console.log(\"start\", info.point),\n * threshold: 3,\n * })\n *\n * @example Reactive options (function form — signals tracked)\n * const [threshold, setThreshold] = createSignal(3)\n * const pan = createPan(el, () => ({\n * threshold: threshold(),\n * onPanStart: (e, info) => console.log(info),\n * }))\n *\n * @example Composing pan.point.x with createTransform\n * const pan = createPan(el)\n * const rotation = createTransform(pan.point.x, [0, 300], [0, 90])\n * <div ref={setEl} style={{ transform: `rotate(${rotation()}deg)` }} />\n *\n * @example Reading reactively in JSX\n * const pan = createPan(el)\n * <Show when={pan.isPanning()}>\n * Position: {pan.point.x()}, {pan.point.y()}\n * </Show>\n */\nexport function createPan(\n ref: () => HTMLElement | null | undefined,\n options: CreatePanOptions | (() => CreatePanOptions) = {},\n): CreatePanResult {\n // Normalize to a function form. All option reads inside event handlers\n // call this so the latest reactive values are seen on each event.\n const getOpts: () => CreatePanOptions = typeof options === \"function\" ? options : () => options\n\n // ---- State surface ----\n // isPanning is a plain signal — booleans aren't animate-able, so a full\n // MotionValue would be dead weight.\n const [isPanning, setIsPanning] = createSignal(false)\n // Eight MVs for the four numeric pairs. Each becomes a callable hybrid via\n // createMotionValue: invokable as a tracked Accessor AND has the full\n // MotionValue surface so consumers can pipe them into `animate()`,\n // `createTransform`, or `useMotion` targets.\n const pointX = createMotionValue(0)\n const pointY = createMotionValue(0)\n const deltaX = createMotionValue(0)\n const deltaY = createMotionValue(0)\n const offsetX = createMotionValue(0)\n const offsetY = createMotionValue(0)\n const velocityX = createMotionValue(0)\n const velocityY = createMotionValue(0)\n\n // createEffect — Solid-idiomatic for side-effect setup (DOM listeners).\n // First iteration runs in the next microtask, which is harmless here: a\n // freshly-mounted element can't receive pointer events between the ref\n // callback firing and the next microtask. Re-runs (ref changes) carry the\n // same harmless delay.\n createEffect(() => {\n const el = ref()\n if (!el) return\n\n // NOTE: threshold and callbacks are read INSIDE the event handlers via\n // getOpts(), not captured here. That way reactive opts changes apply on\n // the next relevant event without re-attaching listeners (which would\n // require this effect to depend on getOpts and re-run on opt changes).\n\n // Session state — reset on each pointerdown. Scoped per effect iteration;\n // cleanup below reaches all listeners regardless of phase.\n let startPoint: Point | null = null\n let lastPoint: Point | null = null\n let pointerId: number | null = null\n let panning = false\n let samples: Array<{ t: number; point: Point }> = []\n\n function pointOf(event: PointerEvent): Point {\n return { x: event.clientX, y: event.clientY }\n }\n\n function computeVelocity(): Point {\n if (samples.length < 2) return { x: 0, y: 0 }\n // biome-ignore lint/style/noNonNullAssertion: length >= 2 guarantees both indices exist\n const first = samples[0]!\n // biome-ignore lint/style/noNonNullAssertion: length >= 2 guarantees both indices exist\n const last = samples[samples.length - 1]!\n const dt = last.t - first.t\n if (dt <= 0) return { x: 0, y: 0 }\n return {\n x: ((last.point.x - first.point.x) / dt) * 1000,\n y: ((last.point.y - first.point.y) / dt) * 1000,\n }\n }\n\n function buildInfo(event: PointerEvent): PanInfo {\n const point = pointOf(event)\n const delta = lastPoint\n ? { x: point.x - lastPoint.x, y: point.y - lastPoint.y }\n : { x: 0, y: 0 }\n const offset = startPoint\n ? { x: point.x - startPoint.x, y: point.y - startPoint.y }\n : { x: 0, y: 0 }\n const velocity = computeVelocity()\n return { point, delta, offset, velocity }\n }\n\n /** Push a freshly-computed info snapshot into the MVs. Each `.set` fires\n * the MV's change subscription, which the callable-hybrid bridge\n * forwards to Solid; consumers reading e.g. only `pan.velocity.x()` only\n * re-run when velocity.x actually changes — pre-existing MotionValue\n * granularity, not Store path-tracking. */\n function writeInfo(info: PanInfo): void {\n pointX.set(info.point.x)\n pointY.set(info.point.y)\n deltaX.set(info.delta.x)\n deltaY.set(info.delta.y)\n offsetX.set(info.offset.x)\n offsetY.set(info.offset.y)\n velocityX.set(info.velocity.x)\n velocityY.set(info.velocity.y)\n }\n\n function onPointerDown(event: PointerEvent): void {\n // motion-dom's isPrimaryPointer filters secondary buttons (mouse) and\n // secondary touch points. Same gating Q13c established for press.\n if (!isPrimaryPointer(event)) return\n\n startPoint = pointOf(event)\n lastPoint = startPoint\n pointerId = event.pointerId\n panning = false\n samples = [{ t: time.now(), point: startPoint }]\n\n // Reset per-session fields. Point goes to start; delta/offset/velocity\n // zero. isPanning false (threshold not crossed yet).\n setIsPanning(false)\n pointX.set(startPoint.x)\n pointY.set(startPoint.y)\n deltaX.set(0)\n deltaY.set(0)\n offsetX.set(0)\n offsetY.set(0)\n velocityX.set(0)\n velocityY.set(0)\n\n // Listen on window so events keep firing even when the pointer leaves\n // the element (e.g., during a fast drag). Mirrors motion-dom's press.\n window.addEventListener(\"pointermove\", onPointerMove)\n window.addEventListener(\"pointerup\", onPointerEnd)\n window.addEventListener(\"pointercancel\", onPointerEnd)\n }\n\n function onPointerMove(event: PointerEvent): void {\n // Multi-touch / unrelated pointers ignored.\n if (event.pointerId !== pointerId) return\n\n const point = pointOf(event)\n const now = time.now()\n\n // Append sample, drop everything outside the 200ms window.\n samples.push({ t: now, point })\n const cutoff = now - VELOCITY_WINDOW_MS\n while (samples.length > 1 && (samples[0]?.t ?? 0) < cutoff) {\n samples.shift()\n }\n\n const info = buildInfo(event)\n // Option X — info updates on EVERY move, including pre-threshold.\n // Consumers gate on `isPanning()` for \"real pan\" semantics.\n writeInfo(info)\n\n if (!panning) {\n // Threshold gate: pan hasn't started yet. Read threshold fresh from\n // getOpts() so reactive changes apply (a session in progress sticks\n // with the threshold it saw when this branch first crossed).\n const threshold = getOpts().threshold ?? DEFAULT_THRESHOLD\n const distance = Math.hypot(info.offset.x, info.offset.y)\n if (distance >= threshold) {\n panning = true\n setIsPanning(true)\n getOpts().onPanStart?.(event, info)\n }\n } else {\n getOpts().onPan?.(event, info)\n }\n lastPoint = point\n }\n\n function onPointerEnd(event: PointerEvent): void {\n if (event.pointerId !== pointerId) return\n // onPanEnd only fires if onPanStart fired — pan-cancelled-before-start\n // (mere clicks) shouldn't emit lifecycle callbacks.\n if (panning) {\n getOpts().onPanEnd?.(event, buildInfo(event))\n }\n panning = false\n // Flip isPanning. Point/delta/offset/velocity MVs are RETAINED\n // (option Q5/3) so consumers can read the final state for\n // snap-to-end animations. Next pointerdown will reset them.\n setIsPanning(false)\n startPoint = null\n lastPoint = null\n pointerId = null\n samples = []\n window.removeEventListener(\"pointermove\", onPointerMove)\n window.removeEventListener(\"pointerup\", onPointerEnd)\n window.removeEventListener(\"pointercancel\", onPointerEnd)\n }\n\n el.addEventListener(\"pointerdown\", onPointerDown)\n\n // Iteration-scoped cleanup: fires when the ref changes (effect re-runs)\n // AND when the owner disposes. Removes all listeners regardless of\n // whether a session was in progress.\n onCleanup(() => {\n el.removeEventListener(\"pointerdown\", onPointerDown)\n window.removeEventListener(\"pointermove\", onPointerMove)\n window.removeEventListener(\"pointerup\", onPointerEnd)\n window.removeEventListener(\"pointercancel\", onPointerEnd)\n })\n })\n\n return {\n isPanning,\n point: { x: pointX, y: pointY },\n delta: { x: deltaX, y: deltaY },\n offset: { x: offsetX, y: offsetY },\n velocity: { x: velocityX, y: velocityY },\n }\n}\n","import { type AnimationPlaybackControls, animate } from \"motion\"\nimport { HTMLVisualElement, type MotionValue, time, visualElementStore } from \"motion-dom\"\nimport { createEffect, onCleanup } from \"solid-js\"\nimport type {\n DragConstraints,\n DragControls,\n DragControlsStartOptions,\n MotionOptions,\n PanInfo,\n} from \"../types\"\nimport { DRAG_CONTROLS_REGISTER } from \"./createDragControls\"\nimport { createPan } from \"./createPan\"\nimport type { SetActive } from \"./gesture-state\"\n\n// ---------------------------------------------------------------------------\n// createDrag — pointer-driven drag with motion-dom VisualElement composition\n// (Q5/C-lean + Q15).\n//\n// Architecture:\n// - Layered on top of createPan (Q11/D3). Pan handles the pointer session\n// (down → threshold-gated start → moves → up/cancel) and exposes its\n// PanInfo via callbacks. Drag adds the side-effects on top: transform\n// writes, body/touchAction styling, pointer capture, state-machine\n// activation, and (Stage 4) momentum.\n// - Translation flows through motion-dom's VisualElement system: drag writes\n// to the element's `x`/`y` MotionValues, and motion's render pipeline\n// composes the final transform string. This is why `whileDrag: { scale }`\n// works for free — the scale animation writes a sibling MV and the VE\n// composes all transform-class values into one output (Q5/C-lean).\n//\n// State machine integration:\n// - On pan-start (only if drag is enabled), `setActive(\"whileDrag\", true)`\n// fires. The state machine's `winners` memo then claims whileDrag's\n// target keys, EXCEPT x and y which are filtered (drag owns them).\n// - On pan-end, `setActive(\"whileDrag\", false)`. Momentum (Stage 4) runs\n// AFTER whileDrag deactivates — visual gesture state ends with the\n// pointerup, not when the animation settles.\n// ---------------------------------------------------------------------------\n\n/**\n * Get or create a motion-dom VisualElement for an HTMLElement. Required\n * because we write to the VE's `x`/`y` MotionValues during drag, and motion\n * only auto-creates the VE inside `animate(el, target)` calls — if a user\n * configures drag without any animate target, no VE would exist.\n *\n * Mirrors framer-motion's `createDOMVisualElement` (which isn't reachable\n * from a non-React context — framer-motion's main entry requires React).\n * The options shape and `mount` + `visualElementStore.set` calls match the\n * upstream implementation. SVG support is omitted for v0.1 — drag on SVG\n * is an unusual case.\n */\nfunction ensureVisualElement(el: HTMLElement): InstanceType<typeof HTMLVisualElement> {\n const existing = visualElementStore.get(el)\n if (existing) return existing as InstanceType<typeof HTMLVisualElement>\n\n // motion-dom's VisualElement options type expects more fields than we\n // can sensibly provide without React-flavored MotionProps. The runtime\n // needs only the visualState shape and an empty props bag.\n const options = {\n presenceContext: null,\n props: {},\n visualState: {\n renderState: {\n transform: {},\n transformOrigin: {},\n style: {},\n vars: {},\n attrs: {},\n },\n latestValues: {},\n },\n }\n // biome-ignore lint/suspicious/noExplicitAny: VisualElement options type expects React-flavored MotionProps we can't supply.\n const ve = new HTMLVisualElement(options as any)\n ve.mount(el)\n visualElementStore.set(el, ve)\n return ve as InstanceType<typeof HTMLVisualElement>\n}\n\n/**\n * Parse the visible translate from an element's transform — reads both\n * `getComputedStyle(el).transform` (which real browsers normalize to\n * matrix form) AND `el.style.transform` (which preserves the raw syntax\n * motion-dom's writer emits, e.g. `translate3d(50px, 0px, 0)`). Used by\n * drag's pan-start to sync the x/y MotionValues to what the user is\n * actually seeing.\n *\n * Why both sources: motion's `animate(el, target)` interpolates style.\n * transform via WAAPI but DOESN'T update the VE's MVs during the tween,\n * so after `initial: {x:-300} → animate: {x:0}` the MV still holds -300.\n * Reading the current transform recovers the truth. We prefer computed\n * (post-animation, post-WAAPI-commit value) and fall back to inline\n * (covers jsdom + cases where motion's writer wrote inline but the\n * browser hasn't run a style-resolve pass yet).\n *\n * Supported syntaxes:\n * - `\"none\"` / empty → {0, 0}\n * - `matrix(a, b, c, d, tx, ty)`\n * - `matrix3d(..., tx, ty, ...)`\n * - `translateX(Npx)` / `translateY(Npx)` / `translate(tx, ty)`\n * - `translate3d(tx, ty, tz)`\n * - Any of the above mixed with other transform functions (regex-\n * based extraction picks just the translate components).\n */\nfunction readVisibleTranslate(el: HTMLElement): { x: number; y: number } {\n const fromString = (transform: string): { x: number; y: number } | null => {\n if (!transform || transform === \"none\") return null\n\n if (transform.startsWith(\"matrix3d(\")) {\n const values = transform.slice(9, -1).split(\",\")\n const tx = Number.parseFloat(values[12] ?? \"0\")\n const ty = Number.parseFloat(values[13] ?? \"0\")\n if (!Number.isFinite(tx) && !Number.isFinite(ty)) return null\n return { x: Number.isFinite(tx) ? tx : 0, y: Number.isFinite(ty) ? ty : 0 }\n }\n if (transform.startsWith(\"matrix(\")) {\n const values = transform.slice(7, -1).split(\",\")\n const tx = Number.parseFloat(values[4] ?? \"0\")\n const ty = Number.parseFloat(values[5] ?? \"0\")\n if (!Number.isFinite(tx) && !Number.isFinite(ty)) return null\n return { x: Number.isFinite(tx) ? tx : 0, y: Number.isFinite(ty) ? ty : 0 }\n }\n\n // motion-dom's writer emits the keyword form: `translate3d(...)`,\n // `translateX(...)`, etc. — usually as the first segment of a\n // composed transform like `translate3d(50px, 0px, 0) scale(1)`.\n let x = 0\n let y = 0\n let found = false\n const translate3d = transform.match(/translate3d\\(\\s*([-\\d.]+)px\\s*,\\s*([-\\d.]+)px/)\n if (translate3d) {\n x = Number.parseFloat(translate3d[1] ?? \"0\")\n y = Number.parseFloat(translate3d[2] ?? \"0\")\n found = true\n } else {\n const translate2d = transform.match(/translate\\(\\s*([-\\d.]+)px\\s*(?:,\\s*([-\\d.]+)px)?/)\n if (translate2d) {\n x = Number.parseFloat(translate2d[1] ?? \"0\")\n y = Number.parseFloat(translate2d[2] ?? \"0\")\n found = true\n }\n const translateX = transform.match(/translateX\\(\\s*([-\\d.]+)px/)\n if (translateX) {\n x = Number.parseFloat(translateX[1] ?? \"0\")\n found = true\n }\n const translateY = transform.match(/translateY\\(\\s*([-\\d.]+)px/)\n if (translateY) {\n y = Number.parseFloat(translateY[1] ?? \"0\")\n found = true\n }\n }\n if (!found) return null\n return { x: Number.isFinite(x) ? x : 0, y: Number.isFinite(y) ? y : 0 }\n }\n\n return fromString(getComputedStyle(el).transform) ?? fromString(el.style.transform) ?? { x: 0, y: 0 }\n}\n\n/**\n * Compute the `touch-action` CSS value for an element being dragged.\n * Disabling touch-action prevents the browser from interpreting the gesture\n * as a scroll. Axis-locked drags leave the unused axis available for scroll\n * (so a horizontally-draggable card can still be scrolled vertically by the\n * surrounding page).\n */\nfunction touchActionFor(drag: MotionOptions[\"drag\"]): string {\n if (drag === \"x\") return \"pan-y\"\n if (drag === \"y\") return \"pan-x\"\n return \"none\"\n}\n\n/**\n * Resolved drag bounds expressed as absolute MotionValue bounds (Q5/C-lean —\n * drag writes absolute values, so we clamp in MV-space, not offset-space).\n * `Infinity` / `-Infinity` represent \"unbounded in that direction.\"\n */\ntype ResolvedBounds = {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\n/**\n * Resolve a {@link DragConstraints} value into absolute MotionValue bounds at\n * drag-start. Two input shapes (Q8):\n *\n * - **Numeric** (`{ top, left, right, bottom }`): bounds are absolute MV\n * values. `left: -100` means x cannot go below -100.\n * - **HTMLElement or `() => HTMLElement | null`**: container that the\n * dragged element must stay inside. Bounds are computed from the\n * container's bounding rect vs the dragged element's current rect, then\n * re-centered around the current MV values.\n *\n * The element form is resolved ONCE at drag-start (current viewport rects).\n * Reactive constraint changes mid-drag aren't honored in v0.1 — they'd\n * require re-measuring on each pointermove. Acceptable corner case.\n *\n * Returns `null` when constraints are unset or the accessor returns null —\n * caller treats as \"no clamping, no elastic resistance.\"\n */\nfunction resolveConstraints(\n constraints: DragConstraints | undefined,\n el: HTMLElement,\n dragStartX: number,\n dragStartY: number,\n): ResolvedBounds | null {\n if (!constraints) return null\n\n // Discriminate variants with `instanceof HTMLElement` first — this rules\n // out HTMLElement so the `typeof === \"function\"` check below narrows\n // cleanly to the accessor variant. (TS gets confused if we test the\n // function form first; HTMLElement instances have many methods on their\n // prototype, which can muddle TS's narrowing logic.)\n let container: HTMLElement | null = null\n if (constraints instanceof HTMLElement) {\n container = constraints\n } else if (typeof constraints === \"function\") {\n container = constraints()\n }\n\n if (container) {\n // Element-form: compute offset bounds from rects, then add dragStart\n // so we get absolute MV bounds. Subtle but important: the element's\n // current rect already includes any applied transform (including the\n // current dragStart translation), so we add dragStart back to convert\n // \"allowable offset from current position\" to \"allowable absolute MV\n // value.\"\n const containerRect = container.getBoundingClientRect()\n const elementRect = el.getBoundingClientRect()\n return {\n minX: dragStartX + (containerRect.left - elementRect.left),\n maxX: dragStartX + (containerRect.right - elementRect.right),\n minY: dragStartY + (containerRect.top - elementRect.top),\n maxY: dragStartY + (containerRect.bottom - elementRect.bottom),\n }\n }\n\n // Numeric form. Missing keys → unbounded on that side.\n const numeric = constraints as { top?: number; left?: number; right?: number; bottom?: number }\n return {\n minX: numeric.left ?? -Infinity,\n maxX: numeric.right ?? Infinity,\n minY: numeric.top ?? -Infinity,\n maxY: numeric.bottom ?? Infinity,\n }\n}\n\n/**\n * Apply elastic resistance past a boundary (Q15c — linear).\n *\n * Within bounds: `value` passes through unchanged. Past a bound by `Δ`: the\n * displayed value is `boundary + elastic × Δ`. With `elastic: 0` the value\n * clamps hard at the boundary; with `elastic: 1` resistance vanishes\n * (motion's default is `0.5`, halving the overflow).\n *\n * The function is symmetric — overflow on either side resists with the\n * same coefficient.\n */\nfunction applyElastic(value: number, min: number, max: number, elastic: number): number {\n if (value < min) return min + (value - min) * elastic\n if (value > max) return max + (value - max) * elastic\n return value\n}\n\nconst DEFAULT_ELASTIC = 0.5\n\n/**\n * Default `dragTransition` (Q15d — matches motion's inertia preset).\n *\n * `type: \"inertia\"` decays from the release point using `velocity`, with\n * spring physics at `min`/`max` boundaries. The defaults are the values\n * the user signed off on during Phase 2 grilling; passing a custom\n * `dragTransition` shallow-merges over these.\n */\nconst DEFAULT_DRAG_TRANSITION = {\n type: \"inertia\" as const,\n power: 0.8,\n timeConstant: 750,\n bounceStiffness: 500,\n bounceDamping: 10,\n restDelta: 1,\n restSpeed: 10,\n}\n\n/**\n * Bind pointer-driven drag to an element. Layers on top of createPan for the\n * pointer session; adds transform writes, body styles, pointer capture, and\n * state-machine activation.\n *\n * Drag is enabled when `opts.drag` is truthy (`true`, `\"x\"`, or `\"y\"`).\n * createDrag always wires the pointer session — the enable check is per-\n * gesture-start, so toggling `opts.drag` on/off doesn't churn listeners.\n *\n * Phase 2 Commit 6 — Stage 2 scope: VE bootstrap, translation, axis lock,\n * body/pointer styles, callbacks, cleanup. Constraints + elastic resistance\n * land in Stage 3; momentum + dragSnapToOrigin in Stage 4.\n */\nexport function createDrag(\n el: HTMLElement,\n getOpts: () => MotionOptions,\n setActive: SetActive,\n): void {\n // Drag-session state. These are reset on each pan-start; null between\n // sessions. Holding references in the closure is fine — the createPan\n // handlers below close over them.\n let xMV: MotionValue<number> | null = null\n let yMV: MotionValue<number> | null = null\n /** Drag-start position of the x/y MotionValues (the values that existed\n * before the user grabbed). offsets from PanInfo accumulate from this. */\n let dragStartX = 0\n let dragStartY = 0\n /** Resolved bounds for this session — computed once at drag-start and\n * reused across all pointermoves to avoid repeat layout reads. `null`\n * means no constraints. */\n let sessionBounds: ResolvedBounds | null = null\n /** Saved before applying drag's `user-select` / `touch-action` overrides\n * so we can restore them exactly on session end. */\n let savedUserSelect = \"\"\n let savedTouchAction = \"\"\n let capturedPointerId: number | null = null\n /** In-flight momentum animations (one per axis when active). Stopped on\n * owner disposal AND on a fresh pointerdown (to interrupt a settling\n * momentum if the user grabs again mid-decay). */\n let momentumControls: AnimationPlaybackControls[] = []\n\n function isDragEnabled(): boolean {\n return Boolean(getOpts().drag)\n }\n\n function restoreBodyAndElementStyles(): void {\n document.body.style.userSelect = savedUserSelect\n el.style.touchAction = savedTouchAction\n }\n\n function releasePointerCaptureSafely(): void {\n if (capturedPointerId === null) return\n try {\n el.releasePointerCapture(capturedPointerId)\n } catch {\n // jsdom doesn't fully implement setPointerCapture; tolerate.\n }\n capturedPointerId = null\n }\n\n function stopMomentum(): void {\n for (const ctrl of momentumControls) ctrl.stop()\n momentumControls = []\n }\n\n // Stable handler references — they close over getOpts so reactive opts\n // are read at event time. Hoisted out of the createPan call so the\n // function-form options below doesn't re-allocate them per getOpts() call.\n const handlePanStart = (event: PointerEvent, info: PanInfo, mvIsAuthoritative = false) => {\n // The pan session always fires onPanStart once movement crosses the\n // threshold. Drag's enable check is here, not at the createPan-setup\n // site, so toggling `drag` off mid-life immediately stops drag\n // engagement without re-attaching pointer listeners.\n if (!isDragEnabled()) return\n\n // If momentum from a previous drag is still settling, cancel it now —\n // the user has grabbed again, and they expect the element to follow\n // their pointer from its current position, not continue decaying.\n stopMomentum()\n\n const ve = ensureVisualElement(el)\n xMV = ve.getValue(\"x\", 0) as MotionValue<number>\n yMV = ve.getValue(\"y\", 0) as MotionValue<number>\n\n // dragStart capture — two modes:\n //\n // (1) Default: sync the MV to the element's CURRENT visible translate\n // before capturing. motion's `animate(el, target)` interpolates\n // `style.transform` via WAAPI but DOESN'T update the\n // visualElement's x/y MVs in lockstep, so after an entrance\n // animation (e.g. `initial: {x:-300} → animate: {x:0}`) the MV\n // would still hold the start value. Reading the painted transform\n // recovers the truth and seeds dragStart correctly.\n //\n // (2) `mvIsAuthoritative=true` (e.g. dragControls.start with\n // snapToCursor): the caller wrote the MV synchronously RIGHT\n // before reaching us, but motion-dom's writer is frame-scheduled,\n // so `el.style.transform` may not reflect that write yet. Trust\n // the MV in this path — visible would be stale.\n //\n // Only the axis drag actually uses is touched — touching the locked\n // axis would generate spurious MV writes that callers + tests notice.\n const axis = getOpts().drag\n if (mvIsAuthoritative) {\n dragStartX = xMV.get()\n dragStartY = yMV.get()\n } else {\n const visible = readVisibleTranslate(el)\n if (axis !== \"y\") {\n if (visible.x !== xMV.get()) xMV.set(visible.x)\n dragStartX = visible.x\n } else {\n dragStartX = xMV.get()\n }\n if (axis !== \"x\") {\n if (visible.y !== yMV.get()) yMV.set(visible.y)\n dragStartY = visible.y\n } else {\n dragStartY = yMV.get()\n }\n }\n\n // Resolve constraints once per session. Reading layout rects mid-drag\n // would cost a forced reflow per pointermove; one read at drag-start\n // is enough for v0.1 (reactive constraint changes during a drag are\n // a rare corner case — they re-apply on the NEXT session).\n sessionBounds = resolveConstraints(getOpts().dragConstraints, el, dragStartX, dragStartY)\n\n // Body + touch-action overrides — saved so the exact prior values\n // restore on session end (don't assume defaults).\n savedUserSelect = document.body.style.userSelect\n savedTouchAction = el.style.touchAction\n document.body.style.userSelect = \"none\"\n el.style.touchAction = touchActionFor(getOpts().drag)\n\n // Pointer capture keeps move events flowing to the element even when\n // the pointer leaves it during a fast drag. setPointerCapture can\n // throw in some browsers (e.g., already captured); swallow.\n try {\n el.setPointerCapture(event.pointerId)\n capturedPointerId = event.pointerId\n } catch {\n // Safe — window listeners in createPan continue to fire regardless.\n }\n\n setActive(\"whileDrag\", true)\n getOpts().onDragStart?.(event, info)\n }\n\n const handlePan = (event: PointerEvent, info: PanInfo) => {\n if (!isDragEnabled() || !xMV || !yMV) return\n\n const axis = getOpts().drag\n // Axis lock: when drag is \"x\" or \"y\", we SKIP writes to the locked axis\n // entirely — matches motion/react's per-axis shouldDrag short-circuit.\n // Writing dragStartY+0 to yMV when y is locked would generate\n // no-op-but-non-empty writes that consumers and tests both observe.\n const writeX = axis !== \"y\"\n const writeY = axis !== \"x\"\n const elastic = getOpts().dragElastic ?? DEFAULT_ELASTIC\n\n if (writeX) {\n const candidateX = dragStartX + info.offset.x\n const finalX = sessionBounds\n ? applyElastic(candidateX, sessionBounds.minX, sessionBounds.maxX, elastic)\n : candidateX\n xMV.set(finalX)\n }\n if (writeY) {\n const candidateY = dragStartY + info.offset.y\n const finalY = sessionBounds\n ? applyElastic(candidateY, sessionBounds.minY, sessionBounds.maxY, elastic)\n : candidateY\n yMV.set(finalY)\n }\n\n getOpts().onDrag?.(event, info)\n }\n\n const handlePanEnd = (event: PointerEvent, info: PanInfo) => {\n if (!isDragEnabled() || !xMV || !yMV) return\n\n // Visual gesture state ends with the pointerup; momentum is a separate\n // animation that continues after whileDrag deactivates. This matches\n // motion/react semantic: `whileDrag: { scale: 1.05 }` un-scales at\n // release, while the position settles independently.\n setActive(\"whileDrag\", false)\n restoreBodyAndElementStyles()\n releasePointerCaptureSafely()\n\n // The user's `onDragEnd` callback fires at the END of this function\n // (just before the early-out), not here. Rationale: a synchronous\n // state flip from the callback (e.g. closing a Dialog whose contents\n // are this draggable) used to race motion's own post-callback work\n // — momentum dispatch, MV-ref cleanup — and could wedge surrounding\n // libraries that observe the same DOM (scroll lock, pointer-event\n // layers). Firing AFTER all motion DOM-touching work guarantees a\n // clean handoff: by the time the callback runs, the drag session is\n // fully torn down and any subsequent reactive cascade is unambiguous\n // about ownership.\n\n // Capture refs locally — the closure clears xMV/yMV below before the\n // momentum promise can resolve, but the inertia animation needs stable\n // references through its lifetime.\n const xRef = xMV\n const yRef = yMV\n const boundsRef = sessionBounds\n const opts = getOpts()\n const snapToOrigin = opts.dragSnapToOrigin ?? false\n const momentum = opts.dragMomentum ?? true\n const userTransition = opts.dragTransition ?? {}\n\n // Axis lock: the release path must mirror the same write-gate the drag\n // loop uses (handlePan). Without this, pointer velocity on the locked\n // axis feeds an inertia animation on that axis's MV — drifting the\n // element along an axis the user explicitly locked. The cursor still\n // has Y velocity when `drag: \"x\"` (any non-perfectly-horizontal motion\n // moves the pointer through Y), so this matters in practice.\n const dragAxis = opts.drag\n const releaseX = dragAxis !== \"y\"\n const releaseY = dragAxis !== \"x\"\n\n // Reset the tracked momentum array — we'll push 1 or 2 controls below\n // depending on axis. (handlePanStart's stopMomentum already cleared any\n // prior session's controls, but we re-initialize here for clarity since\n // the per-axis branches below append rather than replace.)\n momentumControls = []\n\n // Q15c follow-up: couple bounce physics to `dragElastic`. With elastic\n // 0 (hard clamp), inertia's spring-back at the boundary uses default\n // stiffness/damping that visibly overshoots before settling — even\n // though the drag itself is clamped. Mirror motion-react's pattern\n // (VisualElementDragControls.startAnimation): overdamp the spring with\n // very high stiffness + damping so the snap-back is effectively\n // instantaneous. With elastic > 0 we keep the soft spring so the\n // rubber-band feel is preserved.\n //\n // Numerical choices (200/40 soft, 1e6/1e7 hard) come from motion-react.\n const elastic = opts.dragElastic ?? DEFAULT_ELASTIC\n const bounceParams = elastic\n ? { bounceStiffness: 200, bounceDamping: 40 }\n : { bounceStiffness: 1_000_000, bounceDamping: 10_000_000 }\n\n // Flicker fix for elastic=0: motion-react's source acknowledges that\n // overdamping the spring still computes one frame of overshoot before\n // the snap-back. When the user releases AT a boundary with velocity\n // pointing OUT of that boundary, there's nothing for inertia to\n // usefully decay toward — feeding it the outward velocity produces\n // exactly the visible flicker. Zero those release velocities and\n // inertia settles silently at the bound. Inward velocities are\n // preserved so a release moving back toward center still glides.\n const xAtMax = boundsRef !== null && boundsRef.maxX !== Infinity && xRef.get() >= boundsRef.maxX\n const xAtMin =\n boundsRef !== null && boundsRef.minX !== -Infinity && xRef.get() <= boundsRef.minX\n const yAtMax = boundsRef !== null && boundsRef.maxY !== Infinity && yRef.get() >= boundsRef.maxY\n const yAtMin =\n boundsRef !== null && boundsRef.minY !== -Infinity && yRef.get() <= boundsRef.minY\n const xVelocity =\n !elastic && ((xAtMax && info.velocity.x > 0) || (xAtMin && info.velocity.x < 0))\n ? 0\n : info.velocity.x\n const yVelocity =\n !elastic && ((yAtMax && info.velocity.y > 0) || (yAtMin && info.velocity.y < 0))\n ? 0\n : info.velocity.y\n\n /** Fire onDragTransitionEnd via getOpts so reactive callback swaps see\n * the latest value (the user may have swapped handlers between pan-end\n * and momentum-settle). */\n const fireTransitionEnd = () => getOpts().onDragTransitionEnd?.()\n\n if (snapToOrigin) {\n // Spring back to (0, 0). motion's pattern (Q15e): use the inertia\n // transition but clamp min/max to 0 so the spring physics carries\n // the value home from wherever the user released it.\n const transitionX = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: xVelocity,\n min: 0,\n max: 0,\n }\n const transitionY = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: yVelocity,\n min: 0,\n max: 0,\n }\n const settles: Array<Promise<unknown> | AnimationPlaybackControls> = []\n if (releaseX) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct. Target arg is a placeholder — inertia computes the actual settle point from velocity + min/max.\n const ctrlX = animate(xRef, 0, transitionX as any)\n momentumControls.push(ctrlX)\n settles.push(ctrlX)\n }\n if (releaseY) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct.\n const ctrlY = animate(yRef, 0, transitionY as any)\n momentumControls.push(ctrlY)\n settles.push(ctrlY)\n }\n if (settles.length > 0) Promise.all(settles).then(fireTransitionEnd)\n else fireTransitionEnd()\n } else {\n // Inertia release path — runs regardless of `dragMomentum`. When\n // momentum is true, we feed the (heuristic-clamped) release velocity\n // so the element glides naturally. When momentum is false, we feed\n // velocity 0 — there's no decay, but the bounce physics still spring\n // the element back to the bound if elastic let it overshoot during\n // the drag. Skipping the animate entirely (the prior behavior) left\n // the user stranded outside the container with no way to reach the\n // element. Matches motion-react's pattern (VisualElementDragControls\n // .startAnimation always runs inertia, zeroing velocity when\n // dragMomentum is false).\n const releaseVelocityX = momentum ? xVelocity : 0\n const releaseVelocityY = momentum ? yVelocity : 0\n const transitionX = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: releaseVelocityX,\n min: boundsRef?.minX,\n max: boundsRef?.maxX,\n }\n const transitionY = {\n ...DEFAULT_DRAG_TRANSITION,\n ...bounceParams,\n ...userTransition,\n velocity: releaseVelocityY,\n min: boundsRef?.minY,\n max: boundsRef?.maxY,\n }\n const settles: Array<Promise<unknown> | AnimationPlaybackControls> = []\n if (releaseX) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct.\n const ctrlX = animate(xRef, 0, transitionX as any)\n momentumControls.push(ctrlX)\n settles.push(ctrlX)\n }\n if (releaseY) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape; the runtime call is correct.\n const ctrlY = animate(yRef, 0, transitionY as any)\n momentumControls.push(ctrlY)\n settles.push(ctrlY)\n }\n if (settles.length > 0) Promise.all(settles).then(fireTransitionEnd)\n else fireTransitionEnd()\n }\n\n xMV = null\n yMV = null\n sessionBounds = null\n\n // Callback fires last — see the note at the top of handlePanEnd.\n getOpts().onDragEnd?.(event, info)\n }\n\n // Function-form options so createPan reads `panThreshold` reactively.\n // Handler references are stable — only the threshold (and the wrapping\n // object) is recreated per call from createPan.\n createPan(\n () => el,\n () => ({\n threshold: getOpts().panThreshold,\n onPanStart: handlePanStart,\n onPan: handlePan,\n onPanEnd: handlePanEnd,\n }),\n )\n\n // ---------- External drag (Q9 — createDragControls integration) ----------\n // When the user wires `dragControls: someControls` into MotionOptions, an\n // external pointerdown elsewhere in the UI (a \"drag handle\" button) can\n // start a drag on this element via `controls.start(event)`. Bypasses the\n // threshold gate — the user explicitly said \"drag,\" no hysteresis needed.\n //\n // We synthesize our own pan session here rather than re-using createPan's\n // because:\n // 1. The originating element is the drag handle, not `el`. createPan's\n // pointerdown listener is bound to `el` and wouldn't see the event.\n // 2. We need to skip threshold; createPan's threshold gate is private.\n //\n // The session-tracking logic (pointerId match, sample buffer for velocity,\n // window listener attach/cleanup) is duplicated from createPan. A future\n // refactor could extract a shared \"pan session runner\" if a third caller\n // emerges; for v0.1 the duplication is contained.\n function startExternalDrag(event: PointerEvent, options: DragControlsStartOptions): void {\n if (!isDragEnabled()) return\n\n // Snap-to-cursor (Q9b): move the element so its center sits under the\n // pointer BEFORE the drag-start info captures dragStartX/Y. Otherwise\n // the offset chain would start from the original position and the\n // visible jump-to-cursor would be lost on first pointermove.\n if (options.snapToCursor) {\n const ve = ensureVisualElement(el)\n const snapXMV = ve.getValue(\"x\", 0) as MotionValue<number>\n const snapYMV = ve.getValue(\"y\", 0) as MotionValue<number>\n const elRect = el.getBoundingClientRect()\n const centerX = elRect.left + elRect.width / 2\n const centerY = elRect.top + elRect.height / 2\n const axis = getOpts().drag\n if (axis !== \"y\") snapXMV.set(snapXMV.get() + (event.clientX - centerX))\n if (axis !== \"x\") snapYMV.set(snapYMV.get() + (event.clientY - centerY))\n }\n\n // Fire handlePanStart with a synthesized initial PanInfo. This\n // initializes xMV/yMV/dragStartX/Y, resolves bounds, sets body styles,\n // captures pointer, activates whileDrag, and fires onDragStart.\n //\n // `mvIsAuthoritative=true` when the snap path just wrote the MVs\n // above — handlePanStart should read FROM the MV (not from\n // getComputedStyle) because motion-dom's writer is frame-scheduled\n // and `el.style.transform` may not yet reflect the snap write.\n const initialInfo: PanInfo = {\n point: { x: event.clientX, y: event.clientY },\n delta: { x: 0, y: 0 },\n offset: { x: 0, y: 0 },\n velocity: { x: 0, y: 0 },\n }\n handlePanStart(event, initialInfo, Boolean(options.snapToCursor))\n\n // Track the session locally — these would normally live inside\n // createPan's closure. Velocity samples use motion-dom's `time.now()`\n // to stay frame-synchronous with the rest of the pipeline.\n const sessionStartPoint = { x: event.clientX, y: event.clientY }\n let sessionLastPoint = { ...sessionStartPoint }\n const sessionPointerId = event.pointerId\n const sessionSamples: Array<{ t: number; point: { x: number; y: number } }> = [\n { t: time.now(), point: { ...sessionStartPoint } },\n ]\n\n function computeSessionVelocity(): { x: number; y: number } {\n if (sessionSamples.length < 2) return { x: 0, y: 0 }\n const first = sessionSamples[0]\n const last = sessionSamples[sessionSamples.length - 1]\n if (!first || !last) return { x: 0, y: 0 }\n const dt = last.t - first.t\n if (dt <= 0) return { x: 0, y: 0 }\n return {\n x: ((last.point.x - first.point.x) / dt) * 1000,\n y: ((last.point.y - first.point.y) / dt) * 1000,\n }\n }\n\n function buildSessionInfo(e: PointerEvent): PanInfo {\n const point = { x: e.clientX, y: e.clientY }\n return {\n point,\n delta: { x: point.x - sessionLastPoint.x, y: point.y - sessionLastPoint.y },\n offset: { x: point.x - sessionStartPoint.x, y: point.y - sessionStartPoint.y },\n velocity: computeSessionVelocity(),\n }\n }\n\n function onSessionMove(e: PointerEvent): void {\n if (e.pointerId !== sessionPointerId) return\n const point = { x: e.clientX, y: e.clientY }\n const now = time.now()\n sessionSamples.push({ t: now, point })\n const cutoff = now - 200\n while (sessionSamples.length > 1 && (sessionSamples[0]?.t ?? 0) < cutoff) {\n sessionSamples.shift()\n }\n const info = buildSessionInfo(e)\n sessionLastPoint = point\n handlePan(e, info)\n }\n\n function onSessionEnd(e: PointerEvent): void {\n if (e.pointerId !== sessionPointerId) return\n const info = buildSessionInfo(e)\n handlePanEnd(e, info)\n window.removeEventListener(\"pointermove\", onSessionMove)\n window.removeEventListener(\"pointerup\", onSessionEnd)\n window.removeEventListener(\"pointercancel\", onSessionEnd)\n }\n\n window.addEventListener(\"pointermove\", onSessionMove)\n window.addEventListener(\"pointerup\", onSessionEnd)\n window.addEventListener(\"pointercancel\", onSessionEnd)\n }\n\n // Register with the controls instance whenever opts.dragControls changes.\n // createEffect re-runs on swap; the previous registration unmounts via\n // the symbol-keyed unregister function. Q9d — last mount wins; the\n // unregister only nulls out if we're still the active handler.\n createEffect(() => {\n const controls = getOpts().dragControls as DragControls | undefined\n if (!controls) return\n const internal = controls as DragControls & {\n [DRAG_CONTROLS_REGISTER]?: (\n handler: (event: PointerEvent, options: DragControlsStartOptions) => void,\n ) => () => void\n }\n const register = internal[DRAG_CONTROLS_REGISTER]\n if (!register) return\n const unregister = register(startExternalDrag)\n onCleanup(unregister)\n })\n\n // Owner-disposal cleanup. Three layers:\n // 1. Stop any settling momentum animations (they hold MV references that\n // keep ticking after disposal otherwise).\n // 2. Restore the body/touch styles if we're in mid-drag.\n // 3. Release any captured pointer.\n // createPan's own onCleanup handles removing its listeners separately.\n onCleanup(() => {\n stopMomentum()\n if (xMV || yMV) {\n restoreBodyAndElementStyles()\n releasePointerCaptureSafely()\n }\n })\n}\n","import { type Accessor, createEffect, createSignal, onCleanup } from \"solid-js\"\nimport type { ViewportOptions } from \"../types\"\n\n// ---------------------------------------------------------------------------\n// createInView — observe an element's intersection with a viewport.\n//\n// Standalone hook, distinct from the `inView` *gesture* on MotionOptions\n// (which animates a target when in view). Returns a pair of Solid Accessors\n// for the boolean and the raw IntersectionObserverEntry — booleans and\n// objects aren't animate-able, so a MotionValueAccessor would only add weight\n// (compare with createPan, where numeric fields ARE MVs because they're\n// animate-able and composable).\n// ---------------------------------------------------------------------------\n\nexport type CreateInViewOptions = ViewportOptions & {\n /**\n * Fires with the raw {@link IntersectionObserverEntry} on every\n * visibility transition (enter AND leave). Convenience hook for callers\n * who prefer event-driven access to the entry — the entry is also\n * available reactively via the returned `view.entry()` accessor.\n */\n onChange?: (entry: IntersectionObserverEntry) => void\n}\n\n/** Returned by {@link createInView}. Two Solid Accessors — call them to track. */\nexport type CreateInViewResult = {\n /** Solid Accessor; `true` while the element intersects the viewport per the configured threshold. */\n isInView: Accessor<boolean>\n /** Solid Accessor; the most recent {@link IntersectionObserverEntry}, or `null` before any. */\n entry: Accessor<IntersectionObserverEntry | null>\n}\n\n/**\n * Observe an element via {@link IntersectionObserver} and expose its\n * in-view state as a pair of Solid Accessors.\n *\n * Pass a ref-style accessor that returns the element. The observer\n * attaches once the accessor returns a non-null element and re-attaches\n * if it changes. The observer is disconnected on owner disposal.\n *\n * Options can be a static object or a function form (matching `useMotion`\n * and `createPan`'s convention). The function form is tracked inside the\n * effect — option changes (e.g., switching `root`) re-attach the observer.\n *\n * @example Static options\n * const [el, setEl] = createSignal<HTMLElement>()\n * const view = createInView(el, { once: true })\n * createEffect(() => {\n * if (view.isInView()) console.log(\"now in view\")\n * })\n *\n * @example Function-form options (reactive)\n * const [root, setRoot] = createSignal<HTMLElement>()\n * const view = createInView(el, () => ({ root, margin: \"100px\" }))\n *\n * @example Reading the raw entry reactively\n * const view = createInView(el)\n * createEffect(() => {\n * const e = view.entry()\n * if (e) console.log(\"ratio:\", e.intersectionRatio)\n * })\n *\n * <div ref={setEl}>watch me</div>\n */\nexport function createInView(\n ref: () => Element | null | undefined,\n options: CreateInViewOptions | (() => CreateInViewOptions) = {},\n): CreateInViewResult {\n const [isInView, setIsInView] = createSignal(false)\n const [entry, setEntry] = createSignal<IntersectionObserverEntry | null>(null)\n\n // createEffect — Solid-idiomatic for side-effect setup (attaching the\n // IntersectionObserver). First iteration runs in the next microtask,\n // which is harmless: a freshly-mounted element can't be in or out of\n // the viewport before the microtask flushes. Option reads inside the\n // effect's body are tracked — function-form options that read signals\n // will re-run the effect (and re-attach the observer) on change.\n createEffect(() => {\n const el = ref()\n if (!el) return\n const opts = typeof options === \"function\" ? options() : options\n\n const threshold = resolveThreshold(opts.amount)\n const observer = new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n // Fire onChange first so callers can synchronously inspect the\n // entry before any downstream signal-effects see the new state.\n opts.onChange?.(e)\n // Update the entry signal either way — consumers reading\n // `view.entry()` reactively see both enter and leave.\n setEntry(e)\n if (e.isIntersecting) {\n setIsInView(true)\n if (opts.once) observer.disconnect()\n } else if (!opts.once) {\n setIsInView(false)\n }\n }\n },\n {\n root: opts.root?.() ?? null,\n rootMargin: opts.margin ?? \"0px\",\n threshold,\n },\n )\n observer.observe(el)\n\n onCleanup(() => observer.disconnect())\n })\n\n return { isInView, entry }\n}\n\nfunction resolveThreshold(amount: ViewportOptions[\"amount\"]): number | number[] {\n // Pass arrays through unchanged so callers can request continuous\n // `intersectionRatio` updates (the underlying IntersectionObserver fires\n // once per threshold crossing, so a fine array → near-live ratio).\n if (Array.isArray(amount)) return amount\n if (typeof amount === \"number\") return amount\n if (amount === \"all\") return 1\n // \"some\" or undefined → minimal threshold (any pixel intersecting)\n return 0\n}\n","import { addDomEvent, hover, press } from \"motion-dom\"\nimport { createEffect, onCleanup } from \"solid-js\"\nimport type { MotionElement, MotionOptions } from \"../types\"\nimport { createInView } from \"./createInView\"\nimport type { SetActive } from \"./gesture-state\"\n\n// ---------------------------------------------------------------------------\n// createGestures — wires pointer-driven gestures (hover, press, focus, inView)\n// to the gesture state machine's `setActive`. Phase 2 Commit 2 wires hover and\n// press only; focus and inView land in Commit 3.\n//\n// Q1/C — hover and press are routed through motion-dom's primitives directly,\n// not re-implemented. ADR 0001 documents the dependency.\n//\n// Q13/a — listeners attach unconditionally on mount and clean up on owner\n// disposal. We do NOT re-attach when `opts.hover` / `opts.press` flip between\n// defined and undefined: the state machine's per-key winners memo naturally\n// produces an empty diff when an active state has no target, so the extra\n// DOM listener pair costs nothing in practice.\n// ---------------------------------------------------------------------------\n\n/**\n * Bind pointer-event-driven gestures (hover, press) to the motion element.\n * Toggles the state machine's `whileHover` / `whilePress` flags and forwards\n * events to the user's `MotionCallbacks`.\n */\nexport function createGestures(\n el: MotionElement,\n getOpts: () => MotionOptions,\n setActive: SetActive,\n): void {\n // ---------- Hover ----------\n // motion-dom's hover(): start callback shape is `(element, event) => onEnd?`.\n // We ignore `element` (always equal to `el` since we pass the element rather\n // than a selector). The optional returned function fires on hover-end.\n //\n // Why motion-dom's hover() rather than addEventListener(\"pointerenter\")?\n // Subtle behaviors handled inside motion-dom we'd otherwise re-derive:\n // - Press-in-progress defers hover-end until pointer-up (mobile UX).\n // - Secondary pointer events filtered via isPrimaryPointer.\n // - pointercancel cleanup parallel to pointerup.\n const stopHover = hover(el, (_element, event) => {\n setActive(\"whileHover\", true)\n getOpts().onHoverStart?.(event)\n return (event) => {\n setActive(\"whileHover\", false)\n getOpts().onHoverEnd?.(event)\n }\n })\n onCleanup(stopHover)\n\n // ---------- Press ----------\n // motion-dom's press(): same callback shape, plus the end callback receives\n // `(event, { success: boolean })`. `success === true` when the pointer was\n // still over the element at pointer-up (completed press); `false` when it\n // moved away or was cancelled.\n //\n // Q13/c — branch on `info.success`:\n // onPressStart fires at pointerdown (no success info yet — Q13 tightened\n // the signature to drop the info param).\n // onPress fires on completed press.\n // onPressCancel fires on aborted press.\n const stopPress = press(el, (_element, event) => {\n setActive(\"whilePress\", true)\n getOpts().onPressStart?.(event)\n return (event, info) => {\n setActive(\"whilePress\", false)\n if (info.success) {\n getOpts().onPress?.(event, info)\n } else {\n getOpts().onPressCancel?.(event, info)\n }\n }\n })\n onCleanup(stopPress)\n\n // ---------- Focus (Q12) ----------\n // Activation (`whileFocus` state) is gated by `:focus-visible` — mouse\n // clicks that incidentally focus an element should NOT trigger the visual\n // state, only keyboard navigation does. The native `onFocus`/`onBlur`\n // callbacks fire for every focus event regardless (Q12b — programmatic\n // listeners shouldn't be filtered).\n //\n // The `:focus-visible` selector throws in older browsers — we fall back\n // to always-active, matching motion/react's behavior in that scenario.\n //\n // We use motion-dom's `addDomEvent` (rather than el.addEventListener\n // directly) for consistency with the rest of Phase 2's motion-dom usage,\n // and because it returns a tidy cleanup function we can hand to onCleanup.\n let focusActiveByVisible = false\n const stopFocus = addDomEvent(el, \"focus\", (event) => {\n let isFocusVisible = false\n try {\n isFocusVisible = el.matches(\":focus-visible\")\n } catch {\n isFocusVisible = true\n }\n if (isFocusVisible) {\n setActive(\"whileFocus\", true)\n focusActiveByVisible = true\n }\n getOpts().onFocus?.(event as FocusEvent)\n })\n const stopBlur = addDomEvent(el, \"blur\", (event) => {\n if (focusActiveByVisible) {\n setActive(\"whileFocus\", false)\n focusActiveByVisible = false\n }\n getOpts().onBlur?.(event as FocusEvent)\n })\n onCleanup(stopFocus)\n onCleanup(stopBlur)\n\n // ---------- inView (Q10/A1) ----------\n // The gesture reuses `createInView` — same observer setup. The `onChange`\n // merges into the options object so the gesture's onViewportEnter/Leave\n // hooks receive the raw entry.\n //\n // The element is wrapped in `() => el` because createInView takes a ref\n // accessor; we pass a constant accessor since `el` is fixed for the\n // gesture's lifetime. The options are function-form so reactive\n // inViewOptions changes (e.g., a reactive `root` accessor) re-attach\n // the observer naturally.\n //\n // A createEffect bridges createInView's `isInView` Accessor to the state\n // machine's setActive. When `once: true`, createInView keeps isInView=true\n // after first intersection (observer disconnected); the gesture's\n // whileInView stays active forever — motion/react parity.\n const view = createInView(\n () => el,\n () => ({\n ...getOpts().inViewOptions,\n onChange: (entry: IntersectionObserverEntry) => {\n if (entry.isIntersecting) {\n getOpts().onViewportEnter?.(entry)\n } else {\n getOpts().onViewportLeave?.(entry)\n }\n },\n }),\n )\n createEffect(() => {\n setActive(\"whileInView\", view.isInView())\n })\n}\n","// ---------------------------------------------------------------------------\n// Default value table for transform-class and a few well-known CSS properties.\n// Used by the gesture state machine's \"removed keys\" fallback (Q7): when a\n// higher-priority gesture deactivates and no lower-priority state defines a\n// key, we animate the key back to:\n// 1. the user's `initial` target (captured at mount) — handled at call site\n// 2. otherwise the value from this table\n// 3. otherwise `null` (motion's animate() reads from computed style)\n//\n// The values here mirror motion-dom's conventions (scale → 1, x/y/z → 0,\n// rotate/skew → 0, opacity → 1). We don't import motion-dom's defaultValueTypes\n// directly because (a) it's a value-type system, not a defaults table, and\n// (b) keeping a stable local source insulates us from motion-dom internal churn.\n// ---------------------------------------------------------------------------\n\nconst TRANSFORM_DEFAULTS: Readonly<Record<string, number>> = {\n // Translate\n x: 0,\n y: 0,\n z: 0,\n translateX: 0,\n translateY: 0,\n translateZ: 0,\n // Scale (multiplicative identity)\n scale: 1,\n scaleX: 1,\n scaleY: 1,\n scaleZ: 1,\n // Rotate\n rotate: 0,\n rotateX: 0,\n rotateY: 0,\n rotateZ: 0,\n // Skew\n skew: 0,\n skewX: 0,\n skewY: 0,\n // Perspective\n perspective: 0,\n transformPerspective: 0,\n // Opacity (the one non-transform key with a strong default)\n opacity: 1,\n}\n\n/**\n * Look up the canonical fallback value for a property key. Returns the table\n * value if known, else `null` — which motion's `animate()` interprets as\n * \"read from computed style at animation start.\"\n */\nexport function getMotionDefault(key: string): number | null {\n return TRANSFORM_DEFAULTS[key] ?? null\n}\n","import { type AnimationPlaybackControls, animate, isMotionValue, type MotionValue } from \"motion\"\nimport { type Accessor, createEffect, createMemo, onCleanup, untrack } from \"solid-js\"\nimport { createStore, type SetStoreFunction, type Store } from \"solid-js/store\"\nimport { getMotionDefault } from \"../default-values\"\nimport { shouldReduceMotion } from \"../reduced-motion\"\nimport type {\n AnimateValue,\n MotionConfigContextValue,\n MotionElement,\n MotionOptions,\n ResolvedValues,\n Target,\n Transition,\n VariantContextValue,\n} from \"../types\"\nimport { asVariantLabels, mergeTransition, resolveTarget } from \"./createMotion\"\n\n// ---------------------------------------------------------------------------\n// Solid-native fine-grained gesture state machine (ADR 0002).\n//\n// Implements three of the four jobs motion's createAnimationState handles:\n// 1. Priority resolution — high-to-low among active states\n// 2. Per-key handoff — when a higher-priority state deactivates, lower-priority\n// states (or fallbacks) take over each key it was animating\n// 3. Variant resolution — reuses Phase 1's resolveTarget for label→Target lookup\n//\n// Job 4 (parent-child variant inheritance via variantChildren) is handled\n// reactively through Phase 1's VariantContext + Q4's active-gated label slots,\n// NOT via this state machine — keeping the inheritance tree Solid-owned.\n// ---------------------------------------------------------------------------\n\n/** State names, ordered low → high priority. Matches motion-dom's variantPriorityOrder. */\nconst STATE_NAMES = [\n \"animate\",\n \"whileInView\",\n \"whileHover\",\n \"whilePress\",\n \"whileFocus\",\n \"whileDrag\",\n \"exit\",\n] as const\n\nexport type GestureStateName = (typeof STATE_NAMES)[number]\n\n/** High → low priority for the winners walk. Materialized once. */\nconst PRIORITY_HIGH_TO_LOW: readonly GestureStateName[] = [...STATE_NAMES].reverse()\n\n/** A key's resolved value plus the (optional) per-target transition that produced it. */\ntype WinnerEntry = {\n value: unknown\n transition: Transition | undefined\n /** Which state contributed this key — used by the diff effect's onAnimationComplete bookkeeping. */\n stateName: GestureStateName\n}\n\nexport type SetActive = (state: GestureStateName, isActive: boolean) => void\n\n/** The reactive store of active gesture flags, lifted to the caller for sharing. */\nexport type ActiveStore = Store<Record<GestureStateName, boolean>>\nexport type SetActiveStore = SetStoreFunction<Record<GestureStateName, boolean>>\nexport type ActiveStoreTuple = [ActiveStore, SetActiveStore]\n\nexport type CreateGestureStateMachineDeps = {\n el: MotionElement\n getOpts: () => MotionOptions\n parentVariantCtx: VariantContextValue\n motionConfig: MotionConfigContextValue\n systemReducedMotion: Accessor<boolean>\n /** Captured at construction. Used as the first stop in the removed-key fallback chain (Q7). */\n initialTarget: Target | null\n /**\n * Optional external active store (Q4 — useMotion lifts this up so its\n * `myVariantCtx` can read the same flags it propagates to descendants).\n * When omitted, the state machine creates its own internal store —\n * backward-compatible for `createMotion` direct users.\n */\n externalActiveStore?: ActiveStoreTuple\n /**\n * Phase 3 — when an enclosing `<Presence initial={false}>` is active, this\n * is passed through to suppress the first-mount animate (mirrors the\n * existing `initial: false` user-opt-out, but driven from above by\n * Presence instead of by the user's own options).\n */\n suppressFirstMount?: boolean\n /**\n * Phase 3 — readiness gate for the first-mount animate when this motion\n * element is wrapped in a real `<Presence>`. The state machine reads this\n * on each iteration; when it's `false` AND we haven't run yet, the diff\n * effect short-circuits (no animate dispatch, no MV subscriptions sealed).\n * Presence flips it to `true` from its `onEnter` / `onChange.added`\n * callback, at which point the effect re-runs and treats THAT iteration\n * as the first.\n *\n * Outside a Presence (no-op default context), createMotion leaves this\n * `undefined` — the state machine treats absence as `ready=true` and the\n * existing eager-first-iteration behavior is unchanged.\n *\n * Rationale: real `motion.animate()` is a Web Animations API call that\n * runs even on a disconnected element, but its terminal `commitStyles`\n * silently no-ops when the element is off-DOM. For a `mode: \"wait\"` swap\n * the new child is created BEFORE the old child's exit completes, so\n * dispatching the first animate eagerly would let it complete in the\n * detached state and the element would paint at its `initial` target\n * when it finally enters the DOM. Deferring until `onEnter` (when\n * transition-group has synchronously inserted the element via\n * `setReturned`) closes that gap.\n */\n enterReady?: Accessor<boolean>\n /**\n * MV-in-style Stage 3 bridge. When provided, the diff effect calls this\n * per animate-target key. A returned `MotionValue` routes the animation\n * through that MV (`animate(mv, value, opts)`) — its change-subscription\n * (in createMotion) composes `el.style` from the registry. `undefined`\n * routes the key down the existing `animate(el, target, opts)` WAA path.\n *\n * createMotion only activates this when at least one external MV is\n * registered (i.e., the user supplied `style: { scale: mv }`-shaped\n * options). Inactive in the common case → 293 baseline tests stay on\n * the original code path, their animateSpy assertions unaffected.\n */\n getValueForAnimate?: (key: string, fallback: unknown) => MotionValue<unknown> | undefined\n}\n\nexport type GestureStateMachine = {\n /** Imperatively toggle a gesture state. Triggers re-resolution + animate(). */\n setActive: SetActive\n /**\n * Resolves when the next animate dispatched while `exit` is the highest-\n * priority active driver state completes. If no exit animation is in\n * flight AND no exit target is defined, resolves immediately.\n *\n * Used by `createMotion`'s presence registration: the registered\n * `runExit` callable does `setActive(\"exit\", true)` then awaits this.\n * When the exit animation settles, `<Presence>` (or the hook) gets a\n * resolved Promise and proceeds with DOM removal.\n *\n * Multiple concurrent waiters are supported — they all resolve from the\n * same animation's completion.\n */\n onceExitComplete: () => Promise<void>\n}\n\n/**\n * Construct the per-element gesture state machine.\n *\n * Wired primitives:\n * - `createStore` for the seven active flags — Solid tracks per-path, so\n * toggling `whileHover` doesn't dirty memos reading `whilePress`.\n * - `createMemo` for `stateTargets` — cached, re-runs only when opts/parent\n * context change.\n * - `createMemo` for `winners` — same caching, re-runs when `active` flags or\n * `stateTargets` change.\n * - `createEffect` for the diff-and-animate loop — fires on `winners` change;\n * compares against `lastApplied` to compute changed/removed keys.\n * - `onCleanup` inside the effect for per-iteration MV subscriptions — scoped\n * to each effect run (fires on re-run AND owner disposal). Same iteration-\n * scoped cleanup pattern Phase 1 established.\n */\nexport function createGestureStateMachine(\n deps: CreateGestureStateMachineDeps,\n): GestureStateMachine {\n const {\n el,\n getOpts,\n parentVariantCtx,\n motionConfig,\n systemReducedMotion,\n initialTarget,\n externalActiveStore,\n suppressFirstMount,\n enterReady,\n getValueForAnimate,\n } = deps\n\n // ---------- Active flags ----------\n // `animate` defaults true: it's the baseline state (mirrors motion's\n // createTypeState(true) for animate). All other states start inactive.\n // If the caller provided an external store (Q4 — useMotion lifts this up\n // so myVariantCtx can read the same flags), reuse it; else create our own.\n const [active, setActiveStore] =\n externalActiveStore ??\n createStore<Record<GestureStateName, boolean>>({\n animate: true,\n whileInView: false,\n whileHover: false,\n whilePress: false,\n whileFocus: false,\n whileDrag: false,\n exit: false,\n })\n\n // ---------- Per-state resolved targets ----------\n // createMemo (not createComputed): reads only run when opts/parent change,\n // and the value is cached for downstream consumers. The animate call is\n // frame-async tolerant — the side-effect createEffect below handles timing.\n const stateTargets = createMemo<Record<GestureStateName, Target | null>>(() => {\n const opts = getOpts()\n const variants = opts.variants\n const custom = opts.custom ?? parentVariantCtx.custom?.()\n return {\n animate: resolveTarget(\n opts.animate,\n variants,\n asVariantLabels(parentVariantCtx.animate?.()),\n custom,\n ),\n whileInView: resolveTarget(\n opts.inView,\n variants,\n asVariantLabels(parentVariantCtx.inView?.()),\n custom,\n ),\n whileHover: resolveTarget(\n opts.hover,\n variants,\n asVariantLabels(parentVariantCtx.hover?.()),\n custom,\n ),\n whilePress: resolveTarget(\n opts.press,\n variants,\n asVariantLabels(parentVariantCtx.press?.()),\n custom,\n ),\n whileFocus: resolveTarget(\n opts.focus,\n variants,\n asVariantLabels(parentVariantCtx.focus?.()),\n custom,\n ),\n // whileDrag — resolved like any other gesture state's target. Drag's\n // visual state composes with drag's translation through the shared\n // VisualElement (Q5/C-lean).\n whileDrag: resolveTarget(opts.whileDrag, variants, undefined, custom),\n exit: resolveTarget(opts.exit, variants, asVariantLabels(parentVariantCtx.exit?.()), custom),\n }\n })\n\n // ---------- Per-key winners (priority resolution + per-key claim) ----------\n // Walks PRIORITY_HIGH_TO_LOW. A state is considered active if EITHER its\n // own flag is true OR the parent's VariantContext provides a label for it\n // (Q4 — gesture inheritance through context). The first active state that\n // defines a key claims it; lower-priority states are skipped for that key.\n //\n // Q5/C-lean exclusion: while drag is ACTIVE (pointer engaged), `x` and `y`\n // are owned by\n // createDrag (it writes them to the VisualElement's MotionValues during\n // pointer phase). Filter them out of the winners map so motion's animate\n // (called from this effect) doesn't fight drag's writes. Other transform\n // keys (scale, rotate, etc.) still flow normally — they compose with\n // drag's translation through the shared VisualElement.\n //\n // EXCEPTION: when `exit` is active, exit's x/y MUST override drag's claim.\n // Otherwise an element being dragged at the moment of unmount would\n // exit-animate without translation (drag would silently win every frame),\n // which contradicts the priority chain's stated semantic (exit is highest).\n // Drag's pointer listeners will release anyway when the element unmounts;\n // exit's translation reaches DOM until that happens.\n const winners = createMemo<Record<string, WinnerEntry>>(() => {\n const targets = stateTargets()\n // Drag claims x/y only while the user is ACTIVELY dragging (pointer\n // engaged → `active.whileDrag === true`). When drag is merely\n // configured-but-idle, initial/animate/exit and other states get\n // normal access to x/y — matching motion-react. Reading from `active`\n // tracks the store; the winners memo re-runs when whileDrag flips.\n const dragActive = active.whileDrag\n const out: Record<string, WinnerEntry> = {}\n for (const stateName of PRIORITY_HIGH_TO_LOW) {\n if (!isStateActive(stateName, active, parentVariantCtx)) continue\n const target = targets[stateName]\n if (!target) continue\n for (const key in target) {\n // `transition` is animation config, not a style key — never a winner.\n if (key === \"transition\") continue\n // Higher-priority state already won this key.\n if (key in out) continue\n // x/y are drag-owned during active drag — unless exit is also\n // active, in which case exit's translation wins.\n if (!active.exit && dragActive && (key === \"x\" || key === \"y\")) continue\n out[key] = {\n value: (target as Record<string, unknown>)[key],\n transition: target.transition,\n stateName,\n }\n }\n }\n return out\n })\n\n // ---------- Diff-and-animate effect ----------\n // The single site that calls motion's animate(). Diffs winners against\n // lastApplied to compute changed keys (a) and removed keys (b). Removed keys\n // walk Q7's fallback chain: initial → motion default → null.\n let prevControls: AnimationPlaybackControls | null = null\n let lastApplied: Record<string, unknown> = {}\n let isFirstRun = true\n\n // ---------- onceExitComplete plumbing (Phase 3 — Presence integration) ----------\n // Resolvers queued by `onceExitComplete()` waiters. Drain happens when an\n // exit-driven animate dispatched from this effect resolves. Multiple waiters\n // for the same exit batch all resolve from one drain.\n let pendingExitResolvers: Array<() => void> = []\n function drainPendingExitResolvers(): void {\n const resolvers = pendingExitResolvers\n pendingExitResolvers = []\n for (const r of resolvers) r()\n }\n\n createEffect(() => {\n const next = winners()\n const opts = getOpts()\n\n // Presence-aware readiness gate: when the surrounding `<Presence>` is\n // still holding this element off-DOM (the new child during a mode=\"wait\"\n // swap, or the initial child before appear's enterTransition runs),\n // we MUST NOT dispatch the first animate. Web Animations API will run\n // it to completion off-DOM, then silently drop the final commitStyles —\n // the element would paint at its `initial` target when it eventually\n // enters the DOM. Skip the entire iteration (winners() above subscribed\n // us to future changes); when Presence flips enterReady this effect\n // re-runs and the iteration below treats THAT pass as the first.\n if (isFirstRun && enterReady && !enterReady()) {\n return\n }\n\n // First-mount guard: either the user opted out via `initial: false` OR\n // an enclosing `<Presence initial={false}>` propagated suppression via\n // `suppressFirstMount`. Either path seeds lastApplied so the next\n // iteration treats current winners as already-applied. We fall through\n // to the MV subscription loop so subsequent MV.set() drives animate.\n let skipAnimate = false\n if (isFirstRun && (untrack(() => opts.initial) === false || suppressFirstMount)) {\n lastApplied = snapshotValues(next)\n skipAnimate = true\n }\n isFirstRun = false\n\n // Bail out completely only when there is nothing to do AND nothing has\n // been applied yet (no lastApplied to revert). The previous version of\n // this guard also bailed when `next` was empty even if lastApplied still\n // held values from a previous gesture — preventing the removed-key\n // fallback from reverting. The looser condition keeps the same early-out\n // for the initial idle case while letting deactivation reverts run.\n const bailOnNoTarget =\n !skipAnimate &&\n Object.keys(next).length === 0 &&\n Object.keys(lastApplied).length === 0 &&\n opts.animate === undefined &&\n parentVariantCtx.animate?.() === undefined\n if (bailOnNoTarget) return\n\n // Compute changes: (a) keys with new/changed values, (b) removed keys.\n const changes: Record<string, unknown> = {}\n let mergedPerTargetTransition: Transition | undefined\n\n if (!skipAnimate) {\n for (const key in next) {\n const entry = next[key]\n // `noUncheckedIndexedAccess` widens record reads to `T | undefined`,\n // but `for (key in obj)` only yields present keys — entry is real.\n if (!entry) continue\n if (lastApplied[key] !== entry.value) {\n changes[key] = entry.value\n // First non-undefined per-target transition wins. (If multiple winners\n // contribute conflicting transitions, the highest-priority one already\n // took precedence in the priority walk.)\n mergedPerTargetTransition ??= entry.transition\n }\n }\n for (const key in lastApplied) {\n if (key in next) continue\n // x/y aren't \"removed\" when drag is active — drag is CLAIMING them.\n // Falling back to initial here would dispatch animate(el, {x:-W})\n // on pointerdown and snap the element back to its initial state\n // before the user's first move could reach the DOM.\n if (active.whileDrag && (key === \"x\" || key === \"y\")) continue\n // Removed-key fallback: own initial → motion default → null.\n const initialValue =\n initialTarget && key in (initialTarget as Record<string, unknown>)\n ? (initialTarget as Record<string, unknown>)[key]\n : undefined\n changes[key] = initialValue !== undefined ? initialValue : getMotionDefault(key)\n }\n }\n\n // Transition merge: MotionConfig default < user's transition < per-target\n // transition < reduced-motion override (Phase 1's mergeTransition).\n const reduced = shouldReduceMotion(motionConfig.reducedMotion(), systemReducedMotion())\n const transition = mergeTransition(\n motionConfig.transition(),\n opts.transition,\n mergedPerTargetTransition,\n reduced,\n )\n\n // Track which animate value triggered this — used by onAnimationComplete.\n // If `next` has any key from `animate` state, the effective value is opts.animate.\n // If only gesture states are active, the highest-priority active state's value drives.\n const driverState = highestActiveDriverState(next)\n const effectiveAnimateValue = animateValueForState(driverState, opts, parentVariantCtx)\n\n // Animate options builder — read at fire-time so reactive callback swaps\n // apply between calls (per Phase 1 semantics). Closed over by the\n // MV-on-change subscriptions below as well as the diff dispatch.\n const buildAnimateOptions = () => ({\n ...transition,\n onPlay: opts.onAnimationStart ? () => untrack(() => opts.onAnimationStart?.()) : undefined,\n onComplete: opts.onAnimationComplete\n ? () =>\n untrack(() => {\n if (effectiveAnimateValue != null) {\n opts.onAnimationComplete?.(effectiveAnimateValue)\n }\n })\n : undefined,\n onStop: opts.onAnimationCancel ? () => untrack(() => opts.onAnimationCancel?.()) : undefined,\n onUpdate: opts.onUpdate\n ? (latest: ResolvedValues) => untrack(() => opts.onUpdate?.(latest))\n : undefined,\n })\n\n if (!skipAnimate && Object.keys(changes).length > 0) {\n // Update lastApplied to the new winner snapshot (NOT including removed-\n // key fallback values — those become \"applied\" only after the animation\n // lands, but tracking that requires onUpdate plumbing. For diff purposes,\n // we consider them applied immediately; if the user re-activates a state\n // that brings the key back, the diff sees `lastApplied[key] = fallback`\n // vs `next[key] = newValue` and animates correctly).\n lastApplied = { ...lastApplied, ...changes }\n // Then drop keys that don't appear in `next` from lastApplied so future\n // re-removals don't compare against stale fallback values.\n for (const key in lastApplied) {\n if (!(key in next) && !(key in changes)) delete lastApplied[key]\n }\n\n // ---------- splitTarget: separate MotionValue refs from plain values ----------\n // Preserved from Phase 1: motion's vanilla animate(el, target) doesn't\n // subscribe to MotionValue refs in target values. We split and seed the\n // animate call with snapshots; per-MV subscription happens below.\n const { plain } = splitTarget(changes)\n\n // ---------- Stage 3 bridge: split `plain` by routing destination ----------\n // When createMotion's `getValueForAnimate` returns an MV for a key, the\n // tween runs against that MV (transient or external) and the registry's\n // writer composes el.style.transform. When it returns undefined (the\n // common case — no style MVs), the key falls through to the existing\n // `animate(el, target, opts)` WAA path. With NO routed keys, we make a\n // single WAA call exactly like before, preserving the call shape that\n // baseline tests assert against.\n const routed: Array<{ mv: MotionValue<unknown>; value: unknown }> = []\n const waaPlain: Record<string, unknown> = {}\n for (const key in plain) {\n const value = plain[key]\n const fallback =\n initialTarget && key in (initialTarget as Record<string, unknown>)\n ? (initialTarget as Record<string, unknown>)[key]\n : getMotionDefault(key)\n const routedMV = getValueForAnimate?.(key, fallback)\n if (routedMV) {\n routed.push({ mv: routedMV, value })\n } else {\n waaPlain[key] = value\n }\n }\n\n // Cancel any in-flight animation before kicking off the next one.\n prevControls?.stop()\n const animOpts = buildAnimateOptions()\n if (routed.length === 0) {\n // Pure WAA path — identical to the pre-Stage-3 behavior.\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape we can't tighten generically; the runtime call is correct.\n prevControls = animate(el, waaPlain as any, animOpts)\n } else {\n // Bridge path — one tween per routed MV plus (optionally) a single\n // WAA call for non-routed keys. `aggregateControls` combines them\n // into a thenable that .stop()s each and resolves when all settle,\n // so the exit-drain logic below works uniformly across both shapes.\n const controls: AnimationPlaybackControls[] = []\n for (const { mv, value } of routed) {\n // biome-ignore lint/suspicious/noExplicitAny: same as above\n controls.push(animate(mv as any, value as any, animOpts as any))\n }\n if (Object.keys(waaPlain).length > 0) {\n // biome-ignore lint/suspicious/noExplicitAny: same as above\n controls.push(animate(el, waaPlain as any, animOpts))\n }\n prevControls = aggregateControls(controls)\n }\n\n // Drain `onceExitComplete()` waiters when this dispatch is driven by\n // the exit state — i.e., Presence is awaiting the unmount animation.\n // motion's AnimationPlaybackControls is thenable at runtime (motion\n // returns a thenable handle) but the public type doesn't surface\n // `.then` — narrow via PromiseLike. The promise settles on natural\n // completion OR cancellation (`.stop()` from a subsequent effect\n // run). Both should drain — from the caller's perspective the exit\n // animation is \"done\" either way. The freshness check ensures a stale\n // dispatch doesn't drain a newer animation's waiters.\n if (driverState === \"exit\") {\n const dispatched = prevControls\n const thenable = dispatched as unknown as PromiseLike<unknown>\n thenable.then(() => {\n if (prevControls === dispatched) drainPendingExitResolvers()\n })\n }\n } else if (driverState === \"exit\") {\n // Exit is the driver but no animate ran (target absent or no key diff).\n // Drain immediately so any awaiting `runExit` callers don't hang.\n drainPendingExitResolvers()\n }\n\n // ---------- MotionValue-in-target subscriptions ----------\n // Walk `next` (the FULL winner set) rather than `changes` (the diff) and\n // subscribe a per-key animate callback to each MV's `change` event. This\n // loop runs on EVERY effect iteration that gets past the bailOnNoTarget\n // guard above, including iterations that produced no diff.\n //\n // Bug fix: previously this loop lived inside the \"has changes\" branch.\n // Sibling effects in createGestures (notably the inView wiring's\n // setActive call after IntersectionObserver's first emission) can\n // invalidate the winners memo without changing any actual value. On\n // those re-runs, the iteration-scoped `onCleanup` from the prior run\n // unsubscribed the MV listeners and we never reattached, dropping all\n // future MV.set() → animate plumbing. Walking `next` here keeps the\n // subscriptions in lockstep with the effect's lifetime.\n for (const key in next) {\n const entry = next[key]\n if (!entry) continue\n if (isMotionValue(entry.value)) {\n const targetMV = entry.value as MotionValue<unknown>\n onCleanup(\n targetMV.on(\"change\", (v) => {\n // Stage 3: route through the registry the same way the main\n // dispatch does, so a style MV the user also wrote into\n // `animate` doesn't bypass the writer's transform composition.\n const fallback =\n initialTarget && key in (initialTarget as Record<string, unknown>)\n ? (initialTarget as Record<string, unknown>)[key]\n : getMotionDefault(key)\n const routedMV = getValueForAnimate?.(key, fallback)\n if (routedMV && routedMV !== targetMV) {\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate overload soup; runtime correct\n animate(routedMV as any, v as any, buildAnimateOptions() as any)\n } else {\n // biome-ignore lint/suspicious/noExplicitAny: same as above\n animate(el, { [key]: v } as any, buildAnimateOptions())\n }\n }),\n )\n }\n }\n })\n\n // Owner-disposal cleanup: stop any in-flight animation.\n onCleanup(() => prevControls?.stop())\n\n function setActive(state: GestureStateName, isActive: boolean): void {\n setActiveStore(state, isActive)\n }\n\n /**\n * Phase 3 — Presence integration. Returns a Promise that resolves when the\n * NEXT exit-driven animate dispatched by the diff effect completes, OR\n * immediately if no exit target is configured (nothing to wait for).\n *\n * The typical caller is `createMotion`'s presence-registered `runExit`:\n * it flips `setActive(\"exit\", true)` then awaits this. The diff effect\n * runs in the next microtask, dispatches the exit animation, and on its\n * completion drains the pending resolvers.\n *\n * Multiple concurrent waiters are supported — they all resolve from the\n * same animation's completion.\n *\n * Edge case: if the user reactively removes `opts.exit` AFTER this call\n * but before the effect runs, the resolver will still be drained the\n * next time exit drives a dispatch (or by the \"no-animate but exit-\n * driven\" branch in the effect).\n */\n function onceExitComplete(): Promise<void> {\n const exitTarget = untrack(() => stateTargets().exit)\n if (exitTarget === null) return Promise.resolve()\n return new Promise<void>((resolve) => {\n pendingExitResolvers.push(resolve)\n })\n }\n\n return { setActive, onceExitComplete }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Q4 — a state is considered active if EITHER its own flag is set OR the\n * parent's VariantContext carries a label for it (the parent's gesture is\n * active and propagating). The parent slots are themselves active-gated in\n * `useMotion`'s `myVariantCtx`, so a defined return value here means the\n * parent's gesture really is firing right now.\n *\n * `animate` and `exit` are special — their inheritance happens through the\n * normal label-resolution path in `resolveTarget`, not through the active\n * flag. We treat `animate` as always-active (matches motion's\n * createTypeState(true)). `exit` is driven by the Presence context; the\n * flag-based check is fine.\n */\nfunction isStateActive(\n state: GestureStateName,\n active: ActiveStore,\n parent: VariantContextValue,\n): boolean {\n if (active[state]) return true\n switch (state) {\n case \"whileHover\":\n return parent.hover?.() !== undefined\n case \"whilePress\":\n return parent.press?.() !== undefined\n case \"whileFocus\":\n return parent.focus?.() !== undefined\n case \"whileInView\":\n return parent.inView?.() !== undefined\n // Drag inheritance through context isn't wired in Phase 1's\n // VariantContextValue (no `drag` slot). Commit 6 will revisit if needed.\n case \"whileDrag\":\n return false\n case \"animate\":\n case \"exit\":\n return false\n }\n}\n\n/** Convert a winners map into the flat value snapshot used by `lastApplied`. */\nfunction snapshotValues(winners: Record<string, WinnerEntry>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const key in winners) {\n const entry = winners[key]\n if (entry) out[key] = entry.value\n }\n return out\n}\n\n/**\n * Phase 1's splitTarget: separate MotionValue refs in a target from plain\n * values. Motion-vanilla `animate(el, target)` doesn't subscribe to MV refs\n * passed in target — we handle that bridge ourselves.\n */\nfunction splitTarget(target: Record<string, unknown>): {\n plain: Record<string, unknown>\n motionValues: Array<{ key: string; mv: MotionValue<unknown> }>\n} {\n const plain: Record<string, unknown> = {}\n const motionValues: Array<{ key: string; mv: MotionValue<unknown> }> = []\n for (const key in target) {\n const value = target[key]\n if (value === undefined || value === null) {\n plain[key] = value\n continue\n }\n if (isMotionValue(value)) {\n motionValues.push({ key, mv: value as MotionValue<unknown> })\n plain[key] = (value as MotionValue<unknown>).get()\n } else if (typeof value === \"function\") {\n plain[key] = (value as () => unknown)()\n } else if (Array.isArray(value)) {\n plain[key] = value.map((v) => {\n if (isMotionValue(v)) return (v as MotionValue<unknown>).get()\n if (typeof v === \"function\") return (v as () => unknown)()\n return v\n })\n } else {\n plain[key] = value\n }\n }\n return { plain, motionValues }\n}\n\n/**\n * Return the highest-priority active state that contributed any key in the\n * current winners map. Used to identify the \"driver\" for onAnimationComplete\n * (which receives the AnimateValue that drove the animation).\n *\n * `animate` is the fallback when no gesture is contributing — matches Phase 1's\n * effectiveAnimateValue semantic.\n */\nfunction highestActiveDriverState(winners: Record<string, WinnerEntry>): GestureStateName {\n // Walk PRIORITY_HIGH_TO_LOW and find the first state name that appears.\n for (const stateName of PRIORITY_HIGH_TO_LOW) {\n for (const key in winners) {\n const entry = winners[key]\n if (entry && entry.stateName === stateName) return stateName\n }\n }\n return \"animate\"\n}\n\n/**\n * Look up the AnimateValue (Target | string | string[]) that corresponds to a\n * given state — for onAnimationComplete's argument.\n */\nfunction animateValueForState(\n state: GestureStateName,\n opts: MotionOptions,\n parentVariantCtx: VariantContextValue,\n): AnimateValue | undefined {\n switch (state) {\n case \"animate\":\n return opts.animate ?? parentVariantCtx.animate?.()\n case \"whileHover\":\n return opts.hover ?? parentVariantCtx.hover?.()\n case \"whilePress\":\n return opts.press ?? parentVariantCtx.press?.()\n case \"whileFocus\":\n return opts.focus ?? parentVariantCtx.focus?.()\n case \"whileInView\":\n return opts.inView ?? parentVariantCtx.inView?.()\n case \"exit\":\n return opts.exit ?? parentVariantCtx.exit?.()\n case \"whileDrag\":\n return opts.whileDrag\n }\n}\n\n/**\n * Combine N AnimationPlaybackControls into a single Thenable+stoppable handle.\n *\n * Used by the Stage 3 bridge when an animate dispatch fans out across per-MV\n * `animate(mv, value, opts)` calls (one per routed key) plus an optional\n * single `animate(el, target, opts)` for keys still on the WAA path. The\n * gesture state machine treats `prevControls` as one handle: subsequent diff\n * runs call `.stop()` on it to cancel the in-flight animation, and the exit\n * drain awaits `.then(...)` to settle Presence's `onceExitComplete()` waiters.\n * Aggregating lets both code paths stay uniform whether bridging fired one\n * underlying motion call or six.\n *\n * The other AnimationPlaybackControls methods (pause/play/cancel/complete)\n * fan out unchanged. `time`/`speed`/`duration` aren't aggregated — they're\n * read-rare in our codebase and a meaningful aggregate isn't well-defined\n * across heterogeneous animations.\n */\nfunction aggregateControls(\n controls: readonly AnimationPlaybackControls[],\n): AnimationPlaybackControls {\n // Cache the settle promise so multiple `.then` consumers don't each spawn a\n // fresh Promise.all over the same controls. motion's AnimationPlaybackControls\n // is thenable at runtime (the public type omits `.then`, hence the casts).\n let settled: Promise<unknown[]> | null = null\n const settle = (): Promise<unknown[]> => {\n if (!settled) {\n settled = Promise.all(controls.map((c) => c as unknown as PromiseLike<unknown>))\n }\n return settled\n }\n const forAll = (fn: (c: AnimationPlaybackControls) => void): void => {\n for (const c of controls) fn(c)\n }\n const handle: Record<string, unknown> = {\n stop: () => {\n forAll((c) => c.stop())\n },\n pause: () => {\n forAll((c) => c.pause())\n },\n play: () => {\n forAll((c) => c.play())\n },\n cancel: () => {\n forAll((c) => c.cancel())\n },\n complete: () => {\n forAll((c) => c.complete())\n },\n speed: 1,\n time: 0,\n duration: controls.reduce(\n (acc, c) => Math.max(acc, (c as { duration?: number }).duration ?? 0),\n 0,\n ),\n // biome-ignore lint/suspicious/noThenProperty: structurally mirroring motion's AnimationPlaybackControls, which is intentionally thenable.\n then: (onFulfilled?: unknown, onRejected?: unknown) =>\n settle().then(onFulfilled as never, onRejected as never),\n }\n return handle as unknown as AnimationPlaybackControls\n}\n","import { type MotionValue, motionValue } from \"motion\"\n\n// ---------------------------------------------------------------------------\n// Per-element value registry.\n//\n// One `ValueRegistry` per element managed by `createMotion`. It maps style /\n// transform-shortcut keys (`scale`, `y`, `opacity`, etc.) to the\n// `MotionValue` that authoritatively drives the corresponding CSS or\n// transform component for that element.\n//\n// This is the motion-react `visualElement.values` shape, slimmed down. It\n// exists to unify two write paths that currently disagree about who owns a\n// CSS key on the element:\n//\n// 1. **User-provided MVs in `style`** — `<motion.div style={{ scale: mv }}>`.\n// mv is the source of truth for `scale`; subscribing to it and writing\n// `el.style.transform` is the only way the new value reaches the DOM.\n// 2. **animate-target writes** — `useMotion({ animate: { scale: 1.5 } })`.\n// Today these go directly via WAA (`animate(el, target, opts)`). After\n// Stage 3 they will be routed through the registry: if a key has a\n// registered MV, the animation tweens that MV (which writes the DOM\n// via its subscription) instead of writing the element directly.\n//\n// Stage 1 introduces only the data structure. No code reads from or writes\n// to it yet — `createMotion` instantiates an empty registry, attaches a\n// disposal hook, and stops there. Subsequent stages wire it up.\n//\n// Two ownership classes:\n//\n// - **External** — MVs the user created via `createMotionValue` / motion's\n// `motionValue()` and handed us via `style`. The registry tracks them so\n// we know \"this key is MV-backed\" but does NOT dispose them. The user\n// owns their MV's lifetime.\n//\n// - **Transient** — MVs the registry creates internally (Stage 3) because\n// an animate target referenced a key with no existing MV. The registry\n// owns these and clears them on `dispose()`. motion's MotionValue has no\n// imperative teardown method; releasing references is what lets GC\n// collect them once all subscribers have cleaned up.\n// ---------------------------------------------------------------------------\n\nexport type ValueRegistry = {\n /** Returns the MV registered for `key`, or `undefined` if none. */\n get(key: string): MotionValue<unknown> | undefined\n /** Has any MV been registered for `key`? */\n has(key: string): boolean\n /**\n * Number of entries currently registered. Used by `createMotion` to decide\n * whether the per-element writer can take a specialized single-key path\n * (size === 1) or needs the general-purpose `applyStaticStyle` walk.\n */\n readonly size: number\n /**\n * Register a user-provided MV. The registry will NOT dispose it on\n * teardown. If a transient MV exists for the key, it is replaced (the\n * external MV becomes the new source of truth).\n */\n setExternal(key: string, mv: MotionValue<unknown>): void\n /**\n * Get the MV for `key`, creating a transient one initialized to\n * `fallback` if absent. Transient MVs are disposed on `dispose()`.\n */\n getOrCreateTransient(key: string, fallback: unknown): MotionValue<unknown>\n /** Iterate every (key, MV) pair currently registered. */\n entries(): IterableIterator<[string, MotionValue<unknown>]>\n /**\n * Drop registry-owned (transient) MVs. External MVs are untouched.\n * Subscription cleanups are owned by whoever called `mv.on(...)`; they\n * tie to the surrounding Solid owner via `onCleanup` in Stage 2+ so we\n * don't unsubscribe imperatively here.\n */\n dispose(): void\n}\n\nexport function createValueRegistry(): ValueRegistry {\n const values = new Map<string, MotionValue<unknown>>()\n const transient = new Set<MotionValue<unknown>>()\n\n return {\n get(key) {\n return values.get(key)\n },\n has(key) {\n return values.has(key)\n },\n setExternal(key, mv) {\n const existing = values.get(key)\n if (existing && transient.has(existing)) {\n // Replacing a transient with an external takes the transient out\n // of the owned-set so dispose() doesn't pretend to manage it.\n transient.delete(existing)\n }\n values.set(key, mv)\n },\n getOrCreateTransient(key, fallback) {\n const existing = values.get(key)\n if (existing) return existing\n const mv = motionValue(fallback) as MotionValue<unknown>\n values.set(key, mv)\n transient.add(mv)\n return mv\n },\n entries() {\n return values.entries()\n },\n get size() {\n return values.size\n },\n dispose() {\n transient.clear()\n values.clear()\n },\n }\n}\n","import { animate, type MotionValue } from \"motion\"\nimport { createSignal, onCleanup, untrack } from \"solid-js\"\nimport { useMotionConfig } from \"../motion-config\"\nimport { usePresenceContext } from \"../presence-context\"\nimport { createReducedMotion, shouldReduceMotion } from \"../reduced-motion\"\nimport {\n formatProperty,\n pickTransformFormatter,\n snapshotValue,\n TRANSFORM_KEYS,\n targetToStyle,\n} from \"../style\"\nimport type {\n AnimateValue,\n MotionElement,\n MotionOptions,\n Target,\n Transition,\n VariantContextValue,\n VariantLabels,\n Variants,\n} from \"../types\"\nimport { effectiveLabels, resolveVariant, useVariantContext } from \"../variants\"\nimport { createDrag } from \"./createDrag\"\nimport { createGestures } from \"./createGestures\"\nimport { type ActiveStoreTuple, createGestureStateMachine } from \"./gesture-state\"\nimport { createValueRegistry, type ValueRegistry } from \"./value-registry\"\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Detect whether an animate-value is a variant name (string or string[]) vs.\n * an explicit target object. Returns the labels or undefined.\n */\nexport function asVariantLabels(value: AnimateValue | undefined): VariantLabels | undefined {\n if (value === undefined) return undefined\n if (typeof value === \"string\") return value\n if (Array.isArray(value)) return value\n return undefined\n}\n\n/**\n * Resolve a per-state animate value into a {@link Target}. Implements the\n * Q4 sub-2 priority table:\n *\n * - explicit Target object → use as-is (parent context ignored)\n * - variant name → look up in own variants only (no cascade)\n * - undefined → fall back to parent context's variant name, then look up in\n * own variants\n */\nexport function resolveTarget(\n ownValue: AnimateValue | undefined,\n ownVariants: Variants | undefined,\n parentLabel: VariantLabels | undefined,\n custom: unknown,\n): Target | null {\n // Explicit Target object — variant lookup is skipped entirely.\n if (ownValue !== undefined && typeof ownValue !== \"string\" && !Array.isArray(ownValue)) {\n return ownValue as Target\n }\n\n const labels = effectiveLabels(ownValue, parentLabel)\n if (labels === undefined) return null\n // After the explicit-object check above, `labels` is VariantLabels or a\n // Target that came from `parentLabel` slot — but parent context only\n // propagates labels, never Targets, so it's safe to treat as labels here.\n return resolveVariant(labels as VariantLabels, ownVariants, custom)\n}\n\n/**\n * Merge transition specs in priority order: MotionConfig default <\n * user's `transition` < per-target `transition`. When reduced motion is\n * active, returns `{ duration: 0 }` and drops everything else (Q11 sub-4).\n */\nexport function mergeTransition(\n configDefault: Transition | undefined,\n ownTransition: Transition | undefined,\n perTargetTransition: Transition | undefined,\n reduced: boolean,\n): Transition {\n if (reduced) return { duration: 0 } as Transition\n return {\n ...(configDefault ?? {}),\n ...(ownTransition ?? {}),\n ...(perTargetTransition ?? {}),\n } as Transition\n}\n\n/**\n * Apply a static target to an element's inline style before paint. Used on\n * mount when no SSR style was emitted. The ref callback fires before the\n * browser yields, so this avoids a frame of flicker.\n */\nfunction applyStaticStyle(el: MotionElement, target: Target): void {\n const style = targetToStyle(target)\n for (const key in style) {\n const value = (style as Record<string, string | number | undefined>)[key]\n if (value === undefined) continue\n if (key.startsWith(\"--\")) {\n el.style.setProperty(key, String(value))\n } else {\n // ElementCSSInlineStyle.style is indexable for camelCase property names.\n // Available on both HTMLElement and SVGElement (Phase 4 SVG support).\n ;(el.style as unknown as Record<string, string | number>)[key] = value\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// createMotion — the imperative primitive that drives one element's motion\n// state. useMotion wraps this; <motion.*> and motion() will wrap it too.\n// ---------------------------------------------------------------------------\n\nexport type CreateMotionConfig = {\n /**\n * When true, `createMotion` skips applying the initial style — the server\n * already emitted it inline, and re-applying on hydration would shift the\n * paint. Detected via the `data-motion-hydrated` marker in useMotion.\n */\n initialAppliedBySSR?: boolean\n /**\n * Q4 — useMotion lifts the gesture-state active store one level up so its\n * `myVariantCtx` can read the same flags it propagates to descendants.\n * When omitted (standalone createMotion use), the state machine creates\n * its own internal store.\n */\n activeStore?: ActiveStoreTuple\n /**\n * Q4 follow-up — useMotion passes a shadowed parent context here so the\n * controlling-variants check is applied uniformly. When omitted, createMotion\n * falls back to `useVariantContext()` directly (the standalone path).\n */\n parentContext?: VariantContextValue\n /**\n * MV-in-style Stage 2 — useMotion scrapes `MotionValue`-valued keys out of\n * the user's `style` prop and passes them here. createMotion registers\n * each as an external (user-owned) entry in the value registry and\n * subscribes a writer that re-composes `el.style` from the registry\n * snapshot on every change.\n */\n styleMotionValues?: Map<string, MotionValue<unknown>>\n /**\n * MV-in-style Stage 4 — static transform-shortcut entries in the user's\n * `style` (e.g., `style={{ x: 10, scale: mv }}`'s `x: 10`). useMotion scrapes\n * these alongside MVs so createMotion can seed transient registry entries\n * for them. Without this, the writer would drop the static keys on every\n * recompose since they wouldn't appear in the registry.\n *\n * Map values are the resolved leaf (number or string) — no MVs, no\n * keyframe arrays, no accessor functions. useMotion runs the\n * `snapshotValue` reduction before passing them in.\n */\n styleStaticTransforms?: Map<string, number | string>\n}\n\n/**\n * The imperative primitive: bind an element to a reactive motion-options\n * source. Caller is responsible for keeping the element alive (refs in a\n * component, drag controls, etc.).\n *\n * Phase 1 scope: animate + initial + transition + lifecycle hooks +\n * reduced-motion override + presence registration. Phase 2 layers gesture\n * states (hover/press/focus/inView) and drag on top.\n */\nexport function createMotion(\n el: MotionElement,\n getOpts: () => MotionOptions,\n config?: CreateMotionConfig,\n): void {\n // Q4 follow-up: useMotion passes a shadowed (controlling-aware) context;\n // standalone callers fall back to the live VariantContext.\n const parentVariantCtx: VariantContextValue = config?.parentContext ?? useVariantContext()\n const presence = usePresenceContext()\n const motionConfig = useMotionConfig()\n const systemReducedMotion = createReducedMotion()\n\n // ---------- Per-element value registry (lazy — Stage 4.5) ----------\n // Most elements never need a registry: they have no MV in style, no static\n // transform shortcut in style, and no Stage 3 transient is ever required\n // because the WAA dispatch path stays active throughout. For those elements\n // (the bulk of typical motion usage), allocating an empty registry was pure\n // waste. We now create it on first use via `ensureRegistry()`.\n //\n // No `onCleanup(() => valueRegistry?.dispose())` — `dispose()` was just\n // `transient.clear() + values.clear()`. When createMotion's closure dies,\n // GC reclaims the Map+Set + their MV references; user-provided MVs survive\n // because they have other references; transient MVs that no longer have\n // any subscriber will GC naturally. Calling dispose() explicitly bought\n // nothing.\n let valueRegistry: ValueRegistry | undefined\n const ensureRegistry = (): ValueRegistry => {\n if (!valueRegistry) valueRegistry = createValueRegistry()\n return valueRegistry\n }\n\n // Snapshot once at construction. Subsequent reactivity goes through\n // the createEffect below, so we don't subscribe in the body of this fn.\n const initialOpts = untrack(getOpts)\n\n // ---------- Resolve the initial target (used for BOTH static-style write AND\n // the state machine's removed-key fallback chain, Q7) ----------\n // Priority chain (matches use-motion's computeInitialStyle):\n // own.initial > parent.initial > own.animate > parent.animate\n //\n // We resolve this regardless of `initialAppliedBySSR` because the state\n // machine needs it even when SSR already wrote the inline style — the user's\n // explicit `initial` value is part of their intent and should anchor the\n // removed-key fallback regardless of who painted it.\n let capturedInitialTarget: Target | null = null\n if (initialOpts.initial !== false) {\n const inheritedInitial = parentVariantCtx.initial?.()\n const inheritedAnimate = parentVariantCtx.animate?.()\n const effective =\n initialOpts.initial !== undefined\n ? initialOpts.initial\n : inheritedInitial !== undefined\n ? inheritedInitial\n : initialOpts.animate !== undefined\n ? initialOpts.animate\n : inheritedAnimate\n if (effective !== undefined) {\n capturedInitialTarget = resolveTarget(\n effective,\n initialOpts.variants,\n undefined, // priority chain already consumed parent's labels\n initialOpts.custom ?? parentVariantCtx.custom?.(),\n )\n }\n }\n\n // ---------- Apply the initial style pre-paint, unless SSR already did it ----------\n // An enclosing `<Presence initial={false}>` ALSO suppresses the static\n // style application — the descendant should mount at the animate target,\n // not the initial. Done via the same path as the state machine's\n // `suppressFirstMount` flag below; consistent semantic across both.\n const suppressFirstMount = untrack(() => presence.initial?.()) === false\n if (!config?.initialAppliedBySSR && !suppressFirstMount && capturedInitialTarget) {\n applyStaticStyle(el, capturedInitialTarget)\n }\n\n // ---------- MV-in-style: register external MVs + the registry writer ----------\n // Stage 2/3 of the MV-in-style work. useMotion has scraped `MotionValue` refs\n // out of `style` (e.g., `<motion.div style={{ scale: mv }}>`) and handed\n // them to us in `config.styleMotionValues`. We register each as an external\n // entry in the registry and subscribe a single writer that rebuilds the\n // inline style from a fresh registry snapshot via `applyStaticStyle`.\n //\n // The writer is also subscribed to transient MVs Stage 3's animate bridge\n // creates on demand. Composition cost on each MV change is bounded by\n // registry size — for the common `style: { scale: mv }` case it's a single\n // transform-shortcut walk and one `el.style.transform =` write\n // (bench 04 / bench 08 — ~600 ns per subscriber).\n //\n // Bridge activation rule (Stage 3): the state machine routes animate-target\n // dispatches through the registry ONLY when at least one external MV has\n // been registered. Without a style MV, bridging is inactive and the state\n // machine falls back to the existing `animate(el, target, opts)` WAA path.\n // This keeps the 293 baseline tests on their original code path — their\n // `animateSpy.mock.calls[*][1]` assertions still see a target object.\n // ---------- Specialized writer (Stage 4.5b) ----------\n // `writeFromRegistry` is the subscription target: every MV in the registry\n // is hooked to it via `mv.on(\"change\", writeFromRegistry)`. Internally it\n // dispatches to a `writer` closure that's COMPILED based on the registry's\n // current shape:\n //\n // - 0 entries → noop (the registry is empty; nothing to paint)\n // - 1 entry → SPECIALIZED closure that captures (key, mv) in scope.\n // Per-call cost is just mv.get() → snapshotValue → format →\n // DOM write. No iterator allocations, no TRANSFORM_KEYS\n // lookup, no branching on key shape — the shape is baked\n // into the closure choice.\n // - 2+ ents → `multiKeyWriter`, which walks the registry, composes a\n // Target, and runs the full applyStaticStyle path.\n //\n // The closure is recompiled by `refreshWriter()` whenever the registry's\n // size changes (called from every registration site: Stage 2 styleMV\n // loop, Stage 4 initial-target walk, Stage 4 static-transforms walk, and\n // Stage 3 `getValueForAnimate`'s transient-creation branch).\n //\n // Why this matters at scale: Sierpinski at depth 8 has 6,561 dots × one\n // style MV each = 6,561 calls per scale.set, × 60 Hz = 393k calls/sec.\n // The previous fast path allocated 3 IteratorResults per call → 1.2M\n // allocations/sec of GC pressure. The specialized closure has zero per-\n // call allocations.\n const noop = (): void => {}\n let writer: () => void = noop\n const writeFromRegistry = (): void => writer()\n\n const multiKeyWriter = (): void => {\n if (!valueRegistry) return\n const target: Record<string, unknown> = {}\n for (const [k, mv] of valueRegistry.entries()) {\n target[k] = mv.get()\n }\n if (Object.keys(target).length === 0) return\n applyStaticStyle(el, target as Target)\n }\n\n const compileSingleKeyWriter = (): (() => void) => {\n // Safe: caller guarantees size === 1.\n const [key, mv] = (valueRegistry as ValueRegistry).entries().next().value as [\n string,\n MotionValue<unknown>,\n ]\n if (TRANSFORM_KEYS.has(key)) {\n // Pre-pick the formatter so the per-call hot path skips the\n // transform-key switch entirely. Captured in the closure scope; the\n // switch happens ONCE per element at compile time, never per write.\n const formatter = pickTransformFormatter(key)\n if (formatter !== undefined) {\n return () => {\n const v = snapshotValue(mv.get())\n if (v !== undefined) el.style.transform = formatter(v)\n }\n }\n }\n if (key.startsWith(\"--\")) {\n return () => {\n const v = snapshotValue(mv.get())\n if (v !== undefined) el.style.setProperty(key, String(v))\n }\n }\n return () => {\n const v = snapshotValue(mv.get())\n if (v === undefined) return\n const formatted = formatProperty(key, v)\n ;(el.style as unknown as Record<string, string | number>)[key] = formatted\n }\n }\n\n const refreshWriter = (): void => {\n const size = valueRegistry?.size ?? 0\n if (size === 0) {\n writer = noop\n return\n }\n if (size === 1) {\n writer = compileSingleKeyWriter()\n return\n }\n writer = multiKeyWriter\n }\n // Bridge activates whenever the user supplied ANY registry-owned style\n // entry — an MV in style OR a static transform shortcut. The transform\n // string then becomes the registry-writer's exclusive responsibility,\n // composing from the union of (initial transforms, style MVs, static\n // style transforms, animate-target transients). With NO registry-owned\n // entries, transforms stay on the pre-existing WAA dispatch path.\n let bridgeActive = false\n if (config?.styleMotionValues && config.styleMotionValues.size > 0) {\n const registry = ensureRegistry()\n for (const [key, mv] of config.styleMotionValues) {\n registry.setExternal(key, mv)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n }\n bridgeActive = true\n }\n if (config?.styleStaticTransforms && config.styleStaticTransforms.size > 0) {\n bridgeActive = true\n }\n\n // ---------- Stage 4: register initial + static-style transforms as transients ----------\n // When bridging is active, ALL transform-shortcut keys need to flow through\n // the registry so the writer composes the full transform string. Animate\n // targets get routed via Stage 3's bridge (transients created on demand);\n // style MVs get registered as external in the Stage 2 block above. This block\n // closes the remaining two gaps:\n //\n // (a) Initial transform values (from own.initial / parent.initial /\n // own.animate / parent.animate priority chain). Without these,\n // initial.y=20 + style.scale=mv would compose only `scale(<v>)` —\n // initial.y would be lost when the writer fires.\n //\n // (b) Static transform shortcuts in the user's `style` prop (e.g.,\n // `style={{ x: 10, scale: mv }}`'s `x: 10`). These don't enter via\n // Stage 2's MV scrape; useMotion forwards them in\n // `styleStaticTransforms`. Same fate as (a) if not registered:\n // composeFirstPaintStyle gets them onto the SSR HTML, but the writer\n // wouldn't know about them on subsequent recomposes.\n //\n // Both (a) and (b) seed transients in the registry; the bridge function above\n // returns them on subsequent animate dispatches, and the writer composes\n // them with style MVs into one transform string. Non-transform initial\n // values (opacity, etc.) stay on applyStaticStyle's one-shot path — the\n // writer doesn't touch keys it doesn't own.\n //\n // We snapshot the raw value with `snapshotValue` because initial targets can\n // carry keyframe arrays, MotionValues, or accessor functions; the transient\n // needs a concrete leaf to start from. styleStaticTransforms is already\n // pre-snapshotted by useMotion.\n if (bridgeActive && capturedInitialTarget) {\n const registry = ensureRegistry()\n for (const key in capturedInitialTarget) {\n if (key === \"transition\") continue\n if (!TRANSFORM_KEYS.has(key)) continue\n if (registry.has(key)) continue\n const raw = (capturedInitialTarget as Record<string, unknown>)[key]\n const snapshot = snapshotValue(raw)\n if (snapshot === undefined) continue\n const mv = registry.getOrCreateTransient(key, snapshot)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n }\n }\n if (bridgeActive && config?.styleStaticTransforms) {\n const registry = ensureRegistry()\n for (const [key, value] of config.styleStaticTransforms) {\n // Static style entries WIN over initial on key collision — style is\n // the runtime source of truth for any key it specifies. Replace any\n // transient just seeded from initialTarget with this value's transient.\n const existing = registry.get(key)\n if (existing) {\n existing.set(value)\n } else {\n const mv = registry.getOrCreateTransient(key, value)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n }\n }\n }\n\n // Initial paint from the registry — composes initial transforms + style MVs\n // + static-style transforms into a single transform string. Skipped when\n // nothing is registered.\n if (bridgeActive) {\n // All initial registrations complete; compile the specialized writer\n // based on the final registry size before firing the first paint.\n // Subsequent transient additions (via getValueForAnimate) call\n // refreshWriter themselves.\n refreshWriter()\n writeFromRegistry()\n }\n\n // ---------- Stage 3 bridge function — animate target → registered MV ----------\n // Returns the MV the state machine should animate for `key`:\n // • external (user-provided) MV in registry → return it; animate's tween\n // drives this MV directly, and our writer composes the transform.\n // • registry doesn't have an MV but key is a transform shortcut → create\n // a transient MV initialized to `fallback`, subscribe the writer, return\n // the new MV.\n // • non-transform key with no external MV → return undefined; state machine\n // falls back to WAA.\n // Inactive when no external MV exists — preserves the existing dispatch\n // shape end-to-end for non-MV-in-style users.\n const getValueForAnimate = (key: string, fallback: unknown): MotionValue<unknown> | undefined => {\n if (!bridgeActive) return undefined\n // `bridgeActive=true` implies the registry was ensured by one of the\n // registration blocks above, but TypeScript can't see that correlation.\n // Re-resolve through `ensureRegistry()` — idempotent and free if already\n // created.\n const registry = ensureRegistry()\n const existing = registry.get(key)\n if (existing) return existing\n if (!TRANSFORM_KEYS.has(key)) return undefined\n const mv = registry.getOrCreateTransient(key, fallback)\n onCleanup(mv.on(\"change\", writeFromRegistry))\n // Registry size just grew — recompile the writer so the next paint uses\n // the multi-key path that composes all transforms together. (Transitions\n // 1→2 swap from specialized single-key to multiKeyWriter; 2+→N+1 stays\n // on multiKeyWriter, refreshWriter is then idempotent.)\n refreshWriter()\n return mv\n }\n\n // ---------- Presence-aware enter-readiness gate ----------\n // We detect \"inside a real <Presence>\" by the absence of `registerEnter` on\n // the no-op default context. When we ARE inside one, the element may be\n // off-DOM at the moment the state machine first iterates (the new child\n // during a mode=\"wait\" swap is created before the old child's exit\n // settles, and even the initial child is briefly created off-DOM during\n // appear). Dispatching motion's `animate()` then would run the animation\n // on a disconnected element and silently fail commitStyles — the element\n // would paint at its `initial` target when it finally enters the DOM.\n //\n // Solution: start `enterReady = false` while in a Presence, register a\n // `runEnter` callable that flips it true, and let Presence call it from\n // its `onEnter` / `onChange.added` hook (when transition-group has\n // synchronously inserted the element via `setReturned`). Outside a\n // Presence we leave `enterReady` undefined; the state machine treats\n // absence as ready=true and the existing eager-first-iteration behavior\n // is unchanged.\n const inPresence = presence.registerEnter !== undefined\n const [enterReady, setEnterReady] = createSignal(!inPresence)\n if (inPresence && presence.registerEnter) {\n presence.registerEnter(el, () => setEnterReady(true))\n // Fallback: transition-group's onEnter / onChange.added only fires for\n // elements that are NEW to the source list. The initial children of a\n // `<Presence initial={false}>` (appear=false case) are already in the\n // signal at construction and never trigger an enter callback. We flip\n // readiness from a microtask if the element is connected by then —\n // Solid's synchronous render of `returned()` has run, and any element\n // that was meant to be on screen is in the DOM. For wait-mode swaps\n // where the new child is still off-DOM (the old one's exit is in\n // flight), the `isConnected` check fails and we leave readiness false;\n // Presence will fire beforeMount through onEnter when the exit settles.\n queueMicrotask(() => {\n if (el.isConnected) setEnterReady(true)\n })\n }\n\n // ---------- Gesture state machine (Q3b, ADR 0002) ----------\n // Constructed BEFORE presence registration so the registered `runExit`\n // callable can close over `setActive` + `onceExitComplete`. Owns target\n // resolution, priority winners, and the diff-and-animate loop. Returns\n // `setActive` which gesture wiring uses to toggle active flags, and\n // `onceExitComplete` which Presence awaits during unmount.\n // (For drag's typing constraint, see the createDrag call below.)\n const stateMachine = createGestureStateMachine({\n el,\n getOpts,\n parentVariantCtx,\n motionConfig,\n systemReducedMotion,\n initialTarget: capturedInitialTarget,\n externalActiveStore: config?.activeStore,\n suppressFirstMount,\n enterReady,\n getValueForAnimate,\n })\n const { setActive, onceExitComplete } = stateMachine\n\n // ---------- Presence registration (Phase 3 — inverted shape) ----------\n // Child registers a `runExit` callable that dispatches the exit animate\n // DIRECTLY (bypassing the state-machine effect). Direct dispatch is\n // necessary because by the time Presence's `onExit` callback fires,\n // Solid has already disposed the surrounding owner — the state machine's\n // diff effect is gone. `runExit` therefore captures the exit-relevant\n // options at construction time and uses motion's `animate()` itself.\n //\n // We do NOT call `presence.unregister(el)` on owner cleanup — that would\n // race ahead of Presence's onExit. Instead, Presence/hook unregisters\n // after the exit settles. See ADR 0003 for the timing rationale.\n // Register a runExit for this element if EITHER:\n // (a) it has its own `exit` prop, OR\n // (b) an ancestor's exit label cascades down via VariantContext AND this\n // element has a `variants` map that could resolve against it.\n //\n // (b) is the motion-react canonical orchestration pattern: a parent shell\n // declares `exit: \"closed\"` (a label), wraps children in `m.Provider`, and\n // children are passive consumers — they have ONLY a `variants` map keyed\n // by `\"closed\"` (and other labels). Without (b), the children would never\n // register a runExit and Presence's subtree-walk wouldn't find them; the\n // cascade would work on enter but vanish on exit.\n //\n // The check uses parentVariantCtx.exit?.() which (per use-motion.tsx's\n // `myVariantCtx.exit`) returns the parent's exit prop unconditionally —\n // not gated on the parent's active.exit flag — so this snapshot at\n // construction sees the static cascaded label, not a transient runtime\n // value.\n const inheritedExitLabel = untrack(() => parentVariantCtx.exit?.())\n const hasOwnExit = initialOpts.exit !== undefined\n const hasCascadedExit = inheritedExitLabel !== undefined && initialOpts.variants !== undefined\n\n if (hasOwnExit || hasCascadedExit) {\n const runExit = async (): Promise<void> => {\n // Re-read opts at exit time. The previous design snapshotted them at\n // construction, which broke any pattern where `exit` is reactive — a\n // swipe-card whose exit direction depends on which way the user just\n // flicked, for example, would always exit using the PREVIOUS card's\n // direction (the value that was live when THIS card mounted). We\n // untrack the read because we don't want to subscribe anything that\n // would still be alive after the surrounding owner has been disposed\n // by Solid's `<Show>` / `<For>` swap. The props proxy itself survives\n // disposal — it's just a JS object that the runExit closure keeps\n // referenced — so reading `props.X` here returns the latest value\n // the parent passed in.\n const opts = untrack(getOpts)\n // `resolveTarget` walks own.exit, then the inherited cascade. When\n // neither produces a target there's nothing to animate — return\n // without setActive so we don't hang on the (potentially dead)\n // state machine's onceExitComplete.\n const exitTarget = resolveTarget(\n opts.exit,\n opts.variants,\n asVariantLabels(untrack(() => parentVariantCtx.exit?.())),\n opts.custom ?? parentVariantCtx.custom?.(),\n )\n if (!exitTarget) {\n // Resolved to null (e.g., the user passed a label that doesn't\n // exist in variants). Cooperate with the state machine for cases\n // where the user expects an \"exit\" gesture without specific keys.\n setActive(\"exit\", true)\n await onceExitComplete()\n return\n }\n\n // Merge transition: MotionConfig default < user.transition <\n // exit-target.transition < reduced-motion override.\n const reduced = shouldReduceMotion(motionConfig.reducedMotion(), systemReducedMotion())\n const transition = mergeTransition(\n motionConfig.transition(),\n opts.transition,\n exitTarget.transition,\n reduced,\n )\n\n // Strip `transition` from the target before passing to animate.\n const animTarget: Record<string, unknown> = {}\n for (const k in exitTarget) {\n if (k !== \"transition\") {\n animTarget[k] = (exitTarget as Record<string, unknown>)[k]\n }\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: motion's animate has a complex overloaded shape we can't tighten generically; the runtime call is correct.\n const controls = animate(el, animTarget as any, transition as any)\n // AnimationPlaybackControls is thenable at runtime (motion 12.x).\n // The public type doesn't expose `.then` — narrow via PromiseLike.\n await (controls as unknown as PromiseLike<unknown>)\n }\n\n presence.register(el, runExit)\n // No `onCleanup(() => presence.unregister(el))` — that would fire\n // synchronously when Solid disposes the child's owner, BEFORE\n // transition-group's `onExit` callback runs. Presence/hook calls\n // `unregister` itself after the exit settles. For the no-op default\n // context (no enclosing Presence), `register` is a silent drop —\n // nothing to clean up.\n }\n\n // ---------- Pointer-event gestures (hover, press, focus, inView) ----------\n // Listeners attach unconditionally on mount; the state machine no-ops when\n // an active state has no target.\n createGestures(el, getOpts, setActive)\n\n // ---------- Drag + pan (Q5/C-lean + Q11/D3) ----------\n // createDrag layers on createPan for the pointer session and writes to the\n // element's VisualElement x/y MotionValues during drag. Drag is HTML-only\n // for v0.1 — motion-dom's HTMLVisualElement is HTML-specific. Users who\n // wire `drag` onto an SVG element get a no-op at construction; we could\n // surface a dev warning here later if needed.\n if (el instanceof HTMLElement) {\n createDrag(el, getOpts, setActive)\n }\n}\n\n// Re-export for useMotion to consume the same helpers without circular deps.\nexport { applyStaticStyle }\n","import { mergeRefs } from \"@solid-primitives/refs\"\nimport { isMotionValue, type MotionValue } from \"motion\"\nimport { type Accessor, type Component, type JSX, mergeProps, onMount, untrack } from \"solid-js\"\nimport { createStore } from \"solid-js/store\"\nimport { usePresenceContext } from \"./presence-context\"\nimport { asVariantLabels, createMotion, resolveTarget } from \"./primitives/createMotion\"\nimport type { GestureStateName } from \"./primitives/gesture-state\"\nimport { snapshotValue, TRANSFORM_KEYS, targetToStyle } from \"./style\"\nimport type {\n ElementProps,\n MotionElement,\n MotionMergedProps,\n MotionOptions,\n MotionStyle,\n Target,\n Transition,\n UseMotionResult,\n VariantContextValue,\n Variants,\n} from \"./types\"\nimport { isControllingVariants, useVariantContext, VariantContext } from \"./variants\"\n\n// ---------------------------------------------------------------------------\n// useMotion — the canonical public API. Returns a getter that merges user\n// props with motion's (style, ref, hydration marker) and a Provider for\n// opt-in variant context propagation (Q4 sub-3 Option B).\n// ---------------------------------------------------------------------------\n\n/**\n * Wire motion to an element via a getter function.\n *\n * ```tsx\n * const motion = useMotion({\n * initial: { opacity: 0, y: 20 },\n * animate: { opacity: 1, y: 0 },\n * transition: { duration: 0.6 },\n * })\n *\n * <div {...motion({ class: \"card\" })}>Hello</div>\n * ```\n *\n * **Reactive form**: pass a function to track signals.\n * ```tsx\n * useMotion(() => ({ animate: { x: x() } }))\n * ```\n *\n * **Variant context propagation**: `useMotion` only *consumes* the parent\n * variant context. To propagate to descendants, wrap them in `motion.Provider`:\n * ```tsx\n * const m = useMotion({ animate: \"visible\", variants })\n * <div {...m()}>\n * <m.Provider>\n * <ChildMotion />\n * </m.Provider>\n * </div>\n * ```\n *\n * For the common \"JSX wrapper does propagation automatically\" pattern, use\n * `<motion.div>` (Phase 4).\n */\nexport function useMotion(opts: MotionOptions | (() => MotionOptions)): UseMotionResult {\n const getOpts: () => MotionOptions = typeof opts === \"function\" ? opts : () => opts\n\n // ---------- Parent context (with controlling-variants shadowing) ----------\n // Mirrors motion-dom's isControllingVariants check: when THIS node has any\n // variant *label* prop (initial/animate/hover/press/focus/inView/exit as a\n // string), it opts OUT of inheriting from its parent. The wrapped context's\n // slots return undefined while controlling, so the state machine and the\n // initial-target resolver see no inherited values to fall back on.\n //\n // The wrap is reactive — if opts toggle in/out of controlling state, the\n // slots automatically flip between actual-parent and undefined.\n const actualParentCtx: VariantContextValue = useVariantContext()\n const isControlling = (): boolean => isControllingVariants(getOpts())\n const parentVariantCtx: VariantContextValue = {\n variants: () => (isControlling() ? undefined : actualParentCtx.variants?.()),\n initial: () => (isControlling() ? undefined : actualParentCtx.initial?.()),\n animate: () => (isControlling() ? undefined : actualParentCtx.animate?.()),\n hover: () => (isControlling() ? undefined : actualParentCtx.hover?.()),\n press: () => (isControlling() ? undefined : actualParentCtx.press?.()),\n focus: () => (isControlling() ? undefined : actualParentCtx.focus?.()),\n inView: () => (isControlling() ? undefined : actualParentCtx.inView?.()),\n exit: () => (isControlling() ? undefined : actualParentCtx.exit?.()),\n custom: () => (isControlling() ? undefined : actualParentCtx.custom?.()),\n transition: () => (isControlling() ? undefined : actualParentCtx.transition?.()),\n }\n\n // ---------- Compute the SSR-emittable initial target ----------\n // untrack so reading getOpts() during render doesn't subscribe a Solid\n // computation; the createMotion effect inside motionRef owns reactivity.\n //\n // We also peek at the surrounding `<Presence>` (if any). When `initial`\n // is propagated as `false`, the descendant should mount painted at the\n // animate target — not the initial — because we WANT the visual end state\n // to match a normal post-animation appearance, just without the animation.\n // computeInitialTarget reads `presence.initial` once at construction; the\n // signal flips to true on a microtask, but by then the SSR style has\n // been computed and merged into the JSX props.\n //\n // Stage 4 split: this returns the RAW resolved Target rather than the\n // composed CSS. The style getter below composes initialTarget + style MV\n // snapshots together so SSR HTML and client first paint both reflect the\n // MVs the user supplied. Without this split, SSR HTML carries only the\n // initial target and the MV value lands only after the client's ref fires\n // — producing a brief paint discontinuity.\n const presenceCtx = usePresenceContext()\n const initialOpts = untrack(getOpts)\n const initialTarget = computeInitialTarget(initialOpts, parentVariantCtx, presenceCtx.initial)\n\n // ---------- Active gesture flags (Q4) ----------\n // Lifted from inside the state machine so myVariantCtx below can gate its\n // gesture label slots on these flags. createMotion (via the ref) threads\n // this same store into the state machine so both sides share state.\n const activeStore = createStore<Record<GestureStateName, boolean>>({\n animate: true,\n whileInView: false,\n whileHover: false,\n whilePress: false,\n whileFocus: false,\n whileDrag: false,\n exit: false,\n })\n const [active] = activeStore\n\n // ---------- MV-in-style scrape (Stage 2) ----------\n // Walked once on the first m() call (see `getProps` below) and threaded\n // into createMotion via `styleMotionValues`. The contract (locked in the\n // grill): MV references in `style` are STATIC — captured once, not\n // re-scanned on subsequent m() calls. Users who want a reactive MV swap\n // can't do `style: { scale: cond() ? mvA : mvB }`; they animate the MV's\n // value instead.\n //\n // Why capture in m() and not in motionRef: m()'s call is the only point\n // where the user's `style` prop is observable from useMotion's body.\n // motionRef fires later (after JSX evaluates), at which time we no\n // longer have a handle on userProps.\n // Stage 4.5: lazy-allocate both maps. Most elements have no MV-in-style\n // and no static transform shortcut, so allocating these eagerly per\n // `useMotion` call was pure waste. The `??=` in `captureStyleEntries`\n // creates them only on first add; downstream consumers handle the\n // `undefined` case via optional chaining.\n let styleMotionValues: Map<string, MotionValue<unknown>> | undefined\n let styleStaticTransforms: Map<string, number | string> | undefined\n let styleCaptured = false\n\n // ---------- Build the motion ref ----------\n // Pass the shadowed parent context to createMotion so its state machine\n // and initial-target resolver consume the same controlling-aware view.\n //\n // Stage 4: `initialAppliedBySSR` is now true when EITHER we emitted an\n // initial target into the SSR style OR at least one style MV's snapshot\n // landed in the SSR HTML via the style getter below. createMotion uses\n // this flag to skip its own applyStaticStyle pass — without the\n // styleMotionValues branch it would re-apply only the initialTarget half\n // and clobber the MV-snapshot half that's already in the inline style.\n const motionRef = (el: MotionElement) => {\n createMotion(el, getOpts, {\n initialAppliedBySSR:\n initialTarget !== null ||\n styleMotionValues !== undefined ||\n styleStaticTransforms !== undefined,\n activeStore,\n parentContext: parentVariantCtx,\n styleMotionValues,\n styleStaticTransforms,\n })\n }\n\n // ---------- The getter that merges user props with motion's ----------\n // Built on Solid's `mergeProps` rather than an eager object spread. The\n // returned value is a reactive proxy: reads against any property defer to\n // its source, so reactive non-motion props the user spreads through `m()`\n // (e.g. `<div {...m({ class: signal() ? \"on\" : \"off\" })}>`) keep their\n // reactivity through to the rendered element. The previous spread-based\n // implementation snapshotted userProps at call time, which broke this\n // path for the Phase 4 motion proxy.\n //\n // `initialStyle` is included in the `style` getter ONLY before the\n // first render completes. After onMount fires, motion's WAA owns the\n // animated properties on the element — if we kept layering initialStyle\n // into m()'s reactive output, Solid's style fn (which re-applies every\n // tracked key via setProperty on each render — its first-loop deletes\n // every prev entry, so the second loop's `v !== prev[s]` is always true)\n // would re-write the static initial values back into the inline style on\n // every reactive prop change, clobbering whatever WAA committed. Server-\n // side, onMount never fires, so renderedOnce stays false and initialStyle\n // always reaches the SSR HTML for first-paint correctness. Client first\n // render runs BEFORE the onMount microtask, so initialStyle is also in\n // the JSX for hydration consistency with the SSR HTML.\n //\n // `ref` is computed once and snapshotted — refs are conventionally\n // callbacks set once per mount; re-running mergeRefs on each read is\n // wasted work.\n let renderedOnce = false\n onMount(() => {\n renderedOnce = true\n })\n\n /**\n * Walk `style` once and pull `MotionValue` refs into `styleMotionValues`.\n * Idempotent across re-renders — Stage 2's contract is \"MV refs in style\n * are captured on first call and never re-scraped.\" Subsequent m()\n * invocations that pass a different style with new MVs won't pick them\n * up; that pattern wasn't in scope for v0.1.\n *\n * The read is `untrack`ed because m() is typically called from inside a\n * JSX spread, which Solid evaluates within a tracked owner. Without\n * untrack we'd subscribe to whatever signals the user's `style` object\n * references and re-fire this useMotion's owner-level effects on every\n * change.\n */\n const captureStyleEntries = (style: unknown): void => {\n if (styleCaptured) return\n styleCaptured = true\n if (!style || typeof style !== \"object\") return\n for (const key in style) {\n const value = (style as Record<string, unknown>)[key]\n if (isMotionValue(value)) {\n if (!styleMotionValues) styleMotionValues = new Map()\n styleMotionValues.set(key, value as MotionValue<unknown>)\n } else if (TRANSFORM_KEYS.has(key)) {\n // Static transform shortcut. Stage 4 lands these in the registry as\n // transients so the writer composes them with style MVs and initial\n // transforms into one transform string. Reduce MV/accessor/array\n // wrappers to a leaf — though by this branch we already know it's\n // not an MV. The reduction also rejects boolean/object junk values.\n const snap = snapshotValue(value)\n if (snap !== undefined) {\n if (!styleStaticTransforms) styleStaticTransforms = new Map()\n styleStaticTransforms.set(key, snap)\n }\n }\n }\n }\n\n /**\n * Produce a style object with MV-valued keys (and transform-shortcut keys —\n * see below) removed. Solid's style binding would otherwise either write the\n * MotionValue instance as a literal (coercing it via String() to\n * \"[object Object]\") for MV-valued entries, or apply transform shortcuts\n * directly as bogus CSS properties for static-shortcut entries. createMotion\n * handles both via the registry-write path; we strip them here so the\n * Solid-bound `cleaned` style only contains regular CSS keys.\n */\n const stripStyleEntriesOwnedByRegistry = (style: MotionStyle | undefined): JSX.CSSProperties => {\n if (!style) return {}\n const out: Record<string, unknown> = {}\n for (const key in style) {\n if (styleMotionValues?.has(key)) continue\n if (TRANSFORM_KEYS.has(key)) continue\n out[key] = (style as Record<string, unknown>)[key]\n }\n return out as JSX.CSSProperties\n }\n\n /**\n * Stage 4 — compose the first-paint inline style from:\n * 1. `initialTarget` (resolved via the priority chain at construction)\n * 2. MotionValue snapshots from `style: { key: mv }`\n * 3. Static transform shortcuts in `style: { x: 10, scale: 0.5 }`\n *\n * Style entries (2, 3) override `initialTarget` (1) on the same key because\n * `style` is the runtime source-of-truth for those keys. Returns the composed\n * `JSX.CSSProperties` or null when nothing applies (no initial + no style\n * registry contributions).\n *\n * Called only before `onMount` flips `renderedOnce`. After mount, the\n * registry's writer (in createMotion) owns el.style directly and this\n * function isn't consulted.\n */\n const composeFirstPaintStyle = (userStyle: MotionStyle | undefined): JSX.CSSProperties | null => {\n const merged: Record<string, unknown> = {}\n let hasAny = false\n if (initialTarget) {\n Object.assign(merged, initialTarget)\n hasAny = true\n }\n // MV snapshots from style override initialTarget for the same key.\n if (styleMotionValues) {\n for (const [key, mv] of styleMotionValues) {\n merged[key] = mv.get()\n hasAny = true\n }\n }\n // Static transform shortcuts in style (NOT captured as MVs) override too.\n if (userStyle) {\n for (const key in userStyle) {\n if (styleMotionValues?.has(key)) continue\n if (!TRANSFORM_KEYS.has(key)) continue\n const v = (userStyle as Record<string, unknown>)[key]\n if (typeof v === \"number\" || typeof v === \"string\") {\n merged[key] = v\n hasAny = true\n }\n }\n }\n return hasAny ? targetToStyle(merged as Target) : null\n }\n\n function getProps<P extends ElementProps>(userProps?: P): MotionMergedProps<P> {\n untrack(() => captureStyleEntries(userProps?.style))\n // Decide marker presence at call time. Determining this from\n // `getProps` (rather than recomputing per style-getter read) keeps it\n // a stable attribute key on the mergeProps source object.\n const wroteFirstPaintStyle =\n initialTarget !== null ||\n styleMotionValues !== undefined ||\n styleStaticTransforms !== undefined\n return mergeProps(userProps ?? {}, {\n get style() {\n const cleaned = stripStyleEntriesOwnedByRegistry(userProps?.style)\n if (renderedOnce) return cleaned\n const composed = composeFirstPaintStyle(userProps?.style)\n return composed ? { ...cleaned, ...composed } : cleaned\n },\n ref: mergeRefs(userProps?.ref, motionRef),\n ...(wroteFirstPaintStyle ? { \"data-motion-hydrated\": \"\" } : {}),\n }) as MotionMergedProps<P>\n }\n\n // ---------- Provider for opt-in variant context propagation ----------\n // Accessors recompute on each call so the provided context tracks the live\n // options (variant name changes propagate to descendants).\n //\n // Q4 — gesture slots (hover, press, focus, inView) are ACTIVE-GATED:\n // they return the label only when the corresponding gesture flag is true.\n // When inactive, they return undefined — so descendants' priority chains\n // correctly skip the inherited entry. The non-gesture slots (animate,\n // initial, exit, custom, transition, variants) propagate unconditionally.\n const myVariantCtx: VariantContextValue = {\n variants: () => getOpts().variants,\n // `initial: false` is a parent-only opt-out — don't propagate it. Only\n // variant names (string / string[]) propagate to descendants.\n initial: () => {\n const v = getOpts().initial\n return v === false ? undefined : asVariantLabels(v)\n },\n animate: () => asVariantLabels(getOpts().animate),\n hover: () => (active.whileHover ? asVariantLabels(getOpts().hover) : undefined),\n press: () => (active.whilePress ? asVariantLabels(getOpts().press) : undefined),\n focus: () => (active.whileFocus ? asVariantLabels(getOpts().focus) : undefined),\n inView: () => (active.whileInView ? asVariantLabels(getOpts().inView) : undefined),\n exit: () => asVariantLabels(getOpts().exit),\n custom: () => getOpts().custom,\n transition: () => getOpts().transition,\n }\n\n const Provider: Component<{ children: JSX.Element }> = (props) => (\n <VariantContext.Provider value={myVariantCtx}>{props.children}</VariantContext.Provider>\n )\n\n // Attach Provider to the callable function. Object.assign merges types\n // cleanly for callable-with-properties — TS infers the intersection.\n return Object.assign(getProps, { Provider })\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction computeInitialTarget(\n opts: MotionOptions,\n parentVariantCtx: VariantContextValue,\n presenceInitial?: Accessor<boolean>,\n): Target | null {\n // `<Presence initial={false}>` propagates \"skip the enter animation\" down\n // to every motion descendant. The intent is \"render at the animate target\"\n // — NOT \"render at the initial target with no animation\" (the latter would\n // leave the element looking like it failed to mount). So when the surrounding\n // Presence says \"suppress\", we resolve the animate target as the initial\n // instead of walking the initial chain. The state machine separately skips\n // the first-mount animate dispatch via the same `suppressFirstMount` path.\n if (presenceInitial?.() === false) {\n const animateValue = opts.animate !== undefined ? opts.animate : parentVariantCtx.animate?.()\n if (animateValue === undefined) return null\n return resolveTarget(\n animateValue,\n opts.variants as Variants | undefined,\n undefined,\n opts.custom ?? parentVariantCtx.custom?.(),\n )\n }\n\n if (opts.initial === false) return null\n\n // Priority chain for the initial-state target:\n // own.initial > parent.initial > own.animate > parent.animate\n // Each level is consulted only if the previous is undefined. This matches\n // motion/react's variant-context behavior — children without their own\n // initial/animate props inherit from the ancestor motion element.\n const inheritedInitial = parentVariantCtx.initial?.()\n const inheritedAnimate = parentVariantCtx.animate?.()\n const effective =\n opts.initial !== undefined\n ? opts.initial\n : inheritedInitial !== undefined\n ? inheritedInitial\n : opts.animate !== undefined\n ? opts.animate\n : inheritedAnimate\n if (effective === undefined) return null\n\n return resolveTarget(\n effective,\n opts.variants as Variants | undefined,\n undefined, // priority chain already consumed parent's labels\n opts.custom ?? parentVariantCtx.custom?.(),\n )\n}\n\n// Re-export Transition for downstream consumers that destructure from useMotion's module.\nexport type { Transition }\n","import { mergeRefs } from \"@solid-primitives/refs\"\nimport { type Component, type JSX, mergeProps, onMount, splitProps } from \"solid-js\"\nimport { Dynamic } from \"solid-js/web\"\nimport type { ElementProps, MotionElement, MotionOptions, MotionStyle } from \"./types\"\nimport { useMotion } from \"./use-motion\"\n\n// ---------------------------------------------------------------------------\n// motion proxy — Phase 4.\n//\n// `motion` is a Proxy whose property accesses return cached, memoized\n// tag-components: `motion.div`, `motion.svg`, `motion.path`, etc. Each\n// tag-component:\n//\n// 1. Splits incoming props into motion options (fed to useMotion) and\n// element attributes (forwarded to the underlying element reactively).\n// 2. Wires useMotion in its function form so reactive options propagate\n// through to the gesture state machine.\n// 3. Wraps the rendered element in `m.Provider` UNCONDITIONALLY so a\n// variant cascade reaches every motion descendant — the canonical\n// motion-react ergonomic (B1 in ADR 0004).\n// 4. Renders the actual element through <Dynamic>, which transparently\n// handles SVG-vs-HTML namespace resolution.\n//\n// The HOC entry point (`motion.create`) lands in the follow-up commit. This\n// commit ships only the indexable surface for tag-components.\n// ---------------------------------------------------------------------------\n\n/**\n * The exhaustive list of keys that `motion.X` (and `motion.create`,\n * landing next) route to `useMotion` rather than the underlying element.\n * Anything not in this array falls through to `rest` and is spread onto\n * the DOM element via Solid's reactive spread — keeping things like\n * `class`, `onClick`, dynamic style, etc. reactive end-to-end.\n *\n * The `satisfies` clause ensures every entry IS a valid `MotionOptions`\n * key (typos fail to compile). The `_ensureExhaustive` constant below\n * asserts the converse — every `MotionOptions` key appears in this\n * array — so adding a new option to types.ts without registering here\n * fails to compile with the missing key surfaced in the error.\n */\n/**\n * Union of every `MotionOptions` key the proxy splits off from element\n * attributes. Hardcoded as a literal union — NOT derived from\n * `typeof MOTION_OPT_KEYS[number]` — so JSR's \"slow types\" rule can\n * resolve the public type without inferring it from a const.\n *\n * Two compile-time exhaustiveness directions guarantee consistency\n * between this type and the runtime `MOTION_OPT_KEYS` array:\n *\n * 1. `_MissingMotionOptKeys` (below) verifies the union covers every\n * key in `keyof MotionOptions`.\n * 2. The `satisfies` clause on `MOTION_OPT_KEYS` verifies every array\n * entry IS a `MotionOptKey` (typo-proof at the runtime layer).\n *\n * If `MotionOptions` grows a new key, both `_MissingMotionOptKeys`\n * AND `splitProps` at runtime break — the type check surfaces the\n * specific missing key by name.\n */\nexport type MotionOptKey =\n // Variant slots\n | \"initial\"\n | \"animate\"\n | \"exit\"\n // Gesture targets\n | \"hover\"\n | \"press\"\n | \"focus\"\n | \"inView\"\n | \"inViewOptions\"\n // Drag config\n | \"drag\"\n | \"dragConstraints\"\n | \"dragElastic\"\n | \"dragMomentum\"\n | \"dragTransition\"\n | \"dragSnapToOrigin\"\n | \"dragControls\"\n | \"whileDrag\"\n // Pan\n | \"panThreshold\"\n // Variants + transition\n | \"variants\"\n | \"custom\"\n | \"transition\"\n // Animation lifecycle\n | \"onAnimationStart\"\n | \"onAnimationComplete\"\n | \"onAnimationCancel\"\n | \"onUpdate\"\n // Gesture lifecycle\n | \"onHoverStart\"\n | \"onHoverEnd\"\n | \"onPressStart\"\n | \"onPress\"\n | \"onPressCancel\"\n | \"onFocus\"\n | \"onBlur\"\n | \"onPanStart\"\n | \"onPan\"\n | \"onPanEnd\"\n | \"onViewportEnter\"\n | \"onViewportLeave\"\n // Drag lifecycle\n | \"onDragStart\"\n | \"onDrag\"\n | \"onDragEnd\"\n | \"onDragTransitionEnd\"\n\n/**\n * Frozen list of `MotionOptKey`s — fed to `splitProps` at every\n * tag-component render to separate motion options from element\n * attributes. The `satisfies` clause checks every entry against\n * `MotionOptKey` at compile time so typos / drift between the union\n * and the array surface as errors.\n */\nexport const MOTION_OPT_KEYS: readonly MotionOptKey[] = [\n // Variant slots\n \"initial\",\n \"animate\",\n \"exit\",\n // Gesture targets\n \"hover\",\n \"press\",\n \"focus\",\n \"inView\",\n \"inViewOptions\",\n // Drag config\n \"drag\",\n \"dragConstraints\",\n \"dragElastic\",\n \"dragMomentum\",\n \"dragTransition\",\n \"dragSnapToOrigin\",\n \"dragControls\",\n \"whileDrag\",\n // Pan\n \"panThreshold\",\n // Variants + transition\n \"variants\",\n \"custom\",\n \"transition\",\n // Animation lifecycle\n \"onAnimationStart\",\n \"onAnimationComplete\",\n \"onAnimationCancel\",\n \"onUpdate\",\n // Gesture lifecycle\n \"onHoverStart\",\n \"onHoverEnd\",\n \"onPressStart\",\n \"onPress\",\n \"onPressCancel\",\n \"onFocus\",\n \"onBlur\",\n \"onPanStart\",\n \"onPan\",\n \"onPanEnd\",\n \"onViewportEnter\",\n \"onViewportLeave\",\n // Drag lifecycle\n \"onDragStart\",\n \"onDrag\",\n \"onDragEnd\",\n \"onDragTransitionEnd\",\n] as const satisfies readonly MotionOptKey[]\n\n// Compile-time exhaustiveness check (union → keys direction). If a new\n// MotionOptions key is added without being registered in MotionOptKey,\n// TypeScript surfaces the missing key by name here.\ntype _MissingMotionOptKeys = Exclude<keyof MotionOptions, MotionOptKey>\n// Variable prefixed with `_` so biome's noUnusedVariables exempts it —\n// the const exists purely so TypeScript evaluates its type and surfaces\n// the missing key when the constraint fails.\nconst _ensureExhaustive: [_MissingMotionOptKeys] extends [never]\n ? true\n : { _missing: _MissingMotionOptKeys } = true\n\n/**\n * The shape of the `motion` proxy: every HTML/SVG intrinsic element name\n * maps to a typed `Component` whose props are that element's native\n * attribute set intersected with {@link MotionOptions}.\n *\n * The intersected `{ create: ... }` member adds the HOC entry point. The\n * intersection's explicit `create` field wins over the mapped type's\n * lookup (and there's no HTML/SVG tag named `create`), so `motion.create`\n * is unambiguously typed as the HOC.\n */\nexport type Motion = {\n // Override each intrinsic element's `style` to accept `MotionStyle` (which\n // adds transform shortcuts + MotionValue variants on top of standard CSS).\n // Without this override, `<motion.div style={{ scale: mv }} />` wouldn't\n // typecheck — the intrinsic `style: JSX.CSSProperties` doesn't know about\n // motion's transform-shortcut keys or MV values.\n [Tag in keyof JSX.IntrinsicElements]: Component<\n Omit<JSX.IntrinsicElements[Tag], \"style\"> & { style?: MotionStyle } & MotionOptions\n >\n} & {\n /**\n * Wrap a custom Component with motion's behavior. The wrapped Component\n * must forward props (specifically `ref` and `style`) to a single DOM\n * element root — either by spreading `{...props}` on its root or by\n * explicitly setting `ref={props.ref}` and `style={props.style}`. Solid\n * doesn't have `forwardRef`; the contract is enforced by convention and\n * a dev-mode runtime warning if motion's ref never reaches the DOM.\n *\n * @example\n * ```tsx\n * function MyCard(props) {\n * return <div {...props}>{props.children}</div>\n * }\n * const Animated = motion.create(MyCard)\n * <Animated animate={{ x: 100 }} hover={{ scale: 1.05 }} class=\"card\" />\n * ```\n */\n // biome-ignore lint/suspicious/noExplicitAny: Solid's Component<P> requires P extends Record<string, any>\n create: <P extends Record<string, any>>(Component: Component<P>) => Component<P & MotionOptions>\n}\n\n// Module-level cache. `motion.div` returns the SAME component instance\n// across reads, which (a) lets Solid's reconciler skip redundant work and\n// (b) keeps component identity stable for HMR + dev tooling.\n// Solid's `Component<P>` is constrained to `P extends Record<string, any>`,\n// so we use `any` here. The Motion type narrows the per-tag prop shape at\n// the call site (motion.div has DivProps & MotionOptions); this storage\n// uniformity is purely internal.\n// biome-ignore lint/suspicious/noExplicitAny: Component<P> requires P extends Record<string, any>\ntype AnyComponent = Component<any>\n\nconst tagComponentCache = new Map<string, AnyComponent>()\n\n// WeakSet of every component the proxy has manufactured (tag-components AND\n// HOC-wrapped components). Used for the dev-mode `motion.create(motion.X)`\n// double-wrap warning. WeakSet so HMR-replaced components don't pin their\n// predecessors alive.\nconst motionComponents = new WeakSet<object>()\n\nfunction makeMotionTag(tag: string): AnyComponent {\n const cached = tagComponentCache.get(tag)\n if (cached) return cached\n\n const Tag: Component<ElementProps & MotionOptions> = (props) => {\n const [motionOpts, rest] = splitProps(props, MOTION_OPT_KEYS)\n const m = useMotion(() => motionOpts)\n return (\n <m.Provider>\n <Dynamic component={tag} {...m(rest as ElementProps)} />\n </m.Provider>\n )\n }\n const stored = Tag as AnyComponent\n tagComponentCache.set(tag, stored)\n motionComponents.add(stored)\n return stored\n}\n\n/**\n * `motion.create(Component)` — wraps a custom Component with motion's\n * behavior. The wrapped Component must forward props to a single DOM\n * element root; the contract is documented in the {@link Motion.create}\n * JSDoc above and enforced at runtime (in dev mode) by detecting whether\n * motion's ref ever reaches the DOM after mount.\n */\n// biome-ignore lint/suspicious/noExplicitAny: matches Motion.create's generic constraint\nfunction motionCreate<P extends Record<string, any>>(\n Component: Component<P>,\n): Component<P & MotionOptions> {\n // Dev-mode `motion.create(motion.X)` warning. Double-wrapping puts two\n // motion state machines on the SAME root element — both register with\n // Presence, both dispatch animate() writes, and the resulting writes\n // race. Users almost always meant to compose options at one layer.\n if (\n process.env.NODE_ENV !== \"production\" &&\n motionComponents.has(Component as unknown as object)\n ) {\n console.warn(\n \"[solidjs-motion] motion.create(motion.X) double-wraps the same element \" +\n \"with two motion state machines. Compose options on a single layer instead.\",\n )\n }\n\n const Wrapped: Component<P & MotionOptions> = (props) => {\n const [motionOpts, rest] = splitProps(\n props as unknown as Record<string, unknown>,\n MOTION_OPT_KEYS,\n )\n const m = useMotion(() => motionOpts as MotionOptions)\n\n // Dev-mode wrap-validity check (Q7 in the design grill / future ADR\n // 0004): the wrapped Component must forward props.ref to a DOM\n // element so motion's animations and exit registration can actually\n // wire up. We can't enforce this at the type level in Solid (refs\n // are conventionally optional, indistinguishable from \"missing\"), so\n // we detect at runtime by riding a sentinel through the user-ref\n // slot. `m()`'s internal mergeRefs combines this sentinel with\n // motion's own ref — both fire together when the wrapped Component\n // forwards props.ref to a DOM element. If neither fires after the\n // mount cycle, the wrap is broken.\n //\n // The sentinel-merged ref is computed eagerly (not as a getter) so\n // Solid's spread equality check doesn't churn — refs are stable\n // callbacks set once per mount.\n let refFired = false\n const detector = (_el: MotionElement) => {\n refFired = true\n }\n const userRef = (rest as { ref?: ((el: MotionElement) => void) | MotionElement }).ref\n const mergedUserRef =\n process.env.NODE_ENV !== \"production\"\n ? mergeRefs(userRef as ((el: MotionElement) => void) | undefined, detector)\n : userRef\n const restWithDetector =\n process.env.NODE_ENV !== \"production\" ? mergeProps(rest, { ref: mergedUserRef }) : rest\n\n if (process.env.NODE_ENV !== \"production\") {\n onMount(() => {\n // Defer one microtask so any synchronous-but-deep ref chain has\n // had a chance to fire. Solid's createRenderEffect runs refs\n // during the synchronous mount, but the Component might wrap\n // its DOM root in another <Show>-like deferral.\n queueMicrotask(() => {\n if (!refFired) {\n console.warn(\n \"[solidjs-motion] motion.create wrapped a Component whose root \" +\n \"didn't receive motion's ref. The wrapped Component must \" +\n \"either spread {...props} on a single DOM element OR \" +\n \"explicitly forward `props.ref` to its root. Motion's \" +\n \"animations and exit registration won't run until this \" +\n \"is fixed.\",\n )\n }\n })\n })\n }\n\n return (\n <m.Provider>\n <Component {...(m(restWithDetector as ElementProps) as unknown as P)} />\n </m.Provider>\n )\n }\n motionComponents.add(Wrapped)\n return Wrapped\n}\n\n/**\n * `motion` — the indexable proxy. Every property access returns a cached\n * motion-aware component for the given HTML/SVG tag. The reserved\n * `motion.create` key returns the HOC entry point.\n *\n * @example HTML element\n * ```tsx\n * <motion.div animate={{ x: 100 }} hover={{ scale: 1.05 }}>\n * draggable card\n * </motion.div>\n * ```\n *\n * @example SVG element (handled transparently via <Dynamic>)\n * ```tsx\n * <motion.path d=\"M0 0 L100 100\" animate={{ pathLength: 1 }} />\n * ```\n *\n * @example Wrapping a custom Component via the HOC\n * ```tsx\n * const Animated = motion.create(MyCard)\n * <Animated animate={{ scale: 1.05 }} class=\"my-card\" />\n * ```\n *\n * Non-string keys (Symbols, well-known properties) return `undefined` so\n * debugging tools and `typeof` checks see a sane shape.\n */\nexport const motion: Motion = new Proxy({} as Motion, {\n get(_target, key) {\n if (typeof key !== \"string\") return undefined\n if (key === \"create\") return motionCreate\n return makeMotionTag(key) as never\n },\n}) as Motion\n","import { resolveElements } from \"@solid-primitives/refs\"\nimport { createListTransition, createSwitchTransition } from \"@solid-primitives/transition-group\"\nimport {\n type Component,\n createEffect,\n createMemo,\n createSignal,\n type JSX,\n Match,\n onCleanup,\n Switch,\n} from \"solid-js\"\nimport { PresenceContext } from \"./presence-context\"\nimport type { MotionElement, PresenceContextValue } from \"./types\"\n\n// ---------------------------------------------------------------------------\n// <Presence> — exit-animation coordinator for motion children.\n//\n// Architecture (see ADR 0003):\n// - Wraps a conditional JSX subtree (typically `<Show>`, `<For>`, or\n// `<Index>` containing `<motion.*>` elements with `exit` declared).\n// - Resolves children via @solid-primitives/refs (`resolveFirst` /\n// `resolveElements`), then routes them through\n// @solid-primitives/transition-group's `createSwitchTransition` (single)\n// or `createListTransition` (list) which keeps exiting elements in the\n// DOM until we explicitly call `done()`.\n// - Each motion child registers a `runExit` callable via PresenceContext\n// when its `createMotion` runs. The callable flips the state machine's\n// `exit` slot and resolves when the resulting animate settles.\n// - On removal, transition-group calls our `onExit(el, done)`. We look up\n// the registered `runExit` and chain `done` onto its promise. If no\n// `runExit` is registered (a non-motion child, or a motion child with no\n// `exit` prop), `done()` fires immediately and the element disappears.\n//\n// SSR: same JSX shape as client (Provider + PresenceCore + Switch/Match).\n// transition-group's helpers are SSR-safe — they pass children through when\n// no DOM refs have fired — so structural divergence (which would break\n// Solid's hydration marker alignment) is avoided. Each child's initial\n// style is still emitted via the existing `useMotion` SSR contract.\n//\n// Single-vs-list dispatch is decided at first resolution and stable for the\n// Presence instance's lifetime — switching mid-life would require torn-down\n// transition-group state, which neither helper supports. Document the\n// constraint (rare in practice; conditional rendering rarely flips between\n// \"one item\" and \"many items\" without unmount).\n// ---------------------------------------------------------------------------\n\n/**\n * Internal helper: maps the public `mode` prop to the value\n * `createSwitchTransition` expects. `popLayout` is intentionally deferred\n * (layout animations are v0.2+); `wait` maps to `out-in`; `sync` is the\n * default and corresponds to transition-group's `parallel`.\n */\nfunction switchMode(mode: PresenceProps[\"mode\"]): \"out-in\" | \"parallel\" {\n return mode === \"wait\" ? \"out-in\" : \"parallel\"\n}\n\n/**\n * Find every motion child registered under `root` (or root itself) and\n * return their [element, runExit] pairs. Walks the `runExits` map and\n * tests containment via `Node.contains`, which is O(depth) per check —\n * cheap because n is bounded by the number of motion children Presence\n * is tracking. Order isn't load-bearing; callers Promise.all the runExits.\n */\nfunction collectSubtreeExits(\n root: MotionElement,\n runExits: Map<MotionElement, () => Promise<void>>,\n): Array<[MotionElement, () => Promise<void>]> {\n const out: Array<[MotionElement, () => Promise<void>]> = []\n for (const [el, fn] of runExits) {\n if (el === root || root.contains(el)) out.push([el, fn])\n }\n return out\n}\n\nexport type PresenceProps = {\n /**\n * Exit/enter coordination.\n * - `\"sync\"` (default) — exit and enter overlap (transition-group's\n * `parallel`). Best for list animations and independent items.\n * - `\"wait\"` — old child fully exits before the new one enters\n * (transition-group's `out-in`). Single-child only; ignored (with a\n * dev-mode warning) when wrapping a list.\n */\n mode?: \"sync\" | \"wait\"\n /**\n * Animate children on first mount. Defaults to `true` (matches motion-\n * react). Set `false` to suppress the entry animation for the very first\n * child(ren); subsequent mounts mid-life still animate.\n */\n initial?: boolean\n /**\n * List-path only — controls what transition-group does with an exiting\n * element while its `exit` animation is playing. Forwarded directly to\n * `@solid-primitives/transition-group`'s `createListTransition`.\n *\n * - `\"move-to-end\"` (default) — the exiting element is appended to the\n * end of the rendered array so its DOM position changes during exit.\n * Fine for grids/cascades; surprising for vertically-stacked toasts\n * because surviving siblings JUMP up while the dismissed item is\n * still fading out below them.\n * - `\"keep-index\"` — the exiting element stays at its original index\n * until exit completes. Surviving siblings don't reflow until the\n * slot is released. Best default for notification stacks.\n * - `\"remove\"` — no exit transition; the element is gone from the\n * rendered array immediately. Useful when the exit is purely visual\n * on the child (e.g., it self-animates via opacity transitions\n * instead of `exit`).\n */\n exitMethod?: \"move-to-end\" | \"keep-index\" | \"remove\"\n children: JSX.Element\n}\n\n/**\n * Wraps a conditional or iterated JSX subtree and runs the descendants'\n * `exit` targets before they unmount. Matches motion-react's\n * `<AnimatePresence>` shape but with Solid's `<Show>` / `<For>` /\n * `<Index>` patterns instead of conditional children.\n *\n * Nested motion children are first-class: when an ancestor unmounts,\n * Presence walks the subtree from each resolved child and fires every\n * registered `runExit` it finds in parallel — including motion children\n * nested inside plain wrappers, or descendants whose `exit` label was\n * cascaded down via `m.Provider`. Each motion descendant animates with\n * its own variant/target; transition-group only releases the DOM once\n * the combined `Promise.all` settles. Mirrors motion-react's behavior\n * where a `<motion.div exit={...}>` inside an `<AnimatePresence>` boundary\n * animates correctly regardless of depth.\n *\n * @example Single (conditional unmount)\n * <Presence>\n * <Show when={open()}>\n * <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>\n * saved\n * </motion.div>\n * </Show>\n * </Presence>\n *\n * @example List (items entering and exiting independently)\n * <Presence>\n * <For each={items()}>\n * {(item) => (\n * <motion.li exit={{ opacity: 0, x: 20 }}>{item.text}</motion.li>\n * )}\n * </For>\n * </Presence>\n */\nexport const Presence: Component<PresenceProps> = (props) => {\n // SSR: render the SAME JSX shape as the client (Provider + PresenceCore +\n // <Switch>+<Match>) so Solid's hydration markers align. The transition-\n // group helpers ARE SSR-safe — they return the source elements unchanged\n // when no DOM refs have fired (i.e. during renderToString) — so calling\n // them server-side is harmless and avoids the structural divergence that\n // would otherwise produce hydration mismatches.\n //\n // The only server-time wrinkle is `<Presence initial={false}>`:\n // useMotion's first-paint composition reads `PresenceContext.initial`\n // and, when false, emits the ANIMATE target style instead of the\n // initial. We honor that by setting the signal's seed value below.\n //\n // ---------- PresenceContext value supplied to descendants ----------\n const runExits = new Map<MotionElement, () => Promise<void>>()\n // Enter callbacks — symmetric to runExits. createMotion registers a\n // `runEnter` when it's inside this Presence; we fire it the moment the\n // element is actually inserted into the DOM (from transition-group's\n // onEnter / onChange.added). One-shot — deleted after firing so we don't\n // re-trigger the enter animate on subsequent renders.\n const runEnters = new Map<MotionElement, () => void>()\n // `initial` is read at construction. We flip it to `true` after the first\n // microtask so mid-life inserts DO animate even if the user set\n // `initial={false}`. Matches motion-react's behavior.\n const [presenceInitial, setPresenceInitial] = createSignal(props.initial ?? true)\n queueMicrotask(() => setPresenceInitial(true))\n\n const ctx: PresenceContextValue = {\n register: (el, runExit) => {\n runExits.set(el, runExit)\n },\n unregister: (el) => {\n runExits.delete(el)\n },\n beforeUnmount: (el) => {\n // Walk the subtree rooted at `el` and fire every registered runExit\n // we find — the root's own (if registered) plus every descendant\n // that's a motion child. They all run concurrently; we await the\n // combined Promise.all so transition-group only releases the DOM\n // once every motion descendant has finished its exit, then prune\n // the entries from the registry.\n //\n // This is the mechanism that makes motion-react's parent-cascade\n // exit pattern work for us: when an ancestor unmounts, each nested\n // motion child still runs its OWN exit (its runExit closure already\n // captures the element, `getOpts`, and the state-machine handles,\n // so it doesn't matter that Solid has disposed the surrounding\n // owner). Callers don't need to unregister individually — this\n // method finishes the bookkeeping for the whole subtree.\n const exiting = collectSubtreeExits(el, runExits)\n if (exiting.length === 0) return Promise.resolve()\n return Promise.all(exiting.map((pair) => pair[1]())).then(() => {\n for (const [exitedEl] of exiting) runExits.delete(exitedEl)\n })\n },\n registerEnter: (el, runEnter) => {\n runEnters.set(el, runEnter)\n },\n beforeMount: (el) => {\n const fn = runEnters.get(el)\n runEnters.delete(el)\n fn?.()\n },\n initial: presenceInitial,\n }\n\n // CRITICAL — the children-resolution dance lives INSIDE the Provider's\n // JSX scope so that:\n // (a) motion descendants' refs fire under the Provider's owner and\n // `usePresenceContext` resolves to our `ctx` (not the no-op).\n // (b) resolveElements is called from a stable, single-execution scope.\n // solid-motionone's Presence (1.0.4) achieves this by inlining the\n // transition-group call as the Provider's only child; we extend\n // that to two paths by routing through a tiny `PresenceCore`\n // subcomponent so the resolveElements memo isn't recreated.\n return (\n <PresenceContext.Provider value={ctx}>\n <PresenceCore\n source={() => props.children}\n mode={props.mode}\n exitMethod={props.exitMethod}\n appear={presenceInitial}\n ctx={ctx}\n />\n </PresenceContext.Provider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Internal subcomponent that owns the transition-group machinery. Running\n// the resolution + transition-group setup inside a Solid component (rather\n// than inline JSX or an IIFE) gives us a clean single-execution scope: the\n// component's body runs ONCE per <Presence> instance, the resolveElements\n// memo is set up ONCE, and the transition's createComputed is owned by this\n// component's lifetime. The Provider's value still flows down because this\n// component is rendered AS A CHILD of the Provider.\n// ---------------------------------------------------------------------------\ntype PresenceCoreProps = {\n source: () => JSX.Element\n mode: PresenceProps[\"mode\"]\n exitMethod: PresenceProps[\"exitMethod\"]\n appear: () => boolean\n ctx: PresenceContextValue\n}\n\nconst PresenceCore: Component<PresenceCoreProps> = (p) => {\n // One resolveElements call — both paths read from it. Calling it twice\n // (e.g. resolveFirst + resolveElements) would create two children-\n // resolution memos and mount the motion descendants twice.\n const resolved = resolveElements(p.source)\n\n // Sticky single-vs-list decision — DEFERRED until the source resolves\n // to actual data. The earlier \"decide at construction\" approach silently\n // broke any `<For>` that started empty: `Array.isArray(null)` is false,\n // so we'd lock into switch mode and drop every list item past the first.\n // Using a memo with a self-prev short-circuit makes the decision sticky\n // once a non-null value arrives, while still reacting to the first\n // populated read whenever that happens.\n const path = createMemo<\"switch\" | \"list\" | null>((prev) => {\n if (prev) return prev\n const v = resolved()\n if (v == null) return null\n return Array.isArray(v) ? \"list\" : \"switch\"\n })\n\n if (process.env.NODE_ENV !== \"production\") {\n createEffect(() => {\n if (path() === \"list\" && p.mode === \"wait\") {\n console.warn(\n '[solidjs-motion] <Presence mode=\"wait\"> has no meaningful effect with a list of children — \"wait\" sequences a single exiting element before a single entering one. Use it with `<Show>`-style conditional rendering.',\n )\n }\n })\n }\n\n // transition-group's helpers return Accessor<Element[]>. Solid renders\n // accessor functions inline (calls them in a tracking scope), but TS\n // sees Accessor, not JSX.Element. The cast is a no-op at runtime.\n //\n // <Switch> + keyed <Match> renders nothing until the path is decided\n // (the children render as null when both Match `when`s are false). The\n // child function form on Match guarantees the create*Transition call\n // happens AT MOST ONCE, on the branch that wins — both paths can't be\n // set up against the same resolveElements memo.\n return (\n <Switch>\n <Match when={path() === \"switch\"} keyed>\n {(_v) =>\n createSwitchTransition(\n () => {\n const v = resolved()\n return Array.isArray(v) ? (v[0] ?? null) : v\n },\n {\n appear: p.appear(),\n mode: switchMode(p.mode),\n onExit(el, done) {\n // Disable pointer events on the exiting element. In sync\n // mode transition-group keeps the old node in the DOM as\n // a sibling of the new one (with the old one LATER in\n // source order, putting it on top in z-stacking). Without\n // this, the exiting node — even at opacity:0 mid-exit —\n // intercepts pointer events intended for the incoming\n // card, breaking drag and hover on the new element until\n // the exit settles.\n const motionEl = el as MotionElement\n if (motionEl instanceof HTMLElement || motionEl instanceof SVGElement) {\n ;(motionEl.style as CSSStyleDeclaration).pointerEvents = \"none\"\n }\n // beforeUnmount walks the subtree, fires every descendant\n // motion child's runExit in parallel, awaits the combined\n // Promise.all, AND prunes the registry. We just chain\n // done() onto it.\n p.ctx.beforeUnmount(motionEl).then(done)\n },\n onEnter(el, done) {\n // The element was just inserted into the DOM via\n // setReturned (transition-group's createSwitchTransition\n // does this synchronously before invoking onEnter). Fire\n // the child's registered runEnter callback so its state\n // machine can dispatch the first animate against a\n // connected element — without this step, motion's\n // `animate()` would have already completed off-DOM during\n // the surrounding exit (or before the appear-driven\n // insertion). Then unblock transition-group.\n p.ctx.beforeMount?.(el as MotionElement)\n done()\n },\n },\n ) as unknown as JSX.Element\n }\n </Match>\n <Match when={path() === \"list\"} keyed>\n {(_v) =>\n createListTransition(() => resolved.toArray(), {\n appear: p.appear(),\n exitMethod: p.exitMethod,\n onChange({ added, removed, finishRemoved }) {\n // Fire enter callbacks for added elements first —\n // createListTransition has already updated the source array\n // (and Solid's render diff has inserted the new nodes)\n // before `onChange` runs, so this is the analogue of the\n // switch path's onEnter timing. Without it the new motion\n // children's first animate would have dispatched off-DOM at\n // template instantiation and lost their commitStyles.\n for (const el of added) {\n p.ctx.beforeMount?.(el as MotionElement)\n }\n if (removed.length === 0) return\n // Disable pointer events on every exiting node (see\n // switch-path onExit for the rationale — same z-stacking\n // trap applies when a removed list item lingers as a\n // sibling of new/unchanged ones).\n for (const el of removed as MotionElement[]) {\n if (el instanceof HTMLElement || el instanceof SVGElement) {\n ;(el.style as CSSStyleDeclaration).pointerEvents = \"none\"\n }\n }\n // beforeUnmount handles the subtree walk + unregister\n // bookkeeping per root.\n Promise.all((removed as MotionElement[]).map((el) => p.ctx.beforeUnmount(el))).then(\n () => finishRemoved(removed),\n )\n },\n }) as unknown as JSX.Element\n }\n </Match>\n </Switch>\n )\n}\n\n// ---------------------------------------------------------------------------\n// useAnimatePresence — imperative hook variant for library authors.\n//\n// Returns `{ Provider, exit }`. The user wraps their own conditional\n// rendering in the returned Provider and calls `exit()` to trigger exit\n// animations on every motion child currently registered. Resolves when all\n// settle.\n//\n// Use this when:\n// - You're a library author whose internal mount state can't be a Solid\n// `<Show>` (e.g., route transitions controlled by an external state\n// machine; toast queues with non-Solid lifecycle).\n// - You need imperative control over WHEN exits trigger (e.g., await\n// network completion before unmounting).\n//\n// For 95% of application code, prefer `<Presence>` — it handles the\n// children-resolver dance and list semantics automatically.\n// ---------------------------------------------------------------------------\n\nexport type UseAnimatePresenceOptions = {\n /** Same semantics as `<Presence initial>`. Defaults to `true`. */\n initial?: boolean\n}\n\nexport type UseAnimatePresenceResult = {\n /**\n * Provider component to wrap your conditional rendering. Every motion\n * descendant inside this Provider registers with the hook's internal\n * registry and is reachable via `exit()`.\n */\n Provider: Component<{ children: JSX.Element }>\n /**\n * Trigger exit on every motion child currently registered with this\n * hook. Resolves when all exit animations have settled. Calling `exit()`\n * does NOT unmount anything — the caller is responsible for flipping\n * their mount signal once the promise resolves.\n */\n exit: () => Promise<void>\n}\n\nexport function useAnimatePresence(options?: UseAnimatePresenceOptions): UseAnimatePresenceResult {\n const runExits = new Map<MotionElement, () => Promise<void>>()\n const [presenceInitial, setPresenceInitial] = createSignal(options?.initial ?? true)\n // Flip to true after the first microtask so mid-life mounts always animate,\n // regardless of the initial setting.\n queueMicrotask(() => setPresenceInitial(true))\n\n const ctx: PresenceContextValue = {\n register: (el, runExit) => {\n runExits.set(el, runExit)\n },\n unregister: (el) => {\n runExits.delete(el)\n },\n beforeUnmount: (el) => {\n // Mirrors `<Presence>`'s subtree-walk semantics (see its\n // beforeUnmount JSDoc). The hook's own `exit()` API instead\n // iterates the full registry directly — but anyone who hands\n // this ctx to a transition-coordinator that calls `beforeUnmount`\n // gets the same descendant-cascade behavior.\n const exiting = collectSubtreeExits(el, runExits)\n if (exiting.length === 0) return Promise.resolve()\n return Promise.all(exiting.map((pair) => pair[1]())).then(() => {\n for (const [exitedEl] of exiting) runExits.delete(exitedEl)\n })\n },\n initial: presenceInitial,\n }\n\n // Free the registry on owner disposal. Motion children deliberately do NOT\n // unregister in their own onCleanup (see ADR 0003 — that would race ahead\n // of the exit window), so when the hook's owner unmounts without ever\n // calling exit(), this is the only path that drops the entries.\n onCleanup(() => runExits.clear())\n\n const Provider: Component<{ children: JSX.Element }> = (p) => (\n <PresenceContext.Provider value={ctx}>{p.children}</PresenceContext.Provider>\n )\n\n const exit = async (): Promise<void> => {\n // Snapshot the registry at call time so concurrent registrations during\n // the await don't get added to this batch.\n const snapshot = [...runExits.values()]\n await Promise.all(snapshot.map((fn) => fn()))\n }\n\n return { Provider, exit }\n}\n","import { scroll as motionScroll } from \"motion\"\nimport { createEffect, onCleanup } from \"solid-js\"\nimport type { MotionValueAccessor } from \"../types\"\nimport { createMotionValue } from \"./motion-value\"\n\n// ---------------------------------------------------------------------------\n// Scroll progress info — motion's `OnScrollWithInfo` callback receives this\n// shape per scroll tick. Sticking to the small subset we wire into our\n// MotionValues to keep our public types narrow.\n// ---------------------------------------------------------------------------\n\ntype ScrollAxisInfo = {\n current: number\n progress: number\n}\n\ntype MotionScrollInfo = {\n x: ScrollAxisInfo\n y: ScrollAxisInfo\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: motion's offset format is internal; we re-expose it as opaque\ntype ScrollOffset = any[]\n\nexport type CreateScrollOptions = {\n /** Accessor returning the scroll container element. Defaults to window. */\n container?: () => Element | null\n /** Accessor returning the scroll target. Defaults to the container itself. */\n target?: () => Element | null\n /** Primary scroll axis (both axes are still populated regardless). */\n axis?: \"x\" | \"y\"\n /** Intersection offsets controlling when progress reaches 0/1. */\n offset?: ScrollOffset\n}\n\nexport type CreateScrollResult = {\n /** Current scroll-x position in px. Callable: `scrollX()` for reactive read. */\n scrollX: MotionValueAccessor<number>\n /** Current scroll-y position in px. Callable: `scrollY()` for reactive read. */\n scrollY: MotionValueAccessor<number>\n /** Normalized scroll-x progress in `[0, 1]` (or `[0, n]` for multi-offset). */\n scrollXProgress: MotionValueAccessor<number>\n /** Normalized scroll-y progress in `[0, 1]`. */\n scrollYProgress: MotionValueAccessor<number>\n}\n\n/**\n * Bind four {@link MotionValueAccessor}s to a scroll source. Mirrors\n * motion/react's `useScroll`; defaults to the window when no container is\n * supplied. Each returned value is callable as a Solid Accessor AND has the\n * full MotionValue surface, so it composes with `useMotion`'s target,\n * `animate()`, `createTransform`, and direct JSX reactivity.\n *\n * @example\n * const { scrollY, scrollYProgress } = createScroll()\n * const opacity = createTransform(scrollYProgress, [0, 1], [1, 0])\n *\n * @example\n * const [el, setEl] = createSignal<HTMLElement>()\n * const { scrollY } = createScroll({ container: el })\n * <div ref={setEl} style={{ overflow: \"auto\" }}>...</div>\n */\nexport function createScroll(options?: CreateScrollOptions): CreateScrollResult {\n const scrollX = createMotionValue(0)\n const scrollY = createMotionValue(0)\n const scrollXProgress = createMotionValue(0)\n const scrollYProgress = createMotionValue(0)\n\n // motion's scroll callback signature has two forms (OnScrollProgress and\n // OnScrollWithInfo). With two parameters, info is passed.\n const handler = (_progress: number, info?: MotionScrollInfo) => {\n if (!info) return\n scrollX.set(info.x.current)\n scrollY.set(info.y.current)\n scrollXProgress.set(info.x.progress)\n scrollYProgress.set(info.y.progress)\n }\n\n // createEffect — Solid-idiomatic for side-effect setup (attaching the\n // motion scroll subscription). First iteration runs in the next\n // microtask, which is harmless: scroll events can't fire before the\n // microtask flushes after mount. Accessors inside the body (container,\n // target) are tracked — re-init happens when refs change.\n //\n // Each iteration's onCleanup is scoped to that iteration — Solid fires\n // it when the effect re-runs (tearing down the previous subscription)\n // and again when the outer owner disposes (tearing down the final one).\n createEffect(() => {\n const container = options?.container?.() ?? undefined\n const target = options?.target?.() ?? undefined\n const cleanup = motionScroll(handler, {\n container: container as HTMLElement | undefined,\n target: target as HTMLElement | undefined,\n axis: options?.axis,\n offset: options?.offset,\n } as Parameters<typeof motionScroll>[1])\n onCleanup(cleanup)\n })\n\n return { scrollX, scrollY, scrollXProgress, scrollYProgress }\n}\n"],"mappings":"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"}