@ai-matrx/kit 0.7.3 → 0.8.0
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/CHANGELOG.md +89 -0
- package/dist/format.cjs +210 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.cts +171 -0
- package/dist/format.d.ts +171 -0
- package/dist/format.js +189 -0
- package/dist/format.js.map +1 -0
- package/dist/html-escape.cjs +38 -0
- package/dist/html-escape.cjs.map +1 -0
- package/dist/html-escape.d.cts +40 -0
- package/dist/html-escape.d.ts +40 -0
- package/dist/html-escape.js +17 -0
- package/dist/html-escape.js.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/uuid.cjs +35 -0
- package/dist/uuid.cjs.map +1 -0
- package/dist/uuid.d.cts +38 -0
- package/dist/uuid.d.ts +38 -0
- package/dist/uuid.js +14 -0
- package/dist/uuid.js.map +1 -0
- package/package.json +37 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/autosave.ts","../src/latest-request.ts","../src/clipboard.ts","../src/search-scoring.ts","../src/concurrency.ts","../src/text-case.ts","../src/drafts/use-durable-draft.ts","../src/drafts/local-drafts.ts","../src/confirm/opener.ts","../src/confirm/host.tsx","../src/confirm/cn.ts","../src/confirm/alert-dialog.tsx","../src/react-tree.ts","../src/confirm/confirm-dialog.tsx","../src/toast.ts","../src/invalidation.ts","../src/delimiter-guard.ts","../src/json-format/detect.ts","../src/json-format/json-value.ts","../src/json-format/format.ts","../src/idle-scheduler/scheduler.ts","../src/idle-scheduler/hooks.ts","../src/url-state.ts","../src/idb-store/store-manager.ts","../src/idb-store/store-interface.ts","../src/idb-store/feature-store.ts","../src/idb-store/singleton.ts","../src/color-util/lab-delta.ts","../src/color-util/tailwind-colors.ts","../src/color-util/tailwind.ts","../src/color-util/formats.ts","../src/color-util/normalize.ts","../src/qr.ts"],"sourcesContent":["/**\n * @ai-matrx/kit — the always-include package.\n *\n * One package gives you the little primitives every Matrx application speaks,\n * one capability per subpath (`/autosave`, `/latest-request`, `/clipboard`,\n * `/confirm`, `/toast`, `/invalidation`, `/delimiter-guard`, `/json-format`,\n * `/idle-scheduler`, `/url-state`, `/idb-store`, `/color-util`, `/react-tree`,\n * `/qr`, more to come: copy-for-ai). The root re-exports everything for\n * convenience; production consumers import the subpath so tree-shaking keeps\n * them lean.\n *\n * React is the only required peer. The `/confirm` subpath additionally\n * bundles `@radix-ui/react-alert-dialog` + `tailwind-merge` (its product IS\n * the dialog), `/json-format` depends on `json5` (tolerant parsing IS the\n * feature), `/idb-store` depends on `idb` (the typed IndexedDB wrapper IS\n * the engine), and `/qr` lazily loads `jsqr` when the native detector is\n * absent (the fallback IS the capability); every other subpath is\n * dependency-free. Importing any entry point performs no network, storage,\n * or global-state work.\n */\nexport * from \"./autosave\";\nexport * from \"./latest-request\";\nexport * from \"./clipboard\";\nexport * from \"./search-scoring\";\nexport * from \"./concurrency\";\nexport * from \"./text-case\";\nexport * from \"./drafts\";\nexport * from \"./confirm\";\nexport * from \"./toast\";\nexport * from \"./invalidation\";\nexport * from \"./delimiter-guard\";\nexport * from \"./json-format\";\nexport * from \"./idle-scheduler\";\nexport * from \"./url-state\";\nexport * from \"./idb-store\";\nexport * from \"./color-util\";\nexport * from \"./react-tree\";\nexport * from \"./qr\";\n","// A small, generic autosave primitive: debounce a payload, persist it through a\n// caller-supplied async save, and expose a status a UI can show (\"Saving…\" /\n// \"Saved\" / \"Unsaved changes\" / error). Entity-agnostic — the caller owns WHAT\n// to save (the save fn) and WHAT the payload is; this owns the debounce, the\n// in-flight coalescing, the status, and the flush-on-unmount so no keystroke is\n// ever lost. (Notes have their own coupled version; this is the reusable one.)\n// Never throws: the save fn returns `{ error }` (supabase-service style) and a\n// non-null error flips status to \"error\" and re-queues, so a blocked write is\n// loud, not silent.\n// React Compiler is on: no manual useMemo / useCallback — plain closures.\n\n\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type AutosaveStatus = \"idle\" | \"unsaved\" | \"saving\" | \"saved\" | \"error\";\n\nexport interface UseAutosaveResult<T> {\n status: AutosaveStatus;\n lastSavedAt: Date | null;\n /** Queue a payload and (re)start the debounce. */\n schedule: (value: T) => void;\n /** Cancel the debounce and save the pending payload immediately. */\n flush: () => void;\n}\n\nexport function useAutosave<T>(opts: {\n save: (value: T) => Promise<{ error: string | null }>;\n debounceMs?: number;\n}): UseAutosaveResult<T> {\n const { save, debounceMs = 900 } = opts;\n const [status, setStatus] = useState<AutosaveStatus>(\"idle\");\n const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null);\n\n const pendingRef = useRef<{ value: T } | null>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const savingRef = useRef(false);\n // Keep the latest save fn without threading it through closures (updated in an\n // effect, never during render).\n const saveRef = useRef(save);\n useEffect(() => {\n saveRef.current = save;\n });\n\n async function saveNow(): Promise<void> {\n if (savingRef.current) return; // a later debounce flush picks up new edits\n const pending = pendingRef.current;\n if (!pending) return;\n pendingRef.current = null;\n savingRef.current = true;\n setStatus(\"saving\");\n let failed = false;\n try {\n const res = await saveRef.current(pending.value);\n if (res.error) {\n // Re-queue so the NEXT schedule/flush retries; surface loudly.\n failed = true;\n pendingRef.current = pendingRef.current ?? pending;\n setStatus(\"error\");\n } else {\n setLastSavedAt(new Date());\n setStatus(pendingRef.current ? \"unsaved\" : \"saved\");\n }\n } catch {\n failed = true;\n pendingRef.current = pendingRef.current ?? pending;\n setStatus(\"error\");\n } finally {\n savingRef.current = false;\n // If edits arrived mid-save, drain them promptly. NEVER drain after a\n // failure: the re-queued payload waits for the next schedule/flush —\n // draining it here is an unbounded immediate-retry loop against a\n // persistently failing save. (The matrx-frontend original has exactly\n // that loop; it dies with the original at the adoption swap.)\n if (pendingRef.current && !failed) void saveNow();\n }\n }\n\n function schedule(value: T): void {\n pendingRef.current = { value };\n setStatus(\"unsaved\");\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => void saveNow(), debounceMs);\n }\n\n function flush(): void {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n void saveNow();\n }\n\n // Flush any pending payload on unmount so an in-progress edit is never lost.\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n const pending = pendingRef.current;\n if (pending && !savingRef.current) {\n pendingRef.current = null;\n void saveRef.current(pending.value);\n }\n };\n }, []);\n\n return { status, lastSavedAt, schedule, flush };\n}\n","\"use client\";\n\n/**\n * useLatestRequest — makes a superseded async response impossible to apply.\n *\n * THE BUG THIS KILLS: a surface refetches whenever some input changes (a\n * `?app=` scope, a search box, a selected id). Two fetches are then in flight\n * at once, and **responses do not arrive in the order they were sent.** The\n * older one lands last, calls `setRows`, and wins — so the table shows app A's\n * runs while the banner, the URL, and every label already say app B.\n *\n * That is not stale data, which announces itself. It is the WRONG RECORD under\n * a CONFIDENT label — the same failure `StaleDataNotice` exists to prevent on\n * the error path, arriving through the success path instead. Clearing rows when\n * a fetch FAILS (which this repo already does) closes only half the hole: a\n * fetch that succeeds late is just as capable of mislabeling the screen, and\n * nothing about it looks wrong.\n *\n * `AbortController` is the other half of the answer and a good thing to add on\n * top — but it is not a substitute. An abort races the response; the request may\n * already have resolved, and a non-`fetch` data source (a Supabase client call,\n * an RPC wrapper) often has no signal to give. This guard is source-agnostic and\n * final: it decides at APPLY time, which is the only moment that matters.\n *\n * ```ts\n * const beginRequest = useLatestRequest();\n *\n * const load = useCallback(async () => {\n * const isCurrent = beginRequest(); // claim this attempt\n * setLoading(true);\n * try {\n * const data = await fetchScopedRows(appId);\n * if (!isCurrent()) return; // a newer load already started\n * setRows(data);\n * } catch (err) {\n * if (!isCurrent()) return; // don't let an old failure blank new rows\n * setRows([]);\n * setLoadFailed(true);\n * } finally {\n * if (isCurrent()) setLoading(false);\n * }\n * }, [appId, beginRequest]);\n * ```\n *\n * **Guard the catch and the finally too, not just the success path.** A stale\n * REJECTION is the mirror-image bug: it wipes the rows the current request just\n * loaded and raises a \"couldn't load\" notice about a request nobody is waiting\n * for. And an early `setLoading(false)` from a superseded attempt reports the\n * surface as settled while the real one is still in flight.\n *\n * `begin()` returns the predicate rather than exposing a counter, so there is no\n * sequence number to compare wrongly and no way to ask \"is my request current?\"\n * without first having declared one.\n *\n * Three hand-rolled copies of this exact `requestSeq`/`reqIdRef` pattern predate\n * it — `useServerAgentSearch`, `useRagSearch`, `useContextPreview`. They are\n * correct; they are just the evidence that this is a class, not an incident. New\n * code uses this hook, and those three collapse onto it when next touched.\n */\n\nimport { useCallback, useRef } from \"react\";\n\n/**\n * Marks a new attempt as the current one and returns a predicate reporting\n * whether it still is. Call it once at the top of the async function, then\n * check the predicate before EVERY state write that follows an `await`.\n */\nexport type BeginRequest = () => () => boolean;\n\n/**\n * 🚨 RETURNS THE FUNCTION ITSELF, NOT AN OBJECT WRAPPING IT — deliberately, and\n * this is the whole reason the signature looks like that.\n *\n * The first version returned `{ begin }`. That object literal is a NEW\n * reference on every render, and the entire point of this hook is to be named\n * in the dependency array of the very `useCallback` that performs the fetch. An\n * unstable dependency there makes `load` unstable, which makes the\n * `useEffect(…, [load])` that calls it re-run on every render — an unbroken\n * refetch loop against the database with no user input at all. A guard against\n * a fetch race that instead causes infinite fetches is worse than the bug it\n * was written to fix, and it is a High-severity defect that shipped.\n *\n * Returning the `useCallback`-stable function directly removes the hazard by\n * construction: there is no object whose identity a caller could depend on. If\n * this ever needs to return more than one thing, it must be wrapped in\n * `useMemo` — never a bare literal. (Do not lean on the React Compiler to\n * memoize it for you: a primitive has to be correct on its own terms, and\n * correctness here is the difference between one fetch and unbounded ones.)\n */\nexport function useLatestRequest(): BeginRequest {\n const seqRef = useRef(0);\n\n return useCallback(() => {\n const mySeq = ++seqRef.current;\n return () => mySeq === seqRef.current;\n }, []);\n}\n","\"use client\";\n\n/**\n * useClipboard — copy/paste text, links, and images with the browser quirks\n * already solved: image copy re-encodes through a canvas to PNG (the only type\n * `ClipboardItem` reliably accepts), paste-image feature-detects\n * `clipboard.read` (absent in Safari < 16.4) instead of throwing, and link\n * copy can strip query params.\n *\n * The notifier is INJECTED — the package does not know your toast system. The\n * host passes `notify` once (usually wrapping its toast); without it, successes\n * are silent and failures still land in `error` + the console, so nothing is\n * ever swallowed.\n */\nimport { useCallback, useState } from \"react\";\n\nexport type ClipboardNotifyKind = \"success\" | \"error\";\n\nexport interface UseClipboardOptions {\n /** Surface outcomes to the user — wrap your toast here. */\n notify?: (message: string, kind: ClipboardNotifyKind) => void;\n}\n\nexport interface UseClipboardResult {\n copyText: (text: string, successMessage?: string) => Promise<void>;\n copyImage: (imageSrc: string, successMessage?: string) => Promise<void>;\n copyLink: (\n link: string,\n stripParams?: boolean,\n successMessage?: string,\n ) => Promise<void>;\n pasteText: () => Promise<string>;\n pasteImage: () => Promise<File | null>;\n lastCopied: string | null;\n error: Error | null;\n}\n\nfunction toError(err: unknown, fallback: string): Error {\n if (err instanceof Error) return err;\n if (typeof err === \"string\" && err) return new Error(err);\n return new Error(fallback);\n}\n\nexport function useClipboard(\n options: UseClipboardOptions = {},\n): UseClipboardResult {\n const { notify } = options;\n const [lastCopied, setLastCopied] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n const handleSuccess = (type: string, successMessage: string | undefined) => {\n setLastCopied(type);\n setError(null);\n notify?.(\n successMessage ??\n `${type.charAt(0).toUpperCase() + type.slice(1)} copied to clipboard!`,\n \"success\",\n );\n };\n\n const handleError = (err: unknown, type: string) => {\n const message = `Failed to copy ${type}`;\n setError(toError(err, message));\n console.error(message, err);\n notify?.(message, \"error\");\n };\n\n const copyText = useCallback(\n async (text: string, successMessage?: string) => {\n try {\n await navigator.clipboard.writeText(text);\n handleSuccess(\"text\", successMessage);\n } catch (err) {\n handleError(err, \"text\");\n }\n },\n [notify],\n );\n\n const copyImage = useCallback(\n async (imageSrc: string, successMessage?: string) => {\n try {\n const response = await fetch(imageSrc);\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n const blob = await response.blob();\n\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n\n return new Promise<void>((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0);\n\n canvas.toBlob((pngBlob) => {\n if (pngBlob) {\n const item = new ClipboardItem({ \"image/png\": pngBlob });\n navigator.clipboard.write([item]).then(\n () => {\n handleSuccess(\"image\", successMessage);\n resolve();\n },\n (err) =>\n reject(\n toError(err, \"Failed to write image to clipboard\"),\n ),\n );\n } else {\n reject(new Error(\"Failed to convert image to PNG\"));\n }\n }, \"image/png\");\n };\n img.onerror = () => reject(new Error(\"Failed to load image\"));\n img.src = URL.createObjectURL(blob);\n });\n } catch (err) {\n handleError(err, \"image\");\n }\n },\n [notify],\n );\n\n const copyLink = useCallback(\n async (link: string, stripParams = false, successMessage?: string) => {\n try {\n let value = link;\n if (stripParams) {\n const url = new URL(link);\n value = `${url.origin}${url.pathname}`;\n }\n await navigator.clipboard.writeText(value);\n handleSuccess(\"link\", successMessage);\n } catch (err) {\n handleError(err, \"link\");\n }\n },\n [notify],\n );\n\n const pasteText = useCallback(async () => {\n try {\n const text = await navigator.clipboard.readText();\n setError(null);\n return text;\n } catch (err) {\n setError(toError(err, \"Failed to paste text\"));\n console.error(\"Failed to paste text: \", err);\n return \"\";\n }\n }, []);\n\n const pasteImage = useCallback(async () => {\n try {\n // clipboard.read() is not available in Safari < 16.4\n if (!navigator.clipboard?.read) return null;\n const items = await navigator.clipboard.read();\n for (const item of items) {\n const imageType = item.types.find((type) => type.startsWith(\"image/\"));\n if (imageType) {\n const blob = await item.getType(imageType);\n return new File([blob], \"pasted-image.png\", { type: imageType });\n }\n }\n return null;\n } catch (err) {\n setError(toError(err, \"Failed to paste image\"));\n console.error(\"Failed to paste image: \", err);\n return null;\n }\n }, []);\n\n return { copyText, copyImage, copyLink, pasteText, pasteImage, lastCopied, error };\n}\n","/**\n * Relevance-weighted search scoring.\n *\n * Use instead of the naive `name.includes(q) || description.includes(q)` pattern\n * so that title/name matches rank above description matches, and exact/prefix\n * matches rank above partial ones.\n *\n * ── Quick start ────────────────────────────────────────────────────────────────\n * const filtered = filterAndSortBySearch(items, query, [\n * { get: (t) => t.name, weight: \"title\" },\n * { get: (t) => t.description, weight: \"body\" },\n * { get: (t) => t.tags, weight: \"tag\" },\n * ]);\n *\n * ── Weight tiers (higher = more important field) ──────────────────────────────\n * title — the primary identifier (name, label, subject)\n * subtitle — secondary identifier (vendor, author, category name)\n * body — long-form descriptive text (description, summary)\n * tag — tag/category labels\n * meta — weak metadata (modelId, type)\n * id — raw identifiers (uuid, slug) — only useful for pasted-id lookups\n *\n * Within each field, an EXACT match > STARTS-WITH match > INCLUDES match.\n * Fields declared first are a slight tiebreaker (via field-index bonus).\n *\n * ── Automatic id matching ─────────────────────────────────────────────────────\n * Every item with a string `id` is ALSO matched against the query at the `id`\n * weight tier, automatically — you do NOT need to declare an id field. This\n * means a user can paste a full or partial UUID into ANY search box wired to\n * this helper and find the record. It kicks in from {@link MIN_AUTO_ID_QUERY_LEN}\n * characters up (so short queries don't match random hex). Declare an explicit\n * `{ weight: \"id\" }` field only if you want id matching at any length / on a\n * non-`id` property; doing so opts that callsite out of the automatic pass.\n */\n\nexport type SearchFieldWeight =\n | \"title\"\n | \"subtitle\"\n | \"body\"\n | \"tag\"\n | \"meta\"\n | \"id\"\n | \"custom\";\n\nexport interface SearchFieldConfig<T> {\n /**\n * Extracts the value(s) from the item. Return a string, an array of strings,\n * or null/undefined. Arrays score based on the best-matching element.\n */\n get: (item: T) => string | string[] | null | undefined;\n /** Field importance tier. Defaults to \"body\". */\n weight?: SearchFieldWeight;\n /** Optional override for custom tiers. Ignored when `weight` is preset. */\n exact?: number;\n startsWith?: number;\n includes?: number;\n}\n\nconst WEIGHT_TABLE: Record<\n Exclude<SearchFieldWeight, \"custom\">,\n { exact: number; startsWith: number; includes: number }\n> = {\n title: { exact: 10000, startsWith: 5000, includes: 2000 },\n subtitle: { exact: 2000, startsWith: 1000, includes: 500 },\n body: { exact: 1000, startsWith: 600, includes: 400 },\n tag: { exact: 500, startsWith: 400, includes: 300 },\n meta: { exact: 200, startsWith: 150, includes: 100 },\n id: { exact: 100, startsWith: 75, includes: 50 },\n};\n\n/**\n * Below this query length we do NOT auto-match the row `id`. A 1–2 char query\n * is almost always a substring of *some* hex chars in *every* UUID, so matching\n * id at that length would flood results with the whole table. From 3 chars up a\n * partial-UUID paste is selective enough to be a real lookup.\n */\nconst MIN_AUTO_ID_QUERY_LEN = 3;\n\n/** Pull a non-empty string `id` off an item, or null if it has none. */\nfunction getStringId(item: unknown): string | null {\n if (item && typeof item === \"object\" && \"id\" in item) {\n const id = (item as { id?: unknown }).id;\n if (typeof id === \"string\" && id.length > 0) return id;\n }\n return null;\n}\n\nfunction resolveTiers(field: SearchFieldConfig<unknown>) {\n if (field.weight === \"custom\" || field.exact != null) {\n return {\n exact: field.exact ?? 0,\n startsWith: field.startsWith ?? 0,\n includes: field.includes ?? 0,\n };\n }\n return WEIGHT_TABLE[field.weight ?? \"body\"];\n}\n\nfunction scoreValue(\n value: string,\n q: string,\n tiers: { exact: number; startsWith: number; includes: number },\n): number {\n if (!value) return 0;\n const v = value.toLowerCase();\n if (v === q) return tiers.exact;\n if (v.startsWith(q)) return tiers.startsWith;\n if (v.includes(q)) return tiers.includes;\n return 0;\n}\n\n/**\n * Compute a weighted relevance score for `item` against `query`.\n * Returns 0 if there is no match — callers can treat `> 0` as a match predicate.\n *\n * Within each field, multiple values (e.g. tags) contribute the BEST match,\n * not the sum, so an item with many tags doesn't unfairly outrank one with a\n * single exact title match.\n */\nexport function computeSearchScore<T>(\n item: T,\n query: string,\n fields: SearchFieldConfig<T>[],\n): number {\n const trimmed = query.trim();\n if (!trimmed) return 0;\n const q = trimmed.toLowerCase();\n\n let total = 0;\n fields.forEach((field, idx) => {\n const raw = field.get(item);\n if (raw == null) return;\n const tiers = resolveTiers(field as SearchFieldConfig<unknown>);\n\n let best = 0;\n if (Array.isArray(raw)) {\n for (const v of raw) {\n if (typeof v !== \"string\") continue;\n const s = scoreValue(v, q, tiers);\n if (s > best) best = s;\n }\n } else if (typeof raw === \"string\") {\n best = scoreValue(raw, q, tiers);\n }\n\n if (best > 0) {\n // Tiny bias so that when two fields tie, the one declared first wins.\n total += best + (fields.length - idx);\n }\n });\n\n // Auto-match the row's UUID `id` against EVERY search box. A user can paste a\n // full or partial id and find the record, without each callsite remembering\n // to declare an id field. Skipped when the caller already declared an\n // explicit `weight: \"id\"` field (so we don't double-score), and gated on a\n // minimum query length so short queries don't match random hex substrings.\n const hasExplicitId = fields.some((f) => f.weight === \"id\");\n if (!hasExplicitId && q.length >= MIN_AUTO_ID_QUERY_LEN) {\n const id = getStringId(item);\n if (id) {\n total += scoreValue(id, q, WEIGHT_TABLE.id);\n }\n }\n\n return total;\n}\n\nexport function matchesSearch<T>(\n item: T,\n query: string,\n fields: SearchFieldConfig<T>[],\n): boolean {\n return computeSearchScore(item, query, fields) > 0;\n}\n\n/**\n * Drop-in id-match for hand-rolled `.filter()` predicates that can't (yet) move\n * onto {@link filterAndSortBySearch}. Returns true when `query` is a substring\n * of the item's string `id`, applying the same {@link MIN_AUTO_ID_QUERY_LEN}\n * guard as the automatic pass so short queries don't match random hex.\n *\n * list.filter((x) => x.name.toLowerCase().includes(q) || idMatchesQuery(x, q))\n *\n * Prefer migrating the callsite to `filterAndSortBySearch` (which does this for\n * free); reach for this only when an existing custom sort must be preserved.\n */\nexport function idMatchesQuery(item: unknown, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (q.length < MIN_AUTO_ID_QUERY_LEN) return false;\n const id = getStringId(item);\n return id != null && id.toLowerCase().includes(q);\n}\n\n/**\n * Filter out non-matches and sort remaining items by descending relevance.\n * Stable with respect to the original order when two items tie.\n */\nexport function filterAndSortBySearch<T>(\n items: readonly T[],\n query: string,\n fields: SearchFieldConfig<T>[],\n): T[] {\n const trimmed = query.trim();\n if (!trimmed) return items.slice();\n\n const scored: { item: T; score: number; idx: number }[] = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i] as T;\n const score = computeSearchScore(item, trimmed, fields);\n if (score > 0) scored.push({ item, score, idx: i });\n }\n scored.sort((a, b) => (b.score - a.score) || (a.idx - b.idx));\n return scored.map((s) => s.item);\n}\n","export interface ConcurrencyFailure<T> {\n item: T;\n index: number;\n error: unknown;\n}\n\nexport interface ConcurrencyResult<T> {\n started: number;\n succeeded: number;\n failed: number;\n failures: ConcurrencyFailure<T>[];\n}\n\n/**\n * Runs independent items through a bounded worker pool. One item failing does\n * not stop the rest, and `shouldStart` can stop new work without interrupting\n * items already in flight.\n */\nexport async function runWithConcurrency<T>(\n items: readonly T[],\n limit: number,\n worker: (item: T, index: number) => Promise<void>,\n shouldStart: () => boolean = () => true,\n): Promise<ConcurrencyResult<T>> {\n if (items.length === 0) {\n return { started: 0, succeeded: 0, failed: 0, failures: [] };\n }\n\n let cursor = 0;\n let started = 0;\n let succeeded = 0;\n const failures: ConcurrencyFailure<T>[] = [];\n const requestedLimit = Number.isFinite(limit) ? Math.floor(limit) : 1;\n const workerCount = Math.max(1, Math.min(requestedLimit, items.length));\n\n const runners = Array.from({ length: workerCount }, async () => {\n while (shouldStart()) {\n const index = cursor++;\n if (index >= items.length) return;\n started += 1;\n const item = items[index] as T;\n try {\n await worker(item, index);\n succeeded += 1;\n } catch (error) {\n failures.push({ item, index, error });\n }\n }\n });\n\n await Promise.all(runners);\n failures.sort((left, right) => left.index - right.index);\n\n return {\n started,\n succeeded,\n failed: failures.length,\n failures,\n };\n}\n","/**\n * Text formatting options\n */\nexport type TextCaseOption = 'title' | 'sentence' | 'normal' | 'lower' | 'upper';\n\nexport interface TextFormatterOptions {\n /**\n * Text case to apply after normalization\n * - title: First Letter Of Each Word Capitalized\n * - sentence: First letter of first word capitalized\n * - normal: No case transformation after normalization\n * - lower: all text lowercase\n * - upper: ALL TEXT UPPERCASE\n */\n textCase?: TextCaseOption;\n \n /**\n * Map of words to replace with specific formatting\n * Example: { 'api': 'API', 'ui': 'UI' }\n */\n wordReplacements?: Record<string, string>;\n \n /**\n * Whether to trim the result\n */\n trim?: boolean;\n}\n\n/**\n * Default word replacements for common acronyms and terms\n */\nexport type ReplacementMap = Readonly<Record<string, string>>;\n\nexport const DEFAULT_WORD_REPLACEMENTS: ReplacementMap = {\n // Acronyms & initialisms\n 'api': 'API',\n 'apis': 'APIs',\n 'ui': 'UI',\n 'ux': 'UX',\n 'id': 'ID',\n 'ids': 'IDs',\n 'qr': 'QR',\n 'ssr': 'SSR',\n 'csr': 'CSR',\n 'ssg': 'SSG',\n 'isr': 'ISR',\n 'spa': 'SPA',\n 'pwa': 'PWA',\n 'sdk': 'SDK',\n 'sdks': 'SDKs',\n 'cli': 'CLI',\n 'tty': 'TTY',\n 'repl': 'REPL',\n 'ci': 'CI',\n 'cd': 'CD',\n 'cpu': 'CPU',\n 'cpus': 'CPUs',\n 'gpu': 'GPU',\n 'gpus': 'GPUs',\n 'ram': 'RAM',\n 'rom': 'ROM',\n 'ssd': 'SSD',\n 'ssds': 'SSDs',\n 'hdd': 'HDD',\n 'hdds': 'HDDs',\n 'kpi': 'KPI',\n 'kpis': 'KPIs',\n 'sla': 'SLA',\n 'slas': 'SLAs',\n 'slo': 'SLO',\n 'slos': 'SLOs',\n 'sli': 'SLI',\n 'slis': 'SLIs',\n 'dom': 'DOM',\n\n // Web, formats, protocols\n 'url': 'URL',\n 'urls': 'URLs',\n 'uri': 'URI',\n 'uris': 'URIs',\n 'http': 'HTTP',\n 'https': 'HTTPS',\n 'html': 'HTML',\n 'css': 'CSS',\n 'json': 'JSON',\n 'yaml': 'YAML',\n 'yml': 'YML',\n 'toml': 'TOML',\n 'csv': 'CSV',\n 'pdf': 'PDF',\n 'tsv': 'TSV',\n 'jpg': 'JPG',\n 'jpeg': 'JPEG',\n 'png': 'PNG',\n 'gif': 'GIF',\n 'webp': 'WebP',\n 'heic': 'HEIC',\n 'heif': 'HEIF',\n 'bmp': 'BMP',\n 'tiff': 'TIFF',\n 'ico': 'ICO',\n 'xml': 'XML',\n 'sql': 'SQL',\n 'db': 'DB',\n 'dbs': 'DBs',\n 'nosql': 'NoSQL',\n 'graphql': 'GraphQL',\n 'grpc': 'gRPC',\n 'rest': 'REST',\n 'restful': 'RESTful',\n 'websocket': 'WebSocket',\n 'websockets': 'WebSockets',\n 'webrtc': 'WebRTC',\n\n // Networking\n 'ip': 'IP',\n 'ipv4': 'IPv4',\n 'ipv6': 'IPv6',\n 'dns': 'DNS',\n 'dhcp': 'DHCP',\n 'nat': 'NAT',\n 'tcp': 'TCP',\n 'udp': 'UDP',\n 'icmp': 'ICMP',\n 'ttl': 'TTL',\n 'lan': 'LAN',\n 'wan': 'WAN',\n 'vlan': 'VLAN',\n 'cdn': 'CDN',\n 'ftp': 'FTP',\n 'ssh': 'SSH',\n 'tls': 'TLS',\n 'ssl': 'SSL',\n\n // Security & crypto\n 'jwt': 'JWT',\n 'jws': 'JWS',\n 'jwe': 'JWE',\n 'hmac': 'HMAC',\n 'rsa': 'RSA',\n 'ecdsa': 'ECDSA',\n 'aes': 'AES',\n 'pbkdf2': 'PBKDF2',\n 'argon2': 'Argon2',\n 'scrypt': 'scrypt',\n 'totp': 'TOTP',\n 'hotp': 'HOTP',\n 'mfa': 'MFA',\n '2fa': '2FA',\n 'csrf': 'CSRF',\n 'xss': 'XSS',\n 'ssrf': 'SSRF',\n 'rce': 'RCE',\n 'dos': 'DoS',\n 'ddos': 'DDoS',\n 'mitm': 'MITM',\n 'csp': 'CSP',\n 'cors': 'CORS',\n 'pii': 'PII',\n 'phi': 'PHI',\n 'gdpr': 'GDPR',\n 'ccpa': 'CCPA',\n 'hipaa': 'HIPAA',\n 'rfc': 'RFC',\n\n // Platforms, langs, tools (single-token)\n 'javascript': 'JavaScript',\n 'typescript': 'TypeScript',\n 'jsx': 'JSX',\n 'tsx': 'TSX',\n 'node': 'Node', // (used when tokenized alone)\n 'deno': 'Deno',\n 'bun': 'Bun',\n 'react': 'React',\n 'nextjs': 'Next.js', // if your tokenizer drops dots, keep this\n 'nodejs': 'Node.js',\n 'postgresql': 'PostgreSQL',\n 'postgres': 'Postgres',\n 'mysql': 'MySQL',\n 'sqlite': 'SQLite',\n 'redis': 'Redis',\n 'supabase': 'Supabase',\n 'docker': 'Docker',\n 'kubernetes': 'Kubernetes',\n 'k8s': 'Kubernetes',\n 'helm': 'Helm',\n 'npm': 'npm',\n 'pnpm': 'pnpm',\n 'yarn': 'Yarn',\n 'eslint': 'ESLint',\n 'prettier': 'Prettier',\n 'vite': 'Vite',\n 'webpack': 'Webpack',\n 'babel': 'Babel',\n\n // OS & vendors\n 'macos': 'macOS',\n 'ios': 'iOS',\n 'ipados': 'iPadOS',\n 'watchos': 'watchOS',\n 'tvos': 'tvOS',\n 'windows': 'Windows',\n 'linux': 'Linux',\n 'ubuntu': 'Ubuntu',\n 'github': 'GitHub',\n 'gitlab': 'GitLab',\n 'bitbucket': 'Bitbucket',\n\n // Data & analytics\n 'etl': 'ETL',\n 'elt': 'ELT',\n 'olap': 'OLAP',\n 'oltp': 'OLTP',\n 'bi': 'BI',\n\n // Time & locales\n 'utc': 'UTC',\n 'gmt': 'GMT',\n 'pst': 'PST',\n 'pdt': 'PDT',\n 'pt': 'PT',\n\n // Common “small words” to keep lowercase (unless first/last word)\n 'or': 'or',\n 'and': 'and',\n 'the': 'the',\n 'of': 'of',\n 'in': 'in',\n 'to': 'to',\n 'with': 'with',\n 'as': 'as',\n 'by': 'by',\n 'for': 'for',\n 'on': 'on',\n 'at': 'at',\n 'up': 'up',\n 'a': 'a',\n 'an': 'an',\n 'is': 'is',\n 'are': 'are',\n 'was': 'was',\n 'were': 'were',\n 'be': 'be',\n 'but': 'but',\n 'nor': 'nor',\n 'so': 'so',\n 'yet': 'yet',\n 'per': 'per',\n 'via': 'via',\n\n // Latin abbreviations (tokenized as words in some pipelines)\n 'eg': 'e.g.',\n 'ie': 'i.e.',\n 'etc': 'etc.',\n 'aka': 'aka',\n 'vs': 'vs.',\n 'v': 'v.',\n\n // Client abbreviations\n 'CIC': 'CIC',\n 'AGR': 'AGR',\n 'AGER': 'AGER',\n 'DD': 'DD',\n 'TS': 'TS',\n 'TM': 'TM',\n 'arman': \"Arman\",\n};\n\n/**\n * Default options for text formatting\n */\nconst DEFAULT_OPTIONS: TextFormatterOptions = {\n textCase: 'title',\n wordReplacements: DEFAULT_WORD_REPLACEMENTS,\n trim: true,\n};\n\n/**\n * Formats text by normalizing case styles, applying case transformations,\n * and replacing specific words with custom formatting.\n * \n * @param text The input text to format\n * @param options Formatting options\n * @returns Formatted text\n */\nexport function formatText(text: string, options: TextFormatterOptions = {}): string {\n // Merge provided options with defaults\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n // Handle empty text\n if (!text) return '';\n \n // Step 1: Normalize various case styles to space-separated words\n let normalized = text\n // Convert snake_case to space-separated\n .replace(/_/g, ' ')\n // Convert kebab-case to space-separated\n .replace(/-/g, ' ')\n // Convert camelCase and PascalCase to space-separated\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace multiple spaces with a single space\n .replace(/\\s+/g, ' ');\n \n // Step 2: Apply trim if needed\n if (opts.trim) {\n normalized = normalized.trim();\n }\n \n // Step 3: Apply the specified text case\n let caseTransformed = normalized;\n switch (opts.textCase) {\n case 'title':\n caseTransformed = normalized.replace(/\\w\\S*/g, (word) => \n word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()\n );\n break;\n case 'sentence':\n if (normalized.length > 0) {\n caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();\n }\n break;\n case 'lower':\n caseTransformed = normalized.toLowerCase();\n break;\n case 'upper':\n caseTransformed = normalized.toUpperCase();\n break;\n case 'normal':\n default:\n // No case transformation\n break;\n }\n \n // Step 4: Apply word replacements if provided\n let result = caseTransformed;\n if (opts.wordReplacements) {\n Object.entries(opts.wordReplacements).forEach(([key, value]) => {\n // Create a regex that matches the key as a whole word (case insensitive)\n const regex = new RegExp(`\\\\b${key}\\\\b`, 'gi');\n result = result.replace(regex, value);\n });\n }\n \n return result;\n}\n\n/**\n * Creates a pre-configured formatter function with specific options\n * \n * @param defaultOptions Default options for the formatter\n * @returns A formatter function with the specified default options\n */\nexport function createFormatter(defaultOptions: TextFormatterOptions = {}) {\n return (text: string, overrideOptions: TextFormatterOptions = {}) => \n formatText(text, { ...defaultOptions, ...overrideOptions });\n}\n\n// Some pre-configured formatters for common use cases\nexport const formatTitleCase = createFormatter({ textCase: 'title' });\nexport const formatSentenceCase = createFormatter({ textCase: 'sentence' });\nexport const formatNormalCase = createFormatter({ textCase: 'normal' });\nexport const formatUpperCase = createFormatter({ textCase: 'upper' });\nexport const formatLowerCase = createFormatter({ textCase: 'lower' });\nexport const formatWithoutReplacements = createFormatter({ wordReplacements: {} });\n","\"use client\";\n\n// useDurableDraft — user-authored text that MUST survive anything.\n//\n// A composer draft held only in React state dies with the tab: a mobile\n// Safari reload, a crash, an error storm, a mis-tap on Back — and the user's\n// two-minute dictated rant is gone. Losing it once costs all trust\n// (Arman's ruling, 2026-08-16, after exactly that happened in the Vision\n// Interview room).\n//\n// This hook is write-through: every change lands in localStorage\n// synchronously, restore happens on mount, and the draft is removed ONLY\n// via clearDraft() — which callers may invoke only after the content has\n// durably landed somewhere the user can see (a DB row, a rendered turn).\n// A send that fails keeps the draft by construction.\n//\n// Storage failure (private mode, quota) never breaks typing — state still\n// works; the failure is logged loudly once so the degraded durability is\n// visible, not silent.\n\nimport { useEffect, useRef, useState } from \"react\";\n\nconst PREFIX = \"matrx:durable-draft:\";\n\nlet warnedStorageUnavailable = false;\n\nfunction storageWrite(storageKey: string, value: string): void {\n try {\n if (value) window.localStorage.setItem(storageKey, value);\n else window.localStorage.removeItem(storageKey);\n } catch (err) {\n if (!warnedStorageUnavailable) {\n warnedStorageUnavailable = true;\n console.warn(\n \"[useDurableDraft] localStorage unavailable — drafts survive only in memory this session\",\n err,\n );\n }\n }\n}\n\nexport function useDurableDraft(key: string): {\n draft: string;\n setDraft: (value: string) => void;\n clearDraft: () => void;\n} {\n const storageKey = PREFIX + key;\n const [draft, setDraftState] = useState(\"\");\n // Which key the user's live keystrokes belong to. Their typing beats a\n // stale saved copy ONLY for the same key — a key CHANGE always adopts the\n // new key's saved value (or empty), so a swapped entity id can never show\n // or send the previous entity's text.\n const touchedKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n // Restore runs on mount AND on every key change (localStorage is\n // unavailable during SSR, hence effect not render).\n let saved: string | null = null;\n try {\n saved = window.localStorage.getItem(storageKey);\n } catch {\n // Restore is best-effort; the write path warns once (above).\n }\n setDraftState((current) =>\n touchedKeyRef.current === storageKey && current ? current : (saved ?? \"\"),\n );\n }, [storageKey]);\n\n const setDraft = (value: string) => {\n touchedKeyRef.current = storageKey;\n setDraftState(value);\n storageWrite(storageKey, value);\n };\n\n const clearDraft = () => {\n touchedKeyRef.current = storageKey;\n setDraftState(\"\");\n storageWrite(storageKey, \"\");\n };\n\n return { draft, setDraft, clearDraft };\n}\n","// lib/local-drafts/localDrafts.ts\n//\n// THE LAST-RESORT COPY of unsaved in-memory work, in this browser.\n//\n// Nothing here is a persistence path — every feature still owns its real save.\n// This exists for the moment the app is about to LOSE in-memory edits and has\n// no way to persist them: the tab is being hard-stopped (auth identity drift),\n// the page is unloading, or a feature's saves have been failing so long that\n// the buffer is the only copy that exists. Snapshot first, block second.\n//\n// Written because of D132 (2026-08-08): a domain-wide auth cookie rotated\n// under an open /notes tab, ~14h of autosaves were RLS-filtered to 0 rows, and\n// the \"Account Changed\" overlay then forced a reload that threw the in-memory\n// buffer away. One note never reached the DB at all and is unrecoverable.\n//\n// Rules:\n// - A draft is offered back ONLY to the same `ownerId` that wrote it.\n// - Storage is best-effort: quota errors, private mode, and disabled storage\n// degrade to \"no draft\", never to a thrown error on a save path.\n// - Drafts expire (7 days) and are capped, oldest-first, so this can never\n// grow into a shadow database.\n\nimport type { DraftSource, LocalDraft, LocalDraftInput } from \"./types\";\n\nconst STORAGE_KEY = \"matrx.local-drafts.v1\";\n\n/** Drafts older than this are dropped on the next read/write. */\nconst DRAFT_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n/** A single draft larger than this is stored truncated (with a marker). */\nconst MAX_DRAFT_CHARS = 400_000;\n/** Total budget across all drafts; the oldest are dropped to fit. */\nconst MAX_TOTAL_CHARS = 1_500_000;\n\nconst TRUNCATION_MARKER =\n \"\\n\\n[… truncated by the local draft store — the note was too large to snapshot in full]\";\n\n// ── Sources ────────────────────────────────────────────────────────────────\n\nconst sources = new Map<string, DraftSource>();\nlet unloadListenerAttached = false;\n\n// ── Subscription ───────────────────────────────────────────────────────────\n//\n// A capture can happen while a recovery UI is already on screen (a save-failure\n// escalation for a note that is not the open tab). Without a notification that\n// strip would sit empty until a remount — i.e. the rescue exists and the user\n// is never told. `version` bumps on every write.\n\nconst listeners = new Set<() => void>();\nlet version = 0;\n\n/** Subscribe to draft-store writes. Pair with `getDraftsVersion` for `useSyncExternalStore`. */\nexport function subscribeDrafts(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function getDraftsVersion(): number {\n return version;\n}\n\nfunction emitDraftsChanged(): void {\n version += 1;\n for (const listener of listeners) {\n try {\n listener();\n } catch (err) {\n console.error(\"[LocalDrafts] subscriber threw:\", err);\n }\n }\n}\n\n/**\n * Register a collector for one feature's unsaved work. Re-registering the same\n * id replaces the previous collector (remounts are safe); the returned\n * unregister only removes the entry if it is still the one it installed.\n */\nexport function registerDraftSource(id: string, collect: DraftSource): () => void {\n sources.set(id, collect);\n attachUnloadListener();\n return () => {\n if (sources.get(id) === collect) sources.delete(id);\n };\n}\n\nfunction attachUnloadListener(): void {\n if (unloadListenerAttached || typeof window === \"undefined\") return;\n unloadListenerAttached = true;\n // `pagehide` fires in cases `beforeunload` does not (bfcache, mobile Safari).\n window.addEventListener(\"pagehide\", () => {\n captureDrafts(\"unload\");\n });\n}\n\n// ── Capture ────────────────────────────────────────────────────────────────\n\n/**\n * Walk every registered source and persist what they hand back.\n * Returns the drafts written (empty when nothing is unsaved).\n *\n * Call this BEFORE anything that discards in-memory state — a forced reload,\n * a blocking overlay, a hard sign-out.\n */\nexport function captureDrafts(reason: string): LocalDraft[] {\n if (typeof window === \"undefined\") return [];\n\n const collected: LocalDraftInput[] = [];\n for (const [id, collect] of sources) {\n try {\n collected.push(...collect());\n } catch (err) {\n console.error(\"[LocalDrafts] draft source failed:\", id, err);\n }\n }\n if (collected.length === 0) return [];\n\n const now = Date.now();\n const written: LocalDraft[] = collected.map((input) => ({\n ...input,\n content:\n input.content.length > MAX_DRAFT_CHARS\n ? input.content.slice(0, MAX_DRAFT_CHARS) + TRUNCATION_MARKER\n : input.content,\n key: draftKey(input.namespace, input.entityId),\n capturedAt: now,\n reason,\n }));\n\n const existing = readAll().filter(\n (d) => !written.some((w) => w.key === d.key),\n );\n writeAll([...written, ...existing]);\n\n console.warn(\n `[LocalDrafts] snapshotted ${written.length} unsaved item(s) to this browser (reason: ${reason}).`,\n written.map((d) => `${d.key} (${d.content.length} chars)`),\n );\n return written;\n}\n\n// ── Read / discard ─────────────────────────────────────────────────────────\n\n/** Every live draft in a namespace that belongs to `ownerId`, newest first. */\nexport function listDrafts(namespace: string, ownerId: string | null): LocalDraft[] {\n if (!ownerId) return [];\n return readAll()\n .filter((d) => d.namespace === namespace && d.ownerId === ownerId)\n .sort((a, b) => b.capturedAt - a.capturedAt);\n}\n\n/** The draft for one entity, if it belongs to `ownerId`. */\nexport function getDraft(\n namespace: string,\n entityId: string,\n ownerId: string | null,\n): LocalDraft | null {\n if (!ownerId) return null;\n const key = draftKey(namespace, entityId);\n return (\n readAll().find((d) => d.key === key && d.ownerId === ownerId) ?? null\n );\n}\n\n/** Drop one draft (restored, discarded by the user, or its entity saved). */\nexport function discardDraft(namespace: string, entityId: string): void {\n const key = draftKey(namespace, entityId);\n const all = readAll();\n const next = all.filter((d) => d.key !== key);\n if (next.length !== all.length) writeAll(next); // writeAll emits\n}\n\n// ── Storage ────────────────────────────────────────────────────────────────\n\nfunction draftKey(namespace: string, entityId: string): string {\n return `${namespace}:${entityId}`;\n}\n\nfunction readAll(): LocalDraft[] {\n if (typeof window === \"undefined\") return [];\n let raw: string | null = null;\n try {\n raw = window.localStorage.getItem(STORAGE_KEY);\n } catch {\n return []; // storage disabled / private mode — no drafts, never a throw\n }\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const cutoff = Date.now() - DRAFT_TTL_MS;\n return parsed.filter(isLocalDraft).filter((d) => d.capturedAt >= cutoff);\n } catch {\n return [];\n }\n}\n\nfunction writeAll(drafts: LocalDraft[]): void {\n if (typeof window === \"undefined\") return;\n const cutoff = Date.now() - DRAFT_TTL_MS;\n const fresh = drafts\n .filter((d) => d.capturedAt >= cutoff)\n .sort((a, b) => b.capturedAt - a.capturedAt);\n\n // Newest-first budget: keep taking drafts until the char budget runs out.\n const kept: LocalDraft[] = [];\n let total = 0;\n for (const draft of fresh) {\n if (total + draft.content.length > MAX_TOTAL_CHARS && kept.length > 0) {\n console.warn(\n \"[LocalDrafts] draft budget exhausted — dropping older draft\",\n draft.key,\n );\n continue;\n }\n kept.push(draft);\n total += draft.content.length;\n }\n\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(kept));\n } catch (err) {\n // Quota exceeded: retry with only the newest draft before giving up —\n // one recovered note beats zero.\n console.error(\"[LocalDrafts] failed to persist drafts:\", err);\n if (kept.length > 1) {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify([kept[0]]));\n } catch {\n /* storage is unusable — nothing more we can do here */\n }\n }\n }\n\n emitDraftsChanged();\n}\n\nfunction isLocalDraft(value: unknown): value is LocalDraft {\n if (typeof value !== \"object\" || value === null) return false;\n const d = value as Record<string, unknown>;\n return (\n typeof d.key === \"string\" &&\n typeof d.namespace === \"string\" &&\n typeof d.entityId === \"string\" &&\n typeof d.content === \"string\" &&\n typeof d.capturedAt === \"number\"\n );\n}\n","/**\n * @ai-matrx/kit/confirm — imperative opener.\n *\n * Pure-TS imperative API for the global confirm dialog. Zero React, zero\n * dialog markup — this module is statically importable from anywhere\n * (hooks, utils, Redux thunks, async handlers, sync code, anything).\n *\n * The host (`ConfirmDialogHost`) registers a controller on mount and\n * unregisters on unmount. Calls made before the host has hydrated queue\n * up and resolve as soon as the host is alive — so a destructive action\n * triggered in the first ~50ms after page load still gets a real\n * confirmation, never a silent default-yes/no. With no host ever mounted,\n * a `confirm()` promise stays pending forever (the original's behavior —\n * it never resolves to a silent default).\n *\n * One dialog at a time: concurrent calls queue and present sequentially.\n *\n * Ported verbatim from matrx-frontend\n * `components/dialogs/confirm/confirmDialogOpener.ts`, with ONE structural\n * inversion: the host/queue state lives on `globalThis` under a\n * `Symbol.for` slot instead of module-level variables. With the package\n * built `splitting: false` in dual ESM/CJS format, this module is\n * duplicated into the root bundle and the `./confirm` bundle, and CJS/ESM\n * each instantiate their own module graph — a module-level variable would\n * silently split the host registration from the callers (the same hazard\n * `@ai-matrx/tap-target` documents for its link registry). Behavior is\n * unchanged; never \"clean this up\" into a module local.\n */\n\nimport type { ReactNode } from \"react\";\n\nexport interface ConfirmOptions {\n title: ReactNode;\n description?: ReactNode | undefined;\n confirmLabel?: string | undefined;\n /** `null` hides the cancel button (acknowledge-only dialogs). */\n cancelLabel?: string | null | undefined;\n variant?: \"default\" | \"destructive\" | undefined;\n}\n\ntype Resolver = (confirmed: boolean) => void;\n\ninterface PendingRequest {\n opts: ConfirmOptions;\n resolve: Resolver;\n}\n\ninterface HostController {\n show: (opts: ConfirmOptions, resolve: Resolver) => void;\n}\n\ninterface OpenerState {\n host: HostController | null;\n queue: PendingRequest[];\n}\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.confirm-opener-state\");\n\nfunction getState(): OpenerState {\n const holder = globalThis as Record<symbol, OpenerState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = { host: null, queue: [] };\n holder[STATE_SLOT] = state;\n }\n return state;\n}\n\n/** @internal Called by `ConfirmDialogHost` on mount. */\nexport function _registerHost(controller: HostController): void {\n const state = getState();\n state.host = controller;\n while (state.queue.length > 0) {\n const next = state.queue.shift()!;\n controller.show(next.opts, next.resolve);\n }\n}\n\n/** @internal Called by `ConfirmDialogHost` on unmount. */\nexport function _unregisterHost(controller: HostController): void {\n const state = getState();\n if (state.host === controller) state.host = null;\n}\n\n/** @internal Test-only: drop any registered host and pending queue. */\nexport function _resetConfirmOpenerState(): void {\n const state = getState();\n state.host = null;\n state.queue.length = 0;\n}\n\n/**\n * Imperative confirm. Returns a Promise that resolves `true` if the user\n * confirms, `false` if they cancel/dismiss. Replaces `window.confirm`.\n *\n * @example\n * const ok = await confirm({\n * title: \"Delete sandbox\",\n * description: \"This cannot be undone.\",\n * variant: \"destructive\",\n * confirmLabel: \"Delete\",\n * });\n * if (!ok) return;\n */\nexport function confirm(opts: ConfirmOptions): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const state = getState();\n if (state.host) {\n state.host.show(opts, resolve);\n } else {\n state.queue.push({ opts, resolve });\n }\n });\n}\n","\"use client\";\n\n/**\n * `<ConfirmDialogHost />` — render ONCE, near the root of every provider\n * tree, so the imperative `confirm()` always has a live host to dispatch to.\n * Pre-mount calls queue inside `opener.ts` and resolve as soon as the host\n * registers.\n *\n * Ported from matrx-frontend `components/dialogs/confirm/\n * {ConfirmDialogHost,ConfirmDialogHostImpl}.tsx`, with the loading seam\n * inverted: the original split shell + impl and loaded the impl via\n * `next/dynamic({ ssr: false })` to keep radix out of route entry chunks.\n * A framework-agnostic package cannot use `next/dynamic`, so the host is\n * ONE directly-imported component; hosts that want the original's\n * code-splitting lazy-load the subpath themselves, e.g.\n * `dynamic(() => import(\"@ai-matrx/kit/confirm\").then(m => m.ConfirmDialogHost), { ssr: false })`.\n * The \"host renders `<ConfirmDialogHost/>` once\" contract is unchanged.\n *\n * Imperative model: calls to `confirm(...)` from anywhere push a request\n * into a ref-backed queue; this component drains the queue one item at a\n * time and renders a `<ConfirmDialog>` for the currently-active request.\n * Resolving Promise<boolean> happens on Confirm click (true), or on\n * dismiss/cancel (false). The dialog closes immediately on click — callers\n * that need an in-dialog busy spinner during async work should use the\n * inline `<ConfirmDialog>` with the `busy` prop instead.\n */\n\nimport * as React from \"react\";\n\nimport { ConfirmDialog } from \"./confirm-dialog\";\nimport {\n _registerHost,\n _unregisterHost,\n type ConfirmOptions,\n} from \"./opener\";\n\ninterface ActiveRequest {\n opts: ConfirmOptions;\n resolve: (confirmed: boolean) => void;\n}\n\nexport function ConfirmDialogHost() {\n const [active, setActive] = React.useState<ActiveRequest | null>(null);\n const [tick, setTick] = React.useState(0);\n const queueRef = React.useRef<ActiveRequest[]>([]);\n\n // Register/unregister the controller exactly once. The controller's\n // `show` always pushes onto the queue and bumps `tick`; the drain\n // effect below picks up from there. This avoids stale-closure bugs\n // around `active`.\n React.useEffect(() => {\n const controller = {\n show: (opts: ConfirmOptions, resolve: (confirmed: boolean) => void) => {\n queueRef.current.push({ opts, resolve });\n setTick((n) => n + 1);\n },\n };\n _registerHost(controller);\n return () => _unregisterHost(controller);\n }, []);\n\n // Drain the queue whenever nothing is showing.\n React.useEffect(() => {\n if (active === null && queueRef.current.length > 0) {\n setActive(queueRef.current.shift()!);\n }\n }, [active, tick]);\n\n const handleConfirm = React.useCallback(() => {\n if (!active) return;\n active.resolve(true);\n setActive(null);\n }, [active]);\n\n const handleOpenChange = React.useCallback(\n (open: boolean) => {\n if (!open && active) {\n active.resolve(false);\n setActive(null);\n }\n },\n [active],\n );\n\n return (\n <ConfirmDialog\n open={!!active}\n onOpenChange={handleOpenChange}\n title={active?.opts.title ?? \"\"}\n description={active?.opts.description}\n confirmLabel={active?.opts.confirmLabel}\n cancelLabel={active?.opts.cancelLabel}\n variant={active?.opts.variant}\n onConfirm={handleConfirm}\n />\n );\n}\n","import { twMerge } from \"tailwind-merge\";\n\n/**\n * Tailwind-aware className merge. The original app's `cn` is\n * `twMerge(clsx(inputs))`; here `clsx` is dropped (every call site passes\n * strings / false), but `tailwind-merge` is KEPT on purpose: the public\n * `className` / `contentClassName` overrides depend on last-wins conflict\n * resolution (e.g. a host's `max-w-3xl` must beat the built-in `max-w-lg`,\n * a destructive `bg-destructive` must beat the default `bg-primary`).\n * A naive join would leave both classes applied and let stylesheet order\n * decide — a real behavior divergence from the original.\n */\nexport function cn(\n ...values: Array<string | null | undefined | false>\n): string {\n return twMerge(values.filter(Boolean).join(\" \"));\n}\n","\"use client\";\n\n/**\n * Inlined shadcn-style wrapper over `@radix-ui/react-alert-dialog` — the one\n * real runtime dependency of the `./confirm` subpath (this subpath's product\n * IS the dialog). Ported from matrx-frontend `components/ui/alert-dialog.tsx`\n * with the host-shaped seams inverted:\n *\n * - `usePopoutContainer` (window-panels popout portal retargeting) is dropped:\n * the portal targets the Radix default (`document.body`). Hosts with exotic\n * portal needs pass `container` on `AlertDialogPortal` themselves.\n * - `buttonVariants` from the design system is inlined as the exact class\n * strings the two footer buttons use (base + default + outline variants,\n * design-system `button.tsx` as of this port). No cva dependency.\n * - Styling keeps the Tailwind semantic-token classes VERBATIM (`bg-background`,\n * `text-muted-foreground`, `bg-primary`, `border-border`, ...) — the platform\n * vocabulary. Hosts on other design systems override via the `className` /\n * `contentClassName` props (classes merge last-wins via tailwind-merge).\n *\n * THE ROOT RENDERS UNCONDITIONALLY — no mount gate. Radix ids come from\n * React's SSR-stable `useId`, so there is no SSR/client id mismatch to hide\n * from (the original's D144 ruling).\n */\n\nimport * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"./cn\";\nimport { treeContainsComponent } from \"../react-tree\";\n\n/**\n * Inlined design-system button classes (base + the two variants the alert\n * dialog footer uses). Source of truth while the originals live:\n * aidream `apps/shared/design-system/src/button.tsx`.\n */\nconst buttonBase =\n \"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 h-9 px-4 py-2\";\nconst buttonDefault =\n \"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90\";\nconst buttonOutline =\n \"border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-[10000] bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\n/**\n * Unstyled, non-portalling Content for custom AlertDialog layouts. AlertDialog\n * is always modal, so this keeps its ARIA semantics explicit and consistent.\n */\nconst AlertDialogContentPrimitive = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ ...props }, ref) => (\n <AlertDialogPrimitive.Content {...props} ref={ref} aria-modal=\"true\" />\n));\nAlertDialogContentPrimitive.displayName = \"AlertDialogContentPrimitive\";\n\nconst AlertDialogDescription = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> & {\n /**\n * Portal target. Default (undefined): Radix's default, `document.body`.\n * Hosts with retargeting needs (e.g. a popped-out browser window whose\n * dialog must render in THAT window's document) pass the element here.\n */\n container?: HTMLElement | null | undefined;\n }\n>(({ className, children, container, ...props }, ref) => {\n const hasDescription =\n treeContainsComponent(children, AlertDialogDescription) ||\n treeContainsComponent(children, AlertDialogPrimitive.Description);\n return (\n <AlertDialogPortal container={container ?? undefined}>\n <AlertDialogOverlay />\n <AlertDialogContentPrimitive\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-[10000] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n >\n {!hasDescription && (\n <AlertDialogPrimitive.Description className=\"sr-only\">\n Please confirm the action described in this dialog.\n </AlertDialogPrimitive.Description>\n )}\n {children}\n </AlertDialogContentPrimitive>\n </AlertDialogPortal>\n );\n});\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonBase, buttonDefault, className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(buttonBase, buttonOutline, \"mt-2 sm:mt-0\", className)}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogContentPrimitive,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n","/**\n * @ai-matrx/kit/react-tree — safe React children-tree scanning.\n *\n * Ported from matrx-frontend `lib/react/treeContainsComponent.ts`; this\n * subpath is the ONE home of the scanner inside the kit (the `/confirm`\n * subpath's alert-dialog imports it from here — no duplicate bodies).\n *\n * Two deliberate divergences from the frontend original, both documented:\n * - the dev-mode scream checks `typeof process` first, since this package may\n * load in an unbundled browser context where `process` is undefined;\n * - a React PORTAL child (`createPortal(...)` passed as a child) is a valid\n * React child, but it is not an element, an iterable, or a primitive — the\n * original fell through to the non-renderable branch, screamed a false\n * positive in dev, and skipped the portal's content. Portals are now\n * recognized and their children traversed.\n */\n\nimport * as React from \"react\";\n\nconst REACT_PORTAL_TYPE = Symbol.for(\"react.portal\");\n\n/**\n * Returns true if `Component` appears anywhere in the React element tree under\n * `node`. Used to detect optional a11y children (e.g. DialogDescription)\n * without rendering duplicates.\n *\n * DEFENSIVE + LOUD. A non-renderable node — a plain object or function passed\n * as a React child — is a real bug: React throws \"Objects are not valid as a\n * React child\" the instant it renders one. This a11y probe must NOT be the\n * crash site. `React.Children.toArray` would throw HERE, producing a trace that\n * points at the dialog primitive instead of the component that leaked the\n * object (this misdirection has burned real debugging hours). So we walk the\n * tree by hand, SKIP any non-renderable node, and scream in dev with its keys —\n * then let React report the defect at the true render site with the offending\n * component in the stack. For every VALID tree the result is identical to the\n * old `React.Children.toArray(node).some(...)`.\n */\nexport function treeContainsComponent(\n node: React.ReactNode,\n Component: React.ElementType,\n): boolean {\n if (node == null || typeof node === \"boolean\") return false;\n\n if (Array.isArray(node)) {\n return node.some((child) => treeContainsComponent(child, Component));\n }\n\n if (React.isValidElement(node)) {\n if (node.type === Component) return true;\n const props = node.props as { children?: React.ReactNode };\n return props.children != null\n ? treeContainsComponent(props.children, Component)\n : false;\n }\n\n // Strings / numbers are valid leaf children but never the Component.\n if (typeof node === \"string\" || typeof node === \"number\") return false;\n\n // A portal is a valid child that is NOT an element: traverse its content.\n if (\n typeof node === \"object\" &&\n (node as { $$typeof?: unknown }).$$typeof === REACT_PORTAL_TYPE\n ) {\n return treeContainsComponent(\n (node as { children?: React.ReactNode }).children,\n Component,\n );\n }\n\n // Non-array iterables (Set, Map, generator) are valid React children — React\n // supports them — so traverse rather than reject.\n if (typeof node === \"object\" && Symbol.iterator in node) {\n return Array.from(node as Iterable<React.ReactNode>).some((child) =>\n treeContainsComponent(child, Component),\n );\n }\n\n // Anything else (a raw object, a function) is NOT a valid React child. React\n // will throw when it renders this; we must not throw first and hide the cause.\n const runtimeProcess = (\n globalThis as { process?: { env?: { NODE_ENV?: string } } }\n ).process;\n if (runtimeProcess?.env?.NODE_ENV !== \"production\") {\n const keys =\n typeof node === \"object\"\n ? ` with keys {${Object.keys(node).join(\", \")}}`\n : \"\";\n console.error(\n `[treeContainsComponent] A non-renderable value${keys} is being passed as a React child. ` +\n \"React will throw 'Objects are not valid as a React child' at the real render site. \" +\n \"Stringify it (e.g. JSON.stringify) before rendering.\",\n node,\n );\n }\n return false;\n}\n","\"use client\";\n\n/**\n * Declarative `<ConfirmDialog />` — drop-in replacement for `window.confirm`.\n * Ported verbatim from matrx-frontend `components/ui/confirm-dialog.tsx`;\n * the only inversion is the busy spinner: `Loader2` from lucide-react is\n * inlined as a single SVG (the `@ai-matrx/tap-target` precedent — one icon\n * does not justify an icon dependency). Path annotated below.\n *\n * Pattern: hold the pending target in state, render <ConfirmDialog />\n * once at the bottom of the component, and open it by setting the target.\n * When busy state is meaningful (e.g. a network delete that should hold the\n * dialog open with a spinner), use THIS component inline; the imperative\n * `confirm()` closes immediately on click.\n */\n\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"./alert-dialog\";\n\n/** lucide `loader-circle` (a.k.a. `Loader2`) v1.22.0, inlined. */\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={className}\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\nexport interface ConfirmDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: React.ReactNode;\n description?: React.ReactNode | undefined;\n /**\n * Rich body rendered between the header and the footer, OUTSIDE the\n * description `<p>` — use for block-level content (diffs, previews, lists)\n * that would be invalid HTML inside `description`.\n */\n content?: React.ReactNode | undefined;\n /** Extra classes for the dialog content (e.g. a wider max-w for diffs). */\n contentClassName?: string | undefined;\n confirmLabel?: string | undefined;\n /**\n * `null` hides the cancel button entirely — for acknowledge-only dialogs\n * where there is nothing to cancel. Anything else labels it.\n */\n cancelLabel?: string | null | undefined;\n variant?: \"default\" | \"destructive\" | undefined;\n busy?: boolean | undefined;\n /**\n * Blocks confirming without pretending work is in flight. For a dialog whose\n * `content` asks the user something the action cannot proceed without — the\n * choice is missing, not loading — `busy` would show a misleading spinner.\n */\n confirmDisabled?: boolean | undefined;\n /**\n * Portal target for the dialog. Default (undefined): `document.body`.\n * Hosts with portal-retargeting needs (e.g. rendering into a popped-out\n * browser window's document) inject the element here — the seam exists so\n * that concern stays host-shaped.\n */\n portalContainer?: HTMLElement | null | undefined;\n onConfirm: () => void | Promise<void>;\n}\n\n/**\n * Drop-in replacement for `window.confirm`. Use this anywhere you would\n * otherwise reach for a browser-level confirm dialog.\n */\nexport function ConfirmDialog({\n open,\n onOpenChange,\n title,\n description,\n content,\n contentClassName,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n variant = \"default\",\n busy = false,\n confirmDisabled = false,\n portalContainer,\n onConfirm,\n}: ConfirmDialogProps) {\n return (\n <AlertDialog open={open} onOpenChange={onOpenChange}>\n <AlertDialogContent\n className={contentClassName}\n container={portalContainer ?? undefined}\n >\n <AlertDialogHeader>\n <AlertDialogTitle>{title}</AlertDialogTitle>\n {description ? (\n <AlertDialogDescription>{description}</AlertDialogDescription>\n ) : null}\n </AlertDialogHeader>\n {content ?? null}\n <AlertDialogFooter>\n {cancelLabel === null ? null : (\n <AlertDialogCancel className=\"max-lg:min-h-11\" disabled={busy}>\n {cancelLabel}\n </AlertDialogCancel>\n )}\n <AlertDialogAction\n disabled={busy || confirmDisabled}\n onClick={(event) => {\n event.preventDefault();\n void onConfirm();\n }}\n className={cn(\n \"max-lg:min-h-11\",\n variant === \"destructive\" &&\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n )}\n >\n {busy ? <SpinnerIcon className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {confirmLabel}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n","/**\n * @ai-matrx/kit/toast — the captured sonner wrapper, as a factory.\n *\n * A bare `toast.error(...)` from \"sonner\" is INVISIBLE to any error-capture\n * sink — every modern sonner call site silently bypasses error capture (the\n * exact hole matrx-frontend found in its marketing feature, 2026-07-20).\n * `createMatrxToast` returns a drop-in `toast` whose API is identical to the\n * one you pass in — `error` and `warning` additionally feed the injected\n * capture sink. A user seeing the failure is not evidence that it is minor,\n * so error toasts stay red unless a specific downgrade rule says otherwise.\n * Success/info/etc. pass straight through untouched.\n *\n * Ported from matrx-frontend `lib/toast.ts` with the two seams inverted:\n *\n * - `sonner` is NOT imported: the host passes its own `toast` object into the\n * factory (`createMatrxToast({ toast })`). That removes the peer-resolution\n * problem entirely — this module has zero dependencies — and the input is\n * typed STRUCTURALLY (callable + `.error` + `.warning`) so the returned\n * `toast` keeps the host's full sonner type, and no `.d.ts` in this package\n * references \"sonner\". Consequently `sonner` is NOT declared in the manifest\n * at all (X3: advisory peers are banned — nothing resolves it, so nothing\n * declares it; it remains a devDependency purely for the type-compat test).\n * - `captureError` from the app's diagnostics store becomes the injected\n * `capture?: (info) => void`. Omitted, capture is a no-op and every call\n * forwards identically (the original's payload shape is preserved exactly:\n * `source: \"user-toast\"`, the `[warning] ` prefix, the \"Error toast\"\n * fallback, `raw: { kind, message?, data }`). A throwing `capture` never\n * breaks the toast.\n *\n * Usage (once, in the host app):\n * import { toast as sonnerToast } from \"sonner\";\n * export const { toast, toastErrorAlreadyCaptured } =\n * createMatrxToast({ toast: sonnerToast, capture: captureError });\n */\n\nimport type { ReactNode } from \"react\";\n\n/** What sonner accepts as a toast title (structural: sonner's `titleT`). */\nexport type ToastMessage = ReactNode | (() => ReactNode);\n\n/** Structural stand-in for sonner's `ExternalToast` options bag. */\nexport interface ToastData {\n description?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * The structural surface this factory needs from the injected toast object:\n * callable, with `error` and `warning` methods. sonner's `toast` satisfies\n * this for every version this package targets. Deliberate typing choices so\n * the REAL sonner object is assignable without a cast under\n * `strictFunctionTypes`: the call signature uses `never[]` (accepts any\n * function — consumers call through their own `T`, never this signature),\n * and `error`/`warning` use METHOD syntax for bivariant parameter checks\n * against sonner's `ExternalToast`.\n */\nexport interface SonnerLikeToast {\n (...args: never[]): string | number;\n error(message: ToastMessage, data?: ToastData): string | number;\n warning(message: ToastMessage, data?: ToastData): string | number;\n}\n\n/** The payload handed to the injected capture sink — the original's shape. */\nexport interface CapturedToastInfo {\n source: \"user-toast\";\n message: string;\n userMessage: string;\n raw: {\n kind: \"error\" | \"warning\";\n message: string | undefined;\n data: ToastData | undefined;\n };\n}\n\nexport interface CreateMatrxToastOptions<T extends SonnerLikeToast> {\n /** The host's sonner `toast` object (or any structural equivalent). */\n toast: T;\n /**\n * Error-capture sink fed by `.error` / `.warning`. Omitted: no-op.\n * Must never be load-bearing — a throw here is swallowed.\n */\n capture?: (info: CapturedToastInfo) => void;\n}\n\nexport interface MatrxToast<T extends SonnerLikeToast> {\n /** Drop-in replacement for the injected `toast`, with error/warning capture. */\n toast: T;\n /**\n * Render an error toast when the originating failure was already captured\n * at its canonical boundary. Only for aggregate/derived UI notices; the\n * caller must be able to name the upstream capture seam.\n */\n toastErrorAlreadyCaptured: T[\"error\"];\n}\n\nfunction messageText(message: ToastMessage, data?: ToastData): string {\n const description =\n data && typeof data.description === \"string\" ? data.description : \"\";\n const title = typeof message === \"string\" ? message : \"\";\n return [title, description].filter(Boolean).join(\" — \") || \"Error toast\";\n}\n\n/** Build the captured toast pair around the host's sonner `toast` object. */\nexport function createMatrxToast<T extends SonnerLikeToast>({\n toast: hostToast,\n capture,\n}: CreateMatrxToastOptions<T>): MatrxToast<T> {\n if (typeof hostToast !== \"function\") {\n throw new Error(\n \"createMatrxToast: options.toast must be the sonner `toast` object (or a structural equivalent) — got \" +\n typeof hostToast,\n );\n }\n\n function captureToast(\n kind: \"error\" | \"warning\",\n message: ToastMessage,\n data?: ToastData,\n ): void {\n if (!capture) return;\n try {\n capture({\n source: \"user-toast\",\n message: `${kind === \"warning\" ? \"[warning] \" : \"\"}${messageText(message, data)}`,\n userMessage: messageText(message, data),\n raw: {\n kind,\n message: typeof message === \"string\" ? message : undefined,\n data,\n },\n });\n } catch {\n /* capture must never break the toast */\n }\n }\n\n const error: SonnerLikeToast[\"error\"] = (message, data) => {\n captureToast(\"error\", message, data);\n return hostToast.error(message, data);\n };\n\n const warning: SonnerLikeToast[\"warning\"] = (message, data) => {\n captureToast(\"warning\", message, data);\n return hostToast.warning(message, data);\n };\n\n // The constraint's call signature is `never[]` (see SonnerLikeToast), so\n // forwarding the base call goes through a widened alias of the host object.\n const forward = hostToast as unknown as (\n ...args: Parameters<T>\n ) => ReturnType<T>;\n const toast: T = Object.assign(\n ((...args: Parameters<T>) => forward(...args)) as unknown as T,\n hostToast,\n { error, warning },\n );\n\n const toastErrorAlreadyCaptured = ((\n message: ToastMessage,\n data?: ToastData,\n ) => hostToast.error(message, data)) as unknown as T[\"error\"];\n\n return { toast, toastErrorAlreadyCaptured };\n}\n","/**\n * @ai-matrx/kit/invalidation — a tiny name-keyed callback registry that lets a\n * UBIQUITOUS module (a stream processor, an effect runner) trigger cache\n * invalidation inside a HEAVY chunk cluster with ZERO import edge between them.\n *\n * WHY THIS EXISTS (the fragmentation-law incident): a module statically\n * reachable from ~every route context reached a heavy registry cluster with an\n * `await import()` — one line that added +14 GB peak build RSS / +50% compile\n * time and OOM-killed 12 straight production builds. The sanctioned shape is\n * the INVERSION implemented here: the heavy cluster registers a callback at\n * its own module init (it is always initialized wherever its output can\n * render — if the chunk never loaded, nothing stale is mounted), and the\n * ubiquitous module fires the callback by NAME. The only shared code is this\n * module, which imports nothing.\n *\n * RULES:\n * - This module must NEVER grow an import. It is in every chunk that touches\n * it; any dependency it gains is multiplied across all of them.\n * - Firing an unregistered name is a NO-OP by design, not an error — the\n * consumer chunk simply isn't loaded in this tab, so there is nothing\n * stale to invalidate.\n * - Callbacks never break the caller: each runs in its own try/catch and\n * screams to the console on failure.\n * - Key constants live in the HOST app (one shared constants module per app),\n * so producer and consumer agree on the name without importing each other.\n * The registry itself is generic over names — app-specific keys never move\n * into this package.\n *\n * Ported from matrx-frontend `lib/invalidation/invalidation-registry.ts`, with\n * ONE structural inversion: the callback map lives on `globalThis` under a\n * `Symbol.for` slot instead of a module-level variable. With the package built\n * `splitting: false` in dual ESM/CJS format, this module is duplicated into\n * the root bundle and the `./invalidation` bundle, and CJS/ESM each\n * instantiate their own module graph — a module-level Map would silently split\n * the producers from the consumers (the same hazard the confirm opener\n * documents). Behavior is unchanged; never \"clean this up\" into a module\n * local.\n */\n\nexport type InvalidationCallback = (detail?: unknown) => void;\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.invalidation-registry\");\n\ntype RegistryState = Map<string, Set<InvalidationCallback>>;\n\nfunction getCallbacks(): RegistryState {\n const holder = globalThis as Record<symbol, RegistryState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = new Map();\n holder[STATE_SLOT] = state;\n }\n return state;\n}\n\n/**\n * Register a callback for a name. Idempotent-friendly: returns the\n * unsubscribe. Module-scope registration in the consumer chunk is the\n * intended pattern (register once per chunk load, never unsubscribe).\n */\nexport function registerInvalidationCallback(\n name: string,\n callback: InvalidationCallback,\n): () => void {\n const callbacks = getCallbacks();\n let set = callbacks.get(name);\n if (!set) {\n set = new Set();\n callbacks.set(name, set);\n }\n set.add(callback);\n return () => {\n set.delete(callback);\n };\n}\n\n/**\n * Fire every callback registered under `name`. Returns true when at least one\n * callback ran. Never throws — a failing callback screams and the rest run.\n */\nexport function fireInvalidation(name: string, detail?: unknown): boolean {\n const set = getCallbacks().get(name);\n if (!set || set.size === 0) return false;\n for (const callback of set) {\n try {\n callback(detail);\n } catch (error) {\n console.error(\n `[invalidation-registry] callback for \"${name}\" threw`,\n error,\n );\n }\n }\n return true;\n}\n","/**\n * @ai-matrx/kit/delimiter-guard — stops ONE stray markdown delimiter from\n * swallowing a whole section of a streamed answer.\n *\n * THE FAILURE CLASS\n * -----------------\n * Markdown delimiters pair greedily and blindly. A single stray opener emitted\n * by a model (the common shape is a mangled citation:\n * `…/a-quicker-way-to-heal-prp-and-prf$$ .`) pairs with the next matching\n * delimiter anywhere later in the message, and everything in between —\n * headings, bold, links, whole sections — collapses into one node.\n *\n * Two delimiters cause this in a remark-math + CommonMark pipeline:\n *\n * 1. `$$` (remark-math). The swallowed prose becomes a math node, KaTeX fails\n * to parse it, and `rehype-katex` falls back to its built-in error\n * rendering: the raw source re-emitted inside `<span class=\"katex-error\"\n * style=\"color:#cc0000\">`. The symptom is a huge block of BRIGHT RED\n * unrendered markdown mid-answer. That red is KaTeX reporting a parse error\n * on text that was never math — not a style of yours.\n * 2. `[` (CommonMark link label). The swallowed prose becomes the label of one\n * enormous hyperlink — the same bug wearing blue instead of red.\n *\n * WHAT THIS DOES\n * --------------\n * Before the markdown pipeline runs, each candidate span is checked for\n * plausibility. A `$$…$$` span carrying markdown structure (links, URLs, bold,\n * headings, list markers) or reading as prose is not math; a link label that is\n * hundreds of characters long or contains block structure is not a label. The\n * offending OPENER is neutralized (`$$`, `[`) and scanning resumes at the next\n * delimiter, so genuine math and genuine links later in the same message still\n * render. Real content is never touched.\n *\n * LOUD RECOVERY: every firing is a real upstream defect (a model emitting\n * malformed delimiters, or a producer mangling a citation). Callers report the\n * returned violations — see `reportDelimiterViolations`.\n *\n * Ported verbatim from matrx-frontend `lib/markdown/delimiter-guard.ts`, with\n * ONE coupling inversion: the app's `captureError` store import became the\n * injected `capture` sink on `reportDelimiterViolations`' context (payload\n * shape preserved exactly). No sink means console-only loud recovery.\n */\n\nexport type DelimiterViolationReason =\n /** A `$$…$$` pair whose contents are prose/markdown, not math. */\n | \"prose-span\"\n /** A `$$` with no closing partner in the content. */\n | \"unpaired\"\n /** A `[…](…)` link whose label swallowed prose/structure. */\n | \"runaway-link\";\n\nexport interface DelimiterViolation {\n reason: DelimiterViolationReason;\n /** Character offset of the offending delimiter in the input string. */\n index: number;\n /** Length of the span between the delimiters (0 for `unpaired`). */\n spanLength: number;\n /** Short excerpt of what would have been swallowed. */\n preview: string;\n}\n\nexport interface DelimiterGuardResult {\n /** Input with runaway openers escaped. */\n text: string;\n violations: DelimiterViolation[];\n}\n\n/**\n * Neutralized delimiters. Two requirements drove this encoding:\n *\n * - It must be INVISIBLE in the rendered output. A backslash escape (`\\$\\$`)\n * is emitted literally when the delimiter abuts constructs remark does not\n * re-parse, so the reader sees stray backslashes.\n * - It must not be swallowed by the GFM autolink extension. These strays sit\n * right after a bare URL (that is how they are produced), and a character\n * reference placed there is absorbed into the link target instead of being\n * decoded.\n *\n * A zero-width space satisfies both: it terminates the autolink, splits the\n * `$$` token so remark-math never sees a delimiter (single `$` is inert —\n * `singleDollarTextMath: false`), and renders as nothing. The bracket keeps a\n * character reference (a lone `[` has no token to split) behind a ZWSP.\n */\nconst ZWSP = \"\\u200B\";\nconst ESCAPED_DOLLARS = `${ZWSP}$${ZWSP}$`;\nconst ESCAPED_BRACKET = `${ZWSP}[`;\n\n/** Longest span we will accept as real math when no LaTeX command is present. */\nconst MAX_MATH_SPAN = 600;\n\n/**\n * Markdown structure that can never appear inside real math:\n * a markdown link, a bare URL, bold markers, an ATX heading, or a\n * line-leading list marker.\n */\nconst STRUCTURAL_MARKDOWN =\n /\\]\\(|https?:\\/\\/|\\*\\*|(?:^|\\n)[ \\t]{0,3}#{1,6}[ \\t]|(?:^|\\n)[ \\t]*[-*+][ \\t]+|(?:^|\\n)[ \\t]*\\d+[.)][ \\t]/;\n\n/** A LaTeX control sequence (`\\frac`, `\\sim`, `\\text`, …). */\nconst LATEX_COMMAND = /\\\\[a-zA-Z]/;\n\n/** Alphabetic words of 3+ letters — the prose signal for command-free spans. */\nconst PROSE_WORD = /[A-Za-z]{3,}/g;\n\n/** Word count at which a LaTeX-command-free span is judged to be prose. */\nconst PROSE_WORD_LIMIT = 6;\n\nfunction looksLikeMath(inner: string): boolean {\n const s = inner.trim();\n if (!s) return false;\n\n // Structural markdown wins over every other signal — a swallowed prose span\n // routinely contains real LaTeX fragments (`$\\sim 200 \\text{ g}$`) picked up\n // from the sentences it ate, so the command check cannot run first.\n if (STRUCTURAL_MARKDOWN.test(s)) return false;\n\n if (s.length > MAX_MATH_SPAN) return false;\n\n // A LaTeX control sequence is strong evidence of math — but not proof: a\n // swallowed span often eats sentences that themselves contained inline math\n // (`$\\sim 400 \\text{ g}$`). Real math is symbol-dense, so a span that is\n // mostly English words is still prose.\n if (LATEX_COMMAND.test(s)) {\n return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT * 3;\n }\n\n if (/\\n[ \\t]*\\n/.test(s)) return false;\n\n return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT;\n}\n\n/** Ranges (fenced blocks, inline code) whose `$$` must be ignored. */\nfunction protectedRanges(text: string): Array<[number, number]> {\n const ranges: Array<[number, number]> = [];\n const patterns = [/```[\\s\\S]*?(?:```|$)/g, /~~~[\\s\\S]*?(?:~~~|$)/g, /`[^`\\n]*`/g];\n for (const re of patterns) {\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n ranges.push([m.index, m.index + m[0].length]);\n }\n }\n return ranges;\n}\n\nfunction isProtected(index: number, ranges: Array<[number, number]>): boolean {\n return ranges.some(([start, end]) => index >= start && index < end);\n}\n\nfunction preview(text: string, max = 160): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max)}…` : flat;\n}\n\n/**\n * Escapes `$$` delimiters that would make remark-math swallow non-math text.\n * Pure — safe to call on every render / stream chunk.\n */\nexport function guardMathDelimiters(text: string): DelimiterGuardResult {\n if (!text.includes(\"$$\")) return { text, violations: [] };\n\n const ranges = protectedRanges(text);\n\n // Collect `$$` offsets outside code.\n const tokens: number[] = [];\n for (let i = 0; i < text.length - 1; i++) {\n if (text[i] !== \"$\" || text[i + 1] !== \"$\") continue;\n if (!isProtected(i, ranges)) tokens.push(i);\n i++; // never treat the second `$` of a pair as a new opener\n }\n if (tokens.length === 0) return { text, violations: [] };\n\n const violations: DelimiterViolation[] = [];\n const escapeAt: number[] = [];\n\n let j = 0;\n while (j < tokens.length) {\n // Bounded by the loop condition — `tokens[j]` always exists here.\n const open = tokens[j] as number;\n const close = tokens[j + 1];\n\n if (close === undefined) {\n violations.push({\n reason: \"unpaired\",\n index: open,\n spanLength: 0,\n // An unpaired `$$` is inert to remark-math (nothing closes it), so it\n // is reported but NOT escaped — it already renders as literal text.\n preview: preview(text.slice(open, open + 120)),\n });\n break;\n }\n\n const inner = text.slice(open + 2, close);\n if (looksLikeMath(inner)) {\n j += 2;\n continue;\n }\n\n escapeAt.push(open);\n violations.push({\n reason: \"prose-span\",\n index: open,\n spanLength: inner.length,\n preview: preview(inner),\n });\n // Resume at the closing delimiter: it may legitimately open the NEXT span.\n j += 1;\n }\n\n let guarded = text;\n for (const index of [...escapeAt].sort((a, b) => b - a)) {\n guarded = `${guarded.slice(0, index)}${ESCAPED_DOLLARS}${guarded.slice(index + 2)}`;\n }\n\n return { text: guarded, violations };\n}\n\n/** Longest link label we accept before calling it a runaway. */\nconst MAX_LINK_LABEL = 200;\n\n/**\n * Block structure that can never legitimately sit inside a link label:\n * a blank line, a list item on its own line, or an ATX heading marker\n * (`## `…`#### `) anywhere — a heading inside a label always means the label\n * ran past its intended end.\n */\nconst LABEL_BLOCK_STRUCTURE =\n /\\n[ \\t]*\\n|(?:^|\\n)[ \\t]*[-*+][ \\t]+|#{2,6}[ \\t]/;\n\n/**\n * Escapes the `[` of a markdown link whose label ran away — the link twin of\n * the stray-`$$` bug. An unclosed citation bracket pairs with a `]` hundreds of\n * characters later and turns an entire section into one hyperlink.\n *\n * Pure. Runs after the math guard so both share one escaping pass conceptually,\n * but each is independently usable.\n */\nexport function guardRunawayLinks(text: string): DelimiterGuardResult {\n if (!text.includes(\"[\")) return { text, violations: [] };\n\n const ranges = protectedRanges(text);\n const violations: DelimiterViolation[] = [];\n const escapeAt: number[] = [];\n\n // `[label](target)` — label is non-greedy but may span newlines, which is\n // exactly the runaway shape we are looking for.\n const linkRe = /\\[((?:[^[\\]]|\\\\.)*)\\]\\(([^\\s)]*)/g;\n let m: RegExpExecArray | null;\n while ((m = linkRe.exec(text)) !== null) {\n const open = m.index;\n if (isProtected(open, ranges)) continue;\n\n const label = m[1] ?? \"\";\n const runaway =\n label.length > MAX_LINK_LABEL || LABEL_BLOCK_STRUCTURE.test(label);\n if (!runaway) continue;\n\n escapeAt.push(open);\n violations.push({\n reason: \"runaway-link\",\n index: open,\n spanLength: label.length,\n preview: preview(label),\n });\n }\n\n let guarded = text;\n for (const index of [...escapeAt].sort((a, b) => b - a)) {\n guarded = `${guarded.slice(0, index)}${ESCAPED_BRACKET}${guarded.slice(index + 1)}`;\n }\n\n return { text: guarded, violations };\n}\n\n/**\n * The front door: run every delimiter guard in order. Offsets in the returned\n * violations refer to each guard's own input, so they are for diagnostics only.\n */\nexport function guardMarkdownDelimiters(text: string): DelimiterGuardResult {\n const math = guardMathDelimiters(text);\n const links = guardRunawayLinks(math.text);\n return {\n text: links.text,\n violations: [...math.violations, ...links.violations],\n };\n}\n\n/**\n * The payload handed to the injected capture sink — exactly the shape the\n * original passed to the Matrx `captureError` store. A Matrx host passes\n * `captureError` straight through; any host can log/report it its own way.\n */\nexport interface DelimiterCaptureInput {\n source: \"markdown-delimiters\";\n message: string;\n relation: string;\n details: string;\n conversationId?: string | undefined;\n callSite: \"guardMarkdownDelimiters\";\n raw: { messageId?: string | undefined; violations: DelimiterViolation[] };\n}\n\nexport interface DelimiterReportContext {\n renderPath: string;\n messageId?: string | undefined;\n conversationId?: string | undefined;\n /**\n * Optional error-capture sink (a Matrx host passes its `captureError`).\n * Absent, the loud recovery is console-only. Must never be relied on to\n * throw — failures inside it are swallowed so capture can never break\n * rendering.\n */\n capture?: ((input: DelimiterCaptureInput) => void) | undefined;\n}\n\n/**\n * Loud recovery. A firing means malformed math delimiters reached the renderer\n * — the guard kept the message readable, but the producer is still emitting\n * broken content and must be found.\n */\nexport function reportDelimiterViolations(\n violations: DelimiterViolation[],\n context: DelimiterReportContext,\n): void {\n if (violations.length === 0) return;\n try {\n const worst =\n violations.find((v) => v.reason !== \"unpaired\") ?? violations[0];\n if (!worst) return;\n const message =\n worst.reason === \"prose-span\"\n ? `Malformed math delimiters: a stray \"$$\" would have turned ${worst.spanLength} chars of prose into a math span (KaTeX would render it as red error text). Escaped it.`\n : worst.reason === \"runaway-link\"\n ? `Runaway markdown link: an unclosed \"[\" would have turned ${worst.spanLength} chars into one link label. Escaped it.`\n : `Malformed math delimiters: an unpaired \"$$\" reached the renderer.`;\n\n // Loud recovery: this is a defect being reported, not noise.\n console.warn(`[markdown-delimiter-guard] ${message}`, {\n renderPath: context.renderPath,\n violations,\n });\n\n context.capture?.({\n source: \"markdown-delimiters\",\n message,\n relation: `markdown:${context.renderPath}`,\n details: worst.preview,\n conversationId: context.conversationId,\n callSite: \"guardMarkdownDelimiters\",\n raw: { messageId: context.messageId, violations },\n });\n } catch {\n // Capture must never break rendering.\n }\n}\n","// json-format/detect.ts\n//\n// \"Is this text JSON, and where exactly does the JSON start and stop?\"\n//\n// The answer has to survive real-world selections: a fenced ```json block, a\n// bare pasted object, an object with a stray blank line above it, a fence the\n// user only half-selected. So detection splits the text into three parts —\n// leading / payload / trailing — and only the payload is ever re-formatted.\n// Everything outside it is restored verbatim, because a formatter that eats\n// the prose around the JSON is worse than no formatter at all.\n//\n// Two parse tiers: `JSON.parse` first (strict — what the value really is), then\n// JSON5 (tolerant — trailing commas, comments, unquoted keys, single quotes),\n// because the JSON people paste out of logs and code is frequently not legal\n// JSON. Tolerant parsing is reported, never hidden: a consumer that re-emits a\n// tolerantly-parsed value is normalizing it, and the caller can say so.\n//\n// Pure: no React / DOM. Never throws.\n//\n// Ported verbatim from matrx-frontend `lib/json-format/detect.ts`.\n\nimport JSON5 from \"json5\";\nimport type { JsonValue } from \"./json-value\";\nimport type {\n JsonDetection,\n JsonFence,\n JsonParser,\n JsonRootKind,\n} from \"./types\";\n\n/** Opening fence line: optional indent, 3+ backticks or tildes, optional info. */\nconst FENCE_OPEN = /^([ \\t]*)(`{3,}|~{3,})[ \\t]*([^\\s`~]*)[ \\t]*$/;\n\n/** Languages we treat as \"this fence contains JSON\". */\nconst JSON_FENCE_LANGS = new Set([\"json\", \"jsonc\", \"json5\", \"geojson\", \"jsonl\"]);\n\ninterface Split {\n leading: string;\n payload: string;\n trailing: string;\n fence: JsonFence | null;\n}\n\n/** Peel a markdown code fence off the text, if the text IS a fenced block. */\nfunction splitFence(text: string): Split | null {\n const lines = text.split(\"\\n\");\n\n // The fence may sit anywhere in the selection (a user highlighting a block\n // plus the sentence above it is the common case) — but there must be exactly\n // ONE block. Two fenced blocks in one selection is not a single JSON payload,\n // and spanning them would splice unrelated content together.\n const openIdx = lines.findIndex((l) => FENCE_OPEN.test(l));\n if (openIdx === -1) return null;\n\n const open = FENCE_OPEN.exec(lines[openIdx] ?? \"\");\n if (!open) return null;\n const [, indent = \"\", marker = \"```\", lang = \"\"] = open;\n const fenceChar = marker[0] ?? \"`\";\n const closeRe = new RegExp(`^[ \\\\t]*\\\\${fenceChar}{${marker.length},}[ \\\\t]*$`);\n\n let closeIdx = -1;\n for (let i = openIdx + 1; i < lines.length; i++) {\n if (closeRe.test(lines[i] ?? \"\")) {\n closeIdx = i;\n break;\n }\n }\n\n const afterClose = closeIdx === -1 ? [] : lines.slice(closeIdx + 1);\n if (afterClose.some((l) => FENCE_OPEN.test(l))) return null;\n\n const bodyEnd = closeIdx === -1 ? lines.length : closeIdx;\n // The line separators bordering the fence belong to leading/trailing, so\n // reassembly is a plain concatenation and blank lines survive it.\n return {\n leading: openIdx > 0 ? `${lines.slice(0, openIdx).join(\"\\n\")}\\n` : \"\",\n payload: lines.slice(openIdx + 1, bodyEnd).join(\"\\n\"),\n trailing: afterClose.length > 0 ? `\\n${afterClose.join(\"\\n\")}` : \"\",\n fence: {\n marker,\n lang: lang.toLowerCase(),\n indent,\n closed: closeIdx !== -1,\n },\n };\n}\n\n/** Split bare (unfenced) text into surrounding whitespace + payload. */\nfunction splitBare(text: string): Split {\n const payload = text.trim();\n if (payload === \"\") {\n return { leading: text, payload: \"\", trailing: \"\", fence: null };\n }\n const start = text.indexOf(payload);\n return {\n leading: text.slice(0, start),\n payload,\n trailing: text.slice(start + payload.length),\n fence: null,\n };\n}\n\nfunction rootKindOf(value: JsonValue): JsonRootKind {\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\" && value !== null) return \"object\";\n return \"scalar\";\n}\n\n/** Bracket-shaped: opens and closes with a matching container delimiter. */\nfunction isBracketShaped(payload: string): boolean {\n const first = payload[0];\n const last = payload[payload.length - 1];\n if (payload.length < 2) return false;\n return (first === \"{\" && last === \"}\") || (first === \"[\" && last === \"]\");\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : \"Invalid JSON\";\n}\n\nfunction countLines(s: string): number {\n if (s === \"\") return 0;\n let n = 1;\n for (let i = 0; i < s.length; i++) if (s[i] === \"\\n\") n++;\n return n;\n}\n\n/**\n * Detect JSON in `text`. Never throws; a non-JSON string comes back with\n * `ok: false` and `looksLikeJson: false`, which is the signal to offer nothing.\n */\nexport function detectJson(text: string): JsonDetection {\n const split = splitFence(text) ?? splitBare(text);\n // A fenced block's body still carries its own indentation/blank lines.\n const payload = split.fence ? split.payload.trim() : split.payload;\n\n const fenceSaysJson =\n split.fence !== null &&\n (split.fence.lang === \"\" || JSON_FENCE_LANGS.has(split.fence.lang));\n\n const base = {\n fence: split.fence,\n leading: split.leading,\n trailing: split.trailing,\n payload,\n lineCount: countLines(payload),\n charCount: payload.length,\n };\n\n if (payload === \"\") {\n return { ...base, ok: false, looksLikeJson: false };\n }\n\n // A fence declaring a NON-JSON language is a hard no, even if the body would\n // parse — reformatting the inside of a ```python block is not our business.\n if (split.fence !== null && !fenceSaysJson) {\n return { ...base, ok: false, looksLikeJson: false };\n }\n\n const shaped = isBracketShaped(payload);\n\n let value: JsonValue | undefined;\n let parser: JsonParser | undefined;\n let error: string | undefined;\n try {\n value = JSON.parse(payload) as JsonValue;\n parser = \"strict\";\n } catch (strictErr) {\n try {\n value = JSON5.parse(payload) as JsonValue;\n parser = \"tolerant\";\n } catch {\n error = errorMessage(strictErr);\n }\n }\n\n if (value === undefined || parser === undefined) {\n // Unparseable. Still \"looks like JSON\" when it is bracket-shaped, so a\n // surface can show the actions and report the parse error on click rather\n // than pretending the selection is ordinary prose.\n return { ...base, ok: false, looksLikeJson: shaped, error };\n }\n\n const root = rootKindOf(value);\n // A bare scalar (\"hello\", 42, true) parses but is not worth offering JSON\n // actions on — every prose word that happens to be a number would qualify.\n const worthOffering = root !== \"scalar\" || fenceSaysJson;\n\n return { ...base, ok: true, looksLikeJson: worthOffering, value, parser, root };\n}\n","/**\n * Canonical JSON value types + narrowing guards.\n *\n * Ported (the subset this subpath needs) from matrx-frontend `types/json.ts` —\n * the honest names for \"this is just JSON\" that are NOT `any` and NOT a bare\n * `unknown`. The package must stand alone, so the types live here; a Matrx\n * host keeps using its own `@/types/json` for app code and the two are\n * structurally identical.\n */\n\nexport type JsonPrimitive = string | number | boolean | null;\n\n/**\n * A JSON object. Values are `JsonValue | undefined` so optional keys read\n * cleanly (mirrors Supabase's original generated `Json` object member).\n */\nexport interface JsonObject {\n [key: string]: JsonValue | undefined;\n}\n\nexport type JsonArray = JsonValue[];\n\nexport type JsonValue = JsonPrimitive | JsonObject | JsonArray;\n\n/**\n * Narrow an `unknown` (e.g. a bare JSONB column) to a `JsonObject`.\n * Plain object only — arrays and `null` return false.\n */\nexport function isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Narrow an `unknown` to a `JsonArray`. */\nexport function isJsonArray(value: unknown): value is JsonArray {\n return Array.isArray(value);\n}\n\n/** Narrow an `unknown` to a JSON primitive (string | number | boolean | null). */\nexport function isJsonPrimitive(value: unknown): value is JsonPrimitive {\n return (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n","// json-format/format.ts\n//\n// The JSON writer. Three styles over one recursive printer:\n//\n// minify — one line, no optional whitespace.\n// compact — width-aware FILL. Any subtree whose flat form fits the remaining\n// columns is inlined; a subtree that does not fit expands, but its\n// children are then PACKED onto shared lines while they fit. This\n// is what turns an 11-line reference blob into 3 lines without\n// turning it into an unreadable one-liner.\n// pretty — one entry per line (classic 2-space JSON).\n//\n// Why not `JSON.stringify(v, null, 2)`: it cannot inline, cannot pack, and\n// cannot sort keys. All three are the point.\n//\n// Pure: no React / DOM. Never throws — a parse failure comes back as a result\n// with `ok: false` and the input text unchanged.\n//\n// Ported verbatim from matrx-frontend `lib/json-format/format.ts`.\n\nimport type { JsonObject, JsonValue } from \"./json-value\";\nimport { isJsonArray, isJsonObject } from \"./json-value\";\nimport { detectJson } from \"./detect\";\nimport type {\n JsonDetection,\n JsonFormatOptions,\n JsonFormatResult,\n JsonTextSize,\n} from \"./types\";\n\nexport const DEFAULT_JSON_INDENT = 2;\nexport const DEFAULT_JSON_WIDTH = 100;\n\ninterface WriterConfig {\n indent: number;\n /** Target line width; `-1` disables inlining entirely (pretty). */\n width: number;\n /** Pack sibling entries onto shared lines (compact only). */\n pack: boolean;\n /** Spaces inside braces/brackets and after colons/commas. */\n spaced: boolean;\n sortKeys: boolean;\n}\n\nfunction orderedKeys(obj: JsonObject, sortKeys: boolean): string[] {\n // `undefined` values are not JSON — JSON.stringify drops them, so do we.\n const keys = Object.keys(obj).filter((k) => obj[k] !== undefined);\n return sortKeys ? [...keys].sort((a, b) => a.localeCompare(b)) : keys;\n}\n\n/** Serialize a scalar exactly as JSON does. */\nfunction writeScalar(value: JsonValue): string {\n // NaN / Infinity stringify to \"null\", matching JSON.stringify.\n return JSON.stringify(value) ?? \"null\";\n}\n\n/** The whole subtree on one line. */\nfunction flatten(value: JsonValue, cfg: WriterConfig): string {\n if (isJsonArray(value)) {\n if (value.length === 0) return \"[]\";\n const parts = value.map((v) => flatten(v ?? null, cfg));\n return cfg.spaced ? `[${parts.join(\", \")}]` : `[${parts.join(\",\")}]`;\n }\n if (isJsonObject(value)) {\n const keys = orderedKeys(value, cfg.sortKeys);\n if (keys.length === 0) return \"{}\";\n const colon = cfg.spaced ? \": \" : \":\";\n const parts = keys.map(\n (k) => `${JSON.stringify(k)}${colon}${flatten(value[k] ?? null, cfg)}`,\n );\n return cfg.spaced ? `{ ${parts.join(\", \")} }` : `{${parts.join(\",\")}}`;\n }\n return writeScalar(value);\n}\n\n/**\n * Lay out `entries` (already-rendered child texts) inside a container.\n * Single-line entries are packed together while they fit; a multi-line entry\n * always occupies its own line(s). Returns the body lines, unindented-prefixed\n * with `pad` already applied.\n */\nfunction layoutEntries(\n entries: string[],\n pad: string,\n cfg: WriterConfig,\n): string[] {\n if (!cfg.pack) return entries.map((e) => pad + e);\n\n const lines: string[] = [];\n let current = \"\";\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i] ?? \"\";\n const isLast = i === entries.length - 1;\n const piece = isLast ? entry : `${entry},`;\n\n if (entry.includes(\"\\n\")) {\n // Multi-line child: flush whatever is buffered, then stand alone.\n if (current !== \"\") {\n lines.push(pad + current);\n current = \"\";\n }\n lines.push(pad + piece);\n continue;\n }\n\n if (current === \"\") {\n current = piece;\n continue;\n }\n const merged = `${current} ${piece}`;\n if (pad.length + merged.length <= cfg.width) {\n current = merged;\n } else {\n lines.push(pad + current);\n current = piece;\n }\n }\n if (current !== \"\") lines.push(pad + current);\n return lines;\n}\n\n/**\n * Render `value` starting at column `used` on its current line, at nesting\n * `level`. `used` includes the indentation AND any key prefix already written,\n * so the width budget is honest about `\"items\": [` style prefixes.\n */\nfunction renderNode(\n value: JsonValue,\n level: number,\n used: number,\n cfg: WriterConfig,\n): string {\n const isContainer = isJsonArray(value) || isJsonObject(value);\n if (!isContainer) return writeScalar(value);\n\n const flat = flatten(value, cfg);\n if (flat === \"[]\" || flat === \"{}\") return flat;\n if (cfg.width >= 0 && used + flat.length <= cfg.width) return flat;\n\n const pad = \" \".repeat((level + 1) * cfg.indent);\n const closePad = \" \".repeat(level * cfg.indent);\n\n if (isJsonArray(value)) {\n const entries = value.map((v) =>\n renderNode(v ?? null, level + 1, pad.length, cfg),\n );\n const body = layoutEntries(entries, pad, cfg);\n const joined = cfg.pack ? body.join(\"\\n\") : body.join(\",\\n\");\n return `[\\n${joined}\\n${closePad}]`;\n }\n\n const keys = orderedKeys(value, cfg.sortKeys);\n const entries = keys.map((k) => {\n const prefix = `${JSON.stringify(k)}: `;\n const rendered = renderNode(\n value[k] ?? null,\n level + 1,\n pad.length + prefix.length,\n cfg,\n );\n return prefix + rendered;\n });\n const body = layoutEntries(entries, pad, cfg);\n const joined = cfg.pack ? body.join(\"\\n\") : body.join(\",\\n\");\n return `{\\n${joined}\\n${closePad}}`;\n}\n\n/**\n * Serialize a JSON value in one of the three styles. This is the entry point\n * for callers that already HAVE a value (a DB JSONB blob, an API frame) and\n * just want it laid out; text callers want {@link formatJsonText}.\n */\nexport function stringifyJson(\n value: JsonValue,\n options: JsonFormatOptions,\n): string {\n const indent = options.indent ?? DEFAULT_JSON_INDENT;\n const sortKeys = options.sortKeys ?? false;\n\n if (options.style === \"minify\") {\n return flatten(value, { indent, width: -1, pack: false, spaced: false, sortKeys });\n }\n\n const cfg: WriterConfig = {\n indent,\n width: options.style === \"pretty\" ? -1 : (options.width ?? DEFAULT_JSON_WIDTH),\n pack: options.style === \"compact\",\n spaced: true,\n sortKeys,\n };\n return renderNode(value, 0, 0, cfg);\n}\n\nfunction sizeOf(text: string): JsonTextSize {\n let lines = text === \"\" ? 0 : 1;\n for (let i = 0; i < text.length; i++) if (text[i] === \"\\n\") lines++;\n return { lines, chars: text.length };\n}\n\n/** Re-assemble the full text: leading + fence + formatted payload + trailing. */\nfunction reassemble(\n detection: JsonDetection,\n payload: string,\n mode: NonNullable<JsonFormatOptions[\"fence\"]>,\n): string {\n const { fence, leading, trailing } = detection;\n\n const keepFence =\n mode === \"add\" || (mode === \"preserve\" && fence !== null);\n if (!keepFence) {\n return leading + payload + trailing;\n }\n\n const marker = fence?.marker ?? \"```\";\n const lang = fence?.lang && fence.lang !== \"\" ? fence.lang : \"json\";\n const indent = fence?.indent ?? \"\";\n const body = indent\n ? payload\n .split(\"\\n\")\n .map((l) => (l === \"\" ? l : indent + l))\n .join(\"\\n\")\n : payload;\n\n // An unterminated source fence stays unterminated — inventing a closing fence\n // would change the surrounding document's structure, not just this block's.\n const close = fence !== null && !fence.closed ? \"\" : `\\n${indent}${marker}`;\n return `${leading}${indent}${marker}${lang}\\n${body}${close}${trailing}`;\n}\n\n/**\n * Format the JSON found in `text`, preserving everything around it.\n *\n * Never throws. When the text does not parse, the result is `ok: false`,\n * `changed: false`, and `text` is the input verbatim — a formatter that\n * mangles text it did not understand is a data-loss bug.\n */\nexport function formatJsonText(\n text: string,\n options: JsonFormatOptions,\n): JsonFormatResult {\n const detection = detectJson(text);\n const before = sizeOf(text);\n\n if (!detection.ok || detection.value === undefined) {\n return {\n ok: false,\n text,\n error: detection.error ?? \"Selection is not JSON.\",\n changed: false,\n detection,\n before,\n after: before,\n };\n }\n\n const payload = stringifyJson(detection.value, options);\n const next = reassemble(detection, payload, options.fence ?? \"preserve\");\n\n return {\n ok: true,\n text: next,\n changed: next !== text,\n detection,\n before,\n after: sizeOf(next),\n };\n}\n","/**\n * IdleScheduler — a priority-aware deferred execution system for browser apps.\n *\n * Architecture:\n * - Process-wide singleton (NOT React context) — registrations cause zero re-renders\n * - Components register lightweight callbacks with priority 1-5\n * - The scheduler waits for the browser to be truly idle after full page render\n * - Then flushes all registered callbacks in priority order\n *\n * Priority levels:\n * 1 = Highest (first of the \"last things\") — e.g., analytics init, critical measurements\n * 2 = High — e.g., prefetching next-page data, service worker registration\n * 3 = Normal — e.g., lazy-loading non-critical UI, initializing 3rd party widgets\n * 4 = Low — e.g., telemetry, background sync setup\n * 5 = Lowest (absolute last) — e.g., prewarming caches, speculative prefetch\n *\n * Cross-browser idle detection chain:\n * document.readyState === 'complete'\n * → requestAnimationFrame (past next paint)\n * → scheduler.postTask({ priority: 'background' }) [Chrome/Edge/Firefox 142+]\n * → requestIdleCallback [Chrome/Firefox, NOT Safari]\n * → MessageChannel postMessage [Universal — React's own trick]\n *\n * Ported from matrx-frontend `utils/idle-scheduler/idle-scheduler.ts`, with\n * TWO structural inversions, behavior otherwise verbatim:\n * - Scheduler state (queue, flush state, cleanups, listeners) lives on\n * `globalThis` under `Symbol.for(\"ai-matrx.kit.idle-scheduler-state\")`\n * instead of module-level variables. With the package built\n * `splitting: false` in dual ESM/CJS format this module is duplicated into\n * the root and `./idle-scheduler` bundles, and CJS/ESM each instantiate\n * their own module graph — module-level state would silently split the\n * flush pipeline from some registrants (the confirm-opener hazard). Never\n * \"clean this up\" into module locals.\n * - The `window.__idleSched()` diagnostics probe installs on first API use\n * instead of at module evaluation, keeping every entry point import-time\n * inert (the package standard). The probe itself is unchanged.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type IdlePriority = 1 | 2 | 3 | 4 | 5;\n\nexport interface IdleRegistration {\n /** Unique key for deduplication and cancellation */\n key: string;\n /** 1 = highest (first to run), 5 = lowest (last to run) */\n priority: IdlePriority;\n /** The deferred work */\n callback: () => void | Promise<void>;\n}\n\nexport type UnregisterFn = () => void;\n\nexport type FlushState = \"idle\" | \"waiting\" | \"flushing\" | \"done\";\n\n/** Experimental Scheduler API (Chrome/Edge/Firefox 142+) — not yet in standard lib types. */\ninterface GlobalThisWithScheduler {\n scheduler?: {\n postTask: (callback: () => void, options?: { priority: string }) => Promise<void>;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Singleton state — on globalThis so every bundle graph shares ONE pipeline\n// ---------------------------------------------------------------------------\n\ninterface SchedulerState {\n queue: Map<string, IdleRegistration>;\n flushState: FlushState;\n cleanupFns: Array<() => void>;\n /** Listeners that want to know when flush completes (for useIdleReady) */\n flushListeners: Set<() => void>;\n}\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.idle-scheduler-state\");\n\nfunction getState(): SchedulerState {\n const holder = globalThis as Record<symbol, SchedulerState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = {\n queue: new Map(),\n flushState: \"idle\",\n cleanupFns: [],\n flushListeners: new Set(),\n };\n holder[STATE_SLOT] = state;\n\n // Diagnostics probe: lets a console / agent read the live scheduler state\n // (`window.__idleSched()`) — the wrapper-never-mounts class of bug is\n // invisible without it.\n if (typeof window !== \"undefined\") {\n (window as unknown as { __idleSched?: () => unknown }).__idleSched =\n getSchedulerState;\n }\n }\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Register a callback to run after the page is fully idle.\n *\n * - If the scheduler hasn't flushed yet: queues the callback.\n * - If the scheduler already flushed: runs the callback immediately\n * (through the same idle detection chain, so it still won't block).\n *\n * Returns an unregister function for cleanup.\n */\nexport function registerIdleTask(\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n): UnregisterFn {\n const state = getState();\n\n // If we already flushed, schedule this one immediately (still deferred)\n if (state.flushState === \"done\") {\n scheduleImmediate(callback);\n return () => {};\n }\n\n state.queue.set(key, { key, priority, callback });\n\n // Ensure the flush pipeline is started\n if (state.flushState === \"idle\") {\n startFlushPipeline(state);\n }\n\n return () => {\n state.queue.delete(key);\n };\n}\n\n/**\n * Subscribe to the flush-complete event.\n * Useful for components that just need a \"ready\" signal without registering work.\n */\nexport function onFlushComplete(listener: () => void): UnregisterFn {\n const state = getState();\n\n if (state.flushState === \"done\") {\n // Already flushed — notify immediately (but async to avoid sync side effects)\n queueMicrotask(listener);\n return () => {};\n }\n\n state.flushListeners.add(listener);\n\n // A \"tell me when idle\" subscriber needs the pipeline RUNNING. If only\n // registerIdleTask started it, then on pages where nothing registered an\n // idle task the flush would never run and every ready-gated mount would\n // stay dormant forever. Subscribing must start the pipeline too.\n if (state.flushState === \"idle\") {\n startFlushPipeline(state);\n }\n\n return () => {\n state.flushListeners.delete(listener);\n };\n}\n\n/**\n * Resolve after the initial page-load idle flush, or earlier when aborted.\n * Non-React startup services use this instead of recreating the scheduler's\n * load → paint → browser-idle detection chain.\n *\n * @returns false when the caller aborted before idle; true otherwise.\n */\nexport function whenPageIdle(signal?: AbortSignal): Promise<boolean> {\n if (signal?.aborted) return Promise.resolve(false);\n\n return new Promise((resolve) => {\n let settled = false;\n let unsubscribe: UnregisterFn = () => {};\n\n const finish = (ready: boolean) => {\n if (settled) return;\n settled = true;\n unsubscribe();\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ready);\n };\n const onAbort = () => finish(false);\n\n unsubscribe = onFlushComplete(() => finish(true));\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Get current state — useful for debugging or conditional logic.\n */\nexport function getSchedulerState(): {\n flushState: FlushState;\n pendingCount: number;\n pendingKeys: string[];\n} {\n const state = getState();\n return {\n flushState: state.flushState,\n pendingCount: state.queue.size,\n pendingKeys: Array.from(state.queue.keys()),\n };\n}\n\n/**\n * Reset the scheduler — primarily for testing or hot-reload scenarios.\n */\nexport function resetScheduler(): void {\n const state = getState();\n state.cleanupFns.forEach((fn) => fn());\n state.cleanupFns = [];\n state.queue.clear();\n state.flushListeners.clear();\n state.flushState = \"idle\";\n}\n\n// ---------------------------------------------------------------------------\n// Flush pipeline\n// ---------------------------------------------------------------------------\n\nfunction startFlushPipeline(state: SchedulerState): void {\n if (typeof window === \"undefined\") return; // SSR guard\n\n state.flushState = \"waiting\";\n\n const waitForLoad = () => {\n if (document.readyState === \"complete\") {\n waitForPaint();\n } else {\n const onLoad = () => waitForPaint();\n window.addEventListener(\"load\", onLoad, { once: true });\n state.cleanupFns.push(() => window.removeEventListener(\"load\", onLoad));\n }\n };\n\n const waitForPaint = () => {\n // requestAnimationFrame NEVER fires while the tab is hidden (background\n // tab, restored session, headless browser) — waiting on it alone hangs the\n // whole pipeline forever in that state, so every ready-gated mount stays\n // dormant. Paint alignment is an optimization, not a correctness\n // requirement: race the rAF against a timeout so a hidden tab still\n // flushes.\n let advanced = false;\n const advance = () => {\n if (advanced) return;\n advanced = true;\n waitForIdle();\n };\n const rafId = requestAnimationFrame(advance);\n const timeoutId = setTimeout(\n advance,\n document.visibilityState === \"hidden\" ? 250 : 1_500,\n );\n state.cleanupFns.push(() => {\n cancelAnimationFrame(rafId);\n clearTimeout(timeoutId);\n });\n };\n\n const waitForIdle = () => {\n // Tier 1: scheduler.postTask with background priority (Chrome/Edge/Firefox 142+)\n const schedulerGlobal = (globalThis as GlobalThisWithScheduler).scheduler;\n if (schedulerGlobal && \"postTask\" in schedulerGlobal) {\n schedulerGlobal\n .postTask(() => void flush(state), { priority: \"background\" })\n .catch(() => {});\n return;\n }\n\n // Tier 2: requestIdleCallback (Chrome, Firefox — NOT Safari stable)\n if (\"requestIdleCallback\" in window) {\n const idleId = requestIdleCallback(() => void flush(state));\n state.cleanupFns.push(() => cancelIdleCallback(idleId));\n return;\n }\n\n // Tier 3: MessageChannel — universal, including Safari + iOS Safari\n // This is what React's scheduler uses internally.\n const channel = new MessageChannel();\n channel.port1.onmessage = () => void flush(state);\n channel.port2.postMessage(undefined);\n };\n\n waitForLoad();\n}\n\nasync function flush(state: SchedulerState): Promise<void> {\n if (state.flushState === \"done\" || state.flushState === \"flushing\") return;\n state.flushState = \"flushing\";\n\n // Sort by priority (1 first, 5 last), stable sort preserving insertion order within priority\n const sorted = Array.from(state.queue.values()).sort(\n (a, b) => a.priority - b.priority,\n );\n\n // Clear the queue before executing (so late registrations during flush\n // are treated as \"post-flush\" and get scheduled immediately)\n state.queue.clear();\n\n for (const task of sorted) {\n try {\n await task.callback();\n } catch (err) {\n console.error(`[IdleScheduler] Task \"${task.key}\" failed:`, err);\n }\n }\n\n state.flushState = \"done\";\n\n // DEFECT FIX vs the original (see CHANGELOG 0.4.0): a task registered WHILE\n // the flush loop was running (flushState === \"flushing\") landed back in the\n // queue — which nothing ever drained again, so the task silently never ran.\n // The comment above promises such registrations are \"treated as post-flush\n // and get scheduled immediately\"; make that true.\n if (state.queue.size > 0) {\n const late = Array.from(state.queue.values()).sort(\n (a, b) => a.priority - b.priority,\n );\n state.queue.clear();\n for (const task of late) scheduleImmediate(task.callback);\n }\n\n // Notify all listeners\n state.flushListeners.forEach((listener) => {\n try {\n listener();\n } catch (err) {\n console.error(\"[IdleScheduler] Flush listener failed:\", err);\n }\n });\n state.flushListeners.clear();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Schedule a single callback through the idle chain (for post-flush registrations) */\nfunction scheduleImmediate(callback: () => void | Promise<void>): void {\n requestAnimationFrame(() => {\n const schedulerGlobal = (globalThis as GlobalThisWithScheduler).scheduler;\n if (schedulerGlobal && \"postTask\" in schedulerGlobal) {\n schedulerGlobal\n .postTask(() => void callback(), { priority: \"background\" })\n .catch(() => {});\n return;\n }\n if (\"requestIdleCallback\" in window) {\n requestIdleCallback(() => void callback());\n return;\n }\n const channel = new MessageChannel();\n channel.port1.onmessage = () => void callback();\n channel.port2.postMessage(undefined);\n });\n}\n","/**\n * React hooks for the IdleScheduler.\n *\n * These are intentionally thin — they just wire up registration/cleanup\n * to React's lifecycle. No state, no context, no re-renders on registration.\n *\n * Three hooks for three use cases:\n *\n * 1. useIdleTask(key, priority, callback)\n * → \"Run this callback when idle. I don't need to know when.\"\n * → Fire-and-forget. Zero re-renders.\n *\n * 2. useIdleReady()\n * → \"Just tell me when idle flush is done so I can wake up.\"\n * → Returns a boolean. One re-render: false → true.\n *\n * 3. useIdleGate(key, priority, callback)\n * → \"Run this callback when idle AND tell me when it's done.\"\n * → Returns { ready: boolean }. Combines both patterns.\n *\n * Plus useIdleRegister() for imperative/conditional registration.\n *\n * Ported verbatim from matrx-frontend `utils/idle-scheduler/hooks.ts`.\n */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useCallback } from \"react\";\nimport {\n registerIdleTask,\n onFlushComplete,\n type IdlePriority,\n} from \"./scheduler\";\n\n// ---------------------------------------------------------------------------\n// useIdleTask — fire-and-forget deferred work\n// ---------------------------------------------------------------------------\n\n/**\n * Register a callback to execute after page idle. Zero re-renders.\n *\n * @param key Unique identifier (for deduplication/cancellation)\n * @param priority 1 (first of last) through 5 (absolute last)\n * @param callback The deferred work\n *\n * @example\n * ```tsx\n * useIdleTask('analytics-init', 3, () => {\n * initializeAnalytics();\n * });\n * ```\n */\nexport function useIdleTask(\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n): void {\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n const unregister = registerIdleTask(key, priority, () => {\n return callbackRef.current();\n });\n return unregister;\n }, [key, priority]);\n}\n\n// ---------------------------------------------------------------------------\n// useIdleReady — \"am I allowed to wake up yet?\"\n// ---------------------------------------------------------------------------\n\n/**\n * Returns `true` once the idle flush has completed.\n * Causes exactly one re-render (false → true). No work is registered.\n *\n * Use this when a component wants to stay dormant (show nothing, or a skeleton)\n * until the page is fully settled, then \"turn on.\"\n *\n * @example\n * ```tsx\n * function HeavyWidget() {\n * const ready = useIdleReady();\n * if (!ready) return null; // or a skeleton\n * return <ExpensiveComponent />;\n * }\n * ```\n */\nexport function useIdleReady(): boolean {\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n const unsubscribe = onFlushComplete(() => {\n setReady(true);\n });\n return unsubscribe;\n }, []);\n\n return ready;\n}\n\n// ---------------------------------------------------------------------------\n// useIdleGate — register work AND get a ready signal\n// ---------------------------------------------------------------------------\n\n/**\n * Register deferred work and get a `ready` signal when it completes.\n *\n * This is the \"full package\" — your component stays dormant, the scheduler\n * runs your callback at the right time, and then you get notified to\n * update your UI.\n *\n * @example\n * ```tsx\n * function PrefetchedSection() {\n * const { ready } = useIdleGate('prefetch-recommendations', 2, async () => {\n * await prefetchRecommendations();\n * });\n *\n * if (!ready) return <Skeleton />;\n * return <Recommendations />;\n * }\n * ```\n */\nexport function useIdleGate(\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n): { ready: boolean } {\n const [ready, setReady] = useState(false);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n const unregister = registerIdleTask(key, priority, async () => {\n await callbackRef.current();\n setReady(true);\n });\n return unregister;\n }, [key, priority]);\n\n return { ready };\n}\n\n// ---------------------------------------------------------------------------\n// useIdleRegister — imperative registration (for dynamic/conditional work)\n// ---------------------------------------------------------------------------\n\n/**\n * Returns a `register` function you can call imperatively.\n * Useful when the deferred work depends on runtime conditions.\n *\n * @example\n * ```tsx\n * function SearchResults({ query }) {\n * const scheduleIdle = useIdleRegister();\n *\n * useEffect(() => {\n * if (query) {\n * scheduleIdle(`prefetch-${query}`, 4, () => {\n * prefetchRelatedResults(query);\n * });\n * }\n * }, [query, scheduleIdle]);\n * }\n * ```\n */\nexport function useIdleRegister(): (\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n) => void {\n const unregisterRefs = useRef<Map<string, () => void>>(new Map());\n\n // Cleanup all registrations on unmount\n useEffect(() => {\n const refs = unregisterRefs.current;\n return () => {\n refs.forEach((unregister) => unregister());\n refs.clear();\n };\n }, []);\n\n return useCallback(\n (\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n ) => {\n // Cancel previous registration with same key\n unregisterRefs.current.get(key)?.();\n\n const unregister = registerIdleTask(key, priority, callback);\n unregisterRefs.current.set(key, unregister);\n },\n [],\n );\n}\n","\"use client\";\n\n/**\n * @ai-matrx/kit/url-state — THE canonical URL-state core. Every surface that\n * puts view state in the address bar goes through here.\n *\n * The URL is the source of truth: refresh, copied links, and browser\n * back/forward all reproduce the same value. Discrete controls push a history\n * entry by default; high-frequency text inputs opt into `replace` so a single\n * search does not create one entry per keystroke.\n *\n * WHY A RAW `history.pushState` IS A BUG, not just a style choice. It fires no\n * event and no popstate, so every OTHER url-backed control on the page keeps\n * rendering stale values until something unrelated re-renders it.\n * `commitUrlParams` dispatches `matrx:url-state`, which is what\n * `useUrlSearchParams` subscribes to. (Measured in the Matrx frontend,\n * 2026-08-25: 33 hand-rolled writes across 21 files, every one of them\n * silent.)\n *\n * PICK THE RIGHT ONE:\n * one control owns one parameter → `useUrlState` + a codec\n * a cluster of values moving together → `useMirroredUrlState`\n *\n * Codecs below cover string / enum / boolean / positive-integer / JSON, and all\n * of them OMIT the default rather than writing it, so a pristine surface has a\n * clean URL and a link carries only what the user actually chose.\n *\n * Ported verbatim from matrx-frontend `lib/url-state/useUrlState.ts`. The\n * original deliberately imports NOTHING from `next/navigation` — it writes\n * through the History API and notifies subscribers itself, which is exactly\n * how it runs in the Next.js App Router host. This port adds ONE optional\n * seam on top of that verbatim behavior: `setUrlStateRouter` lets a host whose\n * router must observe/perform the writes (react-router, a memory router in\n * tests, a native shell) inject `{ push, replace, getLocation? }`. With no\n * router injected — the default, and the Next.js wiring — behavior is\n * byte-identical to the original. The injected router lives on `globalThis`\n * under `Symbol.for(\"ai-matrx.kit.url-state-router\")` because the package\n * builds `splitting: false` dual ESM/CJS: module-level state would silently\n * split the registration across bundle graphs (the confirm-opener hazard).\n */\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\nconst URL_STATE_EVENT = \"matrx:url-state\";\n\n/**\n * The optional injected router. `push`/`replace` receive the full relative\n * URL (`pathname?query#hash`) exactly as the History API default would write\n * it. `getLocation` overrides where the current URL is read from (a memory\n * router); absent, `window.location` is read.\n */\nexport interface UrlStateRouter {\n push: (url: string) => void;\n replace: (url: string) => void;\n getLocation?: (() => { pathname: string; search: string; hash: string }) | undefined;\n}\n\nconst ROUTER_SLOT = Symbol.for(\"ai-matrx.kit.url-state-router\");\n\nfunction getRouter(): UrlStateRouter | null {\n return (\n (globalThis as Record<symbol, UrlStateRouter | null | undefined>)[\n ROUTER_SLOT\n ] ?? null\n );\n}\n\n/**\n * Inject (or with `null` remove) the host router. Optional — with none set,\n * writes go through `window.history` push/replaceState, which is the verbatim\n * Matrx-frontend behavior and correct for Next.js App Router hosts.\n */\nexport function setUrlStateRouter(router: UrlStateRouter | null): void {\n (globalThis as Record<symbol, UrlStateRouter | null | undefined>)[\n ROUTER_SLOT\n ] = router;\n}\n\nfunction currentLocation(): { pathname: string; search: string; hash: string } {\n const custom = getRouter()?.getLocation;\n if (custom) return custom();\n return {\n pathname: window.location.pathname,\n search: window.location.search,\n hash: window.location.hash,\n };\n}\n\nfunction subscribeToUrl(listener: () => void) {\n window.addEventListener(\"popstate\", listener);\n window.addEventListener(URL_STATE_EVENT, listener);\n return () => {\n window.removeEventListener(\"popstate\", listener);\n window.removeEventListener(URL_STATE_EVENT, listener);\n };\n}\n\nfunction getUrlSnapshot() {\n return currentLocation().search;\n}\n\nfunction getServerUrlSnapshot() {\n return \"\";\n}\n\n/** Reactive query-string snapshot for URL-backed primitives. */\nexport function useUrlSearchParams(): URLSearchParams {\n const search = useSyncExternalStore(\n subscribeToUrl,\n getUrlSnapshot,\n getServerUrlSnapshot,\n );\n return useMemo(() => new URLSearchParams(search), [search]);\n}\n\nexport type UrlHistoryMode = \"push\" | \"replace\";\n\nexport interface UrlStateCodec<T> {\n defaultValue: T;\n parse: (raw: string | null) => T;\n serialize: (value: T) => string | null;\n}\n\nexport interface SetUrlStateOptions {\n history?: UrlHistoryMode | undefined;\n}\n\nexport function commitUrlParams(\n patch: Readonly<Record<string, string | null>>,\n history: UrlHistoryMode,\n) {\n const location = currentLocation();\n const params = new URLSearchParams(location.search);\n for (const [key, value] of Object.entries(patch)) {\n if (value === null || value === \"\") params.delete(key);\n else params.set(key, value);\n }\n\n const query = params.toString();\n const next = `${location.pathname}${query ? `?${query}` : \"\"}${location.hash}`;\n const current = `${location.pathname}${location.search}${location.hash}`;\n if (next === current) return;\n\n const router = getRouter();\n if (router) {\n if (history === \"replace\") router.replace(next);\n else router.push(next);\n } else if (history === \"replace\") {\n window.history.replaceState(window.history.state, \"\", next);\n } else {\n window.history.pushState(window.history.state, \"\", next);\n }\n window.dispatchEvent(new Event(URL_STATE_EVENT));\n}\n\n/**\n * Classify a URL transition for surfaces that MIRROR state (a store, local\n * state) into the URL from an effect, where there is no single call site to\n * label.\n *\n * THE RULE: a discrete user decision (tab, filter, sort, page, selection)\n * PUSHES, so Back undoes exactly that one step; only high-frequency text\n * (`textKeys` — search boxes, a slider being dragged) REPLACES, so one search\n * is one entry instead of one per keystroke.\n */\nexport function historyModeForParamChange(\n current: URLSearchParams,\n next: URLSearchParams,\n textKeys: readonly string[],\n): UrlHistoryMode {\n const keys = new Set([...current.keys(), ...next.keys()]);\n const changed = [...keys].filter(\n (key) => current.get(key) !== next.get(key),\n );\n if (changed.length === 0) return \"replace\";\n return changed.every((key) => textKeys.includes(key)) ? \"replace\" : \"push\";\n}\n\nexport function useUrlState<T>(\n key: string,\n codec: UrlStateCodec<T>,\n): readonly [T, (value: T, options?: SetUrlStateOptions) => void] {\n const searchParams = useUrlSearchParams();\n const value = codec.parse(searchParams.get(key));\n\n const setValue = (next: T, options?: SetUrlStateOptions) => {\n commitUrlParams(\n { [key]: codec.serialize(next) },\n options?.history ?? \"push\",\n );\n };\n\n return [value, setValue] as const;\n}\n\nexport function stringUrlCodec(defaultValue = \"\"): UrlStateCodec<string> {\n return {\n defaultValue,\n parse: (raw) => raw ?? defaultValue,\n serialize: (value) => (value === defaultValue ? null : value),\n };\n}\n\nexport function enumUrlCodec<const T extends string>(\n values: readonly T[],\n defaultValue: T,\n): UrlStateCodec<T> {\n const allowed = new Set<string>(values);\n return {\n defaultValue,\n parse: (raw) => (raw && allowed.has(raw) ? (raw as T) : defaultValue),\n serialize: (value) => (value === defaultValue ? null : value),\n };\n}\n\nexport function booleanUrlCodec(defaultValue = false): UrlStateCodec<boolean> {\n return {\n defaultValue,\n parse: (raw) => (raw === null ? defaultValue : raw === \"1\"),\n serialize: (value) => (value === defaultValue ? null : value ? \"1\" : \"0\"),\n };\n}\n\nexport function positiveIntegerUrlCodec(\n defaultValue: number,\n): UrlStateCodec<number> {\n return {\n defaultValue,\n parse: (raw) => {\n const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;\n return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultValue;\n },\n serialize: (value) =>\n value === defaultValue || !Number.isFinite(value) || value <= 0\n ? null\n : String(Math.trunc(value)),\n };\n}\n\nexport function jsonUrlCodec<T>(\n defaultValue: T,\n isValid: (value: unknown) => value is T,\n): UrlStateCodec<T> {\n return {\n defaultValue,\n parse: (raw) => {\n if (!raw) return defaultValue;\n try {\n const parsed: unknown = JSON.parse(raw);\n return isValid(parsed) ? parsed : defaultValue;\n } catch {\n return defaultValue;\n }\n },\n serialize: (value) =>\n JSON.stringify(value) === JSON.stringify(defaultValue)\n ? null\n : JSON.stringify(value),\n };\n}\n\n/**\n * Mirror a whole view-state OBJECT into the URL, in both directions.\n *\n * THE PATTERN 18 FILES WERE HAND-ROLLING. `useUrlState` is right when one\n * control owns one parameter. It is the wrong shape when a surface holds a\n * cluster of related values (search + sort + filters + page) that must move\n * together, be seeded from the URL on first render, and follow Back/Forward.\n * Every surface that needed that wrote its own `history.pushState` — and NONE\n * of them dispatched the sync event, so any other URL-backed control on the\n * same page silently kept showing stale values after they wrote.\n *\n * 🚨 THE LOOP IS BROKEN BY VALUE, NEVER BY BOOKKEEPING. The obvious guard —\n * remember the last URL you wrote and ignore anything matching it — looks\n * equivalent and is not: pressing Forward to a view already visited produces a\n * URL you did indeed write before, so the guard swallows it and the address bar\n * moves while the surface does not. Compare the DECODED value to the current\n * one instead; your own write compares equal and stops.\n *\n * Seeding happens in the `useState` initialiser, not an effect, so the first\n * render already shows the requested view rather than flashing the default and\n * fetching the wrong page before correcting itself.\n */\nexport interface MirroredUrlStateOptions<T> {\n /** Decode the whole value from the query string. Must never throw. */\n parse: (params: URLSearchParams) => T;\n /** Encode it; `null` for a key means \"omit\", which keeps defaults out of the URL. */\n toParams: (value: T) => Record<string, string | null>;\n /** Value equality — what stops the two directions fighting. */\n isSame: (a: T, b: T) => boolean;\n /** Keys that REPLACE instead of pushing (search boxes, dragged sliders). */\n textKeys?: readonly string[] | undefined;\n /**\n * Changing this clears the mirrored state and its parameters — for when the\n * surface switches to a different subject and the old view would be a lie.\n */\n resetKey?: string | undefined;\n}\n\nexport function useMirroredUrlState<T>(\n options: MirroredUrlStateOptions<T>,\n): readonly [T, (updater: T | ((prev: T) => T)) => void] {\n const { parse, toParams, isSame, textKeys = [], resetKey } = options;\n const params = useUrlSearchParams();\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const [value, setValue] = useState<T>(() =>\n parse(\n typeof window === \"undefined\"\n ? new URLSearchParams()\n : new URLSearchParams(currentLocation().search),\n ),\n );\n\n // value → URL\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const current = new URLSearchParams(currentLocation().search);\n const patch = optionsRef.current.toParams(value);\n\n const next = new URLSearchParams(current);\n for (const [key, v] of Object.entries(patch)) {\n if (v === null || v === \"\") next.delete(key);\n else next.set(key, v);\n }\n if (next.toString() === current.toString()) return;\n\n commitUrlParams(patch, historyModeForParamChange(current, next, textKeys));\n // `textKeys` is a literal in every caller; `value` is the real trigger.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n // URL → value (Back/Forward, a pasted link, another control writing)\n useEffect(() => {\n // Read the URL at EFFECT time, not the render snapshot. The value→URL\n // effect runs first. When it commits a local filter/sort decision it\n // synchronously notifies the external store, but `params` in this render\n // still describes the URL from before that write. Re-applying that stale\n // snapshot here ping-pongs state and URL until React raises #185.\n const fromUrl = optionsRef.current.parse(\n new URLSearchParams(currentLocation().search),\n );\n setValue((prev) => (optionsRef.current.isSame(prev, fromUrl) ? prev : fromUrl));\n }, [params]);\n\n // Clearing on a subject change is deliberate; clearing on a subject ARRIVING\n // is destructive. A surface whose id is undefined for its first render (async\n // params, a late store hydration, a suspended boundary) would otherwise wipe\n // the very view the user just loaded — and the symptom is indistinguishable\n // from \"the URL never saved my filters\", because the write lands and is\n // erased a tick later.\n //\n // So: only a transition between two REAL, DIFFERENT keys resets.\n const previousResetKey = useRef(resetKey);\n useEffect(() => {\n const previous = previousResetKey.current;\n previousResetKey.current = resetKey;\n if (previous === resetKey) return;\n if (previous === undefined || previous === \"\") return; // arriving, not changing\n if (resetKey === undefined || resetKey === \"\") return; // leaving, not changing\n\n const cleared = optionsRef.current.parse(new URLSearchParams());\n setValue(cleared);\n commitUrlParams(optionsRef.current.toParams(cleared), \"replace\");\n }, [resetKey]);\n\n const update = useCallback((updater: T | ((prev: T) => T)) => {\n setValue((prev) =>\n typeof updater === \"function\"\n ? (updater as (p: T) => T)(prev)\n : updater,\n );\n }, []);\n\n return [value, update] as const;\n}\n","/**\n * @ai-matrx/kit/idb-store — base manager.\n *\n * Ported verbatim from matrx-frontend `lib/idb/store-manager.ts`, with ONE\n * structural inversion: the original documented a `protected static _instance`\n * convention (each subclass held its singleton on its own static field).\n * A class-static is module state — with this package built `splitting: false`\n * in dual ESM/CJS format the class is duplicated into the root bundle and the\n * `./idb-store` bundle, and CJS/ESM each instantiate their own module graph,\n * so a static field would silently split \"the\" singleton into up to four\n * instances racing the same IndexedDB database. The singleton slot therefore\n * lives on `globalThis` under `Symbol.for(\"ai-matrx.kit.idb-store-state\")`\n * instead — see `singleton.ts` (`getIdbStoreSingleton`). Never \"clean this\n * up\" back into a static field.\n */\n\nimport { openDB, IDBPDatabase } from \"idb\";\n\nexport type AsyncResult<T> = Promise<{ data: T | null; error: Error | null }>;\n\nexport abstract class DBStoreManager<T> {\n protected db: IDBPDatabase | null = null;\n protected dbName: string;\n protected version: number;\n\n protected constructor(dbName: string, version: number) {\n this.dbName = dbName;\n this.version = version;\n }\n\n protected abstract setupStores(db: IDBPDatabase): void;\n\n protected async initDB(): Promise<void> {\n if (this.db) return;\n\n try {\n this.db = await openDB(this.dbName, this.version, {\n upgrade: (db) => {\n this.setupStores(db);\n },\n });\n } catch (error) {\n console.error(\"Failed to initialize database:\", error);\n throw error;\n }\n }\n\n // `add`/`get` carry their own generic (like `query` below) so a subclass\n // whose `T` covers one IDB object store (e.g. Recording) can still read/write\n // a different store's record shape (e.g. RecordingChunk) without a cast —\n // see the audio store in the original host, which manages both `recordings`\n // and `chunks` stores.\n protected async add<TRecord = T>(storeName: string, data: TRecord): AsyncResult<string> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const id = await this.db.add(storeName, data);\n return { data: id.toString(), error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async get<TRecord = T>(storeName: string, id: string): AsyncResult<TRecord> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const result = await this.db.get(storeName, id);\n return { data: result as TRecord, error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async getAll(storeName: string): AsyncResult<T[]> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const result = await this.db.getAll(storeName);\n return { data: result as T[], error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async update<U extends object>(storeName: string, id: number, data: Partial<U>): AsyncResult<boolean> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const existing = await this.db.get(storeName, id);\n if (!existing) throw new Error(\"Record not found\");\n\n const updated = { ...existing, ...data };\n await this.db.put(storeName, updated);\n return { data: true, error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async delete(storeName: string, id: number): AsyncResult<boolean> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n await this.db.delete(storeName, id);\n return { data: true, error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async query<U>(\n storeName: string,\n indexName: string,\n query: IDBValidKey | IDBKeyRange\n ): AsyncResult<U[]> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const result = await this.db.getAllFromIndex(storeName, indexName, query);\n return { data: result as U[], error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n}\n","/**\n * Public CRUD surface over `DBStoreManager` — ported verbatim from\n * matrx-frontend `lib/idb/store-interface.ts`. The base keeps its operations\n * `protected` so feature stores expose intent-named methods; this subclass is\n * the escape hatch for hosts that want the raw generic surface (e.g. a\n * `useIDB(store)` hook driving arbitrary stores).\n *\n * NOTE (original API shape, kept verbatim): `getItem` takes a string id while\n * `updateItem`/`deleteItem` take a number id. With an `autoIncrement` key path\n * the generated keys are numbers, so reads use `String(id)` only against\n * string-keyed stores — this asymmetry is the original public contract.\n */\n\nimport { DBStoreManager, AsyncResult } from \"./store-manager\";\n\nexport abstract class PublicStoreManager<T> extends DBStoreManager<T> {\n constructor(dbName: string, version: number) {\n super(dbName, version);\n }\n\n public addItem(storeName: string, data: T): AsyncResult<string> {\n return this.add(storeName, data);\n }\n\n public getItem(storeName: string, id: string): AsyncResult<T> {\n return this.get(storeName, id);\n }\n\n public getAllItems(storeName: string): AsyncResult<T[]> {\n return this.getAll(storeName);\n }\n\n public updateItem<U extends object>(\n storeName: string,\n id: number,\n data: Partial<U>\n ): AsyncResult<boolean> {\n return this.update<U>(storeName, id, data);\n }\n\n public deleteItem(storeName: string, id: number): AsyncResult<boolean> {\n return this.delete(storeName, id);\n }\n\n public queryItems<U>(\n storeName: string,\n indexName: string,\n query: IDBValidKey | IDBKeyRange\n ): AsyncResult<U[]> {\n return this.query<U>(storeName, indexName, query);\n }\n}\n","/**\n * Convenience base for a store class bound to one named object store —\n * ported from matrx-frontend `lib/idb/feature-store.ts`.\n *\n * DEFECT FIX vs the original: the constructor kicks off `initDB()` without\n * awaiting it (by design — construction stays synchronous and operations\n * before init resolve `{ error: \"Database not initialized\" }`), but the\n * original left that floating promise unhandled, so a failed `openDB` (e.g.\n * private-mode storage denial) surfaced as an unhandled promise rejection on\n * top of the `initDB` console.error. The rejection is now absorbed here —\n * `initDB` has already screamed, and every operation still reports the\n * uninitialized state through its `AsyncResult` error.\n */\n\nimport { IDBPDatabase } from \"idb\";\nimport { PublicStoreManager } from \"./store-interface\";\n\nexport abstract class FeatureStore<T> extends PublicStoreManager<T> {\n protected storeName: string;\n\n protected constructor(dbName: string, version: number, storeName: string) {\n super(dbName, version);\n this.storeName = storeName;\n this.initDB().catch(() => {\n // Already logged loudly by initDB; operations report\n // \"Database not initialized\" through their AsyncResult.\n });\n }\n\n protected abstract override setupStores(db: IDBPDatabase): void;\n\n public getStoreName(): string {\n return this.storeName;\n }\n}\n","/**\n * The one place a store singleton may live.\n *\n * The original host pattern held each store's singleton on a\n * `protected static _instance` field of the store class. In this package that\n * is a hazard, not a convenience: built `splitting: false` in dual ESM/CJS\n * format, the class body is duplicated into the root bundle and the\n * `./idb-store` bundle, and the ESM and CJS graphs each instantiate their own\n * copy — a class-static would silently split \"the\" singleton into several\n * instances, each opening its own connection (and racing upgrades) against\n * the same IndexedDB database. So per-store instances live on `globalThis`\n * under `Symbol.for(\"ai-matrx.kit.idb-store-state\")`, keyed by a\n * caller-chosen name. Never \"clean this up\" into module or class state.\n *\n * Host usage (replaces the old static `getInstance` body):\n *\n * class AudioStore extends DBStoreManager<Recording> { ... }\n * export const audioStore = getIdbStoreSingleton(\"voiceNotesDB/audio\", () => new AudioStore());\n */\n\ninterface IdbStoreState {\n instances: Map<string, unknown>;\n}\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.idb-store-state\");\n\nfunction getState(): IdbStoreState {\n const holder = globalThis as Record<symbol, IdbStoreState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = { instances: new Map() };\n holder[STATE_SLOT] = state;\n }\n return state;\n}\n\n/**\n * Returns the one instance registered under `key`, creating it via `create`\n * on first call. The key should uniquely name the store (a good convention is\n * `\"<dbName>/<storeName>\"`) — two different classes registering the same key\n * is a caller bug and gets whichever registered first.\n */\nexport function getIdbStoreSingleton<T>(key: string, create: () => T): T {\n const state = getState();\n if (!state.instances.has(key)) {\n state.instances.set(key, create());\n }\n return state.instances.get(key) as T;\n}\n\n/** @internal Test-only: drop every registered store instance. */\nexport function _resetIdbStoreSingletons(): void {\n getState().instances.clear();\n}\n","/**\n * The zero-dependency perceptual-distance engine behind the string input path\n * of `findNearestTailwindColor`.\n *\n * The matrx-frontend original computed distance through colord's lab plugin\n * (`colordInstance.delta(hex)`). This module reproduces that plugin's exact\n * pipeline — sRGB → XYZ(D65) → chromatic adaptation to D50 (colord's\n * matrices, including its channel clamps) → CIE L*a*b* rounded to 2 decimals\n * → CIEDE2000 (colord >= 2.10 formulation) ÷ 100, rounded to 3 decimals and\n * clamped to [0, 1] — so the nearest-token answer is bit-identical to the\n * colord path. The test suite cross-checks this against colord itself (a\n * devDependency only).\n */\n\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\ninterface Lab {\n l: number;\n a: number;\n b: number;\n}\n\n/** colord's rounding helper: round to `digits` decimal places. */\nfunction round(value: number, digits = 0): number {\n const factor = Math.pow(10, digits);\n return Math.round(factor * value) / factor + 0;\n}\n\nfunction clamp(value: number, min = 0, max = 1): number {\n return value > max ? max : value > min ? value : min;\n}\n\n/** sRGB channel (0–255) → linear-light (0–1). */\nfunction linearize(channel: number): number {\n const c = channel / 255;\n return c < 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n// D50 reference white (colord's constants).\nconst WHITE_X = 96.422;\nconst WHITE_Y = 100;\nconst WHITE_Z = 82.521;\n\nconst EPSILON = 216 / 24389;\nconst KAPPA = 24389 / 27;\n\n/** sRGB → XYZ(D65) → Bradford-adapted D50, clamped — colord's exact matrices. */\nfunction rgbToXyz(rgb: Rgb): { x: number; y: number; z: number } {\n const r = linearize(rgb.r);\n const g = linearize(rgb.g);\n const b = linearize(rgb.b);\n const d65 = {\n x: 100 * (0.4124564 * r + 0.3575761 * g + 0.1804375 * b),\n y: 100 * (0.2126729 * r + 0.7151522 * g + 0.072175 * b),\n z: 100 * (0.0193339 * r + 0.119192 * g + 0.9503041 * b),\n };\n const d50 = {\n x: 1.0478112 * d65.x + 0.0228866 * d65.y + -0.050127 * d65.z,\n y: 0.0295424 * d65.x + 0.9904844 * d65.y + -0.0170491 * d65.z,\n z: -0.0092345 * d65.x + 0.0150436 * d65.y + 0.7521316 * d65.z,\n };\n return {\n x: clamp(d50.x, 0, WHITE_X),\n y: clamp(d50.y, 0, WHITE_Y),\n z: clamp(d50.z, 0, WHITE_Z),\n };\n}\n\n/** RGB → CIE L*a*b*, rounded to 2 decimals exactly like colord's `toLab`. */\nexport function rgbToLab(rgb: Rgb): Lab {\n const xyz = rgbToXyz(rgb);\n let x = xyz.x / WHITE_X;\n let y = xyz.y / WHITE_Y;\n let z = xyz.z / WHITE_Z;\n x = x > EPSILON ? Math.cbrt(x) : (KAPPA * x + 16) / 116;\n y = y > EPSILON ? Math.cbrt(y) : (KAPPA * y + 16) / 116;\n z = z > EPSILON ? Math.cbrt(z) : (KAPPA * z + 16) / 116;\n return {\n l: round(116 * y - 16, 2),\n a: round(500 * (x - y), 2),\n b: round(200 * (y - z), 2),\n };\n}\n\n/** CIEDE2000 between two Lab colors — colord's exact formulation. */\nfunction ciede2000(lab1: Lab, lab2: Lab): number {\n const { l: l1, a: a1, b: b1 } = lab1;\n const { l: l2, a: a2, b: b2 } = lab2;\n const toDeg = 180 / Math.PI;\n const toRad = Math.PI / 180;\n\n const c1 = Math.pow(Math.pow(a1, 2) + Math.pow(b1, 2), 0.5);\n const c2 = Math.pow(Math.pow(a2, 2) + Math.pow(b2, 2), 0.5);\n const lBar = (l1 + l2) / 2;\n const cBar7 = Math.pow((c1 + c2) / 2, 7);\n const g = 0.5 * (1 - Math.pow(cBar7 / (cBar7 + Math.pow(25, 7)), 0.5));\n const a1p = a1 * (1 + g);\n const a2p = a2 * (1 + g);\n const c1p = Math.pow(Math.pow(a1p, 2) + Math.pow(b1, 2), 0.5);\n const c2p = Math.pow(Math.pow(a2p, 2) + Math.pow(b2, 2), 0.5);\n const cBarP = (c1p + c2p) / 2;\n let h1p = a1p === 0 && b1 === 0 ? 0 : Math.atan2(b1, a1p) * toDeg;\n let h2p = a2p === 0 && b2 === 0 ? 0 : Math.atan2(b2, a2p) * toDeg;\n if (h1p < 0) h1p += 360;\n if (h2p < 0) h2p += 360;\n\n let dhp = h2p - h1p;\n const hAbs = Math.abs(h2p - h1p);\n if (hAbs > 180 && h2p <= h1p) {\n dhp += 360;\n } else if (hAbs > 180 && h2p > h1p) {\n dhp -= 360;\n }\n let hBarP = h1p + h2p;\n if (hAbs <= 180) {\n hBarP /= 2;\n } else {\n hBarP = (h1p + h2p < 360 ? hBarP + 360 : hBarP - 360) / 2;\n }\n\n const t =\n 1 -\n 0.17 * Math.cos(toRad * (hBarP - 30)) +\n 0.24 * Math.cos(2 * toRad * hBarP) +\n 0.32 * Math.cos(toRad * (3 * hBarP + 6)) -\n 0.2 * Math.cos(toRad * (4 * hBarP - 63));\n const dL = l2 - l1;\n const dCp = c2p - c1p;\n const dHp = 2 * Math.sin((toRad * dhp) / 2) * Math.pow(c1p * c2p, 0.5);\n const sl =\n 1 +\n (0.015 * Math.pow(lBar - 50, 2)) /\n Math.pow(20 + Math.pow(lBar - 50, 2), 0.5);\n const sc = 1 + 0.045 * cBarP;\n const sh = 1 + 0.015 * cBarP * t;\n const dTheta = 30 * Math.exp(-1 * Math.pow((hBarP - 275) / 25, 2));\n // colord >= 2.10 computes the rotation term from the adjusted mean chroma\n // (C'bar^7), the standard CIEDE2000 formulation.\n const cBarP7 = Math.pow(cBarP, 7);\n const rt =\n -2 *\n Math.pow(cBarP7 / (cBarP7 + Math.pow(25, 7)), 0.5) *\n Math.sin(2 * toRad * dTheta);\n\n return Math.pow(\n Math.pow(dL / 1 / sl, 2) +\n Math.pow(dCp / 1 / sc, 2) +\n Math.pow(dHp / 1 / sh, 2) +\n (rt * dCp * dHp) / (1 * sc * 1 * sh),\n 0.5,\n );\n}\n\n/**\n * Perceptual distance between two RGB colors, normalized exactly like\n * colord's `.delta()`: CIEDE2000 / 100, rounded to 3 decimals, clamped [0,1].\n */\nexport function rgbDelta(rgb1: Rgb, rgb2: Rgb): number {\n return clamp(round(ciede2000(rgbToLab(rgb1), rgbToLab(rgb2)) / 100, 3));\n}\n\nconst HEX_RE = /^#?([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGB_FN_RE =\n /^rgba?\\(\\s*([+-]?[\\d.]+)\\s*[,\\s]\\s*([+-]?[\\d.]+)\\s*[,\\s]\\s*([+-]?[\\d.]+)(?:\\s*[,/]\\s*[+-]?[\\d.]+%?)?\\s*\\)$/i;\n\n/**\n * Parses the two input shapes this unit is chartered for — hex (`#rgb`,\n * `#rrggbb`, with or without `#`, alpha digits tolerated and ignored) and\n * `rgb()`/`rgba()` strings — into RGB channels. Returns `null` for anything\n * else; this is deliberately NOT a general CSS color parser.\n */\nexport function parseHexOrRgb(input: string): Rgb | null {\n const text = input.trim();\n const hexMatch = text.match(HEX_RE);\n if (hexMatch) {\n const hex = hexMatch[1] as string;\n if (hex.length === 3 || hex.length === 4) {\n return {\n r: parseInt((hex[0] as string) + hex[0], 16),\n g: parseInt((hex[1] as string) + hex[1], 16),\n b: parseInt((hex[2] as string) + hex[2], 16),\n };\n }\n return {\n r: parseInt(hex.slice(0, 2), 16),\n g: parseInt(hex.slice(2, 4), 16),\n b: parseInt(hex.slice(4, 6), 16),\n };\n }\n const rgbMatch = text.match(RGB_FN_RE);\n if (rgbMatch) {\n const r = Number(rgbMatch[1]);\n const g = Number(rgbMatch[2]);\n const b = Number(rgbMatch[3]);\n if ([r, g, b].some((v) => Number.isNaN(v))) return null;\n return { r: clamp(r, 0, 255), g: clamp(g, 0, 255), b: clamp(b, 0, 255) };\n }\n return null;\n}\n","/**\n * The Tailwind CSS default palette lookup table — ported verbatim from\n * matrx-frontend `constants/tailwind-colors.ts` (the data the S14\n * \"tailwind-color-util\" unit does its lookups against). 22 color groups,\n * shades 50–950.\n */\n\nexport interface TailwindColorGroup {\n name: string;\n shades: Record<string, string>;\n}\n\n\nexport const tailwindColors: readonly TailwindColorGroup[] = [\n {\n name: \"Slate\",\n shades: {\n \"50\": \"#f8fafc\",\n \"100\": \"#f1f5f9\",\n \"200\": \"#e2e8f0\",\n \"300\": \"#cbd5e1\",\n \"400\": \"#94a3b8\",\n \"500\": \"#64748b\",\n \"600\": \"#475569\",\n \"700\": \"#334155\",\n \"800\": \"#1e293b\",\n \"900\": \"#0f172a\",\n \"950\": \"#020617\"\n }\n },\n {\n name: \"Gray\",\n shades: {\n \"50\": \"#f9fafb\",\n \"100\": \"#f3f4f6\",\n \"200\": \"#e5e7eb\",\n \"300\": \"#d1d5db\",\n \"400\": \"#9ca3af\",\n \"500\": \"#6b7280\",\n \"600\": \"#4b5563\",\n \"700\": \"#374151\",\n \"800\": \"#1f2937\",\n \"900\": \"#111827\",\n \"950\": \"#030712\"\n }\n },\n {\n name: \"Zinc\",\n shades: {\n \"50\": \"#fafafa\",\n \"100\": \"#f4f4f5\",\n \"200\": \"#e4e4e7\",\n \"300\": \"#d4d4d8\",\n \"400\": \"#a1a1aa\",\n \"500\": \"#71717a\",\n \"600\": \"#52525b\",\n \"700\": \"#3f3f46\",\n \"800\": \"#27272a\",\n \"900\": \"#18181b\",\n \"950\": \"#09090b\"\n }\n },\n {\n name: \"Neutral\",\n shades: {\n \"50\": \"#fafafa\",\n \"100\": \"#f5f5f5\",\n \"200\": \"#e5e5e5\",\n \"300\": \"#d4d4d4\",\n \"400\": \"#a3a3a3\",\n \"500\": \"#737373\",\n \"600\": \"#525252\",\n \"700\": \"#404040\",\n \"800\": \"#262626\",\n \"900\": \"#171717\",\n \"950\": \"#0a0a0a\"\n }\n },\n {\n name: \"Stone\",\n shades: {\n \"50\": \"#fafaf9\",\n \"100\": \"#f5f5f4\",\n \"200\": \"#e7e5e4\",\n \"300\": \"#d6d3d1\",\n \"400\": \"#a8a29e\",\n \"500\": \"#78716c\",\n \"600\": \"#57534e\",\n \"700\": \"#44403c\",\n \"800\": \"#292524\",\n \"900\": \"#1c1917\",\n \"950\": \"#0c0a09\"\n }\n },\n {\n name: \"Red\",\n shades: {\n \"50\": \"#fef2f2\",\n \"100\": \"#fee2e2\",\n \"200\": \"#fecaca\",\n \"300\": \"#fca5a5\",\n \"400\": \"#f87171\",\n \"500\": \"#ef4444\",\n \"600\": \"#dc2626\",\n \"700\": \"#b91c1c\",\n \"800\": \"#991b1b\",\n \"900\": \"#7f1d1d\",\n \"950\": \"#450a0a\"\n }\n },\n {\n name: \"Orange\",\n shades: {\n \"50\": \"#fff7ed\",\n \"100\": \"#ffedd5\",\n \"200\": \"#fed7aa\",\n \"300\": \"#fdba74\",\n \"400\": \"#fb923c\",\n \"500\": \"#f97316\",\n \"600\": \"#ea580c\",\n \"700\": \"#c2410c\",\n \"800\": \"#9a3412\",\n \"900\": \"#7c2d12\",\n \"950\": \"#431407\"\n }\n },\n {\n name: \"Amber\",\n shades: {\n \"50\": \"#fffbeb\",\n \"100\": \"#fef3c7\",\n \"200\": \"#fde68a\",\n \"300\": \"#fcd34d\",\n \"400\": \"#fbbf24\",\n \"500\": \"#f59e0b\",\n \"600\": \"#d97706\",\n \"700\": \"#b45309\",\n \"800\": \"#92400e\",\n \"900\": \"#78350f\",\n \"950\": \"#451a03\"\n }\n },\n {\n name: \"Yellow\",\n shades: {\n \"50\": \"#fefce8\",\n \"100\": \"#fef9c3\",\n \"200\": \"#fef08a\",\n \"300\": \"#fde047\",\n \"400\": \"#facc15\",\n \"500\": \"#eab308\",\n \"600\": \"#ca8a04\",\n \"700\": \"#a16207\",\n \"800\": \"#854d0e\",\n \"900\": \"#713f12\",\n \"950\": \"#422006\"\n }\n },\n {\n name: \"Lime\",\n shades: {\n \"50\": \"#f7fee7\",\n \"100\": \"#ecfccb\",\n \"200\": \"#d9f99d\",\n \"300\": \"#bef264\",\n \"400\": \"#a3e635\",\n \"500\": \"#84cc16\",\n \"600\": \"#65a30d\",\n \"700\": \"#4d7c0f\",\n \"800\": \"#3f6212\",\n \"900\": \"#365314\",\n \"950\": \"#1a2e05\"\n }\n },\n {\n name: \"Green\",\n shades: {\n \"50\": \"#f0fdf4\",\n \"100\": \"#dcfce7\",\n \"200\": \"#bbf7d0\",\n \"300\": \"#86efac\",\n \"400\": \"#4ade80\",\n \"500\": \"#22c55e\",\n \"600\": \"#16a34a\",\n \"700\": \"#15803d\",\n \"800\": \"#166534\",\n \"900\": \"#14532d\",\n \"950\": \"#052e16\"\n }\n },\n {\n name: \"Emerald\",\n shades: {\n \"50\": \"#ecfdf5\",\n \"100\": \"#d1fae5\",\n \"200\": \"#a7f3d0\",\n \"300\": \"#6ee7b7\",\n \"400\": \"#34d399\",\n \"500\": \"#10b981\",\n \"600\": \"#059669\",\n \"700\": \"#047857\",\n \"800\": \"#065f46\",\n \"900\": \"#064e3b\",\n \"950\": \"#022c22\"\n }\n },\n {\n name: \"Teal\",\n shades: {\n \"50\": \"#f0fdfa\",\n \"100\": \"#ccfbf1\",\n \"200\": \"#99f6e4\",\n \"300\": \"#5eead4\",\n \"400\": \"#2dd4bf\",\n \"500\": \"#14b8a6\",\n \"600\": \"#0d9488\",\n \"700\": \"#0f766e\",\n \"800\": \"#115e59\",\n \"900\": \"#134e4a\",\n \"950\": \"#042f2e\"\n }\n },\n {\n name: \"Cyan\",\n shades: {\n \"50\": \"#ecfeff\",\n \"100\": \"#cffafe\",\n \"200\": \"#a5f3fc\",\n \"300\": \"#67e8f9\",\n \"400\": \"#22d3ee\",\n \"500\": \"#06b6d4\",\n \"600\": \"#0891b2\",\n \"700\": \"#0e7490\",\n \"800\": \"#155e75\",\n \"900\": \"#164e63\",\n \"950\": \"#083344\"\n }\n },\n {\n name: \"Sky\",\n shades: {\n \"50\": \"#f0f9ff\",\n \"100\": \"#e0f2fe\",\n \"200\": \"#bae6fd\",\n \"300\": \"#7dd3fc\",\n \"400\": \"#38bdf8\",\n \"500\": \"#0ea5e9\",\n \"600\": \"#0284c7\",\n \"700\": \"#0369a1\",\n \"800\": \"#075985\",\n \"900\": \"#0c4a6e\",\n \"950\": \"#082f49\"\n }\n },\n {\n name: \"Blue\",\n shades: {\n \"50\": \"#eff6ff\",\n \"100\": \"#dbeafe\",\n \"200\": \"#bfdbfe\",\n \"300\": \"#93c5fd\",\n \"400\": \"#60a5fa\",\n \"500\": \"#3b82f6\",\n \"600\": \"#2563eb\",\n \"700\": \"#1d4ed8\",\n \"800\": \"#1e40af\",\n \"900\": \"#1e3a8a\",\n \"950\": \"#172554\"\n }\n },\n {\n name: \"Indigo\",\n shades: {\n \"50\": \"#eef2ff\",\n \"100\": \"#e0e7ff\",\n \"200\": \"#c7d2fe\",\n \"300\": \"#a5b4fc\",\n \"400\": \"#818cf8\",\n \"500\": \"#6366f1\",\n \"600\": \"#4f46e5\",\n \"700\": \"#4338ca\",\n \"800\": \"#3730a3\",\n \"900\": \"#312e81\",\n \"950\": \"#1e1b4b\"\n }\n },\n {\n name: \"Violet\",\n shades: {\n \"50\": \"#f5f3ff\",\n \"100\": \"#ede9fe\",\n \"200\": \"#ddd6fe\",\n \"300\": \"#c4b5fd\",\n \"400\": \"#a78bfa\",\n \"500\": \"#8b5cf6\",\n \"600\": \"#7c3aed\",\n \"700\": \"#6d28d9\",\n \"800\": \"#5b21b6\",\n \"900\": \"#4c1d95\",\n \"950\": \"#2e1065\"\n }\n },\n {\n name: \"Purple\",\n shades: {\n \"50\": \"#faf5ff\",\n \"100\": \"#f3e8ff\",\n \"200\": \"#e9d5ff\",\n \"300\": \"#d8b4fe\",\n \"400\": \"#c084fc\",\n \"500\": \"#a855f7\",\n \"600\": \"#9333ea\",\n \"700\": \"#7e22ce\",\n \"800\": \"#6b21a8\",\n \"900\": \"#581c87\",\n \"950\": \"#3b0764\"\n }\n },\n {\n name: \"Fuchsia\",\n shades: {\n \"50\": \"#fdf4ff\",\n \"100\": \"#fae8ff\",\n \"200\": \"#f5d0fe\",\n \"300\": \"#f0abfc\",\n \"400\": \"#e879f9\",\n \"500\": \"#d946ef\",\n \"600\": \"#c026d3\",\n \"700\": \"#a21caf\",\n \"800\": \"#86198f\",\n \"900\": \"#701a75\",\n \"950\": \"#4a044e\"\n }\n },\n {\n name: \"Pink\",\n shades: {\n \"50\": \"#fdf2f8\",\n \"100\": \"#fce7f3\",\n \"200\": \"#fbcfe8\",\n \"300\": \"#f9a8d4\",\n \"400\": \"#f472b6\",\n \"500\": \"#ec4899\",\n \"600\": \"#db2777\",\n \"700\": \"#be185d\",\n \"800\": \"#9d174d\",\n \"900\": \"#831843\",\n \"950\": \"#500724\"\n }\n },\n {\n name: \"Rose\",\n shades: {\n \"50\": \"#fff1f2\",\n \"100\": \"#ffe4e6\",\n \"200\": \"#fecdd3\",\n \"300\": \"#fda4af\",\n \"400\": \"#fb7185\",\n \"500\": \"#f43f5e\",\n \"600\": \"#e11d48\",\n \"700\": \"#be123c\",\n \"800\": \"#9f1239\",\n \"900\": \"#881337\",\n \"950\": \"#4c0519\"\n }\n }\n] as const;\n","/**\n * The bidirectional Tailwind-token mapping — the heart of the S14 unit,\n * ported from matrx-frontend `utils/color-utils/color-change-util.ts` /\n * `tailwind-color-util.ts`.\n *\n * token → hex: `getColorFromTailwind(\"slate-500\")` → `\"#64748b\"` (plus the\n * fuzzy `formatTailwindColor` for messy user input like `\"skyblue598\"`).\n * color → token: `findNearestTailwindColor` — the verbatim nearest-match\n * scan. The original took a colord instance; the colord coupling is inverted\n * structurally: pass any object with `.delta(hex) => number` (every colord\n * instance with the lab plugin qualifies — no import, no peer), or pass a\n * plain hex / `rgb()` string and the built-in colord-identical CIEDE2000\n * engine (`lab-delta.ts`) computes the distances with zero dependencies.\n */\n\nimport { parseHexOrRgb, rgbDelta } from \"./lab-delta\";\nimport { tailwindColors } from \"./tailwind-colors\";\n\n/**\n * Anything that can measure its perceptual distance to a hex color —\n * structurally satisfied by a colord instance extended with the lab plugin.\n */\nexport interface ColorDelta {\n delta(color: string): number;\n}\n\n/**\n * Function to find the hex value for a given Tailwind color string.\n * @param tailwindColorString - The Tailwind color string (e.g., 'slate-500').\n * @returns The hex value of the corresponding color (e.g., '#64748b'), or an empty string if not found.\n */\nexport function getColorFromTailwind(tailwindColorString: string): string {\n const [colorName, shade] = tailwindColorString.split('-');\n const colorGroup = tailwindColors.find(group => group.name.toLowerCase() === (colorName ?? '').toLowerCase());\n if (colorGroup) {\n const shadeEntry = Object.entries(colorGroup.shades).find(([key]) => key === shade);\n if (shadeEntry) {\n return shadeEntry[1];\n }\n }\n return '';\n}\n\n/**\n * Function to find the nearest Tailwind color for a given input color.\n * @param inputColor - The input color: a hex or `rgb()` string, or any\n * `{ delta(hex) }` measurer (e.g. a colord instance with the lab plugin).\n * @returns The nearest Tailwind color string (e.g., 'slate-500'), or an\n * empty string when a string input cannot be parsed.\n */\nexport function findNearestTailwindColor(inputColor: string | ColorDelta): string {\n let measure: (hexValue: string) => number;\n if (typeof inputColor === \"string\") {\n const rgb = parseHexOrRgb(inputColor);\n if (!rgb) return \"\";\n measure = (hexValue) => {\n const target = parseHexOrRgb(hexValue);\n // The palette is all six-digit hex; unparseable is impossible here.\n return target ? rgbDelta(rgb, target) : Infinity;\n };\n } else {\n measure = (hexValue) => inputColor.delta(hexValue);\n }\n\n let nearestColor = \"\";\n let smallestDistance = Infinity;\n\n tailwindColors.forEach((colorGroup) => {\n Object.entries(colorGroup.shades).forEach(([shade, hexValue]) => {\n const distance = measure(hexValue);\n if (distance < smallestDistance) {\n smallestDistance = distance;\n nearestColor = `${colorGroup.name.toLowerCase()}-${shade}`;\n }\n });\n });\n\n return nearestColor;\n}\n\n/**\n * Utility to format a Tailwind color string.\n * Matches Tailwind color names and returns the closest Tailwind value.\n * Handles cases like \"skyblue600\", \"sky598\", or \"sky-600\".\n * @param tailwindColor - The user-provided Tailwind color string.\n * @returns A properly formatted Tailwind color string.\n */\nexport function formatTailwindColor(tailwindColor: string): string {\n const tailwindColorNames = [\n \"Slate\", \"Gray\", \"Zinc\", \"Neutral\", \"Stone\", \"Red\", \"Orange\", \"Amber\", \"Yellow\", \"Lime\", \"Green\",\n \"Emerald\", \"Teal\", \"Cyan\", \"Blue\", \"Indigo\", \"Violet\",\"Sky\", \"Purple\", \"Fuchsia\", \"Pink\", \"Rose\"\n ];\n\n // Step 1: Try to match the string to extract the numeric part (shade)\n const splitIndex = tailwindColor.search(/\\d/); // Find the index where numbers start\n\n // Case 1: If there is no numeric part, default to shade 500\n if (splitIndex === -1) {\n const colorName = tailwindColorNames.find(color => tailwindColor.toLowerCase().includes(color.toLowerCase()));\n if (colorName) {\n return getColorFromTailwind(`${colorName.toLowerCase()}-500`); // Default to 500 if no shade provided\n }\n }\n\n // Case 2: There is a numeric part, so handle compound names and numeric values\n if (splitIndex > 0) {\n const colorNamePart = tailwindColor.slice(0, splitIndex); // Get color name part\n let shadePart = tailwindColor.slice(splitIndex); // Get shade part\n\n // Step 2: Find all matching color names in the provided color part\n const matchedColors = tailwindColorNames.filter(color => colorNamePart.toLowerCase().includes(color.toLowerCase()));\n\n // Step 3: Sort matches based on appearance in the string (we want the first match in the original string)\n matchedColors.sort((a, b) => colorNamePart.toLowerCase().indexOf(a.toLowerCase()) - colorNamePart.toLowerCase().indexOf(b.toLowerCase()));\n\n // Step 4: Use the first matching color name (if found)\n if (matchedColors.length > 0) {\n const colorName = (matchedColors[0] as string).toLowerCase(); // The first matched color\n\n // Round the shade to the nearest 100 and convert to string\n let shade = Math.round(parseInt(shadePart) / 100) * 100;\n const formattedColor = getColorFromTailwind(`${colorName}-${shade.toString()}`);\n\n // Return the formatted color if found\n if (formattedColor) {\n return formattedColor;\n }\n }\n }\n\n // If no valid format is found, return an empty string\n return '';\n}\n","/**\n * The pure input normalizers — ported verbatim from matrx-frontend\n * `utils/color-utils/color-change-util.ts`. Each takes the messy shape a\n * human pastes (\"61, 135, 204\", \"r:61,g:135,b:204\", \"94% 29% 0% 9%\",\n * \"0x3d87cc\"…) and returns the canonical string for that format, or `''`\n * when the input does not fit — string in, string out, zero dependencies.\n *\n * ONE deliberate divergence from the original: `formatLabString` /\n * `formatLchString` logged every call (input, match, miss) with\n * unconditional `console.log`s — debug spam on a parse path, removed here.\n * Matching/return behavior is unchanged.\n */\n\n/**\n * Utility to format a hex string.\n * Adds the # prefix if missing.\n * @param hex - The user-provided hex color.\n * @returns A properly formatted hex color string.\n */\nexport function formatHex(hex: string): string {\n // Check if the hex is missing the # symbol and add it\n return hex.startsWith('#') ? hex : `#${hex}`;\n}\n\n/**\n * Utility to format an rgb string.\n * Accepts various formats like \"61, 135, 204\" or \"(61, 135, 204)\".\n * @param rgb - The user-provided rgb color.\n * @returns A properly formatted rgb color string.\n */\nexport function formatRgbString(rgb: string): string {\n // Extract numbers from the string\n const rgbValues = rgb.replace(/[^\\d,]/g, '').split(',');\n if (rgbValues.length === 3) {\n return `rgb(${(rgbValues[0] as string).trim()}, ${(rgbValues[1] as string).trim()}, ${(rgbValues[2] as string).trim()})`;\n }\n return ''; // Return an empty string for invalid cases\n}\n\n/**\n * Utility to format an RGB object.\n * Accepts various object-like formats such as '{\"r\":61,\"g\":135,\"b\":204,\"a\":1}', '\"r\":61,\"g\":135,\"b\":204,\"a\":1', or 'r:61,g:135,b:204,a:1'.\n * @param rgbObject - The user-provided RGB object-like string.\n * @returns A properly formatted RGB object.\n */\nexport function formatRgbObject(rgbObject: string): string {\n // Flexible regex to match and capture r, g, b, a values, regardless of quotes, brackets, or missing attributes\n const regex = /[\"']?r[\"']?\\s*[:=]\\s*(\\d+)\\s*[,]\\s*[\"']?g[\"']?\\s*[:=]\\s*(\\d+)\\s*[,]\\s*[\"']?b[\"']?\\s*[:=]\\s*(\\d+)(?:\\s*[,]\\s*[\"']?a[\"']?\\s*[:=]\\s*(\\d+))?/i;\n const match = rgbObject.match(regex);\n\n if (match) {\n const r = match[1], g = match[2], b = match[3], a = match[4] || 1;\n // Return a normalized RGB(A) object string\n return `{\"r\":${r},\"g\":${g},\"b\":${b},\"a\":${a}}`;\n }\n\n // If input is invalid, return an empty string\n return '';\n}\n\n/**\n * Utility to format an HSL object.\n * Accepts various object-like formats such as '{\"h\":199,\"s\":89,\"l\":48,\"a\":1}' or 'h:199,s:89,l:48,a:1'.\n * @param hslObject - The user-provided HSL object-like string.\n * @returns A properly formatted HSL object.\n */\nexport function formatHslObject(hslObject: string): string {\n // Flexible regex to match and capture h, s, l, a values, regardless of quotes, brackets, or missing attributes\n const regex = /[\"']?h[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?s[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?l[\"']?\\s*[:=]\\s*(\\d+)(?:\\s*,\\s*[\"']?a[\"']?\\s*[:=]\\s*(\\d+))?/i;\n const match = hslObject.match(regex);\n if (match) {\n const h = match[1], s = match[2], l = match[3], a = match[4] || 1;\n return `{\"h\":${h},\"s\":${s},\"l\":${l},\"a\":${a}}`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format an HSL string.\n * Accepts formats like \"hsl(199, 89%, 48%)\" or \"199, 89%, 48%\".\n * @param hslString - The user-provided HSL string.\n * @returns A properly formatted HSL string.\n */\nexport function formatHslString(hslString: string): string {\n // Extract numbers and percentage values\n const hslValues = hslString.replace(/[^\\d,%]/g, '').split(/\\s*,\\s*/);\n if (hslValues.length === 3) {\n return `hsl(${hslValues[0]}, ${hslValues[1]}%, ${hslValues[2]}%)`;\n }\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format an HSV percentage string.\n * Accepts formats like \"94% 29% 0%\" or \"(94% 29% 0%)\".\n * @param hsvString - The user-provided HSV percentage string.\n * @returns A properly formatted HSV string.\n */\nexport function formatHsvString(hsvString: string): string {\n // Remove parentheses and other non-relevant characters, then split based on spaces\n const hsvValues = hsvString.replace(/[^\\d%\\s]/g, '').split(/\\s+/).map(value => parseInt(value.replace('%', ''), 10));\n\n // Check if there are exactly 3 values for HSV (Hue, Saturation, Value)\n if (hsvValues.length === 3 && hsvValues.every(val => !isNaN(val))) {\n return `hsv(${hsvValues[0]}, ${hsvValues[1]}%, ${hsvValues[2]}%)`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format a regular CMYK string.\n * Accepts formats like \"94, 29, 0, 9\" or \"(94, 29, 0, 9)\".\n * @param cmykString - The user-provided CMYK string.\n * @returns A properly formatted CMYK string.\n */\nexport function formatRegularCmykString(cmykString: string): string {\n const cmykValues = cmykString.replace(/[^\\d,]/g, '').split(/\\s*,\\s*/);\n\n if (cmykValues.length === 4 && cmykValues.every(val => !isNaN(Number(val)))) {\n return `cmyk(${cmykValues[0]}, ${cmykValues[1]}, ${cmykValues[2]}, ${cmykValues[3]})`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format a CMYK object.\n * Accepts various object-like formats such as '{\"c\":94,\"m\":29,\"y\":0,\"k\":9,\"a\":1}' or 'c:94,m:29,y:0,k:9,a:1'.\n * @param cmykObject - The user-provided CMYK object-like string.\n * @returns A properly formatted CMYK object.\n */\nexport function formatCmykObject(cmykObject: string): string {\n // Flexible regex to match and capture c, m, y, k, a values, regardless of quotes or brackets\n const regex = /[\"']?c[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?m[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?y[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?k[\"']?\\s*[:=]\\s*(\\d+)(?:\\s*,\\s*[\"']?a[\"']?\\s*[:=]\\s*(\\d+))?/i;\n const match = cmykObject.match(regex);\n\n if (match) {\n const c = match[1], m = match[2], y = match[3], k = match[4], a = match[5] || 1;\n return `{\"c\":${c},\"m\":${m},\"y\":${y},\"k\":${k},\"a\":${a}}`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format a CMYK percentage string.\n * Accepts formats like \"94% 29% 0% 9%\" or \"(94% 29% 0% 9%)\".\n * @param cmykString - The user-provided CMYK percentage string.\n * @returns A properly formatted CMYK string.\n */\nexport function formatCmykString(cmykString: string): string {\n // Remove any parentheses or extra characters, then split based on spaces\n const cmykValues = cmykString.replace(/[^\\d%\\s]/g, '').split(/\\s+/).map(value => parseInt(value.replace('%', ''), 10));\n\n if (cmykValues.length === 4 && cmykValues.every(val => !isNaN(val))) {\n return `device-cmyk(${cmykValues[0]}% ${cmykValues[1]}% ${cmykValues[2]}% ${cmykValues[3]}%)`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to detect device-cmyk color strings (\"device-cmyk(94% 29% 0% 9%)\").\n * @param cmykString - The user-provided CMYK string.\n * @returns True when the string is a well-formed device-cmyk expression.\n */\nexport function isDeviceCmyk(cmykString: string): boolean {\n const regex = /device-cmyk\\(\\s*\\d+%\\s+\\d+%\\s+\\d+%\\s+\\d+%\\s*\\)/;\n return regex.test(cmykString);\n}\n\n/**\n * Utility to format an HWB string.\n * Accepts formats like \"hwb(199 24% 20%)\" or \"hwb(199deg 24% 20%)\".\n * @param hwbString - The user-provided HWB string.\n * @returns A properly formatted HWB string.\n */\nexport function formatHwbString(hwbString: string): string {\n // Extract numbers and percentage values from the HWB string\n const hwbValues = hwbString.replace(/[^\\d,%\\s]/g, '').split(/\\s+/);\n if (hwbValues.length === 3) {\n return `hwb(${hwbValues[0]}, ${hwbValues[1]}%, ${hwbValues[2]}%)`;\n }\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format a Lab string.\n * Accepts formats like \"lab(55.715 -14.02 -32.329)\" or \"55.715 -14.02 -32.329\".\n * @param labString - The user-provided Lab string.\n * @returns A properly formatted Lab string.\n */\nexport function formatLabString(labString: string): string {\n // Try matching with or without the \"lab(\" prefix\n const match = labString.match(/(?:lab\\()?\\s*(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s*\\)?/i);\n\n if (match) {\n const [, l, a, b] = match;\n return `lab(${l} ${a} ${b})`;\n }\n\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format an LCH string.\n * Accepts formats like \"lch(55.715 35.17 246.6)\" or \"55.715 35.17 246.6\".\n * @param lchString - The user-provided LCH string.\n * @returns A properly formatted LCH string.\n */\nexport function formatLchString(lchString: string): string {\n // Try matching with or without the \"lch(\" prefix\n const match = lchString.match(/(?:lch\\()?\\s*(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s*\\)?/i);\n\n if (match) {\n const [, l, c, h] = match;\n return `lch(${l} ${c} ${h})`;\n }\n\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format a hex string with 0x prefix.\n * Converts \"0x3d87cc\" to \"#3d87cc\".\n * @param hex - The user-provided hex color with 0x prefix.\n * @returns A properly formatted hex color string.\n */\nexport function formatHexWith0x(hex: string): string {\n if (hex.startsWith('0x')) {\n return `#${hex.slice(2)}`;\n }\n return ''; // Return empty string for invalid cases\n}\n","/**\n * The \"accept anything a human pastes\" waterfall — ported from matrx-frontend\n * `color-change-util.ts` `normalizeColorInput`, with the colord coupling\n * inverted: the original gated several tiers on `colord(input).isValid()`;\n * here the host injects that validity check (`createColorNormalizer({\n * isValid })` — pass `(c) => colord(c).isValid()` or any equivalent). The\n * tier ORDER, the tiers that skip validation, and the returned\n * `{ value, type }` shapes are verbatim.\n *\n * Deliberate divergence (same class as formats.ts): the original logged every\n * tier hit/miss with unconditional `console.log`s — removed.\n */\n\nimport {\n formatCmykObject,\n formatCmykString,\n formatHex,\n formatHexWith0x,\n formatHslObject,\n formatHslString,\n formatHsvString,\n formatHwbString,\n formatLabString,\n formatLchString,\n formatRegularCmykString,\n formatRgbObject,\n formatRgbString,\n isDeviceCmyk,\n} from \"./formats\";\nimport { formatTailwindColor } from \"./tailwind\";\n\nexport interface NormalizedColor {\n value: string;\n type: string;\n}\n\nexport interface ColorNormalizerOptions {\n /**\n * \"Can this string be parsed as a color?\" — the host's color engine\n * (e.g. `(c) => colord(c).isValid()`).\n */\n isValid: (color: string) => boolean;\n}\n\n/**\n * Builds `normalizeColorInput`: tries the format conversions in the original\n * fixed order until one produces a valid (or structurally well-formed) color,\n * returning `{ value, type }`, or `null` when nothing fits.\n */\nexport function createColorNormalizer({ isValid }: ColorNormalizerOptions) {\n return function normalizeColorInput(colorInput: string): NormalizedColor | null {\n // Try standard validation first\n if (isValid(colorInput)) {\n return { value: colorInput, type: 'standard' };\n }\n\n // Check for 'device-cmyk' manually\n if (isDeviceCmyk(colorInput)) {\n return { value: colorInput, type: 'device-cmyk' };\n }\n\n // Try hex conversion\n const hex = formatHex(colorInput);\n if (isValid(hex)) {\n return { value: hex, type: 'hex' };\n }\n\n // Try RGB string conversion\n const rgbString = formatRgbString(colorInput);\n if (isValid(rgbString)) {\n return { value: rgbString, type: 'rgb' };\n }\n\n // Try RGB object conversion (skip isValid for this)\n const rgbObject = formatRgbObject(colorInput);\n if (rgbObject !== '') {\n return { value: rgbObject, type: 'rgb-object' };\n }\n\n // Try HSL object conversion (skip isValid for this)\n const hslObject = formatHslObject(colorInput);\n if (hslObject !== '') {\n return { value: hslObject, type: 'hsl-object' };\n }\n\n // Try HSL string conversion\n const hslString = formatHslString(colorInput);\n if (isValid(hslString)) {\n return { value: hslString, type: 'hsl' };\n }\n\n // Try HSV string conversion\n const hsvString = formatHsvString(colorInput);\n if (isValid(hsvString)) {\n return { value: hsvString, type: 'hsv' };\n }\n\n // Try Tailwind color conversion\n const tailwindColor = formatTailwindColor(colorInput);\n if (tailwindColor !== '') {\n return { value: tailwindColor, type: 'tailwind' };\n }\n\n // Try regular CMYK string conversion (skip isValid for this)\n const regularCmykString = formatRegularCmykString(colorInput);\n if (regularCmykString !== '') {\n return { value: regularCmykString, type: 'cmyk' };\n }\n\n // Try CMYK object conversion (skip isValid for this)\n const cmykObject = formatCmykObject(colorInput);\n if (cmykObject !== '') {\n return { value: cmykObject, type: 'cmyk-object' };\n }\n\n // Try CMYK percentage string conversion (for device-cmyk)\n const cmykString = formatCmykString(colorInput);\n if (isValid(cmykString)) {\n return { value: cmykString, type: 'cmyk-percentage' };\n }\n\n // Try HWB string conversion\n const hwbString = formatHwbString(colorInput);\n if (isValid(hwbString)) {\n return { value: hwbString, type: 'hwb' };\n }\n\n // Try Lab string conversion (skip isValid for this)\n const labString = formatLabString(colorInput);\n if (labString !== '') {\n return { value: labString, type: 'lab' };\n }\n\n // Try LCH string conversion (skip isValid for this)\n const lchString = formatLchString(colorInput);\n if (lchString !== '') {\n return { value: lchString, type: 'lch' };\n }\n\n // Try hex with 0x conversion\n const hexWith0x = formatHexWith0x(colorInput);\n if (isValid(hexWith0x)) {\n return { value: hexWith0x, type: 'hex-0x' };\n }\n\n // If all else fails, return null\n return null;\n };\n}\n","/**\n * @ai-matrx/kit/qr — THE QR-code decoder (client-side, in memory). Ported\n * verbatim from matrx-frontend `lib/qr/decode.ts`.\n *\n * One primitive, three inputs (a File/Blob, an `ImageData` frame, a\n * `<video>`/`<canvas>` element), one answer: the text the QR encodes, or\n * `null` when no code is present. Nothing here uploads, stores, or persists\n * anything — the bytes live in a canvas for the length of one call.\n *\n * Engine order:\n * 1. `BarcodeDetector` — native, fast, handles rotation and poor contrast.\n * 2. `jsqr` — pure-JS fallback (lazily imported, so it only enters the\n * bundle of a surface that actually decodes), for Safari/Firefox where\n * the native detector does not exist.\n *\n * Runtime dependency of this subpath (and only when the fallback fires):\n * `jsqr` — a browser without `BarcodeDetector` decoding a pasted screenshot\n * IS the capability, not an optional extra; without the fallback the unit\n * silently does nothing on Safari/Firefox.\n *\n * Browser capability: decoding needs a DOM (`document`, canvas 2D,\n * `createImageBitmap`) at call time; importing is inert and SSR-safe, and\n * `hasNativeQrDetector()` is safe to call anywhere (it only probes\n * `globalThis`).\n *\n * 🚨 Reach for THIS, never a second decoder. If a surface needs a new input\n * shape, add an adapter here.\n */\n\n/** Longest edge we rasterise to. Big enough for a phone screenshot of a QR,\n * small enough that a 48MP photo cannot stall the main thread. */\nconst MAX_EDGE = 1600;\n\ntype NativeBarcodeDetector = {\n detect: (source: CanvasImageSource | ImageBitmap | Blob) => Promise<{ rawValue: string }[]>;\n};\n\ntype BarcodeDetectorCtor = {\n new (options?: { formats?: string[] }): NativeBarcodeDetector;\n getSupportedFormats?: () => Promise<string[]>;\n};\n\nfunction nativeDetector(): BarcodeDetectorCtor | null {\n const ctor = (globalThis as { BarcodeDetector?: BarcodeDetectorCtor })\n .BarcodeDetector;\n return typeof ctor === \"function\" ? ctor : null;\n}\n\n/** True when the browser can decode without downloading the JS fallback. */\nexport function hasNativeQrDetector(): boolean {\n return nativeDetector() !== null;\n}\n\nasync function decodeNative(\n source: CanvasImageSource | ImageBitmap | Blob,\n): Promise<string | null> {\n const Ctor = nativeDetector();\n if (!Ctor) return null;\n try {\n const detector = new Ctor({ formats: [\"qr_code\"] });\n const results = await detector.detect(source);\n const value = results.find((r) => r.rawValue)?.rawValue;\n return value ? value : null;\n } catch {\n // A detector that throws (unsupported format, decode error) is a miss,\n // never a crash — the jsqr fallback still gets its turn.\n return null;\n }\n}\n\nasync function decodeWithJsQr(frame: ImageData): Promise<string | null> {\n const { default: jsQR } = await import(\"jsqr\");\n const both = jsQR(frame.data, frame.width, frame.height, {\n inversionAttempts: \"attemptBoth\",\n });\n return both?.data ? both.data : null;\n}\n\n/** Draw any image source onto a canvas, capped at {@link MAX_EDGE}. */\nfunction toImageData(\n source: CanvasImageSource,\n width: number,\n height: number,\n): ImageData | null {\n if (!width || !height) return null;\n const scale = Math.min(1, MAX_EDGE / Math.max(width, height));\n const w = Math.max(1, Math.round(width * scale));\n const h = Math.max(1, Math.round(height * scale));\n const canvas = document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return null;\n ctx.drawImage(source, 0, 0, w, h);\n return ctx.getImageData(0, 0, w, h);\n}\n\n/** Decode a QR code out of an already-rasterised frame. */\nexport async function decodeQrFromImageData(\n frame: ImageData,\n): Promise<string | null> {\n return (await decodeWithJsQr(frame)) ?? null;\n}\n\n/**\n * Decode a QR code out of a live `<video>` (a camera preview) or a `<canvas>`.\n * Returns `null` when the current frame holds no code — call it on a tick.\n */\nexport async function decodeQrFromElement(\n element: HTMLVideoElement | HTMLCanvasElement,\n): Promise<string | null> {\n const width =\n element instanceof HTMLVideoElement ? element.videoWidth : element.width;\n const height =\n element instanceof HTMLVideoElement ? element.videoHeight : element.height;\n if (!width || !height) return null;\n\n const native = await decodeNative(element);\n if (native) return native;\n\n const frame = toImageData(element, width, height);\n return frame ? decodeQrFromImageData(frame) : null;\n}\n\n/**\n * Decode a QR code out of an image File/Blob — a pasted screenshot, a dropped\n * PNG, a photo from the OS camera sheet.\n *\n * Resolves `null` when the image holds no QR code. Throws only when the file\n * is not decodable as an image at all.\n */\nexport async function decodeQrFromImageFile(\n file: Blob,\n): Promise<string | null> {\n // The native detector accepts a Blob directly on Chromium — cheapest path.\n const direct = await decodeNative(file);\n if (direct) return direct;\n\n let bitmap: ImageBitmap | null = null;\n try {\n bitmap = await createImageBitmap(file);\n } catch {\n throw new Error(\"That file could not be read as an image.\");\n }\n try {\n const viaBitmap = await decodeNative(bitmap);\n if (viaBitmap) return viaBitmap;\n const frame = toImageData(bitmap, bitmap.width, bitmap.height);\n return frame ? decodeQrFromImageData(frame) : null;\n } finally {\n bitmap.close();\n }\n}\n"],"mappings":"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","names":["flush","import_react","import_react","import_react","React","React","import_jsx_runtime","import_jsx_runtime","STATE_SLOT","JSON5","entries","body","joined","STATE_SLOT","getState","import_react","import_react","version","version","version","STATE_SLOT","getState"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/autosave.ts","../src/latest-request.ts","../src/clipboard.ts","../src/search-scoring.ts","../src/concurrency.ts","../src/text-case.ts","../src/drafts/use-durable-draft.ts","../src/drafts/local-drafts.ts","../src/confirm/opener.ts","../src/confirm/host.tsx","../src/confirm/cn.ts","../src/confirm/alert-dialog.tsx","../src/react-tree.ts","../src/confirm/confirm-dialog.tsx","../src/toast.ts","../src/invalidation.ts","../src/delimiter-guard.ts","../src/json-format/detect.ts","../src/json-format/json-value.ts","../src/json-format/format.ts","../src/idle-scheduler/scheduler.ts","../src/idle-scheduler/hooks.ts","../src/url-state.ts","../src/idb-store/store-manager.ts","../src/idb-store/store-interface.ts","../src/idb-store/feature-store.ts","../src/idb-store/singleton.ts","../src/color-util/lab-delta.ts","../src/color-util/tailwind-colors.ts","../src/color-util/tailwind.ts","../src/color-util/formats.ts","../src/color-util/normalize.ts","../src/qr.ts"],"sourcesContent":["/**\n * @ai-matrx/kit — the always-include package.\n *\n * One package gives you the little primitives every Matrx application speaks,\n * one capability per subpath (`/autosave`, `/latest-request`, `/clipboard`,\n * `/confirm`, `/toast`, `/invalidation`, `/delimiter-guard`, `/json-format`,\n * `/idle-scheduler`, `/url-state`, `/idb-store`, `/color-util`, `/react-tree`,\n * `/qr`, more to come: copy-for-ai). The root re-exports everything for\n * convenience; production consumers import the subpath so tree-shaking keeps\n * them lean.\n *\n * React is the only required peer. The `/confirm` subpath additionally\n * bundles `@radix-ui/react-alert-dialog` + `tailwind-merge` (its product IS\n * the dialog), `/json-format` depends on `json5` (tolerant parsing IS the\n * feature), `/idb-store` depends on `idb` (the typed IndexedDB wrapper IS\n * the engine), and `/qr` lazily loads `jsqr` when the native detector is\n * absent (the fallback IS the capability); every other subpath is\n * dependency-free. Importing any entry point performs no network, storage,\n * or global-state work.\n */\nexport * from \"./autosave\";\nexport * from \"./latest-request\";\nexport * from \"./clipboard\";\nexport * from \"./search-scoring\";\nexport * from \"./concurrency\";\nexport * from \"./text-case\";\nexport * from \"./drafts\";\nexport * from \"./confirm\";\nexport * from \"./toast\";\nexport * from \"./invalidation\";\nexport * from \"./delimiter-guard\";\nexport * from \"./json-format\";\nexport * from \"./idle-scheduler\";\nexport * from \"./url-state\";\nexport * from \"./idb-store\";\nexport * from \"./color-util\";\nexport * from \"./react-tree\";\nexport * from \"./qr\";\n\n// NOT re-exported here, on purpose: `/short-link`, `/confirm-opener`,\n// `/format`, `/html-escape` and `/uuid` are pure, unstamped modules that\n// Server Components, API routes and Node scripts import directly. This barrel\n// carries the \"use client\" banner, so pulling them through it would turn their\n// exports into client references — a runtime break, not a cosmetic one.\n// Import them by subpath: `@ai-matrx/kit/format`, etc.\n","// A small, generic autosave primitive: debounce a payload, persist it through a\n// caller-supplied async save, and expose a status a UI can show (\"Saving…\" /\n// \"Saved\" / \"Unsaved changes\" / error). Entity-agnostic — the caller owns WHAT\n// to save (the save fn) and WHAT the payload is; this owns the debounce, the\n// in-flight coalescing, the status, and the flush-on-unmount so no keystroke is\n// ever lost. (Notes have their own coupled version; this is the reusable one.)\n// Never throws: the save fn returns `{ error }` (supabase-service style) and a\n// non-null error flips status to \"error\" and re-queues, so a blocked write is\n// loud, not silent.\n// React Compiler is on: no manual useMemo / useCallback — plain closures.\n\n\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type AutosaveStatus = \"idle\" | \"unsaved\" | \"saving\" | \"saved\" | \"error\";\n\nexport interface UseAutosaveResult<T> {\n status: AutosaveStatus;\n lastSavedAt: Date | null;\n /** Queue a payload and (re)start the debounce. */\n schedule: (value: T) => void;\n /** Cancel the debounce and save the pending payload immediately. */\n flush: () => void;\n}\n\nexport function useAutosave<T>(opts: {\n save: (value: T) => Promise<{ error: string | null }>;\n debounceMs?: number;\n}): UseAutosaveResult<T> {\n const { save, debounceMs = 900 } = opts;\n const [status, setStatus] = useState<AutosaveStatus>(\"idle\");\n const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null);\n\n const pendingRef = useRef<{ value: T } | null>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const savingRef = useRef(false);\n // Keep the latest save fn without threading it through closures (updated in an\n // effect, never during render).\n const saveRef = useRef(save);\n useEffect(() => {\n saveRef.current = save;\n });\n\n async function saveNow(): Promise<void> {\n if (savingRef.current) return; // a later debounce flush picks up new edits\n const pending = pendingRef.current;\n if (!pending) return;\n pendingRef.current = null;\n savingRef.current = true;\n setStatus(\"saving\");\n let failed = false;\n try {\n const res = await saveRef.current(pending.value);\n if (res.error) {\n // Re-queue so the NEXT schedule/flush retries; surface loudly.\n failed = true;\n pendingRef.current = pendingRef.current ?? pending;\n setStatus(\"error\");\n } else {\n setLastSavedAt(new Date());\n setStatus(pendingRef.current ? \"unsaved\" : \"saved\");\n }\n } catch {\n failed = true;\n pendingRef.current = pendingRef.current ?? pending;\n setStatus(\"error\");\n } finally {\n savingRef.current = false;\n // If edits arrived mid-save, drain them promptly. NEVER drain after a\n // failure: the re-queued payload waits for the next schedule/flush —\n // draining it here is an unbounded immediate-retry loop against a\n // persistently failing save. (The matrx-frontend original has exactly\n // that loop; it dies with the original at the adoption swap.)\n if (pendingRef.current && !failed) void saveNow();\n }\n }\n\n function schedule(value: T): void {\n pendingRef.current = { value };\n setStatus(\"unsaved\");\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => void saveNow(), debounceMs);\n }\n\n function flush(): void {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n void saveNow();\n }\n\n // Flush any pending payload on unmount so an in-progress edit is never lost.\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n const pending = pendingRef.current;\n if (pending && !savingRef.current) {\n pendingRef.current = null;\n void saveRef.current(pending.value);\n }\n };\n }, []);\n\n return { status, lastSavedAt, schedule, flush };\n}\n","\"use client\";\n\n/**\n * useLatestRequest — makes a superseded async response impossible to apply.\n *\n * THE BUG THIS KILLS: a surface refetches whenever some input changes (a\n * `?app=` scope, a search box, a selected id). Two fetches are then in flight\n * at once, and **responses do not arrive in the order they were sent.** The\n * older one lands last, calls `setRows`, and wins — so the table shows app A's\n * runs while the banner, the URL, and every label already say app B.\n *\n * That is not stale data, which announces itself. It is the WRONG RECORD under\n * a CONFIDENT label — the same failure `StaleDataNotice` exists to prevent on\n * the error path, arriving through the success path instead. Clearing rows when\n * a fetch FAILS (which this repo already does) closes only half the hole: a\n * fetch that succeeds late is just as capable of mislabeling the screen, and\n * nothing about it looks wrong.\n *\n * `AbortController` is the other half of the answer and a good thing to add on\n * top — but it is not a substitute. An abort races the response; the request may\n * already have resolved, and a non-`fetch` data source (a Supabase client call,\n * an RPC wrapper) often has no signal to give. This guard is source-agnostic and\n * final: it decides at APPLY time, which is the only moment that matters.\n *\n * ```ts\n * const beginRequest = useLatestRequest();\n *\n * const load = useCallback(async () => {\n * const isCurrent = beginRequest(); // claim this attempt\n * setLoading(true);\n * try {\n * const data = await fetchScopedRows(appId);\n * if (!isCurrent()) return; // a newer load already started\n * setRows(data);\n * } catch (err) {\n * if (!isCurrent()) return; // don't let an old failure blank new rows\n * setRows([]);\n * setLoadFailed(true);\n * } finally {\n * if (isCurrent()) setLoading(false);\n * }\n * }, [appId, beginRequest]);\n * ```\n *\n * **Guard the catch and the finally too, not just the success path.** A stale\n * REJECTION is the mirror-image bug: it wipes the rows the current request just\n * loaded and raises a \"couldn't load\" notice about a request nobody is waiting\n * for. And an early `setLoading(false)` from a superseded attempt reports the\n * surface as settled while the real one is still in flight.\n *\n * `begin()` returns the predicate rather than exposing a counter, so there is no\n * sequence number to compare wrongly and no way to ask \"is my request current?\"\n * without first having declared one.\n *\n * Three hand-rolled copies of this exact `requestSeq`/`reqIdRef` pattern predate\n * it — `useServerAgentSearch`, `useRagSearch`, `useContextPreview`. They are\n * correct; they are just the evidence that this is a class, not an incident. New\n * code uses this hook, and those three collapse onto it when next touched.\n */\n\nimport { useCallback, useRef } from \"react\";\n\n/**\n * Marks a new attempt as the current one and returns a predicate reporting\n * whether it still is. Call it once at the top of the async function, then\n * check the predicate before EVERY state write that follows an `await`.\n */\nexport type BeginRequest = () => () => boolean;\n\n/**\n * 🚨 RETURNS THE FUNCTION ITSELF, NOT AN OBJECT WRAPPING IT — deliberately, and\n * this is the whole reason the signature looks like that.\n *\n * The first version returned `{ begin }`. That object literal is a NEW\n * reference on every render, and the entire point of this hook is to be named\n * in the dependency array of the very `useCallback` that performs the fetch. An\n * unstable dependency there makes `load` unstable, which makes the\n * `useEffect(…, [load])` that calls it re-run on every render — an unbroken\n * refetch loop against the database with no user input at all. A guard against\n * a fetch race that instead causes infinite fetches is worse than the bug it\n * was written to fix, and it is a High-severity defect that shipped.\n *\n * Returning the `useCallback`-stable function directly removes the hazard by\n * construction: there is no object whose identity a caller could depend on. If\n * this ever needs to return more than one thing, it must be wrapped in\n * `useMemo` — never a bare literal. (Do not lean on the React Compiler to\n * memoize it for you: a primitive has to be correct on its own terms, and\n * correctness here is the difference between one fetch and unbounded ones.)\n */\nexport function useLatestRequest(): BeginRequest {\n const seqRef = useRef(0);\n\n return useCallback(() => {\n const mySeq = ++seqRef.current;\n return () => mySeq === seqRef.current;\n }, []);\n}\n","\"use client\";\n\n/**\n * useClipboard — copy/paste text, links, and images with the browser quirks\n * already solved: image copy re-encodes through a canvas to PNG (the only type\n * `ClipboardItem` reliably accepts), paste-image feature-detects\n * `clipboard.read` (absent in Safari < 16.4) instead of throwing, and link\n * copy can strip query params.\n *\n * The notifier is INJECTED — the package does not know your toast system. The\n * host passes `notify` once (usually wrapping its toast); without it, successes\n * are silent and failures still land in `error` + the console, so nothing is\n * ever swallowed.\n */\nimport { useCallback, useState } from \"react\";\n\nexport type ClipboardNotifyKind = \"success\" | \"error\";\n\nexport interface UseClipboardOptions {\n /** Surface outcomes to the user — wrap your toast here. */\n notify?: (message: string, kind: ClipboardNotifyKind) => void;\n}\n\nexport interface UseClipboardResult {\n copyText: (text: string, successMessage?: string) => Promise<void>;\n copyImage: (imageSrc: string, successMessage?: string) => Promise<void>;\n copyLink: (\n link: string,\n stripParams?: boolean,\n successMessage?: string,\n ) => Promise<void>;\n pasteText: () => Promise<string>;\n pasteImage: () => Promise<File | null>;\n lastCopied: string | null;\n error: Error | null;\n}\n\nfunction toError(err: unknown, fallback: string): Error {\n if (err instanceof Error) return err;\n if (typeof err === \"string\" && err) return new Error(err);\n return new Error(fallback);\n}\n\nexport function useClipboard(\n options: UseClipboardOptions = {},\n): UseClipboardResult {\n const { notify } = options;\n const [lastCopied, setLastCopied] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n const handleSuccess = (type: string, successMessage: string | undefined) => {\n setLastCopied(type);\n setError(null);\n notify?.(\n successMessage ??\n `${type.charAt(0).toUpperCase() + type.slice(1)} copied to clipboard!`,\n \"success\",\n );\n };\n\n const handleError = (err: unknown, type: string) => {\n const message = `Failed to copy ${type}`;\n setError(toError(err, message));\n console.error(message, err);\n notify?.(message, \"error\");\n };\n\n const copyText = useCallback(\n async (text: string, successMessage?: string) => {\n try {\n await navigator.clipboard.writeText(text);\n handleSuccess(\"text\", successMessage);\n } catch (err) {\n handleError(err, \"text\");\n }\n },\n [notify],\n );\n\n const copyImage = useCallback(\n async (imageSrc: string, successMessage?: string) => {\n try {\n const response = await fetch(imageSrc);\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n const blob = await response.blob();\n\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n\n return new Promise<void>((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0);\n\n canvas.toBlob((pngBlob) => {\n if (pngBlob) {\n const item = new ClipboardItem({ \"image/png\": pngBlob });\n navigator.clipboard.write([item]).then(\n () => {\n handleSuccess(\"image\", successMessage);\n resolve();\n },\n (err) =>\n reject(\n toError(err, \"Failed to write image to clipboard\"),\n ),\n );\n } else {\n reject(new Error(\"Failed to convert image to PNG\"));\n }\n }, \"image/png\");\n };\n img.onerror = () => reject(new Error(\"Failed to load image\"));\n img.src = URL.createObjectURL(blob);\n });\n } catch (err) {\n handleError(err, \"image\");\n }\n },\n [notify],\n );\n\n const copyLink = useCallback(\n async (link: string, stripParams = false, successMessage?: string) => {\n try {\n let value = link;\n if (stripParams) {\n const url = new URL(link);\n value = `${url.origin}${url.pathname}`;\n }\n await navigator.clipboard.writeText(value);\n handleSuccess(\"link\", successMessage);\n } catch (err) {\n handleError(err, \"link\");\n }\n },\n [notify],\n );\n\n const pasteText = useCallback(async () => {\n try {\n const text = await navigator.clipboard.readText();\n setError(null);\n return text;\n } catch (err) {\n setError(toError(err, \"Failed to paste text\"));\n console.error(\"Failed to paste text: \", err);\n return \"\";\n }\n }, []);\n\n const pasteImage = useCallback(async () => {\n try {\n // clipboard.read() is not available in Safari < 16.4\n if (!navigator.clipboard?.read) return null;\n const items = await navigator.clipboard.read();\n for (const item of items) {\n const imageType = item.types.find((type) => type.startsWith(\"image/\"));\n if (imageType) {\n const blob = await item.getType(imageType);\n return new File([blob], \"pasted-image.png\", { type: imageType });\n }\n }\n return null;\n } catch (err) {\n setError(toError(err, \"Failed to paste image\"));\n console.error(\"Failed to paste image: \", err);\n return null;\n }\n }, []);\n\n return { copyText, copyImage, copyLink, pasteText, pasteImage, lastCopied, error };\n}\n","/**\n * Relevance-weighted search scoring.\n *\n * Use instead of the naive `name.includes(q) || description.includes(q)` pattern\n * so that title/name matches rank above description matches, and exact/prefix\n * matches rank above partial ones.\n *\n * ── Quick start ────────────────────────────────────────────────────────────────\n * const filtered = filterAndSortBySearch(items, query, [\n * { get: (t) => t.name, weight: \"title\" },\n * { get: (t) => t.description, weight: \"body\" },\n * { get: (t) => t.tags, weight: \"tag\" },\n * ]);\n *\n * ── Weight tiers (higher = more important field) ──────────────────────────────\n * title — the primary identifier (name, label, subject)\n * subtitle — secondary identifier (vendor, author, category name)\n * body — long-form descriptive text (description, summary)\n * tag — tag/category labels\n * meta — weak metadata (modelId, type)\n * id — raw identifiers (uuid, slug) — only useful for pasted-id lookups\n *\n * Within each field, an EXACT match > STARTS-WITH match > INCLUDES match.\n * Fields declared first are a slight tiebreaker (via field-index bonus).\n *\n * ── Automatic id matching ─────────────────────────────────────────────────────\n * Every item with a string `id` is ALSO matched against the query at the `id`\n * weight tier, automatically — you do NOT need to declare an id field. This\n * means a user can paste a full or partial UUID into ANY search box wired to\n * this helper and find the record. It kicks in from {@link MIN_AUTO_ID_QUERY_LEN}\n * characters up (so short queries don't match random hex). Declare an explicit\n * `{ weight: \"id\" }` field only if you want id matching at any length / on a\n * non-`id` property; doing so opts that callsite out of the automatic pass.\n */\n\nexport type SearchFieldWeight =\n | \"title\"\n | \"subtitle\"\n | \"body\"\n | \"tag\"\n | \"meta\"\n | \"id\"\n | \"custom\";\n\nexport interface SearchFieldConfig<T> {\n /**\n * Extracts the value(s) from the item. Return a string, an array of strings,\n * or null/undefined. Arrays score based on the best-matching element.\n */\n get: (item: T) => string | string[] | null | undefined;\n /** Field importance tier. Defaults to \"body\". */\n weight?: SearchFieldWeight;\n /** Optional override for custom tiers. Ignored when `weight` is preset. */\n exact?: number;\n startsWith?: number;\n includes?: number;\n}\n\nconst WEIGHT_TABLE: Record<\n Exclude<SearchFieldWeight, \"custom\">,\n { exact: number; startsWith: number; includes: number }\n> = {\n title: { exact: 10000, startsWith: 5000, includes: 2000 },\n subtitle: { exact: 2000, startsWith: 1000, includes: 500 },\n body: { exact: 1000, startsWith: 600, includes: 400 },\n tag: { exact: 500, startsWith: 400, includes: 300 },\n meta: { exact: 200, startsWith: 150, includes: 100 },\n id: { exact: 100, startsWith: 75, includes: 50 },\n};\n\n/**\n * Below this query length we do NOT auto-match the row `id`. A 1–2 char query\n * is almost always a substring of *some* hex chars in *every* UUID, so matching\n * id at that length would flood results with the whole table. From 3 chars up a\n * partial-UUID paste is selective enough to be a real lookup.\n */\nconst MIN_AUTO_ID_QUERY_LEN = 3;\n\n/** Pull a non-empty string `id` off an item, or null if it has none. */\nfunction getStringId(item: unknown): string | null {\n if (item && typeof item === \"object\" && \"id\" in item) {\n const id = (item as { id?: unknown }).id;\n if (typeof id === \"string\" && id.length > 0) return id;\n }\n return null;\n}\n\nfunction resolveTiers(field: SearchFieldConfig<unknown>) {\n if (field.weight === \"custom\" || field.exact != null) {\n return {\n exact: field.exact ?? 0,\n startsWith: field.startsWith ?? 0,\n includes: field.includes ?? 0,\n };\n }\n return WEIGHT_TABLE[field.weight ?? \"body\"];\n}\n\nfunction scoreValue(\n value: string,\n q: string,\n tiers: { exact: number; startsWith: number; includes: number },\n): number {\n if (!value) return 0;\n const v = value.toLowerCase();\n if (v === q) return tiers.exact;\n if (v.startsWith(q)) return tiers.startsWith;\n if (v.includes(q)) return tiers.includes;\n return 0;\n}\n\n/**\n * Compute a weighted relevance score for `item` against `query`.\n * Returns 0 if there is no match — callers can treat `> 0` as a match predicate.\n *\n * Within each field, multiple values (e.g. tags) contribute the BEST match,\n * not the sum, so an item with many tags doesn't unfairly outrank one with a\n * single exact title match.\n */\nexport function computeSearchScore<T>(\n item: T,\n query: string,\n fields: SearchFieldConfig<T>[],\n): number {\n const trimmed = query.trim();\n if (!trimmed) return 0;\n const q = trimmed.toLowerCase();\n\n let total = 0;\n fields.forEach((field, idx) => {\n const raw = field.get(item);\n if (raw == null) return;\n const tiers = resolveTiers(field as SearchFieldConfig<unknown>);\n\n let best = 0;\n if (Array.isArray(raw)) {\n for (const v of raw) {\n if (typeof v !== \"string\") continue;\n const s = scoreValue(v, q, tiers);\n if (s > best) best = s;\n }\n } else if (typeof raw === \"string\") {\n best = scoreValue(raw, q, tiers);\n }\n\n if (best > 0) {\n // Tiny bias so that when two fields tie, the one declared first wins.\n total += best + (fields.length - idx);\n }\n });\n\n // Auto-match the row's UUID `id` against EVERY search box. A user can paste a\n // full or partial id and find the record, without each callsite remembering\n // to declare an id field. Skipped when the caller already declared an\n // explicit `weight: \"id\"` field (so we don't double-score), and gated on a\n // minimum query length so short queries don't match random hex substrings.\n const hasExplicitId = fields.some((f) => f.weight === \"id\");\n if (!hasExplicitId && q.length >= MIN_AUTO_ID_QUERY_LEN) {\n const id = getStringId(item);\n if (id) {\n total += scoreValue(id, q, WEIGHT_TABLE.id);\n }\n }\n\n return total;\n}\n\nexport function matchesSearch<T>(\n item: T,\n query: string,\n fields: SearchFieldConfig<T>[],\n): boolean {\n return computeSearchScore(item, query, fields) > 0;\n}\n\n/**\n * Drop-in id-match for hand-rolled `.filter()` predicates that can't (yet) move\n * onto {@link filterAndSortBySearch}. Returns true when `query` is a substring\n * of the item's string `id`, applying the same {@link MIN_AUTO_ID_QUERY_LEN}\n * guard as the automatic pass so short queries don't match random hex.\n *\n * list.filter((x) => x.name.toLowerCase().includes(q) || idMatchesQuery(x, q))\n *\n * Prefer migrating the callsite to `filterAndSortBySearch` (which does this for\n * free); reach for this only when an existing custom sort must be preserved.\n */\nexport function idMatchesQuery(item: unknown, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (q.length < MIN_AUTO_ID_QUERY_LEN) return false;\n const id = getStringId(item);\n return id != null && id.toLowerCase().includes(q);\n}\n\n/**\n * Filter out non-matches and sort remaining items by descending relevance.\n * Stable with respect to the original order when two items tie.\n */\nexport function filterAndSortBySearch<T>(\n items: readonly T[],\n query: string,\n fields: SearchFieldConfig<T>[],\n): T[] {\n const trimmed = query.trim();\n if (!trimmed) return items.slice();\n\n const scored: { item: T; score: number; idx: number }[] = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i] as T;\n const score = computeSearchScore(item, trimmed, fields);\n if (score > 0) scored.push({ item, score, idx: i });\n }\n scored.sort((a, b) => (b.score - a.score) || (a.idx - b.idx));\n return scored.map((s) => s.item);\n}\n","export interface ConcurrencyFailure<T> {\n item: T;\n index: number;\n error: unknown;\n}\n\nexport interface ConcurrencyResult<T> {\n started: number;\n succeeded: number;\n failed: number;\n failures: ConcurrencyFailure<T>[];\n}\n\n/**\n * Runs independent items through a bounded worker pool. One item failing does\n * not stop the rest, and `shouldStart` can stop new work without interrupting\n * items already in flight.\n */\nexport async function runWithConcurrency<T>(\n items: readonly T[],\n limit: number,\n worker: (item: T, index: number) => Promise<void>,\n shouldStart: () => boolean = () => true,\n): Promise<ConcurrencyResult<T>> {\n if (items.length === 0) {\n return { started: 0, succeeded: 0, failed: 0, failures: [] };\n }\n\n let cursor = 0;\n let started = 0;\n let succeeded = 0;\n const failures: ConcurrencyFailure<T>[] = [];\n const requestedLimit = Number.isFinite(limit) ? Math.floor(limit) : 1;\n const workerCount = Math.max(1, Math.min(requestedLimit, items.length));\n\n const runners = Array.from({ length: workerCount }, async () => {\n while (shouldStart()) {\n const index = cursor++;\n if (index >= items.length) return;\n started += 1;\n const item = items[index] as T;\n try {\n await worker(item, index);\n succeeded += 1;\n } catch (error) {\n failures.push({ item, index, error });\n }\n }\n });\n\n await Promise.all(runners);\n failures.sort((left, right) => left.index - right.index);\n\n return {\n started,\n succeeded,\n failed: failures.length,\n failures,\n };\n}\n","/**\n * Text formatting options\n */\nexport type TextCaseOption = 'title' | 'sentence' | 'normal' | 'lower' | 'upper';\n\nexport interface TextFormatterOptions {\n /**\n * Text case to apply after normalization\n * - title: First Letter Of Each Word Capitalized\n * - sentence: First letter of first word capitalized\n * - normal: No case transformation after normalization\n * - lower: all text lowercase\n * - upper: ALL TEXT UPPERCASE\n */\n textCase?: TextCaseOption;\n \n /**\n * Map of words to replace with specific formatting\n * Example: { 'api': 'API', 'ui': 'UI' }\n */\n wordReplacements?: Record<string, string>;\n \n /**\n * Whether to trim the result\n */\n trim?: boolean;\n}\n\n/**\n * Default word replacements for common acronyms and terms\n */\nexport type ReplacementMap = Readonly<Record<string, string>>;\n\nexport const DEFAULT_WORD_REPLACEMENTS: ReplacementMap = {\n // Acronyms & initialisms\n 'api': 'API',\n 'apis': 'APIs',\n 'ui': 'UI',\n 'ux': 'UX',\n 'id': 'ID',\n 'ids': 'IDs',\n 'qr': 'QR',\n 'ssr': 'SSR',\n 'csr': 'CSR',\n 'ssg': 'SSG',\n 'isr': 'ISR',\n 'spa': 'SPA',\n 'pwa': 'PWA',\n 'sdk': 'SDK',\n 'sdks': 'SDKs',\n 'cli': 'CLI',\n 'tty': 'TTY',\n 'repl': 'REPL',\n 'ci': 'CI',\n 'cd': 'CD',\n 'cpu': 'CPU',\n 'cpus': 'CPUs',\n 'gpu': 'GPU',\n 'gpus': 'GPUs',\n 'ram': 'RAM',\n 'rom': 'ROM',\n 'ssd': 'SSD',\n 'ssds': 'SSDs',\n 'hdd': 'HDD',\n 'hdds': 'HDDs',\n 'kpi': 'KPI',\n 'kpis': 'KPIs',\n 'sla': 'SLA',\n 'slas': 'SLAs',\n 'slo': 'SLO',\n 'slos': 'SLOs',\n 'sli': 'SLI',\n 'slis': 'SLIs',\n 'dom': 'DOM',\n\n // Web, formats, protocols\n 'url': 'URL',\n 'urls': 'URLs',\n 'uri': 'URI',\n 'uris': 'URIs',\n 'http': 'HTTP',\n 'https': 'HTTPS',\n 'html': 'HTML',\n 'css': 'CSS',\n 'json': 'JSON',\n 'yaml': 'YAML',\n 'yml': 'YML',\n 'toml': 'TOML',\n 'csv': 'CSV',\n 'pdf': 'PDF',\n 'tsv': 'TSV',\n 'jpg': 'JPG',\n 'jpeg': 'JPEG',\n 'png': 'PNG',\n 'gif': 'GIF',\n 'webp': 'WebP',\n 'heic': 'HEIC',\n 'heif': 'HEIF',\n 'bmp': 'BMP',\n 'tiff': 'TIFF',\n 'ico': 'ICO',\n 'xml': 'XML',\n 'sql': 'SQL',\n 'db': 'DB',\n 'dbs': 'DBs',\n 'nosql': 'NoSQL',\n 'graphql': 'GraphQL',\n 'grpc': 'gRPC',\n 'rest': 'REST',\n 'restful': 'RESTful',\n 'websocket': 'WebSocket',\n 'websockets': 'WebSockets',\n 'webrtc': 'WebRTC',\n\n // Networking\n 'ip': 'IP',\n 'ipv4': 'IPv4',\n 'ipv6': 'IPv6',\n 'dns': 'DNS',\n 'dhcp': 'DHCP',\n 'nat': 'NAT',\n 'tcp': 'TCP',\n 'udp': 'UDP',\n 'icmp': 'ICMP',\n 'ttl': 'TTL',\n 'lan': 'LAN',\n 'wan': 'WAN',\n 'vlan': 'VLAN',\n 'cdn': 'CDN',\n 'ftp': 'FTP',\n 'ssh': 'SSH',\n 'tls': 'TLS',\n 'ssl': 'SSL',\n\n // Security & crypto\n 'jwt': 'JWT',\n 'jws': 'JWS',\n 'jwe': 'JWE',\n 'hmac': 'HMAC',\n 'rsa': 'RSA',\n 'ecdsa': 'ECDSA',\n 'aes': 'AES',\n 'pbkdf2': 'PBKDF2',\n 'argon2': 'Argon2',\n 'scrypt': 'scrypt',\n 'totp': 'TOTP',\n 'hotp': 'HOTP',\n 'mfa': 'MFA',\n '2fa': '2FA',\n 'csrf': 'CSRF',\n 'xss': 'XSS',\n 'ssrf': 'SSRF',\n 'rce': 'RCE',\n 'dos': 'DoS',\n 'ddos': 'DDoS',\n 'mitm': 'MITM',\n 'csp': 'CSP',\n 'cors': 'CORS',\n 'pii': 'PII',\n 'phi': 'PHI',\n 'gdpr': 'GDPR',\n 'ccpa': 'CCPA',\n 'hipaa': 'HIPAA',\n 'rfc': 'RFC',\n\n // Platforms, langs, tools (single-token)\n 'javascript': 'JavaScript',\n 'typescript': 'TypeScript',\n 'jsx': 'JSX',\n 'tsx': 'TSX',\n 'node': 'Node', // (used when tokenized alone)\n 'deno': 'Deno',\n 'bun': 'Bun',\n 'react': 'React',\n 'nextjs': 'Next.js', // if your tokenizer drops dots, keep this\n 'nodejs': 'Node.js',\n 'postgresql': 'PostgreSQL',\n 'postgres': 'Postgres',\n 'mysql': 'MySQL',\n 'sqlite': 'SQLite',\n 'redis': 'Redis',\n 'supabase': 'Supabase',\n 'docker': 'Docker',\n 'kubernetes': 'Kubernetes',\n 'k8s': 'Kubernetes',\n 'helm': 'Helm',\n 'npm': 'npm',\n 'pnpm': 'pnpm',\n 'yarn': 'Yarn',\n 'eslint': 'ESLint',\n 'prettier': 'Prettier',\n 'vite': 'Vite',\n 'webpack': 'Webpack',\n 'babel': 'Babel',\n\n // OS & vendors\n 'macos': 'macOS',\n 'ios': 'iOS',\n 'ipados': 'iPadOS',\n 'watchos': 'watchOS',\n 'tvos': 'tvOS',\n 'windows': 'Windows',\n 'linux': 'Linux',\n 'ubuntu': 'Ubuntu',\n 'github': 'GitHub',\n 'gitlab': 'GitLab',\n 'bitbucket': 'Bitbucket',\n\n // Data & analytics\n 'etl': 'ETL',\n 'elt': 'ELT',\n 'olap': 'OLAP',\n 'oltp': 'OLTP',\n 'bi': 'BI',\n\n // Time & locales\n 'utc': 'UTC',\n 'gmt': 'GMT',\n 'pst': 'PST',\n 'pdt': 'PDT',\n 'pt': 'PT',\n\n // Common “small words” to keep lowercase (unless first/last word)\n 'or': 'or',\n 'and': 'and',\n 'the': 'the',\n 'of': 'of',\n 'in': 'in',\n 'to': 'to',\n 'with': 'with',\n 'as': 'as',\n 'by': 'by',\n 'for': 'for',\n 'on': 'on',\n 'at': 'at',\n 'up': 'up',\n 'a': 'a',\n 'an': 'an',\n 'is': 'is',\n 'are': 'are',\n 'was': 'was',\n 'were': 'were',\n 'be': 'be',\n 'but': 'but',\n 'nor': 'nor',\n 'so': 'so',\n 'yet': 'yet',\n 'per': 'per',\n 'via': 'via',\n\n // Latin abbreviations (tokenized as words in some pipelines)\n 'eg': 'e.g.',\n 'ie': 'i.e.',\n 'etc': 'etc.',\n 'aka': 'aka',\n 'vs': 'vs.',\n 'v': 'v.',\n\n // Client abbreviations\n 'CIC': 'CIC',\n 'AGR': 'AGR',\n 'AGER': 'AGER',\n 'DD': 'DD',\n 'TS': 'TS',\n 'TM': 'TM',\n 'arman': \"Arman\",\n};\n\n/**\n * Default options for text formatting\n */\nconst DEFAULT_OPTIONS: TextFormatterOptions = {\n textCase: 'title',\n wordReplacements: DEFAULT_WORD_REPLACEMENTS,\n trim: true,\n};\n\n/**\n * Formats text by normalizing case styles, applying case transformations,\n * and replacing specific words with custom formatting.\n * \n * @param text The input text to format\n * @param options Formatting options\n * @returns Formatted text\n */\nexport function formatText(text: string, options: TextFormatterOptions = {}): string {\n // Merge provided options with defaults\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n // Handle empty text\n if (!text) return '';\n \n // Step 1: Normalize various case styles to space-separated words\n let normalized = text\n // Convert snake_case to space-separated\n .replace(/_/g, ' ')\n // Convert kebab-case to space-separated\n .replace(/-/g, ' ')\n // Convert camelCase and PascalCase to space-separated\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace multiple spaces with a single space\n .replace(/\\s+/g, ' ');\n \n // Step 2: Apply trim if needed\n if (opts.trim) {\n normalized = normalized.trim();\n }\n \n // Step 3: Apply the specified text case\n let caseTransformed = normalized;\n switch (opts.textCase) {\n case 'title':\n caseTransformed = normalized.replace(/\\w\\S*/g, (word) => \n word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()\n );\n break;\n case 'sentence':\n if (normalized.length > 0) {\n caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();\n }\n break;\n case 'lower':\n caseTransformed = normalized.toLowerCase();\n break;\n case 'upper':\n caseTransformed = normalized.toUpperCase();\n break;\n case 'normal':\n default:\n // No case transformation\n break;\n }\n \n // Step 4: Apply word replacements if provided\n let result = caseTransformed;\n if (opts.wordReplacements) {\n Object.entries(opts.wordReplacements).forEach(([key, value]) => {\n // Create a regex that matches the key as a whole word (case insensitive)\n const regex = new RegExp(`\\\\b${key}\\\\b`, 'gi');\n result = result.replace(regex, value);\n });\n }\n \n return result;\n}\n\n/**\n * Creates a pre-configured formatter function with specific options\n * \n * @param defaultOptions Default options for the formatter\n * @returns A formatter function with the specified default options\n */\nexport function createFormatter(defaultOptions: TextFormatterOptions = {}) {\n return (text: string, overrideOptions: TextFormatterOptions = {}) => \n formatText(text, { ...defaultOptions, ...overrideOptions });\n}\n\n// Some pre-configured formatters for common use cases\nexport const formatTitleCase = createFormatter({ textCase: 'title' });\nexport const formatSentenceCase = createFormatter({ textCase: 'sentence' });\nexport const formatNormalCase = createFormatter({ textCase: 'normal' });\nexport const formatUpperCase = createFormatter({ textCase: 'upper' });\nexport const formatLowerCase = createFormatter({ textCase: 'lower' });\nexport const formatWithoutReplacements = createFormatter({ wordReplacements: {} });\n","\"use client\";\n\n// useDurableDraft — user-authored text that MUST survive anything.\n//\n// A composer draft held only in React state dies with the tab: a mobile\n// Safari reload, a crash, an error storm, a mis-tap on Back — and the user's\n// two-minute dictated rant is gone. Losing it once costs all trust\n// (Arman's ruling, 2026-08-16, after exactly that happened in the Vision\n// Interview room).\n//\n// This hook is write-through: every change lands in localStorage\n// synchronously, restore happens on mount, and the draft is removed ONLY\n// via clearDraft() — which callers may invoke only after the content has\n// durably landed somewhere the user can see (a DB row, a rendered turn).\n// A send that fails keeps the draft by construction.\n//\n// Storage failure (private mode, quota) never breaks typing — state still\n// works; the failure is logged loudly once so the degraded durability is\n// visible, not silent.\n\nimport { useEffect, useRef, useState } from \"react\";\n\nconst PREFIX = \"matrx:durable-draft:\";\n\nlet warnedStorageUnavailable = false;\n\nfunction storageWrite(storageKey: string, value: string): void {\n try {\n if (value) window.localStorage.setItem(storageKey, value);\n else window.localStorage.removeItem(storageKey);\n } catch (err) {\n if (!warnedStorageUnavailable) {\n warnedStorageUnavailable = true;\n console.warn(\n \"[useDurableDraft] localStorage unavailable — drafts survive only in memory this session\",\n err,\n );\n }\n }\n}\n\nexport function useDurableDraft(key: string): {\n draft: string;\n setDraft: (value: string) => void;\n clearDraft: () => void;\n} {\n const storageKey = PREFIX + key;\n const [draft, setDraftState] = useState(\"\");\n // Which key the user's live keystrokes belong to. Their typing beats a\n // stale saved copy ONLY for the same key — a key CHANGE always adopts the\n // new key's saved value (or empty), so a swapped entity id can never show\n // or send the previous entity's text.\n const touchedKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n // Restore runs on mount AND on every key change (localStorage is\n // unavailable during SSR, hence effect not render).\n let saved: string | null = null;\n try {\n saved = window.localStorage.getItem(storageKey);\n } catch {\n // Restore is best-effort; the write path warns once (above).\n }\n setDraftState((current) =>\n touchedKeyRef.current === storageKey && current ? current : (saved ?? \"\"),\n );\n }, [storageKey]);\n\n const setDraft = (value: string) => {\n touchedKeyRef.current = storageKey;\n setDraftState(value);\n storageWrite(storageKey, value);\n };\n\n const clearDraft = () => {\n touchedKeyRef.current = storageKey;\n setDraftState(\"\");\n storageWrite(storageKey, \"\");\n };\n\n return { draft, setDraft, clearDraft };\n}\n","// lib/local-drafts/localDrafts.ts\n//\n// THE LAST-RESORT COPY of unsaved in-memory work, in this browser.\n//\n// Nothing here is a persistence path — every feature still owns its real save.\n// This exists for the moment the app is about to LOSE in-memory edits and has\n// no way to persist them: the tab is being hard-stopped (auth identity drift),\n// the page is unloading, or a feature's saves have been failing so long that\n// the buffer is the only copy that exists. Snapshot first, block second.\n//\n// Written because of D132 (2026-08-08): a domain-wide auth cookie rotated\n// under an open /notes tab, ~14h of autosaves were RLS-filtered to 0 rows, and\n// the \"Account Changed\" overlay then forced a reload that threw the in-memory\n// buffer away. One note never reached the DB at all and is unrecoverable.\n//\n// Rules:\n// - A draft is offered back ONLY to the same `ownerId` that wrote it.\n// - Storage is best-effort: quota errors, private mode, and disabled storage\n// degrade to \"no draft\", never to a thrown error on a save path.\n// - Drafts expire (7 days) and are capped, oldest-first, so this can never\n// grow into a shadow database.\n\nimport type { DraftSource, LocalDraft, LocalDraftInput } from \"./types\";\n\nconst STORAGE_KEY = \"matrx.local-drafts.v1\";\n\n/** Drafts older than this are dropped on the next read/write. */\nconst DRAFT_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n/** A single draft larger than this is stored truncated (with a marker). */\nconst MAX_DRAFT_CHARS = 400_000;\n/** Total budget across all drafts; the oldest are dropped to fit. */\nconst MAX_TOTAL_CHARS = 1_500_000;\n\nconst TRUNCATION_MARKER =\n \"\\n\\n[… truncated by the local draft store — the note was too large to snapshot in full]\";\n\n// ── Sources ────────────────────────────────────────────────────────────────\n\nconst sources = new Map<string, DraftSource>();\nlet unloadListenerAttached = false;\n\n// ── Subscription ───────────────────────────────────────────────────────────\n//\n// A capture can happen while a recovery UI is already on screen (a save-failure\n// escalation for a note that is not the open tab). Without a notification that\n// strip would sit empty until a remount — i.e. the rescue exists and the user\n// is never told. `version` bumps on every write.\n\nconst listeners = new Set<() => void>();\nlet version = 0;\n\n/** Subscribe to draft-store writes. Pair with `getDraftsVersion` for `useSyncExternalStore`. */\nexport function subscribeDrafts(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function getDraftsVersion(): number {\n return version;\n}\n\nfunction emitDraftsChanged(): void {\n version += 1;\n for (const listener of listeners) {\n try {\n listener();\n } catch (err) {\n console.error(\"[LocalDrafts] subscriber threw:\", err);\n }\n }\n}\n\n/**\n * Register a collector for one feature's unsaved work. Re-registering the same\n * id replaces the previous collector (remounts are safe); the returned\n * unregister only removes the entry if it is still the one it installed.\n */\nexport function registerDraftSource(id: string, collect: DraftSource): () => void {\n sources.set(id, collect);\n attachUnloadListener();\n return () => {\n if (sources.get(id) === collect) sources.delete(id);\n };\n}\n\nfunction attachUnloadListener(): void {\n if (unloadListenerAttached || typeof window === \"undefined\") return;\n unloadListenerAttached = true;\n // `pagehide` fires in cases `beforeunload` does not (bfcache, mobile Safari).\n window.addEventListener(\"pagehide\", () => {\n captureDrafts(\"unload\");\n });\n}\n\n// ── Capture ────────────────────────────────────────────────────────────────\n\n/**\n * Walk every registered source and persist what they hand back.\n * Returns the drafts written (empty when nothing is unsaved).\n *\n * Call this BEFORE anything that discards in-memory state — a forced reload,\n * a blocking overlay, a hard sign-out.\n */\nexport function captureDrafts(reason: string): LocalDraft[] {\n if (typeof window === \"undefined\") return [];\n\n const collected: LocalDraftInput[] = [];\n for (const [id, collect] of sources) {\n try {\n collected.push(...collect());\n } catch (err) {\n console.error(\"[LocalDrafts] draft source failed:\", id, err);\n }\n }\n if (collected.length === 0) return [];\n\n const now = Date.now();\n const written: LocalDraft[] = collected.map((input) => ({\n ...input,\n content:\n input.content.length > MAX_DRAFT_CHARS\n ? input.content.slice(0, MAX_DRAFT_CHARS) + TRUNCATION_MARKER\n : input.content,\n key: draftKey(input.namespace, input.entityId),\n capturedAt: now,\n reason,\n }));\n\n const existing = readAll().filter(\n (d) => !written.some((w) => w.key === d.key),\n );\n writeAll([...written, ...existing]);\n\n console.warn(\n `[LocalDrafts] snapshotted ${written.length} unsaved item(s) to this browser (reason: ${reason}).`,\n written.map((d) => `${d.key} (${d.content.length} chars)`),\n );\n return written;\n}\n\n// ── Read / discard ─────────────────────────────────────────────────────────\n\n/** Every live draft in a namespace that belongs to `ownerId`, newest first. */\nexport function listDrafts(namespace: string, ownerId: string | null): LocalDraft[] {\n if (!ownerId) return [];\n return readAll()\n .filter((d) => d.namespace === namespace && d.ownerId === ownerId)\n .sort((a, b) => b.capturedAt - a.capturedAt);\n}\n\n/** The draft for one entity, if it belongs to `ownerId`. */\nexport function getDraft(\n namespace: string,\n entityId: string,\n ownerId: string | null,\n): LocalDraft | null {\n if (!ownerId) return null;\n const key = draftKey(namespace, entityId);\n return (\n readAll().find((d) => d.key === key && d.ownerId === ownerId) ?? null\n );\n}\n\n/** Drop one draft (restored, discarded by the user, or its entity saved). */\nexport function discardDraft(namespace: string, entityId: string): void {\n const key = draftKey(namespace, entityId);\n const all = readAll();\n const next = all.filter((d) => d.key !== key);\n if (next.length !== all.length) writeAll(next); // writeAll emits\n}\n\n// ── Storage ────────────────────────────────────────────────────────────────\n\nfunction draftKey(namespace: string, entityId: string): string {\n return `${namespace}:${entityId}`;\n}\n\nfunction readAll(): LocalDraft[] {\n if (typeof window === \"undefined\") return [];\n let raw: string | null = null;\n try {\n raw = window.localStorage.getItem(STORAGE_KEY);\n } catch {\n return []; // storage disabled / private mode — no drafts, never a throw\n }\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const cutoff = Date.now() - DRAFT_TTL_MS;\n return parsed.filter(isLocalDraft).filter((d) => d.capturedAt >= cutoff);\n } catch {\n return [];\n }\n}\n\nfunction writeAll(drafts: LocalDraft[]): void {\n if (typeof window === \"undefined\") return;\n const cutoff = Date.now() - DRAFT_TTL_MS;\n const fresh = drafts\n .filter((d) => d.capturedAt >= cutoff)\n .sort((a, b) => b.capturedAt - a.capturedAt);\n\n // Newest-first budget: keep taking drafts until the char budget runs out.\n const kept: LocalDraft[] = [];\n let total = 0;\n for (const draft of fresh) {\n if (total + draft.content.length > MAX_TOTAL_CHARS && kept.length > 0) {\n console.warn(\n \"[LocalDrafts] draft budget exhausted — dropping older draft\",\n draft.key,\n );\n continue;\n }\n kept.push(draft);\n total += draft.content.length;\n }\n\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(kept));\n } catch (err) {\n // Quota exceeded: retry with only the newest draft before giving up —\n // one recovered note beats zero.\n console.error(\"[LocalDrafts] failed to persist drafts:\", err);\n if (kept.length > 1) {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify([kept[0]]));\n } catch {\n /* storage is unusable — nothing more we can do here */\n }\n }\n }\n\n emitDraftsChanged();\n}\n\nfunction isLocalDraft(value: unknown): value is LocalDraft {\n if (typeof value !== \"object\" || value === null) return false;\n const d = value as Record<string, unknown>;\n return (\n typeof d.key === \"string\" &&\n typeof d.namespace === \"string\" &&\n typeof d.entityId === \"string\" &&\n typeof d.content === \"string\" &&\n typeof d.capturedAt === \"number\"\n );\n}\n","/**\n * @ai-matrx/kit/confirm — imperative opener.\n *\n * Pure-TS imperative API for the global confirm dialog. Zero React, zero\n * dialog markup — this module is statically importable from anywhere\n * (hooks, utils, Redux thunks, async handlers, sync code, anything).\n *\n * The host (`ConfirmDialogHost`) registers a controller on mount and\n * unregisters on unmount. Calls made before the host has hydrated queue\n * up and resolve as soon as the host is alive — so a destructive action\n * triggered in the first ~50ms after page load still gets a real\n * confirmation, never a silent default-yes/no. With no host ever mounted,\n * a `confirm()` promise stays pending forever (the original's behavior —\n * it never resolves to a silent default).\n *\n * One dialog at a time: concurrent calls queue and present sequentially.\n *\n * Ported verbatim from matrx-frontend\n * `components/dialogs/confirm/confirmDialogOpener.ts`, with ONE structural\n * inversion: the host/queue state lives on `globalThis` under a\n * `Symbol.for` slot instead of module-level variables. With the package\n * built `splitting: false` in dual ESM/CJS format, this module is\n * duplicated into the root bundle and the `./confirm` bundle, and CJS/ESM\n * each instantiate their own module graph — a module-level variable would\n * silently split the host registration from the callers (the same hazard\n * `@ai-matrx/tap-target` documents for its link registry). Behavior is\n * unchanged; never \"clean this up\" into a module local.\n */\n\nimport type { ReactNode } from \"react\";\n\nexport interface ConfirmOptions {\n title: ReactNode;\n description?: ReactNode | undefined;\n confirmLabel?: string | undefined;\n /** `null` hides the cancel button (acknowledge-only dialogs). */\n cancelLabel?: string | null | undefined;\n variant?: \"default\" | \"destructive\" | undefined;\n}\n\ntype Resolver = (confirmed: boolean) => void;\n\ninterface PendingRequest {\n opts: ConfirmOptions;\n resolve: Resolver;\n}\n\ninterface HostController {\n show: (opts: ConfirmOptions, resolve: Resolver) => void;\n}\n\ninterface OpenerState {\n host: HostController | null;\n queue: PendingRequest[];\n}\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.confirm-opener-state\");\n\nfunction getState(): OpenerState {\n const holder = globalThis as Record<symbol, OpenerState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = { host: null, queue: [] };\n holder[STATE_SLOT] = state;\n }\n return state;\n}\n\n/** @internal Called by `ConfirmDialogHost` on mount. */\nexport function _registerHost(controller: HostController): void {\n const state = getState();\n state.host = controller;\n while (state.queue.length > 0) {\n const next = state.queue.shift()!;\n controller.show(next.opts, next.resolve);\n }\n}\n\n/** @internal Called by `ConfirmDialogHost` on unmount. */\nexport function _unregisterHost(controller: HostController): void {\n const state = getState();\n if (state.host === controller) state.host = null;\n}\n\n/** @internal Test-only: drop any registered host and pending queue. */\nexport function _resetConfirmOpenerState(): void {\n const state = getState();\n state.host = null;\n state.queue.length = 0;\n}\n\n/**\n * Imperative confirm. Returns a Promise that resolves `true` if the user\n * confirms, `false` if they cancel/dismiss. Replaces `window.confirm`.\n *\n * @example\n * const ok = await confirm({\n * title: \"Delete sandbox\",\n * description: \"This cannot be undone.\",\n * variant: \"destructive\",\n * confirmLabel: \"Delete\",\n * });\n * if (!ok) return;\n */\nexport function confirm(opts: ConfirmOptions): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const state = getState();\n if (state.host) {\n state.host.show(opts, resolve);\n } else {\n state.queue.push({ opts, resolve });\n }\n });\n}\n","\"use client\";\n\n/**\n * `<ConfirmDialogHost />` — render ONCE, near the root of every provider\n * tree, so the imperative `confirm()` always has a live host to dispatch to.\n * Pre-mount calls queue inside `opener.ts` and resolve as soon as the host\n * registers.\n *\n * Ported from matrx-frontend `components/dialogs/confirm/\n * {ConfirmDialogHost,ConfirmDialogHostImpl}.tsx`, with the loading seam\n * inverted: the original split shell + impl and loaded the impl via\n * `next/dynamic({ ssr: false })` to keep radix out of route entry chunks.\n * A framework-agnostic package cannot use `next/dynamic`, so the host is\n * ONE directly-imported component; hosts that want the original's\n * code-splitting lazy-load the subpath themselves, e.g.\n * `dynamic(() => import(\"@ai-matrx/kit/confirm\").then(m => m.ConfirmDialogHost), { ssr: false })`.\n * The \"host renders `<ConfirmDialogHost/>` once\" contract is unchanged.\n *\n * Imperative model: calls to `confirm(...)` from anywhere push a request\n * into a ref-backed queue; this component drains the queue one item at a\n * time and renders a `<ConfirmDialog>` for the currently-active request.\n * Resolving Promise<boolean> happens on Confirm click (true), or on\n * dismiss/cancel (false). The dialog closes immediately on click — callers\n * that need an in-dialog busy spinner during async work should use the\n * inline `<ConfirmDialog>` with the `busy` prop instead.\n */\n\nimport * as React from \"react\";\n\nimport { ConfirmDialog } from \"./confirm-dialog\";\nimport {\n _registerHost,\n _unregisterHost,\n type ConfirmOptions,\n} from \"./opener\";\n\ninterface ActiveRequest {\n opts: ConfirmOptions;\n resolve: (confirmed: boolean) => void;\n}\n\nexport function ConfirmDialogHost() {\n const [active, setActive] = React.useState<ActiveRequest | null>(null);\n const [tick, setTick] = React.useState(0);\n const queueRef = React.useRef<ActiveRequest[]>([]);\n\n // Register/unregister the controller exactly once. The controller's\n // `show` always pushes onto the queue and bumps `tick`; the drain\n // effect below picks up from there. This avoids stale-closure bugs\n // around `active`.\n React.useEffect(() => {\n const controller = {\n show: (opts: ConfirmOptions, resolve: (confirmed: boolean) => void) => {\n queueRef.current.push({ opts, resolve });\n setTick((n) => n + 1);\n },\n };\n _registerHost(controller);\n return () => _unregisterHost(controller);\n }, []);\n\n // Drain the queue whenever nothing is showing.\n React.useEffect(() => {\n if (active === null && queueRef.current.length > 0) {\n setActive(queueRef.current.shift()!);\n }\n }, [active, tick]);\n\n const handleConfirm = React.useCallback(() => {\n if (!active) return;\n active.resolve(true);\n setActive(null);\n }, [active]);\n\n const handleOpenChange = React.useCallback(\n (open: boolean) => {\n if (!open && active) {\n active.resolve(false);\n setActive(null);\n }\n },\n [active],\n );\n\n return (\n <ConfirmDialog\n open={!!active}\n onOpenChange={handleOpenChange}\n title={active?.opts.title ?? \"\"}\n description={active?.opts.description}\n confirmLabel={active?.opts.confirmLabel}\n cancelLabel={active?.opts.cancelLabel}\n variant={active?.opts.variant}\n onConfirm={handleConfirm}\n />\n );\n}\n","import { twMerge } from \"tailwind-merge\";\n\n/**\n * Tailwind-aware className merge. The original app's `cn` is\n * `twMerge(clsx(inputs))`; here `clsx` is dropped (every call site passes\n * strings / false), but `tailwind-merge` is KEPT on purpose: the public\n * `className` / `contentClassName` overrides depend on last-wins conflict\n * resolution (e.g. a host's `max-w-3xl` must beat the built-in `max-w-lg`,\n * a destructive `bg-destructive` must beat the default `bg-primary`).\n * A naive join would leave both classes applied and let stylesheet order\n * decide — a real behavior divergence from the original.\n */\nexport function cn(\n ...values: Array<string | null | undefined | false>\n): string {\n return twMerge(values.filter(Boolean).join(\" \"));\n}\n","\"use client\";\n\n/**\n * Inlined shadcn-style wrapper over `@radix-ui/react-alert-dialog` — the one\n * real runtime dependency of the `./confirm` subpath (this subpath's product\n * IS the dialog). Ported from matrx-frontend `components/ui/alert-dialog.tsx`\n * with the host-shaped seams inverted:\n *\n * - `usePopoutContainer` (window-panels popout portal retargeting) is dropped:\n * the portal targets the Radix default (`document.body`). Hosts with exotic\n * portal needs pass `container` on `AlertDialogPortal` themselves.\n * - `buttonVariants` from the design system is inlined as the exact class\n * strings the two footer buttons use (base + default + outline variants,\n * design-system `button.tsx` as of this port). No cva dependency.\n * - Styling keeps the Tailwind semantic-token classes VERBATIM (`bg-background`,\n * `text-muted-foreground`, `bg-primary`, `border-border`, ...) — the platform\n * vocabulary. Hosts on other design systems override via the `className` /\n * `contentClassName` props (classes merge last-wins via tailwind-merge).\n *\n * THE ROOT RENDERS UNCONDITIONALLY — no mount gate. Radix ids come from\n * React's SSR-stable `useId`, so there is no SSR/client id mismatch to hide\n * from (the original's D144 ruling).\n */\n\nimport * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"./cn\";\nimport { treeContainsComponent } from \"../react-tree\";\n\n/**\n * Inlined design-system button classes (base + the two variants the alert\n * dialog footer uses). Source of truth while the originals live:\n * aidream `apps/shared/design-system/src/button.tsx`.\n */\nconst buttonBase =\n \"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 h-9 px-4 py-2\";\nconst buttonDefault =\n \"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90\";\nconst buttonOutline =\n \"border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-[10000] bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\n/**\n * Unstyled, non-portalling Content for custom AlertDialog layouts. AlertDialog\n * is always modal, so this keeps its ARIA semantics explicit and consistent.\n */\nconst AlertDialogContentPrimitive = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ ...props }, ref) => (\n <AlertDialogPrimitive.Content {...props} ref={ref} aria-modal=\"true\" />\n));\nAlertDialogContentPrimitive.displayName = \"AlertDialogContentPrimitive\";\n\nconst AlertDialogDescription = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> & {\n /**\n * Portal target. Default (undefined): Radix's default, `document.body`.\n * Hosts with retargeting needs (e.g. a popped-out browser window whose\n * dialog must render in THAT window's document) pass the element here.\n */\n container?: HTMLElement | null | undefined;\n }\n>(({ className, children, container, ...props }, ref) => {\n const hasDescription =\n treeContainsComponent(children, AlertDialogDescription) ||\n treeContainsComponent(children, AlertDialogPrimitive.Description);\n return (\n <AlertDialogPortal container={container ?? undefined}>\n <AlertDialogOverlay />\n <AlertDialogContentPrimitive\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-[10000] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n >\n {!hasDescription && (\n <AlertDialogPrimitive.Description className=\"sr-only\">\n Please confirm the action described in this dialog.\n </AlertDialogPrimitive.Description>\n )}\n {children}\n </AlertDialogContentPrimitive>\n </AlertDialogPortal>\n );\n});\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonBase, buttonDefault, className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(buttonBase, buttonOutline, \"mt-2 sm:mt-0\", className)}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogContentPrimitive,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n","/**\n * @ai-matrx/kit/react-tree — safe React children-tree scanning.\n *\n * Ported from matrx-frontend `lib/react/treeContainsComponent.ts`; this\n * subpath is the ONE home of the scanner inside the kit (the `/confirm`\n * subpath's alert-dialog imports it from here — no duplicate bodies).\n *\n * Two deliberate divergences from the frontend original, both documented:\n * - the dev-mode scream checks `typeof process` first, since this package may\n * load in an unbundled browser context where `process` is undefined;\n * - a React PORTAL child (`createPortal(...)` passed as a child) is a valid\n * React child, but it is not an element, an iterable, or a primitive — the\n * original fell through to the non-renderable branch, screamed a false\n * positive in dev, and skipped the portal's content. Portals are now\n * recognized and their children traversed.\n */\n\nimport * as React from \"react\";\n\nconst REACT_PORTAL_TYPE = Symbol.for(\"react.portal\");\n\n/**\n * Returns true if `Component` appears anywhere in the React element tree under\n * `node`. Used to detect optional a11y children (e.g. DialogDescription)\n * without rendering duplicates.\n *\n * DEFENSIVE + LOUD. A non-renderable node — a plain object or function passed\n * as a React child — is a real bug: React throws \"Objects are not valid as a\n * React child\" the instant it renders one. This a11y probe must NOT be the\n * crash site. `React.Children.toArray` would throw HERE, producing a trace that\n * points at the dialog primitive instead of the component that leaked the\n * object (this misdirection has burned real debugging hours). So we walk the\n * tree by hand, SKIP any non-renderable node, and scream in dev with its keys —\n * then let React report the defect at the true render site with the offending\n * component in the stack. For every VALID tree the result is identical to the\n * old `React.Children.toArray(node).some(...)`.\n */\nexport function treeContainsComponent(\n node: React.ReactNode,\n Component: React.ElementType,\n): boolean {\n if (node == null || typeof node === \"boolean\") return false;\n\n if (Array.isArray(node)) {\n return node.some((child) => treeContainsComponent(child, Component));\n }\n\n if (React.isValidElement(node)) {\n if (node.type === Component) return true;\n const props = node.props as { children?: React.ReactNode };\n return props.children != null\n ? treeContainsComponent(props.children, Component)\n : false;\n }\n\n // Strings / numbers are valid leaf children but never the Component.\n if (typeof node === \"string\" || typeof node === \"number\") return false;\n\n // A portal is a valid child that is NOT an element: traverse its content.\n if (\n typeof node === \"object\" &&\n (node as { $$typeof?: unknown }).$$typeof === REACT_PORTAL_TYPE\n ) {\n return treeContainsComponent(\n (node as { children?: React.ReactNode }).children,\n Component,\n );\n }\n\n // Non-array iterables (Set, Map, generator) are valid React children — React\n // supports them — so traverse rather than reject.\n if (typeof node === \"object\" && Symbol.iterator in node) {\n return Array.from(node as Iterable<React.ReactNode>).some((child) =>\n treeContainsComponent(child, Component),\n );\n }\n\n // Anything else (a raw object, a function) is NOT a valid React child. React\n // will throw when it renders this; we must not throw first and hide the cause.\n const runtimeProcess = (\n globalThis as { process?: { env?: { NODE_ENV?: string } } }\n ).process;\n if (runtimeProcess?.env?.NODE_ENV !== \"production\") {\n const keys =\n typeof node === \"object\"\n ? ` with keys {${Object.keys(node).join(\", \")}}`\n : \"\";\n console.error(\n `[treeContainsComponent] A non-renderable value${keys} is being passed as a React child. ` +\n \"React will throw 'Objects are not valid as a React child' at the real render site. \" +\n \"Stringify it (e.g. JSON.stringify) before rendering.\",\n node,\n );\n }\n return false;\n}\n","\"use client\";\n\n/**\n * Declarative `<ConfirmDialog />` — drop-in replacement for `window.confirm`.\n * Ported verbatim from matrx-frontend `components/ui/confirm-dialog.tsx`;\n * the only inversion is the busy spinner: `Loader2` from lucide-react is\n * inlined as a single SVG (the `@ai-matrx/tap-target` precedent — one icon\n * does not justify an icon dependency). Path annotated below.\n *\n * Pattern: hold the pending target in state, render <ConfirmDialog />\n * once at the bottom of the component, and open it by setting the target.\n * When busy state is meaningful (e.g. a network delete that should hold the\n * dialog open with a spinner), use THIS component inline; the imperative\n * `confirm()` closes immediately on click.\n */\n\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"./alert-dialog\";\n\n/** lucide `loader-circle` (a.k.a. `Loader2`) v1.22.0, inlined. */\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={className}\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\nexport interface ConfirmDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: React.ReactNode;\n description?: React.ReactNode | undefined;\n /**\n * Rich body rendered between the header and the footer, OUTSIDE the\n * description `<p>` — use for block-level content (diffs, previews, lists)\n * that would be invalid HTML inside `description`.\n */\n content?: React.ReactNode | undefined;\n /** Extra classes for the dialog content (e.g. a wider max-w for diffs). */\n contentClassName?: string | undefined;\n confirmLabel?: string | undefined;\n /**\n * `null` hides the cancel button entirely — for acknowledge-only dialogs\n * where there is nothing to cancel. Anything else labels it.\n */\n cancelLabel?: string | null | undefined;\n variant?: \"default\" | \"destructive\" | undefined;\n busy?: boolean | undefined;\n /**\n * Blocks confirming without pretending work is in flight. For a dialog whose\n * `content` asks the user something the action cannot proceed without — the\n * choice is missing, not loading — `busy` would show a misleading spinner.\n */\n confirmDisabled?: boolean | undefined;\n /**\n * Portal target for the dialog. Default (undefined): `document.body`.\n * Hosts with portal-retargeting needs (e.g. rendering into a popped-out\n * browser window's document) inject the element here — the seam exists so\n * that concern stays host-shaped.\n */\n portalContainer?: HTMLElement | null | undefined;\n onConfirm: () => void | Promise<void>;\n}\n\n/**\n * Drop-in replacement for `window.confirm`. Use this anywhere you would\n * otherwise reach for a browser-level confirm dialog.\n */\nexport function ConfirmDialog({\n open,\n onOpenChange,\n title,\n description,\n content,\n contentClassName,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n variant = \"default\",\n busy = false,\n confirmDisabled = false,\n portalContainer,\n onConfirm,\n}: ConfirmDialogProps) {\n return (\n <AlertDialog open={open} onOpenChange={onOpenChange}>\n <AlertDialogContent\n className={contentClassName}\n container={portalContainer ?? undefined}\n >\n <AlertDialogHeader>\n <AlertDialogTitle>{title}</AlertDialogTitle>\n {description ? (\n <AlertDialogDescription>{description}</AlertDialogDescription>\n ) : null}\n </AlertDialogHeader>\n {content ?? null}\n <AlertDialogFooter>\n {cancelLabel === null ? null : (\n <AlertDialogCancel className=\"max-lg:min-h-11\" disabled={busy}>\n {cancelLabel}\n </AlertDialogCancel>\n )}\n <AlertDialogAction\n disabled={busy || confirmDisabled}\n onClick={(event) => {\n event.preventDefault();\n void onConfirm();\n }}\n className={cn(\n \"max-lg:min-h-11\",\n variant === \"destructive\" &&\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n )}\n >\n {busy ? <SpinnerIcon className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {confirmLabel}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n","/**\n * @ai-matrx/kit/toast — the captured sonner wrapper, as a factory.\n *\n * A bare `toast.error(...)` from \"sonner\" is INVISIBLE to any error-capture\n * sink — every modern sonner call site silently bypasses error capture (the\n * exact hole matrx-frontend found in its marketing feature, 2026-07-20).\n * `createMatrxToast` returns a drop-in `toast` whose API is identical to the\n * one you pass in — `error` and `warning` additionally feed the injected\n * capture sink. A user seeing the failure is not evidence that it is minor,\n * so error toasts stay red unless a specific downgrade rule says otherwise.\n * Success/info/etc. pass straight through untouched.\n *\n * Ported from matrx-frontend `lib/toast.ts` with the two seams inverted:\n *\n * - `sonner` is NOT imported: the host passes its own `toast` object into the\n * factory (`createMatrxToast({ toast })`). That removes the peer-resolution\n * problem entirely — this module has zero dependencies — and the input is\n * typed STRUCTURALLY (callable + `.error` + `.warning`) so the returned\n * `toast` keeps the host's full sonner type, and no `.d.ts` in this package\n * references \"sonner\". Consequently `sonner` is NOT declared in the manifest\n * at all (X3: advisory peers are banned — nothing resolves it, so nothing\n * declares it; it remains a devDependency purely for the type-compat test).\n * - `captureError` from the app's diagnostics store becomes the injected\n * `capture?: (info) => void`. Omitted, capture is a no-op and every call\n * forwards identically (the original's payload shape is preserved exactly:\n * `source: \"user-toast\"`, the `[warning] ` prefix, the \"Error toast\"\n * fallback, `raw: { kind, message?, data }`). A throwing `capture` never\n * breaks the toast.\n *\n * Usage (once, in the host app):\n * import { toast as sonnerToast } from \"sonner\";\n * export const { toast, toastErrorAlreadyCaptured } =\n * createMatrxToast({ toast: sonnerToast, capture: captureError });\n */\n\nimport type { ReactNode } from \"react\";\n\n/** What sonner accepts as a toast title (structural: sonner's `titleT`). */\nexport type ToastMessage = ReactNode | (() => ReactNode);\n\n/** Structural stand-in for sonner's `ExternalToast` options bag. */\nexport interface ToastData {\n description?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * The structural surface this factory needs from the injected toast object:\n * callable, with `error` and `warning` methods. sonner's `toast` satisfies\n * this for every version this package targets. Deliberate typing choices so\n * the REAL sonner object is assignable without a cast under\n * `strictFunctionTypes`: the call signature uses `never[]` (accepts any\n * function — consumers call through their own `T`, never this signature),\n * and `error`/`warning` use METHOD syntax for bivariant parameter checks\n * against sonner's `ExternalToast`.\n */\nexport interface SonnerLikeToast {\n (...args: never[]): string | number;\n error(message: ToastMessage, data?: ToastData): string | number;\n warning(message: ToastMessage, data?: ToastData): string | number;\n}\n\n/** The payload handed to the injected capture sink — the original's shape. */\nexport interface CapturedToastInfo {\n source: \"user-toast\";\n message: string;\n userMessage: string;\n raw: {\n kind: \"error\" | \"warning\";\n message: string | undefined;\n data: ToastData | undefined;\n };\n}\n\nexport interface CreateMatrxToastOptions<T extends SonnerLikeToast> {\n /** The host's sonner `toast` object (or any structural equivalent). */\n toast: T;\n /**\n * Error-capture sink fed by `.error` / `.warning`. Omitted: no-op.\n * Must never be load-bearing — a throw here is swallowed.\n */\n capture?: (info: CapturedToastInfo) => void;\n}\n\nexport interface MatrxToast<T extends SonnerLikeToast> {\n /** Drop-in replacement for the injected `toast`, with error/warning capture. */\n toast: T;\n /**\n * Render an error toast when the originating failure was already captured\n * at its canonical boundary. Only for aggregate/derived UI notices; the\n * caller must be able to name the upstream capture seam.\n */\n toastErrorAlreadyCaptured: T[\"error\"];\n}\n\nfunction messageText(message: ToastMessage, data?: ToastData): string {\n const description =\n data && typeof data.description === \"string\" ? data.description : \"\";\n const title = typeof message === \"string\" ? message : \"\";\n return [title, description].filter(Boolean).join(\" — \") || \"Error toast\";\n}\n\n/** Build the captured toast pair around the host's sonner `toast` object. */\nexport function createMatrxToast<T extends SonnerLikeToast>({\n toast: hostToast,\n capture,\n}: CreateMatrxToastOptions<T>): MatrxToast<T> {\n if (typeof hostToast !== \"function\") {\n throw new Error(\n \"createMatrxToast: options.toast must be the sonner `toast` object (or a structural equivalent) — got \" +\n typeof hostToast,\n );\n }\n\n function captureToast(\n kind: \"error\" | \"warning\",\n message: ToastMessage,\n data?: ToastData,\n ): void {\n if (!capture) return;\n try {\n capture({\n source: \"user-toast\",\n message: `${kind === \"warning\" ? \"[warning] \" : \"\"}${messageText(message, data)}`,\n userMessage: messageText(message, data),\n raw: {\n kind,\n message: typeof message === \"string\" ? message : undefined,\n data,\n },\n });\n } catch {\n /* capture must never break the toast */\n }\n }\n\n const error: SonnerLikeToast[\"error\"] = (message, data) => {\n captureToast(\"error\", message, data);\n return hostToast.error(message, data);\n };\n\n const warning: SonnerLikeToast[\"warning\"] = (message, data) => {\n captureToast(\"warning\", message, data);\n return hostToast.warning(message, data);\n };\n\n // The constraint's call signature is `never[]` (see SonnerLikeToast), so\n // forwarding the base call goes through a widened alias of the host object.\n const forward = hostToast as unknown as (\n ...args: Parameters<T>\n ) => ReturnType<T>;\n const toast: T = Object.assign(\n ((...args: Parameters<T>) => forward(...args)) as unknown as T,\n hostToast,\n { error, warning },\n );\n\n const toastErrorAlreadyCaptured = ((\n message: ToastMessage,\n data?: ToastData,\n ) => hostToast.error(message, data)) as unknown as T[\"error\"];\n\n return { toast, toastErrorAlreadyCaptured };\n}\n","/**\n * @ai-matrx/kit/invalidation — a tiny name-keyed callback registry that lets a\n * UBIQUITOUS module (a stream processor, an effect runner) trigger cache\n * invalidation inside a HEAVY chunk cluster with ZERO import edge between them.\n *\n * WHY THIS EXISTS (the fragmentation-law incident): a module statically\n * reachable from ~every route context reached a heavy registry cluster with an\n * `await import()` — one line that added +14 GB peak build RSS / +50% compile\n * time and OOM-killed 12 straight production builds. The sanctioned shape is\n * the INVERSION implemented here: the heavy cluster registers a callback at\n * its own module init (it is always initialized wherever its output can\n * render — if the chunk never loaded, nothing stale is mounted), and the\n * ubiquitous module fires the callback by NAME. The only shared code is this\n * module, which imports nothing.\n *\n * RULES:\n * - This module must NEVER grow an import. It is in every chunk that touches\n * it; any dependency it gains is multiplied across all of them.\n * - Firing an unregistered name is a NO-OP by design, not an error — the\n * consumer chunk simply isn't loaded in this tab, so there is nothing\n * stale to invalidate.\n * - Callbacks never break the caller: each runs in its own try/catch and\n * screams to the console on failure.\n * - Key constants live in the HOST app (one shared constants module per app),\n * so producer and consumer agree on the name without importing each other.\n * The registry itself is generic over names — app-specific keys never move\n * into this package.\n *\n * Ported from matrx-frontend `lib/invalidation/invalidation-registry.ts`, with\n * ONE structural inversion: the callback map lives on `globalThis` under a\n * `Symbol.for` slot instead of a module-level variable. With the package built\n * `splitting: false` in dual ESM/CJS format, this module is duplicated into\n * the root bundle and the `./invalidation` bundle, and CJS/ESM each\n * instantiate their own module graph — a module-level Map would silently split\n * the producers from the consumers (the same hazard the confirm opener\n * documents). Behavior is unchanged; never \"clean this up\" into a module\n * local.\n */\n\nexport type InvalidationCallback = (detail?: unknown) => void;\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.invalidation-registry\");\n\ntype RegistryState = Map<string, Set<InvalidationCallback>>;\n\nfunction getCallbacks(): RegistryState {\n const holder = globalThis as Record<symbol, RegistryState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = new Map();\n holder[STATE_SLOT] = state;\n }\n return state;\n}\n\n/**\n * Register a callback for a name. Idempotent-friendly: returns the\n * unsubscribe. Module-scope registration in the consumer chunk is the\n * intended pattern (register once per chunk load, never unsubscribe).\n */\nexport function registerInvalidationCallback(\n name: string,\n callback: InvalidationCallback,\n): () => void {\n const callbacks = getCallbacks();\n let set = callbacks.get(name);\n if (!set) {\n set = new Set();\n callbacks.set(name, set);\n }\n set.add(callback);\n return () => {\n set.delete(callback);\n };\n}\n\n/**\n * Fire every callback registered under `name`. Returns true when at least one\n * callback ran. Never throws — a failing callback screams and the rest run.\n */\nexport function fireInvalidation(name: string, detail?: unknown): boolean {\n const set = getCallbacks().get(name);\n if (!set || set.size === 0) return false;\n for (const callback of set) {\n try {\n callback(detail);\n } catch (error) {\n console.error(\n `[invalidation-registry] callback for \"${name}\" threw`,\n error,\n );\n }\n }\n return true;\n}\n","/**\n * @ai-matrx/kit/delimiter-guard — stops ONE stray markdown delimiter from\n * swallowing a whole section of a streamed answer.\n *\n * THE FAILURE CLASS\n * -----------------\n * Markdown delimiters pair greedily and blindly. A single stray opener emitted\n * by a model (the common shape is a mangled citation:\n * `…/a-quicker-way-to-heal-prp-and-prf$$ .`) pairs with the next matching\n * delimiter anywhere later in the message, and everything in between —\n * headings, bold, links, whole sections — collapses into one node.\n *\n * Two delimiters cause this in a remark-math + CommonMark pipeline:\n *\n * 1. `$$` (remark-math). The swallowed prose becomes a math node, KaTeX fails\n * to parse it, and `rehype-katex` falls back to its built-in error\n * rendering: the raw source re-emitted inside `<span class=\"katex-error\"\n * style=\"color:#cc0000\">`. The symptom is a huge block of BRIGHT RED\n * unrendered markdown mid-answer. That red is KaTeX reporting a parse error\n * on text that was never math — not a style of yours.\n * 2. `[` (CommonMark link label). The swallowed prose becomes the label of one\n * enormous hyperlink — the same bug wearing blue instead of red.\n *\n * WHAT THIS DOES\n * --------------\n * Before the markdown pipeline runs, each candidate span is checked for\n * plausibility. A `$$…$$` span carrying markdown structure (links, URLs, bold,\n * headings, list markers) or reading as prose is not math; a link label that is\n * hundreds of characters long or contains block structure is not a label. The\n * offending OPENER is neutralized (`$$`, `[`) and scanning resumes at the next\n * delimiter, so genuine math and genuine links later in the same message still\n * render. Real content is never touched.\n *\n * LOUD RECOVERY: every firing is a real upstream defect (a model emitting\n * malformed delimiters, or a producer mangling a citation). Callers report the\n * returned violations — see `reportDelimiterViolations`.\n *\n * Ported verbatim from matrx-frontend `lib/markdown/delimiter-guard.ts`, with\n * ONE coupling inversion: the app's `captureError` store import became the\n * injected `capture` sink on `reportDelimiterViolations`' context (payload\n * shape preserved exactly). No sink means console-only loud recovery.\n */\n\nexport type DelimiterViolationReason =\n /** A `$$…$$` pair whose contents are prose/markdown, not math. */\n | \"prose-span\"\n /** A `$$` with no closing partner in the content. */\n | \"unpaired\"\n /** A `[…](…)` link whose label swallowed prose/structure. */\n | \"runaway-link\";\n\nexport interface DelimiterViolation {\n reason: DelimiterViolationReason;\n /** Character offset of the offending delimiter in the input string. */\n index: number;\n /** Length of the span between the delimiters (0 for `unpaired`). */\n spanLength: number;\n /** Short excerpt of what would have been swallowed. */\n preview: string;\n}\n\nexport interface DelimiterGuardResult {\n /** Input with runaway openers escaped. */\n text: string;\n violations: DelimiterViolation[];\n}\n\n/**\n * Neutralized delimiters. Two requirements drove this encoding:\n *\n * - It must be INVISIBLE in the rendered output. A backslash escape (`\\$\\$`)\n * is emitted literally when the delimiter abuts constructs remark does not\n * re-parse, so the reader sees stray backslashes.\n * - It must not be swallowed by the GFM autolink extension. These strays sit\n * right after a bare URL (that is how they are produced), and a character\n * reference placed there is absorbed into the link target instead of being\n * decoded.\n *\n * A zero-width space satisfies both: it terminates the autolink, splits the\n * `$$` token so remark-math never sees a delimiter (single `$` is inert —\n * `singleDollarTextMath: false`), and renders as nothing. The bracket keeps a\n * character reference (a lone `[` has no token to split) behind a ZWSP.\n */\nconst ZWSP = \"\\u200B\";\nconst ESCAPED_DOLLARS = `${ZWSP}$${ZWSP}$`;\nconst ESCAPED_BRACKET = `${ZWSP}[`;\n\n/** Longest span we will accept as real math when no LaTeX command is present. */\nconst MAX_MATH_SPAN = 600;\n\n/**\n * Markdown structure that can never appear inside real math:\n * a markdown link, a bare URL, bold markers, an ATX heading, or a\n * line-leading list marker.\n */\nconst STRUCTURAL_MARKDOWN =\n /\\]\\(|https?:\\/\\/|\\*\\*|(?:^|\\n)[ \\t]{0,3}#{1,6}[ \\t]|(?:^|\\n)[ \\t]*[-*+][ \\t]+|(?:^|\\n)[ \\t]*\\d+[.)][ \\t]/;\n\n/** A LaTeX control sequence (`\\frac`, `\\sim`, `\\text`, …). */\nconst LATEX_COMMAND = /\\\\[a-zA-Z]/;\n\n/** Alphabetic words of 3+ letters — the prose signal for command-free spans. */\nconst PROSE_WORD = /[A-Za-z]{3,}/g;\n\n/** Word count at which a LaTeX-command-free span is judged to be prose. */\nconst PROSE_WORD_LIMIT = 6;\n\nfunction looksLikeMath(inner: string): boolean {\n const s = inner.trim();\n if (!s) return false;\n\n // Structural markdown wins over every other signal — a swallowed prose span\n // routinely contains real LaTeX fragments (`$\\sim 200 \\text{ g}$`) picked up\n // from the sentences it ate, so the command check cannot run first.\n if (STRUCTURAL_MARKDOWN.test(s)) return false;\n\n if (s.length > MAX_MATH_SPAN) return false;\n\n // A LaTeX control sequence is strong evidence of math — but not proof: a\n // swallowed span often eats sentences that themselves contained inline math\n // (`$\\sim 400 \\text{ g}$`). Real math is symbol-dense, so a span that is\n // mostly English words is still prose.\n if (LATEX_COMMAND.test(s)) {\n return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT * 3;\n }\n\n if (/\\n[ \\t]*\\n/.test(s)) return false;\n\n return (s.match(PROSE_WORD) ?? []).length < PROSE_WORD_LIMIT;\n}\n\n/** Ranges (fenced blocks, inline code) whose `$$` must be ignored. */\nfunction protectedRanges(text: string): Array<[number, number]> {\n const ranges: Array<[number, number]> = [];\n const patterns = [/```[\\s\\S]*?(?:```|$)/g, /~~~[\\s\\S]*?(?:~~~|$)/g, /`[^`\\n]*`/g];\n for (const re of patterns) {\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n ranges.push([m.index, m.index + m[0].length]);\n }\n }\n return ranges;\n}\n\nfunction isProtected(index: number, ranges: Array<[number, number]>): boolean {\n return ranges.some(([start, end]) => index >= start && index < end);\n}\n\nfunction preview(text: string, max = 160): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max)}…` : flat;\n}\n\n/**\n * Escapes `$$` delimiters that would make remark-math swallow non-math text.\n * Pure — safe to call on every render / stream chunk.\n */\nexport function guardMathDelimiters(text: string): DelimiterGuardResult {\n if (!text.includes(\"$$\")) return { text, violations: [] };\n\n const ranges = protectedRanges(text);\n\n // Collect `$$` offsets outside code.\n const tokens: number[] = [];\n for (let i = 0; i < text.length - 1; i++) {\n if (text[i] !== \"$\" || text[i + 1] !== \"$\") continue;\n if (!isProtected(i, ranges)) tokens.push(i);\n i++; // never treat the second `$` of a pair as a new opener\n }\n if (tokens.length === 0) return { text, violations: [] };\n\n const violations: DelimiterViolation[] = [];\n const escapeAt: number[] = [];\n\n let j = 0;\n while (j < tokens.length) {\n // Bounded by the loop condition — `tokens[j]` always exists here.\n const open = tokens[j] as number;\n const close = tokens[j + 1];\n\n if (close === undefined) {\n violations.push({\n reason: \"unpaired\",\n index: open,\n spanLength: 0,\n // An unpaired `$$` is inert to remark-math (nothing closes it), so it\n // is reported but NOT escaped — it already renders as literal text.\n preview: preview(text.slice(open, open + 120)),\n });\n break;\n }\n\n const inner = text.slice(open + 2, close);\n if (looksLikeMath(inner)) {\n j += 2;\n continue;\n }\n\n escapeAt.push(open);\n violations.push({\n reason: \"prose-span\",\n index: open,\n spanLength: inner.length,\n preview: preview(inner),\n });\n // Resume at the closing delimiter: it may legitimately open the NEXT span.\n j += 1;\n }\n\n let guarded = text;\n for (const index of [...escapeAt].sort((a, b) => b - a)) {\n guarded = `${guarded.slice(0, index)}${ESCAPED_DOLLARS}${guarded.slice(index + 2)}`;\n }\n\n return { text: guarded, violations };\n}\n\n/** Longest link label we accept before calling it a runaway. */\nconst MAX_LINK_LABEL = 200;\n\n/**\n * Block structure that can never legitimately sit inside a link label:\n * a blank line, a list item on its own line, or an ATX heading marker\n * (`## `…`#### `) anywhere — a heading inside a label always means the label\n * ran past its intended end.\n */\nconst LABEL_BLOCK_STRUCTURE =\n /\\n[ \\t]*\\n|(?:^|\\n)[ \\t]*[-*+][ \\t]+|#{2,6}[ \\t]/;\n\n/**\n * Escapes the `[` of a markdown link whose label ran away — the link twin of\n * the stray-`$$` bug. An unclosed citation bracket pairs with a `]` hundreds of\n * characters later and turns an entire section into one hyperlink.\n *\n * Pure. Runs after the math guard so both share one escaping pass conceptually,\n * but each is independently usable.\n */\nexport function guardRunawayLinks(text: string): DelimiterGuardResult {\n if (!text.includes(\"[\")) return { text, violations: [] };\n\n const ranges = protectedRanges(text);\n const violations: DelimiterViolation[] = [];\n const escapeAt: number[] = [];\n\n // `[label](target)` — label is non-greedy but may span newlines, which is\n // exactly the runaway shape we are looking for.\n const linkRe = /\\[((?:[^[\\]]|\\\\.)*)\\]\\(([^\\s)]*)/g;\n let m: RegExpExecArray | null;\n while ((m = linkRe.exec(text)) !== null) {\n const open = m.index;\n if (isProtected(open, ranges)) continue;\n\n const label = m[1] ?? \"\";\n const runaway =\n label.length > MAX_LINK_LABEL || LABEL_BLOCK_STRUCTURE.test(label);\n if (!runaway) continue;\n\n escapeAt.push(open);\n violations.push({\n reason: \"runaway-link\",\n index: open,\n spanLength: label.length,\n preview: preview(label),\n });\n }\n\n let guarded = text;\n for (const index of [...escapeAt].sort((a, b) => b - a)) {\n guarded = `${guarded.slice(0, index)}${ESCAPED_BRACKET}${guarded.slice(index + 1)}`;\n }\n\n return { text: guarded, violations };\n}\n\n/**\n * The front door: run every delimiter guard in order. Offsets in the returned\n * violations refer to each guard's own input, so they are for diagnostics only.\n */\nexport function guardMarkdownDelimiters(text: string): DelimiterGuardResult {\n const math = guardMathDelimiters(text);\n const links = guardRunawayLinks(math.text);\n return {\n text: links.text,\n violations: [...math.violations, ...links.violations],\n };\n}\n\n/**\n * The payload handed to the injected capture sink — exactly the shape the\n * original passed to the Matrx `captureError` store. A Matrx host passes\n * `captureError` straight through; any host can log/report it its own way.\n */\nexport interface DelimiterCaptureInput {\n source: \"markdown-delimiters\";\n message: string;\n relation: string;\n details: string;\n conversationId?: string | undefined;\n callSite: \"guardMarkdownDelimiters\";\n raw: { messageId?: string | undefined; violations: DelimiterViolation[] };\n}\n\nexport interface DelimiterReportContext {\n renderPath: string;\n messageId?: string | undefined;\n conversationId?: string | undefined;\n /**\n * Optional error-capture sink (a Matrx host passes its `captureError`).\n * Absent, the loud recovery is console-only. Must never be relied on to\n * throw — failures inside it are swallowed so capture can never break\n * rendering.\n */\n capture?: ((input: DelimiterCaptureInput) => void) | undefined;\n}\n\n/**\n * Loud recovery. A firing means malformed math delimiters reached the renderer\n * — the guard kept the message readable, but the producer is still emitting\n * broken content and must be found.\n */\nexport function reportDelimiterViolations(\n violations: DelimiterViolation[],\n context: DelimiterReportContext,\n): void {\n if (violations.length === 0) return;\n try {\n const worst =\n violations.find((v) => v.reason !== \"unpaired\") ?? violations[0];\n if (!worst) return;\n const message =\n worst.reason === \"prose-span\"\n ? `Malformed math delimiters: a stray \"$$\" would have turned ${worst.spanLength} chars of prose into a math span (KaTeX would render it as red error text). Escaped it.`\n : worst.reason === \"runaway-link\"\n ? `Runaway markdown link: an unclosed \"[\" would have turned ${worst.spanLength} chars into one link label. Escaped it.`\n : `Malformed math delimiters: an unpaired \"$$\" reached the renderer.`;\n\n // Loud recovery: this is a defect being reported, not noise.\n console.warn(`[markdown-delimiter-guard] ${message}`, {\n renderPath: context.renderPath,\n violations,\n });\n\n context.capture?.({\n source: \"markdown-delimiters\",\n message,\n relation: `markdown:${context.renderPath}`,\n details: worst.preview,\n conversationId: context.conversationId,\n callSite: \"guardMarkdownDelimiters\",\n raw: { messageId: context.messageId, violations },\n });\n } catch {\n // Capture must never break rendering.\n }\n}\n","// json-format/detect.ts\n//\n// \"Is this text JSON, and where exactly does the JSON start and stop?\"\n//\n// The answer has to survive real-world selections: a fenced ```json block, a\n// bare pasted object, an object with a stray blank line above it, a fence the\n// user only half-selected. So detection splits the text into three parts —\n// leading / payload / trailing — and only the payload is ever re-formatted.\n// Everything outside it is restored verbatim, because a formatter that eats\n// the prose around the JSON is worse than no formatter at all.\n//\n// Two parse tiers: `JSON.parse` first (strict — what the value really is), then\n// JSON5 (tolerant — trailing commas, comments, unquoted keys, single quotes),\n// because the JSON people paste out of logs and code is frequently not legal\n// JSON. Tolerant parsing is reported, never hidden: a consumer that re-emits a\n// tolerantly-parsed value is normalizing it, and the caller can say so.\n//\n// Pure: no React / DOM. Never throws.\n//\n// Ported verbatim from matrx-frontend `lib/json-format/detect.ts`.\n\nimport JSON5 from \"json5\";\nimport type { JsonValue } from \"./json-value\";\nimport type {\n JsonDetection,\n JsonFence,\n JsonParser,\n JsonRootKind,\n} from \"./types\";\n\n/** Opening fence line: optional indent, 3+ backticks or tildes, optional info. */\nconst FENCE_OPEN = /^([ \\t]*)(`{3,}|~{3,})[ \\t]*([^\\s`~]*)[ \\t]*$/;\n\n/** Languages we treat as \"this fence contains JSON\". */\nconst JSON_FENCE_LANGS = new Set([\"json\", \"jsonc\", \"json5\", \"geojson\", \"jsonl\"]);\n\ninterface Split {\n leading: string;\n payload: string;\n trailing: string;\n fence: JsonFence | null;\n}\n\n/** Peel a markdown code fence off the text, if the text IS a fenced block. */\nfunction splitFence(text: string): Split | null {\n const lines = text.split(\"\\n\");\n\n // The fence may sit anywhere in the selection (a user highlighting a block\n // plus the sentence above it is the common case) — but there must be exactly\n // ONE block. Two fenced blocks in one selection is not a single JSON payload,\n // and spanning them would splice unrelated content together.\n const openIdx = lines.findIndex((l) => FENCE_OPEN.test(l));\n if (openIdx === -1) return null;\n\n const open = FENCE_OPEN.exec(lines[openIdx] ?? \"\");\n if (!open) return null;\n const [, indent = \"\", marker = \"```\", lang = \"\"] = open;\n const fenceChar = marker[0] ?? \"`\";\n const closeRe = new RegExp(`^[ \\\\t]*\\\\${fenceChar}{${marker.length},}[ \\\\t]*$`);\n\n let closeIdx = -1;\n for (let i = openIdx + 1; i < lines.length; i++) {\n if (closeRe.test(lines[i] ?? \"\")) {\n closeIdx = i;\n break;\n }\n }\n\n const afterClose = closeIdx === -1 ? [] : lines.slice(closeIdx + 1);\n if (afterClose.some((l) => FENCE_OPEN.test(l))) return null;\n\n const bodyEnd = closeIdx === -1 ? lines.length : closeIdx;\n // The line separators bordering the fence belong to leading/trailing, so\n // reassembly is a plain concatenation and blank lines survive it.\n return {\n leading: openIdx > 0 ? `${lines.slice(0, openIdx).join(\"\\n\")}\\n` : \"\",\n payload: lines.slice(openIdx + 1, bodyEnd).join(\"\\n\"),\n trailing: afterClose.length > 0 ? `\\n${afterClose.join(\"\\n\")}` : \"\",\n fence: {\n marker,\n lang: lang.toLowerCase(),\n indent,\n closed: closeIdx !== -1,\n },\n };\n}\n\n/** Split bare (unfenced) text into surrounding whitespace + payload. */\nfunction splitBare(text: string): Split {\n const payload = text.trim();\n if (payload === \"\") {\n return { leading: text, payload: \"\", trailing: \"\", fence: null };\n }\n const start = text.indexOf(payload);\n return {\n leading: text.slice(0, start),\n payload,\n trailing: text.slice(start + payload.length),\n fence: null,\n };\n}\n\nfunction rootKindOf(value: JsonValue): JsonRootKind {\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\" && value !== null) return \"object\";\n return \"scalar\";\n}\n\n/** Bracket-shaped: opens and closes with a matching container delimiter. */\nfunction isBracketShaped(payload: string): boolean {\n const first = payload[0];\n const last = payload[payload.length - 1];\n if (payload.length < 2) return false;\n return (first === \"{\" && last === \"}\") || (first === \"[\" && last === \"]\");\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : \"Invalid JSON\";\n}\n\nfunction countLines(s: string): number {\n if (s === \"\") return 0;\n let n = 1;\n for (let i = 0; i < s.length; i++) if (s[i] === \"\\n\") n++;\n return n;\n}\n\n/**\n * Detect JSON in `text`. Never throws; a non-JSON string comes back with\n * `ok: false` and `looksLikeJson: false`, which is the signal to offer nothing.\n */\nexport function detectJson(text: string): JsonDetection {\n const split = splitFence(text) ?? splitBare(text);\n // A fenced block's body still carries its own indentation/blank lines.\n const payload = split.fence ? split.payload.trim() : split.payload;\n\n const fenceSaysJson =\n split.fence !== null &&\n (split.fence.lang === \"\" || JSON_FENCE_LANGS.has(split.fence.lang));\n\n const base = {\n fence: split.fence,\n leading: split.leading,\n trailing: split.trailing,\n payload,\n lineCount: countLines(payload),\n charCount: payload.length,\n };\n\n if (payload === \"\") {\n return { ...base, ok: false, looksLikeJson: false };\n }\n\n // A fence declaring a NON-JSON language is a hard no, even if the body would\n // parse — reformatting the inside of a ```python block is not our business.\n if (split.fence !== null && !fenceSaysJson) {\n return { ...base, ok: false, looksLikeJson: false };\n }\n\n const shaped = isBracketShaped(payload);\n\n let value: JsonValue | undefined;\n let parser: JsonParser | undefined;\n let error: string | undefined;\n try {\n value = JSON.parse(payload) as JsonValue;\n parser = \"strict\";\n } catch (strictErr) {\n try {\n value = JSON5.parse(payload) as JsonValue;\n parser = \"tolerant\";\n } catch {\n error = errorMessage(strictErr);\n }\n }\n\n if (value === undefined || parser === undefined) {\n // Unparseable. Still \"looks like JSON\" when it is bracket-shaped, so a\n // surface can show the actions and report the parse error on click rather\n // than pretending the selection is ordinary prose.\n return { ...base, ok: false, looksLikeJson: shaped, error };\n }\n\n const root = rootKindOf(value);\n // A bare scalar (\"hello\", 42, true) parses but is not worth offering JSON\n // actions on — every prose word that happens to be a number would qualify.\n const worthOffering = root !== \"scalar\" || fenceSaysJson;\n\n return { ...base, ok: true, looksLikeJson: worthOffering, value, parser, root };\n}\n","/**\n * Canonical JSON value types + narrowing guards.\n *\n * Ported (the subset this subpath needs) from matrx-frontend `types/json.ts` —\n * the honest names for \"this is just JSON\" that are NOT `any` and NOT a bare\n * `unknown`. The package must stand alone, so the types live here; a Matrx\n * host keeps using its own `@/types/json` for app code and the two are\n * structurally identical.\n */\n\nexport type JsonPrimitive = string | number | boolean | null;\n\n/**\n * A JSON object. Values are `JsonValue | undefined` so optional keys read\n * cleanly (mirrors Supabase's original generated `Json` object member).\n */\nexport interface JsonObject {\n [key: string]: JsonValue | undefined;\n}\n\nexport type JsonArray = JsonValue[];\n\nexport type JsonValue = JsonPrimitive | JsonObject | JsonArray;\n\n/**\n * Narrow an `unknown` (e.g. a bare JSONB column) to a `JsonObject`.\n * Plain object only — arrays and `null` return false.\n */\nexport function isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Narrow an `unknown` to a `JsonArray`. */\nexport function isJsonArray(value: unknown): value is JsonArray {\n return Array.isArray(value);\n}\n\n/** Narrow an `unknown` to a JSON primitive (string | number | boolean | null). */\nexport function isJsonPrimitive(value: unknown): value is JsonPrimitive {\n return (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n","// json-format/format.ts\n//\n// The JSON writer. Three styles over one recursive printer:\n//\n// minify — one line, no optional whitespace.\n// compact — width-aware FILL. Any subtree whose flat form fits the remaining\n// columns is inlined; a subtree that does not fit expands, but its\n// children are then PACKED onto shared lines while they fit. This\n// is what turns an 11-line reference blob into 3 lines without\n// turning it into an unreadable one-liner.\n// pretty — one entry per line (classic 2-space JSON).\n//\n// Why not `JSON.stringify(v, null, 2)`: it cannot inline, cannot pack, and\n// cannot sort keys. All three are the point.\n//\n// Pure: no React / DOM. Never throws — a parse failure comes back as a result\n// with `ok: false` and the input text unchanged.\n//\n// Ported verbatim from matrx-frontend `lib/json-format/format.ts`.\n\nimport type { JsonObject, JsonValue } from \"./json-value\";\nimport { isJsonArray, isJsonObject } from \"./json-value\";\nimport { detectJson } from \"./detect\";\nimport type {\n JsonDetection,\n JsonFormatOptions,\n JsonFormatResult,\n JsonTextSize,\n} from \"./types\";\n\nexport const DEFAULT_JSON_INDENT = 2;\nexport const DEFAULT_JSON_WIDTH = 100;\n\ninterface WriterConfig {\n indent: number;\n /** Target line width; `-1` disables inlining entirely (pretty). */\n width: number;\n /** Pack sibling entries onto shared lines (compact only). */\n pack: boolean;\n /** Spaces inside braces/brackets and after colons/commas. */\n spaced: boolean;\n sortKeys: boolean;\n}\n\nfunction orderedKeys(obj: JsonObject, sortKeys: boolean): string[] {\n // `undefined` values are not JSON — JSON.stringify drops them, so do we.\n const keys = Object.keys(obj).filter((k) => obj[k] !== undefined);\n return sortKeys ? [...keys].sort((a, b) => a.localeCompare(b)) : keys;\n}\n\n/** Serialize a scalar exactly as JSON does. */\nfunction writeScalar(value: JsonValue): string {\n // NaN / Infinity stringify to \"null\", matching JSON.stringify.\n return JSON.stringify(value) ?? \"null\";\n}\n\n/** The whole subtree on one line. */\nfunction flatten(value: JsonValue, cfg: WriterConfig): string {\n if (isJsonArray(value)) {\n if (value.length === 0) return \"[]\";\n const parts = value.map((v) => flatten(v ?? null, cfg));\n return cfg.spaced ? `[${parts.join(\", \")}]` : `[${parts.join(\",\")}]`;\n }\n if (isJsonObject(value)) {\n const keys = orderedKeys(value, cfg.sortKeys);\n if (keys.length === 0) return \"{}\";\n const colon = cfg.spaced ? \": \" : \":\";\n const parts = keys.map(\n (k) => `${JSON.stringify(k)}${colon}${flatten(value[k] ?? null, cfg)}`,\n );\n return cfg.spaced ? `{ ${parts.join(\", \")} }` : `{${parts.join(\",\")}}`;\n }\n return writeScalar(value);\n}\n\n/**\n * Lay out `entries` (already-rendered child texts) inside a container.\n * Single-line entries are packed together while they fit; a multi-line entry\n * always occupies its own line(s). Returns the body lines, unindented-prefixed\n * with `pad` already applied.\n */\nfunction layoutEntries(\n entries: string[],\n pad: string,\n cfg: WriterConfig,\n): string[] {\n if (!cfg.pack) return entries.map((e) => pad + e);\n\n const lines: string[] = [];\n let current = \"\";\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i] ?? \"\";\n const isLast = i === entries.length - 1;\n const piece = isLast ? entry : `${entry},`;\n\n if (entry.includes(\"\\n\")) {\n // Multi-line child: flush whatever is buffered, then stand alone.\n if (current !== \"\") {\n lines.push(pad + current);\n current = \"\";\n }\n lines.push(pad + piece);\n continue;\n }\n\n if (current === \"\") {\n current = piece;\n continue;\n }\n const merged = `${current} ${piece}`;\n if (pad.length + merged.length <= cfg.width) {\n current = merged;\n } else {\n lines.push(pad + current);\n current = piece;\n }\n }\n if (current !== \"\") lines.push(pad + current);\n return lines;\n}\n\n/**\n * Render `value` starting at column `used` on its current line, at nesting\n * `level`. `used` includes the indentation AND any key prefix already written,\n * so the width budget is honest about `\"items\": [` style prefixes.\n */\nfunction renderNode(\n value: JsonValue,\n level: number,\n used: number,\n cfg: WriterConfig,\n): string {\n const isContainer = isJsonArray(value) || isJsonObject(value);\n if (!isContainer) return writeScalar(value);\n\n const flat = flatten(value, cfg);\n if (flat === \"[]\" || flat === \"{}\") return flat;\n if (cfg.width >= 0 && used + flat.length <= cfg.width) return flat;\n\n const pad = \" \".repeat((level + 1) * cfg.indent);\n const closePad = \" \".repeat(level * cfg.indent);\n\n if (isJsonArray(value)) {\n const entries = value.map((v) =>\n renderNode(v ?? null, level + 1, pad.length, cfg),\n );\n const body = layoutEntries(entries, pad, cfg);\n const joined = cfg.pack ? body.join(\"\\n\") : body.join(\",\\n\");\n return `[\\n${joined}\\n${closePad}]`;\n }\n\n const keys = orderedKeys(value, cfg.sortKeys);\n const entries = keys.map((k) => {\n const prefix = `${JSON.stringify(k)}: `;\n const rendered = renderNode(\n value[k] ?? null,\n level + 1,\n pad.length + prefix.length,\n cfg,\n );\n return prefix + rendered;\n });\n const body = layoutEntries(entries, pad, cfg);\n const joined = cfg.pack ? body.join(\"\\n\") : body.join(\",\\n\");\n return `{\\n${joined}\\n${closePad}}`;\n}\n\n/**\n * Serialize a JSON value in one of the three styles. This is the entry point\n * for callers that already HAVE a value (a DB JSONB blob, an API frame) and\n * just want it laid out; text callers want {@link formatJsonText}.\n */\nexport function stringifyJson(\n value: JsonValue,\n options: JsonFormatOptions,\n): string {\n const indent = options.indent ?? DEFAULT_JSON_INDENT;\n const sortKeys = options.sortKeys ?? false;\n\n if (options.style === \"minify\") {\n return flatten(value, { indent, width: -1, pack: false, spaced: false, sortKeys });\n }\n\n const cfg: WriterConfig = {\n indent,\n width: options.style === \"pretty\" ? -1 : (options.width ?? DEFAULT_JSON_WIDTH),\n pack: options.style === \"compact\",\n spaced: true,\n sortKeys,\n };\n return renderNode(value, 0, 0, cfg);\n}\n\nfunction sizeOf(text: string): JsonTextSize {\n let lines = text === \"\" ? 0 : 1;\n for (let i = 0; i < text.length; i++) if (text[i] === \"\\n\") lines++;\n return { lines, chars: text.length };\n}\n\n/** Re-assemble the full text: leading + fence + formatted payload + trailing. */\nfunction reassemble(\n detection: JsonDetection,\n payload: string,\n mode: NonNullable<JsonFormatOptions[\"fence\"]>,\n): string {\n const { fence, leading, trailing } = detection;\n\n const keepFence =\n mode === \"add\" || (mode === \"preserve\" && fence !== null);\n if (!keepFence) {\n return leading + payload + trailing;\n }\n\n const marker = fence?.marker ?? \"```\";\n const lang = fence?.lang && fence.lang !== \"\" ? fence.lang : \"json\";\n const indent = fence?.indent ?? \"\";\n const body = indent\n ? payload\n .split(\"\\n\")\n .map((l) => (l === \"\" ? l : indent + l))\n .join(\"\\n\")\n : payload;\n\n // An unterminated source fence stays unterminated — inventing a closing fence\n // would change the surrounding document's structure, not just this block's.\n const close = fence !== null && !fence.closed ? \"\" : `\\n${indent}${marker}`;\n return `${leading}${indent}${marker}${lang}\\n${body}${close}${trailing}`;\n}\n\n/**\n * Format the JSON found in `text`, preserving everything around it.\n *\n * Never throws. When the text does not parse, the result is `ok: false`,\n * `changed: false`, and `text` is the input verbatim — a formatter that\n * mangles text it did not understand is a data-loss bug.\n */\nexport function formatJsonText(\n text: string,\n options: JsonFormatOptions,\n): JsonFormatResult {\n const detection = detectJson(text);\n const before = sizeOf(text);\n\n if (!detection.ok || detection.value === undefined) {\n return {\n ok: false,\n text,\n error: detection.error ?? \"Selection is not JSON.\",\n changed: false,\n detection,\n before,\n after: before,\n };\n }\n\n const payload = stringifyJson(detection.value, options);\n const next = reassemble(detection, payload, options.fence ?? \"preserve\");\n\n return {\n ok: true,\n text: next,\n changed: next !== text,\n detection,\n before,\n after: sizeOf(next),\n };\n}\n","/**\n * IdleScheduler — a priority-aware deferred execution system for browser apps.\n *\n * Architecture:\n * - Process-wide singleton (NOT React context) — registrations cause zero re-renders\n * - Components register lightweight callbacks with priority 1-5\n * - The scheduler waits for the browser to be truly idle after full page render\n * - Then flushes all registered callbacks in priority order\n *\n * Priority levels:\n * 1 = Highest (first of the \"last things\") — e.g., analytics init, critical measurements\n * 2 = High — e.g., prefetching next-page data, service worker registration\n * 3 = Normal — e.g., lazy-loading non-critical UI, initializing 3rd party widgets\n * 4 = Low — e.g., telemetry, background sync setup\n * 5 = Lowest (absolute last) — e.g., prewarming caches, speculative prefetch\n *\n * Cross-browser idle detection chain:\n * document.readyState === 'complete'\n * → requestAnimationFrame (past next paint)\n * → scheduler.postTask({ priority: 'background' }) [Chrome/Edge/Firefox 142+]\n * → requestIdleCallback [Chrome/Firefox, NOT Safari]\n * → MessageChannel postMessage [Universal — React's own trick]\n *\n * Ported from matrx-frontend `utils/idle-scheduler/idle-scheduler.ts`, with\n * TWO structural inversions, behavior otherwise verbatim:\n * - Scheduler state (queue, flush state, cleanups, listeners) lives on\n * `globalThis` under `Symbol.for(\"ai-matrx.kit.idle-scheduler-state\")`\n * instead of module-level variables. With the package built\n * `splitting: false` in dual ESM/CJS format this module is duplicated into\n * the root and `./idle-scheduler` bundles, and CJS/ESM each instantiate\n * their own module graph — module-level state would silently split the\n * flush pipeline from some registrants (the confirm-opener hazard). Never\n * \"clean this up\" into module locals.\n * - The `window.__idleSched()` diagnostics probe installs on first API use\n * instead of at module evaluation, keeping every entry point import-time\n * inert (the package standard). The probe itself is unchanged.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type IdlePriority = 1 | 2 | 3 | 4 | 5;\n\nexport interface IdleRegistration {\n /** Unique key for deduplication and cancellation */\n key: string;\n /** 1 = highest (first to run), 5 = lowest (last to run) */\n priority: IdlePriority;\n /** The deferred work */\n callback: () => void | Promise<void>;\n}\n\nexport type UnregisterFn = () => void;\n\nexport type FlushState = \"idle\" | \"waiting\" | \"flushing\" | \"done\";\n\n/** Experimental Scheduler API (Chrome/Edge/Firefox 142+) — not yet in standard lib types. */\ninterface GlobalThisWithScheduler {\n scheduler?: {\n postTask: (callback: () => void, options?: { priority: string }) => Promise<void>;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Singleton state — on globalThis so every bundle graph shares ONE pipeline\n// ---------------------------------------------------------------------------\n\ninterface SchedulerState {\n queue: Map<string, IdleRegistration>;\n flushState: FlushState;\n cleanupFns: Array<() => void>;\n /** Listeners that want to know when flush completes (for useIdleReady) */\n flushListeners: Set<() => void>;\n}\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.idle-scheduler-state\");\n\nfunction getState(): SchedulerState {\n const holder = globalThis as Record<symbol, SchedulerState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = {\n queue: new Map(),\n flushState: \"idle\",\n cleanupFns: [],\n flushListeners: new Set(),\n };\n holder[STATE_SLOT] = state;\n\n // Diagnostics probe: lets a console / agent read the live scheduler state\n // (`window.__idleSched()`) — the wrapper-never-mounts class of bug is\n // invisible without it.\n if (typeof window !== \"undefined\") {\n (window as unknown as { __idleSched?: () => unknown }).__idleSched =\n getSchedulerState;\n }\n }\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Register a callback to run after the page is fully idle.\n *\n * - If the scheduler hasn't flushed yet: queues the callback.\n * - If the scheduler already flushed: runs the callback immediately\n * (through the same idle detection chain, so it still won't block).\n *\n * Returns an unregister function for cleanup.\n */\nexport function registerIdleTask(\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n): UnregisterFn {\n const state = getState();\n\n // If we already flushed, schedule this one immediately (still deferred)\n if (state.flushState === \"done\") {\n scheduleImmediate(callback);\n return () => {};\n }\n\n state.queue.set(key, { key, priority, callback });\n\n // Ensure the flush pipeline is started\n if (state.flushState === \"idle\") {\n startFlushPipeline(state);\n }\n\n return () => {\n state.queue.delete(key);\n };\n}\n\n/**\n * Subscribe to the flush-complete event.\n * Useful for components that just need a \"ready\" signal without registering work.\n */\nexport function onFlushComplete(listener: () => void): UnregisterFn {\n const state = getState();\n\n if (state.flushState === \"done\") {\n // Already flushed — notify immediately (but async to avoid sync side effects)\n queueMicrotask(listener);\n return () => {};\n }\n\n state.flushListeners.add(listener);\n\n // A \"tell me when idle\" subscriber needs the pipeline RUNNING. If only\n // registerIdleTask started it, then on pages where nothing registered an\n // idle task the flush would never run and every ready-gated mount would\n // stay dormant forever. Subscribing must start the pipeline too.\n if (state.flushState === \"idle\") {\n startFlushPipeline(state);\n }\n\n return () => {\n state.flushListeners.delete(listener);\n };\n}\n\n/**\n * Resolve after the initial page-load idle flush, or earlier when aborted.\n * Non-React startup services use this instead of recreating the scheduler's\n * load → paint → browser-idle detection chain.\n *\n * @returns false when the caller aborted before idle; true otherwise.\n */\nexport function whenPageIdle(signal?: AbortSignal): Promise<boolean> {\n if (signal?.aborted) return Promise.resolve(false);\n\n return new Promise((resolve) => {\n let settled = false;\n let unsubscribe: UnregisterFn = () => {};\n\n const finish = (ready: boolean) => {\n if (settled) return;\n settled = true;\n unsubscribe();\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ready);\n };\n const onAbort = () => finish(false);\n\n unsubscribe = onFlushComplete(() => finish(true));\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Get current state — useful for debugging or conditional logic.\n */\nexport function getSchedulerState(): {\n flushState: FlushState;\n pendingCount: number;\n pendingKeys: string[];\n} {\n const state = getState();\n return {\n flushState: state.flushState,\n pendingCount: state.queue.size,\n pendingKeys: Array.from(state.queue.keys()),\n };\n}\n\n/**\n * Reset the scheduler — primarily for testing or hot-reload scenarios.\n */\nexport function resetScheduler(): void {\n const state = getState();\n state.cleanupFns.forEach((fn) => fn());\n state.cleanupFns = [];\n state.queue.clear();\n state.flushListeners.clear();\n state.flushState = \"idle\";\n}\n\n// ---------------------------------------------------------------------------\n// Flush pipeline\n// ---------------------------------------------------------------------------\n\nfunction startFlushPipeline(state: SchedulerState): void {\n if (typeof window === \"undefined\") return; // SSR guard\n\n state.flushState = \"waiting\";\n\n const waitForLoad = () => {\n if (document.readyState === \"complete\") {\n waitForPaint();\n } else {\n const onLoad = () => waitForPaint();\n window.addEventListener(\"load\", onLoad, { once: true });\n state.cleanupFns.push(() => window.removeEventListener(\"load\", onLoad));\n }\n };\n\n const waitForPaint = () => {\n // requestAnimationFrame NEVER fires while the tab is hidden (background\n // tab, restored session, headless browser) — waiting on it alone hangs the\n // whole pipeline forever in that state, so every ready-gated mount stays\n // dormant. Paint alignment is an optimization, not a correctness\n // requirement: race the rAF against a timeout so a hidden tab still\n // flushes.\n let advanced = false;\n const advance = () => {\n if (advanced) return;\n advanced = true;\n waitForIdle();\n };\n const rafId = requestAnimationFrame(advance);\n const timeoutId = setTimeout(\n advance,\n document.visibilityState === \"hidden\" ? 250 : 1_500,\n );\n state.cleanupFns.push(() => {\n cancelAnimationFrame(rafId);\n clearTimeout(timeoutId);\n });\n };\n\n const waitForIdle = () => {\n // Tier 1: scheduler.postTask with background priority (Chrome/Edge/Firefox 142+)\n const schedulerGlobal = (globalThis as GlobalThisWithScheduler).scheduler;\n if (schedulerGlobal && \"postTask\" in schedulerGlobal) {\n schedulerGlobal\n .postTask(() => void flush(state), { priority: \"background\" })\n .catch(() => {});\n return;\n }\n\n // Tier 2: requestIdleCallback (Chrome, Firefox — NOT Safari stable)\n if (\"requestIdleCallback\" in window) {\n const idleId = requestIdleCallback(() => void flush(state));\n state.cleanupFns.push(() => cancelIdleCallback(idleId));\n return;\n }\n\n // Tier 3: MessageChannel — universal, including Safari + iOS Safari\n // This is what React's scheduler uses internally.\n const channel = new MessageChannel();\n channel.port1.onmessage = () => void flush(state);\n channel.port2.postMessage(undefined);\n };\n\n waitForLoad();\n}\n\nasync function flush(state: SchedulerState): Promise<void> {\n if (state.flushState === \"done\" || state.flushState === \"flushing\") return;\n state.flushState = \"flushing\";\n\n // Sort by priority (1 first, 5 last), stable sort preserving insertion order within priority\n const sorted = Array.from(state.queue.values()).sort(\n (a, b) => a.priority - b.priority,\n );\n\n // Clear the queue before executing (so late registrations during flush\n // are treated as \"post-flush\" and get scheduled immediately)\n state.queue.clear();\n\n for (const task of sorted) {\n try {\n await task.callback();\n } catch (err) {\n console.error(`[IdleScheduler] Task \"${task.key}\" failed:`, err);\n }\n }\n\n state.flushState = \"done\";\n\n // DEFECT FIX vs the original (see CHANGELOG 0.4.0): a task registered WHILE\n // the flush loop was running (flushState === \"flushing\") landed back in the\n // queue — which nothing ever drained again, so the task silently never ran.\n // The comment above promises such registrations are \"treated as post-flush\n // and get scheduled immediately\"; make that true.\n if (state.queue.size > 0) {\n const late = Array.from(state.queue.values()).sort(\n (a, b) => a.priority - b.priority,\n );\n state.queue.clear();\n for (const task of late) scheduleImmediate(task.callback);\n }\n\n // Notify all listeners\n state.flushListeners.forEach((listener) => {\n try {\n listener();\n } catch (err) {\n console.error(\"[IdleScheduler] Flush listener failed:\", err);\n }\n });\n state.flushListeners.clear();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Schedule a single callback through the idle chain (for post-flush registrations) */\nfunction scheduleImmediate(callback: () => void | Promise<void>): void {\n requestAnimationFrame(() => {\n const schedulerGlobal = (globalThis as GlobalThisWithScheduler).scheduler;\n if (schedulerGlobal && \"postTask\" in schedulerGlobal) {\n schedulerGlobal\n .postTask(() => void callback(), { priority: \"background\" })\n .catch(() => {});\n return;\n }\n if (\"requestIdleCallback\" in window) {\n requestIdleCallback(() => void callback());\n return;\n }\n const channel = new MessageChannel();\n channel.port1.onmessage = () => void callback();\n channel.port2.postMessage(undefined);\n });\n}\n","/**\n * React hooks for the IdleScheduler.\n *\n * These are intentionally thin — they just wire up registration/cleanup\n * to React's lifecycle. No state, no context, no re-renders on registration.\n *\n * Three hooks for three use cases:\n *\n * 1. useIdleTask(key, priority, callback)\n * → \"Run this callback when idle. I don't need to know when.\"\n * → Fire-and-forget. Zero re-renders.\n *\n * 2. useIdleReady()\n * → \"Just tell me when idle flush is done so I can wake up.\"\n * → Returns a boolean. One re-render: false → true.\n *\n * 3. useIdleGate(key, priority, callback)\n * → \"Run this callback when idle AND tell me when it's done.\"\n * → Returns { ready: boolean }. Combines both patterns.\n *\n * Plus useIdleRegister() for imperative/conditional registration.\n *\n * Ported verbatim from matrx-frontend `utils/idle-scheduler/hooks.ts`.\n */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useCallback } from \"react\";\nimport {\n registerIdleTask,\n onFlushComplete,\n type IdlePriority,\n} from \"./scheduler\";\n\n// ---------------------------------------------------------------------------\n// useIdleTask — fire-and-forget deferred work\n// ---------------------------------------------------------------------------\n\n/**\n * Register a callback to execute after page idle. Zero re-renders.\n *\n * @param key Unique identifier (for deduplication/cancellation)\n * @param priority 1 (first of last) through 5 (absolute last)\n * @param callback The deferred work\n *\n * @example\n * ```tsx\n * useIdleTask('analytics-init', 3, () => {\n * initializeAnalytics();\n * });\n * ```\n */\nexport function useIdleTask(\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n): void {\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n const unregister = registerIdleTask(key, priority, () => {\n return callbackRef.current();\n });\n return unregister;\n }, [key, priority]);\n}\n\n// ---------------------------------------------------------------------------\n// useIdleReady — \"am I allowed to wake up yet?\"\n// ---------------------------------------------------------------------------\n\n/**\n * Returns `true` once the idle flush has completed.\n * Causes exactly one re-render (false → true). No work is registered.\n *\n * Use this when a component wants to stay dormant (show nothing, or a skeleton)\n * until the page is fully settled, then \"turn on.\"\n *\n * @example\n * ```tsx\n * function HeavyWidget() {\n * const ready = useIdleReady();\n * if (!ready) return null; // or a skeleton\n * return <ExpensiveComponent />;\n * }\n * ```\n */\nexport function useIdleReady(): boolean {\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n const unsubscribe = onFlushComplete(() => {\n setReady(true);\n });\n return unsubscribe;\n }, []);\n\n return ready;\n}\n\n// ---------------------------------------------------------------------------\n// useIdleGate — register work AND get a ready signal\n// ---------------------------------------------------------------------------\n\n/**\n * Register deferred work and get a `ready` signal when it completes.\n *\n * This is the \"full package\" — your component stays dormant, the scheduler\n * runs your callback at the right time, and then you get notified to\n * update your UI.\n *\n * @example\n * ```tsx\n * function PrefetchedSection() {\n * const { ready } = useIdleGate('prefetch-recommendations', 2, async () => {\n * await prefetchRecommendations();\n * });\n *\n * if (!ready) return <Skeleton />;\n * return <Recommendations />;\n * }\n * ```\n */\nexport function useIdleGate(\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n): { ready: boolean } {\n const [ready, setReady] = useState(false);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n const unregister = registerIdleTask(key, priority, async () => {\n await callbackRef.current();\n setReady(true);\n });\n return unregister;\n }, [key, priority]);\n\n return { ready };\n}\n\n// ---------------------------------------------------------------------------\n// useIdleRegister — imperative registration (for dynamic/conditional work)\n// ---------------------------------------------------------------------------\n\n/**\n * Returns a `register` function you can call imperatively.\n * Useful when the deferred work depends on runtime conditions.\n *\n * @example\n * ```tsx\n * function SearchResults({ query }) {\n * const scheduleIdle = useIdleRegister();\n *\n * useEffect(() => {\n * if (query) {\n * scheduleIdle(`prefetch-${query}`, 4, () => {\n * prefetchRelatedResults(query);\n * });\n * }\n * }, [query, scheduleIdle]);\n * }\n * ```\n */\nexport function useIdleRegister(): (\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n) => void {\n const unregisterRefs = useRef<Map<string, () => void>>(new Map());\n\n // Cleanup all registrations on unmount\n useEffect(() => {\n const refs = unregisterRefs.current;\n return () => {\n refs.forEach((unregister) => unregister());\n refs.clear();\n };\n }, []);\n\n return useCallback(\n (\n key: string,\n priority: IdlePriority,\n callback: () => void | Promise<void>,\n ) => {\n // Cancel previous registration with same key\n unregisterRefs.current.get(key)?.();\n\n const unregister = registerIdleTask(key, priority, callback);\n unregisterRefs.current.set(key, unregister);\n },\n [],\n );\n}\n","\"use client\";\n\n/**\n * @ai-matrx/kit/url-state — THE canonical URL-state core. Every surface that\n * puts view state in the address bar goes through here.\n *\n * The URL is the source of truth: refresh, copied links, and browser\n * back/forward all reproduce the same value. Discrete controls push a history\n * entry by default; high-frequency text inputs opt into `replace` so a single\n * search does not create one entry per keystroke.\n *\n * WHY A RAW `history.pushState` IS A BUG, not just a style choice. It fires no\n * event and no popstate, so every OTHER url-backed control on the page keeps\n * rendering stale values until something unrelated re-renders it.\n * `commitUrlParams` dispatches `matrx:url-state`, which is what\n * `useUrlSearchParams` subscribes to. (Measured in the Matrx frontend,\n * 2026-08-25: 33 hand-rolled writes across 21 files, every one of them\n * silent.)\n *\n * PICK THE RIGHT ONE:\n * one control owns one parameter → `useUrlState` + a codec\n * a cluster of values moving together → `useMirroredUrlState`\n *\n * Codecs below cover string / enum / boolean / positive-integer / JSON, and all\n * of them OMIT the default rather than writing it, so a pristine surface has a\n * clean URL and a link carries only what the user actually chose.\n *\n * Ported verbatim from matrx-frontend `lib/url-state/useUrlState.ts`. The\n * original deliberately imports NOTHING from `next/navigation` — it writes\n * through the History API and notifies subscribers itself, which is exactly\n * how it runs in the Next.js App Router host. This port adds ONE optional\n * seam on top of that verbatim behavior: `setUrlStateRouter` lets a host whose\n * router must observe/perform the writes (react-router, a memory router in\n * tests, a native shell) inject `{ push, replace, getLocation? }`. With no\n * router injected — the default, and the Next.js wiring — behavior is\n * byte-identical to the original. The injected router lives on `globalThis`\n * under `Symbol.for(\"ai-matrx.kit.url-state-router\")` because the package\n * builds `splitting: false` dual ESM/CJS: module-level state would silently\n * split the registration across bundle graphs (the confirm-opener hazard).\n */\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\nconst URL_STATE_EVENT = \"matrx:url-state\";\n\n/**\n * The optional injected router. `push`/`replace` receive the full relative\n * URL (`pathname?query#hash`) exactly as the History API default would write\n * it. `getLocation` overrides where the current URL is read from (a memory\n * router); absent, `window.location` is read.\n */\nexport interface UrlStateRouter {\n push: (url: string) => void;\n replace: (url: string) => void;\n getLocation?: (() => { pathname: string; search: string; hash: string }) | undefined;\n}\n\nconst ROUTER_SLOT = Symbol.for(\"ai-matrx.kit.url-state-router\");\n\nfunction getRouter(): UrlStateRouter | null {\n return (\n (globalThis as Record<symbol, UrlStateRouter | null | undefined>)[\n ROUTER_SLOT\n ] ?? null\n );\n}\n\n/**\n * Inject (or with `null` remove) the host router. Optional — with none set,\n * writes go through `window.history` push/replaceState, which is the verbatim\n * Matrx-frontend behavior and correct for Next.js App Router hosts.\n */\nexport function setUrlStateRouter(router: UrlStateRouter | null): void {\n (globalThis as Record<symbol, UrlStateRouter | null | undefined>)[\n ROUTER_SLOT\n ] = router;\n}\n\nfunction currentLocation(): { pathname: string; search: string; hash: string } {\n const custom = getRouter()?.getLocation;\n if (custom) return custom();\n return {\n pathname: window.location.pathname,\n search: window.location.search,\n hash: window.location.hash,\n };\n}\n\nfunction subscribeToUrl(listener: () => void) {\n window.addEventListener(\"popstate\", listener);\n window.addEventListener(URL_STATE_EVENT, listener);\n return () => {\n window.removeEventListener(\"popstate\", listener);\n window.removeEventListener(URL_STATE_EVENT, listener);\n };\n}\n\nfunction getUrlSnapshot() {\n return currentLocation().search;\n}\n\nfunction getServerUrlSnapshot() {\n return \"\";\n}\n\n/** Reactive query-string snapshot for URL-backed primitives. */\nexport function useUrlSearchParams(): URLSearchParams {\n const search = useSyncExternalStore(\n subscribeToUrl,\n getUrlSnapshot,\n getServerUrlSnapshot,\n );\n return useMemo(() => new URLSearchParams(search), [search]);\n}\n\nexport type UrlHistoryMode = \"push\" | \"replace\";\n\nexport interface UrlStateCodec<T> {\n defaultValue: T;\n parse: (raw: string | null) => T;\n serialize: (value: T) => string | null;\n}\n\nexport interface SetUrlStateOptions {\n history?: UrlHistoryMode | undefined;\n}\n\nexport function commitUrlParams(\n patch: Readonly<Record<string, string | null>>,\n history: UrlHistoryMode,\n) {\n const location = currentLocation();\n const params = new URLSearchParams(location.search);\n for (const [key, value] of Object.entries(patch)) {\n if (value === null || value === \"\") params.delete(key);\n else params.set(key, value);\n }\n\n const query = params.toString();\n const next = `${location.pathname}${query ? `?${query}` : \"\"}${location.hash}`;\n const current = `${location.pathname}${location.search}${location.hash}`;\n if (next === current) return;\n\n const router = getRouter();\n if (router) {\n if (history === \"replace\") router.replace(next);\n else router.push(next);\n } else if (history === \"replace\") {\n window.history.replaceState(window.history.state, \"\", next);\n } else {\n window.history.pushState(window.history.state, \"\", next);\n }\n window.dispatchEvent(new Event(URL_STATE_EVENT));\n}\n\n/**\n * Classify a URL transition for surfaces that MIRROR state (a store, local\n * state) into the URL from an effect, where there is no single call site to\n * label.\n *\n * THE RULE: a discrete user decision (tab, filter, sort, page, selection)\n * PUSHES, so Back undoes exactly that one step; only high-frequency text\n * (`textKeys` — search boxes, a slider being dragged) REPLACES, so one search\n * is one entry instead of one per keystroke.\n */\nexport function historyModeForParamChange(\n current: URLSearchParams,\n next: URLSearchParams,\n textKeys: readonly string[],\n): UrlHistoryMode {\n const keys = new Set([...current.keys(), ...next.keys()]);\n const changed = [...keys].filter(\n (key) => current.get(key) !== next.get(key),\n );\n if (changed.length === 0) return \"replace\";\n return changed.every((key) => textKeys.includes(key)) ? \"replace\" : \"push\";\n}\n\nexport function useUrlState<T>(\n key: string,\n codec: UrlStateCodec<T>,\n): readonly [T, (value: T, options?: SetUrlStateOptions) => void] {\n const searchParams = useUrlSearchParams();\n const value = codec.parse(searchParams.get(key));\n\n const setValue = (next: T, options?: SetUrlStateOptions) => {\n commitUrlParams(\n { [key]: codec.serialize(next) },\n options?.history ?? \"push\",\n );\n };\n\n return [value, setValue] as const;\n}\n\nexport function stringUrlCodec(defaultValue = \"\"): UrlStateCodec<string> {\n return {\n defaultValue,\n parse: (raw) => raw ?? defaultValue,\n serialize: (value) => (value === defaultValue ? null : value),\n };\n}\n\nexport function enumUrlCodec<const T extends string>(\n values: readonly T[],\n defaultValue: T,\n): UrlStateCodec<T> {\n const allowed = new Set<string>(values);\n return {\n defaultValue,\n parse: (raw) => (raw && allowed.has(raw) ? (raw as T) : defaultValue),\n serialize: (value) => (value === defaultValue ? null : value),\n };\n}\n\nexport function booleanUrlCodec(defaultValue = false): UrlStateCodec<boolean> {\n return {\n defaultValue,\n parse: (raw) => (raw === null ? defaultValue : raw === \"1\"),\n serialize: (value) => (value === defaultValue ? null : value ? \"1\" : \"0\"),\n };\n}\n\nexport function positiveIntegerUrlCodec(\n defaultValue: number,\n): UrlStateCodec<number> {\n return {\n defaultValue,\n parse: (raw) => {\n const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;\n return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultValue;\n },\n serialize: (value) =>\n value === defaultValue || !Number.isFinite(value) || value <= 0\n ? null\n : String(Math.trunc(value)),\n };\n}\n\nexport function jsonUrlCodec<T>(\n defaultValue: T,\n isValid: (value: unknown) => value is T,\n): UrlStateCodec<T> {\n return {\n defaultValue,\n parse: (raw) => {\n if (!raw) return defaultValue;\n try {\n const parsed: unknown = JSON.parse(raw);\n return isValid(parsed) ? parsed : defaultValue;\n } catch {\n return defaultValue;\n }\n },\n serialize: (value) =>\n JSON.stringify(value) === JSON.stringify(defaultValue)\n ? null\n : JSON.stringify(value),\n };\n}\n\n/**\n * Mirror a whole view-state OBJECT into the URL, in both directions.\n *\n * THE PATTERN 18 FILES WERE HAND-ROLLING. `useUrlState` is right when one\n * control owns one parameter. It is the wrong shape when a surface holds a\n * cluster of related values (search + sort + filters + page) that must move\n * together, be seeded from the URL on first render, and follow Back/Forward.\n * Every surface that needed that wrote its own `history.pushState` — and NONE\n * of them dispatched the sync event, so any other URL-backed control on the\n * same page silently kept showing stale values after they wrote.\n *\n * 🚨 THE LOOP IS BROKEN BY VALUE, NEVER BY BOOKKEEPING. The obvious guard —\n * remember the last URL you wrote and ignore anything matching it — looks\n * equivalent and is not: pressing Forward to a view already visited produces a\n * URL you did indeed write before, so the guard swallows it and the address bar\n * moves while the surface does not. Compare the DECODED value to the current\n * one instead; your own write compares equal and stops.\n *\n * Seeding happens in the `useState` initialiser, not an effect, so the first\n * render already shows the requested view rather than flashing the default and\n * fetching the wrong page before correcting itself.\n */\nexport interface MirroredUrlStateOptions<T> {\n /** Decode the whole value from the query string. Must never throw. */\n parse: (params: URLSearchParams) => T;\n /** Encode it; `null` for a key means \"omit\", which keeps defaults out of the URL. */\n toParams: (value: T) => Record<string, string | null>;\n /** Value equality — what stops the two directions fighting. */\n isSame: (a: T, b: T) => boolean;\n /** Keys that REPLACE instead of pushing (search boxes, dragged sliders). */\n textKeys?: readonly string[] | undefined;\n /**\n * Changing this clears the mirrored state and its parameters — for when the\n * surface switches to a different subject and the old view would be a lie.\n */\n resetKey?: string | undefined;\n}\n\nexport function useMirroredUrlState<T>(\n options: MirroredUrlStateOptions<T>,\n): readonly [T, (updater: T | ((prev: T) => T)) => void] {\n const { parse, toParams, isSame, textKeys = [], resetKey } = options;\n const params = useUrlSearchParams();\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const [value, setValue] = useState<T>(() =>\n parse(\n typeof window === \"undefined\"\n ? new URLSearchParams()\n : new URLSearchParams(currentLocation().search),\n ),\n );\n\n // value → URL\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const current = new URLSearchParams(currentLocation().search);\n const patch = optionsRef.current.toParams(value);\n\n const next = new URLSearchParams(current);\n for (const [key, v] of Object.entries(patch)) {\n if (v === null || v === \"\") next.delete(key);\n else next.set(key, v);\n }\n if (next.toString() === current.toString()) return;\n\n commitUrlParams(patch, historyModeForParamChange(current, next, textKeys));\n // `textKeys` is a literal in every caller; `value` is the real trigger.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n // URL → value (Back/Forward, a pasted link, another control writing)\n useEffect(() => {\n // Read the URL at EFFECT time, not the render snapshot. The value→URL\n // effect runs first. When it commits a local filter/sort decision it\n // synchronously notifies the external store, but `params` in this render\n // still describes the URL from before that write. Re-applying that stale\n // snapshot here ping-pongs state and URL until React raises #185.\n const fromUrl = optionsRef.current.parse(\n new URLSearchParams(currentLocation().search),\n );\n setValue((prev) => (optionsRef.current.isSame(prev, fromUrl) ? prev : fromUrl));\n }, [params]);\n\n // Clearing on a subject change is deliberate; clearing on a subject ARRIVING\n // is destructive. A surface whose id is undefined for its first render (async\n // params, a late store hydration, a suspended boundary) would otherwise wipe\n // the very view the user just loaded — and the symptom is indistinguishable\n // from \"the URL never saved my filters\", because the write lands and is\n // erased a tick later.\n //\n // So: only a transition between two REAL, DIFFERENT keys resets.\n const previousResetKey = useRef(resetKey);\n useEffect(() => {\n const previous = previousResetKey.current;\n previousResetKey.current = resetKey;\n if (previous === resetKey) return;\n if (previous === undefined || previous === \"\") return; // arriving, not changing\n if (resetKey === undefined || resetKey === \"\") return; // leaving, not changing\n\n const cleared = optionsRef.current.parse(new URLSearchParams());\n setValue(cleared);\n commitUrlParams(optionsRef.current.toParams(cleared), \"replace\");\n }, [resetKey]);\n\n const update = useCallback((updater: T | ((prev: T) => T)) => {\n setValue((prev) =>\n typeof updater === \"function\"\n ? (updater as (p: T) => T)(prev)\n : updater,\n );\n }, []);\n\n return [value, update] as const;\n}\n","/**\n * @ai-matrx/kit/idb-store — base manager.\n *\n * Ported verbatim from matrx-frontend `lib/idb/store-manager.ts`, with ONE\n * structural inversion: the original documented a `protected static _instance`\n * convention (each subclass held its singleton on its own static field).\n * A class-static is module state — with this package built `splitting: false`\n * in dual ESM/CJS format the class is duplicated into the root bundle and the\n * `./idb-store` bundle, and CJS/ESM each instantiate their own module graph,\n * so a static field would silently split \"the\" singleton into up to four\n * instances racing the same IndexedDB database. The singleton slot therefore\n * lives on `globalThis` under `Symbol.for(\"ai-matrx.kit.idb-store-state\")`\n * instead — see `singleton.ts` (`getIdbStoreSingleton`). Never \"clean this\n * up\" back into a static field.\n */\n\nimport { openDB, IDBPDatabase } from \"idb\";\n\nexport type AsyncResult<T> = Promise<{ data: T | null; error: Error | null }>;\n\nexport abstract class DBStoreManager<T> {\n protected db: IDBPDatabase | null = null;\n protected dbName: string;\n protected version: number;\n\n protected constructor(dbName: string, version: number) {\n this.dbName = dbName;\n this.version = version;\n }\n\n protected abstract setupStores(db: IDBPDatabase): void;\n\n protected async initDB(): Promise<void> {\n if (this.db) return;\n\n try {\n this.db = await openDB(this.dbName, this.version, {\n upgrade: (db) => {\n this.setupStores(db);\n },\n });\n } catch (error) {\n console.error(\"Failed to initialize database:\", error);\n throw error;\n }\n }\n\n // `add`/`get` carry their own generic (like `query` below) so a subclass\n // whose `T` covers one IDB object store (e.g. Recording) can still read/write\n // a different store's record shape (e.g. RecordingChunk) without a cast —\n // see the audio store in the original host, which manages both `recordings`\n // and `chunks` stores.\n protected async add<TRecord = T>(storeName: string, data: TRecord): AsyncResult<string> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const id = await this.db.add(storeName, data);\n return { data: id.toString(), error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async get<TRecord = T>(storeName: string, id: string): AsyncResult<TRecord> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const result = await this.db.get(storeName, id);\n return { data: result as TRecord, error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async getAll(storeName: string): AsyncResult<T[]> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const result = await this.db.getAll(storeName);\n return { data: result as T[], error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async update<U extends object>(storeName: string, id: number, data: Partial<U>): AsyncResult<boolean> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const existing = await this.db.get(storeName, id);\n if (!existing) throw new Error(\"Record not found\");\n\n const updated = { ...existing, ...data };\n await this.db.put(storeName, updated);\n return { data: true, error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async delete(storeName: string, id: number): AsyncResult<boolean> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n await this.db.delete(storeName, id);\n return { data: true, error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n\n protected async query<U>(\n storeName: string,\n indexName: string,\n query: IDBValidKey | IDBKeyRange\n ): AsyncResult<U[]> {\n try {\n if (!this.db) throw new Error(\"Database not initialized\");\n const result = await this.db.getAllFromIndex(storeName, indexName, query);\n return { data: result as U[], error: null };\n } catch (error) {\n return { data: null, error: error as Error };\n }\n }\n}\n","/**\n * Public CRUD surface over `DBStoreManager` — ported verbatim from\n * matrx-frontend `lib/idb/store-interface.ts`. The base keeps its operations\n * `protected` so feature stores expose intent-named methods; this subclass is\n * the escape hatch for hosts that want the raw generic surface (e.g. a\n * `useIDB(store)` hook driving arbitrary stores).\n *\n * NOTE (original API shape, kept verbatim): `getItem` takes a string id while\n * `updateItem`/`deleteItem` take a number id. With an `autoIncrement` key path\n * the generated keys are numbers, so reads use `String(id)` only against\n * string-keyed stores — this asymmetry is the original public contract.\n */\n\nimport { DBStoreManager, AsyncResult } from \"./store-manager\";\n\nexport abstract class PublicStoreManager<T> extends DBStoreManager<T> {\n constructor(dbName: string, version: number) {\n super(dbName, version);\n }\n\n public addItem(storeName: string, data: T): AsyncResult<string> {\n return this.add(storeName, data);\n }\n\n public getItem(storeName: string, id: string): AsyncResult<T> {\n return this.get(storeName, id);\n }\n\n public getAllItems(storeName: string): AsyncResult<T[]> {\n return this.getAll(storeName);\n }\n\n public updateItem<U extends object>(\n storeName: string,\n id: number,\n data: Partial<U>\n ): AsyncResult<boolean> {\n return this.update<U>(storeName, id, data);\n }\n\n public deleteItem(storeName: string, id: number): AsyncResult<boolean> {\n return this.delete(storeName, id);\n }\n\n public queryItems<U>(\n storeName: string,\n indexName: string,\n query: IDBValidKey | IDBKeyRange\n ): AsyncResult<U[]> {\n return this.query<U>(storeName, indexName, query);\n }\n}\n","/**\n * Convenience base for a store class bound to one named object store —\n * ported from matrx-frontend `lib/idb/feature-store.ts`.\n *\n * DEFECT FIX vs the original: the constructor kicks off `initDB()` without\n * awaiting it (by design — construction stays synchronous and operations\n * before init resolve `{ error: \"Database not initialized\" }`), but the\n * original left that floating promise unhandled, so a failed `openDB` (e.g.\n * private-mode storage denial) surfaced as an unhandled promise rejection on\n * top of the `initDB` console.error. The rejection is now absorbed here —\n * `initDB` has already screamed, and every operation still reports the\n * uninitialized state through its `AsyncResult` error.\n */\n\nimport { IDBPDatabase } from \"idb\";\nimport { PublicStoreManager } from \"./store-interface\";\n\nexport abstract class FeatureStore<T> extends PublicStoreManager<T> {\n protected storeName: string;\n\n protected constructor(dbName: string, version: number, storeName: string) {\n super(dbName, version);\n this.storeName = storeName;\n this.initDB().catch(() => {\n // Already logged loudly by initDB; operations report\n // \"Database not initialized\" through their AsyncResult.\n });\n }\n\n protected abstract override setupStores(db: IDBPDatabase): void;\n\n public getStoreName(): string {\n return this.storeName;\n }\n}\n","/**\n * The one place a store singleton may live.\n *\n * The original host pattern held each store's singleton on a\n * `protected static _instance` field of the store class. In this package that\n * is a hazard, not a convenience: built `splitting: false` in dual ESM/CJS\n * format, the class body is duplicated into the root bundle and the\n * `./idb-store` bundle, and the ESM and CJS graphs each instantiate their own\n * copy — a class-static would silently split \"the\" singleton into several\n * instances, each opening its own connection (and racing upgrades) against\n * the same IndexedDB database. So per-store instances live on `globalThis`\n * under `Symbol.for(\"ai-matrx.kit.idb-store-state\")`, keyed by a\n * caller-chosen name. Never \"clean this up\" into module or class state.\n *\n * Host usage (replaces the old static `getInstance` body):\n *\n * class AudioStore extends DBStoreManager<Recording> { ... }\n * export const audioStore = getIdbStoreSingleton(\"voiceNotesDB/audio\", () => new AudioStore());\n */\n\ninterface IdbStoreState {\n instances: Map<string, unknown>;\n}\n\nconst STATE_SLOT = Symbol.for(\"ai-matrx.kit.idb-store-state\");\n\nfunction getState(): IdbStoreState {\n const holder = globalThis as Record<symbol, IdbStoreState | undefined>;\n let state = holder[STATE_SLOT];\n if (!state) {\n state = { instances: new Map() };\n holder[STATE_SLOT] = state;\n }\n return state;\n}\n\n/**\n * Returns the one instance registered under `key`, creating it via `create`\n * on first call. The key should uniquely name the store (a good convention is\n * `\"<dbName>/<storeName>\"`) — two different classes registering the same key\n * is a caller bug and gets whichever registered first.\n */\nexport function getIdbStoreSingleton<T>(key: string, create: () => T): T {\n const state = getState();\n if (!state.instances.has(key)) {\n state.instances.set(key, create());\n }\n return state.instances.get(key) as T;\n}\n\n/** @internal Test-only: drop every registered store instance. */\nexport function _resetIdbStoreSingletons(): void {\n getState().instances.clear();\n}\n","/**\n * The zero-dependency perceptual-distance engine behind the string input path\n * of `findNearestTailwindColor`.\n *\n * The matrx-frontend original computed distance through colord's lab plugin\n * (`colordInstance.delta(hex)`). This module reproduces that plugin's exact\n * pipeline — sRGB → XYZ(D65) → chromatic adaptation to D50 (colord's\n * matrices, including its channel clamps) → CIE L*a*b* rounded to 2 decimals\n * → CIEDE2000 (colord >= 2.10 formulation) ÷ 100, rounded to 3 decimals and\n * clamped to [0, 1] — so the nearest-token answer is bit-identical to the\n * colord path. The test suite cross-checks this against colord itself (a\n * devDependency only).\n */\n\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\ninterface Lab {\n l: number;\n a: number;\n b: number;\n}\n\n/** colord's rounding helper: round to `digits` decimal places. */\nfunction round(value: number, digits = 0): number {\n const factor = Math.pow(10, digits);\n return Math.round(factor * value) / factor + 0;\n}\n\nfunction clamp(value: number, min = 0, max = 1): number {\n return value > max ? max : value > min ? value : min;\n}\n\n/** sRGB channel (0–255) → linear-light (0–1). */\nfunction linearize(channel: number): number {\n const c = channel / 255;\n return c < 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n// D50 reference white (colord's constants).\nconst WHITE_X = 96.422;\nconst WHITE_Y = 100;\nconst WHITE_Z = 82.521;\n\nconst EPSILON = 216 / 24389;\nconst KAPPA = 24389 / 27;\n\n/** sRGB → XYZ(D65) → Bradford-adapted D50, clamped — colord's exact matrices. */\nfunction rgbToXyz(rgb: Rgb): { x: number; y: number; z: number } {\n const r = linearize(rgb.r);\n const g = linearize(rgb.g);\n const b = linearize(rgb.b);\n const d65 = {\n x: 100 * (0.4124564 * r + 0.3575761 * g + 0.1804375 * b),\n y: 100 * (0.2126729 * r + 0.7151522 * g + 0.072175 * b),\n z: 100 * (0.0193339 * r + 0.119192 * g + 0.9503041 * b),\n };\n const d50 = {\n x: 1.0478112 * d65.x + 0.0228866 * d65.y + -0.050127 * d65.z,\n y: 0.0295424 * d65.x + 0.9904844 * d65.y + -0.0170491 * d65.z,\n z: -0.0092345 * d65.x + 0.0150436 * d65.y + 0.7521316 * d65.z,\n };\n return {\n x: clamp(d50.x, 0, WHITE_X),\n y: clamp(d50.y, 0, WHITE_Y),\n z: clamp(d50.z, 0, WHITE_Z),\n };\n}\n\n/** RGB → CIE L*a*b*, rounded to 2 decimals exactly like colord's `toLab`. */\nexport function rgbToLab(rgb: Rgb): Lab {\n const xyz = rgbToXyz(rgb);\n let x = xyz.x / WHITE_X;\n let y = xyz.y / WHITE_Y;\n let z = xyz.z / WHITE_Z;\n x = x > EPSILON ? Math.cbrt(x) : (KAPPA * x + 16) / 116;\n y = y > EPSILON ? Math.cbrt(y) : (KAPPA * y + 16) / 116;\n z = z > EPSILON ? Math.cbrt(z) : (KAPPA * z + 16) / 116;\n return {\n l: round(116 * y - 16, 2),\n a: round(500 * (x - y), 2),\n b: round(200 * (y - z), 2),\n };\n}\n\n/** CIEDE2000 between two Lab colors — colord's exact formulation. */\nfunction ciede2000(lab1: Lab, lab2: Lab): number {\n const { l: l1, a: a1, b: b1 } = lab1;\n const { l: l2, a: a2, b: b2 } = lab2;\n const toDeg = 180 / Math.PI;\n const toRad = Math.PI / 180;\n\n const c1 = Math.pow(Math.pow(a1, 2) + Math.pow(b1, 2), 0.5);\n const c2 = Math.pow(Math.pow(a2, 2) + Math.pow(b2, 2), 0.5);\n const lBar = (l1 + l2) / 2;\n const cBar7 = Math.pow((c1 + c2) / 2, 7);\n const g = 0.5 * (1 - Math.pow(cBar7 / (cBar7 + Math.pow(25, 7)), 0.5));\n const a1p = a1 * (1 + g);\n const a2p = a2 * (1 + g);\n const c1p = Math.pow(Math.pow(a1p, 2) + Math.pow(b1, 2), 0.5);\n const c2p = Math.pow(Math.pow(a2p, 2) + Math.pow(b2, 2), 0.5);\n const cBarP = (c1p + c2p) / 2;\n let h1p = a1p === 0 && b1 === 0 ? 0 : Math.atan2(b1, a1p) * toDeg;\n let h2p = a2p === 0 && b2 === 0 ? 0 : Math.atan2(b2, a2p) * toDeg;\n if (h1p < 0) h1p += 360;\n if (h2p < 0) h2p += 360;\n\n let dhp = h2p - h1p;\n const hAbs = Math.abs(h2p - h1p);\n if (hAbs > 180 && h2p <= h1p) {\n dhp += 360;\n } else if (hAbs > 180 && h2p > h1p) {\n dhp -= 360;\n }\n let hBarP = h1p + h2p;\n if (hAbs <= 180) {\n hBarP /= 2;\n } else {\n hBarP = (h1p + h2p < 360 ? hBarP + 360 : hBarP - 360) / 2;\n }\n\n const t =\n 1 -\n 0.17 * Math.cos(toRad * (hBarP - 30)) +\n 0.24 * Math.cos(2 * toRad * hBarP) +\n 0.32 * Math.cos(toRad * (3 * hBarP + 6)) -\n 0.2 * Math.cos(toRad * (4 * hBarP - 63));\n const dL = l2 - l1;\n const dCp = c2p - c1p;\n const dHp = 2 * Math.sin((toRad * dhp) / 2) * Math.pow(c1p * c2p, 0.5);\n const sl =\n 1 +\n (0.015 * Math.pow(lBar - 50, 2)) /\n Math.pow(20 + Math.pow(lBar - 50, 2), 0.5);\n const sc = 1 + 0.045 * cBarP;\n const sh = 1 + 0.015 * cBarP * t;\n const dTheta = 30 * Math.exp(-1 * Math.pow((hBarP - 275) / 25, 2));\n // colord >= 2.10 computes the rotation term from the adjusted mean chroma\n // (C'bar^7), the standard CIEDE2000 formulation.\n const cBarP7 = Math.pow(cBarP, 7);\n const rt =\n -2 *\n Math.pow(cBarP7 / (cBarP7 + Math.pow(25, 7)), 0.5) *\n Math.sin(2 * toRad * dTheta);\n\n return Math.pow(\n Math.pow(dL / 1 / sl, 2) +\n Math.pow(dCp / 1 / sc, 2) +\n Math.pow(dHp / 1 / sh, 2) +\n (rt * dCp * dHp) / (1 * sc * 1 * sh),\n 0.5,\n );\n}\n\n/**\n * Perceptual distance between two RGB colors, normalized exactly like\n * colord's `.delta()`: CIEDE2000 / 100, rounded to 3 decimals, clamped [0,1].\n */\nexport function rgbDelta(rgb1: Rgb, rgb2: Rgb): number {\n return clamp(round(ciede2000(rgbToLab(rgb1), rgbToLab(rgb2)) / 100, 3));\n}\n\nconst HEX_RE = /^#?([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGB_FN_RE =\n /^rgba?\\(\\s*([+-]?[\\d.]+)\\s*[,\\s]\\s*([+-]?[\\d.]+)\\s*[,\\s]\\s*([+-]?[\\d.]+)(?:\\s*[,/]\\s*[+-]?[\\d.]+%?)?\\s*\\)$/i;\n\n/**\n * Parses the two input shapes this unit is chartered for — hex (`#rgb`,\n * `#rrggbb`, with or without `#`, alpha digits tolerated and ignored) and\n * `rgb()`/`rgba()` strings — into RGB channels. Returns `null` for anything\n * else; this is deliberately NOT a general CSS color parser.\n */\nexport function parseHexOrRgb(input: string): Rgb | null {\n const text = input.trim();\n const hexMatch = text.match(HEX_RE);\n if (hexMatch) {\n const hex = hexMatch[1] as string;\n if (hex.length === 3 || hex.length === 4) {\n return {\n r: parseInt((hex[0] as string) + hex[0], 16),\n g: parseInt((hex[1] as string) + hex[1], 16),\n b: parseInt((hex[2] as string) + hex[2], 16),\n };\n }\n return {\n r: parseInt(hex.slice(0, 2), 16),\n g: parseInt(hex.slice(2, 4), 16),\n b: parseInt(hex.slice(4, 6), 16),\n };\n }\n const rgbMatch = text.match(RGB_FN_RE);\n if (rgbMatch) {\n const r = Number(rgbMatch[1]);\n const g = Number(rgbMatch[2]);\n const b = Number(rgbMatch[3]);\n if ([r, g, b].some((v) => Number.isNaN(v))) return null;\n return { r: clamp(r, 0, 255), g: clamp(g, 0, 255), b: clamp(b, 0, 255) };\n }\n return null;\n}\n","/**\n * The Tailwind CSS default palette lookup table — ported verbatim from\n * matrx-frontend `constants/tailwind-colors.ts` (the data the S14\n * \"tailwind-color-util\" unit does its lookups against). 22 color groups,\n * shades 50–950.\n */\n\nexport interface TailwindColorGroup {\n name: string;\n shades: Record<string, string>;\n}\n\n\nexport const tailwindColors: readonly TailwindColorGroup[] = [\n {\n name: \"Slate\",\n shades: {\n \"50\": \"#f8fafc\",\n \"100\": \"#f1f5f9\",\n \"200\": \"#e2e8f0\",\n \"300\": \"#cbd5e1\",\n \"400\": \"#94a3b8\",\n \"500\": \"#64748b\",\n \"600\": \"#475569\",\n \"700\": \"#334155\",\n \"800\": \"#1e293b\",\n \"900\": \"#0f172a\",\n \"950\": \"#020617\"\n }\n },\n {\n name: \"Gray\",\n shades: {\n \"50\": \"#f9fafb\",\n \"100\": \"#f3f4f6\",\n \"200\": \"#e5e7eb\",\n \"300\": \"#d1d5db\",\n \"400\": \"#9ca3af\",\n \"500\": \"#6b7280\",\n \"600\": \"#4b5563\",\n \"700\": \"#374151\",\n \"800\": \"#1f2937\",\n \"900\": \"#111827\",\n \"950\": \"#030712\"\n }\n },\n {\n name: \"Zinc\",\n shades: {\n \"50\": \"#fafafa\",\n \"100\": \"#f4f4f5\",\n \"200\": \"#e4e4e7\",\n \"300\": \"#d4d4d8\",\n \"400\": \"#a1a1aa\",\n \"500\": \"#71717a\",\n \"600\": \"#52525b\",\n \"700\": \"#3f3f46\",\n \"800\": \"#27272a\",\n \"900\": \"#18181b\",\n \"950\": \"#09090b\"\n }\n },\n {\n name: \"Neutral\",\n shades: {\n \"50\": \"#fafafa\",\n \"100\": \"#f5f5f5\",\n \"200\": \"#e5e5e5\",\n \"300\": \"#d4d4d4\",\n \"400\": \"#a3a3a3\",\n \"500\": \"#737373\",\n \"600\": \"#525252\",\n \"700\": \"#404040\",\n \"800\": \"#262626\",\n \"900\": \"#171717\",\n \"950\": \"#0a0a0a\"\n }\n },\n {\n name: \"Stone\",\n shades: {\n \"50\": \"#fafaf9\",\n \"100\": \"#f5f5f4\",\n \"200\": \"#e7e5e4\",\n \"300\": \"#d6d3d1\",\n \"400\": \"#a8a29e\",\n \"500\": \"#78716c\",\n \"600\": \"#57534e\",\n \"700\": \"#44403c\",\n \"800\": \"#292524\",\n \"900\": \"#1c1917\",\n \"950\": \"#0c0a09\"\n }\n },\n {\n name: \"Red\",\n shades: {\n \"50\": \"#fef2f2\",\n \"100\": \"#fee2e2\",\n \"200\": \"#fecaca\",\n \"300\": \"#fca5a5\",\n \"400\": \"#f87171\",\n \"500\": \"#ef4444\",\n \"600\": \"#dc2626\",\n \"700\": \"#b91c1c\",\n \"800\": \"#991b1b\",\n \"900\": \"#7f1d1d\",\n \"950\": \"#450a0a\"\n }\n },\n {\n name: \"Orange\",\n shades: {\n \"50\": \"#fff7ed\",\n \"100\": \"#ffedd5\",\n \"200\": \"#fed7aa\",\n \"300\": \"#fdba74\",\n \"400\": \"#fb923c\",\n \"500\": \"#f97316\",\n \"600\": \"#ea580c\",\n \"700\": \"#c2410c\",\n \"800\": \"#9a3412\",\n \"900\": \"#7c2d12\",\n \"950\": \"#431407\"\n }\n },\n {\n name: \"Amber\",\n shades: {\n \"50\": \"#fffbeb\",\n \"100\": \"#fef3c7\",\n \"200\": \"#fde68a\",\n \"300\": \"#fcd34d\",\n \"400\": \"#fbbf24\",\n \"500\": \"#f59e0b\",\n \"600\": \"#d97706\",\n \"700\": \"#b45309\",\n \"800\": \"#92400e\",\n \"900\": \"#78350f\",\n \"950\": \"#451a03\"\n }\n },\n {\n name: \"Yellow\",\n shades: {\n \"50\": \"#fefce8\",\n \"100\": \"#fef9c3\",\n \"200\": \"#fef08a\",\n \"300\": \"#fde047\",\n \"400\": \"#facc15\",\n \"500\": \"#eab308\",\n \"600\": \"#ca8a04\",\n \"700\": \"#a16207\",\n \"800\": \"#854d0e\",\n \"900\": \"#713f12\",\n \"950\": \"#422006\"\n }\n },\n {\n name: \"Lime\",\n shades: {\n \"50\": \"#f7fee7\",\n \"100\": \"#ecfccb\",\n \"200\": \"#d9f99d\",\n \"300\": \"#bef264\",\n \"400\": \"#a3e635\",\n \"500\": \"#84cc16\",\n \"600\": \"#65a30d\",\n \"700\": \"#4d7c0f\",\n \"800\": \"#3f6212\",\n \"900\": \"#365314\",\n \"950\": \"#1a2e05\"\n }\n },\n {\n name: \"Green\",\n shades: {\n \"50\": \"#f0fdf4\",\n \"100\": \"#dcfce7\",\n \"200\": \"#bbf7d0\",\n \"300\": \"#86efac\",\n \"400\": \"#4ade80\",\n \"500\": \"#22c55e\",\n \"600\": \"#16a34a\",\n \"700\": \"#15803d\",\n \"800\": \"#166534\",\n \"900\": \"#14532d\",\n \"950\": \"#052e16\"\n }\n },\n {\n name: \"Emerald\",\n shades: {\n \"50\": \"#ecfdf5\",\n \"100\": \"#d1fae5\",\n \"200\": \"#a7f3d0\",\n \"300\": \"#6ee7b7\",\n \"400\": \"#34d399\",\n \"500\": \"#10b981\",\n \"600\": \"#059669\",\n \"700\": \"#047857\",\n \"800\": \"#065f46\",\n \"900\": \"#064e3b\",\n \"950\": \"#022c22\"\n }\n },\n {\n name: \"Teal\",\n shades: {\n \"50\": \"#f0fdfa\",\n \"100\": \"#ccfbf1\",\n \"200\": \"#99f6e4\",\n \"300\": \"#5eead4\",\n \"400\": \"#2dd4bf\",\n \"500\": \"#14b8a6\",\n \"600\": \"#0d9488\",\n \"700\": \"#0f766e\",\n \"800\": \"#115e59\",\n \"900\": \"#134e4a\",\n \"950\": \"#042f2e\"\n }\n },\n {\n name: \"Cyan\",\n shades: {\n \"50\": \"#ecfeff\",\n \"100\": \"#cffafe\",\n \"200\": \"#a5f3fc\",\n \"300\": \"#67e8f9\",\n \"400\": \"#22d3ee\",\n \"500\": \"#06b6d4\",\n \"600\": \"#0891b2\",\n \"700\": \"#0e7490\",\n \"800\": \"#155e75\",\n \"900\": \"#164e63\",\n \"950\": \"#083344\"\n }\n },\n {\n name: \"Sky\",\n shades: {\n \"50\": \"#f0f9ff\",\n \"100\": \"#e0f2fe\",\n \"200\": \"#bae6fd\",\n \"300\": \"#7dd3fc\",\n \"400\": \"#38bdf8\",\n \"500\": \"#0ea5e9\",\n \"600\": \"#0284c7\",\n \"700\": \"#0369a1\",\n \"800\": \"#075985\",\n \"900\": \"#0c4a6e\",\n \"950\": \"#082f49\"\n }\n },\n {\n name: \"Blue\",\n shades: {\n \"50\": \"#eff6ff\",\n \"100\": \"#dbeafe\",\n \"200\": \"#bfdbfe\",\n \"300\": \"#93c5fd\",\n \"400\": \"#60a5fa\",\n \"500\": \"#3b82f6\",\n \"600\": \"#2563eb\",\n \"700\": \"#1d4ed8\",\n \"800\": \"#1e40af\",\n \"900\": \"#1e3a8a\",\n \"950\": \"#172554\"\n }\n },\n {\n name: \"Indigo\",\n shades: {\n \"50\": \"#eef2ff\",\n \"100\": \"#e0e7ff\",\n \"200\": \"#c7d2fe\",\n \"300\": \"#a5b4fc\",\n \"400\": \"#818cf8\",\n \"500\": \"#6366f1\",\n \"600\": \"#4f46e5\",\n \"700\": \"#4338ca\",\n \"800\": \"#3730a3\",\n \"900\": \"#312e81\",\n \"950\": \"#1e1b4b\"\n }\n },\n {\n name: \"Violet\",\n shades: {\n \"50\": \"#f5f3ff\",\n \"100\": \"#ede9fe\",\n \"200\": \"#ddd6fe\",\n \"300\": \"#c4b5fd\",\n \"400\": \"#a78bfa\",\n \"500\": \"#8b5cf6\",\n \"600\": \"#7c3aed\",\n \"700\": \"#6d28d9\",\n \"800\": \"#5b21b6\",\n \"900\": \"#4c1d95\",\n \"950\": \"#2e1065\"\n }\n },\n {\n name: \"Purple\",\n shades: {\n \"50\": \"#faf5ff\",\n \"100\": \"#f3e8ff\",\n \"200\": \"#e9d5ff\",\n \"300\": \"#d8b4fe\",\n \"400\": \"#c084fc\",\n \"500\": \"#a855f7\",\n \"600\": \"#9333ea\",\n \"700\": \"#7e22ce\",\n \"800\": \"#6b21a8\",\n \"900\": \"#581c87\",\n \"950\": \"#3b0764\"\n }\n },\n {\n name: \"Fuchsia\",\n shades: {\n \"50\": \"#fdf4ff\",\n \"100\": \"#fae8ff\",\n \"200\": \"#f5d0fe\",\n \"300\": \"#f0abfc\",\n \"400\": \"#e879f9\",\n \"500\": \"#d946ef\",\n \"600\": \"#c026d3\",\n \"700\": \"#a21caf\",\n \"800\": \"#86198f\",\n \"900\": \"#701a75\",\n \"950\": \"#4a044e\"\n }\n },\n {\n name: \"Pink\",\n shades: {\n \"50\": \"#fdf2f8\",\n \"100\": \"#fce7f3\",\n \"200\": \"#fbcfe8\",\n \"300\": \"#f9a8d4\",\n \"400\": \"#f472b6\",\n \"500\": \"#ec4899\",\n \"600\": \"#db2777\",\n \"700\": \"#be185d\",\n \"800\": \"#9d174d\",\n \"900\": \"#831843\",\n \"950\": \"#500724\"\n }\n },\n {\n name: \"Rose\",\n shades: {\n \"50\": \"#fff1f2\",\n \"100\": \"#ffe4e6\",\n \"200\": \"#fecdd3\",\n \"300\": \"#fda4af\",\n \"400\": \"#fb7185\",\n \"500\": \"#f43f5e\",\n \"600\": \"#e11d48\",\n \"700\": \"#be123c\",\n \"800\": \"#9f1239\",\n \"900\": \"#881337\",\n \"950\": \"#4c0519\"\n }\n }\n] as const;\n","/**\n * The bidirectional Tailwind-token mapping — the heart of the S14 unit,\n * ported from matrx-frontend `utils/color-utils/color-change-util.ts` /\n * `tailwind-color-util.ts`.\n *\n * token → hex: `getColorFromTailwind(\"slate-500\")` → `\"#64748b\"` (plus the\n * fuzzy `formatTailwindColor` for messy user input like `\"skyblue598\"`).\n * color → token: `findNearestTailwindColor` — the verbatim nearest-match\n * scan. The original took a colord instance; the colord coupling is inverted\n * structurally: pass any object with `.delta(hex) => number` (every colord\n * instance with the lab plugin qualifies — no import, no peer), or pass a\n * plain hex / `rgb()` string and the built-in colord-identical CIEDE2000\n * engine (`lab-delta.ts`) computes the distances with zero dependencies.\n */\n\nimport { parseHexOrRgb, rgbDelta } from \"./lab-delta\";\nimport { tailwindColors } from \"./tailwind-colors\";\n\n/**\n * Anything that can measure its perceptual distance to a hex color —\n * structurally satisfied by a colord instance extended with the lab plugin.\n */\nexport interface ColorDelta {\n delta(color: string): number;\n}\n\n/**\n * Function to find the hex value for a given Tailwind color string.\n * @param tailwindColorString - The Tailwind color string (e.g., 'slate-500').\n * @returns The hex value of the corresponding color (e.g., '#64748b'), or an empty string if not found.\n */\nexport function getColorFromTailwind(tailwindColorString: string): string {\n const [colorName, shade] = tailwindColorString.split('-');\n const colorGroup = tailwindColors.find(group => group.name.toLowerCase() === (colorName ?? '').toLowerCase());\n if (colorGroup) {\n const shadeEntry = Object.entries(colorGroup.shades).find(([key]) => key === shade);\n if (shadeEntry) {\n return shadeEntry[1];\n }\n }\n return '';\n}\n\n/**\n * Function to find the nearest Tailwind color for a given input color.\n * @param inputColor - The input color: a hex or `rgb()` string, or any\n * `{ delta(hex) }` measurer (e.g. a colord instance with the lab plugin).\n * @returns The nearest Tailwind color string (e.g., 'slate-500'), or an\n * empty string when a string input cannot be parsed.\n */\nexport function findNearestTailwindColor(inputColor: string | ColorDelta): string {\n let measure: (hexValue: string) => number;\n if (typeof inputColor === \"string\") {\n const rgb = parseHexOrRgb(inputColor);\n if (!rgb) return \"\";\n measure = (hexValue) => {\n const target = parseHexOrRgb(hexValue);\n // The palette is all six-digit hex; unparseable is impossible here.\n return target ? rgbDelta(rgb, target) : Infinity;\n };\n } else {\n measure = (hexValue) => inputColor.delta(hexValue);\n }\n\n let nearestColor = \"\";\n let smallestDistance = Infinity;\n\n tailwindColors.forEach((colorGroup) => {\n Object.entries(colorGroup.shades).forEach(([shade, hexValue]) => {\n const distance = measure(hexValue);\n if (distance < smallestDistance) {\n smallestDistance = distance;\n nearestColor = `${colorGroup.name.toLowerCase()}-${shade}`;\n }\n });\n });\n\n return nearestColor;\n}\n\n/**\n * Utility to format a Tailwind color string.\n * Matches Tailwind color names and returns the closest Tailwind value.\n * Handles cases like \"skyblue600\", \"sky598\", or \"sky-600\".\n * @param tailwindColor - The user-provided Tailwind color string.\n * @returns A properly formatted Tailwind color string.\n */\nexport function formatTailwindColor(tailwindColor: string): string {\n const tailwindColorNames = [\n \"Slate\", \"Gray\", \"Zinc\", \"Neutral\", \"Stone\", \"Red\", \"Orange\", \"Amber\", \"Yellow\", \"Lime\", \"Green\",\n \"Emerald\", \"Teal\", \"Cyan\", \"Blue\", \"Indigo\", \"Violet\",\"Sky\", \"Purple\", \"Fuchsia\", \"Pink\", \"Rose\"\n ];\n\n // Step 1: Try to match the string to extract the numeric part (shade)\n const splitIndex = tailwindColor.search(/\\d/); // Find the index where numbers start\n\n // Case 1: If there is no numeric part, default to shade 500\n if (splitIndex === -1) {\n const colorName = tailwindColorNames.find(color => tailwindColor.toLowerCase().includes(color.toLowerCase()));\n if (colorName) {\n return getColorFromTailwind(`${colorName.toLowerCase()}-500`); // Default to 500 if no shade provided\n }\n }\n\n // Case 2: There is a numeric part, so handle compound names and numeric values\n if (splitIndex > 0) {\n const colorNamePart = tailwindColor.slice(0, splitIndex); // Get color name part\n let shadePart = tailwindColor.slice(splitIndex); // Get shade part\n\n // Step 2: Find all matching color names in the provided color part\n const matchedColors = tailwindColorNames.filter(color => colorNamePart.toLowerCase().includes(color.toLowerCase()));\n\n // Step 3: Sort matches based on appearance in the string (we want the first match in the original string)\n matchedColors.sort((a, b) => colorNamePart.toLowerCase().indexOf(a.toLowerCase()) - colorNamePart.toLowerCase().indexOf(b.toLowerCase()));\n\n // Step 4: Use the first matching color name (if found)\n if (matchedColors.length > 0) {\n const colorName = (matchedColors[0] as string).toLowerCase(); // The first matched color\n\n // Round the shade to the nearest 100 and convert to string\n let shade = Math.round(parseInt(shadePart) / 100) * 100;\n const formattedColor = getColorFromTailwind(`${colorName}-${shade.toString()}`);\n\n // Return the formatted color if found\n if (formattedColor) {\n return formattedColor;\n }\n }\n }\n\n // If no valid format is found, return an empty string\n return '';\n}\n","/**\n * The pure input normalizers — ported verbatim from matrx-frontend\n * `utils/color-utils/color-change-util.ts`. Each takes the messy shape a\n * human pastes (\"61, 135, 204\", \"r:61,g:135,b:204\", \"94% 29% 0% 9%\",\n * \"0x3d87cc\"…) and returns the canonical string for that format, or `''`\n * when the input does not fit — string in, string out, zero dependencies.\n *\n * ONE deliberate divergence from the original: `formatLabString` /\n * `formatLchString` logged every call (input, match, miss) with\n * unconditional `console.log`s — debug spam on a parse path, removed here.\n * Matching/return behavior is unchanged.\n */\n\n/**\n * Utility to format a hex string.\n * Adds the # prefix if missing.\n * @param hex - The user-provided hex color.\n * @returns A properly formatted hex color string.\n */\nexport function formatHex(hex: string): string {\n // Check if the hex is missing the # symbol and add it\n return hex.startsWith('#') ? hex : `#${hex}`;\n}\n\n/**\n * Utility to format an rgb string.\n * Accepts various formats like \"61, 135, 204\" or \"(61, 135, 204)\".\n * @param rgb - The user-provided rgb color.\n * @returns A properly formatted rgb color string.\n */\nexport function formatRgbString(rgb: string): string {\n // Extract numbers from the string\n const rgbValues = rgb.replace(/[^\\d,]/g, '').split(',');\n if (rgbValues.length === 3) {\n return `rgb(${(rgbValues[0] as string).trim()}, ${(rgbValues[1] as string).trim()}, ${(rgbValues[2] as string).trim()})`;\n }\n return ''; // Return an empty string for invalid cases\n}\n\n/**\n * Utility to format an RGB object.\n * Accepts various object-like formats such as '{\"r\":61,\"g\":135,\"b\":204,\"a\":1}', '\"r\":61,\"g\":135,\"b\":204,\"a\":1', or 'r:61,g:135,b:204,a:1'.\n * @param rgbObject - The user-provided RGB object-like string.\n * @returns A properly formatted RGB object.\n */\nexport function formatRgbObject(rgbObject: string): string {\n // Flexible regex to match and capture r, g, b, a values, regardless of quotes, brackets, or missing attributes\n const regex = /[\"']?r[\"']?\\s*[:=]\\s*(\\d+)\\s*[,]\\s*[\"']?g[\"']?\\s*[:=]\\s*(\\d+)\\s*[,]\\s*[\"']?b[\"']?\\s*[:=]\\s*(\\d+)(?:\\s*[,]\\s*[\"']?a[\"']?\\s*[:=]\\s*(\\d+))?/i;\n const match = rgbObject.match(regex);\n\n if (match) {\n const r = match[1], g = match[2], b = match[3], a = match[4] || 1;\n // Return a normalized RGB(A) object string\n return `{\"r\":${r},\"g\":${g},\"b\":${b},\"a\":${a}}`;\n }\n\n // If input is invalid, return an empty string\n return '';\n}\n\n/**\n * Utility to format an HSL object.\n * Accepts various object-like formats such as '{\"h\":199,\"s\":89,\"l\":48,\"a\":1}' or 'h:199,s:89,l:48,a:1'.\n * @param hslObject - The user-provided HSL object-like string.\n * @returns A properly formatted HSL object.\n */\nexport function formatHslObject(hslObject: string): string {\n // Flexible regex to match and capture h, s, l, a values, regardless of quotes, brackets, or missing attributes\n const regex = /[\"']?h[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?s[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?l[\"']?\\s*[:=]\\s*(\\d+)(?:\\s*,\\s*[\"']?a[\"']?\\s*[:=]\\s*(\\d+))?/i;\n const match = hslObject.match(regex);\n if (match) {\n const h = match[1], s = match[2], l = match[3], a = match[4] || 1;\n return `{\"h\":${h},\"s\":${s},\"l\":${l},\"a\":${a}}`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format an HSL string.\n * Accepts formats like \"hsl(199, 89%, 48%)\" or \"199, 89%, 48%\".\n * @param hslString - The user-provided HSL string.\n * @returns A properly formatted HSL string.\n */\nexport function formatHslString(hslString: string): string {\n // Extract numbers and percentage values\n const hslValues = hslString.replace(/[^\\d,%]/g, '').split(/\\s*,\\s*/);\n if (hslValues.length === 3) {\n return `hsl(${hslValues[0]}, ${hslValues[1]}%, ${hslValues[2]}%)`;\n }\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format an HSV percentage string.\n * Accepts formats like \"94% 29% 0%\" or \"(94% 29% 0%)\".\n * @param hsvString - The user-provided HSV percentage string.\n * @returns A properly formatted HSV string.\n */\nexport function formatHsvString(hsvString: string): string {\n // Remove parentheses and other non-relevant characters, then split based on spaces\n const hsvValues = hsvString.replace(/[^\\d%\\s]/g, '').split(/\\s+/).map(value => parseInt(value.replace('%', ''), 10));\n\n // Check if there are exactly 3 values for HSV (Hue, Saturation, Value)\n if (hsvValues.length === 3 && hsvValues.every(val => !isNaN(val))) {\n return `hsv(${hsvValues[0]}, ${hsvValues[1]}%, ${hsvValues[2]}%)`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format a regular CMYK string.\n * Accepts formats like \"94, 29, 0, 9\" or \"(94, 29, 0, 9)\".\n * @param cmykString - The user-provided CMYK string.\n * @returns A properly formatted CMYK string.\n */\nexport function formatRegularCmykString(cmykString: string): string {\n const cmykValues = cmykString.replace(/[^\\d,]/g, '').split(/\\s*,\\s*/);\n\n if (cmykValues.length === 4 && cmykValues.every(val => !isNaN(Number(val)))) {\n return `cmyk(${cmykValues[0]}, ${cmykValues[1]}, ${cmykValues[2]}, ${cmykValues[3]})`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format a CMYK object.\n * Accepts various object-like formats such as '{\"c\":94,\"m\":29,\"y\":0,\"k\":9,\"a\":1}' or 'c:94,m:29,y:0,k:9,a:1'.\n * @param cmykObject - The user-provided CMYK object-like string.\n * @returns A properly formatted CMYK object.\n */\nexport function formatCmykObject(cmykObject: string): string {\n // Flexible regex to match and capture c, m, y, k, a values, regardless of quotes or brackets\n const regex = /[\"']?c[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?m[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?y[\"']?\\s*[:=]\\s*(\\d+)\\s*,\\s*[\"']?k[\"']?\\s*[:=]\\s*(\\d+)(?:\\s*,\\s*[\"']?a[\"']?\\s*[:=]\\s*(\\d+))?/i;\n const match = cmykObject.match(regex);\n\n if (match) {\n const c = match[1], m = match[2], y = match[3], k = match[4], a = match[5] || 1;\n return `{\"c\":${c},\"m\":${m},\"y\":${y},\"k\":${k},\"a\":${a}}`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to format a CMYK percentage string.\n * Accepts formats like \"94% 29% 0% 9%\" or \"(94% 29% 0% 9%)\".\n * @param cmykString - The user-provided CMYK percentage string.\n * @returns A properly formatted CMYK string.\n */\nexport function formatCmykString(cmykString: string): string {\n // Remove any parentheses or extra characters, then split based on spaces\n const cmykValues = cmykString.replace(/[^\\d%\\s]/g, '').split(/\\s+/).map(value => parseInt(value.replace('%', ''), 10));\n\n if (cmykValues.length === 4 && cmykValues.every(val => !isNaN(val))) {\n return `device-cmyk(${cmykValues[0]}% ${cmykValues[1]}% ${cmykValues[2]}% ${cmykValues[3]}%)`;\n }\n return ''; // Return empty string for invalid input\n}\n\n/**\n * Utility to detect device-cmyk color strings (\"device-cmyk(94% 29% 0% 9%)\").\n * @param cmykString - The user-provided CMYK string.\n * @returns True when the string is a well-formed device-cmyk expression.\n */\nexport function isDeviceCmyk(cmykString: string): boolean {\n const regex = /device-cmyk\\(\\s*\\d+%\\s+\\d+%\\s+\\d+%\\s+\\d+%\\s*\\)/;\n return regex.test(cmykString);\n}\n\n/**\n * Utility to format an HWB string.\n * Accepts formats like \"hwb(199 24% 20%)\" or \"hwb(199deg 24% 20%)\".\n * @param hwbString - The user-provided HWB string.\n * @returns A properly formatted HWB string.\n */\nexport function formatHwbString(hwbString: string): string {\n // Extract numbers and percentage values from the HWB string\n const hwbValues = hwbString.replace(/[^\\d,%\\s]/g, '').split(/\\s+/);\n if (hwbValues.length === 3) {\n return `hwb(${hwbValues[0]}, ${hwbValues[1]}%, ${hwbValues[2]}%)`;\n }\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format a Lab string.\n * Accepts formats like \"lab(55.715 -14.02 -32.329)\" or \"55.715 -14.02 -32.329\".\n * @param labString - The user-provided Lab string.\n * @returns A properly formatted Lab string.\n */\nexport function formatLabString(labString: string): string {\n // Try matching with or without the \"lab(\" prefix\n const match = labString.match(/(?:lab\\()?\\s*(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s*\\)?/i);\n\n if (match) {\n const [, l, a, b] = match;\n return `lab(${l} ${a} ${b})`;\n }\n\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format an LCH string.\n * Accepts formats like \"lch(55.715 35.17 246.6)\" or \"55.715 35.17 246.6\".\n * @param lchString - The user-provided LCH string.\n * @returns A properly formatted LCH string.\n */\nexport function formatLchString(lchString: string): string {\n // Try matching with or without the \"lch(\" prefix\n const match = lchString.match(/(?:lch\\()?\\s*(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s+(-?\\d+(?:\\.\\d+)?)\\s*\\)?/i);\n\n if (match) {\n const [, l, c, h] = match;\n return `lch(${l} ${c} ${h})`;\n }\n\n return ''; // Return empty string for invalid cases\n}\n\n/**\n * Utility to format a hex string with 0x prefix.\n * Converts \"0x3d87cc\" to \"#3d87cc\".\n * @param hex - The user-provided hex color with 0x prefix.\n * @returns A properly formatted hex color string.\n */\nexport function formatHexWith0x(hex: string): string {\n if (hex.startsWith('0x')) {\n return `#${hex.slice(2)}`;\n }\n return ''; // Return empty string for invalid cases\n}\n","/**\n * The \"accept anything a human pastes\" waterfall — ported from matrx-frontend\n * `color-change-util.ts` `normalizeColorInput`, with the colord coupling\n * inverted: the original gated several tiers on `colord(input).isValid()`;\n * here the host injects that validity check (`createColorNormalizer({\n * isValid })` — pass `(c) => colord(c).isValid()` or any equivalent). The\n * tier ORDER, the tiers that skip validation, and the returned\n * `{ value, type }` shapes are verbatim.\n *\n * Deliberate divergence (same class as formats.ts): the original logged every\n * tier hit/miss with unconditional `console.log`s — removed.\n */\n\nimport {\n formatCmykObject,\n formatCmykString,\n formatHex,\n formatHexWith0x,\n formatHslObject,\n formatHslString,\n formatHsvString,\n formatHwbString,\n formatLabString,\n formatLchString,\n formatRegularCmykString,\n formatRgbObject,\n formatRgbString,\n isDeviceCmyk,\n} from \"./formats\";\nimport { formatTailwindColor } from \"./tailwind\";\n\nexport interface NormalizedColor {\n value: string;\n type: string;\n}\n\nexport interface ColorNormalizerOptions {\n /**\n * \"Can this string be parsed as a color?\" — the host's color engine\n * (e.g. `(c) => colord(c).isValid()`).\n */\n isValid: (color: string) => boolean;\n}\n\n/**\n * Builds `normalizeColorInput`: tries the format conversions in the original\n * fixed order until one produces a valid (or structurally well-formed) color,\n * returning `{ value, type }`, or `null` when nothing fits.\n */\nexport function createColorNormalizer({ isValid }: ColorNormalizerOptions) {\n return function normalizeColorInput(colorInput: string): NormalizedColor | null {\n // Try standard validation first\n if (isValid(colorInput)) {\n return { value: colorInput, type: 'standard' };\n }\n\n // Check for 'device-cmyk' manually\n if (isDeviceCmyk(colorInput)) {\n return { value: colorInput, type: 'device-cmyk' };\n }\n\n // Try hex conversion\n const hex = formatHex(colorInput);\n if (isValid(hex)) {\n return { value: hex, type: 'hex' };\n }\n\n // Try RGB string conversion\n const rgbString = formatRgbString(colorInput);\n if (isValid(rgbString)) {\n return { value: rgbString, type: 'rgb' };\n }\n\n // Try RGB object conversion (skip isValid for this)\n const rgbObject = formatRgbObject(colorInput);\n if (rgbObject !== '') {\n return { value: rgbObject, type: 'rgb-object' };\n }\n\n // Try HSL object conversion (skip isValid for this)\n const hslObject = formatHslObject(colorInput);\n if (hslObject !== '') {\n return { value: hslObject, type: 'hsl-object' };\n }\n\n // Try HSL string conversion\n const hslString = formatHslString(colorInput);\n if (isValid(hslString)) {\n return { value: hslString, type: 'hsl' };\n }\n\n // Try HSV string conversion\n const hsvString = formatHsvString(colorInput);\n if (isValid(hsvString)) {\n return { value: hsvString, type: 'hsv' };\n }\n\n // Try Tailwind color conversion\n const tailwindColor = formatTailwindColor(colorInput);\n if (tailwindColor !== '') {\n return { value: tailwindColor, type: 'tailwind' };\n }\n\n // Try regular CMYK string conversion (skip isValid for this)\n const regularCmykString = formatRegularCmykString(colorInput);\n if (regularCmykString !== '') {\n return { value: regularCmykString, type: 'cmyk' };\n }\n\n // Try CMYK object conversion (skip isValid for this)\n const cmykObject = formatCmykObject(colorInput);\n if (cmykObject !== '') {\n return { value: cmykObject, type: 'cmyk-object' };\n }\n\n // Try CMYK percentage string conversion (for device-cmyk)\n const cmykString = formatCmykString(colorInput);\n if (isValid(cmykString)) {\n return { value: cmykString, type: 'cmyk-percentage' };\n }\n\n // Try HWB string conversion\n const hwbString = formatHwbString(colorInput);\n if (isValid(hwbString)) {\n return { value: hwbString, type: 'hwb' };\n }\n\n // Try Lab string conversion (skip isValid for this)\n const labString = formatLabString(colorInput);\n if (labString !== '') {\n return { value: labString, type: 'lab' };\n }\n\n // Try LCH string conversion (skip isValid for this)\n const lchString = formatLchString(colorInput);\n if (lchString !== '') {\n return { value: lchString, type: 'lch' };\n }\n\n // Try hex with 0x conversion\n const hexWith0x = formatHexWith0x(colorInput);\n if (isValid(hexWith0x)) {\n return { value: hexWith0x, type: 'hex-0x' };\n }\n\n // If all else fails, return null\n return null;\n };\n}\n","/**\n * @ai-matrx/kit/qr — THE QR-code decoder (client-side, in memory). Ported\n * verbatim from matrx-frontend `lib/qr/decode.ts`.\n *\n * One primitive, three inputs (a File/Blob, an `ImageData` frame, a\n * `<video>`/`<canvas>` element), one answer: the text the QR encodes, or\n * `null` when no code is present. Nothing here uploads, stores, or persists\n * anything — the bytes live in a canvas for the length of one call.\n *\n * Engine order:\n * 1. `BarcodeDetector` — native, fast, handles rotation and poor contrast.\n * 2. `jsqr` — pure-JS fallback (lazily imported, so it only enters the\n * bundle of a surface that actually decodes), for Safari/Firefox where\n * the native detector does not exist.\n *\n * Runtime dependency of this subpath (and only when the fallback fires):\n * `jsqr` — a browser without `BarcodeDetector` decoding a pasted screenshot\n * IS the capability, not an optional extra; without the fallback the unit\n * silently does nothing on Safari/Firefox.\n *\n * Browser capability: decoding needs a DOM (`document`, canvas 2D,\n * `createImageBitmap`) at call time; importing is inert and SSR-safe, and\n * `hasNativeQrDetector()` is safe to call anywhere (it only probes\n * `globalThis`).\n *\n * 🚨 Reach for THIS, never a second decoder. If a surface needs a new input\n * shape, add an adapter here.\n */\n\n/** Longest edge we rasterise to. Big enough for a phone screenshot of a QR,\n * small enough that a 48MP photo cannot stall the main thread. */\nconst MAX_EDGE = 1600;\n\ntype NativeBarcodeDetector = {\n detect: (source: CanvasImageSource | ImageBitmap | Blob) => Promise<{ rawValue: string }[]>;\n};\n\ntype BarcodeDetectorCtor = {\n new (options?: { formats?: string[] }): NativeBarcodeDetector;\n getSupportedFormats?: () => Promise<string[]>;\n};\n\nfunction nativeDetector(): BarcodeDetectorCtor | null {\n const ctor = (globalThis as { BarcodeDetector?: BarcodeDetectorCtor })\n .BarcodeDetector;\n return typeof ctor === \"function\" ? ctor : null;\n}\n\n/** True when the browser can decode without downloading the JS fallback. */\nexport function hasNativeQrDetector(): boolean {\n return nativeDetector() !== null;\n}\n\nasync function decodeNative(\n source: CanvasImageSource | ImageBitmap | Blob,\n): Promise<string | null> {\n const Ctor = nativeDetector();\n if (!Ctor) return null;\n try {\n const detector = new Ctor({ formats: [\"qr_code\"] });\n const results = await detector.detect(source);\n const value = results.find((r) => r.rawValue)?.rawValue;\n return value ? value : null;\n } catch {\n // A detector that throws (unsupported format, decode error) is a miss,\n // never a crash — the jsqr fallback still gets its turn.\n return null;\n }\n}\n\nasync function decodeWithJsQr(frame: ImageData): Promise<string | null> {\n const { default: jsQR } = await import(\"jsqr\");\n const both = jsQR(frame.data, frame.width, frame.height, {\n inversionAttempts: \"attemptBoth\",\n });\n return both?.data ? both.data : null;\n}\n\n/** Draw any image source onto a canvas, capped at {@link MAX_EDGE}. */\nfunction toImageData(\n source: CanvasImageSource,\n width: number,\n height: number,\n): ImageData | null {\n if (!width || !height) return null;\n const scale = Math.min(1, MAX_EDGE / Math.max(width, height));\n const w = Math.max(1, Math.round(width * scale));\n const h = Math.max(1, Math.round(height * scale));\n const canvas = document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return null;\n ctx.drawImage(source, 0, 0, w, h);\n return ctx.getImageData(0, 0, w, h);\n}\n\n/** Decode a QR code out of an already-rasterised frame. */\nexport async function decodeQrFromImageData(\n frame: ImageData,\n): Promise<string | null> {\n return (await decodeWithJsQr(frame)) ?? null;\n}\n\n/**\n * Decode a QR code out of a live `<video>` (a camera preview) or a `<canvas>`.\n * Returns `null` when the current frame holds no code — call it on a tick.\n */\nexport async function decodeQrFromElement(\n element: HTMLVideoElement | HTMLCanvasElement,\n): Promise<string | null> {\n const width =\n element instanceof HTMLVideoElement ? element.videoWidth : element.width;\n const height =\n element instanceof HTMLVideoElement ? element.videoHeight : element.height;\n if (!width || !height) return null;\n\n const native = await decodeNative(element);\n if (native) return native;\n\n const frame = toImageData(element, width, height);\n return frame ? decodeQrFromImageData(frame) : null;\n}\n\n/**\n * Decode a QR code out of an image File/Blob — a pasted screenshot, a dropped\n * PNG, a photo from the OS camera sheet.\n *\n * Resolves `null` when the image holds no QR code. Throws only when the file\n * is not decodable as an image at all.\n */\nexport async function decodeQrFromImageFile(\n file: Blob,\n): Promise<string | null> {\n // The native detector accepts a Blob directly on Chromium — cheapest path.\n const direct = await decodeNative(file);\n if (direct) return direct;\n\n let bitmap: ImageBitmap | null = null;\n try {\n bitmap = await createImageBitmap(file);\n } catch {\n throw new Error(\"That file could not be read as an image.\");\n }\n try {\n const viaBitmap = await decodeNative(bitmap);\n if (viaBitmap) return viaBitmap;\n const frame = toImageData(bitmap, bitmap.width, bitmap.height);\n return frame ? decodeQrFromImageData(frame) : null;\n } finally {\n bitmap.close();\n }\n}\n"],"mappings":"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","names":["flush","import_react","import_react","import_react","React","React","import_jsx_runtime","import_jsx_runtime","STATE_SLOT","JSON5","entries","body","joined","STATE_SLOT","getState","import_react","import_react","version","version","version","STATE_SLOT","getState"]}
|