phase 0.0.3 → 0.0.5
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/README.md +54 -18
- package/dist/{index-D3epuj2x.d.ts → index-BynP-ee0.d.ts} +28 -2
- package/dist/index-BynP-ee0.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{reduced-motion-CEJtegNG.js → mutation-BDx6r5D3.js} +120 -2
- package/dist/mutation-BDx6r5D3.js.map +1 -0
- package/dist/react.d.ts +75 -28
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +69 -39
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/dist/index-D3epuj2x.d.ts.map +0 -1
- package/dist/reduced-motion-CEJtegNG.js.map +0 -1
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["INITIAL_STATE","INITIAL_STATE","INITIAL_STATE"],"sources":["../src/react/use-synced-ref/index.ts","../src/react/use-stable-callback/index.ts","../src/react/_internal/degraded-config/index.ts","../src/react/use-loop/index.ts","../src/react/use-lifecycle/index.ts","../src/react/use-device-pixel-ratio/index.ts","../src/react/use-media/index.ts","../src/react/use-reduced-motion/index.ts","../src/react/use-sight/index.ts","../src/core/_internal/pool/ro-pool.ts","../src/react/use-size/index.ts","../src/react/use-container-query/index.ts","../src/react/use-scroll-progress/index.ts","../src/react/use-render-state/index.ts","../src/react/use-idle/index.ts","../src/react/use-when-idle/index.ts","../src/react/use-canvas/index.ts","../src/react/use-tween/index.ts","../src/react/_internal/use-update-effect/index.ts","../src/react/use-presence/index.ts","../src/react/presence/index.tsx","../src/react/when-visible/index.tsx","../src/react/when-idle/index.tsx","../src/react/defer/index.tsx","../src/react/swap/index.tsx"],"sourcesContent":["import { useRef, type RefObject } from 'react';\n\n/**\n * Ref whose `.current` is always the latest value, updated synchronously on\n * every render. Readable from any callback or effect without triggering re-render.\n *\n * @example\n * const propsRef = useSyncedRef(props);\n * useEffect(() => {\n * // propsRef.current is always fresh\n * }, []);\n */\nexport function useSyncedRef<T>(value: T): RefObject<T> {\n // Writes ref.current during render — opt out of React Compiler\n // memoization so the write is never skipped. No-op without the compiler.\n 'use no memo';\n\n const ref = useRef(value);\n ref.current = value;\n return ref;\n}\n","import { useRef, useCallback } from 'react';\n\n/**\n * Returns a function with **stable identity** that always calls the latest\n * version of `callback`. Safe in deps arrays and as a prop to `memo()`'d children.\n *\n * @example\n * const handleClick = useStableCallback((e: MouseEvent) => {\n * console.log(latestValue); // always fresh\n * });\n */\nexport function useStableCallback<Args extends unknown[], R>(\n callback: (...args: Args) => R,\n): (...args: Args) => R {\n // Writes callbackRef.current during render — opt out of React Compiler\n // memoization so the write is never skipped. No-op without the compiler.\n 'use no memo';\n\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n // Stable wrapper created once — delegates to the ref on every call.\n // Preserves the exact parameter and return types, no casts required.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback((...args: Args) => callbackRef.current(...args), []);\n}\n","import type { DegradedBehavior } from '../../../core/loop';\n\nexport type DegradedConfig =\n | { degraded?: 'throttle'; degradedFps?: number }\n | { degraded: 'pause' }\n | { degraded: 'ignore' };\n\n/**\n * Map flat `degraded` / `degradedFps` hook options onto the loop's discriminated\n * union. `degradedFps` is only meaningful in `'throttle'` mode.\n */\nexport function degradedConfig(\n degraded: DegradedBehavior | undefined,\n degradedFps: number | undefined,\n): DegradedConfig {\n if (degraded === 'pause') return { degraded: 'pause' };\n if (degraded === 'ignore') return { degraded: 'ignore' };\n return { degraded: 'throttle', degradedFps };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createLoop,\n type LoopPhase,\n type LoopReason,\n type Quality,\n type DegradedBehavior,\n type DegradedReason,\n type ReducedMotionBehavior,\n} from '../../core/loop';\nimport type { FrameState } from '../../core/tick';\nimport { degradedConfig } from '../_internal/degraded-config';\nimport { useSyncedRef } from '../use-synced-ref';\n\n/**\n * Per-frame loop callback. Receives the current frame state. Write to refs or\n * DOM directly. Never call React `setState` here (60 calls/sec = 60\n * re-renders/sec).\n */\nexport type LoopTickFn = (frame: FrameState) => void;\n\nexport interface UseLoopOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to observe. Optional. When omitted, attach the returned `ref`.\n * Pass your own ref to share it or attach it elsewhere.\n */\n ref?: RefObject<T | null>;\n /**\n * Called every frame. Write to refs or DOM directly. Never call React\n * `setState` here (60 calls/sec = 60 re-renders/sec).\n */\n onTick: LoopTickFn;\n fps?: number;\n enabled?: boolean;\n reducedMotion?: ReducedMotionBehavior;\n /** Behavior when quality degrades (window blur, frame-budget). Default `'throttle'`. */\n degraded?: DegradedBehavior;\n /** FPS cap when `degraded` is `'throttle'`. Default `30`. */\n degradedFps?: number;\n intersectionOptions?: IntersectionObserverInit;\n}\n\nexport interface UseLoopResult<T extends Element = HTMLDivElement> {\n /** Attach to the element you want to animate. */\n ref: RefObject<T | null>;\n phase: LoopPhase;\n phaseReason: LoopReason;\n quality: Quality;\n qualityReason: DegradedReason | undefined;\n}\n\ntype LoopState = Omit<UseLoopResult, 'ref'>;\n\n// Disabled or unmounted: the loop isn't created, so it reports `idle` — matching\n// useCanvas and useLifecycle. (Toggling `enabled` tears down and recreates the\n// loop, so \"idle/will start fresh\" is more accurate than \"paused/will resume\".)\nconst INITIAL_STATE: LoopState = {\n phase: 'idle',\n phaseReason: 'initial',\n quality: 'full',\n qualityReason: undefined,\n};\n\n/**\n * Ref-based animation loop that never triggers re-renders from the frame loop.\n *\n * @example\n * const { ref, phase } = useLoop({\n * onTick: (frame) => {\n * ref.current.style.transform = `translateX(${frame.elapsed * 0.1}px)`;\n * },\n * });\n * return <div ref={ref} />;\n */\nexport function useLoop<T extends Element = HTMLDivElement>(\n options: UseLoopOptions<T>,\n): UseLoopResult<T> {\n const {\n fps,\n enabled = true,\n reducedMotion,\n degraded,\n degradedFps,\n intersectionOptions,\n } = options;\n const onTickRef = useSyncedRef(options.onTick);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options.ref ?? internalRef;\n\n const [state, setState] = useState<LoopState>(INITIAL_STATE);\n\n const loopRef = useRef<ReturnType<typeof createLoop> | null>(null);\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element || !enabled) {\n setState(INITIAL_STATE);\n return;\n }\n\n const loop = createLoop({\n element,\n onTick: (frame) => onTickRef.current(frame),\n fps,\n reducedMotion,\n intersectionOptions,\n ...degradedConfig(degraded, degradedFps),\n onPhaseChange: (phase, reason) => {\n // Read from loopRef instead of the local `loop` variable to avoid\n // accessing it before createLoop returns (start:'auto' fires\n // onPhaseChange synchronously during construction).\n const current = loopRef.current;\n setState({\n phase,\n phaseReason: reason,\n quality: current?.quality ?? 'full',\n qualityReason: current?.qualityReason,\n });\n },\n });\n loopRef.current = loop;\n\n return () => {\n loop.stop();\n loopRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, fps, reducedMotion, degraded, degradedFps]);\n\n return { ref, ...state };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createLifecycle,\n type Lifecycle,\n type LifecyclePhase,\n type LifecycleReason,\n type LifecycleReducedMotion,\n} from '../../core/lifecycle';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport interface UseLifecycleOptions<T extends Element = HTMLDivElement> {\n /**\n * Element whose visibility gates the lifecycle. Optional. When omitted, attach\n * the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /** Whether reduced motion pauses the lifecycle. Default `'pause'`. */\n reducedMotion?: LifecycleReducedMotion;\n /** Manually pause regardless of visibility (e.g. a panel opened over the animation). */\n paused?: boolean;\n /** When `false`, the lifecycle is torn down and reports `idle`. Default `true`. */\n enabled?: boolean;\n intersectionOptions?: IntersectionObserverInit;\n /**\n * Synchronous callback fired in the observer/MQL callback, before React\n * schedules a render. Use to post messages to a worker or update a ref\n * without waiting for the React commit.\n */\n onPhaseChange?: (phase: LifecyclePhase, reason: LifecycleReason) => void;\n}\n\nexport interface UseLifecycleResult<T extends Element = HTMLDivElement> {\n /** Attach to the element whose visibility should gate your loop. */\n ref: RefObject<T | null>;\n phase: LifecyclePhase;\n phaseReason: LifecycleReason;\n /** Convenience: `phase === 'active'`. Drive your own render loop off this. */\n isActive: boolean;\n}\n\ntype LifecycleState = Omit<UseLifecycleResult, 'ref' | 'isActive'>;\n\nconst INITIAL_STATE: LifecycleState = {\n phase: 'idle',\n phaseReason: 'initial',\n};\n\n/**\n * React binding for `createLifecycle`. The activation signal for loops you own.\n *\n * Returns `active` / `paused` so a consumer-owned render loop (WebGL, three.js, a\n * Web Worker) can pause when off-screen or under reduced motion. When `phase`\n * should drive the loop for you, use `useLoop` or `useCanvas` instead.\n *\n * @example\n * const { ref, isActive } = useLifecycle();\n * useEffect(() => {\n * if (!isActive) return;\n * const id = requestAnimationFrame(function render() {\n * renderer.render();\n * requestAnimationFrame(render);\n * });\n * return () => cancelAnimationFrame(id);\n * }, [isActive]);\n * return <canvas ref={ref} />;\n */\nexport function useLifecycle<T extends Element = HTMLDivElement>(\n options?: UseLifecycleOptions<T>,\n): UseLifecycleResult<T> {\n const { reducedMotion, intersectionOptions, enabled = true } = options ?? {};\n const paused = options?.paused ?? false;\n const onPhaseChangeRef = useSyncedRef(options?.onPhaseChange);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n const [state, setState] = useState<LifecycleState>(INITIAL_STATE);\n const lifecycleRef = useRef<Lifecycle | null>(null);\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element || !enabled) {\n setState(INITIAL_STATE);\n return;\n }\n\n const lifecycle = createLifecycle({\n element,\n reducedMotion,\n intersectionOptions,\n onPhaseChange: (phase, phaseReason) => {\n onPhaseChangeRef.current?.(phase, phaseReason);\n setState({ phase, phaseReason });\n },\n });\n lifecycleRef.current = lifecycle;\n\n // Apply the manual pause that was requested at mount.\n if (paused) lifecycle.pause();\n\n return () => {\n lifecycle.stop();\n lifecycleRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, reducedMotion]);\n\n // Sync subsequent `paused` changes onto the live lifecycle.\n useEffect(() => {\n const lifecycle = lifecycleRef.current;\n if (!lifecycle) return;\n if (paused) lifecycle.pause();\n else lifecycle.resume();\n }, [paused]);\n\n return { ref, ...state, isActive: state.phase === 'active' };\n}\n","import { useState, useEffect } from 'react';\n\nimport { subscribeDpr, readDpr } from '../../core/_internal/pool/dpr';\n\n/**\n * Reactive devicePixelRatio that updates when the user moves the window\n * between monitors with different DPR values.\n *\n * Returns `1` during SSR and initial hydration, then the live value.\n */\nexport function useDevicePixelRatio(): number {\n const [dpr, setDpr] = useState(1);\n\n useEffect(() => {\n setDpr(readDpr());\n return subscribeDpr(setDpr);\n }, []);\n\n return dpr;\n}\n","import { useState, useEffect } from 'react';\n\nimport {\n subscribeMediaQuery,\n readMediaQuery,\n} from '../../core/_internal/pool/mql-pool';\n\n/**\n * Subscribe to a media query via the shared MQL pool.\n *\n * Returns `false` during SSR and initial hydration render,\n * then the live value from the first `useEffect`.\n *\n * @example\n * const isNarrow = useMediaQuery('(max-width: 600px)');\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n setMatches(readMediaQuery(query));\n return subscribeMediaQuery(query, setMatches);\n }, [query]);\n\n return matches;\n}\n","import { REDUCED_MOTION_QUERY } from '../../core/reduced-motion';\nimport { useMediaQuery } from '../use-media';\n\n/**\n * Reactive boolean that tracks the user's `prefers-reduced-motion` OS setting.\n *\n * Returns `false` during SSR and initial hydration, then the live value.\n * Re-renders only when the preference changes.\n */\nexport function usePrefersReducedMotion(): boolean {\n return useMediaQuery(REDUCED_MOTION_QUERY);\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createSight,\n type SightPhase,\n type SightReason,\n} from '../../core/sight';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport type SightCallback = (\n phase: SightPhase,\n phaseReason: SightReason,\n) => void;\n\nexport interface UseSightOptions<\n T extends Element = HTMLDivElement,\n> extends IntersectionObserverInit {\n /**\n * Element to observe. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /** `'continuous'` keeps observing. `'once'` freezes at `'visible'` after first intersection. */\n observe?: 'continuous' | 'once';\n /**\n * Called on every visibility transition. When provided, `phase` and\n * `phaseReason` stay at initial values and no re-renders occur.\n */\n onVisibilityChange?: SightCallback;\n}\n\nexport interface UseSightReactiveResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n phase: SightPhase;\n phaseReason: SightReason;\n /** Visibility phase via ref. Always current, never triggers re-render. */\n phaseRef: RefObject<SightPhase>;\n /** Phase reason via ref. Always current, never triggers re-render. */\n phaseReasonRef: RefObject<SightReason>;\n}\n\nexport interface UseSightTransientResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n /** Visibility phase via ref. Always current, never triggers re-render. */\n phaseRef: RefObject<SightPhase>;\n /** Phase reason via ref. Always current, never triggers re-render. */\n phaseReasonRef: RefObject<SightReason>;\n}\n\n/** @deprecated Use `UseSightReactiveResult` or `UseSightTransientResult`. */\nexport type UseSightResult<T extends Element = HTMLDivElement> =\n UseSightReactiveResult<T>;\n\ntype SightState = { phase: SightPhase; phaseReason: SightReason };\n\nconst INITIAL_STATE: SightState = {\n phase: 'unknown',\n phaseReason: 'initial',\n};\n\n/**\n * Intersection + document visibility as a phase.\n *\n * Pass `onVisibilityChange` for zero-re-render mode (animation gating,\n * many-element observation). Without it, `phase` and `phaseReason` update\n * via state on every transition. `phaseRef`/`phaseReasonRef` are always current.\n *\n * @example\n * // Reactive\n * const { ref, phase } = useSight();\n *\n * // Transient (no re-renders)\n * const { ref, phaseRef } = useSight({\n * onVisibilityChange: (phase) => { worker.postMessage({ visible: phase === 'visible' }); },\n * });\n */\nexport function useSight<T extends Element = HTMLDivElement>(\n options: UseSightOptions<T> & { onVisibilityChange: SightCallback },\n): UseSightTransientResult<T>;\nexport function useSight<T extends Element = HTMLDivElement>(\n options?: UseSightOptions<T>,\n): UseSightReactiveResult<T>;\nexport function useSight<T extends Element = HTMLDivElement>(\n options?: UseSightOptions<T>,\n): UseSightReactiveResult<T> | UseSightTransientResult<T> {\n const [state, setState] = useState<SightState>(INITIAL_STATE);\n const observe = options?.observe ?? 'continuous';\n const phaseRef = useRef<SightPhase>('unknown');\n const phaseReasonRef = useRef<SightReason>('initial');\n const onVisibilityChangeRef = useSyncedRef(options?.onVisibilityChange);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n let frozen = false;\n\n const sight = createSight({\n element,\n intersectionOptions: {\n root: options?.root,\n rootMargin: options?.rootMargin,\n threshold: options?.threshold,\n },\n onPhaseChange: (phase, reason) => {\n if (frozen) return;\n\n phaseRef.current = phase;\n phaseReasonRef.current = reason;\n\n if (onVisibilityChangeRef.current) {\n onVisibilityChangeRef.current(phase, reason);\n } else {\n setState({ phase, phaseReason: reason });\n }\n\n if (observe === 'once' && phase === 'visible') {\n frozen = true;\n sight.stop();\n }\n },\n });\n\n return () => sight.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [observe]);\n\n return { ref, ...state, phaseRef, phaseReasonRef };\n}\n","type ROCallback = (entry: ResizeObserverEntry) => void;\n\nlet observer: ResizeObserver | null = null;\nconst callbacks = new Map<Element, ROCallback>();\n\n/**\n * Observe an element via a singleton ResizeObserver.\n * One RO instance for the entire page. Per-element `box` options are\n * forwarded to `ResizeObserver.observe()`.\n *\n * @returns Cleanup function that unobserves the element.\n */\nexport function observeResize(\n element: Element,\n callback: ROCallback,\n box?: ResizeObserverBoxOptions,\n): () => void {\n callbacks.set(element, callback);\n getObserver().observe(element, box ? { box } : undefined);\n\n let disposed = false;\n\n return () => {\n if (disposed) return;\n disposed = true;\n\n // Only unobserve if our callback is still the registered one.\n // A later subscription on the same element would have overwritten it.\n if (callbacks.get(element) === callback) {\n callbacks.delete(element);\n observer?.unobserve(element);\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Lazy-created singleton. RO takes zero constructor options, so one instance can observe everything. */\nfunction getObserver(): ResizeObserver {\n if (!observer) {\n observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const cb: ROCallback | undefined = callbacks.get(entry.target);\n if (cb) cb(entry);\n }\n });\n }\n return observer;\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport { observeResize } from '../../core/_internal/pool/ro-pool';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport type SizeCallback = (size: Size) => void;\n\nexport interface Size {\n width: number;\n height: number;\n}\n\nexport interface UseSizeOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to measure. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /**\n * Which CSS box model to measure. `'content-box'` returns the content area\n * (inside padding). `'border-box'` returns content + padding + border.\n * Default `'content-box'`.\n */\n box?: 'content-box' | 'border-box';\n /**\n * Called on every resize. When provided, `size` is omitted from the return\n * type and no re-renders occur, the right path for canvas and animation\n * consumers that read dimensions imperatively.\n */\n onResize?: SizeCallback;\n}\n\nexport interface UseSizeReactiveResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n /** Element dimensions via state, or `null` until first observation. */\n size: Size | null;\n /** Element dimensions via ref. Always current, never triggers re-render. */\n sizeRef: RefObject<Size | null>;\n}\n\nexport interface UseSizeTransientResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n /** Element dimensions via ref. Always current, never triggers re-render. */\n sizeRef: RefObject<Size | null>;\n}\n\n/** @deprecated Use `UseSizeReactiveResult` or `UseSizeTransientResult`. */\nexport type UseSizeResult<T extends Element = HTMLDivElement> =\n UseSizeReactiveResult<T>;\n\n/**\n * Element dimensions via the shared ResizeObserver singleton.\n *\n * Pass `onResize` for zero-re-render mode (canvas, animation loops).\n * Without it, `size` updates via state on every dimension change.\n * `sizeRef` is always current in both modes.\n *\n * @example\n * // Reactive (re-renders on resize)\n * const { ref, size } = useSize();\n *\n * // Transient (no re-renders — read sizeRef in onTick/draw)\n * const { ref, sizeRef } = useSize({ onResize: (s) => applySize(s) });\n */\nexport function useSize<T extends Element = HTMLDivElement>(\n options: UseSizeOptions<T> & { onResize: SizeCallback },\n): UseSizeTransientResult<T>;\nexport function useSize<T extends Element = HTMLDivElement>(\n options?: UseSizeOptions<T>,\n): UseSizeReactiveResult<T>;\nexport function useSize<T extends Element = HTMLDivElement>(\n options?: UseSizeOptions<T>,\n): UseSizeReactiveResult<T> | UseSizeTransientResult<T> {\n const [size, setSize] = useState<Size | null>(null);\n const sizeRef = useRef<Size | null>(null);\n const prevWidth = useRef<number | null>(null);\n const prevHeight = useRef<number | null>(null);\n const onResizeRef = useSyncedRef(options?.onResize);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n const boxOption: 'content-box' | 'border-box' | undefined = options?.box;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const unobserve: () => void = observeResize(\n element,\n (entry) => {\n const resolved: ResizeObserverSize | undefined =\n boxOption === 'border-box'\n ? entry.borderBoxSize[0]\n : entry.contentBoxSize[0];\n if (!resolved) return;\n\n const width: number = resolved.inlineSize;\n const height: number = resolved.blockSize;\n\n if (width === prevWidth.current && height === prevHeight.current)\n return;\n prevWidth.current = width;\n prevHeight.current = height;\n\n const next: Size = { width, height };\n sizeRef.current = next;\n\n if (onResizeRef.current) {\n onResizeRef.current(next);\n } else {\n setSize(next);\n }\n },\n boxOption,\n );\n\n return unobserve;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [boxOption]);\n\n return { ref, size, sizeRef };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport { observeResize } from '../../core/_internal/pool/ro-pool';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ContainerBreakpoint {\n minWidth?: number;\n maxWidth?: number;\n minHeight?: number;\n maxHeight?: number;\n}\n\nexport interface UseContainerQueryOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to measure. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n}\n\nexport interface UseContainerQueryResult<T extends Element = HTMLDivElement> {\n /** Attach to the element you want to match against the breakpoint. */\n ref: RefObject<T | null>;\n /** Whether the element currently matches the breakpoint. */\n matches: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// useContainerQuery\n// ---------------------------------------------------------------------------\n\n/**\n * Returns whether an element matches a size-based container breakpoint.\n *\n * Unlike `useSize` (which re-renders on every pixel of resize), this hook only\n * re-renders when the match result changes, i.e. when the element crosses a\n * breakpoint boundary. Uses the shared ResizeObserver singleton.\n *\n * @example\n * const { ref, matches } = useContainerQuery({ minWidth: 600 });\n * return <div ref={ref}>{matches ? 'wide' : 'narrow'}</div>;\n */\nexport function useContainerQuery<T extends Element = HTMLDivElement>(\n breakpoint: ContainerBreakpoint,\n options?: UseContainerQueryOptions<T>,\n): UseContainerQueryResult<T> {\n const [matches, setMatches] = useState(false);\n const matchesRef = useRef(false);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n const { minWidth, maxWidth, minHeight, maxHeight } = breakpoint;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const unobserve: () => void = observeResize(element, (entry) => {\n const box = entry.contentBoxSize[0];\n if (!box) return;\n\n const width: number = box.inlineSize;\n const height: number = box.blockSize;\n\n const nowMatches: boolean = evaluateBreakpoint(\n width,\n height,\n minWidth,\n maxWidth,\n minHeight,\n maxHeight,\n );\n\n // Only re-render when the boolean flips — not on every pixel of resize.\n if (nowMatches !== matchesRef.current) {\n matchesRef.current = nowMatches;\n setMatches(nowMatches);\n }\n });\n\n return unobserve;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [minWidth, maxWidth, minHeight, maxHeight]);\n\n return { ref, matches };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction evaluateBreakpoint(\n width: number,\n height: number,\n minWidth?: number,\n maxWidth?: number,\n minHeight?: number,\n maxHeight?: number,\n): boolean {\n if (minWidth !== undefined && width < minWidth) return false;\n if (maxWidth !== undefined && width > maxWidth) return false;\n if (minHeight !== undefined && height < minHeight) return false;\n if (maxHeight !== undefined && height > maxHeight) return false;\n return true;\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport { createScrollProgress } from '../../core/scroll-progress';\nimport { useSyncedRef } from '../use-synced-ref';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ScrollProgressCallback = (progress: number) => void;\n\nexport interface UseScrollProgressOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to observe. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /** Number of evenly-spaced thresholds. Default 20 (~5% granularity). */\n steps?: number;\n root?: Element | null;\n rootMargin?: string;\n /**\n * Called on every threshold crossing. When provided, `progress` stays `0`\n * and no re-renders occur, the right path for scroll-driven animation\n * consumers that read progress imperatively.\n */\n onProgress?: ScrollProgressCallback;\n}\n\nexport interface UseScrollProgressReactiveResult<\n T extends Element = HTMLDivElement,\n> {\n ref: RefObject<T | null>;\n /** Fraction of the element currently visible (0–1). */\n progress: number;\n /** Fraction visible via ref. Always current, never triggers re-render. */\n progressRef: RefObject<number>;\n}\n\nexport interface UseScrollProgressTransientResult<\n T extends Element = HTMLDivElement,\n> {\n ref: RefObject<T | null>;\n /** Fraction visible via ref. Always current, never triggers re-render. */\n progressRef: RefObject<number>;\n}\n\n/** @deprecated Use `UseScrollProgressReactiveResult` or `UseScrollProgressTransientResult`. */\nexport type UseScrollProgressResult<T extends Element = HTMLDivElement> =\n UseScrollProgressReactiveResult<T>;\n\n// ---------------------------------------------------------------------------\n// useScrollProgress\n// ---------------------------------------------------------------------------\n\n/**\n * Element visibility ratio (0–1) via the shared IntersectionObserver pool.\n *\n * Pass `onProgress` for zero-re-render mode (scroll-driven animation).\n * Without it, `progress` updates via state at each threshold crossing.\n * `progressRef` is always current in both modes.\n *\n * @example\n * // Reactive (re-renders at threshold crossings)\n * const { ref, progress } = useScrollProgress();\n *\n * // Transient (no re-renders — read progressRef in onTick)\n * const { ref, progressRef } = useScrollProgress({\n * onProgress: (p) => { el.style.opacity = String(p); },\n * });\n */\nexport function useScrollProgress<T extends Element = HTMLDivElement>(\n options: UseScrollProgressOptions<T> & {\n onProgress: ScrollProgressCallback;\n },\n): UseScrollProgressTransientResult<T>;\nexport function useScrollProgress<T extends Element = HTMLDivElement>(\n options?: UseScrollProgressOptions<T>,\n): UseScrollProgressReactiveResult<T>;\nexport function useScrollProgress<T extends Element = HTMLDivElement>(\n options?: UseScrollProgressOptions<T>,\n): UseScrollProgressReactiveResult<T> | UseScrollProgressTransientResult<T> {\n const [progress, setProgress] = useState(0);\n const progressRef = useRef(0);\n const steps: number | undefined = options?.steps;\n const rootMargin: string | undefined = options?.rootMargin;\n const onProgressRef = useSyncedRef(options?.onProgress);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const scrollProgress = createScrollProgress({\n element,\n onProgress: (ratio: number) => {\n progressRef.current = ratio;\n\n if (onProgressRef.current) {\n onProgressRef.current(ratio);\n } else {\n setProgress(ratio);\n }\n },\n steps,\n root: options?.root,\n rootMargin,\n });\n\n return () => scrollProgress.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [steps, rootMargin]);\n\n return { ref, progress, progressRef };\n}\n","import { useState, useEffect, type RefObject } from 'react';\n\nimport { createRenderState, type RenderPhase } from '../../core/render-state';\n\nexport type { RenderPhase } from '../../core/render-state';\n\n/**\n * Track whether the browser is rendering an element or skipping it under\n * `content-visibility` (e.g. a `Defer` subtree). Returns `'rendered'` until the\n * browser reports otherwise.\n *\n * Use it to pause raw, non-phase work (a hand-written rAF loop, `setInterval`)\n * when the subtree stops painting. phase loops self-pause off-screen already.\n * Has no layout effect. Safe for CLS.\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null);\n * const phase = useRenderState(ref);\n * useEffect(() => {\n * if (phase === 'skipped') clock.pause();\n * else clock.resume();\n * }, [phase]);\n * return <Defer ref={ref}><Heavy /></Defer>;\n */\nexport function useRenderState<T extends Element = HTMLDivElement>(\n ref: RefObject<T | null>,\n): RenderPhase {\n const [phase, setPhase] = useState<RenderPhase>('rendered');\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const render = createRenderState({\n element,\n onPhaseChange: setPhase,\n });\n\n return () => render.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return phase;\n}\n","import { useState, useEffect } from 'react';\n\nimport { whenIdle, type IdleOptions } from '../../core/idle';\n\nexport type { IdleOptions } from '../../core/idle';\n\n/**\n * Returns `false`, then `true` once the browser is idle after mount. Use it to\n * defer non-critical work or mounting until the main thread is free.\n *\n * SSR-safe: returns `false` on the server and during the first client render.\n *\n * @example\n * const idle = useIdle();\n * return idle ? <Analytics /> : null;\n */\nexport function useIdle(options?: IdleOptions): boolean {\n const [idle, setIdle] = useState(false);\n const timeout = options?.timeout;\n\n useEffect(() => {\n const cancel: () => void = whenIdle(() => setIdle(true), { timeout });\n return cancel;\n }, [timeout]);\n\n return idle;\n}\n","import { useEffect } from 'react';\n\nimport { whenIdle, type IdleOptions } from '../../core/idle';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport type { IdleOptions } from '../../core/idle';\n\n/**\n * Run a callback once, when the browser is idle after mount. The effect-shaped\n * counterpart to `useIdle`. Use it for side effects (prefetching a chunk,\n * warming a cache, `import()`) rather than rendering.\n *\n * Cancels automatically on unmount, and always calls the latest `callback`\n * without re-subscribing. SSR-safe: nothing runs on the server.\n *\n * @example\n * // Prefetch a heavy panel during idle time so it opens instantly later.\n * useWhenIdle(() => void import('./chat-panel'));\n */\nexport function useWhenIdle(callback: () => void, options?: IdleOptions): void {\n const callbackRef = useSyncedRef(callback);\n const timeout = options?.timeout;\n\n useEffect(() => {\n const cancel: () => void = whenIdle(() => callbackRef.current(), {\n timeout,\n });\n return cancel;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [timeout]);\n}\n","import {\n useState,\n useEffect,\n useRef,\n useCallback,\n type RefObject,\n} from 'react';\n\nimport { subscribeDpr, readDpr } from '../../core/_internal/pool/dpr';\nimport { observeResize } from '../../core/_internal/pool/ro-pool';\nimport {\n createLoop,\n type LoopPhase,\n type LoopReason,\n type Quality,\n type DegradedBehavior,\n type DegradedReason,\n type ReducedMotionBehavior,\n} from '../../core/loop';\nimport type { FrameState } from '../../core/tick';\nimport { degradedConfig } from '../_internal/degraded-config';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/**\n * Per-frame canvas draw callback. Receives the 2D context, frame state, and\n * current element size. Draw directly to the canvas. Never call React\n * `setState` here.\n */\nexport type CanvasDrawFn = (\n ctx: CanvasRenderingContext2D,\n frame: FrameState,\n size: Size,\n) => void;\n\nexport interface UseCanvasOptions {\n containerRef: RefObject<Element | null>;\n canvasRef: RefObject<HTMLCanvasElement | null>;\n /**\n * Called every frame with the 2D context, frame state, and current element size.\n * Draw directly to the canvas. Never call React `setState` here.\n */\n draw: CanvasDrawFn;\n fps?: number;\n enabled?: boolean;\n reducedMotion?: ReducedMotionBehavior;\n /** Behavior when quality degrades. Default `'throttle'`. For heavy GPU work, `'pause'` is often the right call. */\n degraded?: DegradedBehavior;\n /** FPS cap when `degraded` is `'throttle'`. Default `30`. */\n degradedFps?: number;\n}\n\nexport interface UseCanvasResult {\n restart: () => void;\n phase: LoopPhase;\n phaseReason: LoopReason;\n quality: Quality;\n qualityReason: DegradedReason | undefined;\n}\n\nconst INITIAL_STATE: Omit<UseCanvasResult, 'restart'> = {\n phase: 'idle',\n phaseReason: 'initial',\n quality: 'full',\n qualityReason: undefined,\n};\n\n/**\n * Canvas-specific animation with DPR-aware sizing, ResizeObserver coalescing,\n * context management, and GPU context loss recovery.\n *\n * @example\n * useCanvas({\n * containerRef,\n * canvasRef,\n * draw: (ctx, frame, size) => {\n * ctx.clearRect(0, 0, size.width, size.height);\n * // render...\n * },\n * });\n */\nexport function useCanvas(options: UseCanvasOptions): UseCanvasResult {\n const {\n containerRef,\n canvasRef,\n fps,\n enabled = true,\n reducedMotion,\n degraded,\n degradedFps,\n } = options;\n const drawRef = useSyncedRef(options.draw);\n\n const [state, setState] = useState(INITIAL_STATE);\n const [restartNonce, setRestartNonce] = useState(0);\n\n const ctxRef = useRef<CanvasRenderingContext2D | null>(null);\n const sizeRef = useRef<Size>({ width: 0, height: 0 });\n const qualityRef = useSyncedRef(state.quality);\n\n useEffect(() => {\n const container: Element | null = containerRef.current;\n const canvasEl: HTMLCanvasElement | null = canvasRef.current;\n if (!container || !canvasEl || !enabled) return;\n const canvas: HTMLCanvasElement = canvasEl;\n\n const initialCtx: CanvasRenderingContext2D | null = canvas.getContext('2d');\n if (!initialCtx) return;\n ctxRef.current = initialCtx;\n\n let dpr: number = readDpr();\n let contextLost = false;\n\n // --- Canvas buffer sizing ---\n\n function applySize(\n width: number,\n height: number,\n physicalBox?: ResizeObserverSize,\n ): void {\n sizeRef.current = { width, height };\n const isDegraded: boolean = qualityRef.current === 'degraded';\n\n let bufferWidth: number;\n let bufferHeight: number;\n\n if (isDegraded) {\n bufferWidth = width;\n bufferHeight = height;\n } else if (physicalBox) {\n bufferWidth = physicalBox.inlineSize;\n bufferHeight = physicalBox.blockSize;\n } else {\n bufferWidth = width * dpr;\n bufferHeight = height * dpr;\n }\n\n canvas.width = bufferWidth;\n canvas.height = bufferHeight;\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n\n const effectiveDpr: number = isDegraded ? 1 : dpr;\n ctxRef.current?.setTransform(effectiveDpr, 0, 0, effectiveDpr, 0, 0);\n }\n\n // --- DPR monitoring (e.g. user drags window between monitors) ---\n\n const unsubDpr: () => void = subscribeDpr((newDpr) => {\n dpr = newDpr;\n applySize(sizeRef.current.width, sizeRef.current.height);\n });\n\n // --- Resize via shared RO pool ---\n\n const unobserve: () => void = observeResize(container, (entry) => {\n const box = entry.contentBoxSize[0];\n if (!box) return;\n const physicalBox: ResizeObserverSize | undefined =\n entry.devicePixelContentBoxSize?.[0];\n applySize(box.inlineSize, box.blockSize, physicalBox);\n });\n\n // --- GPU context loss recovery ---\n\n function onContextLost(event: Event): void {\n event.preventDefault();\n contextLost = true;\n }\n\n function onContextRestored(): void {\n const restoredCtx: CanvasRenderingContext2D | null =\n canvas.getContext('2d');\n if (!restoredCtx) return;\n ctxRef.current = restoredCtx;\n contextLost = false;\n applySize(sizeRef.current.width, sizeRef.current.height);\n }\n\n canvas.addEventListener('contextlost', onContextLost);\n canvas.addEventListener('contextrestored', onContextRestored);\n\n // --- Animation loop ---\n\n let loopInstance: ReturnType<typeof createLoop> | null = null;\n\n const loop = createLoop({\n element: container,\n fps,\n reducedMotion,\n ...degradedConfig(degraded, degradedFps),\n onTick: (frame) => {\n if (contextLost || !ctxRef.current) return;\n drawRef.current(ctxRef.current, frame, sizeRef.current);\n },\n onPhaseChange: (phase, reason) => {\n setState({\n phase,\n phaseReason: reason,\n quality: loopInstance?.quality ?? 'full',\n qualityReason: loopInstance?.qualityReason,\n });\n },\n });\n loopInstance = loop;\n\n // --- Teardown ---\n\n function teardown(): void {\n loop.stop();\n loopInstance = null;\n unobserve();\n unsubDpr();\n canvas.removeEventListener('contextlost', onContextLost);\n canvas.removeEventListener('contextrestored', onContextRestored);\n }\n\n return teardown;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, fps, reducedMotion, degraded, degradedFps, restartNonce]);\n\n // Restart bumps a nonce so the effect re-runs: it tears down the current\n // loop + observers and rebuilds them on the next cycle.\n const restart = useCallback(() => {\n setRestartNonce((n) => n + 1);\n }, []);\n\n return { restart, ...state };\n}\n","import { useState, useEffect, useRef } from 'react';\n\nimport { invalidDurationError } from '../../core/_internal/errors';\nimport type { ReducedMotionBehavior } from '../../core/loop';\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { clamp01, easeOutCubic } from '../../ease';\n\nexport interface UseTweenOptions {\n target: number;\n duration?: number;\n delay?: number;\n easing?: (progress: number) => number;\n enabled?: boolean;\n /** Default: `'complete'`. Tweens jump to target under reduced motion. */\n reducedMotion?: ReducedMotionBehavior;\n}\n\n/**\n * Animate a value from its current position to `target` over `duration`.\n *\n * Uses `useState` per frame. Appropriate for cheap renders (counters, opacity,\n * progress bars). For batch animations, use `useLoop` with ref-based DOM writes.\n *\n * @remarks\n * Unlike `createTicker`/`createLoop`, `useTween` drives its own rAF rather than\n * the shared frame-locked clock. It's a finite, self-completing tween whose value\n * must land in React state, so it doesn't need cross-loop visual sync, strong\n * pause, or delta clamping. Routing it through the shared clock would add bundle\n * weight for no benefit.\n *\n * @example\n * const value = useTween({ target: 100, duration: 500 });\n */\nexport function useTween(options: UseTweenOptions): number {\n const {\n target,\n duration = 300,\n delay = 0,\n easing = easeOutCubic,\n enabled = true,\n reducedMotion = 'complete',\n } = options;\n\n const [value, setValue] = useState(target);\n\n const fromRef = useRef(target);\n const currentRef = useRef(target);\n const isFirstRender = useRef(true);\n\n useEffect(() => {\n if (!Number.isFinite(duration) || duration <= 0) {\n invalidDurationError('useTween', duration);\n }\n\n // First render: sync refs without animating.\n if (isFirstRender.current) {\n isFirstRender.current = false;\n jumpToTarget({ target, fromRef, currentRef, setValue });\n return;\n }\n\n // Disabled or reduced motion: jump immediately.\n if (!enabled || (reducedMotion !== 'ignore' && prefersReducedMotion())) {\n jumpToTarget({ target, fromRef, currentRef, setValue });\n return;\n }\n\n // Already at target: nothing to animate.\n const from: number = currentRef.current;\n if (from === target) return;\n\n let rafId: number;\n let startTime: number | null = null;\n\n function tick(now: number): void {\n if (startTime === null) startTime = now;\n const elapsed: number = now - startTime - delay;\n\n // Still in the delay period — keep scheduling.\n if (elapsed < 0) {\n rafId = requestAnimationFrame(tick);\n return;\n }\n\n const progress: number = clamp01(elapsed / duration);\n const current: number = from + (target - from) * easing(progress);\n currentRef.current = current;\n setValue(current);\n\n if (progress < 1) {\n rafId = requestAnimationFrame(tick);\n } else {\n fromRef.current = target;\n }\n }\n\n rafId = requestAnimationFrame(tick);\n\n return () => {\n cancelAnimationFrame(rafId);\n // Preserve where we actually are so the next tween starts from here.\n fromRef.current = currentRef.current;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [target, duration, delay, enabled, reducedMotion]);\n\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface JumpToTargetOptions {\n target: number;\n fromRef: React.RefObject<number>;\n currentRef: React.RefObject<number>;\n setValue: (value: number) => void;\n}\n\nfunction jumpToTarget(options: JumpToTargetOptions): void {\n const { target, fromRef, currentRef, setValue } = options;\n fromRef.current = target;\n currentRef.current = target;\n setValue(target);\n}\n","import {\n useEffect,\n useRef,\n type EffectCallback,\n type DependencyList,\n} from 'react';\n\n/**\n * Like `useEffect` but skips the first invocation on mount.\n * Used by Presence to distinguish initial render from subsequent `show` changes.\n */\nexport function useUpdateEffect(\n effect: EffectCallback,\n deps: DependencyList,\n): void {\n const isMounted = useRef(false);\n\n useEffect(() => {\n if (!isMounted.current) {\n isMounted.current = true;\n return;\n }\n return effect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n}\n","import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type RefObject,\n} from 'react';\n\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { useUpdateEffect } from '../_internal/use-update-effect';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type PresencePhase = 'idle' | 'entered' | 'exiting' | 'exited';\n\nexport type PresenceReason =\n | 'initial'\n | 'show'\n | 'hide'\n | 'animation-end'\n | 'interrupted';\n\nexport type PresenceMode = 'mount' | 'reveal';\n\nexport interface UsePresenceOptions {\n show: boolean;\n mode?: PresenceMode;\n /** Controls first-mount behavior. `'animate'` (default): enter animation plays. `'instant'`: appears immediately. */\n enter?: 'animate' | 'instant';\n /** Safety-net timeout in ms if transitionend/animationend doesn't fire during exit. Default 5000. */\n exitDuration?: number;\n /** Whether to respect the user's reduced motion preference. Default `'respect'`. */\n reducedMotion?: 'respect' | 'ignore';\n}\n\nexport interface UsePresenceResult {\n phase: PresencePhase;\n phaseReason: PresenceReason;\n /** Convenience: `phase !== 'idle' && phase !== 'exited'` for conditional rendering in mount mode. */\n mounted: boolean;\n ref: RefObject<Element | null>;\n /** Whether the component should stamp `data-enter=\"animate\"`. Accounts for enter option + reduced motion. */\n enter: 'animate' | 'instant';\n}\n\n// ---------------------------------------------------------------------------\n// usePresence\n// ---------------------------------------------------------------------------\n\n/**\n * Composable presence primitive for mount/unmount lifecycle with CSS transitions.\n *\n * Enter animations use CSS `@starting-style`, gated by `data-enter=\"animate\"`.\n * Exit animations are JS-coordinated: waits for `transitionend`/`animationend`\n * before unmounting.\n *\n * @example\n * const { phase, ref, mounted, enter } = usePresence({ show: isOpen });\n * if (!mounted) return null;\n * return (\n * <div ref={ref} data-phase={phase} data-enter={enter === 'animate' ? 'animate' : undefined}\n * className=\"transition-opacity data-[enter=animate]:starting:opacity-0 data-[phase=exiting]:opacity-0\" />\n * );\n */\nexport function usePresence(options: UsePresenceOptions): UsePresenceResult {\n const {\n show,\n mode = 'mount',\n enter: enterOption = 'animate',\n exitDuration = 5000,\n reducedMotion = 'respect',\n } = options;\n\n const ref = useRef<Element | null>(null);\n\n const initialPhase: PresencePhase = show ? 'entered' : 'idle';\n\n const [phase, setPhase] = useState<PresencePhase>(initialPhase);\n const [reason, setReason] = useState<PresenceReason>('initial');\n\n const exitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const exitCleanupRef = useRef<(() => void) | null>(null);\n\n const clearTimers = useCallback(() => {\n if (exitTimerRef.current !== null) {\n clearTimeout(exitTimerRef.current);\n exitTimerRef.current = null;\n }\n if (exitCleanupRef.current) {\n exitCleanupRef.current();\n exitCleanupRef.current = null;\n }\n }, []);\n\n useEffect(() => () => clearTimers(), [clearTimers]);\n\n useUpdateEffect(() => {\n clearTimers();\n\n if (show) {\n setPhase((prev) => {\n setReason(prev === 'exiting' ? 'interrupted' : 'show');\n return 'entered';\n });\n } else {\n const shouldSkipAnimation =\n reducedMotion === 'respect' && prefersReducedMotion();\n\n if (shouldSkipAnimation) {\n const exitTarget: PresencePhase = mode === 'reveal' ? 'idle' : 'exited';\n setPhase(exitTarget);\n setReason('animation-end');\n } else {\n handleExit(\n ref,\n mode,\n exitDuration,\n setPhase,\n setReason,\n clearTimers,\n exitTimerRef,\n exitCleanupRef,\n );\n }\n }\n }, [show]);\n\n const mounted: boolean = phase !== 'idle' && phase !== 'exited';\n\n const isFirstMount = reason === 'initial';\n const wantsAnimation = !(isFirstMount && enterOption === 'instant');\n const motionAllowed = reducedMotion === 'ignore' || !prefersReducedMotion();\n const enter: 'animate' | 'instant' =\n wantsAnimation && motionAllowed ? 'animate' : 'instant';\n\n return { phase, phaseReason: reason, mounted, ref, enter };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction handleExit(\n ref: RefObject<Element | null>,\n mode: PresenceMode,\n exitDuration: number,\n setPhase: (\n phase: PresencePhase | ((prev: PresencePhase) => PresencePhase),\n ) => void,\n setReason: (reason: PresenceReason) => void,\n clearTimers: () => void,\n exitTimerRef: React.RefObject<ReturnType<typeof setTimeout> | null>,\n exitCleanupRef: React.RefObject<(() => void) | null>,\n): void {\n setPhase('exiting');\n setReason('hide');\n\n const exitTarget: PresencePhase = mode === 'reveal' ? 'idle' : 'exited';\n const element: Element | null = ref.current;\n\n function completeExit(): void {\n clearTimers();\n setPhase((current) => {\n if (current !== 'exiting') return current;\n setReason('animation-end');\n return exitTarget;\n });\n }\n\n function cleanup(): void {\n if (element) {\n element.removeEventListener('transitionend', completeExit);\n element.removeEventListener('animationend', completeExit);\n }\n if (exitTimerRef.current !== null) {\n clearTimeout(exitTimerRef.current);\n exitTimerRef.current = null;\n }\n exitCleanupRef.current = null;\n }\n\n exitCleanupRef.current = cleanup;\n\n if (element) {\n element.addEventListener('transitionend', completeExit, { once: true });\n element.addEventListener('animationend', completeExit, { once: true });\n }\n\n exitTimerRef.current = setTimeout(completeExit, exitDuration);\n}\n","import {\n useImperativeHandle,\n type ComponentProps,\n type JSX,\n type Ref,\n} from 'react';\n\nimport { usePresence, type PresenceMode } from '../use-presence';\n\nexport interface PresenceProps extends ComponentProps<'div'> {\n show: boolean;\n mode?: PresenceMode;\n /** Controls first-mount behavior. `'animate'` (default): enter animation plays. `'instant'`: appears immediately. */\n enter?: 'animate' | 'instant';\n /** Safety-net timeout in ms if transitionend/animationend doesn't fire during exit. Default 5000. */\n exitDuration?: number;\n /** Whether to respect the user's reduced motion preference. Default `'respect'`. */\n reducedMotion?: 'respect' | 'ignore';\n ref?: Ref<HTMLDivElement>;\n}\n\n/**\n * Renders a `div` that manages its own mounting lifecycle.\n *\n * Stamps `data-phase` for exit animations and `data-enter=\"animate\"` to gate\n * CSS `@starting-style` enter animations. Reduced motion is handled automatically.\n *\n * @example\n * <Presence\n * show={isOpen}\n * className=\"transition-opacity data-[enter=animate]:starting:opacity-0 data-[phase=exiting]:opacity-0\"\n * >\n * Modal content\n * </Presence>\n */\nexport function Presence({\n show,\n mode,\n enter: enterOption,\n exitDuration,\n reducedMotion,\n ref: forwardedRef,\n children,\n ...divProps\n}: PresenceProps): JSX.Element | null {\n const { phase, ref, mounted, enter } = usePresence({\n show,\n mode,\n enter: enterOption,\n exitDuration,\n reducedMotion,\n });\n\n useImperativeHandle(forwardedRef, () => ref.current as HTMLDivElement);\n\n if (!mounted && mode !== 'reveal') return null;\n\n return (\n <div\n {...divProps}\n ref={ref as React.RefObject<HTMLDivElement | null>}\n data-phase={phase}\n data-enter={enter === 'animate' ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n","import {\n useRef,\n type ComponentProps,\n type JSX,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { useSight } from '../use-sight';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface WhenVisibleProps extends ComponentProps<'div'> {\n /** IntersectionObserver rootMargin. Default `'200px'` (generous headroom for preloading). */\n rootMargin?: string;\n /** IntersectionObserver threshold. */\n threshold?: number | number[];\n /** IntersectionObserver root element. */\n root?: Element | null;\n /** Content shown while awaiting intersection. Sentinel div is always rendered for IO. */\n fallback?: ReactNode;\n /** Forwarded to the rendered div in both states (the sentinel before visible, the entered div after). Populated at mount. */\n ref?: Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// WhenVisible\n// ---------------------------------------------------------------------------\n\n/**\n * Mounts children when the element enters the viewport. One-shot (once\n * triggered, stays mounted).\n *\n * Enter animation uses CSS `@starting-style`, gated by `data-enter=\"animate\"`.\n * Reduced motion is automatic: the attribute is not stamped when the user\n * prefers reduced motion.\n *\n * @example\n * <WhenVisible rootMargin=\"200px\" className=\"transition-opacity data-[enter=animate]:starting:opacity-0\">\n * <HeavyChart />\n * </WhenVisible>\n */\nexport function WhenVisible({\n rootMargin = '200px',\n threshold,\n root,\n fallback,\n children,\n ref: forwardedRef,\n ...divProps\n}: WhenVisibleProps): JSX.Element {\n const sentinelRef = useRef<HTMLDivElement>(null);\n const { phase } = useSight({\n ref: sentinelRef,\n observe: 'once',\n rootMargin,\n threshold,\n root,\n });\n\n const setRef = (node: HTMLDivElement | null): void => {\n sentinelRef.current = node;\n assignRef(forwardedRef, node);\n };\n\n if (phase !== 'visible') {\n return (\n <div ref={setRef} {...divProps}>\n {fallback}\n </div>\n );\n }\n\n const motionAllowed = !prefersReducedMotion();\n\n return (\n <div\n {...divProps}\n ref={setRef}\n data-phase=\"entered\"\n data-enter={motionAllowed ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n\nfunction assignRef(\n ref: Ref<HTMLDivElement> | undefined,\n node: HTMLDivElement | null,\n): void {\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n}\n","import type { ComponentProps, JSX, ReactNode, Ref } from 'react';\n\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { useIdle } from '../use-idle';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface WhenIdleProps extends ComponentProps<'div'> {\n /** Max ms to wait before mounting even if no idle period occurs. */\n timeout?: number;\n /** Content shown until the browser is idle. */\n fallback?: ReactNode;\n ref?: Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// WhenIdle\n// ---------------------------------------------------------------------------\n\n/**\n * Mounts children once the browser is idle after first paint. One-shot (once\n * mounted, stays mounted). Use it to defer non-critical UI off the critical path.\n *\n * Children are not server-rendered (idle never fires during SSR), so reserve\n * this for non-critical content. For viewport-gated mounting use `WhenVisible`;\n * to keep content in the DOM but skip painting use `Defer`.\n *\n * Enter animation uses CSS `@starting-style`, gated by `data-enter=\"animate\"`.\n * Reduced motion is automatic: the attribute is not stamped when the user\n * prefers reduced motion.\n *\n * @example\n * <WhenIdle fallback={<Skeleton />}>\n * <SecondaryPanel />\n * </WhenIdle>\n */\nexport function WhenIdle({\n timeout,\n fallback,\n children,\n ref: forwardedRef,\n ...divProps\n}: WhenIdleProps): JSX.Element {\n const idle = useIdle({ timeout });\n\n if (!idle) {\n return <div {...divProps}>{fallback}</div>;\n }\n\n const motionAllowed = !prefersReducedMotion();\n\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n data-phase=\"entered\"\n data-enter={motionAllowed ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n","import type { ComponentProps, CSSProperties, JSX, Ref } from 'react';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface DeferProps extends Omit<ComponentProps<'div'>, 'style'> {\n /**\n * Approximate size reserved before first paint (any CSS length, e.g. `'800px'`).\n * After the first render the browser remembers the real size. Default `'1000px'`.\n */\n estimatedHeight?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// Defer\n// ---------------------------------------------------------------------------\n\n/**\n * Skip the browser's rendering work (style, layout, paint) for off-screen\n * content via `content-visibility: auto`. Pure CSS, no JS, no observer.\n *\n * Children stay in the DOM and are server-rendered (SEO- and CLS-safe).\n * `contain-intrinsic-size: auto <estimatedHeight>` reserves space so the\n * scrollbar does not jump. Defers rendering only, not hydration or mounting.\n *\n * The render-skip styles are encapsulated and cannot be overridden. There is\n * no `style` prop. Style the wrapper with `className`; this keeps the\n * no-layout-shift guarantee intact.\n *\n * @example\n * <Defer estimatedHeight=\"600px\" className=\"my-section\">\n * <ArticleSection />\n * </Defer>\n *\n * @remarks\n * Animations inside a `Defer` keep running while paint is skipped. phase loops\n * self-pause off-screen on their own; for raw rAF/interval work, gate it with\n * `useRenderState`.\n */\nexport function Defer({\n estimatedHeight = '1000px',\n children,\n ref,\n ...divProps\n}: DeferProps): JSX.Element {\n const deferStyle: CSSProperties = {\n contentVisibility: 'auto',\n containIntrinsicSize: `auto ${estimatedHeight}`,\n };\n\n return (\n <div {...divProps} ref={ref} style={deferStyle}>\n {children}\n </div>\n );\n}\n","import {\n createContext,\n use,\n useState,\n useEffect,\n useMemo,\n useCallback,\n useImperativeHandle,\n type ComponentProps,\n type JSX,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { missingContextError } from '../../core/_internal/errors';\nimport { usePresence } from '../use-presence';\nimport { useSyncedRef } from '../use-synced-ref';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface SwapContext {\n current: string;\n active: string;\n exitDuration: number;\n /** 'instant' on first mount (prevents CLS), 'animate' on subsequent swaps. */\n enter: 'animate' | 'instant';\n onExited: (id: string) => void;\n}\n\nconst SwapCtx = createContext<SwapContext | null>(null);\n\n// ---------------------------------------------------------------------------\n// Swap\n// ---------------------------------------------------------------------------\n\nexport interface SwapProps extends ComponentProps<'div'> {\n active: string;\n exitDuration?: number;\n children: ReactNode;\n}\n\n/**\n * Coordinated exit-then-enter transitions for N states.\n * Only one state is entering or exiting at a time (no overlap).\n *\n * The current state fully exits before the new state enters. Rapid changes\n * (A->B->C during A's exit) skip intermediate states and jump to the latest.\n *\n * @example\n * <Swap active={success ? 'success' : 'form'}>\n * <Swap.State id=\"form\" className=\"transition-all data-[phase=exiting]:opacity-0\">\n * <Form />\n * </Swap.State>\n * <Swap.State id=\"success\" className=\"transition-all data-[enter=animate]:starting:opacity-0\">\n * <SuccessMessage />\n * </Swap.State>\n * </Swap>\n */\nfunction SwapRoot({\n active,\n exitDuration = 5000,\n children,\n ...divProps\n}: SwapProps): JSX.Element {\n const [current, setCurrent] = useState(active);\n const [hasSwapped, setHasSwapped] = useState(false);\n const activeRef = useSyncedRef(active);\n\n const onExited = useCallback(\n (id: string): void => {\n setHasSwapped(true);\n setCurrent((cur) => (cur === id ? activeRef.current : cur));\n },\n [activeRef],\n );\n\n const enter: 'animate' | 'instant' = hasSwapped ? 'animate' : 'instant';\n\n const ctx: SwapContext = useMemo(\n () => ({ current, active, exitDuration, enter, onExited }),\n [current, active, exitDuration, enter, onExited],\n );\n\n return (\n <SwapCtx.Provider value={ctx}>\n <div {...divProps}>{children}</div>\n </SwapCtx.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Swap.State\n// ---------------------------------------------------------------------------\n\nexport interface SwapStateProps extends ComponentProps<'div'> {\n id: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nfunction SwapState({\n id,\n ref: forwardedRef,\n children,\n ...divProps\n}: SwapStateProps): JSX.Element | null {\n const ctx = use(SwapCtx);\n if (!ctx) missingContextError('Swap.State', 'Swap');\n\n const isCurrent: boolean = ctx.current === id;\n const show: boolean = isCurrent && ctx.active === id;\n\n const { phase, ref, mounted, enter } = usePresence({\n show,\n mode: 'mount',\n enter: ctx.enter,\n exitDuration: ctx.exitDuration,\n });\n\n useImperativeHandle(forwardedRef, () => ref.current as HTMLDivElement);\n\n useEffect(() => {\n if (isCurrent && !show && phase === 'exited') {\n ctx.onExited(id);\n }\n }, [isCurrent, show, phase, id, ctx]);\n\n if (!isCurrent || !mounted) return null;\n\n return (\n <div\n {...divProps}\n ref={ref as React.RefObject<HTMLDivElement | null>}\n data-phase={phase}\n data-enter={enter === 'animate' ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Compound component export\n// ---------------------------------------------------------------------------\n\nexport const Swap: typeof SwapRoot & { State: typeof SwapState } =\n Object.assign(SwapRoot, { State: SwapState });\n"],"mappings":";;;;;;;;;;;;;;;;AAYA,SAAgB,aAAgB,OAAwB;AAGtD;CAEA,MAAM,MAAM,OAAO,MAAM;AACzB,KAAI,UAAU;AACd,QAAO;;;;;;;;;;;;;ACRT,SAAgB,kBACd,UACsB;AAGtB;CAEA,MAAM,cAAc,OAAO,SAAS;AACpC,aAAY,UAAU;AAKtB,QAAO,aAAa,GAAG,SAAe,YAAY,QAAQ,GAAG,KAAK,EAAE,EAAE,CAAC;;;;;;;;ACbzE,SAAgB,eACd,UACA,aACgB;AAChB,KAAI,aAAa,QAAS,QAAO,EAAE,UAAU,SAAS;AACtD,KAAI,aAAa,SAAU,QAAO,EAAE,UAAU,UAAU;AACxD,QAAO;EAAE,UAAU;EAAY;EAAa;;;;ACwC9C,MAAMA,kBAA2B;CAC/B,OAAO;CACP,aAAa;CACb,SAAS;CACT,eAAe,KAAA;CAChB;;;;;;;;;;;;AAaD,SAAgB,QACd,SACkB;CAClB,MAAM,EACJ,KACA,UAAU,MACV,eACA,UACA,aACA,wBACE;CACJ,MAAM,YAAY,aAAa,QAAQ,OAAO;CAE9C,MAAM,cAAc,OAAiB,KAAK;CAC1C,MAAM,MAA2B,QAAQ,OAAO;CAEhD,MAAM,CAAC,OAAO,YAAY,SAAoBA,gBAAc;CAE5D,MAAM,UAAU,OAA6C,KAAK;AAElE,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,WAAW,CAAC,SAAS;AACxB,YAASA,gBAAc;AACvB;;EAGF,MAAM,OAAO,WAAW;GACtB;GACA,SAAS,UAAU,UAAU,QAAQ,MAAM;GAC3C;GACA;GACA;GACA,GAAG,eAAe,UAAU,YAAY;GACxC,gBAAgB,OAAO,WAAW;IAIhC,MAAM,UAAU,QAAQ;AACxB,aAAS;KACP;KACA,aAAa;KACb,SAAS,SAAS,WAAW;KAC7B,eAAe,SAAS;KACzB,CAAC;;GAEL,CAAC;AACF,UAAQ,UAAU;AAElB,eAAa;AACX,QAAK,MAAM;AACX,WAAQ,UAAU;;IAGnB;EAAC;EAAS;EAAK;EAAe;EAAU;EAAY,CAAC;AAExD,QAAO;EAAE;EAAK,GAAG;EAAO;;;;ACxF1B,MAAMC,kBAAgC;CACpC,OAAO;CACP,aAAa;CACd;;;;;;;;;;;;;;;;;;;;AAqBD,SAAgB,aACd,SACuB;CACvB,MAAM,EAAE,eAAe,qBAAqB,UAAU,SAAS,WAAW,EAAE;CAC5E,MAAM,SAAS,SAAS,UAAU;CAClC,MAAM,mBAAmB,aAAa,SAAS,cAAc;CAE7D,MAAM,cAAc,OAAiB,KAAK;CAC1C,MAAM,MAA2B,SAAS,OAAO;CAEjD,MAAM,CAAC,OAAO,YAAY,SAAyBA,gBAAc;CACjE,MAAM,eAAe,OAAyB,KAAK;AAEnD,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,WAAW,CAAC,SAAS;AACxB,YAASA,gBAAc;AACvB;;EAGF,MAAM,YAAY,gBAAgB;GAChC;GACA;GACA;GACA,gBAAgB,OAAO,gBAAgB;AACrC,qBAAiB,UAAU,OAAO,YAAY;AAC9C,aAAS;KAAE;KAAO;KAAa,CAAC;;GAEnC,CAAC;AACF,eAAa,UAAU;AAGvB,MAAI,OAAQ,WAAU,OAAO;AAE7B,eAAa;AACX,aAAU,MAAM;AAChB,gBAAa,UAAU;;IAGxB,CAAC,SAAS,cAAc,CAAC;AAG5B,iBAAgB;EACd,MAAM,YAAY,aAAa;AAC/B,MAAI,CAAC,UAAW;AAChB,MAAI,OAAQ,WAAU,OAAO;MACxB,WAAU,QAAQ;IACtB,CAAC,OAAO,CAAC;AAEZ,QAAO;EAAE;EAAK,GAAG;EAAO,UAAU,MAAM,UAAU;EAAU;;;;;;;;;;AC1G9D,SAAgB,sBAA8B;CAC5C,MAAM,CAAC,KAAK,UAAU,SAAS,EAAE;AAEjC,iBAAgB;AACd,SAAO,SAAS,CAAC;AACjB,SAAO,aAAa,OAAO;IAC1B,EAAE,CAAC;AAEN,QAAO;;;;;;;;;;;;;ACFT,SAAgB,cAAc,OAAwB;CACpD,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAE7C,iBAAgB;AACd,aAAW,eAAe,MAAM,CAAC;AACjC,SAAO,oBAAoB,OAAO,WAAW;IAC5C,CAAC,MAAM,CAAC;AAEX,QAAO;;;;;;;;;;ACfT,SAAgB,0BAAmC;AACjD,QAAO,cAAc,qBAAqB;;;;AC4C5C,MAAMC,kBAA4B;CAChC,OAAO;CACP,aAAa;CACd;AAwBD,SAAgB,SACd,SACwD;CACxD,MAAM,CAAC,OAAO,YAAY,SAAqBA,gBAAc;CAC7D,MAAM,UAAU,SAAS,WAAW;CACpC,MAAM,WAAW,OAAmB,UAAU;CAC9C,MAAM,iBAAiB,OAAoB,UAAU;CACrD,MAAM,wBAAwB,aAAa,SAAS,mBAAmB;CAEvE,MAAM,cAAc,OAAiB,KAAK;CAC1C,MAAM,MAA2B,SAAS,OAAO;AAEjD,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,QAAS;EAEd,IAAI,SAAS;EAEb,MAAM,QAAQ,YAAY;GACxB;GACA,qBAAqB;IACnB,MAAM,SAAS;IACf,YAAY,SAAS;IACrB,WAAW,SAAS;IACrB;GACD,gBAAgB,OAAO,WAAW;AAChC,QAAI,OAAQ;AAEZ,aAAS,UAAU;AACnB,mBAAe,UAAU;AAEzB,QAAI,sBAAsB,QACxB,uBAAsB,QAAQ,OAAO,OAAO;QAE5C,UAAS;KAAE;KAAO,aAAa;KAAQ,CAAC;AAG1C,QAAI,YAAY,UAAU,UAAU,WAAW;AAC7C,cAAS;AACT,WAAM,MAAM;;;GAGjB,CAAC;AAEF,eAAa,MAAM,MAAM;IAExB,CAAC,QAAQ,CAAC;AAEb,QAAO;EAAE;EAAK,GAAG;EAAO;EAAU;EAAgB;;;;AC/HpD,IAAI,WAAkC;AACtC,MAAM,4BAAY,IAAI,KAA0B;;;;;;;;AAShD,SAAgB,cACd,SACA,UACA,KACY;AACZ,WAAU,IAAI,SAAS,SAAS;AAChC,cAAa,CAAC,QAAQ,SAAS,MAAM,EAAE,KAAK,GAAG,KAAA,EAAU;CAEzD,IAAI,WAAW;AAEf,cAAa;AACX,MAAI,SAAU;AACd,aAAW;AAIX,MAAI,UAAU,IAAI,QAAQ,KAAK,UAAU;AACvC,aAAU,OAAO,QAAQ;AACzB,aAAU,UAAU,QAAQ;;;;;AAUlC,SAAS,cAA8B;AACrC,KAAI,CAAC,SACH,YAAW,IAAI,gBAAgB,YAAY;AACzC,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,KAA6B,UAAU,IAAI,MAAM,OAAO;AAC9D,OAAI,GAAI,IAAG,MAAM;;GAEnB;AAEJ,QAAO;;;;ACoBT,SAAgB,QACd,SACsD;CACtD,MAAM,CAAC,MAAM,WAAW,SAAsB,KAAK;CACnD,MAAM,UAAU,OAAoB,KAAK;CACzC,MAAM,YAAY,OAAsB,KAAK;CAC7C,MAAM,aAAa,OAAsB,KAAK;CAC9C,MAAM,cAAc,aAAa,SAAS,SAAS;CAEnD,MAAM,cAAc,OAAiB,KAAK;CAC1C,MAAM,MAA2B,SAAS,OAAO;CACjD,MAAM,YAAsD,SAAS;AAErE,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,QAAS;AA+Bd,SA7B8B,cAC5B,UACC,UAAU;GACT,MAAM,WACJ,cAAc,eACV,MAAM,cAAc,KACpB,MAAM,eAAe;AAC3B,OAAI,CAAC,SAAU;GAEf,MAAM,QAAgB,SAAS;GAC/B,MAAM,SAAiB,SAAS;AAEhC,OAAI,UAAU,UAAU,WAAW,WAAW,WAAW,QACvD;AACF,aAAU,UAAU;AACpB,cAAW,UAAU;GAErB,MAAM,OAAa;IAAE;IAAO;IAAQ;AACpC,WAAQ,UAAU;AAElB,OAAI,YAAY,QACd,aAAY,QAAQ,KAAK;OAEzB,SAAQ,KAAK;KAGjB,UACD;IAIA,CAAC,UAAU,CAAC;AAEf,QAAO;EAAE;EAAK;EAAM;EAAS;;;;;;;;;;;;;;;AC3E/B,SAAgB,kBACd,YACA,SAC4B;CAC5B,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAC7C,MAAM,aAAa,OAAO,MAAM;CAEhC,MAAM,cAAc,OAAiB,KAAK;CAC1C,MAAM,MAA2B,SAAS,OAAO;CAEjD,MAAM,EAAE,UAAU,UAAU,WAAW,cAAc;AAErD,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,QAAS;AAyBd,SAvB8B,cAAc,UAAU,UAAU;GAC9D,MAAM,MAAM,MAAM,eAAe;AACjC,OAAI,CAAC,IAAK;GAEV,MAAM,QAAgB,IAAI;GAC1B,MAAM,SAAiB,IAAI;GAE3B,MAAM,aAAsB,mBAC1B,OACA,QACA,UACA,UACA,WACA,UACD;AAGD,OAAI,eAAe,WAAW,SAAS;AACrC,eAAW,UAAU;AACrB,eAAW,WAAW;;IAExB;IAID;EAAC;EAAU;EAAU;EAAW;EAAU,CAAC;AAE9C,QAAO;EAAE;EAAK;EAAS;;AAOzB,SAAS,mBACP,OACA,QACA,UACA,UACA,WACA,WACS;AACT,KAAI,aAAa,KAAA,KAAa,QAAQ,SAAU,QAAO;AACvD,KAAI,aAAa,KAAA,KAAa,QAAQ,SAAU,QAAO;AACvD,KAAI,cAAc,KAAA,KAAa,SAAS,UAAW,QAAO;AAC1D,KAAI,cAAc,KAAA,KAAa,SAAS,UAAW,QAAO;AAC1D,QAAO;;;;AC5BT,SAAgB,kBACd,SAC0E;CAC1E,MAAM,CAAC,UAAU,eAAe,SAAS,EAAE;CAC3C,MAAM,cAAc,OAAO,EAAE;CAC7B,MAAM,QAA4B,SAAS;CAC3C,MAAM,aAAiC,SAAS;CAChD,MAAM,gBAAgB,aAAa,SAAS,WAAW;CAEvD,MAAM,cAAc,OAAiB,KAAK;CAC1C,MAAM,MAA2B,SAAS,OAAO;AAEjD,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,QAAS;EAEd,MAAM,iBAAiB,qBAAqB;GAC1C;GACA,aAAa,UAAkB;AAC7B,gBAAY,UAAU;AAEtB,QAAI,cAAc,QAChB,eAAc,QAAQ,MAAM;QAE5B,aAAY,MAAM;;GAGtB;GACA,MAAM,SAAS;GACf;GACD,CAAC;AAEF,eAAa,eAAe,MAAM;IAEjC,CAAC,OAAO,WAAW,CAAC;AAEvB,QAAO;EAAE;EAAK;EAAU;EAAa;;;;;;;;;;;;;;;;;;;;;;AC1FvC,SAAgB,eACd,KACa;CACb,MAAM,CAAC,OAAO,YAAY,SAAsB,WAAW;AAE3D,iBAAgB;EACd,MAAM,UAA0B,IAAI;AACpC,MAAI,CAAC,QAAS;EAEd,MAAM,SAAS,kBAAkB;GAC/B;GACA,eAAe;GAChB,CAAC;AAEF,eAAa,OAAO,MAAM;IAEzB,EAAE,CAAC;AAEN,QAAO;;;;;;;;;;;;;;AC1BT,SAAgB,QAAQ,SAAgC;CACtD,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;CACvC,MAAM,UAAU,SAAS;AAEzB,iBAAgB;AAEd,SAD2B,eAAe,QAAQ,KAAK,EAAE,EAAE,SAAS,CAAC;IAEpE,CAAC,QAAQ,CAAC;AAEb,QAAO;;;;;;;;;;;;;;;;ACNT,SAAgB,YAAY,UAAsB,SAA6B;CAC7E,MAAM,cAAc,aAAa,SAAS;CAC1C,MAAM,UAAU,SAAS;AAEzB,iBAAgB;AAId,SAH2B,eAAe,YAAY,SAAS,EAAE,EAC/D,SACD,CAAC;IAGD,CAAC,QAAQ,CAAC;;;;ACmCf,MAAM,gBAAkD;CACtD,OAAO;CACP,aAAa;CACb,SAAS;CACT,eAAe,KAAA;CAChB;;;;;;;;;;;;;;;AAgBD,SAAgB,UAAU,SAA4C;CACpE,MAAM,EACJ,cACA,WACA,KACA,UAAU,MACV,eACA,UACA,gBACE;CACJ,MAAM,UAAU,aAAa,QAAQ,KAAK;CAE1C,MAAM,CAAC,OAAO,YAAY,SAAS,cAAc;CACjD,MAAM,CAAC,cAAc,mBAAmB,SAAS,EAAE;CAEnD,MAAM,SAAS,OAAwC,KAAK;CAC5D,MAAM,UAAU,OAAa;EAAE,OAAO;EAAG,QAAQ;EAAG,CAAC;CACrD,MAAM,aAAa,aAAa,MAAM,QAAQ;AAE9C,iBAAgB;EACd,MAAM,YAA4B,aAAa;EAC/C,MAAM,WAAqC,UAAU;AACrD,MAAI,CAAC,aAAa,CAAC,YAAY,CAAC,QAAS;EACzC,MAAM,SAA4B;EAElC,MAAM,aAA8C,OAAO,WAAW,KAAK;AAC3E,MAAI,CAAC,WAAY;AACjB,SAAO,UAAU;EAEjB,IAAI,MAAc,SAAS;EAC3B,IAAI,cAAc;EAIlB,SAAS,UACP,OACA,QACA,aACM;AACN,WAAQ,UAAU;IAAE;IAAO;IAAQ;GACnC,MAAM,aAAsB,WAAW,YAAY;GAEnD,IAAI;GACJ,IAAI;AAEJ,OAAI,YAAY;AACd,kBAAc;AACd,mBAAe;cACN,aAAa;AACtB,kBAAc,YAAY;AAC1B,mBAAe,YAAY;UACtB;AACL,kBAAc,QAAQ;AACtB,mBAAe,SAAS;;AAG1B,UAAO,QAAQ;AACf,UAAO,SAAS;AAChB,UAAO,MAAM,QAAQ,QAAQ;AAC7B,UAAO,MAAM,SAAS,SAAS;GAE/B,MAAM,eAAuB,aAAa,IAAI;AAC9C,UAAO,SAAS,aAAa,cAAc,GAAG,GAAG,cAAc,GAAG,EAAE;;EAKtE,MAAM,WAAuB,cAAc,WAAW;AACpD,SAAM;AACN,aAAU,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,OAAO;IACxD;EAIF,MAAM,YAAwB,cAAc,YAAY,UAAU;GAChE,MAAM,MAAM,MAAM,eAAe;AACjC,OAAI,CAAC,IAAK;GACV,MAAM,cACJ,MAAM,4BAA4B;AACpC,aAAU,IAAI,YAAY,IAAI,WAAW,YAAY;IACrD;EAIF,SAAS,cAAc,OAAoB;AACzC,SAAM,gBAAgB;AACtB,iBAAc;;EAGhB,SAAS,oBAA0B;GACjC,MAAM,cACJ,OAAO,WAAW,KAAK;AACzB,OAAI,CAAC,YAAa;AAClB,UAAO,UAAU;AACjB,iBAAc;AACd,aAAU,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,OAAO;;AAG1D,SAAO,iBAAiB,eAAe,cAAc;AACrD,SAAO,iBAAiB,mBAAmB,kBAAkB;EAI7D,IAAI,eAAqD;EAEzD,MAAM,OAAO,WAAW;GACtB,SAAS;GACT;GACA;GACA,GAAG,eAAe,UAAU,YAAY;GACxC,SAAS,UAAU;AACjB,QAAI,eAAe,CAAC,OAAO,QAAS;AACpC,YAAQ,QAAQ,OAAO,SAAS,OAAO,QAAQ,QAAQ;;GAEzD,gBAAgB,OAAO,WAAW;AAChC,aAAS;KACP;KACA,aAAa;KACb,SAAS,cAAc,WAAW;KAClC,eAAe,cAAc;KAC9B,CAAC;;GAEL,CAAC;AACF,iBAAe;EAIf,SAAS,WAAiB;AACxB,QAAK,MAAM;AACX,kBAAe;AACf,cAAW;AACX,aAAU;AACV,UAAO,oBAAoB,eAAe,cAAc;AACxD,UAAO,oBAAoB,mBAAmB,kBAAkB;;AAGlE,SAAO;IAEN;EAAC;EAAS;EAAK;EAAe;EAAU;EAAa;EAAa,CAAC;AAQtE,QAAO;EAAE,SAJO,kBAAkB;AAChC,oBAAiB,MAAM,IAAI,EAAE;KAC5B,EAAE,CAAC;EAEY,GAAG;EAAO;;;;;;;;;;;;;;;;;;;;ACtM9B,SAAgB,SAAS,SAAkC;CACzD,MAAM,EACJ,QACA,WAAW,KACX,QAAQ,GACR,SAAS,cACT,UAAU,MACV,gBAAgB,eACd;CAEJ,MAAM,CAAC,OAAO,YAAY,SAAS,OAAO;CAE1C,MAAM,UAAU,OAAO,OAAO;CAC9B,MAAM,aAAa,OAAO,OAAO;CACjC,MAAM,gBAAgB,OAAO,KAAK;AAElC,iBAAgB;AACd,MAAI,CAAC,OAAO,SAAS,SAAS,IAAI,YAAY,EAC5C,sBAAqB,YAAY,SAAS;AAI5C,MAAI,cAAc,SAAS;AACzB,iBAAc,UAAU;AACxB,gBAAa;IAAE;IAAQ;IAAS;IAAY;IAAU,CAAC;AACvD;;AAIF,MAAI,CAAC,WAAY,kBAAkB,YAAY,sBAAsB,EAAG;AACtE,gBAAa;IAAE;IAAQ;IAAS;IAAY;IAAU,CAAC;AACvD;;EAIF,MAAM,OAAe,WAAW;AAChC,MAAI,SAAS,OAAQ;EAErB,IAAI;EACJ,IAAI,YAA2B;EAE/B,SAAS,KAAK,KAAmB;AAC/B,OAAI,cAAc,KAAM,aAAY;GACpC,MAAM,UAAkB,MAAM,YAAY;AAG1C,OAAI,UAAU,GAAG;AACf,YAAQ,sBAAsB,KAAK;AACnC;;GAGF,MAAM,WAAmB,QAAQ,UAAU,SAAS;GACpD,MAAM,UAAkB,QAAQ,SAAS,QAAQ,OAAO,SAAS;AACjE,cAAW,UAAU;AACrB,YAAS,QAAQ;AAEjB,OAAI,WAAW,EACb,SAAQ,sBAAsB,KAAK;OAEnC,SAAQ,UAAU;;AAItB,UAAQ,sBAAsB,KAAK;AAEnC,eAAa;AACX,wBAAqB,MAAM;AAE3B,WAAQ,UAAU,WAAW;;IAG9B;EAAC;EAAQ;EAAU;EAAO;EAAS;EAAc,CAAC;AAErD,QAAO;;AAcT,SAAS,aAAa,SAAoC;CACxD,MAAM,EAAE,QAAQ,SAAS,YAAY,aAAa;AAClD,SAAQ,UAAU;AAClB,YAAW,UAAU;AACrB,UAAS,OAAO;;;;;;;;ACjHlB,SAAgB,gBACd,QACA,MACM;CACN,MAAM,YAAY,OAAO,MAAM;AAE/B,iBAAgB;AACd,MAAI,CAAC,UAAU,SAAS;AACtB,aAAU,UAAU;AACpB;;AAEF,SAAO,QAAQ;IAEd,KAAK;;;;;;;;;;;;;;;;;;;AC0CV,SAAgB,YAAY,SAAgD;CAC1E,MAAM,EACJ,MACA,OAAO,SACP,OAAO,cAAc,WACrB,eAAe,KACf,gBAAgB,cACd;CAEJ,MAAM,MAAM,OAAuB,KAAK;CAIxC,MAAM,CAAC,OAAO,YAAY,SAFU,OAAO,YAAY,OAEQ;CAC/D,MAAM,CAAC,QAAQ,aAAa,SAAyB,UAAU;CAE/D,MAAM,eAAe,OAA6C,KAAK;CACvE,MAAM,iBAAiB,OAA4B,KAAK;CAExD,MAAM,cAAc,kBAAkB;AACpC,MAAI,aAAa,YAAY,MAAM;AACjC,gBAAa,aAAa,QAAQ;AAClC,gBAAa,UAAU;;AAEzB,MAAI,eAAe,SAAS;AAC1B,kBAAe,SAAS;AACxB,kBAAe,UAAU;;IAE1B,EAAE,CAAC;AAEN,uBAAsB,aAAa,EAAE,CAAC,YAAY,CAAC;AAEnD,uBAAsB;AACpB,eAAa;AAEb,MAAI,KACF,WAAU,SAAS;AACjB,aAAU,SAAS,YAAY,gBAAgB,OAAO;AACtD,UAAO;IACP;WAGA,kBAAkB,aAAa,sBAAsB,EAE9B;AAEvB,YADkC,SAAS,WAAW,SAAS,SAC3C;AACpB,aAAU,gBAAgB;QAE1B,YACE,KACA,MACA,cACA,UACA,WACA,aACA,cACA,eACD;IAGJ,CAAC,KAAK,CAAC;CAEV,MAAM,UAAmB,UAAU,UAAU,UAAU;CAGvD,MAAM,iBAAiB,EADF,WAAW,aACS,gBAAgB;CACzD,MAAM,gBAAgB,kBAAkB,YAAY,CAAC,sBAAsB;AAI3E,QAAO;EAAE;EAAO,aAAa;EAAQ;EAAS;EAAK,OAFjD,kBAAkB,gBAAgB,YAAY;EAEU;;AAO5D,SAAS,WACP,KACA,MACA,cACA,UAGA,WACA,aACA,cACA,gBACM;AACN,UAAS,UAAU;AACnB,WAAU,OAAO;CAEjB,MAAM,aAA4B,SAAS,WAAW,SAAS;CAC/D,MAAM,UAA0B,IAAI;CAEpC,SAAS,eAAqB;AAC5B,eAAa;AACb,YAAU,YAAY;AACpB,OAAI,YAAY,UAAW,QAAO;AAClC,aAAU,gBAAgB;AAC1B,UAAO;IACP;;CAGJ,SAAS,UAAgB;AACvB,MAAI,SAAS;AACX,WAAQ,oBAAoB,iBAAiB,aAAa;AAC1D,WAAQ,oBAAoB,gBAAgB,aAAa;;AAE3D,MAAI,aAAa,YAAY,MAAM;AACjC,gBAAa,aAAa,QAAQ;AAClC,gBAAa,UAAU;;AAEzB,iBAAe,UAAU;;AAG3B,gBAAe,UAAU;AAEzB,KAAI,SAAS;AACX,UAAQ,iBAAiB,iBAAiB,cAAc,EAAE,MAAM,MAAM,CAAC;AACvE,UAAQ,iBAAiB,gBAAgB,cAAc,EAAE,MAAM,MAAM,CAAC;;AAGxE,cAAa,UAAU,WAAW,cAAc,aAAa;;;;;;;;;;;;;;;;;;AC3J/D,SAAgB,SAAS,EACvB,MACA,MACA,OAAO,aACP,cACA,eACA,KAAK,cACL,UACA,GAAG,YACiC;CACpC,MAAM,EAAE,OAAO,KAAK,SAAS,UAAU,YAAY;EACjD;EACA;EACA,OAAO;EACP;EACA;EACD,CAAC;AAEF,qBAAoB,oBAAoB,IAAI,QAA0B;AAEtE,KAAI,CAAC,WAAW,SAAS,SAAU,QAAO;AAE1C,QACE,oBAAC,OAAD;EACE,GAAI;EACC;EACL,cAAY;EACZ,cAAY,UAAU,YAAY,YAAY,KAAA;EAE7C;EACG,CAAA;;;;;;;;;;;;;;;;;ACpBV,SAAgB,YAAY,EAC1B,aAAa,SACb,WACA,MACA,UACA,UACA,KAAK,cACL,GAAG,YAC6B;CAChC,MAAM,cAAc,OAAuB,KAAK;CAChD,MAAM,EAAE,UAAU,SAAS;EACzB,KAAK;EACL,SAAS;EACT;EACA;EACA;EACD,CAAC;CAEF,MAAM,UAAU,SAAsC;AACpD,cAAY,UAAU;AACtB,YAAU,cAAc,KAAK;;AAG/B,KAAI,UAAU,UACZ,QACE,oBAAC,OAAD;EAAK,KAAK;EAAQ,GAAI;YACnB;EACG,CAAA;CAIV,MAAM,gBAAgB,CAAC,sBAAsB;AAE7C,QACE,oBAAC,OAAD;EACE,GAAI;EACJ,KAAK;EACL,cAAW;EACX,cAAY,gBAAgB,YAAY,KAAA;EAEvC;EACG,CAAA;;AAIV,SAAS,UACP,KACA,MACM;AACN,KAAI,OAAO,QAAQ,WACjB,KAAI,KAAK;UACA,IACT,KAAI,UAAU;;;;;;;;;;;;;;;;;;;;;AC3DlB,SAAgB,SAAS,EACvB,SACA,UACA,UACA,KAAK,cACL,GAAG,YAC0B;AAG7B,KAAI,CAFS,QAAQ,EAAE,SAAS,CAAC,CAG/B,QAAO,oBAAC,OAAD;EAAK,GAAI;YAAW;EAAe,CAAA;CAG5C,MAAM,gBAAgB,CAAC,sBAAsB;AAE7C,QACE,oBAAC,OAAD;EACE,GAAI;EACJ,KAAK;EACL,cAAW;EACX,cAAY,gBAAgB,YAAY,KAAA;EAEvC;EACG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBV,SAAgB,MAAM,EACpB,kBAAkB,UAClB,UACA,KACA,GAAG,YACuB;CAC1B,MAAM,aAA4B;EAChC,mBAAmB;EACnB,sBAAsB,QAAQ;EAC/B;AAED,QACE,oBAAC,OAAD;EAAK,GAAI;EAAe;EAAK,OAAO;EACjC;EACG,CAAA;;;;ACxBV,MAAM,UAAU,cAAkC,KAAK;;;;;;;;;;;;;;;;;;AA6BvD,SAAS,SAAS,EAChB,QACA,eAAe,KACf,UACA,GAAG,YACsB;CACzB,MAAM,CAAC,SAAS,cAAc,SAAS,OAAO;CAC9C,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CACnD,MAAM,YAAY,aAAa,OAAO;CAEtC,MAAM,WAAW,aACd,OAAqB;AACpB,gBAAc,KAAK;AACnB,cAAY,QAAS,QAAQ,KAAK,UAAU,UAAU,IAAK;IAE7D,CAAC,UAAU,CACZ;CAED,MAAM,QAA+B,aAAa,YAAY;CAE9D,MAAM,MAAmB,eAChB;EAAE;EAAS;EAAQ;EAAc;EAAO;EAAU,GACzD;EAAC;EAAS;EAAQ;EAAc;EAAO;EAAS,CACjD;AAED,QACE,oBAAC,QAAQ,UAAT;EAAkB,OAAO;YACvB,oBAAC,OAAD;GAAK,GAAI;GAAW;GAAe,CAAA;EAClB,CAAA;;AAavB,SAAS,UAAU,EACjB,IACA,KAAK,cACL,UACA,GAAG,YACkC;CACrC,MAAM,MAAM,IAAI,QAAQ;AACxB,KAAI,CAAC,IAAK,qBAAoB,cAAc,OAAO;CAEnD,MAAM,YAAqB,IAAI,YAAY;CAC3C,MAAM,OAAgB,aAAa,IAAI,WAAW;CAElD,MAAM,EAAE,OAAO,KAAK,SAAS,UAAU,YAAY;EACjD;EACA,MAAM;EACN,OAAO,IAAI;EACX,cAAc,IAAI;EACnB,CAAC;AAEF,qBAAoB,oBAAoB,IAAI,QAA0B;AAEtE,iBAAgB;AACd,MAAI,aAAa,CAAC,QAAQ,UAAU,SAClC,KAAI,SAAS,GAAG;IAEjB;EAAC;EAAW;EAAM;EAAO;EAAI;EAAI,CAAC;AAErC,KAAI,CAAC,aAAa,CAAC,QAAS,QAAO;AAEnC,QACE,oBAAC,OAAD;EACE,GAAI;EACC;EACL,cAAY;EACZ,cAAY,UAAU,YAAY,YAAY,KAAA;EAE7C;EACG,CAAA;;AAQV,MAAa,OACX,OAAO,OAAO,UAAU,EAAE,OAAO,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"react.js","names":["INITIAL_STATE","INITIAL_STATE","INITIAL_STATE","INITIAL_STATE"],"sources":["../src/react/use-synced-ref/index.ts","../src/react/use-stable-callback/index.ts","../src/react/_internal/degraded-config/index.ts","../src/react/use-loop/index.ts","../src/react/use-lifecycle/index.ts","../src/react/use-device-pixel-ratio/index.ts","../src/react/use-media/index.ts","../src/react/use-reduced-motion/index.ts","../src/react/use-sight/index.ts","../src/core/_internal/pool/ro-pool.ts","../src/react/use-size/index.ts","../src/react/use-container-query/index.ts","../src/react/use-scroll-progress/index.ts","../src/react/use-render-state/index.ts","../src/react/use-idle/index.ts","../src/react/use-when-idle/index.ts","../src/react/use-canvas/index.ts","../src/react/use-mutation/index.ts","../src/react/use-tween/index.ts","../src/react/_internal/use-update-effect/index.ts","../src/react/use-presence/index.ts","../src/react/presence/index.tsx","../src/react/when-visible/index.tsx","../src/react/when-idle/index.tsx","../src/react/defer/index.tsx","../src/react/swap/index.tsx"],"sourcesContent":["import { useRef, type RefObject } from 'react';\n\n/**\n * Ref whose `.current` is always the latest value, updated synchronously on\n * every render. Readable from any callback or effect without triggering re-render.\n *\n * @example\n * const propsRef = useSyncedRef(props);\n * useEffect(() => {\n * // propsRef.current is always fresh\n * }, []);\n */\nexport function useSyncedRef<T>(value: T): RefObject<T> {\n // Writes ref.current during render — opt out of React Compiler\n // memoization so the write is never skipped. No-op without the compiler.\n 'use no memo';\n\n const ref = useRef(value);\n ref.current = value;\n return ref;\n}\n","import { useRef, useCallback } from 'react';\n\n/**\n * Returns a function with **stable identity** that always calls the latest\n * version of `callback`. Safe in deps arrays and as a prop to `memo()`'d children.\n *\n * @example\n * const handleClick = useStableCallback((e: MouseEvent) => {\n * console.log(latestValue); // always fresh\n * });\n */\nexport function useStableCallback<Args extends unknown[], R>(\n callback: (...args: Args) => R,\n): (...args: Args) => R {\n // Writes callbackRef.current during render — opt out of React Compiler\n // memoization so the write is never skipped. No-op without the compiler.\n 'use no memo';\n\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n // Stable wrapper created once — delegates to the ref on every call.\n // Preserves the exact parameter and return types, no casts required.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback((...args: Args) => callbackRef.current(...args), []);\n}\n","import type { DegradedBehavior } from '../../../core/loop';\n\nexport type DegradedConfig =\n | { degraded?: 'throttle'; degradedFps?: number }\n | { degraded: 'pause' }\n | { degraded: 'ignore' };\n\n/**\n * Map flat `degraded` / `degradedFps` hook options onto the loop's discriminated\n * union. `degradedFps` is only meaningful in `'throttle'` mode.\n */\nexport function degradedConfig(\n degraded: DegradedBehavior | undefined,\n degradedFps: number | undefined,\n): DegradedConfig {\n if (degraded === 'pause') return { degraded: 'pause' };\n if (degraded === 'ignore') return { degraded: 'ignore' };\n return { degraded: 'throttle', degradedFps };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createLoop,\n type LoopPhase,\n type LoopReason,\n type Quality,\n type DegradedBehavior,\n type DegradedReason,\n type ReducedMotionBehavior,\n} from '../../core/loop';\nimport type { FrameState } from '../../core/tick';\nimport { degradedConfig } from '../_internal/degraded-config';\nimport { useSyncedRef } from '../use-synced-ref';\n\n/**\n * Per-frame loop callback. Receives the current frame state. Write to refs or\n * DOM directly. Never call React `setState` here (60 calls/sec = 60\n * re-renders/sec).\n */\nexport type LoopTickFn = (frame: FrameState) => void;\n\nexport interface UseLoopOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to observe. Optional. When omitted, attach the returned `ref`.\n * Pass your own ref to share it or attach it elsewhere.\n */\n ref?: RefObject<T | null>;\n /**\n * Called every frame. Write to refs or DOM directly. Never call React\n * `setState` here (60 calls/sec = 60 re-renders/sec).\n */\n onTick: LoopTickFn;\n fps?: number;\n enabled?: boolean;\n reducedMotion?: ReducedMotionBehavior;\n /** Behavior when quality degrades (window blur, frame-budget). Default `'throttle'`. */\n degraded?: DegradedBehavior;\n /** FPS cap when `degraded` is `'throttle'`. Default `30`. */\n degradedFps?: number;\n intersectionOptions?: IntersectionObserverInit;\n}\n\nexport interface UseLoopResult<T extends Element = HTMLDivElement> {\n /** Attach to the element you want to animate. */\n ref: RefObject<T | null>;\n phase: LoopPhase;\n phaseReason: LoopReason;\n quality: Quality;\n qualityReason: DegradedReason | undefined;\n}\n\ntype LoopState = Omit<UseLoopResult, 'ref'>;\n\n// Disabled or unmounted: the loop isn't created, so it reports `idle` — matching\n// useCanvas and useLifecycle. (Toggling `enabled` tears down and recreates the\n// loop, so \"idle/will start fresh\" is more accurate than \"paused/will resume\".)\nconst INITIAL_STATE: LoopState = {\n phase: 'idle',\n phaseReason: 'initial',\n quality: 'full',\n qualityReason: undefined,\n};\n\n/**\n * Ref-based animation loop that never triggers re-renders from the frame loop.\n *\n * @example\n * const { ref, phase } = useLoop({\n * onTick: (frame) => {\n * ref.current.style.transform = `translateX(${frame.elapsed * 0.1}px)`;\n * },\n * });\n * return <div ref={ref} />;\n */\nexport function useLoop<T extends Element = HTMLDivElement>(\n options: UseLoopOptions<T>,\n): UseLoopResult<T> {\n const {\n fps,\n enabled = true,\n reducedMotion,\n degraded,\n degradedFps,\n intersectionOptions,\n } = options;\n const onTickRef = useSyncedRef(options.onTick);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options.ref ?? internalRef;\n\n const [state, setState] = useState<LoopState>(INITIAL_STATE);\n\n const loopRef = useRef<ReturnType<typeof createLoop> | null>(null);\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element || !enabled) {\n setState(INITIAL_STATE);\n return;\n }\n\n const loop = createLoop({\n element,\n onTick: (frame) => onTickRef.current(frame),\n fps,\n reducedMotion,\n intersectionOptions,\n ...degradedConfig(degraded, degradedFps),\n onPhaseChange: (phase, reason) => {\n // Read from loopRef instead of the local `loop` variable to avoid\n // accessing it before createLoop returns (start:'auto' fires\n // onPhaseChange synchronously during construction).\n const current = loopRef.current;\n setState({\n phase,\n phaseReason: reason,\n quality: current?.quality ?? 'full',\n qualityReason: current?.qualityReason,\n });\n },\n });\n loopRef.current = loop;\n\n return () => {\n loop.stop();\n loopRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, fps, reducedMotion, degraded, degradedFps]);\n\n return { ref, ...state };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createLifecycle,\n type Lifecycle,\n type LifecyclePhase,\n type LifecycleReason,\n type LifecycleReducedMotion,\n} from '../../core/lifecycle';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport interface UseLifecycleOptions<T extends Element = HTMLDivElement> {\n /**\n * Element whose visibility gates the lifecycle. Optional. When omitted, attach\n * the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /** Whether reduced motion pauses the lifecycle. Default `'pause'`. */\n reducedMotion?: LifecycleReducedMotion;\n /** Manually pause regardless of visibility (e.g. a panel opened over the animation). */\n paused?: boolean;\n /** When `false`, the lifecycle is torn down and reports `idle`. Default `true`. */\n enabled?: boolean;\n intersectionOptions?: IntersectionObserverInit;\n /**\n * Synchronous callback fired in the observer/MQL callback, before React\n * schedules a render. Use to post messages to a worker or update a ref\n * without waiting for the React commit.\n */\n onPhaseChange?: (phase: LifecyclePhase, reason: LifecycleReason) => void;\n}\n\nexport interface UseLifecycleResult<T extends Element = HTMLDivElement> {\n /** Attach to the element whose visibility should gate your loop. */\n ref: RefObject<T | null>;\n phase: LifecyclePhase;\n phaseReason: LifecycleReason;\n /** Convenience: `phase === 'active'`. Drive your own render loop off this. */\n isActive: boolean;\n}\n\ntype LifecycleState = Omit<UseLifecycleResult, 'ref' | 'isActive'>;\n\nconst INITIAL_STATE: LifecycleState = {\n phase: 'idle',\n phaseReason: 'initial',\n};\n\n/**\n * React binding for `createLifecycle`. The activation signal for loops you own.\n *\n * Returns `active` / `paused` so a consumer-owned render loop (WebGL, three.js, a\n * Web Worker) can pause when off-screen or under reduced motion. When `phase`\n * should drive the loop for you, use `useLoop` or `useCanvas` instead.\n *\n * @example\n * const { ref, isActive } = useLifecycle();\n * useEffect(() => {\n * if (!isActive) return;\n * const id = requestAnimationFrame(function render() {\n * renderer.render();\n * requestAnimationFrame(render);\n * });\n * return () => cancelAnimationFrame(id);\n * }, [isActive]);\n * return <canvas ref={ref} />;\n */\nexport function useLifecycle<T extends Element = HTMLDivElement>(\n options?: UseLifecycleOptions<T>,\n): UseLifecycleResult<T> {\n const { reducedMotion, intersectionOptions, enabled = true } = options ?? {};\n const paused = options?.paused ?? false;\n const onPhaseChangeRef = useSyncedRef(options?.onPhaseChange);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n const [state, setState] = useState<LifecycleState>(INITIAL_STATE);\n const lifecycleRef = useRef<Lifecycle | null>(null);\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element || !enabled) {\n setState(INITIAL_STATE);\n return;\n }\n\n const lifecycle = createLifecycle({\n element,\n reducedMotion,\n intersectionOptions,\n onPhaseChange: (phase, phaseReason) => {\n onPhaseChangeRef.current?.(phase, phaseReason);\n setState({ phase, phaseReason });\n },\n });\n lifecycleRef.current = lifecycle;\n\n // Apply the manual pause that was requested at mount.\n if (paused) lifecycle.pause();\n\n return () => {\n lifecycle.stop();\n lifecycleRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, reducedMotion]);\n\n // Sync subsequent `paused` changes onto the live lifecycle.\n useEffect(() => {\n const lifecycle = lifecycleRef.current;\n if (!lifecycle) return;\n if (paused) lifecycle.pause();\n else lifecycle.resume();\n }, [paused]);\n\n return { ref, ...state, isActive: state.phase === 'active' };\n}\n","import { useState, useEffect } from 'react';\n\nimport { subscribeDpr, readDpr } from '../../core/_internal/pool/dpr';\n\n/**\n * Reactive devicePixelRatio that updates when the user moves the window\n * between monitors with different DPR values.\n *\n * Returns `1` during SSR and initial hydration, then the live value.\n */\nexport function useDevicePixelRatio(): number {\n const [dpr, setDpr] = useState(1);\n\n useEffect(() => {\n setDpr(readDpr());\n return subscribeDpr(setDpr);\n }, []);\n\n return dpr;\n}\n","import { useState, useEffect } from 'react';\n\nimport {\n subscribeMediaQuery,\n readMediaQuery,\n} from '../../core/_internal/pool/mql-pool';\n\n/**\n * Subscribe to a media query via the shared MQL pool.\n *\n * Returns `false` during SSR and initial hydration render,\n * then the live value from the first `useEffect`.\n *\n * @example\n * const isNarrow = useMediaQuery('(max-width: 600px)');\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n setMatches(readMediaQuery(query));\n return subscribeMediaQuery(query, setMatches);\n }, [query]);\n\n return matches;\n}\n","import { REDUCED_MOTION_QUERY } from '../../core/reduced-motion';\nimport { useMediaQuery } from '../use-media';\n\n/**\n * Reactive boolean that tracks the user's `prefers-reduced-motion` OS setting.\n *\n * Returns `false` during SSR and initial hydration, then the live value.\n * Re-renders only when the preference changes.\n */\nexport function usePrefersReducedMotion(): boolean {\n return useMediaQuery(REDUCED_MOTION_QUERY);\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createSight,\n type SightPhase,\n type SightReason,\n} from '../../core/sight';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport type SightCallback = (\n phase: SightPhase,\n phaseReason: SightReason,\n) => void;\n\nexport interface UseSightOptions<\n T extends Element = HTMLDivElement,\n> extends IntersectionObserverInit {\n /**\n * Element to observe. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /** `'continuous'` keeps observing. `'once'` freezes at `'visible'` after first intersection. */\n observe?: 'continuous' | 'once';\n /**\n * Called on every visibility transition. When provided, `phase` and\n * `phaseReason` stay at initial values and no re-renders occur.\n */\n onVisibilityChange?: SightCallback;\n}\n\nexport interface UseSightReactiveResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n phase: SightPhase;\n phaseReason: SightReason;\n /** Visibility phase via ref. Always current, never triggers re-render. */\n phaseRef: RefObject<SightPhase>;\n /** Phase reason via ref. Always current, never triggers re-render. */\n phaseReasonRef: RefObject<SightReason>;\n}\n\nexport interface UseSightTransientResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n /** Visibility phase via ref. Always current, never triggers re-render. */\n phaseRef: RefObject<SightPhase>;\n /** Phase reason via ref. Always current, never triggers re-render. */\n phaseReasonRef: RefObject<SightReason>;\n}\n\n/** @deprecated Use `UseSightReactiveResult` or `UseSightTransientResult`. */\nexport type UseSightResult<T extends Element = HTMLDivElement> =\n UseSightReactiveResult<T>;\n\ntype SightState = { phase: SightPhase; phaseReason: SightReason };\n\nconst INITIAL_STATE: SightState = {\n phase: 'unknown',\n phaseReason: 'initial',\n};\n\n/**\n * Intersection + document visibility as a phase.\n *\n * Pass `onVisibilityChange` for zero-re-render mode (animation gating,\n * many-element observation). Without it, `phase` and `phaseReason` update\n * via state on every transition. `phaseRef`/`phaseReasonRef` are always current.\n *\n * @example\n * // Reactive\n * const { ref, phase } = useSight();\n *\n * // Transient (no re-renders)\n * const { ref, phaseRef } = useSight({\n * onVisibilityChange: (phase) => { worker.postMessage({ visible: phase === 'visible' }); },\n * });\n */\nexport function useSight<T extends Element = HTMLDivElement>(\n options: UseSightOptions<T> & { onVisibilityChange: SightCallback },\n): UseSightTransientResult<T>;\nexport function useSight<T extends Element = HTMLDivElement>(\n options?: UseSightOptions<T>,\n): UseSightReactiveResult<T>;\nexport function useSight<T extends Element = HTMLDivElement>(\n options?: UseSightOptions<T>,\n): UseSightReactiveResult<T> | UseSightTransientResult<T> {\n const [state, setState] = useState<SightState>(INITIAL_STATE);\n const observe = options?.observe ?? 'continuous';\n const phaseRef = useRef<SightPhase>('unknown');\n const phaseReasonRef = useRef<SightReason>('initial');\n const onVisibilityChangeRef = useSyncedRef(options?.onVisibilityChange);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n let frozen = false;\n\n const sight = createSight({\n element,\n intersectionOptions: {\n root: options?.root,\n rootMargin: options?.rootMargin,\n threshold: options?.threshold,\n },\n onPhaseChange: (phase, reason) => {\n if (frozen) return;\n\n phaseRef.current = phase;\n phaseReasonRef.current = reason;\n\n if (onVisibilityChangeRef.current) {\n onVisibilityChangeRef.current(phase, reason);\n } else {\n setState({ phase, phaseReason: reason });\n }\n\n if (observe === 'once' && phase === 'visible') {\n frozen = true;\n sight.stop();\n }\n },\n });\n\n return () => sight.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [observe]);\n\n return { ref, ...state, phaseRef, phaseReasonRef };\n}\n","type ROCallback = (entry: ResizeObserverEntry) => void;\n\nlet observer: ResizeObserver | null = null;\nconst callbacks = new Map<Element, ROCallback>();\n\n/**\n * Observe an element via a singleton ResizeObserver.\n * One RO instance for the entire page. Per-element `box` options are\n * forwarded to `ResizeObserver.observe()`.\n *\n * @returns Cleanup function that unobserves the element.\n */\nexport function observeResize(\n element: Element,\n callback: ROCallback,\n box?: ResizeObserverBoxOptions,\n): () => void {\n callbacks.set(element, callback);\n getObserver().observe(element, box ? { box } : undefined);\n\n let disposed = false;\n\n return () => {\n if (disposed) return;\n disposed = true;\n\n // Only unobserve if our callback is still the registered one.\n // A later subscription on the same element would have overwritten it.\n if (callbacks.get(element) === callback) {\n callbacks.delete(element);\n observer?.unobserve(element);\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Lazy-created singleton. RO takes zero constructor options, so one instance can observe everything. */\nfunction getObserver(): ResizeObserver {\n if (!observer) {\n observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const cb: ROCallback | undefined = callbacks.get(entry.target);\n if (cb) cb(entry);\n }\n });\n }\n return observer;\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport { observeResize } from '../../core/_internal/pool/ro-pool';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport type SizeCallback = (size: Size) => void;\n\nexport interface Size {\n width: number;\n height: number;\n}\n\nexport interface UseSizeOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to measure. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /**\n * Which CSS box model to measure. `'content-box'` returns the content area\n * (inside padding). `'border-box'` returns content + padding + border.\n * Default `'content-box'`.\n */\n box?: 'content-box' | 'border-box';\n /**\n * Called on every resize. When provided, `size` is omitted from the return\n * type and no re-renders occur, the right path for canvas and animation\n * consumers that read dimensions imperatively.\n */\n onResize?: SizeCallback;\n}\n\nexport interface UseSizeReactiveResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n /** Element dimensions via state, or `null` until first observation. */\n size: Size | null;\n /** Element dimensions via ref. Always current, never triggers re-render. */\n sizeRef: RefObject<Size | null>;\n}\n\nexport interface UseSizeTransientResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n /** Element dimensions via ref. Always current, never triggers re-render. */\n sizeRef: RefObject<Size | null>;\n}\n\n/** @deprecated Use `UseSizeReactiveResult` or `UseSizeTransientResult`. */\nexport type UseSizeResult<T extends Element = HTMLDivElement> =\n UseSizeReactiveResult<T>;\n\n/**\n * Element dimensions via the shared ResizeObserver singleton.\n *\n * Pass `onResize` for zero-re-render mode (canvas, animation loops).\n * Without it, `size` updates via state on every dimension change.\n * `sizeRef` is always current in both modes.\n *\n * @example\n * // Reactive (re-renders on resize)\n * const { ref, size } = useSize();\n *\n * // Transient (no re-renders — read sizeRef in onTick/draw)\n * const { ref, sizeRef } = useSize({ onResize: (s) => applySize(s) });\n */\nexport function useSize<T extends Element = HTMLDivElement>(\n options: UseSizeOptions<T> & { onResize: SizeCallback },\n): UseSizeTransientResult<T>;\nexport function useSize<T extends Element = HTMLDivElement>(\n options?: UseSizeOptions<T>,\n): UseSizeReactiveResult<T>;\nexport function useSize<T extends Element = HTMLDivElement>(\n options?: UseSizeOptions<T>,\n): UseSizeReactiveResult<T> | UseSizeTransientResult<T> {\n const [size, setSize] = useState<Size | null>(null);\n const sizeRef = useRef<Size | null>(null);\n const prevWidth = useRef<number | null>(null);\n const prevHeight = useRef<number | null>(null);\n const onResizeRef = useSyncedRef(options?.onResize);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n const boxOption: 'content-box' | 'border-box' | undefined = options?.box;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const unobserve: () => void = observeResize(\n element,\n (entry) => {\n const resolved: ResizeObserverSize | undefined =\n boxOption === 'border-box'\n ? entry.borderBoxSize[0]\n : entry.contentBoxSize[0];\n if (!resolved) return;\n\n const width: number = resolved.inlineSize;\n const height: number = resolved.blockSize;\n\n if (width === prevWidth.current && height === prevHeight.current)\n return;\n prevWidth.current = width;\n prevHeight.current = height;\n\n const next: Size = { width, height };\n sizeRef.current = next;\n\n if (onResizeRef.current) {\n onResizeRef.current(next);\n } else {\n setSize(next);\n }\n },\n boxOption,\n );\n\n return unobserve;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [boxOption]);\n\n return { ref, size, sizeRef };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport { observeResize } from '../../core/_internal/pool/ro-pool';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ContainerBreakpoint {\n minWidth?: number;\n maxWidth?: number;\n minHeight?: number;\n maxHeight?: number;\n}\n\nexport interface UseContainerQueryOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to measure. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n}\n\nexport interface UseContainerQueryResult<T extends Element = HTMLDivElement> {\n /** Attach to the element you want to match against the breakpoint. */\n ref: RefObject<T | null>;\n /** Whether the element currently matches the breakpoint. */\n matches: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// useContainerQuery\n// ---------------------------------------------------------------------------\n\n/**\n * Returns whether an element matches a size-based container breakpoint.\n *\n * Unlike `useSize` (which re-renders on every pixel of resize), this hook only\n * re-renders when the match result changes, i.e. when the element crosses a\n * breakpoint boundary. Uses the shared ResizeObserver singleton.\n *\n * @example\n * const { ref, matches } = useContainerQuery({ minWidth: 600 });\n * return <div ref={ref}>{matches ? 'wide' : 'narrow'}</div>;\n */\nexport function useContainerQuery<T extends Element = HTMLDivElement>(\n breakpoint: ContainerBreakpoint,\n options?: UseContainerQueryOptions<T>,\n): UseContainerQueryResult<T> {\n const [matches, setMatches] = useState(false);\n const matchesRef = useRef(false);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n const { minWidth, maxWidth, minHeight, maxHeight } = breakpoint;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const unobserve: () => void = observeResize(element, (entry) => {\n const box = entry.contentBoxSize[0];\n if (!box) return;\n\n const width: number = box.inlineSize;\n const height: number = box.blockSize;\n\n const nowMatches: boolean = evaluateBreakpoint(\n width,\n height,\n minWidth,\n maxWidth,\n minHeight,\n maxHeight,\n );\n\n // Only re-render when the boolean flips — not on every pixel of resize.\n if (nowMatches !== matchesRef.current) {\n matchesRef.current = nowMatches;\n setMatches(nowMatches);\n }\n });\n\n return unobserve;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [minWidth, maxWidth, minHeight, maxHeight]);\n\n return { ref, matches };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction evaluateBreakpoint(\n width: number,\n height: number,\n minWidth?: number,\n maxWidth?: number,\n minHeight?: number,\n maxHeight?: number,\n): boolean {\n if (minWidth !== undefined && width < minWidth) return false;\n if (maxWidth !== undefined && width > maxWidth) return false;\n if (minHeight !== undefined && height < minHeight) return false;\n if (maxHeight !== undefined && height > maxHeight) return false;\n return true;\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport { createScrollProgress } from '../../core/scroll-progress';\nimport { useSyncedRef } from '../use-synced-ref';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ScrollProgressCallback = (progress: number) => void;\n\nexport interface UseScrollProgressOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to observe. Optional. When omitted, attach the returned `ref`.\n */\n ref?: RefObject<T | null>;\n /** Number of evenly-spaced thresholds. Default 20 (~5% granularity). */\n steps?: number;\n root?: Element | null;\n rootMargin?: string;\n /**\n * Called on every threshold crossing. When provided, `progress` stays `0`\n * and no re-renders occur, the right path for scroll-driven animation\n * consumers that read progress imperatively.\n */\n onProgress?: ScrollProgressCallback;\n}\n\nexport interface UseScrollProgressReactiveResult<\n T extends Element = HTMLDivElement,\n> {\n ref: RefObject<T | null>;\n /** Fraction of the element currently visible (0–1). */\n progress: number;\n /** Fraction visible via ref. Always current, never triggers re-render. */\n progressRef: RefObject<number>;\n}\n\nexport interface UseScrollProgressTransientResult<\n T extends Element = HTMLDivElement,\n> {\n ref: RefObject<T | null>;\n /** Fraction visible via ref. Always current, never triggers re-render. */\n progressRef: RefObject<number>;\n}\n\n/** @deprecated Use `UseScrollProgressReactiveResult` or `UseScrollProgressTransientResult`. */\nexport type UseScrollProgressResult<T extends Element = HTMLDivElement> =\n UseScrollProgressReactiveResult<T>;\n\n// ---------------------------------------------------------------------------\n// useScrollProgress\n// ---------------------------------------------------------------------------\n\n/**\n * Element visibility ratio (0–1) via the shared IntersectionObserver pool.\n *\n * Pass `onProgress` for zero-re-render mode (scroll-driven animation).\n * Without it, `progress` updates via state at each threshold crossing.\n * `progressRef` is always current in both modes.\n *\n * @example\n * // Reactive (re-renders at threshold crossings)\n * const { ref, progress } = useScrollProgress();\n *\n * // Transient (no re-renders — read progressRef in onTick)\n * const { ref, progressRef } = useScrollProgress({\n * onProgress: (p) => { el.style.opacity = String(p); },\n * });\n */\nexport function useScrollProgress<T extends Element = HTMLDivElement>(\n options: UseScrollProgressOptions<T> & {\n onProgress: ScrollProgressCallback;\n },\n): UseScrollProgressTransientResult<T>;\nexport function useScrollProgress<T extends Element = HTMLDivElement>(\n options?: UseScrollProgressOptions<T>,\n): UseScrollProgressReactiveResult<T>;\nexport function useScrollProgress<T extends Element = HTMLDivElement>(\n options?: UseScrollProgressOptions<T>,\n): UseScrollProgressReactiveResult<T> | UseScrollProgressTransientResult<T> {\n const [progress, setProgress] = useState(0);\n const progressRef = useRef(0);\n const steps: number | undefined = options?.steps;\n const rootMargin: string | undefined = options?.rootMargin;\n const onProgressRef = useSyncedRef(options?.onProgress);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options?.ref ?? internalRef;\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const scrollProgress = createScrollProgress({\n element,\n onProgress: (ratio: number) => {\n progressRef.current = ratio;\n\n if (onProgressRef.current) {\n onProgressRef.current(ratio);\n } else {\n setProgress(ratio);\n }\n },\n steps,\n root: options?.root,\n rootMargin,\n });\n\n return () => scrollProgress.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [steps, rootMargin]);\n\n return { ref, progress, progressRef };\n}\n","import { useState, useEffect, type RefObject } from 'react';\n\nimport { createRenderState, type RenderPhase } from '../../core/render-state';\n\nexport type { RenderPhase } from '../../core/render-state';\n\n/**\n * Track whether the browser is rendering an element or skipping it under\n * `content-visibility` (e.g. a `Defer` subtree). Returns `'rendered'` until the\n * browser reports otherwise.\n *\n * Use it to pause raw, non-phase work (a hand-written rAF loop, `setInterval`)\n * when the subtree stops painting. phase loops self-pause off-screen already.\n * Has no layout effect. Safe for CLS.\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null);\n * const phase = useRenderState(ref);\n * useEffect(() => {\n * if (phase === 'skipped') clock.pause();\n * else clock.resume();\n * }, [phase]);\n * return <Defer ref={ref}><Heavy /></Defer>;\n */\nexport function useRenderState<T extends Element = HTMLDivElement>(\n ref: RefObject<T | null>,\n): RenderPhase {\n const [phase, setPhase] = useState<RenderPhase>('rendered');\n\n useEffect(() => {\n const element: Element | null = ref.current;\n if (!element) return;\n\n const render = createRenderState({\n element,\n onPhaseChange: setPhase,\n });\n\n return () => render.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return phase;\n}\n","import { useState, useEffect } from 'react';\n\nimport { whenIdle, type IdleOptions } from '../../core/idle';\n\nexport type { IdleOptions } from '../../core/idle';\n\n/**\n * Returns `false`, then `true` once the browser is idle after mount. Use it to\n * defer non-critical work or mounting until the main thread is free.\n *\n * SSR-safe: returns `false` on the server and during the first client render.\n *\n * @example\n * const idle = useIdle();\n * return idle ? <Analytics /> : null;\n */\nexport function useIdle(options?: IdleOptions): boolean {\n const [idle, setIdle] = useState(false);\n const timeout = options?.timeout;\n\n useEffect(() => {\n const cancel: () => void = whenIdle(() => setIdle(true), { timeout });\n return cancel;\n }, [timeout]);\n\n return idle;\n}\n","import { useEffect } from 'react';\n\nimport { whenIdle, type IdleOptions } from '../../core/idle';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport type { IdleOptions } from '../../core/idle';\n\n/**\n * Run a callback once, when the browser is idle after mount. The effect-shaped\n * counterpart to `useIdle`. Use it for side effects (prefetching a chunk,\n * warming a cache, `import()`) rather than rendering.\n *\n * Cancels automatically on unmount, and always calls the latest `callback`\n * without re-subscribing. SSR-safe: nothing runs on the server.\n *\n * @example\n * // Prefetch a heavy panel during idle time so it opens instantly later.\n * useWhenIdle(() => void import('./chat-panel'));\n */\nexport function useWhenIdle(callback: () => void, options?: IdleOptions): void {\n const callbackRef = useSyncedRef(callback);\n const timeout = options?.timeout;\n\n useEffect(() => {\n const cancel: () => void = whenIdle(() => callbackRef.current(), {\n timeout,\n });\n return cancel;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [timeout]);\n}\n","import {\n useState,\n useEffect,\n useRef,\n useCallback,\n type RefObject,\n} from 'react';\n\nimport { subscribeDpr, readDpr } from '../../core/_internal/pool/dpr';\nimport { observeResize } from '../../core/_internal/pool/ro-pool';\nimport {\n createLoop,\n type LoopPhase,\n type LoopReason,\n type Quality,\n type DegradedBehavior,\n type DegradedReason,\n type ReducedMotionBehavior,\n} from '../../core/loop';\nimport type { FrameState } from '../../core/tick';\nimport { degradedConfig } from '../_internal/degraded-config';\nimport { useSyncedRef } from '../use-synced-ref';\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/**\n * Per-frame canvas draw callback. Receives the 2D context, frame state, and\n * current element size. Draw directly to the canvas. Never call React\n * `setState` here.\n */\nexport type CanvasDrawFn = (\n ctx: CanvasRenderingContext2D,\n frame: FrameState,\n size: Size,\n) => void;\n\nexport interface UseCanvasOptions {\n containerRef: RefObject<Element | null>;\n canvasRef: RefObject<HTMLCanvasElement | null>;\n /**\n * Called every frame with the 2D context, frame state, and current element size.\n * Draw directly to the canvas. Never call React `setState` here.\n */\n draw: CanvasDrawFn;\n fps?: number;\n enabled?: boolean;\n reducedMotion?: ReducedMotionBehavior;\n /** Behavior when quality degrades. Default `'throttle'`. For heavy GPU work, `'pause'` is often the right call. */\n degraded?: DegradedBehavior;\n /** FPS cap when `degraded` is `'throttle'`. Default `30`. */\n degradedFps?: number;\n}\n\nexport interface UseCanvasResult {\n restart: () => void;\n phase: LoopPhase;\n phaseReason: LoopReason;\n quality: Quality;\n qualityReason: DegradedReason | undefined;\n}\n\nconst INITIAL_STATE: Omit<UseCanvasResult, 'restart'> = {\n phase: 'idle',\n phaseReason: 'initial',\n quality: 'full',\n qualityReason: undefined,\n};\n\n/**\n * Canvas-specific animation with DPR-aware sizing, ResizeObserver coalescing,\n * context management, and GPU context loss recovery.\n *\n * @example\n * useCanvas({\n * containerRef,\n * canvasRef,\n * draw: (ctx, frame, size) => {\n * ctx.clearRect(0, 0, size.width, size.height);\n * // render...\n * },\n * });\n */\nexport function useCanvas(options: UseCanvasOptions): UseCanvasResult {\n const {\n containerRef,\n canvasRef,\n fps,\n enabled = true,\n reducedMotion,\n degraded,\n degradedFps,\n } = options;\n const drawRef = useSyncedRef(options.draw);\n\n const [state, setState] = useState(INITIAL_STATE);\n const [restartNonce, setRestartNonce] = useState(0);\n\n const ctxRef = useRef<CanvasRenderingContext2D | null>(null);\n const sizeRef = useRef<Size>({ width: 0, height: 0 });\n const qualityRef = useSyncedRef(state.quality);\n\n useEffect(() => {\n const container: Element | null = containerRef.current;\n const canvasEl: HTMLCanvasElement | null = canvasRef.current;\n if (!container || !canvasEl || !enabled) return;\n const canvas: HTMLCanvasElement = canvasEl;\n\n const initialCtx: CanvasRenderingContext2D | null = canvas.getContext('2d');\n if (!initialCtx) return;\n ctxRef.current = initialCtx;\n\n let dpr: number = readDpr();\n let contextLost = false;\n\n // --- Canvas buffer sizing ---\n\n function applySize(\n width: number,\n height: number,\n physicalBox?: ResizeObserverSize,\n ): void {\n sizeRef.current = { width, height };\n const isDegraded: boolean = qualityRef.current === 'degraded';\n\n let bufferWidth: number;\n let bufferHeight: number;\n\n if (isDegraded) {\n bufferWidth = width;\n bufferHeight = height;\n } else if (physicalBox) {\n bufferWidth = physicalBox.inlineSize;\n bufferHeight = physicalBox.blockSize;\n } else {\n bufferWidth = width * dpr;\n bufferHeight = height * dpr;\n }\n\n canvas.width = bufferWidth;\n canvas.height = bufferHeight;\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n\n const effectiveDpr: number = isDegraded ? 1 : dpr;\n ctxRef.current?.setTransform(effectiveDpr, 0, 0, effectiveDpr, 0, 0);\n }\n\n // --- DPR monitoring (e.g. user drags window between monitors) ---\n\n const unsubDpr: () => void = subscribeDpr((newDpr) => {\n dpr = newDpr;\n applySize(sizeRef.current.width, sizeRef.current.height);\n });\n\n // --- Resize via shared RO pool ---\n\n const unobserve: () => void = observeResize(container, (entry) => {\n const box = entry.contentBoxSize[0];\n if (!box) return;\n const physicalBox: ResizeObserverSize | undefined =\n entry.devicePixelContentBoxSize?.[0];\n applySize(box.inlineSize, box.blockSize, physicalBox);\n });\n\n // --- GPU context loss recovery ---\n\n function onContextLost(event: Event): void {\n event.preventDefault();\n contextLost = true;\n }\n\n function onContextRestored(): void {\n const restoredCtx: CanvasRenderingContext2D | null =\n canvas.getContext('2d');\n if (!restoredCtx) return;\n ctxRef.current = restoredCtx;\n contextLost = false;\n applySize(sizeRef.current.width, sizeRef.current.height);\n }\n\n canvas.addEventListener('contextlost', onContextLost);\n canvas.addEventListener('contextrestored', onContextRestored);\n\n // --- Animation loop ---\n\n let loopInstance: ReturnType<typeof createLoop> | null = null;\n\n const loop = createLoop({\n element: container,\n fps,\n reducedMotion,\n ...degradedConfig(degraded, degradedFps),\n onTick: (frame) => {\n if (contextLost || !ctxRef.current) return;\n drawRef.current(ctxRef.current, frame, sizeRef.current);\n },\n onPhaseChange: (phase, reason) => {\n setState({\n phase,\n phaseReason: reason,\n quality: loopInstance?.quality ?? 'full',\n qualityReason: loopInstance?.qualityReason,\n });\n },\n });\n loopInstance = loop;\n\n // --- Teardown ---\n\n function teardown(): void {\n loop.stop();\n loopInstance = null;\n unobserve();\n unsubDpr();\n canvas.removeEventListener('contextlost', onContextLost);\n canvas.removeEventListener('contextrestored', onContextRestored);\n }\n\n return teardown;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, fps, reducedMotion, degraded, degradedFps, restartNonce]);\n\n // Restart bumps a nonce so the effect re-runs: it tears down the current\n // loop + observers and rebuilds them on the next cycle.\n const restart = useCallback(() => {\n setRestartNonce((n) => n + 1);\n }, []);\n\n return { restart, ...state };\n}\n","import { useState, useEffect, useRef, type RefObject } from 'react';\n\nimport {\n createMutation,\n type MutationPhase,\n type MutationReason,\n} from '../../core/mutation';\nimport { useSyncedRef } from '../use-synced-ref';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type MutationRecordsCallback = (records: MutationRecord[]) => void;\n\nexport type MutationPhaseCallback = (\n phase: MutationPhase,\n phaseReason: MutationReason,\n) => void;\n\nexport interface UseMutationOptions<T extends Element = HTMLDivElement> {\n /**\n * Element to observe. When omitted, attach the returned `ref`.\n * Must be set before the first effect commit (standard React ref contract).\n */\n ref?: RefObject<T | null>;\n /**\n * Standard MutationObserver configuration. Must be stable across renders\n * (define outside the component or memoize). Changes are not tracked.\n */\n mutation: MutationObserverInit;\n /** Called once per rAF frame with coalesced records. Never per-record. */\n onMutations: MutationRecordsCallback;\n /**\n * Called on every phase transition. When provided, `phase` and `phaseReason`\n * stay at initial values and no re-renders occur (transient mode).\n */\n onPhaseChange?: MutationPhaseCallback;\n /** Pause when off-screen or ignore visibility. Default `'pause'`. */\n visibility?: 'pause' | 'ignore';\n /** When `false`, tears down the observer entirely. Default `true`. */\n enabled?: boolean;\n /** IO options forwarded to the visibility observer. */\n intersectionOptions?: IntersectionObserverInit;\n}\n\nexport interface UseMutationReactiveResult<T extends Element = HTMLDivElement> {\n ref: RefObject<T | null>;\n phase: MutationPhase;\n phaseReason: MutationReason;\n /** Phase via ref. Always current, never triggers re-render. */\n phaseRef: RefObject<MutationPhase>;\n /** Reason via ref. Always current, never triggers re-render. */\n phaseReasonRef: RefObject<MutationReason>;\n}\n\nexport interface UseMutationTransientResult<\n T extends Element = HTMLDivElement,\n> {\n ref: RefObject<T | null>;\n /** Phase via ref. Always current, never triggers re-render. */\n phaseRef: RefObject<MutationPhase>;\n /** Reason via ref. Always current, never triggers re-render. */\n phaseReasonRef: RefObject<MutationReason>;\n}\n\nexport type UseMutationResult<T extends Element = HTMLDivElement> =\n UseMutationReactiveResult<T>;\n\n// ---------------------------------------------------------------------------\n// useMutation\n// ---------------------------------------------------------------------------\n\ntype MutationState = { phase: MutationPhase; phaseReason: MutationReason };\n\nconst INITIAL_STATE: MutationState = {\n phase: 'paused',\n phaseReason: 'initial',\n};\n\n/**\n * Lifecycle-aware MutationObserver with rAF-coalesced callbacks.\n * Auto-pauses off-screen and tears down on unmount.\n *\n * Pass `onPhaseChange` for zero-re-render mode (transient). Without it,\n * `phase` and `phaseReason` update via state on every transition.\n */\nexport function useMutation<T extends Element = HTMLDivElement>(\n options: UseMutationOptions<T> & { onPhaseChange: MutationPhaseCallback },\n): UseMutationTransientResult<T>;\nexport function useMutation<T extends Element = HTMLDivElement>(\n options: UseMutationOptions<T>,\n): UseMutationReactiveResult<T>;\nexport function useMutation<T extends Element = HTMLDivElement>(\n options: UseMutationOptions<T>,\n): UseMutationReactiveResult<T> | UseMutationTransientResult<T> {\n const [state, setState] = useState<MutationState>(INITIAL_STATE);\n const {\n mutation: mutationInit,\n visibility = 'pause',\n enabled = true,\n intersectionOptions,\n } = options;\n\n const phaseRef = useRef<MutationPhase>('paused');\n const phaseReasonRef = useRef<MutationReason>('initial');\n const onMutationsRef = useSyncedRef(options.onMutations);\n const onPhaseChangeRef = useSyncedRef(options.onPhaseChange);\n\n const internalRef = useRef<T | null>(null);\n const ref: RefObject<T | null> = options.ref ?? internalRef;\n\n useEffect(() => {\n const element = ref.current;\n if (!element || !enabled) {\n setState(INITIAL_STATE);\n phaseRef.current = 'paused';\n phaseReasonRef.current = 'initial';\n return;\n }\n\n const instance = createMutation({\n element,\n mutation: mutationInit,\n onMutations: (records) => onMutationsRef.current(records),\n onPhaseChange: (phase, reason) => {\n phaseRef.current = phase;\n phaseReasonRef.current = reason;\n\n if (onPhaseChangeRef.current) {\n onPhaseChangeRef.current(phase, reason);\n } else {\n setState({ phase, phaseReason: reason });\n }\n },\n visibility,\n intersectionOptions,\n });\n\n return () => instance.stop();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, visibility]);\n\n return { ref, ...state, phaseRef, phaseReasonRef };\n}\n","import { useState, useEffect, useRef } from 'react';\n\nimport { invalidDurationError } from '../../core/_internal/errors';\nimport type { ReducedMotionBehavior } from '../../core/loop';\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { clamp01, easeOutCubic } from '../../ease';\n\nexport interface UseTweenOptions {\n target: number;\n duration?: number;\n delay?: number;\n easing?: (progress: number) => number;\n enabled?: boolean;\n /** Default: `'complete'`. Tweens jump to target under reduced motion. */\n reducedMotion?: ReducedMotionBehavior;\n}\n\n/**\n * Animate a value from its current position to `target` over `duration`.\n *\n * Uses `useState` per frame. Appropriate for cheap renders (counters, opacity,\n * progress bars). For batch animations, use `useLoop` with ref-based DOM writes.\n *\n * @remarks\n * Unlike `createTicker`/`createLoop`, `useTween` drives its own rAF rather than\n * the shared frame-locked clock. It's a finite, self-completing tween whose value\n * must land in React state, so it doesn't need cross-loop visual sync, strong\n * pause, or delta clamping. Routing it through the shared clock would add bundle\n * weight for no benefit.\n *\n * @example\n * const value = useTween({ target: 100, duration: 500 });\n */\nexport function useTween(options: UseTweenOptions): number {\n const {\n target,\n duration = 300,\n delay = 0,\n easing = easeOutCubic,\n enabled = true,\n reducedMotion = 'complete',\n } = options;\n\n const [value, setValue] = useState(target);\n\n const fromRef = useRef(target);\n const currentRef = useRef(target);\n const isFirstRender = useRef(true);\n\n useEffect(() => {\n if (!Number.isFinite(duration) || duration <= 0) {\n invalidDurationError('useTween', duration);\n }\n\n // First render: sync refs without animating.\n if (isFirstRender.current) {\n isFirstRender.current = false;\n jumpToTarget({ target, fromRef, currentRef, setValue });\n return;\n }\n\n // Disabled or reduced motion: jump immediately.\n if (!enabled || (reducedMotion !== 'ignore' && prefersReducedMotion())) {\n jumpToTarget({ target, fromRef, currentRef, setValue });\n return;\n }\n\n // Already at target: nothing to animate.\n const from: number = currentRef.current;\n if (from === target) return;\n\n let rafId: number;\n let startTime: number | null = null;\n\n function tick(now: number): void {\n if (startTime === null) startTime = now;\n const elapsed: number = now - startTime - delay;\n\n // Still in the delay period — keep scheduling.\n if (elapsed < 0) {\n rafId = requestAnimationFrame(tick);\n return;\n }\n\n const progress: number = clamp01(elapsed / duration);\n const current: number = from + (target - from) * easing(progress);\n currentRef.current = current;\n setValue(current);\n\n if (progress < 1) {\n rafId = requestAnimationFrame(tick);\n } else {\n fromRef.current = target;\n }\n }\n\n rafId = requestAnimationFrame(tick);\n\n return () => {\n cancelAnimationFrame(rafId);\n // Preserve where we actually are so the next tween starts from here.\n fromRef.current = currentRef.current;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [target, duration, delay, enabled, reducedMotion]);\n\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface JumpToTargetOptions {\n target: number;\n fromRef: React.RefObject<number>;\n currentRef: React.RefObject<number>;\n setValue: (value: number) => void;\n}\n\nfunction jumpToTarget(options: JumpToTargetOptions): void {\n const { target, fromRef, currentRef, setValue } = options;\n fromRef.current = target;\n currentRef.current = target;\n setValue(target);\n}\n","import {\n useEffect,\n useRef,\n type EffectCallback,\n type DependencyList,\n} from 'react';\n\n/**\n * Like `useEffect` but skips the first invocation on mount.\n * Used by Presence to distinguish initial render from subsequent `show` changes.\n */\nexport function useUpdateEffect(\n effect: EffectCallback,\n deps: DependencyList,\n): void {\n const isMounted = useRef(false);\n\n useEffect(() => {\n if (!isMounted.current) {\n isMounted.current = true;\n return;\n }\n return effect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n}\n","import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type RefObject,\n} from 'react';\n\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { useUpdateEffect } from '../_internal/use-update-effect';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type PresencePhase = 'idle' | 'entered' | 'exiting' | 'exited';\n\nexport type PresenceReason =\n | 'initial'\n | 'show'\n | 'hide'\n | 'animation-end'\n | 'interrupted';\n\nexport type PresenceMode = 'mount' | 'reveal';\n\nexport interface UsePresenceOptions {\n show: boolean;\n mode?: PresenceMode;\n /** Controls first-mount behavior. `'animate'` (default): enter animation plays. `'instant'`: appears immediately. */\n enter?: 'animate' | 'instant';\n /** Safety-net timeout in ms if transitionend/animationend doesn't fire during exit. Default 5000. */\n exitDuration?: number;\n /** Whether to respect the user's reduced motion preference. Default `'respect'`. */\n reducedMotion?: 'respect' | 'ignore';\n}\n\nexport interface UsePresenceResult {\n phase: PresencePhase;\n phaseReason: PresenceReason;\n /** Convenience: `phase !== 'idle' && phase !== 'exited'` for conditional rendering in mount mode. */\n mounted: boolean;\n ref: RefObject<Element | null>;\n /** Whether the component should stamp `data-enter=\"animate\"`. Accounts for enter option + reduced motion. */\n enter: 'animate' | 'instant';\n}\n\n// ---------------------------------------------------------------------------\n// usePresence\n// ---------------------------------------------------------------------------\n\n/**\n * Composable presence primitive for mount/unmount lifecycle with CSS transitions.\n *\n * Enter animations use CSS `@starting-style`, gated by `data-enter=\"animate\"`.\n * Exit animations are JS-coordinated: waits for `transitionend`/`animationend`\n * before unmounting.\n *\n * @example\n * const { phase, ref, mounted, enter } = usePresence({ show: isOpen });\n * if (!mounted) return null;\n * return (\n * <div ref={ref} data-phase={phase} data-enter={enter === 'animate' ? 'animate' : undefined}\n * className=\"transition-opacity data-[enter=animate]:starting:opacity-0 data-[phase=exiting]:opacity-0\" />\n * );\n */\nexport function usePresence(options: UsePresenceOptions): UsePresenceResult {\n const {\n show,\n mode = 'mount',\n enter: enterOption = 'animate',\n exitDuration = 5000,\n reducedMotion = 'respect',\n } = options;\n\n const ref = useRef<Element | null>(null);\n\n const initialPhase: PresencePhase = show ? 'entered' : 'idle';\n\n const [phase, setPhase] = useState<PresencePhase>(initialPhase);\n const [reason, setReason] = useState<PresenceReason>('initial');\n\n const exitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const exitCleanupRef = useRef<(() => void) | null>(null);\n\n const clearTimers = useCallback(() => {\n if (exitTimerRef.current !== null) {\n clearTimeout(exitTimerRef.current);\n exitTimerRef.current = null;\n }\n if (exitCleanupRef.current) {\n exitCleanupRef.current();\n exitCleanupRef.current = null;\n }\n }, []);\n\n useEffect(() => () => clearTimers(), [clearTimers]);\n\n useUpdateEffect(() => {\n clearTimers();\n\n if (show) {\n setPhase((prev) => {\n setReason(prev === 'exiting' ? 'interrupted' : 'show');\n return 'entered';\n });\n } else {\n const shouldSkipAnimation =\n reducedMotion === 'respect' && prefersReducedMotion();\n\n if (shouldSkipAnimation) {\n const exitTarget: PresencePhase = mode === 'reveal' ? 'idle' : 'exited';\n setPhase(exitTarget);\n setReason('animation-end');\n } else {\n handleExit(\n ref,\n mode,\n exitDuration,\n setPhase,\n setReason,\n clearTimers,\n exitTimerRef,\n exitCleanupRef,\n );\n }\n }\n }, [show]);\n\n const mounted: boolean = phase !== 'idle' && phase !== 'exited';\n\n const isFirstMount = reason === 'initial';\n const wantsAnimation = !(isFirstMount && enterOption === 'instant');\n const motionAllowed = reducedMotion === 'ignore' || !prefersReducedMotion();\n const enter: 'animate' | 'instant' =\n wantsAnimation && motionAllowed ? 'animate' : 'instant';\n\n return { phase, phaseReason: reason, mounted, ref, enter };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction handleExit(\n ref: RefObject<Element | null>,\n mode: PresenceMode,\n exitDuration: number,\n setPhase: (\n phase: PresencePhase | ((prev: PresencePhase) => PresencePhase),\n ) => void,\n setReason: (reason: PresenceReason) => void,\n clearTimers: () => void,\n exitTimerRef: React.RefObject<ReturnType<typeof setTimeout> | null>,\n exitCleanupRef: React.RefObject<(() => void) | null>,\n): void {\n setPhase('exiting');\n setReason('hide');\n\n const exitTarget: PresencePhase = mode === 'reveal' ? 'idle' : 'exited';\n const element: Element | null = ref.current;\n\n function completeExit(): void {\n clearTimers();\n setPhase((current) => {\n if (current !== 'exiting') return current;\n setReason('animation-end');\n return exitTarget;\n });\n }\n\n function cleanup(): void {\n if (element) {\n element.removeEventListener('transitionend', completeExit);\n element.removeEventListener('animationend', completeExit);\n }\n if (exitTimerRef.current !== null) {\n clearTimeout(exitTimerRef.current);\n exitTimerRef.current = null;\n }\n exitCleanupRef.current = null;\n }\n\n exitCleanupRef.current = cleanup;\n\n if (element) {\n element.addEventListener('transitionend', completeExit, { once: true });\n element.addEventListener('animationend', completeExit, { once: true });\n }\n\n exitTimerRef.current = setTimeout(completeExit, exitDuration);\n}\n","import {\n useImperativeHandle,\n type ComponentProps,\n type JSX,\n type Ref,\n} from 'react';\n\nimport { usePresence, type PresenceMode } from '../use-presence';\n\nexport interface PresenceProps extends ComponentProps<'div'> {\n show: boolean;\n mode?: PresenceMode;\n /** Controls first-mount behavior. `'animate'` (default): enter animation plays. `'instant'`: appears immediately. */\n enter?: 'animate' | 'instant';\n /** Safety-net timeout in ms if transitionend/animationend doesn't fire during exit. Default 5000. */\n exitDuration?: number;\n /** Whether to respect the user's reduced motion preference. Default `'respect'`. */\n reducedMotion?: 'respect' | 'ignore';\n ref?: Ref<HTMLDivElement>;\n}\n\n/**\n * Renders a `div` that manages its own mounting lifecycle.\n *\n * Stamps `data-phase` for exit animations and `data-enter=\"animate\"` to gate\n * CSS `@starting-style` enter animations. Reduced motion is handled automatically.\n *\n * @example\n * <Presence\n * show={isOpen}\n * className=\"transition-opacity data-[enter=animate]:starting:opacity-0 data-[phase=exiting]:opacity-0\"\n * >\n * Modal content\n * </Presence>\n */\nexport function Presence({\n show,\n mode,\n enter: enterOption,\n exitDuration,\n reducedMotion,\n ref: forwardedRef,\n children,\n ...divProps\n}: PresenceProps): JSX.Element | null {\n const { phase, ref, mounted, enter } = usePresence({\n show,\n mode,\n enter: enterOption,\n exitDuration,\n reducedMotion,\n });\n\n useImperativeHandle(forwardedRef, () => ref.current as HTMLDivElement);\n\n if (!mounted && mode !== 'reveal') return null;\n\n return (\n <div\n {...divProps}\n ref={ref as React.RefObject<HTMLDivElement | null>}\n data-phase={phase}\n data-enter={enter === 'animate' ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n","import {\n useRef,\n type ComponentProps,\n type JSX,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { useSight } from '../use-sight';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface WhenVisibleProps extends ComponentProps<'div'> {\n /** IntersectionObserver rootMargin. Default `'200px'` (generous headroom for preloading). */\n rootMargin?: string;\n /** IntersectionObserver threshold. */\n threshold?: number | number[];\n /** IntersectionObserver root element. */\n root?: Element | null;\n /** Content shown while awaiting intersection. Sentinel div is always rendered for IO. */\n fallback?: ReactNode;\n /** Forwarded to the rendered div in both states (the sentinel before visible, the entered div after). Populated at mount. */\n ref?: Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// WhenVisible\n// ---------------------------------------------------------------------------\n\n/**\n * Mounts children when the element enters the viewport. One-shot (once\n * triggered, stays mounted).\n *\n * Enter animation uses CSS `@starting-style`, gated by `data-enter=\"animate\"`.\n * Reduced motion is automatic: the attribute is not stamped when the user\n * prefers reduced motion.\n *\n * @example\n * <WhenVisible rootMargin=\"200px\" className=\"transition-opacity data-[enter=animate]:starting:opacity-0\">\n * <HeavyChart />\n * </WhenVisible>\n */\nexport function WhenVisible({\n rootMargin = '200px',\n threshold,\n root,\n fallback,\n children,\n ref: forwardedRef,\n ...divProps\n}: WhenVisibleProps): JSX.Element {\n const sentinelRef = useRef<HTMLDivElement>(null);\n const { phase } = useSight({\n ref: sentinelRef,\n observe: 'once',\n rootMargin,\n threshold,\n root,\n });\n\n const setRef = (node: HTMLDivElement | null): void => {\n sentinelRef.current = node;\n assignRef(forwardedRef, node);\n };\n\n if (phase !== 'visible') {\n return (\n <div ref={setRef} {...divProps}>\n {fallback}\n </div>\n );\n }\n\n const motionAllowed = !prefersReducedMotion();\n\n return (\n <div\n {...divProps}\n ref={setRef}\n data-phase=\"entered\"\n data-enter={motionAllowed ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n\nfunction assignRef(\n ref: Ref<HTMLDivElement> | undefined,\n node: HTMLDivElement | null,\n): void {\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n}\n","import type { ComponentProps, JSX, ReactNode, Ref } from 'react';\n\nimport { prefersReducedMotion } from '../../core/reduced-motion';\nimport { useIdle } from '../use-idle';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface WhenIdleProps extends ComponentProps<'div'> {\n /** Max ms to wait before mounting even if no idle period occurs. */\n timeout?: number;\n /** Content shown until the browser is idle. */\n fallback?: ReactNode;\n ref?: Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// WhenIdle\n// ---------------------------------------------------------------------------\n\n/**\n * Mounts children once the browser is idle after first paint. One-shot (once\n * mounted, stays mounted). Use it to defer non-critical UI off the critical path.\n *\n * Children are not server-rendered (idle never fires during SSR), so reserve\n * this for non-critical content. For viewport-gated mounting use `WhenVisible`;\n * to keep content in the DOM but skip painting use `Defer`.\n *\n * Enter animation uses CSS `@starting-style`, gated by `data-enter=\"animate\"`.\n * Reduced motion is automatic: the attribute is not stamped when the user\n * prefers reduced motion.\n *\n * @example\n * <WhenIdle fallback={<Skeleton />}>\n * <SecondaryPanel />\n * </WhenIdle>\n */\nexport function WhenIdle({\n timeout,\n fallback,\n children,\n ref: forwardedRef,\n ...divProps\n}: WhenIdleProps): JSX.Element {\n const idle = useIdle({ timeout });\n\n if (!idle) {\n return <div {...divProps}>{fallback}</div>;\n }\n\n const motionAllowed = !prefersReducedMotion();\n\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n data-phase=\"entered\"\n data-enter={motionAllowed ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n","import {\n createElement,\n type CSSProperties,\n type ElementType,\n type HTMLAttributes,\n type JSX,\n type ReactNode,\n type Ref,\n} from 'react';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface DeferProps extends Omit<HTMLAttributes<HTMLElement>, 'style'> {\n /**\n * HTML element to render. Default `'div'`. Use `'li'`, `'tr'`, or any\n * semantic element when a wrapper div would break document structure.\n */\n as?: ElementType;\n /**\n * Approximate size reserved before first paint (any CSS length).\n * After first render the browser remembers the real size. Default `'1000px'`.\n */\n estimatedHeight?: string;\n children?: ReactNode;\n ref?: Ref<HTMLElement>;\n}\n\n// ---------------------------------------------------------------------------\n// Defer\n// ---------------------------------------------------------------------------\n\n/**\n * Skip browser rendering (style, layout, paint) for off-screen content via\n * `content-visibility: auto`. Pure CSS, no JS, no observer. Children stay\n * in the DOM and are server-rendered (SEO- and CLS-safe).\n */\nexport function Defer({\n as: Component = 'div',\n estimatedHeight = '1000px',\n children,\n ref,\n ...rest\n}: DeferProps): JSX.Element {\n const deferStyle: CSSProperties = {\n contentVisibility: 'auto',\n containIntrinsicSize: `auto ${estimatedHeight}`,\n };\n\n return createElement(\n Component,\n { ...rest, ref, style: deferStyle },\n children,\n );\n}\n","import {\n createContext,\n use,\n useState,\n useEffect,\n useMemo,\n useCallback,\n useImperativeHandle,\n type ComponentProps,\n type JSX,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { missingContextError } from '../../core/_internal/errors';\nimport { usePresence } from '../use-presence';\nimport { useSyncedRef } from '../use-synced-ref';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface SwapContext {\n current: string;\n active: string;\n exitDuration: number;\n /** 'instant' on first mount (prevents CLS), 'animate' on subsequent swaps. */\n enter: 'animate' | 'instant';\n onExited: (id: string) => void;\n}\n\nconst SwapCtx = createContext<SwapContext | null>(null);\n\n// ---------------------------------------------------------------------------\n// Swap\n// ---------------------------------------------------------------------------\n\nexport interface SwapProps extends ComponentProps<'div'> {\n active: string;\n exitDuration?: number;\n children: ReactNode;\n}\n\n/**\n * Coordinated exit-then-enter transitions for N states.\n * Only one state is entering or exiting at a time (no overlap).\n *\n * The current state fully exits before the new state enters. Rapid changes\n * (A->B->C during A's exit) skip intermediate states and jump to the latest.\n *\n * @example\n * <Swap active={success ? 'success' : 'form'}>\n * <Swap.State id=\"form\" className=\"transition-all data-[phase=exiting]:opacity-0\">\n * <Form />\n * </Swap.State>\n * <Swap.State id=\"success\" className=\"transition-all data-[enter=animate]:starting:opacity-0\">\n * <SuccessMessage />\n * </Swap.State>\n * </Swap>\n */\nfunction SwapRoot({\n active,\n exitDuration = 5000,\n children,\n ...divProps\n}: SwapProps): JSX.Element {\n const [current, setCurrent] = useState(active);\n const [hasSwapped, setHasSwapped] = useState(false);\n const activeRef = useSyncedRef(active);\n\n const onExited = useCallback(\n (id: string): void => {\n setHasSwapped(true);\n setCurrent((cur) => (cur === id ? activeRef.current : cur));\n },\n [activeRef],\n );\n\n const enter: 'animate' | 'instant' = hasSwapped ? 'animate' : 'instant';\n\n const ctx: SwapContext = useMemo(\n () => ({ current, active, exitDuration, enter, onExited }),\n [current, active, exitDuration, enter, onExited],\n );\n\n return (\n <SwapCtx.Provider value={ctx}>\n <div {...divProps}>{children}</div>\n </SwapCtx.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Swap.State\n// ---------------------------------------------------------------------------\n\nexport interface SwapStateProps extends ComponentProps<'div'> {\n id: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nfunction SwapState({\n id,\n ref: forwardedRef,\n children,\n ...divProps\n}: SwapStateProps): JSX.Element | null {\n const ctx = use(SwapCtx);\n if (!ctx) missingContextError('Swap.State', 'Swap');\n\n const isCurrent: boolean = ctx.current === id;\n const show: boolean = isCurrent && ctx.active === id;\n\n const { phase, ref, mounted, enter } = usePresence({\n show,\n mode: 'mount',\n enter: ctx.enter,\n exitDuration: ctx.exitDuration,\n });\n\n useImperativeHandle(forwardedRef, () => ref.current as HTMLDivElement);\n\n useEffect(() => {\n if (isCurrent && !show && phase === 'exited') {\n ctx.onExited(id);\n }\n }, [isCurrent, show, phase, id, ctx]);\n\n if (!isCurrent || !mounted) return null;\n\n return (\n <div\n {...divProps}\n ref={ref as React.RefObject<HTMLDivElement | null>}\n data-phase={phase}\n data-enter={enter === 'animate' ? 'animate' : undefined}\n >\n {children}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Compound component export\n// ---------------------------------------------------------------------------\n\nexport const Swap: typeof SwapRoot & { State: typeof SwapState } =\n Object.assign(SwapRoot, { State: SwapState });\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "phase",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "A lightweight, lifecycle-aware UI performance layer for the web. Includes tools to optimize render performance, build performant animations, and manage layout and off-screen resources",
|
|
5
5
|
"author": "Vercel",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D3epuj2x.d.ts","names":[],"sources":["../src/core/tick/index.ts","../src/core/sight/index.ts","../src/core/lifecycle/index.ts","../src/core/loop/index.ts","../src/core/render-state/index.ts","../src/core/idle/index.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reduced-motion-CEJtegNG.js","names":["pool","createPoolEntry","REDUCED_MOTION_QUERY"],"sources":["../src/core/_internal/abort/index.ts","../src/core/_internal/errors/index.ts","../src/core/tick/index.ts","../src/core/_internal/pool/io-pool.ts","../src/core/sight/index.ts","../src/core/_internal/pool/mql-pool.ts","../src/core/lifecycle/index.ts","../src/core/loop/index.ts","../src/core/scroll-progress/index.ts","../src/core/render-state/index.ts","../src/core/_internal/pool/dpr.ts","../src/core/idle/index.ts","../src/core/reduced-motion/index.ts"],"sourcesContent":["/**\n * Link an optional `AbortSignal` to a primitive's `stop`/cancel function.\n *\n * When the signal aborts, `stop` runs once. If the signal is already aborted,\n * `stop` runs synchronously. Returns an unlink function that removes the abort\n * listener. Call it from inside `stop` so a manual stop does not leave a\n * dangling listener on a long-lived controller.\n *\n * The listener is registered with `{ once: true }`, so abort and manual stop\n * are safe to interleave: whichever fires first wins, the other is a no-op.\n */\nexport function linkAbortSignal(\n signal: AbortSignal | undefined,\n stop: () => void,\n): () => void {\n if (!signal) return unlinkNoop;\n if (signal.aborted) {\n stop();\n return unlinkNoop;\n }\n signal.addEventListener('abort', stop, { once: true });\n return () => signal.removeEventListener('abort', stop);\n}\n\n/** Shared empty unlink for the no-signal and already-aborted paths. */\nfunction unlinkNoop(): void {\n // No listener was registered, so there is nothing to remove.\n}\n","export type PhaseErrorCode =\n | 'server_context'\n | 'no_element'\n | 'invalid_duration'\n | 'ticker_stopped'\n | 'missing_context';\n\ninterface PhaseErrorOptions {\n code: PhaseErrorCode;\n reason?: string;\n fix?: string;\n link?: string;\n}\n\n/** Lightweight structured error for phase. */\nexport class PhaseError extends Error {\n readonly code: PhaseErrorCode;\n readonly reason: string | undefined;\n readonly fix: string | undefined;\n readonly link: string | undefined;\n\n constructor(message: string, options: PhaseErrorOptions) {\n super(message);\n this.name = 'PhaseError';\n this.code = options.code;\n this.reason = options.reason;\n this.fix = options.fix;\n this.link = options.link;\n }\n}\n\n/** Check if a value is a PhaseError instance. */\nexport function isPhaseError(error: unknown): error is PhaseError {\n return error instanceof PhaseError;\n}\n\nexport function serverContextError(fn: string): never {\n throw new PhaseError(`${fn}() cannot be called on the server.`, {\n code: 'server_context',\n reason: 'Browser APIs are unavailable during SSR.',\n fix: 'Move into a useEffect or client-only module.',\n });\n}\n\nexport function noElementError(fn: string): never {\n throw new PhaseError(`${fn}() requires a DOM element.`, {\n code: 'no_element',\n reason: 'The element was null or undefined.',\n fix: 'Pass a mounted Element, or use the React hook which manages the ref.',\n });\n}\n\nexport function invalidDurationError(fn: string, value: number): never {\n throw new PhaseError(`${fn}() received an invalid duration: ${value}`, {\n code: 'invalid_duration',\n reason: 'Duration must be a finite positive number.',\n fix: 'Pass a positive number (e.g., 300 for 300ms).',\n });\n}\n\nexport function tickerStoppedError(): never {\n throw new PhaseError('Cannot resume a stopped ticker.', {\n code: 'ticker_stopped',\n reason: 'stop() is terminal, so a stopped ticker cannot be resumed.',\n fix: 'Create a new ticker instance instead of resuming a stopped one.',\n });\n}\n\nexport function missingContextError(child: string, parent: string): never {\n throw new PhaseError(`<${child}> must be used inside <${parent}>.`, {\n code: 'missing_context',\n reason: `<${child}> reads from a context that <${parent}> provides.`,\n fix: `Wrap <${child}> with <${parent}>.`,\n });\n}\n","import { linkAbortSignal } from '../_internal/abort';\nimport { serverContextError, tickerStoppedError } from '../_internal/errors';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FrameState {\n /** Current timestamp from performance.now(). */\n time: number;\n /** Milliseconds since last tick, clamped to 40ms. */\n delta: number;\n /** Milliseconds since start, excluding paused time. */\n elapsed: number;\n /** Frame count since start. */\n frame: number;\n}\n\nexport type TickerPhase = 'idle' | 'running' | 'paused' | 'stopped';\nexport type TickerReason =\n | 'initial'\n | 'started'\n | 'resumed'\n | 'manual'\n | 'disposed';\n\nexport interface TickerOptions {\n /** Cap frame rate. Default: uncapped (display refresh rate). */\n fps?: number;\n /**\n * Called every frame with the current frame state. Write to refs or DOM\n * directly. Never call React `setState` here (60 state updates/sec = 60 re-renders/sec).\n */\n onTick: (frame: FrameState) => void;\n /** Abort signal that stops the ticker when aborted. */\n signal?: AbortSignal;\n}\n\nexport interface Ticker {\n start(): void;\n stop(): void;\n pause(): void;\n resume(): void;\n readonly phase: TickerPhase;\n readonly phaseReason: TickerReason;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Prevents teleportation on resume. Matches motion's maxElapsed. */\nconst MAX_DELTA_MS = 40;\n\n/** Default first-frame delta when no previous tick exists. */\nconst DEFAULT_FIRST_DELTA_MS = 16.67;\n\n// ---------------------------------------------------------------------------\n// Shared frame-locked clock\n//\n// All ticker instances subscribe to a single rAF loop so they read the same\n// timestamp each frame. This prevents visual desync between multiple loops\n// on the same page. The clock starts when the first subscriber joins and\n// stops when the last one leaves.\n// ---------------------------------------------------------------------------\n\nlet sharedTime = 0;\nlet sharedRafId = 0;\nconst sharedSubscribers = new Set<() => void>();\n\nfunction sharedTick(): void {\n sharedTime = performance.now();\n for (const callback of sharedSubscribers) callback();\n if (sharedSubscribers.size > 0) {\n sharedRafId = requestAnimationFrame(sharedTick);\n }\n}\n\nfunction joinSharedClock(callback: () => void): () => void {\n const wasEmpty: boolean = sharedSubscribers.size === 0;\n sharedSubscribers.add(callback);\n\n if (wasEmpty) {\n sharedTime = performance.now();\n sharedRafId = requestAnimationFrame(sharedTick);\n }\n\n return () => {\n sharedSubscribers.delete(callback);\n if (sharedSubscribers.size === 0 && sharedRafId) {\n cancelAnimationFrame(sharedRafId);\n sharedRafId = 0;\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction resetFrameState(state: FrameState): void {\n state.time = 0;\n state.delta = 0;\n state.elapsed = 0;\n state.frame = 0;\n}\n\n// ---------------------------------------------------------------------------\n// createTicker\n// ---------------------------------------------------------------------------\n\n/**\n * Core rAF loop primitive with FPS cap, delta clamping, and strong pause.\n *\n * @remarks\n * `FrameState` is reused across frames. Do not store a reference to it.\n * Read values immediately in your `onTick` callback.\n */\nexport function createTicker(options: TickerOptions): Ticker {\n if (typeof requestAnimationFrame === 'undefined') {\n serverContextError('createTicker');\n }\n\n const { onTick, fps, signal } = options;\n const minFrameTime: number = fps ? 1000 / fps : 0;\n\n let _phase: TickerPhase = 'idle';\n let _reason: TickerReason = 'initial';\n let leaveSharedClock: (() => void) | null = null;\n\n let lastTickTime = 0;\n let pauseStartTime = 0;\n let totalPausedTime = 0;\n let startTime = 0;\n\n // Pre-allocated, mutated in place each frame — zero allocations per tick.\n const frame: FrameState = { time: 0, delta: 0, elapsed: 0, frame: 0 };\n\n function tick(): void {\n const now: number = sharedTime;\n\n // FPS throttle: skip this frame if we're ahead of the target interval.\n if (minFrameTime > 0 && now - lastTickTime < minFrameTime) return;\n\n const rawDelta: number =\n lastTickTime === 0 ? DEFAULT_FIRST_DELTA_MS : now - lastTickTime;\n lastTickTime = now;\n\n frame.time = now;\n frame.delta = rawDelta > MAX_DELTA_MS ? MAX_DELTA_MS : rawDelta;\n frame.elapsed = now - startTime - totalPausedTime;\n frame.frame++;\n\n onTick(frame);\n }\n\n function start(): void {\n if (_phase === 'running') return;\n if (_phase === 'stopped') tickerStoppedError();\n if (_phase === 'paused') {\n resume();\n return;\n }\n\n _phase = 'running';\n _reason = 'started';\n startTime = performance.now();\n lastTickTime = 0;\n totalPausedTime = 0;\n resetFrameState(frame);\n\n leaveSharedClock = joinSharedClock(tick);\n }\n\n function pause(): void {\n if (_phase !== 'running') return;\n\n _phase = 'paused';\n _reason = 'manual';\n pauseStartTime = performance.now();\n\n // Strong pause: cancel rAF subscription entirely — zero CPU while paused.\n leaveSharedClock?.();\n leaveSharedClock = null;\n }\n\n function resume(): void {\n if (_phase === 'stopped') tickerStoppedError();\n if (_phase !== 'paused') return;\n\n totalPausedTime += performance.now() - pauseStartTime;\n // Reset so the first resumed tick gets a clean delta (not the pause gap).\n lastTickTime = 0;\n\n _phase = 'running';\n _reason = 'resumed';\n leaveSharedClock = joinSharedClock(tick);\n }\n\n function stop(): void {\n if (_phase === 'stopped') return;\n\n _phase = 'stopped';\n _reason = _reason === 'initial' ? 'disposed' : 'manual';\n unlinkAbort?.();\n leaveSharedClock?.();\n leaveSharedClock = null;\n }\n\n // Declared before assignment because an already-aborted signal makes\n // linkAbortSignal call stop() synchronously, which reads unlinkAbort.\n let unlinkAbort: (() => void) | undefined;\n unlinkAbort = linkAbortSignal(signal, stop);\n\n return {\n start,\n stop,\n pause,\n resume,\n get phase() {\n return _phase;\n },\n get phaseReason() {\n return _reason;\n },\n };\n}\n","type IOCallback = (entry: IntersectionObserverEntry) => void;\n\nexport interface ObserveIntersectionOptions {\n element: Element;\n onIntersect: IOCallback;\n root?: Element | Document | null;\n rootMargin?: string;\n threshold?: number | number[];\n}\n\ninterface IOPoolEntry {\n observer: IntersectionObserver;\n callbacks: Map<Element, IOCallback>;\n}\n\nconst pool = new Map<string, IOPoolEntry>();\n\n/**\n * Observe an element via a shared IntersectionObserver pool.\n * Elements with identical options share one IO instance.\n *\n * @returns Cleanup function that unobserves the element and removes the IO if empty.\n */\nexport function observeIntersection(\n options: ObserveIntersectionOptions,\n): () => void {\n const { element, onIntersect, root, rootMargin, threshold } = options;\n const ioInit: IntersectionObserverInit = { root, rootMargin, threshold };\n\n const key: string = getPoolKey(ioInit);\n const entry: IOPoolEntry = getOrCreatePoolEntry(key, ioInit);\n\n entry.callbacks.set(element, onIntersect);\n entry.observer.observe(element);\n\n let disposed = false;\n\n return () => {\n if (disposed) return;\n disposed = true;\n\n const poolEntry: IOPoolEntry | undefined = pool.get(key);\n if (!poolEntry) return;\n\n // Only unobserve if our callback is still the registered one.\n // A later subscription on the same element would have overwritten it.\n if (poolEntry.callbacks.get(element) === onIntersect) {\n poolEntry.observer.unobserve(element);\n poolEntry.callbacks.delete(element);\n }\n\n if (poolEntry.callbacks.size === 0) {\n poolEntry.observer.disconnect();\n pool.delete(key);\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Produces a stable string key from IO options to group observers in the pool.\n * IO options are immutable after construction, so identical options can share.\n */\nfunction getPoolKey(opts: IntersectionObserverInit): string {\n const root = opts.root ? 'custom' : 'null';\n const margin = opts.rootMargin ?? '0px';\n const threshold = Array.isArray(opts.threshold)\n ? opts.threshold.join(',')\n : String(opts.threshold ?? 0);\n\n return root + '|' + margin + '|' + threshold;\n}\n\n/** Return an existing pool entry for this key, or create and register a new one. */\nfunction getOrCreatePoolEntry(\n key: string,\n options: IntersectionObserverInit,\n): IOPoolEntry {\n const existing: IOPoolEntry | undefined = pool.get(key);\n if (existing) return existing;\n\n const entry = createPoolEntry(options);\n\n pool.set(key, entry);\n return entry;\n}\n\n/** Create a new pool entry for the given options. */\nconst createPoolEntry = (options: IntersectionObserverInit): IOPoolEntry => {\n const callbacks = new Map<Element, IOCallback>();\n const observer = new IntersectionObserver((entries) => {\n for (const ioEntry of entries) {\n const cb: IOCallback | undefined = callbacks.get(ioEntry.target);\n if (cb) cb(ioEntry);\n }\n }, options);\n\n return { observer, callbacks };\n};\n","import { linkAbortSignal } from '../_internal/abort';\nimport { noElementError, serverContextError } from '../_internal/errors';\nimport { observeIntersection } from '../_internal/pool/io-pool';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SightPhase = 'unknown' | 'visible' | 'hidden';\nexport type SightReason =\n | 'initial'\n | 'viewport'\n | 'document'\n | 'bfcache'\n | 'all-hidden';\n\nexport interface SightOptions {\n element: Element;\n intersectionOptions?: IntersectionObserverInit;\n onPhaseChange?: (phase: SightPhase, reason: SightReason) => void;\n /** Abort signal that stops the observer when aborted. */\n signal?: AbortSignal;\n}\n\nexport interface Sight {\n readonly phase: SightPhase;\n readonly phaseReason: SightReason;\n stop(): void;\n}\n\n// ---------------------------------------------------------------------------\n// createSight\n// ---------------------------------------------------------------------------\n\n/**\n * Visibility observer combining document focus and viewport intersection.\n *\n * `phase` is `'visible'` only when both the document is visible (not backgrounded)\n * and the element is within the viewport. Uses a shared IntersectionObserver\n * pool. Multiple `createSight` calls with the same options share one observer.\n *\n * @example\n * const sight = createSight({\n * element: el,\n * onPhaseChange: (phase) => phase === 'visible' ? loop.start() : loop.pause(),\n * });\n * // cleanup:\n * sight.stop();\n *\n * @remarks\n * `onPhaseChange` fires only on phase transitions, not on every IntersectionObserver callback.\n */\nexport function createSight(options: SightOptions): Sight {\n if (typeof document === 'undefined') {\n serverContextError('createSight');\n }\n\n const { element, intersectionOptions, onPhaseChange, signal } = options;\n\n if (!element) noElementError('createSight');\n\n let _phase: SightPhase = 'unknown';\n let _reason: SightReason = 'initial';\n let stopped = false;\n\n let documentVisible: boolean = !document.hidden;\n let elementInView = false;\n\n function recompute(trigger: SightReason): void {\n if (stopped) return;\n\n const prev = _phase;\n const next: SightPhase =\n documentVisible && elementInView ? 'visible' : 'hidden';\n\n _reason =\n next === 'hidden' && !documentVisible && !elementInView\n ? 'all-hidden'\n : trigger;\n\n if (next === prev) return;\n _phase = next;\n onPhaseChange?.(_phase, _reason);\n }\n\n // --- Signal handlers ---\n\n function onVisibilityChange(): void {\n documentVisible = !document.hidden;\n recompute('document');\n }\n\n function onPageShow(event: PageTransitionEvent): void {\n if (!event.persisted) return;\n documentVisible = true;\n recompute('bfcache');\n }\n\n function onIntersection(entry: IntersectionObserverEntry): void {\n elementInView = entry.isIntersecting;\n recompute('viewport');\n }\n\n // --- Subscribe ---\n\n document.addEventListener('visibilitychange', onVisibilityChange);\n window.addEventListener('pageshow', onPageShow);\n const unobserveIO: () => void = observeIntersection({\n element,\n onIntersect: onIntersection,\n ...intersectionOptions,\n });\n\n let unlinkAbort: (() => void) | undefined;\n\n function stop(): void {\n if (stopped) return;\n stopped = true;\n unlinkAbort?.();\n document.removeEventListener('visibilitychange', onVisibilityChange);\n window.removeEventListener('pageshow', onPageShow);\n unobserveIO();\n _phase = 'hidden';\n _reason = 'initial';\n }\n\n unlinkAbort = linkAbortSignal(signal, stop);\n\n return {\n get phase() {\n return stopped ? 'hidden' : _phase;\n },\n get phaseReason() {\n return _reason;\n },\n stop,\n };\n}\n","type MQLCallback = (matches: boolean) => void;\n\ninterface MQLPoolEntry {\n mql: MediaQueryList;\n listeners: Set<MQLCallback>;\n handler: (e: MediaQueryListEvent) => void;\n}\n\nconst pool = new Map<string, MQLPoolEntry>();\n\n/**\n * Subscribe to a media query via a shared MediaQueryList pool.\n * Multiple subscribers to the same query share one MQL and one change listener.\n *\n * @returns Cleanup function that removes the subscriber.\n */\nexport function subscribeMediaQuery(\n query: string,\n callback: MQLCallback,\n): () => void {\n const entry: MQLPoolEntry = getOrCreateEntry(query);\n\n entry.listeners.add(callback);\n\n let disposed = false;\n\n return () => {\n if (disposed) return;\n disposed = true;\n\n const poolEntry: MQLPoolEntry | undefined = pool.get(query);\n if (!poolEntry) return;\n poolEntry.listeners.delete(callback);\n\n if (poolEntry.listeners.size === 0) {\n poolEntry.mql.removeEventListener('change', poolEntry.handler);\n pool.delete(query);\n }\n };\n}\n\n/**\n * Synchronous read of a media query via the shared pool.\n * Uses the existing pool entry if available, otherwise reads directly.\n */\nexport function readMediaQuery(query: string): boolean {\n const entry: MQLPoolEntry | undefined = pool.get(query);\n if (entry) return entry.mql.matches;\n return matchMedia(query).matches;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Return an existing pool entry for this query, or create and register a new one. */\nfunction getOrCreateEntry(query: string): MQLPoolEntry {\n const existing: MQLPoolEntry | undefined = pool.get(query);\n if (existing) return existing;\n\n const entry = createPoolEntry(query);\n\n entry.mql.addEventListener('change', entry.handler);\n pool.set(query, entry);\n\n return entry;\n}\n\nconst createPoolEntry = (query: string): MQLPoolEntry => {\n const mql: MediaQueryList = matchMedia(query);\n const listeners = new Set<MQLCallback>();\n\n const handler = (event: MediaQueryListEvent): void => {\n for (const cb of listeners) cb(event.matches);\n };\n return { mql, listeners, handler };\n};\n","import { linkAbortSignal } from '../_internal/abort';\nimport { noElementError, serverContextError } from '../_internal/errors';\nimport {\n readMediaQuery,\n subscribeMediaQuery,\n} from '../_internal/pool/mql-pool';\nimport { createSight } from '../sight';\nimport type { SightPhase } from '../sight';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type LifecyclePhase = 'idle' | 'active' | 'paused' | 'stopped';\nexport type LifecycleReason =\n | 'initial'\n | 'started'\n | 'resumed'\n | 'sight'\n | 'reduced-motion'\n | 'manual'\n | 'disposed';\n\n/** Whether reduced motion pauses the lifecycle. Default `'pause'`. */\nexport type LifecycleReducedMotion = 'pause' | 'ignore';\n\nexport interface LifecycleOptions {\n element: Element;\n reducedMotion?: LifecycleReducedMotion;\n intersectionOptions?: IntersectionObserverInit;\n start?: 'auto' | 'manual';\n onPhaseChange?: (phase: LifecyclePhase, reason: LifecycleReason) => void;\n /** Abort signal that stops the lifecycle when aborted. */\n signal?: AbortSignal;\n}\n\nexport interface Lifecycle {\n /** Begin honoring signals. Called automatically unless `start: 'manual'`. */\n start(): void;\n /** Terminal. Disposes observers and listeners. Cannot be restarted. */\n stop(): void;\n /** Manually pause (e.g. a panel opened over the animation). Lowest priority. */\n pause(): void;\n /** Clear a manual pause. */\n resume(): void;\n readonly phase: LifecyclePhase;\n readonly phaseReason: LifecycleReason;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\n// ---------------------------------------------------------------------------\n// createLifecycle\n// ---------------------------------------------------------------------------\n\n/**\n * The activation decision for an animation, decoupled from who drives the frames.\n *\n * Composes visibility (`createSight`), reduced motion, and a manual pause into a\n * single `active` / `paused` phase. Use when you own your render loop (WebGL,\n * three.js, a Web Worker, or non-rAF work that should still pause off-screen or\n * under reduced motion). For loops `phase` should drive, use `createLoop` instead.\n *\n * @example\n * const lifecycle = createLifecycle({\n * element: canvas,\n * onPhaseChange: (phase) => {\n * if (phase === 'active') renderer.start();\n * else renderer.stop();\n * },\n * });\n * // cleanup:\n * lifecycle.stop();\n */\nexport function createLifecycle(options: LifecycleOptions): Lifecycle {\n if (typeof document === 'undefined') {\n serverContextError('createLifecycle');\n }\n\n const {\n element,\n reducedMotion = 'pause',\n intersectionOptions,\n start: startMode = 'auto',\n onPhaseChange,\n signal,\n } = options;\n\n if (!element) noElementError('createLifecycle');\n\n let _phase: LifecyclePhase = 'idle';\n let _reason: LifecycleReason = 'initial';\n\n let sightVisible = false;\n let reducedMotionActive = false;\n let manualPaused = false;\n let intentStarted = false;\n let hasBeenActive = false;\n\n function setPhase(phase: LifecyclePhase, reason: LifecycleReason): void {\n if (_phase === phase && _reason === reason) return;\n _phase = phase;\n _reason = reason;\n onPhaseChange?.(phase, reason);\n }\n\n /** Highest-priority active pause signal, or null when nothing should pause. */\n function pauseReason(): LifecycleReason | null {\n if (reducedMotionActive && reducedMotion === 'pause')\n return 'reduced-motion';\n if (!sightVisible) return 'sight';\n if (manualPaused) return 'manual';\n return null;\n }\n\n function reconcile(): void {\n if (_phase === 'stopped' || !intentStarted) return;\n\n const reason = pauseReason();\n if (reason) {\n setPhase('paused', reason);\n return;\n }\n\n setPhase('active', hasBeenActive ? 'resumed' : 'started');\n hasBeenActive = true;\n }\n\n // --- Signal handlers ---\n\n function onSightChange(phase: SightPhase): void {\n sightVisible = phase === 'visible';\n reconcile();\n }\n\n function onReducedMotionChange(matches: boolean): void {\n reducedMotionActive = matches;\n reconcile();\n }\n\n // --- Init subsystems ---\n\n const sight = createSight({\n element,\n intersectionOptions,\n onPhaseChange: onSightChange,\n });\n\n let unsubReducedMotion: (() => void) | null = null;\n if (reducedMotion !== 'ignore') {\n reducedMotionActive = readMediaQuery(REDUCED_MOTION_QUERY);\n unsubReducedMotion = subscribeMediaQuery(\n REDUCED_MOTION_QUERY,\n onReducedMotionChange,\n );\n }\n\n // --- Public API ---\n\n function start(): void {\n if (_phase === 'stopped') return;\n intentStarted = true;\n reconcile();\n }\n\n function stop(): void {\n if (_phase === 'stopped') return;\n unlinkAbort?.();\n sight.stop();\n unsubReducedMotion?.();\n unsubReducedMotion = null;\n setPhase('stopped', 'disposed');\n }\n\n function pause(): void {\n if (manualPaused) return;\n manualPaused = true;\n reconcile();\n }\n\n function resume(): void {\n if (!manualPaused) return;\n manualPaused = false;\n reconcile();\n }\n\n let unlinkAbort: (() => void) | undefined;\n unlinkAbort = linkAbortSignal(signal, stop);\n\n if (startMode === 'auto') {\n start();\n }\n\n return {\n start,\n stop,\n pause,\n resume,\n get phase() {\n return _phase;\n },\n get phaseReason() {\n return _reason;\n },\n };\n}\n","import { linkAbortSignal } from '../_internal/abort';\nimport { noElementError, serverContextError } from '../_internal/errors';\nimport { createLifecycle } from '../lifecycle';\nimport { createTicker } from '../tick';\nimport type { FrameState, Ticker } from '../tick';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ReducedMotionBehavior = 'pause' | 'complete' | 'ignore';\nexport type DegradedBehavior = 'throttle' | 'pause' | 'ignore';\n\nexport type LoopPhase = 'idle' | 'running' | 'paused' | 'stopped';\nexport type LoopReason =\n | 'initial'\n | 'started'\n | 'resumed'\n | 'sight'\n | 'reduced-motion'\n | 'degraded'\n | 'manual'\n | 'disposed';\n\nexport type Quality = 'full' | 'degraded';\nexport type DegradedReason = 'unfocused' | 'frame-budget';\n\ninterface LoopOptionsBase {\n element: Element;\n /**\n * Called every frame. Write to refs or DOM directly. Never call React\n * `setState` here (60 calls/sec = 60 re-renders/sec).\n */\n onTick: (frame: FrameState) => void;\n fps?: number;\n reducedMotion?: ReducedMotionBehavior;\n intersectionOptions?: IntersectionObserverInit;\n start?: 'auto' | 'manual';\n onPhaseChange?: (phase: LoopPhase, reason: LoopReason) => void;\n /** Abort signal that stops the loop when aborted. */\n signal?: AbortSignal;\n}\n\ntype DegradedOptions =\n | { degraded?: 'throttle'; degradedFps?: number }\n | { degraded: 'pause' }\n | { degraded: 'ignore' };\n\nexport type LoopOptions = LoopOptionsBase & DegradedOptions;\n\nexport interface Loop {\n start(): void;\n stop(): void;\n readonly phase: LoopPhase;\n readonly phaseReason: LoopReason;\n readonly quality: Quality;\n readonly qualityReason: DegradedReason | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** How many consecutive over-budget frames before degrading quality. */\nconst OVER_BUDGET_THRESHOLD = 3;\n\n/** FPS cap applied when quality is degraded (throttle mode). */\nconst DEGRADED_FPS_CAP = 30;\n\n/**\n * In `degraded: 'pause'` mode a frame-budget degrade pauses the loop, so no\n * further frames tick to clear it. Without a timer the loop would stay paused\n * forever after a transient spike. After this delay the loop optimistically\n * un-pauses and re-measures, rescheduling on each subsequent degrade. (Throttle\n * mode keeps ticking, so it does not use this.)\n */\nconst RECOVERY_RETRY_MS = 2000;\n\n// ---------------------------------------------------------------------------\n// createLoop\n// ---------------------------------------------------------------------------\n\n/**\n * Lifecycle-aware animation loop composing ticker, visibility, and reduced motion.\n *\n * Pass an element and get a loop that pauses when the element leaves the viewport\n * or the tab is backgrounded, resumes when it returns, and cleans up with `stop()`.\n *\n * @remarks\n * The loop is signal-driven and exposes only `start()` and `stop()`. There is no\n * imperative `pause()`/`resume()`. Pausing is decided by visibility, reduced\n * motion, and quality, so an imperative pause would compete with those signals.\n * For manual control, use `useLoop`'s `enabled` option (React) or `createLifecycle`,\n * which exposes `pause()`/`resume()` for loops you drive yourself.\n *\n * @example\n * const loop = createLoop({\n * element: el,\n * onTick: (frame) => draw(ctx, frame),\n * });\n * // cleanup:\n * loop.stop();\n */\nexport function createLoop(options: LoopOptions): Loop {\n if (typeof requestAnimationFrame === 'undefined') {\n serverContextError('createLoop');\n }\n\n const {\n element,\n onTick,\n fps: baseFps,\n reducedMotion = 'pause',\n degraded = 'throttle' as DegradedBehavior,\n degradedFps: configuredDegradedFps,\n intersectionOptions,\n start: startMode = 'auto',\n onPhaseChange,\n signal,\n } = options as LoopOptionsBase & {\n degraded?: DegradedBehavior;\n degradedFps?: number;\n signal?: AbortSignal;\n };\n\n if (!element) noElementError('createLoop');\n\n const degradedFps: number | undefined =\n degraded === 'throttle' ? configuredDegradedFps : undefined;\n\n // --- State ---\n\n let _phase: LoopPhase = 'idle';\n let _reason: LoopReason = 'initial';\n let _quality: Quality = 'full';\n let _qualityReason: DegradedReason | undefined;\n\n let intentStarted = false;\n let overBudgetCount = 0;\n let ticker: Ticker | null = null;\n\n // Quality signal flags\n let focusDegraded = false;\n\n // Pending pause-mode frame-budget recovery timer (see RECOVERY_RETRY_MS).\n let recoveryTimer: ReturnType<typeof setTimeout> | null = null;\n\n // --- State transitions ---\n\n function setPhase(phase: LoopPhase, reason: LoopReason): void {\n if (_phase === phase && _reason === reason) return;\n _phase = phase;\n _reason = reason;\n onPhaseChange?.(phase, reason);\n }\n\n function setQuality(quality: Quality, reason?: DegradedReason): void {\n const changed = _quality !== quality;\n _quality = quality;\n _qualityReason = reason;\n\n if (!changed) return;\n\n if (degraded === 'throttle') {\n if (ticker && _phase === 'running') {\n queueMicrotask(rebuildTicker);\n }\n } else if (degraded === 'pause') {\n reconcile();\n }\n }\n\n /** Evaluate all quality signals and pick the highest-priority active one. */\n function reconcileQuality(): void {\n if (focusDegraded) {\n setQuality('degraded', 'unfocused');\n return;\n }\n if (overBudgetCount >= OVER_BUDGET_THRESHOLD) {\n setQuality('degraded', 'frame-budget');\n return;\n }\n setQuality('full');\n }\n\n /**\n * Un-pause and re-measure after a pause-mode frame-budget degrade. If frames\n * are still over budget, the next degrade reschedules this.\n */\n function scheduleBudgetRecovery(): void {\n if (recoveryTimer !== null) return;\n recoveryTimer = setTimeout(() => {\n recoveryTimer = null;\n overBudgetCount = 0;\n reconcileQuality();\n }, RECOVERY_RETRY_MS);\n }\n\n function clearBudgetRecovery(): void {\n if (recoveryTimer === null) return;\n clearTimeout(recoveryTimer);\n recoveryTimer = null;\n }\n\n // --- Ticker lifecycle ---\n\n function getEffectiveFps(): number | undefined {\n if (_quality !== 'degraded') return baseFps;\n const cap: number = degradedFps ?? DEGRADED_FPS_CAP;\n if (baseFps === undefined) return cap;\n return Math.min(baseFps, cap);\n }\n\n function destroyTicker(): void {\n if (!ticker) return;\n ticker.stop();\n ticker = null;\n }\n\n function buildTicker(): void {\n const targetFps: number | undefined = getEffectiveFps();\n const budget: number = 1000 / (targetFps ?? 60);\n\n destroyTicker();\n\n ticker = createTicker({\n fps: targetFps,\n onTick: (frame) => {\n checkFrameBudget(frame.delta, budget);\n onTick(frame);\n },\n });\n ticker.start();\n }\n\n function rebuildTicker(): void {\n if (_phase !== 'running' || !ticker) return;\n buildTicker();\n }\n\n function checkFrameBudget(delta: number, budget: number): void {\n if (delta <= budget * 1.5) {\n overBudgetCount = 0;\n return;\n }\n\n overBudgetCount++;\n if (overBudgetCount < OVER_BUDGET_THRESHOLD) return;\n\n reconcileQuality();\n // Pause mode stops ticking once degraded, so no future frame can clear the\n // degraded state — schedule a timed retry. Throttle keeps running.\n if (degraded === 'pause') scheduleBudgetRecovery();\n }\n\n // --- Reconcile ---\n\n /** Check if any signal requires the loop to be paused. */\n function shouldPause(): LoopReason | null {\n // Visibility + reduced motion are owned by the lifecycle; its paused reasons\n // ('sight' | 'reduced-motion') are a subset of LoopReason.\n if (lifecycle.phase === 'paused')\n return lifecycle.phaseReason as LoopReason;\n // Quality-driven pause stays here — it needs the ticker's frame timing.\n if (degraded === 'pause' && _quality === 'degraded') return 'degraded';\n return null;\n }\n\n /** Evaluate all signals and transition to the correct phase. */\n function reconcile(): void {\n if (_phase === 'stopped' || !intentStarted) return;\n\n const pauseReason = shouldPause();\n\n if (pauseReason) {\n if (ticker && _phase === 'running') ticker.pause();\n setPhase('paused', pauseReason);\n return;\n }\n\n if (!ticker) {\n buildTicker();\n setPhase('running', _reason === 'initial' ? 'started' : 'resumed');\n } else if (_phase === 'paused') {\n ticker.resume();\n setPhase('running', 'resumed');\n }\n }\n\n // --- Signal handlers ---\n\n function onFocusChange(): void {\n focusDegraded = !document.hasFocus();\n reconcileQuality();\n }\n\n // --- Init subsystems ---\n\n // Lifecycle owns the visibility + reduced-motion decision. The loop layers the\n // ticker and quality (frame-budget / focus) on top. Driven manually so it only\n // activates once the loop itself starts.\n const lifecycle = createLifecycle({\n element,\n reducedMotion: reducedMotion === 'pause' ? 'pause' : 'ignore',\n intersectionOptions,\n start: 'manual',\n onPhaseChange: reconcile,\n });\n\n const unsubFocus: () => void = subscribeFocusTracking(onFocusChange);\n\n // --- Public API ---\n\n function start(): void {\n if (_phase === 'stopped') return;\n intentStarted = true;\n lifecycle.start();\n reconcile();\n }\n\n function stop(): void {\n if (_phase === 'stopped') return;\n unlinkAbort?.();\n clearBudgetRecovery();\n destroyTicker();\n lifecycle.stop();\n unsubFocus();\n setPhase('stopped', 'disposed');\n }\n\n // Declared before assignment because an already-aborted signal makes\n // linkAbortSignal call stop() synchronously, which reads unlinkAbort.\n let unlinkAbort: (() => void) | undefined;\n unlinkAbort = linkAbortSignal(signal, stop);\n\n if (startMode === 'auto') {\n start();\n }\n\n return {\n start,\n stop,\n get phase() {\n return _phase;\n },\n get phaseReason() {\n return _reason;\n },\n get quality() {\n return _quality;\n },\n get qualityReason() {\n return _qualityReason;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction subscribeFocusTracking(onChange: () => void): () => void {\n window.addEventListener('focus', onChange);\n window.addEventListener('blur', onChange);\n return () => {\n window.removeEventListener('focus', onChange);\n window.removeEventListener('blur', onChange);\n };\n}\n","import { linkAbortSignal } from '../_internal/abort';\nimport { noElementError, serverContextError } from '../_internal/errors';\nimport { observeIntersection } from '../_internal/pool/io-pool';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ScrollProgressOptions {\n element: Element;\n /** Called when the intersection ratio changes at a threshold crossing. */\n onProgress: (ratio: number) => void;\n /** Number of evenly-spaced thresholds. Default 20 (~5% granularity). */\n steps?: number;\n root?: Element | Document | null;\n rootMargin?: string;\n /** Abort signal that stops the observer when aborted. */\n signal?: AbortSignal;\n}\n\nexport interface ScrollProgress {\n /** Current intersection ratio (0–1). Synchronous read of the last-reported value. */\n readonly ratio: number;\n stop(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_STEPS = 20;\n\n// ---------------------------------------------------------------------------\n// Threshold cache\n//\n// Most consumers use the same step count. Cache the array so the IO pool\n// receives stable references and identical pool keys without re-allocating.\n// ---------------------------------------------------------------------------\n\nconst thresholdCache = new Map<number, number[]>();\n\nfunction buildThresholds(steps: number): number[] {\n const cached: number[] | undefined = thresholdCache.get(steps);\n if (cached) return cached;\n\n const thresholds: number[] = [];\n for (let i = 0; i <= steps; i++) {\n thresholds.push(i / steps);\n }\n thresholdCache.set(steps, thresholds);\n return thresholds;\n}\n\n// ---------------------------------------------------------------------------\n// createScrollProgress\n// ---------------------------------------------------------------------------\n\n/**\n * Observe what fraction of an element is visible in the viewport (0–1).\n *\n * Uses the shared IntersectionObserver pool with multi-threshold options.\n * Multiple instances with the same `steps` share a single IO.\n *\n * @example\n * const progress = createScrollProgress({\n * element: el,\n * onProgress: (ratio) => {\n * el.style.opacity = String(ratio);\n * },\n * });\n * // cleanup:\n * progress.stop();\n */\nexport function createScrollProgress(\n options: ScrollProgressOptions,\n): ScrollProgress {\n if (typeof IntersectionObserver === 'undefined') {\n serverContextError('createScrollProgress');\n }\n\n const {\n element,\n onProgress,\n steps = DEFAULT_STEPS,\n root,\n rootMargin,\n signal,\n } = options;\n\n if (!element) noElementError('createScrollProgress');\n\n let _ratio = 0;\n let stopped = false;\n\n const threshold: number[] = buildThresholds(steps);\n\n const unobserve: () => void = observeIntersection({\n element,\n onIntersect: (entry: IntersectionObserverEntry) => {\n const newRatio: number = entry.intersectionRatio;\n if (newRatio === _ratio) return;\n _ratio = newRatio;\n onProgress(newRatio);\n },\n root,\n rootMargin,\n threshold,\n });\n\n let unlinkAbort: (() => void) | undefined;\n\n function stop(): void {\n if (stopped) return;\n stopped = true;\n unlinkAbort?.();\n unobserve();\n }\n\n unlinkAbort = linkAbortSignal(signal, stop);\n\n return {\n get ratio(): number {\n return _ratio;\n },\n stop,\n };\n}\n","import { linkAbortSignal } from '../_internal/abort';\nimport { noElementError, serverContextError } from '../_internal/errors';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type RenderPhase = 'rendered' | 'skipped';\n\nexport interface RenderStateOptions {\n element: Element;\n onPhaseChange?: (phase: RenderPhase) => void;\n /** Abort signal that stops the observer when aborted. */\n signal?: AbortSignal;\n}\n\nexport interface RenderState {\n /** Whether the browser is currently rendering the element or skipping it. */\n readonly phase: RenderPhase;\n stop(): void;\n}\n\n// ---------------------------------------------------------------------------\n// createRenderState\n// ---------------------------------------------------------------------------\n\n/**\n * Report whether the browser is rendering an element or skipping it under\n * `content-visibility`. Listens to the `contentvisibilityautostatechange`\n * event, the browser's ground-truth paint decision.\n *\n * Use it to pause raw, non-phase work (a hand-written rAF loop, `setInterval`,\n * expensive effects) when a `Defer` subtree stops painting. phase's own loops\n * already self-pause off-screen, so they do not need this.\n *\n * Listening and reacting has zero layout effect. It never breaks the\n * no-layout-shift guarantee of `content-visibility`.\n *\n * @example\n * const render = createRenderState({\n * element: el,\n * onPhaseChange: (phase) => phase === 'skipped' ? clock.pause() : clock.resume(),\n * });\n * // cleanup:\n * render.stop();\n *\n * @remarks\n * Where `content-visibility` is unsupported, `phase` stays `'rendered'`.\n *\n * Per the CSS Containment spec, `ResizeObserver` callbacks pause for elements\n * inside a skipped `content-visibility: auto` subtree. Use this primitive to\n * detect that transition when your code depends on size observations resuming.\n */\nexport function createRenderState(options: RenderStateOptions): RenderState {\n if (typeof document === 'undefined') {\n serverContextError('createRenderState');\n }\n\n const { element, onPhaseChange, signal } = options;\n\n if (!element) noElementError('createRenderState');\n\n let _phase: RenderPhase = 'rendered';\n let stopped = false;\n\n function onStateChange(event: Event): void {\n if (stopped) return;\n const next: RenderPhase = (event as ContentVisibilityAutoStateChangeEvent)\n .skipped\n ? 'skipped'\n : 'rendered';\n if (next === _phase) return;\n _phase = next;\n onPhaseChange?.(_phase);\n }\n\n element.addEventListener('contentvisibilityautostatechange', onStateChange);\n\n let unlinkAbort: (() => void) | undefined;\n\n function stop(): void {\n if (stopped) return;\n stopped = true;\n unlinkAbort?.();\n element.removeEventListener(\n 'contentvisibilityautostatechange',\n onStateChange,\n );\n }\n\n unlinkAbort = linkAbortSignal(signal, stop);\n\n return {\n get phase() {\n return _phase;\n },\n stop,\n };\n}\n","type DprCallback = (dpr: number) => void;\n\nconst listeners = new Set<DprCallback>();\n\n// Last-bound DPR. Set by bind() before the MQL is created; only meaningful\n// while a subscription is active.\nlet currentDpr = 1;\n\nlet mql: MediaQueryList | null = null;\nlet handler: (() => void) | null = null;\n\n/**\n * Subscribe to devicePixelRatio changes (e.g. user drags window between monitors).\n *\n * Uses a single shared `matchMedia` query that re-subscribes on every DPR change,\n * so chained monitor switches (A -> B -> C) are all caught.\n *\n * @returns Cleanup function that removes the subscriber.\n */\nexport function subscribeDpr(callback: DprCallback): () => void {\n listeners.add(callback);\n\n if (listeners.size === 1) {\n bind();\n }\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n listeners.delete(callback);\n if (listeners.size === 0) {\n unbind();\n }\n };\n}\n\n/** Read the current devicePixelRatio. */\nexport function readDpr(): number {\n if (typeof window === 'undefined') return 1;\n return window.devicePixelRatio || 1;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: bind/unbind the resolution MQL\n// ---------------------------------------------------------------------------\n\nfunction bind(): void {\n if (typeof matchMedia === 'undefined') return;\n currentDpr = window.devicePixelRatio || 1;\n mql = matchMedia(`(resolution: ${currentDpr}dppx)`);\n handler = onDprChange;\n mql.addEventListener('change', handler);\n}\n\nfunction unbind(): void {\n if (mql && handler) {\n mql.removeEventListener('change', handler);\n }\n mql = null;\n handler = null;\n}\n\nfunction onDprChange(): void {\n const newDpr: number = window.devicePixelRatio || 1;\n if (newDpr === currentDpr) return;\n currentDpr = newDpr;\n\n // Re-subscribe with the new DPR value so the next change is caught.\n unbind();\n bind();\n\n for (const cb of listeners) cb(newDpr);\n}\n","import { linkAbortSignal } from '../_internal/abort';\nimport { serverContextError } from '../_internal/errors';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface IdleOptions {\n /** Max ms to wait before running the callback even if no idle period occurs. */\n timeout?: number;\n /** Abort signal that cancels the scheduled callback when aborted. */\n signal?: AbortSignal;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Fallback delay when `requestIdleCallback` is unavailable (e.g. Safari). */\nconst FALLBACK_DELAY = 1;\n\n// ---------------------------------------------------------------------------\n// whenIdle\n// ---------------------------------------------------------------------------\n\n/**\n * Run a callback once the browser is idle. Wraps `requestIdleCallback`, falling\n * back to a near-immediate `setTimeout` where it is unavailable (Safari).\n *\n * Returns a cancel function. Calling it before the callback runs prevents it.\n *\n * @example\n * const cancel = whenIdle(() => warmCache(), { timeout: 2000 });\n * // later, if no longer needed:\n * cancel();\n */\nexport function whenIdle(\n callback: () => void,\n options?: IdleOptions,\n): () => void {\n if (typeof window === 'undefined') {\n serverContextError('whenIdle');\n }\n\n const { timeout, signal } = options ?? {};\n\n // Already aborted: never schedule, and hand back a no-op cancel.\n if (signal?.aborted) {\n return () => {\n // Nothing was scheduled, so there is nothing to cancel.\n };\n }\n\n let cancel: () => void;\n\n if (typeof window.requestIdleCallback === 'function') {\n // Capture cancelIdleCallback now (bound to window), rather than reading\n // window.cancelIdleCallback inside the returned closure. The cancel may run\n // after the global is swapped out (e.g. test teardown unstubbing globals),\n // and a late lookup would throw \"not a function\". Binding also avoids an\n // illegal-invocation error from calling it detached from window.\n const cancelIdle = window.cancelIdleCallback.bind(window);\n const handle: number = window.requestIdleCallback(\n () => callback(),\n timeout === undefined ? undefined : { timeout },\n );\n cancel = () => cancelIdle(handle);\n } else {\n const handle: ReturnType<typeof setTimeout> = setTimeout(\n callback,\n FALLBACK_DELAY,\n );\n cancel = () => clearTimeout(handle);\n }\n\n const unlinkAbort: () => void = linkAbortSignal(signal, cancel);\n\n return () => {\n unlinkAbort();\n cancel();\n };\n}\n","import { readMediaQuery } from '../_internal/pool/mql-pool';\n\nexport const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\n/**\n * Synchronous check for `prefers-reduced-motion: reduce`.\n *\n * Returns `false` on the server (no `matchMedia`). On the client, reads from\n * the shared MQL pool so the underlying `MediaQueryList` is reused across\n * all callers.\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof matchMedia === 'undefined') return false;\n return readMediaQuery(REDUCED_MOTION_QUERY);\n}\n"],"mappings":"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"}
|