{"version":3,"names":["onCleanup","untrack","createStableCallback","useAnimationFrame","STARTING_STYLE_ATTR","resolveElement","source","useAnimationsFinished","elementSource","waitForStartingStyleRemoved","treatAbortedAsFinished","frame","activeObserver","activeInternalAbort","disconnect","abort","runWhenAnimationsFinished","fnToExecute","signal","cancel","element","resolvedElement","getAnimations","globalThis","QUOIN_ANIMATIONS_DISABLED","cycleAbort","AbortController","done","exec","Promise","all","map","animation","finished","then","aborted","catch","currentAnimations","length","some","pending","playState","hasAttribute","request","attributeObserver","MutationObserver","observe","attributes","attributeFilter","teardown","addEventListener","once"],"sources":["use-animations-finished.ts"],"sourcesContent":["import { type Accessor, onCleanup, untrack } from \"solid-js\";\nimport { createStableCallback } from \"./stable-callback\";\nimport { useAnimationFrame } from \"./use-animation-frame\";\n\n/**\n * A `data-starting-style` marker attribute — matches the convention used by\n * Base UI React's `TransitionStatusDataAttributes.startingStyle`. Kept inline\n * here so this primitive doesn't need to depend on a\n * `stateAttributesMapping` module that may not yet exist in the Solid port.\n */\nconst STARTING_STYLE_ATTR = \"data-starting-style\";\n\n/**\n * The element source accepted by {@link useAnimationsFinished}. Consumers may\n * pass either:\n *\n * - An accessor that returns the element (preferred — re-reading it lets the\n *   primitive pick up late-mounted elements).\n * - A plain `HTMLElement | null` reference captured via `ref`.\n */\nexport type ElementSource = Accessor<HTMLElement | null> | HTMLElement | null;\n\nfunction resolveElement(source: ElementSource): HTMLElement | null {\n\tif (source === null) return null;\n\tif (typeof source === \"function\") return source();\n\treturn source;\n}\n\n/**\n * Returns a function that, given a callback, waits for all CSS\n * animations/transitions on the target element to settle before invoking it.\n *\n * Mirrors Base UI React's `useAnimationsFinished`\n * (`packages/react/src/internals/useAnimationsFinished.ts`), but without\n * `ReactDOM.flushSync` — Solid 2 uses `flush()` for synchronous application,\n * and consumers that need a synchronous apply can wrap the callback\n * themselves. The vast majority of callers just want \"run after animations\",\n * so we invoke the callback directly.\n *\n * Options:\n *\n * - `waitForStartingStyleRemoved`: if `true`, waits for\n *   `[data-starting-style]` to be removed from the element before probing\n *   `getAnimations()`. This matches React's behavior for \"open\" animations\n *   that aren't registered until the starting-style attribute is cleared.\n * - `treatAbortedAsFinished`: if `false`, when an animation is aborted the\n *   primitive re-probes for new animations instead of treating it as\n *   finished.\n *\n * The returned function is stabilized via {@link createStableCallback} so its\n * identity never changes — safe to pass through directives or capture in\n * long-lived subscriptions.\n *\n * Solid 2 notes:\n *\n * - Must be called from an owned scope (the internal `useAnimationFrame`\n *   registers an `onCleanup`).\n * - No DOM reads happen during setup; the element is resolved lazily each\n *   time the returned function is called, so it's safe to pass an accessor\n *   that returns `null` on the first call.\n */\nexport function useAnimationsFinished(\n\telementSource: ElementSource,\n\twaitForStartingStyleRemoved = false,\n\ttreatAbortedAsFinished = true,\n): (fnToExecute: () => void, signal?: AbortSignal | null) => void {\n\tconst frame = useAnimationFrame();\n\n\t// Owner-dispose cleanup. The frame-scheduler + any external `signal` each\n\t// clean themselves up, but a MutationObserver kicked off in the\n\t// `waitForStartingStyleRemoved` branch has no owner tie: if the owning\n\t// scope disposes before the attribute is removed (and no signal is\n\t// passed), the observer would leak. We track the live observer and the\n\t// live per-call AbortController so `onCleanup` can tear everything down\n\t// in one shot.\n\tlet activeObserver: MutationObserver | null = null;\n\tlet activeInternalAbort: AbortController | null = null;\n\tonCleanup(() => {\n\t\tactiveObserver?.disconnect();\n\t\tactiveObserver = null;\n\t\tactiveInternalAbort?.abort();\n\t\tactiveInternalAbort = null;\n\t});\n\n\tconst runWhenAnimationsFinished = (\n\t\tfnToExecute: () => void,\n\t\tsignal: AbortSignal | null = null,\n\t): void =>\n\t\t// Side-effect helper — re-runs are scheduled by the caller, not by\n\t\t// this body's reads. Wrapping the entry in `untrack` keeps the\n\t\t// elementSource accessor read AND the consumer callback invocation\n\t\t// from tripping `[STRICT_READ_UNTRACKED]` when the helper is invoked\n\t\t// from an effect's apply scope (e.g. `useOpenChangeComplete`).\n\t\tuntrack(() => {\n\t\t\tframe.cancel();\n\t\t\t// New invocation — stop any prior observer/listener we may have set\n\t\t\t// up for a previous call's `waitForStartingStyleRemoved` cycle AND\n\t\t\t// abort any in-flight `Promise.all(animations.finished)` from a\n\t\t\t// previous call, so a stale `.then` can't fire `fnToExecute` after\n\t\t\t// we've started a fresh cycle (stale state writes on rapid toggle).\n\t\t\tactiveObserver?.disconnect();\n\t\t\tactiveObserver = null;\n\t\t\tactiveInternalAbort?.abort();\n\t\t\tactiveInternalAbort = null;\n\n\t\t\tconst element = resolveElement(elementSource);\n\t\t\tif (element == null) return;\n\t\t\tconst resolvedElement = element;\n\n\t\t\t// Tests and SSR-like environments may omit `getAnimations`; and the\n\t\t\t// global kill-switch disables animation waiting entirely.\n\t\t\tif (\n\t\t\t\ttypeof resolvedElement.getAnimations !== \"function\" ||\n\t\t\t\t(globalThis as { QUOIN_ANIMATIONS_DISABLED?: boolean })\n\t\t\t\t\t.QUOIN_ANIMATIONS_DISABLED\n\t\t\t) {\n\t\t\t\t// `untrack` so consumer callbacks reading reactive state during\n\t\t\t\t// the synchronous fast-path don't trip `[STRICT_READ_UNTRACKED]`\n\t\t\t\t// when this helper is invoked from inside an effect's apply scope\n\t\t\t\t// (e.g. `useOpenChangeComplete`'s setOpen-driven effect calling\n\t\t\t\t// the popup's `onComplete` straight through). The async path\n\t\t\t\t// below already runs after a microtask so it's outside the apply\n\t\t\t\t// scope by definition; wrapping `done()` consistently keeps the\n\t\t\t\t// synchronous and async semantics identical from the consumer's\n\t\t\t\t// perspective.\n\t\t\t\tuntrack(fnToExecute);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Fresh internal abort controller for this invocation. The\n\t\t\t// `Promise.all` chain below checks `cycleAbort.signal.aborted`\n\t\t\t// before calling `done()`, so a later invocation that fires\n\t\t\t// `cycleAbort.abort()` cancels this cycle's callback. Without this,\n\t\t\t// a rapid open/close cycle can land the previous close's\n\t\t\t// `fnToExecute` AFTER the new open's measure has committed.\n\t\t\tconst cycleAbort = new AbortController();\n\t\t\tactiveInternalAbort = cycleAbort;\n\n\t\t\tconst done = (): void => {\n\t\t\t\tuntrack(fnToExecute);\n\t\t\t};\n\n\t\t\tfunction exec(): void {\n\t\t\t\tPromise.all(\n\t\t\t\t\tresolvedElement\n\t\t\t\t\t\t.getAnimations()\n\t\t\t\t\t\t.map((animation) => animation.finished),\n\t\t\t\t)\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (cycleAbort.signal.aborted) return;\n\t\t\t\t\t\tif (!signal?.aborted) done();\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tif (cycleAbort.signal.aborted) return;\n\t\t\t\t\t\tif (treatAbortedAsFinished) {\n\t\t\t\t\t\t\tif (!signal?.aborted) done();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst currentAnimations = resolvedElement.getAnimations();\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!signal?.aborted &&\n\t\t\t\t\t\t\tcurrentAnimations.length > 0 &&\n\t\t\t\t\t\t\tcurrentAnimations.some(\n\t\t\t\t\t\t\t\t(animation) =>\n\t\t\t\t\t\t\t\t\tanimation.pending || animation.playState !== \"finished\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// Animation was aborted because an underlying property changed\n\t\t\t\t\t\t\t// mid-flight; re-probe so we wait on the replacement.\n\t\t\t\t\t\t\texec();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (waitForStartingStyleRemoved) {\n\t\t\t\t// If the attribute isn't present at call-time, fall back to waiting\n\t\t\t\t// one frame so late-registered \"open\" animations get a chance to\n\t\t\t\t// show up in `getAnimations()`.\n\t\t\t\tif (!resolvedElement.hasAttribute(STARTING_STYLE_ATTR)) {\n\t\t\t\t\tframe.request(exec);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst attributeObserver = new MutationObserver(() => {\n\t\t\t\t\tif (!resolvedElement.hasAttribute(STARTING_STYLE_ATTR)) {\n\t\t\t\t\t\tattributeObserver.disconnect();\n\t\t\t\t\t\tif (activeObserver === attributeObserver) activeObserver = null;\n\t\t\t\t\t\texec();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tattributeObserver.observe(resolvedElement, {\n\t\t\t\t\tattributes: true,\n\t\t\t\t\tattributeFilter: [STARTING_STYLE_ATTR],\n\t\t\t\t});\n\n\t\t\t\t// Track so owner-dispose can disconnect us. `cycleAbort` is this\n\t\t\t\t// invocation's abort controller — aborting it (on owner dispose\n\t\t\t\t// or on the next invocation of `runWhenAnimationsFinished`)\n\t\t\t\t// tears down the observer, and the `Promise.all` branch above\n\t\t\t\t// short-circuits `done()` when `cycleAbort.signal.aborted`.\n\t\t\t\tactiveObserver = attributeObserver;\n\t\t\t\tconst teardown = () => {\n\t\t\t\t\tattributeObserver.disconnect();\n\t\t\t\t\tif (activeObserver === attributeObserver) activeObserver = null;\n\t\t\t\t};\n\t\t\t\tcycleAbort.signal.addEventListener(\"abort\", teardown, { once: true });\n\t\t\t\tsignal?.addEventListener(\"abort\", teardown, { once: true });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tframe.request(exec);\n\t\t});\n\n\t// Expose via `createStableCallback` so the returned function's identity is\n\t// stable (matches React's `useStableCallback` contract). The inner\n\t// function is already a single closure for this hook's lifetime, but we\n\t// keep the trampoline so call-site shape matches React.\n\treturn createStableCallback<typeof runWhenAnimationsFinished>(\n\t\t() => runWhenAnimationsFinished,\n\t);\n}\n"],"mappings":"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","ignoreList":[]}