gridsmith-ui 0.26.0 → 0.27.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +969 -0
  2. package/README.md +21 -5
  3. package/dist/charts.d.ts +2 -2
  4. package/dist/charts.js +58 -43
  5. package/dist/charts.js.map +1 -1
  6. package/dist/chat.js +4 -3
  7. package/dist/chat.js.map +1 -1
  8. package/dist/{chunk-CYN5O567.js → chunk-2CKSSWYG.js} +9 -5
  9. package/dist/chunk-2CKSSWYG.js.map +1 -0
  10. package/dist/chunk-3BRQRKDO.js +1 -0
  11. package/dist/chunk-3BRQRKDO.js.map +1 -1
  12. package/dist/{chunk-RWKCAKN3.js → chunk-5TUVX4B2.js} +6 -5
  13. package/dist/chunk-5TUVX4B2.js.map +1 -0
  14. package/dist/{chunk-X2HEV7FB.js → chunk-64TXZ4L7.js} +23 -33
  15. package/dist/chunk-64TXZ4L7.js.map +1 -0
  16. package/dist/chunk-7Q46JXSK.js +1 -0
  17. package/dist/chunk-7Q46JXSK.js.map +1 -1
  18. package/dist/chunk-CRQ6KCRD.js +1 -0
  19. package/dist/chunk-CRQ6KCRD.js.map +1 -1
  20. package/dist/{chunk-ZYVXV4WC.js → chunk-EKBWWA6P.js} +53 -6
  21. package/dist/chunk-EKBWWA6P.js.map +1 -0
  22. package/dist/chunk-HP7WUZPK.js +1 -0
  23. package/dist/chunk-HP7WUZPK.js.map +1 -1
  24. package/dist/{chunk-MYIJNVTK.js → chunk-IXR4UEF4.js} +5 -4
  25. package/dist/chunk-IXR4UEF4.js.map +1 -0
  26. package/dist/chunk-M2QRNBDQ.js +1 -0
  27. package/dist/chunk-M2QRNBDQ.js.map +1 -1
  28. package/dist/chunk-MD2EFMES.js +1 -0
  29. package/dist/chunk-MD2EFMES.js.map +1 -1
  30. package/dist/chunk-NRHIYS5W.js +1 -0
  31. package/dist/chunk-NRHIYS5W.js.map +1 -1
  32. package/dist/chunk-OTCEJN64.js +1 -0
  33. package/dist/chunk-OTCEJN64.js.map +1 -1
  34. package/dist/chunk-OYNUU346.js +78 -0
  35. package/dist/chunk-OYNUU346.js.map +1 -0
  36. package/dist/{chunk-EX64MN2U.js → chunk-PO65I3MQ.js} +4 -3
  37. package/dist/chunk-PO65I3MQ.js.map +1 -0
  38. package/dist/chunk-QM4SJKWV.js +1 -0
  39. package/dist/chunk-QM4SJKWV.js.map +1 -1
  40. package/dist/{chunk-KWLNEH53.js → chunk-R5NFCEZ3.js} +10 -7
  41. package/dist/chunk-R5NFCEZ3.js.map +1 -0
  42. package/dist/chunk-SFY2KMHG.js +1 -0
  43. package/dist/chunk-SFY2KMHG.js.map +1 -1
  44. package/dist/{chunk-HXVXJUGV.js → chunk-TJEV7YAY.js} +38 -10
  45. package/dist/chunk-TJEV7YAY.js.map +1 -0
  46. package/dist/chunk-WH2FUFAC.js +1 -0
  47. package/dist/chunk-WH2FUFAC.js.map +1 -1
  48. package/dist/chunk-XVB55M3N.js +1 -0
  49. package/dist/chunk-XVB55M3N.js.map +1 -1
  50. package/dist/chunk-ZI3OQDET.js +1 -0
  51. package/dist/chunk-ZI3OQDET.js.map +1 -1
  52. package/dist/data-grid.d.ts +1 -1
  53. package/dist/data-grid.js +5 -3
  54. package/dist/data-grid.js.map +1 -1
  55. package/dist/editor-mentions.js +2 -1
  56. package/dist/editor-mentions.js.map +1 -1
  57. package/dist/editor.js +3 -2
  58. package/dist/editor.js.map +1 -1
  59. package/dist/{feather-VFWLAILO.js → feather-FNBQ74RR.js} +10 -17
  60. package/dist/feather-FNBQ74RR.js.map +1 -0
  61. package/dist/{heroicons-H3Z7DFCF.js → heroicons-DODCSYWD.js} +9 -8
  62. package/dist/heroicons-DODCSYWD.js.map +1 -0
  63. package/dist/icons.d.ts +31 -4
  64. package/dist/icons.js +2 -1
  65. package/dist/icons.js.map +1 -1
  66. package/dist/index.d.ts +418 -65
  67. package/dist/index.js +1893 -838
  68. package/dist/index.js.map +1 -1
  69. package/dist/kanban.js +3 -2
  70. package/dist/kanban.js.map +1 -1
  71. package/dist/{lucide-MR32KM4G.js → lucide-ZWE3EPGP.js} +9 -8
  72. package/dist/lucide-ZWE3EPGP.js.map +1 -0
  73. package/dist/{phosphor-ABQQL5N5.js → phosphor-DIHPA4AJ.js} +9 -8
  74. package/dist/phosphor-DIHPA4AJ.js.map +1 -0
  75. package/dist/resizable.js +7 -5
  76. package/dist/resizable.js.map +1 -1
  77. package/dist/roots.css +25 -7
  78. package/dist/{tabler-ANUSY4D2.js → tabler-D3VYTSGI.js} +9 -8
  79. package/dist/tabler-D3VYTSGI.js.map +1 -0
  80. package/dist/tokens.css +11 -8
  81. package/dist/{use-pagination-BnKOnBdz.d.ts → use-pagination-BxcRlNQG.d.ts} +6 -0
  82. package/dist/utils.d.ts +275 -1
  83. package/dist/utils.js +875 -1
  84. package/dist/utils.js.map +1 -1
  85. package/dist/virtualized.d.ts +1 -1
  86. package/dist/virtualized.js +5 -3
  87. package/dist/virtualized.js.map +1 -1
  88. package/dist-static/tokens.css +11 -8
  89. package/package.json +5 -3
  90. package/dist/chunk-CYN5O567.js.map +0 -1
  91. package/dist/chunk-EX64MN2U.js.map +0 -1
  92. package/dist/chunk-HXVXJUGV.js.map +0 -1
  93. package/dist/chunk-KWLNEH53.js.map +0 -1
  94. package/dist/chunk-MYIJNVTK.js.map +0 -1
  95. package/dist/chunk-RWKCAKN3.js.map +0 -1
  96. package/dist/chunk-X2HEV7FB.js.map +0 -1
  97. package/dist/chunk-ZYVXV4WC.js.map +0 -1
  98. package/dist/feather-VFWLAILO.js.map +0 -1
  99. package/dist/heroicons-H3Z7DFCF.js.map +0 -1
  100. package/dist/lucide-MR32KM4G.js.map +0 -1
  101. package/dist/phosphor-ABQQL5N5.js.map +0 -1
  102. package/dist/tabler-ANUSY4D2.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/use-close-settle.ts","../../../showcase/src/lib/edge-resize.tsx","../../../showcase/src/components/DiscardConfirm.tsx","../../../showcase/src/lib/drawer-width.ts","../../../showcase/src/lib/use-scrollbar-inset.ts","../../../showcase/src/components/Drawer.tsx","../../../showcase/src/components/SkipLink.tsx","../../../showcase/src/lib/react-version.ts","../../../showcase/src/components/AppShell.tsx","../../../showcase/src/components/Breadcrumbs.tsx","../../../showcase/src/lib/use-compact.ts"],"names":["t","useEffect","jsx","useRef","useState","useCallback","createContext","useMemo","jsxs","useContext","AppShell","forwardRef","Breadcrumbs","Fragment","createPortal","label"],"mappings":"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","file":"chunk-KWLNEH53.js","sourcesContent":["import { useEffect, type RefObject } from \"react\";\nimport { useLatest } from \"./use-latest\";\n\n/** Longest transition (duration + delay) declared on `el`, in milliseconds. */\nfunction transitionMs(el: HTMLElement): number {\n const cs = getComputedStyle(el);\n const parse = (list: string) =>\n list.split(\",\").map((raw) => {\n const s = raw.trim();\n if (!s) return 0;\n const n = parseFloat(s);\n if (Number.isNaN(n)) return 0;\n return s.endsWith(\"ms\") ? n : n * 1000;\n });\n const durations = parse(cs.transitionDuration || \"0s\");\n const delays = parse(cs.transitionDelay || \"0s\");\n let max = 0;\n durations.forEach((d, i) => {\n const total = d + (delays[i] ?? delays[0] ?? 0);\n if (total > max) max = total;\n });\n return max;\n}\n\n/**\n * Run `onSettled` once an overlay's close transition has finished.\n *\n * Overlays used to unmount on `transitionend`, but a transition of zero\n * duration never fires that event — and `prefers-reduced-motion` sets every\n * transition to zero — so a closed Drawer stayed mounted off-screen with its\n * controls still in the Tab order. This settles on the event when there is a\n * transition, immediately (next tick) when there is none, and on a timeout if\n * the browser never reports the end. Reopening during the close cancels it.\n */\nexport function useCloseSettle(open: boolean, elRef: RefObject<HTMLElement | null>, onSettled: () => void) {\n const cb = useLatest(onSettled);\n useEffect(() => {\n if (open) return;\n const el = elRef.current;\n const ms = el ? transitionMs(el) : 0;\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n cb.current();\n };\n if (!el || ms === 0) {\n const t = setTimeout(finish, 0);\n return () => clearTimeout(t);\n }\n const onEnd = (e: TransitionEvent) => {\n if (e.target === el) finish();\n };\n el.addEventListener(\"transitionend\", onEnd);\n const t = setTimeout(finish, ms + 50);\n return () => {\n el.removeEventListener(\"transitionend\", onEnd);\n clearTimeout(t);\n };\n }, [open, elRef, cb]);\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { cn } from \"./utils\";\nimport { useLatest } from \"./use-latest\";\n\n/**\n * A drag-to-resize edge shared by the docked AsidePanel and the non-modal\n * Drawer. Visually it is the panel's page-side edge: hover shows the resize\n * cursor and the line thickens in the accent colour; it stays lit while\n * dragging. Nothing else appears for mouse users.\n *\n * Keyboard, invisibly: the same edge is a focusable separator (WAI-ARIA\n * window-splitter pattern). On focus it lights up as on hover; Left/Right\n * nudge the width by a step (Shift for a larger one), Home/End snap to the\n * bounds, Escape restores the width from before the interaction, and a\n * double-click (or Enter) snaps back to the default. This is what satisfies\n * WCAG 2.1.1 and 2.5.7 without a visible button.\n *\n * The width the user chose is remembered for the session (per `memoryKey`),\n * like the sidebar's collapsed state — never persisted.\n */\n\nexport interface ResizeEdgeProps {\n /** Which edge of the panel the handle sits on — the side facing the page. A right-docked panel's handle is on its \"left\" edge. */\n edge: \"left\" | \"right\";\n /** Current width in px. */\n width: number;\n /** Lower bound in px — the width the app configured. */\n min: number;\n /** Upper bound in px; a function so it can follow the viewport. */\n max: () => number;\n /** The width to snap back to. */\n defaultWidth: number;\n onResize: (width: number) => void;\n /** Accessible name, e.g. \"Resize assistant\". */\n label: string;\n /** Called when a pointer drag starts and ends — panels switch off their width animation while it runs so the edge follows the pointer exactly. */\n onDraggingChange?: (dragging: boolean) => void;\n className?: string;\n}\n\nconst STEP = 16;\nconst BIG_STEP = 64;\n\nfunction clamp(v: number, min: number, max: number) {\n return Math.min(Math.max(v, min), max);\n}\n\nexport function ResizeEdge({ edge, width, min, max, defaultWidth, onResize, label, onDraggingChange, className }: ResizeEdgeProps) {\n const [dragging, setDragging] = useState(false);\n const start = useRef<{ x: number; width: number } | null>(null);\n const latestOnResize = useLatest(onResize);\n\n // Dragging the handle away from the panel makes it wider: for a handle on the\n // panel's left edge that is a leftward drag (negative dx), on its right edge a rightward one.\n const direction = edge === \"left\" ? -1 : 1;\n\n const onPointerDown = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n e.preventDefault();\n start.current = { x: e.clientX, width };\n setDragging(true);\n e.currentTarget.setPointerCapture(e.pointerId);\n },\n [width],\n );\n\n const onPointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (!start.current) return;\n const next = clamp(start.current.width + direction * (e.clientX - start.current.x), min, max());\n latestOnResize.current(next);\n },\n [direction, min, max, latestOnResize],\n );\n\n const endDrag = useCallback(() => {\n start.current = null;\n setDragging(false);\n }, []);\n\n const latestOnDraggingChange = useLatest(onDraggingChange);\n useEffect(() => {\n latestOnDraggingChange.current?.(dragging);\n }, [dragging, latestOnDraggingChange]);\n\n // Escape during a drag reverts to the width before it (corpus: Escape cancels\n // any in-progress pointer interaction).\n useEffect(() => {\n if (!dragging) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || !start.current) return;\n latestOnResize.current(start.current.width);\n endDrag();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [dragging, endDrag, latestOnResize]);\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const step = e.shiftKey ? BIG_STEP : STEP;\n let next: number | null = null;\n // Left/Right move the edge itself; which way that widens depends on the edge.\n if (e.key === \"ArrowLeft\") next = width - direction * step;\n else if (e.key === \"ArrowRight\") next = width + direction * step;\n else if (e.key === \"Home\") next = min;\n else if (e.key === \"End\") next = max();\n else if (e.key === \"Enter\") next = defaultWidth;\n if (next === null) return;\n e.preventDefault();\n onResize(clamp(next, min, max()));\n };\n\n return (\n <div\n role=\"separator\"\n tabIndex={0}\n aria-orientation=\"vertical\"\n aria-label={label}\n aria-valuemin={min}\n aria-valuemax={max()}\n aria-valuenow={Math.round(width)}\n data-resize-edge={edge}\n data-dragging={dragging || undefined}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onDoubleClick={() => onResize(clamp(defaultWidth, min, max()))}\n onKeyDown={onKeyDown}\n className={cn(\n // A narrow absolutely-positioned strip over the edge — never a flex child that takes width.\n \"group/edge absolute top-0 bottom-0 z-10 w-ds-2 cursor-col-resize touch-none select-none outline-none\",\n edge === \"left\" ? \"-left-ds-1\" : \"-right-ds-1\",\n className,\n )}\n >\n {/* The visible line: the panel's own border at rest, thicker and accent on hover / focus / drag. */}\n <div\n aria-hidden=\"true\"\n className={cn(\n \"absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 transition-[width,background-color] duration-[var(--ds-transition-speed)]\",\n \"group-hover/edge:w-[3px] group-hover/edge:bg-[var(--ds-accent-primary)]\",\n \"group-focus-visible/edge:w-[3px] group-focus-visible/edge:bg-[var(--ds-accent-primary)]\",\n dragging && \"w-[3px] bg-[var(--ds-accent-primary)]\",\n )}\n />\n </div>\n );\n}\n\n// ─── Session memory for chosen widths ────────────────────────────────────────\n\nconst remembered = new Map<string, number>();\n\n/**\n * The width a user dragged a panel to, kept for the session under `key`.\n * Returns [width | null, remember].\n */\nexport function useRememberedWidth(key: string | undefined): [number | null, (w: number | null) => void] {\n const [width, setWidth] = useState<number | null>(() => (key ? remembered.get(key) ?? null : null));\n const remember = useCallback(\n (w: number | null) => {\n setWidth(w);\n if (!key) return;\n if (w === null) remembered.delete(key);\n else remembered.set(key, w);\n },\n [key],\n );\n return [width, remember];\n}\n\n/** Test seam. */\nexport function clearRememberedWidths() {\n remembered.clear();\n}\n\n/** Parse a px length; anything else (a token, a percentage) reads as null and the panel measures itself instead. */\nexport function pxOf(length: string | undefined): number | null {\n if (!length) return null;\n const m = /^(\\d+(?:\\.\\d+)?)px$/.exec(length.trim());\n return m ? parseFloat(m[1]) : null;\n}\n\n/** Default upper bound: sixty percent of the viewport (or of the container). */\nexport function defaultMaxWidth(container?: Element | null): number {\n const base = container instanceof HTMLElement ? container.clientWidth : typeof window !== \"undefined\" ? window.innerWidth : 1200;\n return Math.round(base * 0.6);\n}\n","import { createContext, useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"./Button\";\nimport { FormChangeCtx } from \"../lib/form-context\";\n\n/** Marks an overlay's panel: the part of the page whose controls a submit's answer is read from (0.21.0). */\nexport const OVERLAY_ROOT_ATTR = \"data-overlay-root\";\n\n/**\n * The controls a part of the page shows, by id or name: a save that keeps its form shows the same ones afterwards, a\n * step flow that moves on shows others, and a confirmation that replaces the form shows none (Sprint 25.12 A15).\n */\nfunction controlsOf(root: Element | null): string {\n if (!root) return \"\";\n const controls = root.querySelectorAll<HTMLElement>(\"input, select, textarea, [role='combobox'], [role='radiogroup'], [role='checkbox'], [role='switch'], [role='slider'], [role='spinbutton'], [contenteditable='true']\");\n return Array.from(controls).map((el) => el.id || el.getAttribute(\"name\") || el.getAttribute(\"role\") || el.tagName).join(\"|\");\n}\n\n/** A submitted form's answer, which the overlay reads once the page's answer is on screen. */\nexport interface OverlaySubmit {\n /** The page answered: its promise resolved (\"resolved\"), or its onSubmit returned no promise (\"returned\"). */\n settle: (how: \"resolved\" | \"returned\") => void;\n}\n\n/**\n * Sprint 25.12 A15 (R28-25): what an overlay knows of the forms inside it. A FormWrapper reports each change the user\n * makes, and the overlay asks before discarding while any form holds one. The overlay owns the marks, so a step flow\n * with one form per step keeps its changes after Next. A `dirty` prop the page passes wins over them. Hand-written flags\n * failed both ways in one run: the seats drawer had none, and the event drawer's was true before anything was typed.\n *\n * 0.21.0 (the review of 29 September): one mark per form, and a save clears only its own form's changes, and only those\n * made before its submit: two forms in one drawer, or a change typed while a save was running, were lost when the other\n * save cleared the drawer's single mark. A form that's gone keeps its changes until a later save or the overlay closing.\n */\nexport interface OverlayMark {\n /** The user gave one of this form's controls a new value. */\n report: (form: string) => void;\n /** This form is in the overlay until the returned function runs. */\n attach: (form: string) => () => void;\n /**\n * This form was submitted. Call before the page's onSubmit runs, then settle with its answer: the overlay reads it\n * once the answer is on screen, and clears the form's changes if it saved (FormWrapper's onSubmit says when).\n */\n submit: (form: string, from: { element: () => HTMLFormElement | null; failing: () => boolean }) => OverlaySubmit;\n /**\n * Work that closing would lose, such as a running upload (Sprint 25.12 A33): the overlay asks before closing while any\n * is held. Returns the release.\n */\n hold: () => () => void;\n /** Whether the overlay is open: work held inside a kept-mounted overlay stops when it closes. */\n open: boolean;\n}\n\nexport const OverlayMarkCtx = createContext<OverlayMark | null>(null);\n\n/**\n * An overlay's children, with its mark. Controls inside answer to a FormWrapper inside the overlay, never to a form\n * around it (0.21.0): a \"New label\" dialog opened from an edit drawer's form, or a delete's typed confirmation, marked the\n * drawer.\n */\nexport function OverlayMarkScope({ mark, children }: { mark: OverlayMark; children: ReactNode }) {\n return <OverlayMarkCtx value={mark}><FormChangeCtx value={null}>{children}</FormChangeCtx></OverlayMarkCtx>;\n}\n\n/** A form's changes in its overlay: the last one's number (0: none since it saved), and whether the form is still there. */\ninterface FormMark { stamp: number; mounted: boolean }\n\ninterface Answer { form: string; since: number; root: HTMLElement | null; controls: string; how: \"resolved\" | \"returned\"; element: () => HTMLFormElement | null; failing: () => boolean }\n\n/** An overlay's marks: set by a change, cleared by a save of the same form, and reset whenever the overlay closes; held while work runs. */\nexport function useOverlayMark(open: boolean): { marked: boolean; mark: OverlayMark } {\n const forms = useRef(new Map<string, FormMark>());\n const count = useRef(0);\n // answers from before the overlay last closed are void\n const round = useRef(0);\n const [changed, setChanged] = useState(false);\n const [holds, setHolds] = useState(0);\n const [answers, setAnswers] = useState<Answer[]>([]);\n const [wasOpen, setWasOpen] = useState(open);\n if (open !== wasOpen) {\n setWasOpen(open);\n if (!open) {\n setChanged(false);\n setAnswers([]);\n }\n }\n useEffect(() => {\n if (open) return;\n round.current++;\n for (const [id, f] of forms.current) {\n if (f.mounted) f.stamp = 0;\n else forms.current.delete(id);\n }\n }, [open]);\n const mark = useMemo<OverlayMark>(() => ({\n report: (form) => {\n const f = forms.current.get(form) ?? { stamp: 0, mounted: true };\n f.stamp = ++count.current;\n forms.current.set(form, f);\n setChanged(true);\n },\n attach: (form) => {\n const f = forms.current.get(form) ?? { stamp: 0, mounted: true };\n f.mounted = true;\n forms.current.set(form, f);\n return () => {\n const gone = forms.current.get(form);\n if (!gone) return;\n if (gone.stamp > 0) gone.mounted = false;\n else forms.current.delete(form);\n };\n },\n submit: (form, from) => {\n // the overlay's controls before the page answers, and the last change the save can carry\n const root = from.element()?.closest<HTMLElement>(`[${OVERLAY_ROOT_ATTR}]`) ?? null;\n const answer = { form, since: count.current, root, controls: controlsOf(root), ...from };\n const at = round.current;\n let settled = false;\n return {\n settle: (how) => {\n if (settled || at !== round.current) return;\n settled = true;\n setAnswers((list) => [...list, { ...answer, how }]);\n },\n };\n },\n hold: () => {\n setHolds((n) => n + 1);\n let released = false;\n return () => {\n if (released) return;\n released = true;\n setHolds((n) => n - 1);\n };\n },\n open,\n }), [open]);\n\n // An answer is read once it is on screen (this runs after the commit that carries the page's answer):\n // - a field still invalid in the form, or a check of its own failing: nothing saved;\n // - a submit that returned no promise and now shows other controls: a step flow moved on, and saves at its end;\n // - otherwise it saved: its form's changes up to its submit clear, with those of forms that have gone (a flow's steps).\n /* eslint-disable react-hooks/set-state-in-effect -- the answer is a DOM read after the page's answer commits */\n useEffect(() => {\n if (!answers.length) return;\n for (const a of answers) {\n const form = a.element();\n if (form?.isConnected && (form.querySelector(\"[aria-invalid='true']\") || a.failing())) continue;\n if (a.how === \"returned\") {\n const now = a.root?.isConnected ? controlsOf(a.root) : \"\";\n if (now !== \"\" && now !== a.controls) continue;\n }\n for (const [id, f] of forms.current) {\n if (f.stamp === 0 || f.stamp > a.since || (id !== a.form && f.mounted)) continue;\n if (f.mounted) forms.current.set(id, { ...f, stamp: 0 });\n else forms.current.delete(id);\n }\n }\n setAnswers([]);\n setChanged([...forms.current.values()].some((f) => f.stamp > 0));\n }, [answers]);\n /* eslint-enable react-hooks/set-state-in-effect */\n return { marked: changed || holds > 0, mark };\n}\n\n/**\n * The open overlay's guarded close (round 21): a Drawer, Dialog, or a Sheet given `dirty`, provides it so a form inside\n * can close the overlay through the same unsaved-changes question Escape and the close control ask. FormWrapper's\n * `onCancel` uses it; run 58's hand-wired Cancel closed a half-filled invite with no question while Escape asked.\n * `then` runs once the overlay has closed — never when the user keeps editing (the review of 23 September: the\n * form's own onCancel was dropped inside an overlay).\n */\nexport const OverlayCloseCtx = createContext<((then?: () => void) => void) | null>(null);\n\n/**\n * The dirty guard an overlay with a form shares (Sprint 25.2, C1): while the\n * content is dirty, every close path — Escape, backdrop, the close control —\n * asks first, inside the overlay rather than in a second dialog. The page\n * passes `dirty`; the overlay does the rest.\n */\nexport function useDirtyGuard(dirty: boolean | undefined, onClose: () => void, onDiscard?: () => void) {\n const [wantsConfirm, setWantsConfirm] = useState(false);\n const confirming = wantsConfirm && !!dirty;\n // What runs after the close goes ahead (a form's own onCancel). A close path wired as a click handler passes its event\n // here, so only a function counts; the overlay's own onClose is not run twice.\n const pending = useRef<unknown>(undefined);\n const runAfter = useCallback((then: unknown) => { if (typeof then === \"function\" && then !== onClose) (then as () => void)(); }, [onClose]);\n const requestClose = useCallback((then?: unknown) => {\n if (!dirty) { onClose(); runAfter(then); return; }\n pending.current = then;\n // A second close request while the question is showing (Escape again, another backdrop click) keeps editing.\n setWantsConfirm((c) => !c);\n }, [dirty, onClose, runAfter]);\n const keep = useCallback(() => { pending.current = undefined; setWantsConfirm(false); }, []);\n const discard = useCallback(() => {\n setWantsConfirm(false);\n onDiscard?.();\n onClose();\n const then = pending.current;\n pending.current = undefined;\n runAfter(then);\n }, [onClose, onDiscard, runAfter]);\n return { confirming, requestClose, keep, discard };\n}\n\nexport function DiscardConfirm({ open, onKeep, onDiscard }: { open: boolean; onKeep: () => void; onDiscard: () => void }) {\n const keepRef = useRef<HTMLButtonElement>(null);\n const returnTo = useRef<HTMLElement | null>(null);\n const overlay = useRef<HTMLElement | null>(null);\n // Focus moves to \"Keep editing\" while the question shows and goes back where it was when it closes — or to the\n // overlay's first control when nothing inside it had focus — so a non-modal drawer keeps answering Escape and a\n // screen reader keeps its place (Sprint 25.2 review).\n useEffect(() => {\n if (!open) return;\n const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n overlay.current = keepRef.current?.closest<HTMLElement>(\"[role='dialog'], [role='alertdialog']\") ?? null;\n returnTo.current = active && active !== document.body && overlay.current?.contains(active) ? active : null;\n keepRef.current?.focus();\n return () => {\n if (document.activeElement !== document.body) return;\n const back = returnTo.current;\n if (back && back.isConnected) { back.focus(); return; }\n const first = overlay.current?.querySelector<HTMLElement>(\"button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex='-1'])\");\n (first ?? overlay.current)?.focus();\n };\n }, [open]);\n if (!open) return null;\n return (\n <div\n role=\"group\"\n aria-label=\"Unsaved changes\"\n data-discard-confirm=\"\"\n className=\"shrink-0 flex flex-wrap items-center justify-between gap-ds-3 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-status-warning-bg)]\"\n // at the overlay's inset, as its header, body and footer are (Sprint 25.14 A36)\n style={{ padding: \"var(--ds-space-3) var(--ds-page-gutter)\" }}\n >\n <p className=\"text-sm text-[var(--ds-text-primary)]\">You have unsaved changes.</p>\n <div className=\"flex items-center gap-ds-2\">\n <Button type=\"button\" ref={keepRef} variant=\"secondary\" size=\"sm\" onClick={onKeep}>Keep editing</Button>\n <Button type=\"button\" variant=\"destructive\" size=\"sm\" onClick={onDiscard}>Discard changes</Button>\n </div>\n </div>\n );\n}\n","import { createContext } from \"react\";\n\n/**\n * Sprint 25.14 A24: the width a Drawer given none takes. AppShell provides its drawerWidth here (520 px by default), so a\n * page's drawers share one width with nothing passed; a lib context, so the Drawer never imports the shell that renders\n * it. Null outside a shell, where a Drawer keeps 400 px.\n */\nexport const DrawerWidthCtx = createContext<string | null>(null);\n","import { useCallback, useRef } from \"react\";\n\n/**\n * Sprint 25.14 (the review of 30 September): an overlay's scrolling body whose scrollbar takes room (Windows, Linux, a\n * Mac set to always show scroll bars) loses the scrollbar's width from its right inset, so its fields end short of the\n * header's and the footer's. This measures the scrollbar and publishes its width as `--gs-scrollbar` on the element,\n * which the body's right padding takes from the gutter. A scrollbar that overlays the content (a Mac's default, a\n * phone's) measures 0. Returns a callback ref.\n */\nexport function useScrollbarInset<T extends HTMLElement = HTMLDivElement>() {\n const observer = useRef<ResizeObserver | null>(null);\n return useCallback((el: T | null) => {\n observer.current?.disconnect();\n observer.current = null;\n if (!el) return;\n const measure = () => {\n const style = getComputedStyle(el);\n const borders = (parseFloat(style.borderLeftWidth) || 0) + (parseFloat(style.borderRightWidth) || 0);\n el.style.setProperty(\"--gs-scrollbar\", `${Math.max(0, el.offsetWidth - el.clientWidth - borders)}px`);\n };\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n // a scrollbar that appears or goes narrows or widens the content box, which the observer reports\n const o = new ResizeObserver(measure);\n o.observe(el);\n observer.current = o;\n }, []);\n}\n\n/** The right padding of a body inset by `gutter`, less the scrollbar's width where it takes room. */\nexport const insetLessScrollbar = (gutter: string) => `max(0px, calc(${gutter} - var(--gs-scrollbar, 0px)))`;\n","import { useContext, useEffect, useRef, useState, useId, useCallback, useMemo, createContext, type ReactNode, type CSSProperties } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn, OVERLAY_SURFACE, GLASS_OVERLAY, lockBodyScroll, unlockBodyScroll } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { focusInitial, useReturnFocus, useFocusTrap, useOverlayLayer, useNonModalDialog, OVERLAY_CLOSE_ATTR } from \"../lib/focus\";\nimport { useCloseSettle } from \"../lib/use-close-settle\";\nimport { ResizeEdge, useRememberedWidth, pxOf, defaultMaxWidth } from \"../lib/edge-resize\";\nimport { Tooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useBreakpoint } from \"../lib/use-breakpoint\";\nimport { useDirtyGuard, DiscardConfirm, OverlayCloseCtx, OverlayMarkScope, OVERLAY_ROOT_ATTR, useOverlayMark } from \"./DiscardConfirm\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { DrawerWidthCtx } from \"../lib/drawer-width\";\nimport { SurfaceBoundary } from \"../lib/surface-context\";\nimport { insetLessScrollbar, useScrollbarInset } from \"../lib/use-scrollbar-inset\";\n\n// ---------------------------------------------------------------------------\n// DrawerFooterContext — FormWrapper registers its actions here so the overlay\n// renders them in its footer area (outside the form's DOM tree, linked by the\n// HTML form attribute). An explicit `footer` prop on Drawer/Sheet wins.\n// ---------------------------------------------------------------------------\n\nexport interface DrawerFooterContextValue {\n registerActions: (id: string, actions: ReactNode) => void;\n unregisterActions: (id: string) => void;\n}\n\nexport const DrawerFooterCtx = createContext<DrawerFooterContextValue | null>(null);\n\ninterface DrawerProps {\n open: boolean;\n onClose: () => void;\n position?: \"left\" | \"right\" | \"bottom\";\n /** Pass none: the Drawer takes the app's width, which the shell carries (AppShell's drawerWidth, 520 px by default; 400 px outside a shell). For a deliberate wide or narrow drawer only. A non-modal side panel (modal={false}, such as the shell's assistant) keeps the width it is given. */\n width?: string;\n title?: ReactNode;\n children: ReactNode;\n footer?: ReactNode;\n container?: Element | DocumentFragment;\n /** Remove default content padding — use when the child (e.g. Sidebar) handles its own spacing. */\n flush?: boolean;\n /** Use a lighter backdrop (no blur, subtle dim). Use for compact overlays. */\n lightBackdrop?: boolean;\n /** Offset the drawer from the top of its container. When set, the area above this offset remains visible and interactive (e.g. keeping a navbar accessible). */\n topOffset?: string;\n /**\n * What the drawer becomes at phone width (≤ the sm breakpoint).\n * \"sheet\" (default for right and bottom): a draggable bottom Sheet with snap points.\n * \"panel\" (default for left, which is the navigation convention): a full-height side panel.\n * lightBackdrop and topOffset do not apply in sheet mode.\n */\n mobile?: \"sheet\" | \"panel\";\n /** Snap points for the phone-width Sheet, as fractions of the viewport. Default [0.5, 0.92]. */\n snapPoints?: number[];\n /**\n * Default true. false makes the drawer a persistent, non-modal panel the user works alongside\n * (an assistant, help): no backdrop, no scroll lock, no focus trap — the page stays operable.\n * It closes only on Escape while focus is inside it, its close control, or onClose from the\n * consumer; an outside click does nothing. At phone width the sheet it becomes is modal: a backdrop, the focus trap,\n * the scroll lock and Escape from anywhere, and focus moves in if the window narrows while it is open.\n */\n modal?: boolean;\n /**\n * Keep the panel in the DOM while closed (hidden and out of the tab order) so a half-typed\n * message, the scroll position and any in-progress rendering survive close and reopen.\n * Default false — the panel unmounts after its close transition, as it always has.\n */\n keepMounted?: boolean;\n /** id applied to the dialog element, for an opener's aria-controls. */\n id?: string;\n /** id of the element that names the dialog when no title is rendered — e.g. ChatPanel's heading. */\n labelledBy?: string;\n /**\n * Let the user drag the page-side edge to widen a non-modal side drawer,\n * between `width` and maxWidth (default 60% of the viewport). Default false —\n * ordinary drawers keep the one shared width. Ignored when modal or at phone width.\n */\n resizable?: boolean;\n maxWidth?: string;\n /** The content has unsaved changes: every close path asks before discarding, inside the drawer (Sprint 25.2, C1). */\n dirty?: boolean;\n /** Called when the user chooses to discard, before onClose. */\n onDiscard?: () => void;\n}\n\nconst slideClasses: Record<string, { panel: string; open: string; closed: string }> = {\n right: {\n panel: \"top-0 right-0 h-full\",\n open: \"translate-x-0\",\n closed: \"translate-x-full\",\n },\n left: {\n panel: \"top-0 left-0 h-full\",\n open: \"translate-x-0\",\n closed: \"-translate-x-full\",\n },\n bottom: {\n panel: \"bottom-0 left-0 right-0\",\n open: \"translate-y-0\",\n closed: \"translate-y-full\",\n },\n};\n\nconst borderByPosition: Record<string, string> = {\n right: \"border-l-[length:var(--ds-border-width)] border-l-[var(--ds-border-default)]\",\n left: \"border-r-[length:var(--ds-border-width)] border-r-[var(--ds-border-default)]\",\n bottom: \"border-t-[length:var(--ds-border-width)] border-t-[var(--ds-border-default)]\",\n};\n\nexport function Drawer(props: DrawerProps) {\n const { position = \"right\", mobile, open, onClose, footer, dirty, onDiscard } = props;\n // Sprint 25.14 A24: a Drawer given no width takes the app's, which the shell carries (520 px by default); outside a\n // shell it keeps 400 px. A width prop wins.\n const shellWidth = useContext(DrawerWidthCtx) ?? undefined;\n const isPhone = useBreakpoint(\"sm\");\n const mobileMode = mobile ?? (position === \"left\" ? \"panel\" : \"sheet\");\n // Sprint 25.12 A15: a form inside marks the drawer when the user changes something; a `dirty` prop still wins. The\n // drawer owns the mark in both its forms, so the sheet it becomes on a phone asks with the drawer's question.\n const { marked, mark } = useOverlayMark(open);\n const guard = useDirtyGuard(dirty ?? marked, onClose, onDiscard);\n const confirm = <DiscardConfirm open={guard.confirming} onKeep={guard.keep} onDiscard={guard.discard} />;\n\n // Registered actions from FormWrapper children (C10).\n const [actionsMap, setActionsMap] = useState<Map<string, ReactNode>>(new Map());\n const registerActions = useCallback((formId: string, acts: ReactNode) => {\n setActionsMap((prev) => new Map(prev).set(formId, acts));\n }, []);\n const unregisterActions = useCallback((formId: string) => {\n setActionsMap((prev) => { const next = new Map(prev); next.delete(formId); return next; });\n }, []);\n const registeredActions = actionsMap.size > 0\n ? <>{Array.from(actionsMap.values())}</>\n : null;\n // An explicit footer wins; otherwise fall back to FormWrapper-registered actions.\n const effectiveFooter = footer ?? registeredActions;\n const footerCtx = useMemo<DrawerFooterContextValue>(\n () => ({ registerActions, unregisterActions }),\n [registerActions, unregisterActions]\n );\n\n // Sprint 25.14 A50: one panel in both forms. Below `sm` it takes the sheet's form in place, so a phone turned\n // sideways and back keeps the content's elements (typed text, an upload, an editor's history, the unsaved-changes\n // mark) and focus; a Sheet here and a panel there were two trees, and crossing 640 px rebuilt the content.\n return (\n <DrawerFooterCtx value={footerCtx}>\n <OverlayMarkScope mark={mark}>\n <OverlayCloseCtx value={guard.requestClose}>\n <DrawerPanel {...props} width={props.width ?? shellWidth} form={isPhone && mobileMode === \"sheet\" ? \"sheet\" : \"panel\"} footer={effectiveFooter} onClose={guard.requestClose} confirm={confirm} />\n </OverlayCloseCtx>\n </OverlayMarkScope>\n </DrawerFooterCtx>\n );\n}\n\n/** The inset an overlay's header, body and footer share: the page's gutter (Sprint 25.14 A36, D34). */\nconst INSET = \"var(--ds-page-gutter)\";\nconst DEFAULT_SNAPS = [0.5, 0.92];\n\nexport interface DrawerPanelProps extends DrawerProps {\n /**\n * \"panel\": a side or bottom panel. \"sheet\": the phone's bottom sheet, with a drag handle and snap heights, always\n * modal. The Drawer switches between them at the `sm` breakpoint; the Sheet is always \"sheet\".\n */\n form: \"panel\" | \"sheet\";\n /** Between the body and the footer: the unsaved-changes question. */\n confirm?: ReactNode;\n}\n\n/** The Drawer's panel and the Sheet: one frame, so a Drawer changing form keeps its content (Sprint 25.14 A50). */\nexport function DrawerPanel({ form, open, onClose, position = \"right\", width = \"400px\", title, children, footer, container, flush, lightBackdrop, topOffset, modal = true, keepMounted = false, id, labelledBy, resizable = false, maxWidth, snapPoints = DEFAULT_SNAPS, confirm }: DrawerPanelProps) {\n const sheet = form === \"sheet\";\n const nonModal = !modal;\n // At phone width the sheet is always modal: the backdrop, the focus trap and the scroll lock. Focus on open and on\n // close follows `modal` alone, so a drawer that changes form while open leaves focus where it is.\n const blocking = !nonModal || sheet;\n // Drag-to-resize (non-modal side drawers only): the configured width is the\n // minimum; the user's choice is remembered for the session.\n const [chosen, remember] = useRememberedWidth(id ?? labelledBy);\n const canResize = !sheet && nonModal && resizable && position !== \"bottom\";\n const effectiveWidth = canResize && chosen !== null ? `${chosen}px` : width;\n const minPx = pxOf(width) ?? 320;\n const maxPx = () => pxOf(maxWidth) ?? defaultMaxWidth(container instanceof Element ? container : null);\n const titleId = useId();\n const { ref: titleOverflowRef, isTruncated: titleTruncated } = useTextOverflow({ lines: 1 });\n const isMobile = useBreakpoint(\"sm\");\n const panelRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(open);\n // keepMounted: the panel stays in the DOM and this flips instead of `mounted`.\n const [hidden, setHidden] = useState(!open);\n // The sheet's height: a snap point, plus the distance of a drag in progress.\n const [snapIdx, setSnapIdx] = useState(0);\n const [dragOffset, setDragOffset] = useState(0);\n const [dragging, setDragging] = useState(false);\n const dragStartY = useRef(0);\n const startHeight = useRef(0);\n const onCloseRef = useLatest(onClose);\n // Every open starts at the first snap point. React's \"adjust state when a prop changes\": it runs before commit, so\n // the first painted frame is already right.\n const [prevOpen, setPrevOpen] = useState(open);\n if (open !== prevOpen) {\n setPrevOpen(open);\n if (open) { setSnapIdx(0); setDragOffset(0); }\n }\n // Mount (or unhide) as soon as `open` flips, checked on every render (the visual pass of 23 September: the close\n // settle runs once at load and sets `mounted` false while it already is; React keeps that update and replays it\n // after the first open, so a panel mounted only on the change of `open` vanished on the first open after a load).\n if (open && !mounted) setMounted(true);\n if (open && hidden) setHidden(false);\n\n const isTopLayer = useOverlayLayer(open);\n\n // ── Modal mechanics (the default, and the phone's sheet, which is always modal) ──\n useEffect(() => {\n if (!open || !blocking) return;\n\n // An Escape a control inside already handled (a list closing) is its own; a non-modal drawer's own handler marks\n // the event handled, so a drawer that is both never closes twice.\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || e.defaultPrevented || !isTopLayer()) return;\n e.preventDefault();\n onCloseRef.current();\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [open, blocking, onCloseRef, isTopLayer]);\n\n useEffect(() => {\n if (!open || !blocking || container) return;\n lockBodyScroll();\n return () => unlockBodyScroll();\n }, [open, blocking, container]);\n\n useReturnFocus(open && !nonModal, panelRef);\n // A drawer offset below a navbar leaves that navbar interactive by design,\n // so it is not modal and must not trap focus; the phone's sheet always traps.\n useFocusTrap(panelRef, open && blocking && (sheet || !topOffset), isTopLayer);\n\n // The panel only exists once `mounted` flips, so depend on it too — an\n // [open]-only effect ran before the panel rendered and focused nothing.\n useEffect(() => {\n if (!open || !mounted || nonModal) return;\n const raf = requestAnimationFrame(() => focusInitial(panelRef.current));\n return () => cancelAnimationFrame(raf);\n }, [open, mounted, nonModal]);\n\n // ── Non-modal mechanics ──\n useNonModalDialog(panelRef, open && mounted && nonModal, onClose, isTopLayer);\n\n // A non-modal drawer that becomes the phone's modal sheet while open (the window narrowed, a phone turned) takes focus\n // in, as a modal does when it opens: its backdrop and its Tab trap now cover the page, so focus left out there typed\n // into a field no one could see (the review of 30 September).\n const wasBlocking = useRef(blocking);\n useEffect(() => {\n const was = wasBlocking.current;\n wasBlocking.current = blocking;\n if (!open || !mounted || !blocking || was) return;\n const panel = panelRef.current;\n if (panel && !panel.contains(document.activeElement)) focusInitial(panel);\n }, [open, mounted, blocking]);\n\n // the body keeps its right inset when a scrollbar takes room\n const bodyRef = useScrollbarInset<HTMLDivElement>();\n\n // After the close transition settles (at once under reduced motion): unmount,\n // or just hide when the consumer wants the panel's state preserved.\n useCloseSettle(open, panelRef, () => {\n if (keepMounted) setHidden(true);\n else setMounted(false);\n });\n\n // ── The sheet's drag ──\n // Snap fractions are relative to the viewport, or to the container when one is given.\n const viewportHeight = useCallback(\n () => (container instanceof HTMLElement ? container.clientHeight : window.innerHeight),\n [container],\n );\n const handlePointerDown = useCallback((e: React.PointerEvent) => {\n setDragging(true);\n dragStartY.current = e.clientY;\n startHeight.current = (snapPoints[snapIdx] ?? snapPoints[0]) * viewportHeight();\n setDragOffset(0);\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n }, [snapIdx, snapPoints, viewportHeight]);\n const handlePointerMove = useCallback((e: React.PointerEvent) => {\n if (!dragging) return;\n setDragOffset(dragStartY.current - e.clientY);\n }, [dragging]);\n const handlePointerUp = useCallback(() => {\n if (!dragging) return;\n setDragging(false);\n const currentFraction = (startHeight.current + dragOffset) / viewportHeight();\n if (currentFraction < snapPoints[0] * 0.6) {\n onClose();\n setDragOffset(0);\n return;\n }\n let bestIdx = 0;\n let bestDist = Math.abs(currentFraction - snapPoints[0]);\n for (let i = 1; i < snapPoints.length; i++) {\n const dist = Math.abs(currentFraction - snapPoints[i]);\n if (dist < bestDist) { bestDist = dist; bestIdx = i; }\n }\n setSnapIdx(bestIdx);\n setDragOffset(0);\n }, [dragging, dragOffset, snapPoints, onClose, viewportHeight]);\n\n if (!mounted) return null;\n\n const slide = slideClasses[position];\n const isHorizontal = position === \"left\" || position === \"right\";\n const positionClass = container ? \"absolute\" : \"fixed\";\n // lightBackdrop and topOffset do not apply to the sheet\n const offset = sheet ? undefined : topOffset;\n const baseHeight = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;\n const heightUnit = container ? \"%\" : \"vh\";\n const dragPx = dragging ? dragOffset : 0;\n const heading = \"font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate\";\n\n // Every element from here to the content is the same in both forms, so the content keeps its place in the tree when\n // the form changes (A50): what differs is classes and styles, and the handle and the resize edge beside the body.\n return createPortal(\n <div\n hidden={keepMounted && hidden ? true : undefined}\n className={cn(\n `${positionClass} transition-opacity duration-[var(--ds-transition-speed)]`,\n // A non-modal panel never intercepts the page: the wrapper is inert to the\n // pointer and only the panel itself accepts events.\n blocking ? cn(\"z-[var(--ds-z-modal)]\", open ? \"pointer-events-auto\" : \"pointer-events-none\") : \"z-[var(--ds-z-overlay)] pointer-events-none\",\n offset ? \"left-0 right-0 bottom-0\" : \"inset-0\",\n )}\n style={offset ? { top: offset } : undefined}\n >\n {/* Backdrop — modal only */}\n {blocking && (\n <div\n className={cn(\n \"absolute inset-0 transition-opacity duration-[var(--ds-transition-speed)]\",\n sheet\n ? \"bg-black/50\"\n : lightBackdrop\n ? \"bg-black/15\"\n : cn(\"bg-black/50\", \"[backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]\"),\n open ? \"opacity-100\" : \"opacity-0\"\n )}\n onClick={onClose}\n />\n )}\n\n {/* Panel */}\n <div\n ref={panelRef}\n id={id}\n role=\"dialog\"\n data-gs={sheet ? \"sheet\" : \"drawer\"}\n data-ds-sheet={sheet ? \"\" : undefined}\n {...{ [OVERLAY_ROOT_ATTR]: \"\" }}\n aria-modal={blocking ? \"true\" : undefined}\n aria-labelledby={title ? titleId : labelledBy}\n // a form in it takes the drawer's width, not the page's reading width (Sprint 25.16 A8)\n style={sheet ? {\n containerType: \"inline-size\",\n \"--ds-form-max\": \"none\",\n height: dragPx ? `calc(${baseHeight}${heightUnit} + ${dragPx}px)` : `${baseHeight}${heightUnit}`,\n } as CSSProperties : {\n containerType: \"inline-size\",\n \"--ds-form-max\": \"none\",\n width: isHorizontal ? effectiveWidth : undefined,\n maxWidth: isHorizontal ? \"100%\" : undefined,\n height: isMobile ? \"100%\" : undefined,\n maxHeight: !isMobile && !isHorizontal ? \"80vh\" : undefined,\n } as CSSProperties}\n className={cn(\n `${positionClass} z-10 flex flex-col`,\n !blocking && \"pointer-events-auto\",\n OVERLAY_SURFACE, \"text-[var(--ds-text-primary)]\",\n GLASS_OVERLAY,\n sheet ? cn(\n \"bottom-0 left-0 right-0\",\n \"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-t-[var(--ds-radius-xl)]\",\n !dragging && \"transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]\",\n open ? \"translate-y-0\" : \"translate-y-full\",\n ) : cn(\n // flush drops the edge border for children that draw their own (the mobile\n // menu's Sidebar); a non-modal panel has no backdrop to separate it from\n // the page, so it always keeps the border.\n (!flush || nonModal) && borderByPosition[position],\n \"transition-transform duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]\",\n isHorizontal && position === \"left\" && \"rounded-r-[var(--ds-radius-lg)] overflow-hidden\",\n isHorizontal && position === \"right\" && \"rounded-l-[var(--ds-radius-lg)] overflow-hidden\",\n !isHorizontal && \"rounded-t-[var(--ds-radius-lg)] overflow-hidden\",\n (lightBackdrop || nonModal) && \"shadow-[var(--ds-shadow-overlay)]\",\n slide.panel,\n open ? slide.open : slide.closed\n ),\n )}\n >\n {sheet && (\n <div\n className=\"flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n <div className=\"w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]\" />\n </div>\n )}\n\n {canResize && open && (\n <ResizeEdge\n edge={position === \"right\" ? \"left\" : \"right\"}\n width={chosen ?? minPx}\n min={minPx}\n max={maxPx}\n defaultWidth={minPx}\n onResize={(w) => remember(w === minPx ? null : w)}\n label=\"Resize panel\"\n />\n )}\n\n {/* Header */}\n {title && (\n <div\n className=\"flex items-center justify-between gap-ds-3 shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\"\n style={sheet ? { padding: `var(--ds-space-2) ${INSET}` } : {\n padding: `var(--ds-space-3) ${INSET}`,\n minHeight: \"calc(var(--ds-space-unit) * 6 + 1.75rem + 2px + var(--ds-border-width))\",\n }}\n >\n {!sheet && titleTruncated ? (\n <Tooltip content={title}>\n <h2 ref={titleOverflowRef} id={titleId} className={heading}>{title}</h2>\n </Tooltip>\n ) : (\n <h2 ref={titleOverflowRef} id={titleId} className={heading}>{title}</h2>\n )}\n <button type=\"button\"\n onClick={onClose}\n {...{ [OVERLAY_CLOSE_ATTR]: \"\" }}\n className=\"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer\"\n aria-label=\"Close\"\n >\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n )}\n\n {/* Content: a surface of its own, so a Card or a pane the drawer was declared in tells its content nothing */}\n <div\n ref={bodyRef}\n className=\"flex-1 overflow-y-auto\"\n style={flush ? undefined : { padding: `var(--ds-space-5) ${insetLessScrollbar(INSET)} var(--ds-space-5) ${INSET}` }}\n >\n <SurfaceBoundary>{children}</SurfaceBoundary>\n </div>\n\n {confirm}\n\n {/* Footer */}\n {footer && (\n <div\n className=\"shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\"\n style={{ padding: `var(--ds-space-3) ${INSET}` }}\n >\n {footer}\n </div>\n )}\n </div>\n </div>,\n container ?? document.body,\n );\n}\n","import { cn } from \"../lib/utils\";\n\ninterface SkipLinkProps {\n /** The id of the main region (AppShell names its <main> \"main\"). */\n href?: string;\n children?: string;\n className?: string;\n}\n\n/**\n * The first focusable element on a page with repeated navigation: invisible\n * until it receives keyboard focus, then a small floating button that jumps\n * past the sidebar and navbar to the main content (WCAG 2.4.1). AppShell\n * renders one by default; a page outside AppShell composes it first.\n */\nexport function SkipLink({ href = \"#main\", children = \"Skip to content\", className }: SkipLinkProps) {\n return (\n <a\n href={href}\n className={cn(\n \"sr-only focus:not-sr-only focus:fixed focus:top-[var(--ds-space-2)] focus:left-[var(--ds-space-2)] focus:z-[var(--ds-z-tooltip)]\",\n \"focus:px-[var(--ds-space-3)] focus:py-[var(--ds-space-2)] focus:rounded-[var(--ds-radius-md)] focus:text-sm focus:font-medium\",\n \"focus:bg-[var(--ds-bg-surface-elevated)] focus:text-[var(--ds-text-primary)] focus:shadow-[var(--ds-shadow-md)]\",\n \"focus:outline-none focus:ring-2 focus:ring-[var(--ds-accent-primary)]\",\n className\n )}\n >\n {children}\n </a>\n );\n}\n","import { version } from \"react\";\n\n/**\n * gridsmith-ui needs React 19: its components render React 19's context providers and take `ref` as a prop, so on\n * React 18 the shell crashes with React's own \"render is not a function\". The words a React 18 app gets instead, so\n * the fix is named (Sprint 25.7, the owner's call of 26 September 2026: the package says React 19 only). An\n * experimental build (0.0.0-…) is taken as current.\n */\nexport function reactVersionProblem(v: string = version): string | null {\n if (v.startsWith(\"0.0.0\")) return null;\n const major = Number.parseInt(v, 10);\n return Number.isFinite(major) && major < 19\n ? `gridsmith-ui needs React 19, and this app has React ${v}. Upgrade react, react-dom, @types/react and @types/react-dom to 19, then reinstall; an install forced with --force or --legacy-peer-deps cannot run.`\n : null;\n}\n\n/** Evaluated once: the shell and the page container throw it before rendering anything React 18 cannot. */\nexport const REACT_VERSION_PROBLEM = reactVersionProblem();\n","import { isValidElement, useState, useCallback, useEffect, useRef, forwardRef, createContext, useContext, type ReactNode } from \"react\";\nimport { REACT_VERSION_PROBLEM } from \"../lib/react-version\";\nimport type { AppShellTheme, ChromePosition } from \"../lib/shell-theme\";\nimport { PreferencesContext, type AppShellPreferences } from \"../lib/preferences\";\nimport { SkipLink } from \"./SkipLink\";\nimport { cn } from \"../lib/utils\";\nimport { useBreakpoint } from \"../lib/use-breakpoint\";\nimport { Drawer } from \"./Drawer\";\nimport { DrawerWidthCtx } from \"../lib/drawer-width\";\n\nexport interface AppShellContextValue {\n hasSidebar: boolean;\n hasMobileMenu: boolean;\n hasMobileNav: boolean;\n sidebarOpen: boolean;\n setSidebarOpen: (open: boolean) => void;\n isMobile: boolean;\n /** True only for tablet-sized viewports (between sm and md breakpoints). Drawer shows here, not on small mobile. */\n isTablet: boolean;\n /**\n * Effective sidebar collapse for a traditional Sidebar rendered in the shell.\n * The user's explicit choice wins; otherwise the auto tier applies — collapsed\n * to a rail at or below the `lg` breakpoint, expanded above it. Lives here rather\n * than in Sidebar so it survives the sidebar unmounting in the drawer range.\n */\n sidebarCollapsed: boolean;\n /** Records an explicit user choice. Overrides the auto tier in both directions for the session. */\n setSidebarCollapsed: (collapsed: boolean) => void;\n /** True while a docked AsidePanel in the aside slot is open beside the content. Pages may hide non-essential chrome on it. */\n asideOpen: boolean;\n /** Set by AsidePanel; not for pages to call. */\n setAsideOpen: (open: boolean) => void;\n /** Which side the aside slot is on (AppShell's asideSide). */\n asideSide: \"right\" | \"left\";\n /** True while the docked AsidePanel is floating — a floating PageHeader drops its gutter on that side, as it does beside a floating Sidebar. */\n asideFloating: boolean;\n /** Set by AsidePanel; not for pages to call. */\n setAsideFloating: (floating: boolean) => void;\n /**\n * The shell's root element, for previews that need to render overlays inside their frame\n * (the dashboard builder passes it to Launcher, CornerPanel and Drawer as `container`).\n * Components never read it themselves: a container moves the toast-inset claim onto that\n * element, where a body-level ToastProvider cannot see it.\n */\n container: HTMLElement | null;\n /** The theme's shell-level decisions (Sprint 25). PageHeader and PageContainer resolve their defaults from it. */\n theme: AppShellTheme | null;\n /** The current route is the home page (`currentPath === homePath`); decides `colourfulHomeOnly`. */\n isHome: boolean;\n /** The rendered Navbar floats (registered by the Navbar; the theme's `navbarPosition` until it has). */\n navbarFloating: boolean;\n /** The rendered Sidebar floats, and is a sidebar rather than a drawer: false below md and in stacked layouts. */\n sidebarFloating: boolean;\n /** Called by Sidebar and Navbar so the shell knows the chrome that is actually rendered. Returns the unregister. */\n registerChrome: (kind: \"navbar\" | \"sidebar\", position: ChromePosition) => () => void;\n /** True when the shell renders a Launcher above sm — PageContainer adjusts its bottom padding to clear the launcher. */\n hasLauncher: boolean;\n /** The bottom corner that launcher occupies (a ribbon occupies none), so the container reads that corner's inset variable. */\n launcherCorner: \"bottom-right\" | \"bottom-left\" | null;\n /** The shell renders an app footer under the page. Its children sit in a wrapper whose height is not definite, so a\n * `fill` SplitView reads `--ds-main-height` (published on the shell element) instead of `h-full`. */\n hasFooter: boolean;\n /** The flow this shell is in focus mode for (Sprint 25.7, C1), or null. The Navbar and PageHeader read it. */\n focus: AppShellFocus | null;\n /** A page inside the shell has unsaved changes (useUnsavedChanges): focus mode's Exit asks before it leaves. */\n hasUnsavedChanges: boolean;\n /** Set by useUnsavedChanges; not for pages to call. Returns the release. */\n addUnsavedChanges: () => () => void;\n /** The width every Drawer in the app takes when it is given none (Sprint 25.14 A24): AppShell's drawerWidth, 520 px by default. */\n drawerWidth: string;\n /** The app's router (AppShell's `navigate`), or null: the library's links in the shell (a breadcrumb's crumb) and a flow's steps go through it. */\n navigate: ((href: string, options?: { replace?: boolean }) => void) | null;\n /** A page that has left the flow is showing (<FlowSaved>, Sprint 25.16 A30): focus mode draws no exit control. */\n flowLeft: boolean;\n /** Set by FlowSaved; not for pages to call. Returns the release. */\n markFlowLeft: () => () => void;\n}\n\n/**\n * Focus mode (Sprint 25.7, C1): a task flow the user completes before or outside the app — setup, onboarding,\n * checkout, an import — renders in the same shell with the navigation taken away. The header keeps the logo and the\n * assistant, and its one way out is the exit control.\n */\nexport interface AppShellFocus {\n /**\n * `before-app`: a flow before the app (setup, onboarding). The exit control, \"Save and log out\", takes the user\n * menu's place. `in-app`: a flow inside the app (checkout, an import). \"Exit\" goes back to where the user came from,\n * asks first while the page has unsaved changes, and the user menu stays.\n */\n kind: \"before-app\" | \"in-app\";\n /** The exit control's label. Default \"Save and log out\" before the app, \"Exit\" inside it. */\n exitLabel?: string;\n /** What the exit control does: save and log out, or return to where the user came from. */\n onExit?: () => void;\n}\n\nconst AppShellContext = createContext<AppShellContextValue | null>(null);\n\nexport function useAppShell() {\n return useContext(AppShellContext);\n}\n\n/**\n * Tells the shell this page has unsaved changes, so focus mode's Exit asks before it leaves (Sprint 25.7, C1). Pass the\n * same `dirty` a Drawer takes; outside a shell it does nothing.\n */\nexport function useUnsavedChanges(dirty: boolean) {\n const add = useContext(AppShellContext)?.addUnsavedChanges;\n useEffect(() => {\n if (!dirty || !add) return;\n return add();\n }, [dirty, add]);\n}\n\ntype AppShellLayout = \"sidebar\" | \"stacked\" | \"sidebar-header\" | \"multi-column\";\n\ninterface AppShellProps {\n layout?: AppShellLayout;\n sidebar?: ReactNode;\n /** Content to render in the mobile drawer. For sidebar layouts, this is typically a Sidebar+SidebarNav. For header layouts, a MobileHeaderMenu. */\n mobileMenu?: ReactNode;\n /** Override drawer width for the mobile menu. Defaults to --ds-drawer-width. */\n mobileMenuWidth?: string;\n /** Use a lighter backdrop for the mobile menu drawer. */\n mobileMenuLightBackdrop?: boolean;\n /** Remove drawer padding and borders. Default true. Set false for compact overlays. */\n mobileMenuFlush?: boolean;\n navbar?: ReactNode;\n mobileNav?: ReactNode;\n /** Rendered below the page content inside the scrolling region and pinned to the bottom on short pages. Ignored when `scrollable` is false. */\n footer?: ReactNode;\n /** Render a SkipLink as the first focusable element (default true); it targets `mainId`. */\n skipLink?: boolean;\n /** The id of the <main> region the skip link jumps to. */\n mainId?: string;\n /** A docked AsidePanel rendered beside the content column: the page narrows to make room. Rendered at every width — the panel decides its own fallbacks. */\n aside?: ReactNode;\n /** Which side of the content the aside sits on. Default \"right\". Pass the same value to the AsidePanel. */\n asideSide?: \"right\" | \"left\";\n /**\n * A Launcher for the assistant. Rendered only above the sm breakpoint — a conditional render,\n * because the Launcher portals out of any wrapper — so on phones the Navbar button is the entry point\n * and it never collides with BottomNav.\n */\n launcher?: ReactNode;\n children: ReactNode;\n className?: string;\n /** When false, main area won't scroll — use for full-height layouts like ResizablePanelGroup. Default true. */\n scrollable?: boolean;\n /** The theme's shell-level decisions: what the generated shell passes once so pages carry nothing (Sprint 25). */\n theme?: AppShellTheme;\n /** The customer's UX preferences, passed once by the generated shell so pages and components carry nothing (Sprint 25.6). */\n preferences?: AppShellPreferences;\n /**\n * The width of every Drawer in the app that is given none (Sprint 25.14 A24): pages pass no width, so the app's\n * drawers share one. Default \"520px\". A Drawer's own width prop still wins, for a deliberate wide or narrow one.\n */\n drawerWidth?: string;\n /** The current route's path, so the shell knows which page is home. */\n currentPath?: string;\n /** The home page's path. Default \"/\". */\n homePath?: string;\n /**\n * The app's router: `(href, options) => navigate(href, options)` with React Router, `(href, options) =>\n * (options?.replace ? router.replace(href) : router.push(href))` with Next.js. The library's links in the shell — a\n * breadcrumb's crumb, a SplitView's path — go through it on a plain click, so the page changes with no reload, and so\n * do a flow's steps (useFlowSteps), which replace an address that isn't a step reached (Sprint 25.16 A19, A30).\n * Without it they are ordinary links. The generated layout passes it.\n */\n navigate?: (href: string, options?: { replace?: boolean }) => void;\n /**\n * Focus mode for a flow outside the navigation (setup, onboarding, checkout). The sidebar, mobile menu and bottom\n * nav are not rendered, and the Navbar drops its links and search; the logo, the assistant (its launcher and its\n * docked panel in the aside slot), the skip link, the theme, the preferences and the page spacing stay. The\n * generated layout passes it; a page never does.\n */\n focus?: AppShellFocus;\n}\n\nexport const AppShell = forwardRef<HTMLDivElement, AppShellProps>(function AppShell({\n layout = \"sidebar\",\n sidebar,\n mobileMenu,\n mobileMenuWidth,\n mobileMenuLightBackdrop,\n mobileMenuFlush = true,\n navbar,\n mobileNav,\n footer,\n skipLink = true,\n mainId = \"main\",\n aside,\n asideSide = \"right\",\n launcher,\n children,\n className,\n scrollable = true,\n theme,\n preferences,\n currentPath,\n homePath = \"/\",\n navigate,\n focus,\n drawerWidth = \"520px\",\n}, ref) {\n // gridsmith-ui needs React 19: say so before rendering anything React 18 cannot (the package says React 19 only)\n if (REACT_VERSION_PROBLEM) throw new Error(REACT_VERSION_PROBLEM);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [asideOpen, setAsideOpen] = useState(false);\n const [asideFloating, setAsideFloating] = useState(false);\n const isMobile = useBreakpoint(\"md\");\n const isSmallMobile = useBreakpoint(\"sm\");\n const isTablet = isMobile && !isSmallMobile;\n // Sidebar tiers: expanded above lg, auto-rail between md and lg, drawer at or below md.\n // `userCollapsed` is null until the collapse button is used; from then on it wins.\n const autoCollapsed = useBreakpoint(\"lg\");\n const [userCollapsed, setUserCollapsed] = useState<boolean | null>(null);\n const sidebarCollapsed = userCollapsed ?? autoCollapsed;\n // Focus mode takes the navigation away: no sidebar, mobile menu or bottom nav, and the context says so. The aside\n // stays: in the generated shell it is the assistant's docked panel, and a flow keeps the assistant (D9).\n const inFocus = focus != null;\n const hasSidebar = !inFocus && (layout === \"sidebar\" || layout === \"sidebar-header\") && sidebar != null;\n const hasMobileMenu = !inFocus && mobileMenu != null;\n const hasMobileNav = !inFocus && mobileNav != null;\n const [unsavedCount, setUnsavedCount] = useState(0);\n const addUnsavedChanges = useCallback(() => {\n setUnsavedCount((n) => n + 1);\n let released = false;\n return () => { if (released) return; released = true; setUnsavedCount((n) => n - 1); };\n }, []);\n // Sprint 25.16 A30: \"Your progress has been saved\" has left the flow, so the flow's way out goes while it shows\n const [leftCount, setLeftCount] = useState(0);\n const markFlowLeft = useCallback(() => {\n setLeftCount((n) => n + 1);\n let released = false;\n return () => { if (released) return; released = true; setLeftCount((n) => n - 1); };\n }, []);\n const showMobileDrawer = hasMobileMenu && !(isSmallMobile && hasMobileNav);\n const [shellEl, setShellEl] = useState<HTMLDivElement | null>(null);\n // The chrome that is actually rendered, reported by Sidebar and Navbar; the theme's positions until they report.\n const [chrome, setChrome] = useState<{ navbar?: ChromePosition; sidebar?: ChromePosition }>({});\n const registerChrome = useCallback((kind: \"navbar\" | \"sidebar\", position: ChromePosition) => {\n setChrome((c) => (c[kind] === position ? c : { ...c, [kind]: position }));\n return () => setChrome((c) => { if (!(kind in c)) return c; const next = { ...c }; delete next[kind]; return next; });\n }, []);\n const navbarFloating = (chrome.navbar ?? theme?.navbarPosition) === \"floating\";\n const sidebarFloating = hasSidebar && !isMobile && (chrome.sidebar ?? theme?.sidebarPosition) === \"floating\";\n const isHome = currentPath != null && currentPath === homePath;\n // With a footer the children wrapper is `min-h-full`, which gives a child no definite height to fill (C6): main's\n // height is published as --ds-main-height on the shell element for the fill SplitView. Written straight to the\n // element from a ResizeObserver; nothing re-renders.\n const hasFooter = footer != null && scrollable;\n const mainRef = useRef<HTMLElement | null>(null);\n useEffect(() => {\n const main = mainRef.current;\n if (!hasFooter || !shellEl || !main || typeof ResizeObserver === \"undefined\") { shellEl?.style.removeProperty(\"--ds-main-height\"); return; }\n const ro = new ResizeObserver(() => shellEl.style.setProperty(\"--ds-main-height\", `${main.clientHeight}px`));\n ro.observe(main);\n return () => { ro.disconnect(); shellEl.style.removeProperty(\"--ds-main-height\"); };\n }, [hasFooter, shellEl]);\n\n // C7: the launcher element says which corner it takes (Launcher's `edge`; a ribbon claims no corner).\n const hasLauncher = !!launcher && !isSmallMobile;\n const launcherProps = isValidElement(launcher) ? (launcher.props as { edge?: string; variant?: string }) : null;\n const launcherCorner: AppShellContextValue[\"launcherCorner\"] = !hasLauncher ? null\n : launcherProps?.variant === \"ribbon\" ? null\n : launcherProps?.edge === \"bottom-left\" ? \"bottom-left\"\n : launcherProps?.edge === \"right\" || launcherProps?.edge === \"left\" || launcherProps?.edge === \"bottom\" ? null\n : \"bottom-right\";\n\n return (\n <PreferencesContext value={preferences ?? null}>\n <DrawerWidthCtx value={drawerWidth}>\n <AppShellContext\n value={{ hasSidebar, hasMobileMenu, hasMobileNav, sidebarOpen, setSidebarOpen, isMobile, isTablet, sidebarCollapsed, setSidebarCollapsed: setUserCollapsed, asideOpen, setAsideOpen, asideSide, asideFloating, setAsideFloating, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome, hasLauncher, launcherCorner, hasFooter, focus: focus ?? null, hasUnsavedChanges: unsavedCount > 0, addUnsavedChanges, drawerWidth, navigate: navigate ?? null, flowLeft: leftCount > 0, markFlowLeft }}\n >\n <div ref={(el) => {\n setShellEl(el);\n if (typeof ref === \"function\") ref(el);\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = el;\n }} className={cn(\n // Sprint 25.16 A42: the dynamic viewport where the browser has it, so nothing hides under a phone browser's\n // toolbar (100vh is the height with the toolbar hidden)\n \"relative h-screen supports-[height:100dvh]:h-dvh flex flex-col bg-[var(--ds-bg-canvas)] overflow-hidden\",\n className,\n )}>\n {skipLink && <SkipLink href={`#${mainId}`} />}\n {layout === \"sidebar-header\" && navbar}\n {layout === \"multi-column\" && navbar}\n\n <div className=\"flex flex-1 min-h-0\">\n {hasSidebar && !isMobile && (\n <div className=\"shrink-0 h-full\">\n {sidebar}\n </div>\n )}\n\n {/* A left-docked aside sits between the sidebar and the content. */}\n {aside && asideSide === \"left\" && aside}\n\n <div className=\"flex-1 flex flex-col min-w-0 min-h-0\">\n {layout === \"sidebar\" && navbar}\n {layout === \"stacked\" && navbar}\n\n <main\n ref={mainRef}\n id={mainId}\n data-shell-main=\"\" /* Sprint 25.16 A42: the page's height, which a view that fills takes (useFillHeight) */\n tabIndex={-1} /* the skip link's target: focusable by script, never by Tab */\n className={cn(\n \"flex-1 min-h-0 focus:outline-none\",\n scrollable ? \"overflow-y-auto\" : \"relative\",\n layout === \"multi-column\" && \"flex\",\n )}\n style={{ containerType: \"inline-size\" }}\n >\n {scrollable ? (\n footer ? (\n <div className=\"min-h-full flex flex-col\">\n {/* the page's own content: a view that fills it stops here, and the footer sits below the fold */}\n <div className=\"flex-1\" data-shell-content=\"\">{children}</div>\n {footer}\n </div>\n ) : children\n ) : (\n <div className=\"absolute inset-0\">{children}</div>\n )}\n </main>\n </div>\n\n {/* The content column is flex-1 min-w-0, so it gives up width to the aside and <main>'s container query fires. */}\n {aside && asideSide === \"right\" && aside}\n </div>\n\n {showMobileDrawer && isMobile && (\n <Drawer\n open={sidebarOpen}\n onClose={() => setSidebarOpen(false)}\n position=\"left\"\n width={mobileMenuWidth ?? \"var(--ds-drawer-width)\"}\n container={shellEl ?? undefined}\n flush={mobileMenuFlush}\n lightBackdrop={mobileMenuLightBackdrop}\n topOffset={layout !== \"stacked\" && navbar != null ? \"var(--ds-navbar-height)\" : undefined}\n >\n {mobileMenu}\n </Drawer>\n )}\n\n {isSmallMobile && hasMobileNav && (\n <div className=\"sticky bottom-0 z-[var(--ds-z-sticky)]\">\n {mobileNav}\n </div>\n )}\n\n {/* Phone width: the Navbar button is the entry point; the launcher is not rendered at all. */}\n {!isSmallMobile && launcher}\n </div>\n </AppShellContext>\n </DrawerWidthCtx>\n </PreferencesContext>\n );\n});\n","import { useState, useRef, useEffect, useCallback, forwardRef, type KeyboardEvent as ReactKeyboardEvent, type MouseEvent as ReactMouseEvent } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { usePopupFocus } from \"../lib/focus\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type IconName } from \"../lib/icons\";\nimport { usePosition } from \"../lib/use-position\";\nimport { useAppShell } from \"./AppShell\";\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n onClick?: () => void;\n icon?: IconName;\n}\n\nexport type BreadcrumbsVariant = \"inline\" | \"contained\" | \"pill\";\nexport type BreadcrumbsSeparator = \"slash\" | \"chevron\" | \"dot\" | \"arrow\";\nexport type BreadcrumbsSize = \"sm\" | \"md\";\n\ninterface BreadcrumbsProps {\n items: BreadcrumbItem[];\n separator?: BreadcrumbsSeparator;\n variant?: BreadcrumbsVariant;\n /** Visual treatment of individual breadcrumb items — independent of layout variant. */\n itemVariant?: \"default\" | \"pill\";\n size?: BreadcrumbsSize;\n showIcons?: boolean;\n maxItems?: number;\n /** Full-bleed: contained background extends edge-to-edge, breaking out of parent padding. Text stays aligned with sibling content. */\n bleed?: boolean;\n /** Max-width for bleed content alignment. Defaults to --ds-bp-xl. */\n contentMaxWidth?: string;\n className?: string;\n container?: Element | DocumentFragment;\n /** The landmark's name. Default \"Breadcrumb\"; a second trail on the page names itself (SplitView's path: \"Path\"). */\n \"aria-label\"?: string;\n}\n\n/**\n * Sprint 25.16 A19: how a crumb is followed, for Breadcrumbs and for PageHeader's own crumbs. A crumb that is a page\n * goes there, through the app's router when the shell has one (AppShell's navigate), so the page changes with no\n * reload; with none it is an ordinary link. A crumb's onClick runs instead. A click with a modifier key or another\n * button (a new tab, a new window) on a crumb with an address keeps the browser's own behaviour, whatever handler the\n * crumb has; an address on another site is an ordinary link, as a router's own Link leaves it (the review of 1\n * October). Every click used to be cancelled, so a crumb with only an address did nothing (runs 11, 18 and 33).\n */\nexport function useCrumbFollow() {\n const navigate = useAppShell()?.navigate ?? null;\n return useCallback((e: ReactMouseEvent, item: BreadcrumbItem) => {\n if (item.href && (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)) return;\n if (item.onClick) { e.preventDefault(); item.onClick(); return; }\n if (!item.href) { e.preventDefault(); return; }\n if (!navigate || e.defaultPrevented || !onThisSite(item.href)) return;\n e.preventDefault();\n navigate(item.href);\n }, [navigate]);\n}\n\n/** An address this app's router can go to: relative, or on this page's own origin. */\nfunction onThisSite(href: string): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return new URL(href, window.location.href).origin === window.location.origin;\n } catch {\n return false;\n }\n}\n\n/** A crumb that goes somewhere: a page (href) or an item the app selects (onClick). Any other is text. */\nexport const crumbGoes = (item: BreadcrumbItem) => !!(item.href || item.onClick);\n\nfunction SeparatorIcon({ type, size }: { type: BreadcrumbsSeparator; size: BreadcrumbsSize }) {\n const iconSize = size === \"sm\" ? 10 : 12;\n if (type === \"chevron\") return <Icon name=\"chevron-right\" size={iconSize} />;\n if (type === \"arrow\") return <Icon name=\"arrow-right\" size={iconSize} />;\n if (type === \"dot\") return <span>·</span>;\n return <span>/</span>;\n}\n\nexport const Breadcrumbs = forwardRef<HTMLElement, BreadcrumbsProps>(function Breadcrumbs({\n items,\n separator = \"chevron\",\n variant = \"inline\",\n itemVariant,\n size = \"md\",\n showIcons = false,\n maxItems,\n bleed = false,\n contentMaxWidth,\n className,\n container,\n \"aria-label\": label = \"Breadcrumb\",\n}, ref) {\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const follow = useCrumbFollow();\n const [activeIdx, setActiveIdx] = useState(0);\n const ellipsisBtnRef = useRef<HTMLButtonElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const closeDropdown = useCallback(() => setDropdownOpen(false), []);\n // Sprint 25.7: the hidden crumbs are a menu. The arrows move through it, Tab leaves it and carries on from the\n // \"···\" button (\"any\"), Escape hands focus back to the button, and a choice leaves focus to the page it opens.\n const { isTop, returnFocus } = usePopupFocus(dropdownOpen, { trigger: ellipsisBtnRef, panel: dropdownRef, close: closeDropdown, tabExits: \"any\" });\n\n const pos = usePosition(ellipsisBtnRef, dropdownRef, dropdownOpen, { side: \"bottom\", align: \"start\", offset: 4, flip: true });\n\n const effectiveMaxItems = maxItems ? Math.max(maxItems, 2) : undefined;\n const shouldCollapse = effectiveMaxItems && items.length > effectiveMaxItems;\n const collapsedItems = shouldCollapse ? items.slice(1, -(effectiveMaxItems - 1)) : [];\n const visibleItems = shouldCollapse\n ? [...items.slice(0, 1), null, ...items.slice(-(effectiveMaxItems - 1))]\n : items;\n\n useEffect(() => {\n if (!dropdownOpen) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (ellipsisBtnRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;\n setDropdownOpen(false);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || e.defaultPrevented || !isTop()) return;\n e.preventDefault();\n returnFocus();\n setDropdownOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"mousedown\", handler);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [dropdownOpen, isTop, returnFocus]);\n\n // Focus follows the active item, from the first one on open.\n useEffect(() => {\n if (!dropdownOpen) return;\n const id = requestAnimationFrame(() => dropdownRef.current?.querySelector<HTMLElement>(`[data-index=\"${activeIdx}\"]`)?.focus());\n return () => cancelAnimationFrame(id);\n }, [dropdownOpen, activeIdx]);\n\n function onMenuKeyDown(e: ReactKeyboardEvent) {\n const last = collapsedItems.length - 1;\n const next = e.key === \"ArrowDown\" ? (activeIdx >= last ? 0 : activeIdx + 1)\n : e.key === \"ArrowUp\" ? (activeIdx <= 0 ? last : activeIdx - 1)\n : e.key === \"Home\" ? 0\n : e.key === \"End\" ? last\n : null;\n if (next === null) return;\n e.preventDefault();\n setActiveIdx(next);\n }\n\n // Links, separators and the overflow button read --ds-text-secondary, not\n // --ds-text-muted: neutral-400 is 2.4:1 on canvas and 2.2:1 on the contained\n // band, well short of AA; neutral-600 clears it on both in light and dark.\n const textClass = size === \"sm\" ? \"text-xs\" : \"text-sm\";\n const gapClass = size === \"sm\" ? \"gap-ds-1\" : \"gap-ds-1.5\";\n const iconSize = size === \"sm\" ? 12 : 14;\n\n const isContainedBleed = variant === \"contained\" && bleed;\n\n const wrapperClasses = cn(\n variant === \"contained\" && !bleed && cn(\n \"bg-[var(--ds-bg-muted)] rounded-[var(--ds-radius-md)]\",\n size === \"sm\" ? \"py-ds-1 px-ds-2\" : \"py-ds-1.5 px-ds-3\",\n ),\n !isContainedBleed && className,\n );\n\n function renderItem(item: BreadcrumbItem, _index: number, isLast: boolean) {\n const isPill = itemVariant === \"pill\" || (variant === \"pill\" && !itemVariant);\n const insideContained = variant === \"contained\";\n const pillClasses = isPill\n ? cn(\n \"rounded-[var(--ds-radius-full)]\",\n insideContained ? \"bg-[var(--ds-bg-surface)]\" : \"bg-[var(--ds-bg-muted)]\",\n size === \"sm\" ? \"px-ds-2 py-[2px]\" : \"px-ds-2.5 py-ds-0.5\",\n )\n : \"\";\n\n const content = (\n <>\n {showIcons && item.icon && (\n <Icon name={item.icon} size={iconSize} className=\"shrink-0\" />\n )}\n <span className=\"truncate\">{item.label}</span>\n </>\n );\n\n // a crumb that goes nowhere is text, never a link to \"#\", and the last such is the current page; a crumb that goes\n // somewhere is a link wherever it stands, as PageHeader's are: a trail that ends at the page's parent (a SplitView's\n // path, the owner's review of 1 October) ends with its way back\n if (!crumbGoes(item)) {\n return (\n <span\n aria-current={isLast ? \"page\" : undefined}\n className={cn(\n \"flex items-center\",\n isLast ? \"font-medium text-[var(--ds-text-primary)]\" : \"text-[var(--ds-text-secondary)]\",\n gapClass,\n pillClasses,\n )}\n >\n {content}\n </span>\n );\n }\n\n return (\n <a\n href={item.href ?? \"#\"}\n onClick={(e) => follow(e, item)}\n className={cn(\n \"text-[var(--ds-text-secondary)] flex items-center\",\n \"hover:text-[var(--ds-text-primary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n gapClass,\n pillClasses,\n )}\n >\n {content}\n </a>\n );\n }\n\n const listContent = (\n <ol className={cn(\"flex items-center flex-wrap\", gapClass, textClass)}>\n {visibleItems.map((item, i) => {\n if (item === null) {\n return (\n <li key=\"__ellipsis\" className={cn(\"flex items-center\", gapClass)}>\n {i > 0 && (\n <span aria-hidden className=\"text-[var(--ds-text-secondary)] select-none flex items-center\">\n <SeparatorIcon type={separator} size={size} />\n </span>\n )}\n <button type=\"button\"\n ref={ellipsisBtnRef}\n onClick={() => { if (!dropdownOpen) setActiveIdx(0); setDropdownOpen(!dropdownOpen); }}\n aria-label=\"Show hidden breadcrumbs\"\n aria-expanded={dropdownOpen}\n aria-haspopup=\"menu\"\n className={cn(\n \"text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)] cursor-pointer\",\n \"flex items-center\",\n (itemVariant === \"pill\" || (variant === \"pill\" && !itemVariant)) && cn(\n \"rounded-[var(--ds-radius-full)]\",\n variant === \"contained\" ? \"bg-[var(--ds-bg-surface)]\" : \"bg-[var(--ds-bg-muted)]\",\n size === \"sm\" ? \"px-ds-2 py-[2px]\" : \"px-ds-2.5 py-ds-0.5\",\n ),\n )}\n >\n ···\n </button>\n </li>\n );\n }\n\n const isLast = i === visibleItems.length - 1;\n return (\n <li key={i} className={cn(\"flex items-center\", gapClass)}>\n {i > 0 && (\n <span aria-hidden className=\"text-[var(--ds-text-secondary)] select-none flex items-center\">\n <SeparatorIcon type={separator} size={size} />\n </span>\n )}\n {renderItem(item, i, isLast)}\n </li>\n );\n })}\n </ol>\n );\n\n const dropdown = dropdownOpen && collapsedItems.length > 0 && createPortal(\n <div\n ref={dropdownRef}\n role=\"menu\"\n aria-label=\"Hidden breadcrumbs\"\n onKeyDown={onMenuKeyDown}\n className={cn(\n \"fixed z-[var(--ds-z-popover)] min-w-[160px] max-h-60 overflow-auto\",\n \"bg-[var(--ds-bg-surface-elevated)]\",\n \"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]\",\n \"py-ds-1\",\n )}\n style={{ top: pos.top, left: pos.left }}\n >\n {collapsedItems.map((ci, idx) => {\n const itemClass = cn(\n \"flex items-center w-full text-left text-sm cursor-pointer\",\n \"px-ds-3 py-ds-1.5 transition-colors\",\n \"text-[var(--ds-text-secondary)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n \"focus-visible:outline-none focus-visible:bg-[var(--ds-bg-muted)] focus-visible:text-[var(--ds-text-primary)] focus-visible:shadow-[inset_var(--ds-shadow-focus)]\",\n gapClass,\n );\n const label = <>{showIcons && ci.icon && <Icon name={ci.icon} size={iconSize} className=\"shrink-0\" />}{ci.label}</>;\n // Sprint 25.16 A19: a hidden crumb that is a page is a link, as a drawn one is: the router on a plain click, a new\n // tab on a modified one, and its address to copy. Space chooses it too, as it does any menu item.\n return ci.href && !ci.onClick ? (\n <a\n key={idx}\n data-index={idx}\n role=\"menuitem\"\n href={ci.href}\n tabIndex={idx === activeIdx ? 0 : -1}\n className={itemClass}\n onClick={(e) => { setDropdownOpen(false); follow(e, ci); }}\n onKeyDown={(e) => { if (e.key === \" \") { e.preventDefault(); e.currentTarget.click(); } }}\n >\n {label}\n </a>\n ) : (\n <button type=\"button\"\n key={idx}\n data-index={idx}\n role=\"menuitem\"\n tabIndex={idx === activeIdx ? 0 : -1}\n aria-disabled={!crumbGoes(ci) || undefined}\n className={itemClass}\n onClick={() => { if (!ci.onClick) return; setDropdownOpen(false); ci.onClick(); }}\n >\n {label}\n </button>\n );\n })}\n </div>,\n container ?? document.body\n );\n\n if (isContainedBleed) {\n return (\n <nav\n ref={ref}\n aria-label={label}\n className={cn(\n \"w-full bg-[var(--ds-bg-muted)]\",\n // Hairline under the band: it sits within ~1.2:1 of both canvas and a tinted header, so the edge needs a line.\n \"border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n className,\n )}\n >\n <div\n className={cn(\"w-full mx-auto px-ds-6\", size === \"sm\" ? \"py-ds-1\" : \"py-ds-1.5\")}\n style={{ maxWidth: contentMaxWidth ?? \"var(--ds-bp-xl)\" }}\n >\n {listContent}\n </div>\n {dropdown}\n </nav>\n );\n }\n\n return (\n <nav ref={ref} aria-label={label} className={wrapperClasses}>\n {listContent}\n {dropdown}\n </nav>\n );\n});\n","import { useState, useCallback, useLayoutEffect, type RefObject } from \"react\";\nimport { readBreakpointPx, type BreakpointKey } from \"./use-breakpoint\";\n\n/**\n * True when the observed element is narrower than the breakpoint — a container\n * measurement, not the viewport, so a layout inside a sidebar shell or the\n * builder's canvas answers for the width it actually has. One implementation\n * for TableToolbar, SettingsLayout and the examples (Sprint 25.2).\n *\n * An unlaid-out element (tests, SSR) reports width 0 and is treated as not\n * compact; tests inject a width by overriding `offsetWidth`.\n */\nexport function useCompact(ref: RefObject<HTMLElement | null>, breakpoint: number | BreakpointKey, band = 0): boolean {\n const px = typeof breakpoint === \"number\" ? breakpoint : readBreakpointPx(breakpoint);\n const width = useElementWidth(ref);\n return useBelow(width, px, band);\n}\n\n/**\n * Whether a width is below a threshold, held across `band` px above it once it is (round 27 review): a layout whose\n * answer changes the width it measures — an aside that collapses removes a page scrollbar, which widens the layout\n * back over the threshold — otherwise flips on every frame at the edge (SplitView's aside toggled about 90 times in\n * 1.5 s with a 15 px scrollbar). The answer turns true below `threshold` and false again only at `threshold + band`.\n * A width of 0 (no layout yet) is never below.\n */\nexport function useBelow(width: number, threshold: number, band = 0): boolean {\n const [below, setBelow] = useState(false);\n const next = width > 0 && width < (below ? threshold + band : threshold);\n // render-time state adjustment: the answer is known now, so no frame paints the other one\n if (next !== below) setBelow(next);\n return next;\n}\n\n/** The element's laid-out width in px, kept current by a ResizeObserver; 0 until it has a layout (tests, SSR). */\nexport function useElementWidth(ref: RefObject<HTMLElement | null>): number {\n const [width, setWidth] = useState(0);\n const check = useCallback(() => {\n const next = ref.current?.offsetWidth ?? 0;\n if (next > 0) setWidth(next);\n }, [ref]);\n useLayoutEffect(() => {\n check();\n if (!ref.current || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(check);\n observer.observe(ref.current);\n return () => observer.disconnect();\n }, [check, ref]);\n return width;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/components/CodeBlock.tsx","../../../showcase/src/components/Link.tsx","../../../showcase/src/components/Divider.tsx"],"names":["Link","jsxs","jsx"],"mappings":"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","file":"chunk-MYIJNVTK.js","sourcesContent":["import { useState, useCallback } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Badge } from \"./Badge\";\n\ninterface CodeBlockProps {\n code: string;\n language?: string;\n showLineNumbers?: boolean;\n /** Wrap long lines instead of scrolling sideways. Default: on for a single-line snippet (a tracking tag, a command), off for multi-line code. */\n wrap?: boolean;\n className?: string;\n}\n\nexport function CodeBlock({\n code,\n language,\n showLineNumbers = false,\n wrap,\n className,\n}: CodeBlockProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch {\n /* clipboard not available */\n }\n }, [code]);\n\n const lines = code.split(\"\\n\");\n const wraps = wrap ?? lines.length === 1;\n const gutterWidth = showLineNumbers ? `${String(lines.length).length + 1}ch` : undefined;\n\n return (\n <div\n className={cn(\n \"relative group\",\n \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-shadow-sm)]\",\n \"overflow-hidden\",\n className,\n )}\n >\n <div className=\"flex items-center justify-between px-ds-4 py-ds-2 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-bg-muted)]\">\n <div className=\"flex items-center gap-ds-2\">\n {language && <Badge variant=\"outline\" size=\"sm\">{language}</Badge>}\n </div>\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"inline-flex items-center gap-ds-1.5 px-ds-2 py-ds-1 text-xs font-medium cursor-pointer\",\n \"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]\",\n \"rounded-[var(--ds-radius-sm)]\",\n \"hover:bg-[var(--ds-bg-surface)]\",\n \"transition-colors\",\n \"focus-visible:shadow-[var(--ds-shadow-focus)] outline-none\",\n )}\n aria-label={copied ? \"Copied\" : \"Copy code\"}\n >\n <Icon name={copied ? \"check\" : \"folder\"} size={14} />\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n\n <div className={wraps ? undefined : \"overflow-x-auto\"} data-wrap={wraps ? \"true\" : undefined}>\n <pre className={cn(\"p-ds-4 text-sm leading-relaxed font-[family-name:var(--ds-font-mono)]\", wraps && \"whitespace-pre-wrap break-words\")}>\n <code>\n {lines.map((line, i) => (\n // with line numbers each line is a two-column row, so a wrapped line continues under its text, not under the gutter\n <span key={i} className={showLineNumbers ? \"grid grid-cols-[max-content_1fr]\" : \"block\"}>\n {showLineNumbers && (\n <span\n className=\"text-right text-[var(--ds-text-muted)] select-none mr-ds-4 opacity-50\"\n style={{ width: gutterWidth }}\n >\n {i + 1}\n </span>\n )}\n <span className=\"min-w-0\">{line || \" \"}</span>\n </span>\n ))}\n </code>\n </pre>\n </div>\n </div>\n );\n}\n","import { forwardRef, type AnchorHTMLAttributes, type ElementType, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { slotIcon, type IconSlot } from \"../lib/icons\";\n\ntype LinkUnderline = \"hover\" | \"always\" | \"none\";\ntype LinkTone = \"accent\" | \"muted\" | \"inherit\";\n\nexport interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string;\n children: ReactNode;\n /** When to show the underline. Default \"hover\". */\n underline?: LinkUnderline;\n /** Colour: accent (default), muted for secondary links, inherit to match surrounding text. */\n tone?: LinkTone;\n /** Opens in a new tab with rel=\"noopener noreferrer\". Default false. */\n external?: boolean;\n /**\n * Render through a router link component instead of a plain anchor\n * (e.g. `component={RouterLink}` from react-router or next/link). The\n * component receives the same props; `href` is also passed as `to` for\n * react-router compatibility. Any element type: a router's Link requires\n * its own props (react-router's `to`), which a narrower type refused under\n * strict TypeScript (Sprint 25.16 A19).\n */\n component?: ElementType;\n /** An icon name (\"info\"), drawn as the theme's icon at 14 px, or an element. Not text: use children. */\n iconLeft?: IconSlot;\n /** As iconLeft, after the label. */\n iconRight?: IconSlot;\n}\n\nconst toneStyles: Record<LinkTone, string> = {\n accent: \"text-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary-hover)] active:text-[var(--ds-accent-primary-active)]\",\n muted: \"text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)]\",\n inherit: \"text-inherit hover:text-[var(--ds-accent-primary)]\",\n};\n\nconst underlineStyles: Record<LinkUnderline, string> = {\n hover: \"no-underline hover:underline\",\n always: \"underline underline-offset-2\",\n none: \"no-underline\",\n};\n\n/**\n * Navigation link. Renders a real <a> (or a router link via `component`) so\n * middle-click, open-in-new-tab, right-click \"copy link\" and screen readers\n * all behave correctly. Visually identical to Button variant=\"link\".\n *\n * Use Link for NAVIGATION (to a page or URL). Use Button variant=\"link\" for an\n * ACTION that should look like a link (show more, resend code). Never use a\n * ghost Button for inline text — its padding breaks the line.\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(\n { href, children, underline = \"hover\", tone = \"accent\", external = false, component: Component, iconLeft, iconRight, className, target, rel, ...props },\n ref,\n) {\n const classes = cn(\n \"inline-flex items-center gap-ds-1 font-medium cursor-pointer\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2 rounded-[var(--ds-radius-sm)]\",\n toneStyles[tone],\n underlineStyles[underline],\n className,\n );\n const resolvedTarget = external ? \"_blank\" : target;\n const resolvedRel = external ? cn(\"noopener noreferrer\", rel) : rel;\n const content = (\n <>\n {slotIcon(iconLeft, 14, \"Link's iconLeft\")}\n {children}\n {slotIcon(iconRight, 14, \"Link's iconRight\")}\n </>\n );\n\n if (Component) {\n return (\n <Component ref={ref} href={href} to={href} className={classes} target={resolvedTarget} rel={resolvedRel} {...props}>\n {content}\n </Component>\n );\n }\n\n return (\n <a ref={ref} href={href} className={classes} target={resolvedTarget} rel={resolvedRel} {...props}>\n {content}\n </a>\n );\n});\n","import { cn } from \"../lib/utils\";\nimport type { ReactNode } from \"react\";\n\ntype Orientation = \"horizontal\" | \"vertical\";\n\ninterface DividerProps {\n orientation?: Orientation;\n label?: ReactNode;\n className?: string;\n}\n\nexport function Divider({\n orientation = \"horizontal\",\n label,\n className,\n}: DividerProps) {\n if (orientation === \"vertical\") {\n return (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n className={cn(\n \"inline-block self-stretch min-h-[1em]\",\n \"w-[var(--ds-divider-width)]\",\n \"bg-[var(--ds-border-default)]\",\n className,\n )}\n />\n );\n }\n\n if (label) {\n return (\n <div\n role=\"separator\"\n className={cn(\"flex items-center gap-ds-3\", className)}\n >\n <span className=\"flex-1 h-[var(--ds-divider-width)] bg-[var(--ds-border-default)]\" />\n <span className=\"text-xs font-medium text-[var(--ds-text-muted)] shrink-0\">\n {label}\n </span>\n <span className=\"flex-1 h-[var(--ds-divider-width)] bg-[var(--ds-border-default)]\" />\n </div>\n );\n }\n\n return (\n <hr\n role=\"separator\"\n className={cn(\n \"border-none w-full\",\n \"h-[var(--ds-divider-width)]\",\n \"bg-[var(--ds-border-default)]\",\n className,\n )}\n />\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/initials.ts","../../../showcase/src/components/Avatar.tsx","../../../showcase/src/lib/use-active-option.ts","../../../showcase/src/lib/search-text.ts","../../../showcase/src/components/MentionList.tsx"],"names":["useRef","jsxs","jsx"],"mappings":";;;;;;;;AAQO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,IAAA,EAAK,CACL,KAAA,CAAM,KAAK,CAAA,CACX,MAAA,CAAO,OAAO,CAAA,CACd,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CACV,GAAA,CAAI,CAAC,IAAA,KAAS,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAA,IAAK,EAAE,CAAA,CACvC,IAAA,CAAK,EAAE,CAAA,CACP,WAAA,EAAY;AACjB;AAGO,SAAS,WAAW,KAAA,EAAuB;AAChD,EAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AACrB,EAAA,IAAI,CAAC,GAAG,OAAO,EAAA;AACf,EAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,IAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,CAAE,MAAA,IAAU,CAAA,EAAG,OAAO,CAAA;AACvD,EAAA,OAAO,WAAW,CAAC,CAAA;AACrB;ACPA,IAAM,UAAA,GAAa;AAAA,EACjB,EAAA,EAAI,iBAAA;AAAA,EACJ,EAAA,EAAI,mBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAGA,IAAM,aAAA,GAAgB;AAAA,EACpB,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAEA,SAAS,WAAW,IAAA,EAA0C;AAC5D,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,MAAW,EAAA,IAAM,MAAM,CAAA,GAAK,CAAA,GAAI,KAAK,EAAA,CAAG,UAAA,CAAW,CAAC,CAAA,KAAO,CAAA;AAC3D,EAAA,OAAS,IAAI,CAAA,GAAK,CAAA;AACpB;AAEA,SAAS,WAAA,CAAY,OAAoB,IAAA,EAAsB;AAC7D,EAAA,IAAI,KAAA,KAAU,UAAU,OAAO,gEAAA;AAC/B,EAAA,IAAI,KAAA,KAAU,WAAW,OAAO,yDAAA;AAChC,EAAA,OAAO,cAAc,KAAA,KAAU,MAAA,GAAS,UAAA,CAAW,IAAI,IAAI,KAAK,CAAA;AAClE;AAMA,SAAS,YAAA,CAAa,EAAE,MAAA,EAAO,EAA6B;AAC1D,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,OAAA,EAAQ,WAAA,EAAY,OAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,OAAA,EAAQ,eAAA,EAAe,MAAA,EAAQ,WAAU,OAAA,EACnH,QAAA,EAAA;AAAA,IAAA,MAAA,KAAW,QAAA,oBAAY,GAAA,CAAC,QAAA,EAAA,EAAO,EAAA,EAAG,GAAA,EAAI,IAAG,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,SAAA,EAAU,iCAAA,EAAkC,CAAA;AAAA,IAC/F,MAAA,KAAW,MAAA,oBAAU,GAAA,CAAC,QAAA,EAAA,EAAO,IAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA,EAAE,KAAI,IAAA,EAAK,MAAA,EAAO,WAAA,EAAY,GAAA,EAAI,WAAU,mCAAA,EAAoC,CAAA;AAAA,IAC3H,MAAA,KAAW,0BACV,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,IAAG,GAAA,EAAI,EAAA,EAAG,KAAI,CAAA,EAAE,GAAA,EAAI,WAAU,+BAAA,EAAgC,CAAA;AAAA,sBACtE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,KAAA,EAAM,CAAA,EAAE,KAAA,EAAM,KAAA,EAAM,GAAA,EAAI,MAAA,EAAO,KAAA,EAAM,EAAA,EAAG,KAAA,EAAM,WAAU,4BAAA,EAA6B;AAAA,KAAA,EAC/F,CAAA;AAAA,IAED,MAAA,KAAW,6BACV,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,IAAA,EAAK,MAAA,EAAO,WAAA,EAAY,GAAA,EAAI,SAAA,EAAU,+BAAA,EAAgC,CAAA;AAAA,sBAClG,GAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,KAAA,EAAM,IAAG,KAAA,EAAM,EAAA,EAAG,KAAA,EAAM,EAAA,EAAG,OAAM,WAAA,EAAY,KAAA,EAAM,aAAA,EAAc,OAAA,EAAQ,WAAU,+BAAA,EAAgC;AAAA,KAAA,EAC9H;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAEO,SAAS,MAAA,CAAO,EAAE,QAAA,EAAU,GAAA,EAAK,GAAA,EAAK,IAAA,GAAO,IAAA,EAAM,MAAA,EAAQ,KAAA,GAAQ,MAAA,EAAQ,SAAA,EAAU,EAAgB;AAE1G,EAAA,MAAM,GAAA,GAAM,OAAO,QAAA,IAAY,EAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,CAAC,GAAA,EAAK,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,MAAA;AAClE,EAAA,MAAM,IAAA,GAAO,EAAA;AAAA,IACX,8DAAA;AAAA,IACA,iCAAA;AAAA,IACA,WAAW,IAAI,CAAA;AAAA,IACf;AAAA,GACF;AAGA,EAAA,MAAM,gBAAgB,GAAA,mBACpB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,EAAA;AAAA,MACZ,GAAA;AAAA,MACA,GAAA,EAAK,KAAA,IAAS,GAAA,IAAO,QAAA,IAAY,EAAA;AAAA,MACjC,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,cAAc;AAAA;AAAA,GACpC,mBAEA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,EAAA;AAAA,MACZ,IAAA,EAAM,QAAQ,KAAA,GAAQ,MAAA;AAAA,MACtB,YAAA,EAAY,KAAA;AAAA,MACZ,SAAA,EAAW,EAAA;AAAA,QACT,IAAA;AAAA,QACA,WAAA,CAAY,KAAA,EAAO,GAAA,IAAO,QAAA,IAAY,EAAE,CAAA;AAAA,QACxC;AAAA,OACF;AAAA,MAGC,QAAA,EAAA,QAAA,IAAY,IAAA,GAAO,UAAA,CAAW,QAAQ,CAAA,GAAI;AAAA;AAAA,GAC7C;AAGF,EAAA,IAAI,CAAC,QAAQ,OAAO,aAAA;AAEpB,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACZ,QAAA,EAAA;AAAA,IAAA,aAAA;AAAA,oBACD,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,UACT,UAAA;AAAA,UACA,SAAS,IAAA,IAAQ,4BAAA;AAAA,UACjB,SAAS,IAAA,IAAQ,4BAAA;AAAA,UACjB,SAAS,IAAA,IAAQ;AAAA,SACnB;AAAA,QACA,aAAA,EAAY,MAAA;AAAA,QAGZ,8BAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yGACd,QAAA,kBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,QAAgB,CAAA,EAChC;AAAA;AAAA;AACF,GAAA,EACF,CAAA;AAEJ;ACnHO,SAAS,qBAAA,CAAsB,MAAqC,QAAA,EAAoC;AAE7G,EAAA,MAAM,KAAA,GAAQ,OAAsB,IAAI,CAAA;AACxC,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,QAAA,EAAU;AACrB,MAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY;AAC7B,IAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,cAAA,KAAmB,aAAa,IAAA,CAAK,cAAA,CAAe,QAAQ,CAAA,GAAI,IAAA;AAC3F,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA,EAAG;AACtC,IAAA,MAAM,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAS,MAAA,CAAO,eAAe,EAAE,CAAA,CAAA;AACzD,IAAA,IAAI,IAAA,KAAS,MAAM,OAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,IAAA,MAAM,GAAA,GAAM,OAAO,qBAAA,EAAsB,CAAE,MAAM,GAAA,CAAI,qBAAA,EAAsB,CAAE,GAAA,GAAM,GAAA,CAAI,SAAA;AACvF,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,YAAA;AAC5B,IAAA,IAAI,MAAM,GAAA,CAAI,SAAA,MAAe,QAAA,CAAS,EAAE,KAAK,CAAA;AAAA,SAAA,IACpC,MAAA,GAAS,GAAA,CAAI,SAAA,GAAY,GAAA,CAAI,YAAA,EAAc,GAAA,CAAI,QAAA,CAAS,EAAE,GAAA,EAAK,MAAA,GAAS,GAAA,CAAI,YAAA,EAAc,CAAA;AAAA,EACrG,CAAC,CAAA;AACH;;;AC3BO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,WAAA,EAAY;AACrF;ACWA,IAAM,IAAA,GAAO,aAAA;AAON,SAAS,aAAA,CAAc,OAA4B,KAAA,EAAoC;AAC5F,EAAA,MAAM,CAAA,GAAI,KAAK,KAAK,CAAA;AACpB,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAiC;AAC7C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA;AACzB,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,EAAG,OAAO,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,UAAA,CAAW,CAAC,CAAC,CAAA,EAAG,OAAO,CAAA;AACjE,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,EAAG,OAAO,CAAA;AAC7B,IAAA,OAAO,CAAA,CAAE,eAAe,IAAA,CAAK,CAAA,CAAE,WAAW,CAAA,CAAE,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,GAAI,EAAA;AAAA,EAChE,CAAA;AACA,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAC,GAAE,CAAE,CAAA,CAAE,MAAA,CAAO,CAAC,EAAE,CAAA,EAAE,KAAM,CAAA,IAAK,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAC,EAAE,GAAA,CAAI,CAAC,EAAE,CAAA,OAAQ,CAAC,CAAA;AACnH;AAGO,IAAM,kBAAkB,CAAC,MAAA,EAAgB,UAAkB,CAAA,EAAG,MAAM,WAAW,KAAK,CAAA;AAMpF,IAAM,kBAAA,GAAqB,EAAA;AAG3B,SAAS,cAAc,KAAA,EAA0E;AACtG,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,GAAG,kBAAkB,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,MAAA,GAAS,kBAAkB,CAAA,EAAE;AAC3G;AA0BO,SAAS,WAAA,CAAY,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,WAAA,EAAa,mBAAA,EAAqB,MAAA,EAAQ,UAAA,EAAY,OAAA,EAAQ,EAAqB;AAC3I,EAAA,MAAM,MAAA,GAASA,OAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,cAAc,OAAA,IAAW,MAAA;AAC/B,EAAA,MAAM,MAAA,GAASA,OAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,UAAU,UAAU,CAAA;AAEtC,EAAA,MAAM,SAAS,OAAA,CAAQ,OAAO,EAAE,OAAA,EAAS,EAAE,uBAAuB,MAAM,SAAA,CAAU,OAAA,EAAQ,IAAK,IAAI,OAAA,EAAQ,IAAmB,CAAA,EAAI,CAAC,SAAS,CAAC,CAAA;AAC7I,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,MAAA,EAAQ,WAAA,EAAa,MAAM,MAAA,GAAS,CAAA,EAAG,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,GAAG,CAAA;AAE5G,EAAA,qBAAA,CAAsB,MAAA,EAAQ,MAAM,MAAA,GAAS,CAAA,GAAI,gBAAgB,EAAA,EAAI,WAAW,IAAI,MAAS,CAAA;AAC7F,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,EAAA,OAAO,YAAA;AAAA,oBACLC,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,WAAA;AAAA,QACL,SAAA,EAAW,EAAA;AAAA,UACT,2DAAA;AAAA,UACA,oCAAA;AAAA,UACA,2FAAA;AAAA,UACA,0EAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,OAAO,EAAE,GAAA,EAAK,IAAI,GAAA,EAAK,IAAA,EAAM,IAAI,IAAA,EAAK;AAAA,QAGtC,QAAA,EAAA;AAAA,0BAAAC,IAAC,KAAA,EAAA,EAAI,GAAA,EAAK,MAAA,EAAQ,EAAA,EAAQ,MAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAAO,SAAA,EAAU,wCACrE,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,EAAG,sBACbD,IAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEC,EAAA,EAAI,eAAA,CAAgB,EAAA,EAAI,CAAC,CAAA;AAAA,cACzB,IAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,QAAA;AAAA,cACL,QAAA,EAAU,EAAA;AAAA,cACV,iBAAe,CAAA,KAAM,WAAA;AAAA,cACrB,SAAA,EAAW,EAAA;AAAA,gBACT,sHAAA;AAAA,gBACA,yDAAA;AAAA,gBACA,CAAA,KAAM,cAAc,uDAAA,GAA0D;AAAA,eAChF;AAAA,cAEA,WAAA,EAAa,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,cACrC,OAAA,EAAS,MAAM,MAAA,CAAO,CAAC,CAAA;AAAA,cACvB,YAAA,EAAc,MAAM,mBAAA,CAAoB,CAAC,CAAA;AAAA,cAGzC,QAAA,EAAA;AAAA,gCAAAC,IAAC,MAAA,EAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,sBAAA,EACjC,0BAAAA,GAAAA,CAAC,MAAA,EAAA,EAAO,KAAK,CAAA,CAAE,MAAA,EAAQ,UAAU,CAAA,CAAE,KAAA,EAAO,MAAK,IAAA,EAAK,SAAA,EAAU,uBAAsB,CAAA,EACtF,CAAA;AAAA,gCACAD,IAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EACd,QAAA,EAAA;AAAA,kCAAAC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0DAAA,EAA4D,YAAE,KAAA,EAAM,CAAA;AAAA,kBACnF,CAAA,CAAE,+BAAeA,GAAAA,CAAC,UAAK,SAAA,EAAU,oDAAA,EAAsD,YAAE,WAAA,EAAY;AAAA,iBAAA,EACxG;AAAA;AAAA,aAAA;AAAA,YAvBK,CAAA,CAAE;AAAA,WAyBV,CAAA,EACD,CAAA;AAAA,UACC,OAAO,CAAA,oBACND,IAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,kIAAA,EACV,QAAA,EAAA;AAAA,YAAA,IAAA;AAAA,YAAK,QAAA;AAAA,YAAO,IAAA,KAAS,IAAI,SAAA,GAAY,OAAA;AAAA,YAAQ;AAAA,WAAA,EAChD;AAAA;AAAA;AAAA,KAEJ;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF","file":"chunk-RWKCAKN3.js","sourcesContent":["/**\n * Initials for an avatar. Round 21 (run 58): a builder passed each person's full name as `initials`, and the avatar\n * printed \"Amara Haddad\" across a 40 px circle on every row of the Team table. The avatar now reads what it is given:\n * up to three characters with no space are initials already and stay as they are (\"JB\", \"ABC\"); anything longer is a\n * name, and its first two words give the letters.\n */\n\n/** \"Sarah Chen\" → \"SC\"; \"Acme\" → \"A\"; \"Mary Jane Watson\" → \"MJ\". */\nexport function initialsOf(name: string): string {\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => Array.from(word)[0] ?? \"\")\n .join(\"\")\n .toUpperCase();\n}\n\n/** What an avatar shows for an `initials` value: initials as given, or the initials of a name. */\nexport function toInitials(value: string): string {\n const s = value.trim();\n if (!s) return \"\";\n if (!/\\s/.test(s) && Array.from(s).length <= 3) return s;\n return initialsOf(s);\n}\n","import { cn } from \"../lib/utils\";\nimport { toInitials } from \"../lib/initials\";\n\nexport type AvatarStatus = \"online\" | \"away\" | \"busy\" | \"offline\";\nexport type AvatarColor = \"auto\" | \"accent\" | \"neutral\" | 1 | 2 | 3 | 4 | 5;\n\ninterface AvatarProps {\n /** One to three letters (\"JB\"). A name passed here shows its initials (\"Amara Haddad\" → \"AH\"), never the whole name. */\n initials?: string;\n src?: string;\n alt?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n status?: AvatarStatus;\n /** Initials background. \"auto\" (default) derives a stable palette tint from alt/initials so groups vary; use \"accent\" sparingly. */\n color?: AvatarColor;\n className?: string;\n}\n\nconst sizeStyles = {\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n};\n\n// Fallbacks cover themes whose tokens CSS predates the decorative palette.\nconst paletteStyles = {\n 1: \"bg-[var(--ds-palette-1-bg,var(--ds-bg-muted))] text-[var(--ds-palette-1-text,var(--ds-text-secondary))]\",\n 2: \"bg-[var(--ds-palette-2-bg,var(--ds-bg-muted))] text-[var(--ds-palette-2-text,var(--ds-text-secondary))]\",\n 3: \"bg-[var(--ds-palette-3-bg,var(--ds-bg-muted))] text-[var(--ds-palette-3-text,var(--ds-text-secondary))]\",\n 4: \"bg-[var(--ds-palette-4-bg,var(--ds-bg-muted))] text-[var(--ds-palette-4-text,var(--ds-text-secondary))]\",\n 5: \"bg-[var(--ds-palette-5-bg,var(--ds-bg-muted))] text-[var(--ds-palette-5-text,var(--ds-text-secondary))]\",\n} as const;\n\nfunction paletteFor(seed: string): keyof typeof paletteStyles {\n let h = 0;\n for (const ch of seed) h = (h * 31 + ch.charCodeAt(0)) >>> 0;\n return ((h % 5) + 1) as keyof typeof paletteStyles;\n}\n\nfunction colorStyles(color: AvatarColor, seed: string): string {\n if (color === \"accent\") return \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\";\n if (color === \"neutral\") return \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)]\";\n return paletteStyles[color === \"auto\" ? paletteFor(seed) : color];\n}\n\n/**\n * Presence as a shape as well as a colour (Sprint 25.12 A48, WCAG 1.4.1), as Fluent's presence badges do: online a filled\n * dot, away a ring, busy a dot with a bar, offline a ring with a slash. The words are in the avatar's name.\n */\nfunction PresenceMark({ status }: { status: AvatarStatus }) {\n return (\n <svg viewBox=\"0 0 10 10\" width=\"10\" height=\"10\" aria-hidden=\"true\" focusable=\"false\" data-presence={status} className=\"block\">\n {status === \"online\" && <circle cx=\"5\" cy=\"5\" r=\"5\" className=\"fill-[var(--ds-status-success)]\" />}\n {status === \"away\" && <circle cx=\"5\" cy=\"5\" r=\"4\" fill=\"none\" strokeWidth=\"2\" className=\"stroke-[var(--ds-status-warning)]\" />}\n {status === \"busy\" && (\n <>\n <circle cx=\"5\" cy=\"5\" r=\"5\" className=\"fill-[var(--ds-status-error)]\" />\n <rect x=\"2.5\" y=\"4.1\" width=\"5\" height=\"1.8\" rx=\"0.9\" className=\"fill-[var(--ds-bg-canvas)]\" />\n </>\n )}\n {status === \"offline\" && (\n <>\n <circle cx=\"5\" cy=\"5\" r=\"4\" fill=\"none\" strokeWidth=\"2\" className=\"stroke-[var(--ds-text-muted)]\" />\n <line x1=\"3.1\" y1=\"6.9\" x2=\"6.9\" y2=\"3.1\" strokeWidth=\"1.5\" strokeLinecap=\"round\" className=\"stroke-[var(--ds-text-muted)]\" />\n </>\n )}\n </svg>\n );\n}\n\nexport function Avatar({ initials, src, alt, size = \"md\", status, color = \"auto\", className }: AvatarProps) {\n // A48: presence can't show words beside a small avatar, so the avatar's own name carries it (\"Priya Nair, online\")\n const who = alt ?? initials ?? \"\";\n const named = status ? [who, status].filter(Boolean).join(\", \") : undefined;\n const base = cn(\n \"inline-flex items-center justify-center font-medium shrink-0\",\n \"rounded-[var(--ds-radius-full)]\",\n sizeStyles[size],\n className,\n );\n\n // data-avatar: the Table and DataGrid card mode stacks a cell that holds an avatar (Sprint 25.4 C-2).\n const avatarElement = src ? (\n <img\n data-avatar=\"\"\n src={src}\n alt={named ?? alt ?? initials ?? \"\"}\n className={cn(base, \"object-cover\")}\n />\n ) : (\n <div\n data-avatar=\"\"\n role={named ? \"img\" : undefined}\n aria-label={named}\n className={cn(\n base,\n colorStyles(color, alt ?? initials ?? \"\"),\n \"border-[length:var(--ds-border-width)] border-transparent\",\n )}\n >\n {/* round 21: a full name passed as initials shows its initials, not the name squeezed into the circle */}\n {initials != null ? toInitials(initials) : null}\n </div>\n );\n\n if (!status) return avatarElement;\n\n return (\n <div className=\"relative inline-flex\">\n {avatarElement}\n <span\n className={cn(\n \"absolute\",\n size === \"sm\" && \"bottom-[-4px] right-[-4px]\",\n size === \"md\" && \"bottom-[-2px] right-[-2px]\",\n size === \"lg\" && \"bottom-[0px] right-[0px]\",\n )}\n aria-hidden=\"true\"\n >\n {/* the canvas behind the mark fills a ring's middle and draws the 2px halo that separates it from the photo */}\n <span className=\"block rounded-[var(--ds-radius-full)] bg-[var(--ds-bg-canvas)] shadow-[0_0_0_2px_var(--ds-bg-canvas)]\">\n <PresenceMark status={status} />\n </span>\n </span>\n </div>\n );\n}\n","import { useLayoutEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Keeps the active option of a list driven by aria-activedescendant in view (Sprint 25.17's review; WCAG 2.4.11): when\n * the list opens and when the active option changes, the list scrolls just enough to show it. Only the list's own box\n * scrolls, never the page: the list sits fixed over it. The option is found by its id, in the list's own document or\n * shadow root.\n *\n * Only a change brings it back into view (the second review): a render that leaves the same option active — the page\n * scrolling, the list scrolled by touch or by its scrollbar — leaves the list where the user put it.\n */\nexport function useActiveOptionInView(list: RefObject<HTMLElement | null>, activeId: string | undefined): void {\n // the option last brought into view, by its id and its text: a filtered list reuses an id for another option\n const shown = useRef<string | null>(null);\n useLayoutEffect(() => {\n const box = list.current;\n if (!box || !activeId) {\n shown.current = null;\n return;\n }\n const root = box.getRootNode() as Document | ShadowRoot;\n const option = typeof root.getElementById === \"function\" ? root.getElementById(activeId) : null;\n if (!option || !box.contains(option)) return;\n const seen = `${activeId}\\u0000${option.textContent ?? \"\"}`;\n if (seen === shown.current) return;\n shown.current = seen;\n const top = option.getBoundingClientRect().top - box.getBoundingClientRect().top + box.scrollTop;\n const bottom = top + option.offsetHeight;\n if (top < box.scrollTop) box.scrollTo({ top });\n else if (bottom > box.scrollTop + box.clientHeight) box.scrollTo({ top: bottom - box.clientHeight });\n });\n}\n","/**\n * Text as a search reads it, one way for every picker (Sprint 25.17's second review): no case, no accents, and \"_\" as a\n * space, so \"@toma\" finds Tomás, \"Sao Paulo\" and \"São Paulo\" find America/Sao_Paulo, and \"New_York\" finds New York.\n */\nexport function foldForSearch(text: string): string {\n return text.normalize(\"NFD\").replace(/\\p{M}/gu, \"\").replace(/_/g, \" \").toLowerCase();\n}\n","import { useMemo, useRef, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { usePosition } from \"../lib/use-position\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { useActiveOptionInView } from \"../lib/use-active-option\";\nimport { foldForSearch } from \"../lib/search-text\";\nimport { Avatar } from \"./Avatar\";\n\nexport interface MentionSuggestion {\n id: string;\n label: string;\n avatar?: string;\n description?: string;\n}\n\n/** Text as a search reads it: no case, no accents (\"@toma\" finds Tomás, \"@zoe\" Zoë), as every picker reads it. */\nconst fold = foldForSearch;\n\n/**\n * The suggestions a query matches, by name or by description, ignoring case and accents, best first: a name that starts with it\n * (\"@Mar\": Marcus Chen), then a name with a word that does (Tomás Martin), then a name holding it anywhere (Amara), then\n * a description that does; in their own order within each.\n */\nexport function matchMentions(items: MentionSuggestion[], query: string): MentionSuggestion[] {\n const q = fold(query);\n const rank = (s: MentionSuggestion): number => {\n const name = fold(s.label);\n if (name.startsWith(q)) return 0;\n if (name.split(/\\s+/).some((word) => word.startsWith(q))) return 1;\n if (name.includes(q)) return 2;\n return s.description && fold(s.description).includes(q) ? 3 : -1;\n };\n return items.map((s) => ({ s, r: rank(s) })).filter(({ r }) => r >= 0).sort((a, b) => a.r - b.r).map(({ s }) => s);\n}\n\n/** An option's id, for the field's aria-activedescendant. */\nexport const mentionOptionId = (listId: string, index: number) => `${listId}-option-${index}`;\n\n/**\n * The most people a list shows (Sprint 25.17's second review: two thousand drawn at once took a key a third of a second\n * to paint): the best matches, and a line saying how many more match, which typing narrows.\n */\nexport const MENTION_LIST_LIMIT = 10;\n\n/** The matches a list shows, best first, and how many more there are. */\nexport function shownMentions(found: MentionSuggestion[]): { items: MentionSuggestion[]; more: number } {\n return { items: found.slice(0, MENTION_LIST_LIMIT), more: Math.max(0, found.length - MENTION_LIST_LIMIT) };\n}\n\nexport interface MentionListProps {\n /** The listbox's id: the field's aria-controls, and the stem of its options' ids. */\n id: string;\n /** The listbox's name (\"People\", \"Suggestions\"). */\n label: string;\n /** The people shown, at most MENTION_LIST_LIMIT (shownMentions). */\n items: MentionSuggestion[];\n /** How many more match than are shown: the list says so under its people. */\n more?: number;\n activeIndex: number;\n onActiveIndexChange: (index: number) => void;\n onPick: (item: MentionSuggestion) => void;\n /** Where the mention being typed is, in the viewport: the list opens under it, above it when the screen runs out below. */\n anchorRect: () => DOMRect | null;\n /** The list's element, for the owner's checks (a click outside, focus moving into it). */\n listRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * The list of suggestions while a mention is typed (Sprint 25.17 A17): MentionInput's and the editor's, so a mention\n * looks and works the same in a comment box and a document. The field keeps focus and carries aria-activedescendant\n * (the field's owner wires the keys: arrows move, Enter or Tab inserts, Escape closes); the options are no Tab stops,\n * and a pointer picks one without taking focus from the field.\n */\nexport function MentionList({ id, label, items, more = 0, activeIndex, onActiveIndexChange, onPick, anchorRect, listRef }: MentionListProps) {\n const ownRef = useRef<HTMLDivElement | null>(null);\n const floatingRef = listRef ?? ownRef;\n const boxRef = useRef<HTMLDivElement | null>(null);\n const anchorRef = useLatest(anchorRect);\n // the caret as an element for usePosition, which reads only its rectangle\n const anchor = useMemo(() => ({ current: { getBoundingClientRect: () => anchorRef.current() ?? new DOMRect() } as HTMLElement }), [anchorRef]);\n const pos = usePosition(anchor, floatingRef, items.length > 0, { side: \"bottom\", align: \"start\", offset: 4 });\n // the arrows move through a list longer than its box: the active person stays in view\n useActiveOptionInView(boxRef, items.length > 0 ? mentionOptionId(id, activeIndex) : undefined);\n if (items.length === 0) return null;\n\n return createPortal(\n <div\n ref={floatingRef}\n className={cn(\n \"fixed z-[var(--ds-z-popover)] min-w-[200px] flex flex-col\",\n \"bg-[var(--ds-bg-surface-elevated)]\",\n \"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-[var(--ds-radius-md)] shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]\",\n )}\n style={{ top: pos.top, left: pos.left }}\n >\n {/* rows inset in the list, rounded, as Combobox's and the menus' are (the second review: full-width square rows) */}\n <div ref={boxRef} id={id} role=\"listbox\" aria-label={label} className=\"max-h-[200px] overflow-y-auto p-ds-1\">\n {items.map((s, i) => (\n <button\n key={s.id}\n id={mentionOptionId(id, i)}\n type=\"button\"\n role=\"option\"\n tabIndex={-1}\n aria-selected={i === activeIndex}\n className={cn(\n \"flex items-center gap-ds-2.5 w-full px-ds-2 py-ds-1.5 text-left text-sm cursor-pointer rounded-[var(--ds-radius-sm)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n i === activeIndex ? \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)]\" : \"text-[var(--ds-text-secondary)]\",\n )}\n // the field keeps focus, so the pick lands where the mention is being typed\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(s)}\n onMouseEnter={() => onActiveIndexChange(i)}\n >\n {/* the name follows as text, so the picture is decoration */}\n <span aria-hidden=\"true\" className=\"inline-flex shrink-0\">\n <Avatar src={s.avatar} initials={s.label} size=\"sm\" className=\"!h-6 !w-6 !text-2xs\" />\n </span>\n <span className=\"min-w-0\">\n <span className=\"block font-medium text-[var(--ds-text-primary)] truncate\">{s.label}</span>\n {s.description && <span className=\"block text-xs text-[var(--ds-text-muted)] truncate\">{s.description}</span>}\n </span>\n </button>\n ))}\n </div>\n {more > 0 && (\n <p className=\"px-ds-3 py-ds-1.5 text-xs text-[var(--ds-text-muted)] border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {more} more {more === 1 ? \"matches\" : \"match\"}: keep typing to narrow\n </p>\n )}\n </div>,\n document.body,\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/components/Skeleton.tsx","../../../showcase/src/lib/format-locale.ts","../../../showcase/src/lib/title-text.ts"],"names":[],"mappings":"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","file":"chunk-X2HEV7FB.js","sourcesContent":["import { cn } from \"../lib/utils\";\n\ninterface SkeletonProps {\n variant?: \"text\" | \"avatar\" | \"card\" | \"table-row\" | \"custom\";\n lines?: number;\n width?: string;\n height?: string;\n className?: string;\n}\n\nfunction Bone({ className, style, \"data-gs\": marker }: { className?: string; style?: React.CSSProperties; \"data-gs\"?: string }) {\n return (\n <div\n data-gs={marker}\n className={cn(\"rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-emphasis)] animate-pulse\", className)}\n style={style}\n />\n );\n}\n\nexport function Skeleton({ variant = \"text\", lines = 3, width, height, className }: SkeletonProps) {\n if (variant === \"custom\") {\n return <Bone data-gs=\"skeleton\" className={className} style={{ width, height }} />;\n }\n\n if (variant === \"avatar\") {\n return <Bone data-gs=\"skeleton\" className={cn(\"h-10 w-10 rounded-[var(--ds-radius-full)]\", className)} />;\n }\n\n if (variant === \"card\") {\n return (\n <div data-gs=\"skeleton\" className={cn(\"space-y-ds-3\", className)}>\n <Bone className=\"h-32 w-full rounded-[var(--ds-radius-md)]\" />\n <Bone className=\"h-4 w-3/4\" />\n <Bone className=\"h-4 w-1/2\" />\n </div>\n );\n }\n\n if (variant === \"table-row\") {\n return (\n <div data-gs=\"skeleton\" className={cn(\"flex gap-ds-4\", className)}>\n <Bone className=\"h-4 flex-[3]\" />\n <Bone className=\"h-4 flex-[2]\" />\n <Bone className=\"h-4 flex-1\" />\n <Bone className=\"h-4 flex-1\" />\n </div>\n );\n }\n\n // text variant\n const widths = [\"w-3/4\", \"w-1/2\", \"w-5/6\", \"w-2/3\", \"w-4/5\"];\n return (\n <div data-gs=\"skeleton\" className={cn(\"space-y-ds-3\", className)}>\n {Array.from({ length: lines }, (_, i) => (\n <Bone key={i} className={cn(\"h-4\", widths[i % widths.length])} />\n ))}\n </div>\n );\n}\n","/** The last page language and visitor's languages read, and the locale they gave: formatting runs often, they change rarely. */\nlet last: { key: string; locale: string | undefined } | null = null;\n\n/**\n * The locale the library writes dates, times and numbers in: the app's language, the page's `lang`, in the visitor's own\n * formats where they speak it (Sprint 25.17, the owner's decision of 2 October). An English page shows \"5 minutes ago\"\n * and \"250K\" to a visitor whose browser is Japanese, where it showed \"5 分前\" and \"25万\" in a page of English (WCAG 3.1.2:\n * text in the page's language needs no `lang` of its own), and a British visitor to it keeps \"1 Oct 2026\". The visitor's\n * form counts only in the page's script: a page in traditional Chinese stays traditional for a visitor who reads\n * simplified. A page with no `lang` is written in the browser's language, as before; so is anything drawn on a server,\n * where there is no page yet.\n */\nexport function formatLocale(): string | undefined {\n if (typeof document === \"undefined\") return undefined;\n const page = document.documentElement.lang?.trim();\n if (!page) return undefined;\n const spoken = typeof navigator === \"undefined\" ? [] : navigator.languages?.length ? navigator.languages : [navigator.language];\n const key = `${page}|${spoken.join(\",\")}`;\n if (last?.key !== key) last = { key, locale: choose(page, spoken) };\n return last.locale;\n}\n\n/** The language and script a tag is written in: \"en\" and \"en-GB\" are both \"en-Latn\"; \"zh-TW\" is \"zh-Hant\", \"zh-CN\" \"zh-Hans\". */\nfunction writtenIn(tag: string): string | null {\n try {\n const locale = new Intl.Locale(tag).maximize();\n return `${locale.language}-${locale.script ?? \"\"}`;\n } catch {\n return null;\n }\n}\n\nfunction choose(page: string, spoken: readonly string[]): string | undefined {\n const language = writtenIn(page);\n // a tag Intl can't read: the browser's language\n if (language === null) return undefined;\n // the visitor's own form of the page's language (\"en-GB\" for an \"en\" page), wherever it is in their list; else the page's\n const own = spoken.find((tag) => typeof tag === \"string\" && writtenIn(tag) === language);\n try {\n return Intl.getCanonicalLocales(own ?? page)[0];\n } catch {\n return undefined;\n }\n}\n","/**\n * A title's text classes: CardTitle's, which a titled Table's band and a ChartContainer's title share (Sprint 25.9, A1),\n * one definition so they cannot drift. A word or a name longer than its line breaks at the line's edge (round 27,\n * R27-16: run 70's \"primary-logo-navy.svg\" ran out of its card); break-word, not anywhere, so a title's words still\n * set its minimum and the actions beside it wrap under it before a word is broken (HEADER_LAYOUT.floor).\n */\nexport const TITLE_TEXT = \"font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] break-words\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/components/Spinner.tsx","../../../showcase/src/components/Button.tsx","../../../showcase/src/lib/preferences.ts"],"names":["Button","jsx","createContext","useContext"],"mappings":"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","file":"chunk-ZYVXV4WC.js","sourcesContent":["import { cn } from \"../lib/utils\";\n\nconst sizes = {\n sm: \"h-4 w-4 border-[1.5px]\",\n md: \"h-6 w-6 border-2\",\n lg: \"h-8 w-8 border-[2.5px]\",\n} as const;\n\ninterface SpinnerProps {\n size?: keyof typeof sizes;\n color?: \"default\" | \"inherit\";\n label?: string;\n className?: string;\n}\n\nexport function Spinner({ size = \"md\", color = \"default\", label = \"Loading\", className }: SpinnerProps) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(\n \"inline-block rounded-[var(--ds-radius-full)] animate-spin\",\n color === \"inherit\"\n ? \"border-current/30 border-t-current\"\n : \"border-[var(--ds-bg-emphasis)] border-t-[var(--ds-accent-primary)]\",\n sizes[size],\n className\n )}\n />\n );\n}\n","import { cn } from \"../lib/utils\";\nimport { createContext, useContext, forwardRef, isValidElement, type ButtonHTMLAttributes, type CSSProperties, type ReactNode } from \"react\";\nimport { Tooltip, TooltipCtx } from \"./Tooltip\";\nimport { Spinner } from \"./Spinner\";\nimport { slotIcon, type IconSlot, slotDraws } from \"../lib/icons\";\n\ntype ButtonVariant = \"default\" | \"secondary\" | \"tertiary\" | \"outline\" | \"ghost\" | \"destructive\" | \"success\" | \"warning\" | \"link\";\ntype ButtonSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"icon-xs\" | \"icon-sm\" | \"icon\" | \"icon-lg\";\n\nexport type ControlSize = \"sm\" | \"md\" | \"lg\";\nexport const ControlSizeContext = createContext<ControlSize | null>(null);\nexport const ButtonSizeContext = ControlSizeContext;\n\ninterface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** An icon name (\"clock\"), drawn as the theme's icon at the button's icon size, or an element. Not text: use children. */\n iconLeft?: IconSlot;\n /** As iconLeft, after the label. */\n iconRight?: IconSlot;\n loading?: boolean;\n children?: ReactNode;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n default: \"bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box] text-[var(--ds-text-on-primary)] border-transparent hover:bg-[var(--ds-accent-primary-hover)] hover:brightness-110\",\n secondary: \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]\",\n tertiary: \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)] border-transparent hover:brightness-95\",\n outline: \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]\",\n ghost: \"bg-transparent text-[var(--ds-text-primary)] border-transparent hover:bg-[var(--ds-bg-muted)] shadow-none\",\n destructive: \"bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)] border-transparent hover:opacity-90\",\n success: \"bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)] border-transparent hover:opacity-90\",\n warning: \"bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)] border-transparent hover:opacity-90\",\n link: \"bg-transparent text-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary-hover)] hover:underline\",\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n // xs / icon-xs: dense tool chrome (builder toolbars, inline row actions).\n xs: \"h-ds-6 px-ds-3 py-0 text-xs\",\n sm: \"h-[var(--ds-control-height-sm)] px-ds-4 py-ds-1 text-xs\",\n md: \"h-[var(--ds-control-height-md)] px-ds-6 py-ds-2 text-sm\",\n lg: \"h-[var(--ds-control-height-lg)] px-ds-8 py-ds-3 text-base\",\n \"icon-xs\": \"h-ds-6 w-ds-6 p-0\",\n \"icon-sm\": \"h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] p-0\",\n icon: \"h-[var(--ds-control-height-md)] w-[var(--ds-control-height-md)] p-0\",\n \"icon-lg\": \"h-[var(--ds-control-height-lg)] w-[var(--ds-control-height-lg)] p-0\",\n};\n\n// Link buttons have no box, so only the text size follows `size`.\nconst linkSizeStyles: Record<ButtonSize, string> = {\n xs: \"text-xs\",\n sm: \"text-xs\",\n md: \"text-sm\",\n lg: \"text-base\",\n \"icon-xs\": \"text-xs\",\n \"icon-sm\": \"text-xs\",\n icon: \"text-sm\",\n \"icon-lg\": \"text-base\",\n};\n\nconst iconPaddingReduce: Record<Exclude<ButtonSize, \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\">, number> = {\n xs: 2,\n sm: 2,\n md: 4,\n lg: 6,\n};\n\n/** The icon size each button size draws a named icon at (Sprint 25.17 A26): what the library's own buttons pass by hand. */\nconst SLOT_ICON_PX: Record<ButtonSize, number> = { xs: 12, sm: 14, md: 16, lg: 18, \"icon-xs\": 12, \"icon-sm\": 14, icon: 16, \"icon-lg\": 18 };\n\nconst HOVER_SCALE_CAP = { '--_btn-scale': 'min(var(--ds-hover-scale), 1.02)' } as CSSProperties;\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button({ variant = \"default\", size: sizeProp, iconLeft, iconRight, loading, className, children, disabled, style, onClick, ...props }, ref) {\n const contextSize = useContext(ControlSizeContext);\n const size = sizeProp ?? contextSize ?? \"md\";\n const isLink = variant === \"link\";\n const spinnerSize = size === \"lg\" || size === \"icon-lg\" ? \"md\" : \"sm\";\n let paddingStyle: CSSProperties | undefined;\n const isIconSize = size === \"icon\" || size === \"icon-xs\" || size === \"icon-sm\" || size === \"icon-lg\";\n // a slot that draws nothing (text, which no icon pack names) keeps the button's even padding\n const drawsLeft = slotDraws(iconLeft);\n const drawsRight = slotDraws(iconRight);\n if (!isIconSize && !isLink && (drawsLeft || drawsRight)) {\n const reduce = iconPaddingReduce[size];\n paddingStyle = {};\n if (drawsLeft) paddingStyle.paddingLeft = `calc(${getCssPadding(size)} - ${reduce}px)`;\n if (drawsRight) paddingStyle.paddingRight = `calc(${getCssPadding(size)} - ${reduce}px)`;\n }\n\n const isLoading = loading && !disabled;\n const isDisabled = !!disabled;\n\n const handleClick = isLoading\n ? (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); }\n : onClick;\n\n const ariaLabel = props[\"aria-label\"];\n // Round 15 (52.7): inside an explicit <Tooltip> the caller owns the label; the automatic one from aria-label would be a second tooltip.\n const inTooltip = useContext(TooltipCtx);\n\n const btn = (\n <button\n ref={ref}\n data-variant={variant}\n className={cn(\n \"relative inline-flex items-center justify-center gap-ds-2 whitespace-nowrap font-medium\",\n isLink\n ? cn(\n \"px-0 py-ds-0.5 h-auto\",\n linkSizeStyles[size],\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2\",\n \"cursor-pointer\",\n \"active:text-[var(--ds-accent-primary-active)]\",\n )\n : cn(\n \"border-[length:var(--ds-border-width)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-shadow-button)]\",\n \"hover:scale-[var(--_btn-scale)] hover:-translate-y-[var(--ds-hover-lift)]\",\n \"active:shadow-[var(--ds-shadow-button-pressed)] active:translate-x-[var(--ds-press-depth)] active:translate-y-[var(--ds-press-depth)]\",\n \"[transition:var(--ds-transition-interactive)]\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n \"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled\",\n sizeStyles[size],\n ),\n variantStyles[variant],\n isLoading && !isLink && \"cursor-wait pointer-events-none\",\n className\n )}\n disabled={isDisabled}\n aria-busy={isLoading || undefined}\n aria-disabled={isLoading && !disabled ? true : undefined}\n onClick={handleClick}\n style={isLink ? style : { ...HOVER_SCALE_CAP, ...paddingStyle, ...style }}\n {...props}\n >\n {loading && !isLink && (\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <Spinner size={spinnerSize} color=\"inherit\" />\n </span>\n )}\n <span className={cn(\"inline-flex items-center gap-ds-2 min-w-0\", loading && !isLink && \"invisible\")}>\n {slotIcon(iconLeft, SLOT_ICON_PX[size], \"Button's iconLeft\")}\n {children}\n {slotIcon(iconRight, SLOT_ICON_PX[size], \"Button's iconRight\")}\n </span>\n </button>\n );\n\n if (isIconSize && ariaLabel && !inTooltip) {\n return <Tooltip content={ariaLabel}>{btn}</Tooltip>;\n }\n\n return btn;\n});\n\nfunction getCssPadding(size: Exclude<ButtonSize, \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\">): string {\n switch (size) {\n case \"xs\": return \"var(--ds-space-3)\";\n case \"sm\": return \"var(--ds-space-4)\";\n case \"md\": return \"var(--ds-space-6)\";\n case \"lg\": return \"var(--ds-space-8)\";\n }\n}\n\n/**\n * A trigger the library wires up (a Collapsible's, a menu's, a popover's) never submits the form it sits in (0.21.0): a\n * button element or Button given no type gets type=\"button\". A page's own Button keeps HTML's default, so its submits\n * still work.\n */\nexport function triggerType(node: unknown): { type?: \"button\" } {\n if (!isValidElement(node)) return {};\n return (node.type === \"button\" || node.type === Button) && (node.props as { type?: unknown }).type === undefined ? { type: \"button\" } : {};\n}\n","/**\n * The customer's UX preferences, carried once by AppShell the way the theme is (Sprint 25.6 B9).\n *\n * The generated shell passes the object the template emits from the profile's rules; the builder preview passes the\n * same values from the theme state. Components default from it when no prop is passed — FormWrapper's validation mode\n * and actions alignment, Table and DataGrid's mobile breakpoint, Pagination's page size, EmptyState's style, the\n * destructive-action helper's mode, lists and undo window, and RelativeTime's threshold (Sprint 25.17 A29) — so a page\n * gets the customer's value by doing nothing. A\n * prop always wins; a component outside any shell keeps the default it always had (components read\n * `useShellPreferences`). App code reads `usePreferences`, which fills every field (round 21); a paged list reads its\n * page size through `usePagination`.\n */\nimport { createContext, useContext, useMemo } from \"react\";\n\nexport type PreferenceValidationTiming = \"onBlur\" | \"onSubmit\" | \"onChange\";\nexport type PreferenceBreakpoint = \"sm\" | \"md\" | \"lg\";\nexport type PreferenceEmptyStyle = \"illustration-cta\" | \"text-cta\" | \"redirect\";\nexport type PreferenceLoadingStyle = \"skeleton\" | \"spinner\" | \"progress-bar\";\nexport type PreferenceDestructiveMode = \"dialog\" | \"undo\";\n/** dataDisplay.paginationStyle — how a long list shows more: page numbers, a Load more button, or loading as the user scrolls. */\nexport type PreferencePaginationStyle = \"pagination\" | \"load-more\" | \"infinite-scroll\";\n\nexport interface AppShellPreferences {\n /** forms.validationTiming — when a field first shows its error. */\n validationTiming?: PreferenceValidationTiming;\n /** forms.actions — where a form's buttons sit and how they align. */\n formActions?: { align?: \"start\" | \"end\"; placement?: \"auto\" | \"inline\" };\n /** dataDisplay.itemsPerPage — the page size of a paged or load-more list. */\n itemsPerPage?: number;\n /** dataDisplay.paginationStyle — page numbers, a Load more button, or loading on scroll; usePagination and Pagination follow it (round 22). */\n paginationStyle?: PreferencePaginationStyle;\n /** responsive.tableToCardsBreakpoint — below this width a Table becomes stacked cards. */\n tableToCardsBreakpoint?: PreferenceBreakpoint;\n /** emptyStates.emptyStyle — illustration with an action, text with an action, or redirect to creation. */\n emptyStyle?: PreferenceEmptyStyle;\n /** emptyStates.loadingStyle — what a page shows while data loads. */\n loadingStyle?: PreferenceLoadingStyle;\n /** destructiveActions.mode — confirm in a dialog, or act now with an Undo toast. */\n destructiveMode?: PreferenceDestructiveMode;\n /** destructiveActions.highSeverityActions — always confirm in a dialog, even in undo mode. */\n highSeverityActions?: string[];\n /** destructiveActions.typeToConfirmActions — the user types the name before the confirm enables. */\n typeToConfirmActions?: string[];\n /** destructiveActions.undoWindowSeconds — how long the Undo toast stays. */\n undoWindowSeconds?: number;\n /** dateTime.relativeThresholdHours — within this many hours a time reads relative (\"2 hours ago\"), older the date (RelativeTime). */\n relativeThresholdHours?: number;\n}\n\nexport const PreferencesContext = createContext<AppShellPreferences | null>(null);\n\n/** Every preference in force, the shell's value or the house default — what app code reads. */\nexport interface ResolvedPreferences {\n validationTiming: PreferenceValidationTiming;\n formActions: { align: \"start\" | \"end\"; placement: \"auto\" | \"inline\" };\n itemsPerPage: number;\n paginationStyle: PreferencePaginationStyle;\n tableToCardsBreakpoint: PreferenceBreakpoint;\n emptyStyle: PreferenceEmptyStyle;\n loadingStyle: PreferenceLoadingStyle;\n destructiveMode: PreferenceDestructiveMode;\n highSeverityActions: string[];\n typeToConfirmActions: string[];\n undoWindowSeconds: number;\n relativeThresholdHours: number;\n}\n\n/**\n * The house defaults for the fields the shell carries: the platform's preference-defaults.ts, mirrored in\n * decisions-schema.ts (DEFAULT_PATTERN_DECISIONS); a test keeps the three equal.\n */\nconst HOUSE_DEFAULTS: ResolvedPreferences = {\n validationTiming: \"onBlur\",\n formActions: { align: \"end\", placement: \"auto\" },\n itemsPerPage: 25,\n paginationStyle: \"pagination\",\n tableToCardsBreakpoint: \"md\",\n emptyStyle: \"illustration-cta\",\n loadingStyle: \"skeleton\",\n destructiveMode: \"dialog\",\n highSeverityActions: [\"delete_account\", \"remove_team_member\"],\n typeToConfirmActions: [\"delete_account\"],\n undoWindowSeconds: 5,\n relativeThresholdHours: 24,\n};\nexport const PREFERENCE_HOUSE_DEFAULTS: Readonly<ResolvedPreferences> = Object.freeze(HOUSE_DEFAULTS);\n\n/**\n * For app code: every preference in force — the shell's value, else the house default — so a page never writes a\n * fallback of its own. Round 21 (run 58): with every field optional, TypeScript made the builder write\n * `const { itemsPerPage = 20 } = usePreferences()`, a second copy of the preference it then edited by hand when the\n * rule changed. Paged lists use `usePagination`, which reads the page size itself.\n */\nexport function usePreferences(): ResolvedPreferences {\n const raw = useShellPreferences();\n return useMemo(() => resolvePreferences(raw), [raw]);\n}\n\n/** The shell's values over the house defaults; a field the shell leaves undefined keeps its default. */\nexport function resolvePreferences(raw: AppShellPreferences): ResolvedPreferences {\n const d = PREFERENCE_HOUSE_DEFAULTS;\n const out: ResolvedPreferences = { ...d, formActions: { ...d.formActions }, highSeverityActions: [...d.highSeverityActions], typeToConfirmActions: [...d.typeToConfirmActions] };\n for (const [key, value] of Object.entries(raw) as Array<[keyof AppShellPreferences, unknown]>) {\n if (value === undefined) continue;\n if (key === \"formActions\") {\n const actions = value as AppShellPreferences[\"formActions\"];\n if (actions?.align !== undefined) out.formActions.align = actions.align;\n if (actions?.placement !== undefined) out.formActions.placement = actions.placement;\n continue;\n }\n (out as unknown as Record<string, unknown>)[key] = value;\n }\n return out;\n}\n\n/**\n * For components: only what the shell passed, or an empty object outside any shell — a component with no prop takes\n * the shell's value, and a bare component keeps the default it always had.\n */\nexport function useShellPreferences(): AppShellPreferences {\n return useContext(PreferencesContext) ?? EMPTY;\n}\n\nconst EMPTY: AppShellPreferences = Object.freeze({});\n\n/**\n * \"Remove range\" → \"remove_range\": the key the high-severity and type-to-confirm lists use. The engine's `actionKey`\n * (platform/src/lib/destructive-mode.ts) is the same rule for compliance; a platform test keeps the two identical.\n */\nexport function preferenceActionKey(label: string): string {\n return label.trim().toLowerCase().replace(/[^a-z0-9]+/g, \"_\").replace(/^_|_$/g, \"\");\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/icon-packs/feather.ts"],"names":[],"mappings":"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","file":"feather-VFWLAILO.js","sourcesContent":["import type { IconMap } from './types'\nimport { buildExtendedMap, pickCurated } from './utils'\n\n/**\n * Feather (react-icons) icons.\n *\n * The pack is reached only through the dynamic import in peer() — never a\n * static named import. A static import of an optional peer makes a consumer's\n * production build fail on Vite 8 when the peer is not installed: Vite\n * substitutes an export-less stub and the bundler treats every missing name as\n * fatal (Sprint 22 bench finding 1, 13 Sep 2026; showcase/src/test/\n * vite8-optional-peers-build.test.ts guards it). The curated names are strings\n * for the same reason; icon-completeness.test.tsx proves every one resolves in\n * the installed pack. If the pack is missing, peer() rejects and loadPack in\n * icons.tsx reports which package to install.\n */\nconst CURATED: Record<string, string> = {\n \"home\": \"FiHome\",\n \"folder\": \"FiFolder\",\n \"chart\": \"FiBarChart2\",\n \"settings\": \"FiSettings\",\n \"chevron-right\": \"FiChevronRight\",\n \"close\": \"FiX\",\n \"plus\": \"FiPlus\",\n \"search\": \"FiSearch\",\n \"bell\": \"FiBell\",\n \"user\": \"FiUser\",\n \"check\": \"FiCheck\",\n \"warning\": \"FiAlertTriangle\",\n \"info\": \"FiInfo\",\n \"error\": \"FiAlertCircle\",\n \"clock\": \"FiClock\",\n \"calendar\": \"FiCalendar\",\n \"bold\": \"FiBold\",\n \"italic\": \"FiItalic\",\n \"underline\": \"FiUnderline\",\n \"strikethrough\": \"FiSlash\",\n \"align-left\": \"FiAlignLeft\",\n \"align-center\": \"FiAlignCenter\",\n \"align-right\": \"FiAlignRight\",\n \"list\": \"FiList\",\n \"list-ordered\": \"FiList\",\n \"list-checks\": \"FiCheckSquare\",\n \"link\": \"FiLink\",\n \"image\": \"FiImage\",\n \"table\": \"FiGrid\",\n \"code\": \"FiCode\",\n \"quote\": \"FiMessageSquare\",\n \"minus\": \"FiMinus\",\n \"superscript\": \"FiChevronUp\",\n \"subscript\": \"FiChevronDown\",\n \"highlight\": \"FiEdit2\",\n \"type\": \"FiType\",\n \"chevron-up\": \"FiChevronUp\",\n \"chevron-down\": \"FiChevronDown\",\n \"chevron-left\": \"FiChevronLeft\",\n \"trash\": \"FiTrash2\",\n \"undo\": \"FiRotateCcw\",\n \"redo\": \"FiRotateCw\",\n \"arrow-left\": \"FiArrowLeft\",\n \"grip-vertical\": \"FiMoreVertical\",\n \"mic\": \"FiMic\",\n \"paperclip\": \"FiPaperclip\",\n \"send\": \"FiSend\",\n \"log-out\": \"FiLogOut\",\n \"edit\": \"FiEdit2\",\n \"menu\": \"FiMenu\",\n \"more-horizontal\": \"FiMoreHorizontal\",\n \"star\": \"FiStar\",\n \"bookmark\": \"FiBookmark\",\n \"download\": \"FiDownload\",\n \"upload\": \"FiUpload\",\n \"sparkles\": \"FiStar\",\n \"file\": \"FiFile\",\n \"file-text\": \"FiFileText\",\n \"eye\": \"FiEye\",\n \"eye-off\": \"FiEyeOff\",\n \"copy\": \"FiCopy\",\n \"external-link\": \"FiExternalLink\",\n \"filter\": \"FiFilter\",\n \"lock\": \"FiLock\",\n \"map-pin\": \"FiMapPin\",\n}\n\nasync function peer(): Promise<Record<string, unknown>> {\n return (await import(\"react-icons/fi\")) as unknown as Record<string, unknown>\n}\n\nexport async function loadCurated(): Promise<IconMap> {\n return pickCurated(await peer(), CURATED)\n}\n\nexport async function loadExtended(): Promise<IconMap> {\n const mod = await peer()\n const extended = buildExtendedMap(mod, {}, { stripPrefix: \"Fi\" })\n Object.assign(extended, pickCurated(mod, CURATED))\n return extended\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/icon-packs/heroicons.ts"],"names":["TypeGlyph"],"mappings":"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","file":"heroicons-H3Z7DFCF.js","sourcesContent":["import { createElement, forwardRef } from 'react'\nimport type { IconMap } from './types'\nimport { buildExtendedMap, pickCurated } from './utils'\n\n/**\n * Heroicons icons.\n *\n * The pack is reached only through the dynamic import in peer() — never a\n * static named import. A static import of an optional peer makes a consumer's\n * production build fail on Vite 8 when the peer is not installed: Vite\n * substitutes an export-less stub and the bundler treats every missing name as\n * fatal (Sprint 22 bench finding 1, 13 Sep 2026; showcase/src/test/\n * vite8-optional-peers-build.test.ts guards it). The curated names are strings\n * for the same reason; icon-completeness.test.tsx proves every one resolves in\n * the installed pack. If the pack is missing, peer() rejects and loadPack in\n * icons.tsx reports which package to install.\n */\nconst CURATED: Record<string, string> = {\n \"home\": \"HomeIcon\",\n \"folder\": \"FolderIcon\",\n \"chart\": \"ChartBarIcon\",\n \"settings\": \"Cog6ToothIcon\",\n \"chevron-right\": \"ChevronRightIcon\",\n \"close\": \"XMarkIcon\",\n \"plus\": \"PlusIcon\",\n \"search\": \"MagnifyingGlassIcon\",\n \"bell\": \"BellIcon\",\n \"user\": \"UserIcon\",\n \"check\": \"CheckIcon\",\n \"warning\": \"ExclamationTriangleIcon\",\n \"info\": \"InformationCircleIcon\",\n \"error\": \"ExclamationCircleIcon\",\n \"clock\": \"ClockIcon\",\n \"calendar\": \"CalendarDaysIcon\",\n \"bold\": \"BoldIcon\",\n \"italic\": \"ItalicIcon\",\n \"underline\": \"UnderlineIcon\",\n \"strikethrough\": \"StrikethroughIcon\",\n \"align-left\": \"Bars3BottomLeftIcon\",\n \"align-center\": \"Bars3Icon\",\n \"align-right\": \"Bars3BottomRightIcon\",\n \"list\": \"ListBulletIcon\",\n \"list-ordered\": \"NumberedListIcon\",\n \"list-checks\": \"ClipboardDocumentCheckIcon\",\n \"link\": \"LinkIcon\",\n \"image\": \"PhotoIcon\",\n \"table\": \"TableCellsIcon\",\n \"code\": \"CodeBracketIcon\",\n \"quote\": \"ChatBubbleBottomCenterTextIcon\",\n \"minus\": \"MinusIcon\",\n \"superscript\": \"H1Icon\",\n \"subscript\": \"H2Icon\",\n \"highlight\": \"PaintBrushIcon\",\n \"chevron-up\": \"ChevronUpIcon\",\n \"chevron-down\": \"ChevronDownIcon\",\n \"chevron-left\": \"ChevronLeftIcon\",\n \"trash\": \"TrashIcon\",\n \"undo\": \"ArrowUturnLeftIcon\",\n \"redo\": \"ArrowUturnRightIcon\",\n \"arrow-left\": \"ArrowLeftIcon\",\n \"grip-vertical\": \"Bars2Icon\",\n \"mic\": \"MicrophoneIcon\",\n \"paperclip\": \"PaperClipIcon\",\n \"send\": \"PaperAirplaneIcon\",\n \"log-out\": \"ArrowRightStartOnRectangleIcon\",\n \"edit\": \"PencilIcon\",\n \"menu\": \"Bars3Icon\",\n \"more-horizontal\": \"EllipsisHorizontalIcon\",\n \"star\": \"StarIcon\",\n \"bookmark\": \"BookmarkIcon\",\n \"download\": \"ArrowDownTrayIcon\",\n \"upload\": \"ArrowUpTrayIcon\",\n \"sparkles\": \"SparklesIcon\",\n \"file\": \"DocumentIcon\",\n \"file-text\": \"DocumentTextIcon\",\n \"eye\": \"EyeIcon\",\n \"eye-off\": \"EyeSlashIcon\",\n \"copy\": \"DocumentDuplicateIcon\",\n \"external-link\": \"ArrowTopRightOnSquareIcon\",\n \"filter\": \"FunnelIcon\",\n \"lock\": \"LockClosedIcon\",\n \"map-pin\": \"MapPinIcon\",\n}\n\n/**\n * Heroicons draws no letter T, and its LanguageIcon (文A, translate) meant the wrong thing beside a document (round 28,\n * R28-35). So `type` is a T drawn in the pack's own outline style: a 24 px box, a 1.5 stroke that the theme's weight\n * overrides, round ends.\n */\nconst TypeGlyph = forwardRef<SVGSVGElement, Record<string, unknown>>(function TypeGlyph(props, ref) {\n return createElement('svg', { ref, xmlns: 'http://www.w3.org/2000/svg', fill: 'none', viewBox: '0 0 24 24', strokeWidth: 1.5, stroke: 'currentColor', 'aria-hidden': true, 'data-slot': 'icon', ...props },\n createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', d: 'M4.5 7.5v-3h15v3M12 4.5v15M9 19.5h6' }))\n})\n\nasync function peer(): Promise<Record<string, unknown>> {\n return (await import(\"@heroicons/react/24/outline\")) as unknown as Record<string, unknown>\n}\n\nexport async function loadCurated(): Promise<IconMap> {\n return { ...pickCurated(await peer(), CURATED), type: TypeGlyph }\n}\n\nexport async function loadExtended(): Promise<IconMap> {\n const mod = await peer()\n const extended = buildExtendedMap(mod, {}, { stripSuffix: \"Icon\" })\n Object.assign(extended, pickCurated(mod, CURATED), { type: TypeGlyph })\n return extended\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/icon-packs/lucide.ts"],"names":[],"mappings":"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","file":"lucide-MR32KM4G.js","sourcesContent":["import type { IconMap } from './types'\nimport { buildExtendedMap, pickCurated } from './utils'\n\n/**\n * Lucide icons.\n *\n * The pack is reached only through the dynamic import in peer() — never a\n * static named import. A static import of an optional peer makes a consumer's\n * production build fail on Vite 8 when the peer is not installed: Vite\n * substitutes an export-less stub and the bundler treats every missing name as\n * fatal (Sprint 22 bench finding 1, 13 Sep 2026; showcase/src/test/\n * vite8-optional-peers-build.test.ts guards it). The curated names are strings\n * for the same reason; icon-completeness.test.tsx proves every one resolves in\n * the installed pack. If the pack is missing, peer() rejects and loadPack in\n * icons.tsx reports which package to install.\n */\nconst CURATED: Record<string, string> = {\n \"home\": \"Home\",\n \"folder\": \"FolderKanban\",\n \"chart\": \"BarChart3\",\n \"settings\": \"Settings\",\n \"chevron-right\": \"ChevronRight\",\n \"close\": \"X\",\n \"plus\": \"Plus\",\n \"search\": \"Search\",\n \"bell\": \"Bell\",\n \"user\": \"User\",\n \"check\": \"Check\",\n \"warning\": \"AlertTriangle\",\n \"info\": \"Info\",\n \"error\": \"AlertCircle\",\n \"clock\": \"Clock\",\n \"calendar\": \"CalendarDays\",\n \"bold\": \"Bold\",\n \"italic\": \"Italic\",\n \"underline\": \"Underline\",\n \"strikethrough\": \"Strikethrough\",\n \"align-left\": \"AlignLeft\",\n \"align-center\": \"AlignCenter\",\n \"align-right\": \"AlignRight\",\n \"list\": \"List\",\n \"list-ordered\": \"ListOrdered\",\n \"list-checks\": \"ListChecks\",\n \"link\": \"Link\",\n \"image\": \"Image\",\n \"table\": \"Table\",\n \"code\": \"Code\",\n \"quote\": \"Quote\",\n \"minus\": \"Minus\",\n \"superscript\": \"Superscript\",\n \"subscript\": \"Subscript\",\n \"highlight\": \"Highlighter\",\n \"type\": \"Type\",\n \"chevron-up\": \"ChevronUp\",\n \"chevron-down\": \"ChevronDown\",\n \"chevron-left\": \"ChevronLeft\",\n \"trash\": \"Trash2\",\n \"undo\": \"Undo2\",\n \"redo\": \"Redo2\",\n \"arrow-left\": \"ArrowLeft\",\n \"grip-vertical\": \"GripVertical\",\n \"mic\": \"Mic\",\n \"paperclip\": \"Paperclip\",\n \"send\": \"Send\",\n \"log-out\": \"LogOut\",\n \"edit\": \"Pencil\",\n \"menu\": \"Menu\",\n \"more-horizontal\": \"MoreHorizontal\",\n \"star\": \"Star\",\n \"bookmark\": \"Bookmark\",\n \"download\": \"Download\",\n \"upload\": \"Upload\",\n \"sparkles\": \"Sparkles\",\n \"file\": \"File\",\n \"file-text\": \"FileText\",\n \"eye\": \"Eye\",\n \"eye-off\": \"EyeOff\",\n \"copy\": \"Copy\",\n \"external-link\": \"ExternalLink\",\n \"filter\": \"Funnel\",\n \"lock\": \"Lock\",\n \"map-pin\": \"MapPin\",\n}\n\nasync function peer(): Promise<Record<string, unknown>> {\n return (await import(\"lucide-react\")) as unknown as Record<string, unknown>\n}\n\nexport async function loadCurated(): Promise<IconMap> {\n return pickCurated(await peer(), CURATED)\n}\n\nexport async function loadExtended(): Promise<IconMap> {\n const mod = await peer()\n const extended = buildExtendedMap(mod, {})\n Object.assign(extended, pickCurated(mod, CURATED))\n return extended\n}\n"]}