{"version":3,"sources":["../src/hooks/use-id.ts","../src/hooks/use-node-registry.ts","../src/theme.ts","../src/hooks/use-theme.ts"],"names":["useReactId","useRef","useState","useCallback","useEffect"],"mappings":"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","file":"chunk-HPNIEYSJ.cjs","sourcesContent":["import { useId as useReactId } from \"react\";\n\nexport function useId(prefix?: string): string {\n  const id = useReactId();\n  return prefix ? `${prefix}-${id}` : id;\n}\n","import { useCallback, useRef, useState } from \"react\";\n\nexport interface NodeRect {\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n}\n\ninterface UseNodeRegistryReturn {\n  registerNode: (id: string, rect: NodeRect) => void;\n  unregisterNode: (id: string) => void;\n  nodeRects: Map<string, NodeRect>;\n  version: number;\n}\n\nexport function useNodeRegistry(): UseNodeRegistryReturn {\n  const rectsRef = useRef(new Map<string, NodeRect>());\n  const [version, setVersion] = useState(0);\n\n  const registerNode = useCallback((id: string, rect: NodeRect) => {\n    rectsRef.current.set(id, rect);\n    setVersion((v) => v + 1);\n  }, []);\n\n  const unregisterNode = useCallback((id: string) => {\n    rectsRef.current.delete(id);\n    setVersion((v) => v + 1);\n  }, []);\n\n  return { registerNode, unregisterNode, nodeRects: rectsRef.current, version };\n}\n","/**\n * Light / dark / **system** theming.\n *\n * `styles.css` in this package defines the dark contract — it redefines the\n * whole `--color-secondary-*` scale under `:where(.dark)` so that \"900\" always\n * means strongest foreground and \"50\" always means faintest surface. This module\n * is the other half of that contract: the thing that decides when `.dark` is on.\n *\n * It lives here rather than in each app because every consumer was hand-rolling\n * it, and every hand-rolled copy had the same two holes:\n *\n *  - **No live listener.** The OS preference was read once at boot, so changing\n *    the system theme with the page open did nothing. That is a default, not a\n *    \"system\" mode.\n *  - **No way back.** Choosing light or dark wrote to storage forever, so\n *    \"follow my system\" was unreachable after a single click.\n *\n * Both are fixed by treating **\"system\" as the absence of a stored choice**\n * rather than as a third stored value.\n *\n * Every export is safe to call during SSR, where it is a no-op that resolves to\n * `\"light\"`. Pair it with `useTheme`, which deliberately renders `system/light`\n * on the server and syncs in an effect — this project has paid for hydration\n * mismatches caused by reading the real theme during render.\n */\n\nexport type ThemePreference = \"light\" | \"dark\" | \"system\";\nexport type ResolvedTheme = \"light\" | \"dark\";\n\n/**\n * Deliberately the key the showcase already used, so adopting this module keeps\n * a returning visitor's saved choice instead of silently resetting it.\n */\nexport const THEME_STORAGE_KEY = \"fancy-ui.theme\";\n\nconst DARK_QUERY = \"(prefers-color-scheme: dark)\";\n\ntype ThemeListener = (resolved: ResolvedTheme, preference: ThemePreference) => void;\n\nconst listeners = new Set<ThemeListener>();\nlet storageKey = THEME_STORAGE_KEY;\nlet stopWatchingSystem: (() => void) | null = null;\n\nfunction canUseDom(): boolean {\n    return typeof window !== \"undefined\" && typeof document !== \"undefined\";\n}\n\n/** The stored choice, or `\"system\"` when there isn't one. */\nexport function getThemePreference(): ThemePreference {\n    if (!canUseDom()) return \"system\";\n    try {\n        const saved = window.localStorage.getItem(storageKey);\n        return saved === \"light\" || saved === \"dark\" ? saved : \"system\";\n    } catch {\n        // Private browsing and blocked storage both throw here. A theme is not\n        // worth taking the page down over.\n        return \"system\";\n    }\n}\n\nfunction systemTheme(): ResolvedTheme {\n    if (!canUseDom() || typeof window.matchMedia !== \"function\") return \"light\";\n    return window.matchMedia(DARK_QUERY).matches ? \"dark\" : \"light\";\n}\n\n/** What is actually on screen, as opposed to what the user asked for. */\nexport function resolveTheme(preference: ThemePreference = getThemePreference()): ResolvedTheme {\n    return preference === \"system\" ? systemTheme() : preference;\n}\n\nfunction applyToDocument(resolved: ResolvedTheme): void {\n    if (!canUseDom()) return;\n    const root = document.documentElement;\n    // The class is what this package's CSS keys off; the attribute is for\n    // consumers whose own styles key off `[data-theme]`.\n    root.classList.toggle(\"dark\", resolved === \"dark\");\n    root.setAttribute(\"data-theme\", resolved);\n}\n\nfunction publish(): void {\n    const preference = getThemePreference();\n    const resolved = resolveTheme(preference);\n    applyToDocument(resolved);\n    listeners.forEach((listener) => listener(resolved, preference));\n}\n\n/**\n * Choose a theme. `\"system\"` REMOVES the stored value rather than storing the\n * string — an absent choice is what lets the OS keep speaking for the user.\n */\nexport function setThemePreference(preference: ThemePreference): void {\n    if (canUseDom()) {\n        try {\n            if (preference === \"system\") {\n                window.localStorage.removeItem(storageKey);\n            } else {\n                window.localStorage.setItem(storageKey, preference);\n            }\n        } catch {\n            // As above: still apply it for this page even if it cannot persist.\n        }\n    }\n    publish();\n}\n\n/** Observe theme changes. Returns an unsubscribe. */\nexport function subscribeTheme(listener: ThemeListener): () => void {\n    listeners.add(listener);\n    return () => {\n        listeners.delete(listener);\n    };\n}\n\n/**\n * Apply the current theme and start following the OS. Call once, as early as\n * possible — before first paint if you want to avoid a flash of the wrong\n * theme. Returns a disposer; calling it again is harmless.\n */\nexport function initTheme(options: { storageKey?: string } = {}): () => void {\n    if (options.storageKey) storageKey = options.storageKey;\n    if (!canUseDom()) return () => {};\n\n    applyToDocument(resolveTheme());\n\n    if (!stopWatchingSystem && typeof window.matchMedia === \"function\") {\n        const media = window.matchMedia(DARK_QUERY);\n        const onSystemChange = (): void => {\n            // Only \"system\" follows the OS. An explicit choice has to survive\n            // the user switching their OS theme, or it isn't a choice.\n            if (getThemePreference() === \"system\") publish();\n        };\n\n        if (typeof media.addEventListener === \"function\") {\n            media.addEventListener(\"change\", onSystemChange);\n            stopWatchingSystem = () => media.removeEventListener(\"change\", onSystemChange);\n        } else {\n            // Safari < 14 and friends.\n            media.addListener(onSystemChange);\n            stopWatchingSystem = () => media.removeListener(onSystemChange);\n        }\n    }\n\n    return () => {\n        stopWatchingSystem?.();\n        stopWatchingSystem = null;\n    };\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport {\n    getThemePreference,\n    resolveTheme,\n    setThemePreference,\n    subscribeTheme,\n    type ResolvedTheme,\n    type ThemePreference,\n} from \"../theme\";\n\nexport type UseThemeResult = {\n    /** What the user asked for, including `\"system\"`. */\n    preference: ThemePreference;\n    /** What is actually on screen. */\n    resolved: ResolvedTheme;\n    setPreference: (preference: ThemePreference) => void;\n};\n\n/**\n * Read and set the theme from a component, re-rendering when it changes —\n * including when the OS theme changes underneath a `\"system\"` preference.\n *\n * The initial state is deliberately `system` / `light` rather than the real\n * theme: the server has neither storage nor an OS preference, so reading the\n * truth during render is exactly the hydration mismatch this project has\n * already chased down more than once. The effect syncs immediately on mount.\n */\nexport function useTheme(): UseThemeResult {\n    const [state, setState] = useState<{ preference: ThemePreference; resolved: ResolvedTheme }>({\n        preference: \"system\",\n        resolved: \"light\",\n    });\n\n    useEffect(() => {\n        const sync = (): void => {\n            setState({ preference: getThemePreference(), resolved: resolveTheme() });\n        };\n        sync();\n        return subscribeTheme(sync);\n    }, []);\n\n    const setPreference = useCallback((preference: ThemePreference): void => {\n        setThemePreference(preference);\n    }, []);\n\n    return { ...state, setPreference };\n}\n"]}