gridsmith-ui 0.33.0 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/charts.js +7 -7
- package/dist/chat.js +6 -6
- package/dist/{chunk-WSKPESAX.js → chunk-4FX6UCSS.js} +5 -5
- package/dist/{chunk-WSKPESAX.js.map → chunk-4FX6UCSS.js.map} +1 -1
- package/dist/{chunk-OWGF362U.js → chunk-4TQVFRKK.js} +6 -6
- package/dist/{chunk-OWGF362U.js.map → chunk-4TQVFRKK.js.map} +1 -1
- package/dist/{chunk-HCEHTJ5E.js → chunk-77X7AHFB.js} +3 -3
- package/dist/{chunk-HCEHTJ5E.js.map → chunk-77X7AHFB.js.map} +1 -1
- package/dist/{chunk-AVSP6NDX.js → chunk-BL2C35BN.js} +42 -32
- package/dist/chunk-BL2C35BN.js.map +1 -0
- package/dist/{chunk-2724SJO2.js → chunk-HDFTENVW.js} +7 -3
- package/dist/chunk-HDFTENVW.js.map +1 -0
- package/dist/{chunk-6XCWKLJZ.js → chunk-MPXE2XOP.js} +5 -5
- package/dist/{chunk-6XCWKLJZ.js.map → chunk-MPXE2XOP.js.map} +1 -1
- package/dist/{chunk-FF57N3P7.js → chunk-MW5CJOJN.js} +4 -4
- package/dist/{chunk-FF57N3P7.js.map → chunk-MW5CJOJN.js.map} +1 -1
- package/dist/{chunk-UBLBVCQN.js → chunk-N6QLEZFH.js} +5 -5
- package/dist/{chunk-UBLBVCQN.js.map → chunk-N6QLEZFH.js.map} +1 -1
- package/dist/{chunk-TMPPBXX3.js → chunk-NFVJEICH.js} +3 -3
- package/dist/{chunk-TMPPBXX3.js.map → chunk-NFVJEICH.js.map} +1 -1
- package/dist/{chunk-AB4UQ4G5.js → chunk-NJG6JQGC.js} +7 -7
- package/dist/{chunk-AB4UQ4G5.js.map → chunk-NJG6JQGC.js.map} +1 -1
- package/dist/{chunk-6NRLTG5W.js → chunk-PT4HYHI3.js} +7 -7
- package/dist/{chunk-6NRLTG5W.js.map → chunk-PT4HYHI3.js.map} +1 -1
- package/dist/{chunk-F2XMZOUP.js → chunk-T33JK3ZE.js} +4 -4
- package/dist/{chunk-F2XMZOUP.js.map → chunk-T33JK3ZE.js.map} +1 -1
- package/dist/{chunk-ZQV26NND.js → chunk-UI4BSRCQ.js} +3 -3
- package/dist/{chunk-ZQV26NND.js.map → chunk-UI4BSRCQ.js.map} +1 -1
- package/dist/{chunk-WD6T57ZJ.js → chunk-XJGFZ5CP.js} +5 -5
- package/dist/{chunk-WD6T57ZJ.js.map → chunk-XJGFZ5CP.js.map} +1 -1
- package/dist/{chunk-R2IAK3J3.js → chunk-ZTS6HJAU.js} +3 -3
- package/dist/{chunk-R2IAK3J3.js.map → chunk-ZTS6HJAU.js.map} +1 -1
- package/dist/dashboard.js +6 -6
- package/dist/data-grid.js +7 -7
- package/dist/editor-mentions.js +2 -2
- package/dist/editor.js +2 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +78 -42
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +7 -7
- package/dist/resizable.js +7 -7
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.js +7 -7
- package/package.json +1 -1
- package/dist/chunk-2724SJO2.js.map +0 -1
- package/dist/chunk-AVSP6NDX.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/use-close-settle.ts","../../../showcase/src/lib/corner-insets.ts","../../../showcase/src/lib/edge-resize.tsx","../../../showcase/src/lib/drawer-width.ts","../../../showcase/src/lib/bulk-bar-host.tsx","../../../showcase/src/lib/use-scrollbar-inset.ts","../../../showcase/src/lib/aside-slot.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"],"names":["t","useEffect","createContext","useState","useRef","useCallback","jsx","useContext","useMemo","jsxs","AppShell","winner","useId","Fragment","forwardRef","Breadcrumbs","createPortal","label"],"mappings":"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","file":"chunk-AB4UQ4G5.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 { useEffect } from \"react\";\n\n/**\n * Corner-inset registry.\n *\n * Fixed chrome that occupies a bottom corner — a Launcher, an open CornerPanel —\n * claims the corner so the toast stack lands above it rather than over it.\n * Each claim is a CSS length expression (usually a calc()), so claims cannot be\n * compared numerically; instead every claimant declares a priority and the\n * highest active priority wins, ties going to the most recent claim. The\n * winner is written to the matching --ds-toast-inset-* custom property on the\n * target element (document root by default; a preview frame when the chrome is\n * rendered inside a container). Releasing the last claim removes the override\n * so roots.css's default applies again.\n */\n\n/**\n * A bottom corner (Launcher, CornerPanel), the middle of the bottom edge (a mid-edge bottom ribbon, a bottom panel), a\n * whole side edge (a docked AsidePanel, a non-modal side Drawer, a mid-edge side ribbon), or the top edge (the app's\n * Navbar, round 21).\n */\nexport type InsetEdge = \"bottom-right\" | \"bottom-left\" | \"bottom-center\" | \"right\" | \"left\" | \"top\";\n\nexport const TOAST_INSET_VARS: Record<InsetEdge, string> = {\n \"bottom-right\": \"--ds-toast-inset-bottom-right\",\n \"bottom-left\": \"--ds-toast-inset-bottom-left\",\n \"bottom-center\": \"--ds-toast-inset-bottom-center\",\n right: \"--ds-toast-inset-right\",\n left: \"--ds-toast-inset-left\",\n top: \"--ds-toast-inset-top\",\n};\n\n/**\n * A side claim for a panel beside the stack, capped so a toast still fits beside it at its narrowest (Toast's min-w,\n * 280 px) with a gutter: on a window with no such room the stack overlaps the panel's outer part rather than leaving the\n * window. The percentage is the stack's containing block, the window (or the preview frame).\n */\nexport function besideRoom(room: string): string {\n return `min(${room}, calc(100% - 280px - var(--ds-space-4)))`;\n}\n\n/** Launcher sits under everything else in its corner. */\nexport const LAUNCHER_INSET_PRIORITY = 1;\n/** A corner panel is taller than the launcher beneath it. */\nexport const PANEL_INSET_PRIORITY = 2;\n/** The app's top bar: a toast at the top lands below it, not over the user menu (round 21). */\nexport const NAVBAR_INSET_PRIORITY = 1;\n\ninterface Claim {\n inset: string;\n priority: number;\n seq: number;\n}\n\ntype CornerClaims = Record<InsetEdge, Claim[]>;\n\nconst registry = new WeakMap<Element, CornerClaims>();\nlet seq = 0;\n\nfunction claimsFor(target: Element): CornerClaims {\n let entry = registry.get(target);\n if (!entry) {\n entry = { \"bottom-right\": [], \"bottom-left\": [], \"bottom-center\": [], right: [], left: [], top: [] };\n registry.set(target, entry);\n }\n return entry;\n}\n\nfunction winner(claims: Claim[]): Claim | null {\n let best: Claim | null = null;\n for (const c of claims) {\n if (!best || c.priority > best.priority || (c.priority === best.priority && c.seq > best.seq)) best = c;\n }\n return best;\n}\n\nfunction apply(target: Element, corner: InsetEdge) {\n const style = (target as HTMLElement).style;\n if (!style) return;\n const best = winner(claimsFor(target)[corner]);\n if (best) style.setProperty(TOAST_INSET_VARS[corner], best.inset);\n else style.removeProperty(TOAST_INSET_VARS[corner]);\n}\n\n/**\n * Register a claim on `corner` for `target`. Returns the release function.\n * Imperative form, used by the hook and directly testable.\n */\nexport function claimCornerInset(corner: InsetEdge, inset: string, priority: number, target: Element): () => void {\n const claim: Claim = { inset, priority, seq: ++seq };\n const list = claimsFor(target)[corner];\n list.push(claim);\n apply(target, corner);\n return () => {\n const i = list.indexOf(claim);\n if (i >= 0) list.splice(i, 1);\n apply(target, corner);\n };\n}\n\n/** Test seam: the active claims on a corner of `target`, winner first. */\nexport function getCornerInsetClaims(corner: InsetEdge, target: Element): { inset: string; priority: number }[] {\n const list = registry.get(target)?.[corner] ?? [];\n return [...list]\n .sort((a, b) => (b.priority - a.priority) || (b.seq - a.seq))\n .map(({ inset, priority }) => ({ inset, priority }));\n}\n\n/**\n * Hold a corner claim while `corner` and `inset` are non-null. Pass the\n * container element when the chrome renders inside a frame; otherwise the\n * document root is used so the app-level ToastProvider sees the inset.\n */\nexport function useCornerInset(corner: InsetEdge | null, inset: string | null, priority: number, target?: Element | null) {\n useEffect(() => {\n if (!corner || !inset) return;\n const el = target ?? document.documentElement;\n return claimCornerInset(corner, inset, priority, el);\n }, [corner, inset, priority, target]);\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { cn, GROUP_FOCUS_RING } from \"./utils\";\nimport { Icon } from \"./icons\";\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. Its keyboard focus is\n // drawn round a grip it shows while focused (Sprint 30): an outline round the whole strip would be cut off at its\n // ends, which run the panel's full height, as ResizablePanels' handle draws its own.\n \"group 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 {/* the grip, inside the panel beside its edge, so the panel, which clips what lies past it, shows its outline whole:\n the strip sits a space's width over the edge, and the outline reaches 4 px past the grip */}\n <div\n aria-hidden=\"true\"\n className={cn(\n \"absolute top-1/2 hidden h-4 w-3 -translate-y-1/2 items-center justify-center group-focus-visible:flex\",\n edge === \"left\" ? \"left-[calc(var(--ds-space-1)+4px)]\" : \"right-[calc(var(--ds-space-1)+4px)]\",\n \"rounded-[var(--ds-radius-sm)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] bg-[var(--ds-bg-surface)]\",\n GROUP_FOCUS_RING,\n )}\n >\n <Icon name=\"grip-vertical\" size={10} className=\"text-[var(--ds-text-muted)]\" />\n </div>\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 } 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","/**\n * Where a BulkActionBar floats (Sprint 25.33, the owner, 19 October: \"the floating bulk action bar at the bottom of the\n * screen, without a doubt\"). A surface that scrolls content — the AppShell's content column, a SplitView's pane, a\n * Drawer's or a Dialog's body — hosts the bar: a layer across the foot of what it shows, where the bar is drawn over the\n * content, so selecting a row moves nothing; and the room the bar takes, which the surface keeps at the foot of what\n * scrolls, so the last rows scroll clear of it and the keyboard never puts focus under it (WCAG 2.4.11).\n *\n * Why a layer the surface owns, not `position: fixed`: a fixed box is placed against the nearest ancestor with a filter or\n * a transform, and the library's own surfaces have them (the glass filter on a Card, a Table's frame, a Drawer's slide),\n * so a fixed bar inside a Card landed at the Card's foot (the plan review measured it).\n */\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface BulkBarHost {\n /** The layer the bar is drawn in, across the foot of the host's visible area. */\n layer: HTMLElement | null;\n /** A bar's height while it shows, 0 once it goes, so the host keeps room for the tallest at the foot of what scrolls. */\n setRoom: (bar: object, height: number) => void;\n}\n\nexport const BulkBarHostCtx = createContext<BulkBarHost | null>(null);\n\n/**\n * Internal (Sprint 25.33): the ToastProvider's side. A host (or a bar with none) reports the room its bars take at the\n * page's foot (0 once they go), so the stack at the bottom rises above them at every width; and a bar has its count said\n * in the provider's polite region, which is in the page before the bar is (the bar comes and goes with the selection, so a\n * region of its own is heard by no one).\n */\nexport interface BulkBarPresence {\n room: (owner: object, room: number) => void;\n say: (text: string) => void;\n}\nexport const BulkBarPresenceCtx = createContext<BulkBarPresence | null>(null);\n\n/** The gap between the bar and the host's foot, in px; the room kept above the bar is the bar's height and two of these. */\nexport const BULK_BAR_GAP = 16;\n\n// across the foot, the bar centred and clear of the edges; clicks pass through the layer, but not the bar. Two bars in one\n// host stack, a gap apart, in the order they came (the fix pass of 25.33, L-4: side by side they overflowed the column)\nconst LAYOUT = \"pointer-events-none inset-x-0 bottom-0 z-[var(--ds-z-sticky)] flex flex-col items-center gap-ds-2 px-ds-4 pb-ds-4\";\n/** A host's layer: across the foot of the host, which is positioned. */\nexport const BULK_BAR_LAYER = `absolute ${LAYOUT}`;\n/** With no host (a page outside the shell): across the window's foot, clear of its safe area. */\nexport const BULK_BAR_WINDOW_LAYER = `fixed ${LAYOUT} pb-[calc(var(--ds-space-4)+env(safe-area-inset-bottom))]`;\n\n/** The room to keep at the foot of what scrolls, while a bar of this height shows. */\nexport const bulkBarRoom = (height: number) => (height > 0 ? height + BULK_BAR_GAP * 2 : 0);\n\n/**\n * A host's side: the layer's setter (its ref), the height its bars take now (0 for none: their heights and the gaps between them, as\n * they stack), and the value to provide. The host tells the toasts the room its whole stack takes.\n */\nexport function useBulkBarHost() {\n const presence = useContext(BulkBarPresenceCtx);\n const [layer, setLayer] = useState<HTMLElement | null>(null);\n const [room, setRoomState] = useState(0);\n const bars = useRef(new Map<object, number>());\n const setRoom = useCallback((bar: object, height: number) => {\n if (height > 0) bars.current.set(bar, height);\n else bars.current.delete(bar);\n const heights = [...bars.current.values()];\n const gap = layer ? parseFloat(getComputedStyle(layer).rowGap) || 0 : 0;\n setRoomState(heights.length ? heights.reduce((sum, h) => sum + h, 0) + gap * (heights.length - 1) : 0);\n }, [layer]);\n // the host's own key in the toasts' record of the room taken\n const [owner] = useState(() => ({}));\n useEffect(() => {\n presence?.room(owner, bulkBarRoom(room));\n return () => presence?.room(owner, 0);\n }, [presence, owner, room]);\n const value = useMemo<BulkBarHost>(() => ({ layer, setRoom }), [layer, setRoom]);\n // a host destructures this: the React Compiler's lint reads an object whose value is passed to `ref` as a ref, and each\n // read of it while rendering as reading one (the fix pass of 25.33)\n return { setLayer, room, value };\n}\n\n/**\n * The room a host keeps after what scrolls while a bar shows, so the last rows scroll above it. `extra` adds what else\n * sits under the bar (the window's safe area). The fill-height logic never counts it as the page's content.\n */\nexport function BulkBarSpacer({ room, extra }: { room: number; extra?: string }) {\n const space = bulkBarRoom(room);\n if (!space) return null;\n return <div aria-hidden=\"true\" data-bulk-bar-spacer=\"\" style={{ height: extra ? `calc(${space}px + ${extra})` : space }} />;\n}\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 { createContext } from \"react\";\n\n/**\n * Sprint 32: true where an AsidePanel docks where it's drawn. Inside AppShell's `aside` slot, which is already beside the\n * content column; inside an overlay (a Dialog, a Drawer, a Sheet), which a panel drawn in it never leaves. Elsewhere in a\n * shell it's false (AppShell sets it so round its own content, so an inner shell's pages dock in the inner shell), and a\n * page's own panel docks beside the content column through the shell's host on its side. A file of its own: the shell\n * and the overlays both read it, and the shell imports the Drawer.\n */\nexport const AsideSlotContext = createContext(false);\n","import { useContext, useEffect, useRef, useState, useId, useCallback, useMemo, createContext, type ReactNode, type CSSProperties, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn, OVERLAY_SURFACE, GLASS_OVERLAY, FOCUS_RING, FOCUS_INSET, lockBodyScroll, unlockBodyScroll } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { focusInitial, useReturnFocus, useFocusTrap, useOverlayLayer, useNonModalDialog, inertOutside, OVERLAY_CLOSE_ATTR } from \"../lib/focus\";\nimport { useCloseSettle } from \"../lib/use-close-settle\";\nimport { besideRoom, PANEL_INSET_PRIORITY, useCornerInset } from \"../lib/corner-insets\";\nimport { ResizeEdge, useRememberedWidth, pxOf, defaultMaxWidth } from \"../lib/edge-resize\";\nimport { AutoTooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\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 { BulkBarHostCtx, BulkBarSpacer, useBulkBarHost, BULK_BAR_LAYER, bulkBarRoom } from \"../lib/bulk-bar-host\";\nimport { insetLessScrollbar, useScrollbarInset } from \"../lib/use-scrollbar-inset\";\nimport { AsideSlotContext } from \"../lib/aside-slot\";\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\n/**\n * What stays in a modal drawer's scope outside it (Sprint 25.29 item 9): the shell gives its phone menu, offset below the\n * navbar, the navbar. While the drawer is open everything else in its container is inert, and Tab cycles the two. The\n * panel isn't marked aria-modal, which would hide the navbar from a screen reader; the inert page is what makes it modal.\n */\nexport const DrawerScopeCtx = createContext<RefObject<HTMLElement | null> | 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, and for a non-modal drawer on any side): a draggable bottom Sheet with snap\n * points, always modal.\n * \"panel\" (default for a modal left drawer, 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 // A non-modal panel on a phone covers the page it was beside, so it becomes the modal sheet whatever its side: a left\n // one too, which would otherwise be a full-width panel with nothing to keep focus in it (the review of 21.6 session B).\n const mobileMode = mobile ?? (position === \"left\" && props.modal !== false ? \"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, pending, mark } = useOverlayMark(open);\n // text a control holds uncommitted (a half-typed tag) always asks, whatever the page's `dirty` says (Sprint 25.29 item 15)\n const guard = useDirtyGuard((dirty ?? marked) || pending, 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 wrapperRef = useRef<HTMLDivElement>(null);\n const scope = useContext(DrawerScopeCtx);\n const scoped = !!scope && blocking && !sheet;\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, so it does not trap focus, unless the navbar\n // is in its scope (the shell's phone menu: the two trap together, the rest inert); the phone's sheet always traps.\n useFocusTrap(panelRef, open && blocking && (sheet || !topOffset || scoped), isTopLayer, scoped ? scope : null);\n useEffect(() => {\n const keep = scope?.current;\n const own = wrapperRef.current;\n if (!open || !mounted || !scoped || !keep || !own) return;\n return inertOutside([keep, own], container instanceof Element ? container : document.body);\n }, [open, mounted, scoped, scope, container]);\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 panel the user works alongside keeps the toast stack off it while it is open, as the docked column and the corner\n // window do: a side panel holds its side (toasts slide past it), a bottom panel the bottom edge (toasts land above it,\n // by its measured height). A modal drawer and the phone's sheet cover the page under a backdrop, so they hold nothing.\n const holdsRoom = open && mounted && nonModal && !sheet;\n const horizontal = position === \"left\" || position === \"right\";\n const [panelHeight, setPanelHeight] = useState<number | null>(null);\n useEffect(() => {\n const el = panelRef.current;\n if (!holdsRoom || horizontal || !el || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(([entry]) => {\n const height = ((entry?.target ?? el) as HTMLElement).offsetHeight;\n setPanelHeight(height > 0 ? height : null);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [holdsRoom, horizontal]);\n const claimTarget = container instanceof Element ? container : null;\n const sideRoom = holdsRoom && horizontal ? besideRoom(`calc(${effectiveWidth} + var(--ds-space-4))`) : null;\n const bottomRoom = holdsRoom && !horizontal && panelHeight ? `calc(${panelHeight}px + var(--ds-space-3))` : null;\n useCornerInset(sideRoom ? (position as \"left\" | \"right\") : null, sideRoom, PANEL_INSET_PRIORITY, claimTarget);\n useCornerInset(bottomRoom ? \"bottom-right\" : null, bottomRoom, PANEL_INSET_PRIORITY, claimTarget);\n useCornerInset(bottomRoom ? \"bottom-left\" : null, bottomRoom, PANEL_INSET_PRIORITY, claimTarget);\n useCornerInset(bottomRoom ? \"bottom-center\" : null, bottomRoom, PANEL_INSET_PRIORITY, claimTarget);\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 bodyInset = useScrollbarInset<HTMLDivElement>();\n // a body that scrolls with nothing inside to Tab to is a Tab stop, named by the drawer's title (Sprint 25.29 item 10)\n const [bodyEl, setBodyEl] = useState<HTMLDivElement | null>(null);\n const bodyRef = useCallback((el: HTMLDivElement | null) => { bodyInset(el); setBodyEl(el); }, [bodyInset]);\n useKeyboardScroll(bodyEl, typeof title === \"string\" ? title : \"Content\", open);\n // a bulk-action bar inside floats at the body's foot, above the footer (Sprint 25.33)\n const { setLayer: setBarLayer, room: barStack, value: barHost } = useBulkBarHost();\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 ref={wrapperRef}\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 && !scoped ? \"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 <AutoTooltip content={title}>\n <h2 ref={titleOverflowRef} id={titleId} className={heading}>{title}</h2>\n </AutoTooltip>\n ) : (\n <h2 ref={titleOverflowRef} id={titleId} className={heading}>{title}</h2>\n )}\n {/* an icon button's one tooltip, its name (Sprint 25.29 item 18, accessibility#10) */}\n <AutoTooltip content=\"Close\">\n <button type=\"button\"\n onClick={onClose}\n {...{ [OVERLAY_CLOSE_ATTR]: \"\" }}\n className={cn(\"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer\", FOCUS_RING)}\n aria-label=\"Close\"\n >\n <Icon name=\"close\" size={18} />\n </button>\n </AutoTooltip>\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. Its box\n hosts a bulk-action bar from inside: at its foot, above the footer, with room kept under the last rows */}\n <div className=\"relative flex-1 min-h-0 flex flex-col\">\n <div\n ref={bodyRef}\n // a Tab stop while it scrolls with nothing inside to Tab to: the inset ring SplitView's panes draw (Sprint 25.29)\n className={cn(\"flex-1 min-h-0 overflow-y-auto\", FOCUS_INSET)}\n style={{\n ...(flush ? {} : { padding: `var(--ds-space-5) ${insetLessScrollbar(INSET)} var(--ds-space-5) ${INSET}` }),\n ...(barStack ? { scrollPaddingBottom: bulkBarRoom(barStack) } : {}),\n }}\n >\n {/* Sprint 32: an AsidePanel drawn in a drawer or a sheet (this panel draws both) docks there, never portalled out */}\n <BulkBarHostCtx value={barHost}><SurfaceBoundary><AsideSlotContext value={true}>{children}</AsideSlotContext></SurfaceBoundary></BulkBarHostCtx>\n <BulkBarSpacer room={barStack} />\n </div>\n <div ref={setBarLayer} data-bulk-bar-layer=\"\" className={BULK_BAR_LAYER} />\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, FOCUS_RING } 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_RING,\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 { useState, useCallback, useEffect, useLayoutEffect, useRef, useId, forwardRef, createContext, useContext, type ReactNode } from \"react\";\nimport { REACT_VERSION_PROBLEM } from \"../lib/react-version\";\nimport { AsideSlotContext } from \"../lib/aside-slot\";\nimport { warnOnce } from \"../lib/dev-warn\";\nimport type { AppShellTheme, ChromePosition } from \"../lib/shell-theme\";\nimport { PreferencesContext, type AppShellPreferences } from \"../lib/preferences\";\nimport { SkipLink } from \"./SkipLink\";\nimport { cn, FOCUS_INSET_WHILE_STOP } from \"../lib/utils\";\nimport { useBreakpoint } from \"../lib/use-breakpoint\";\nimport { Drawer, DrawerScopeCtx } from \"./Drawer\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\nimport { DrawerWidthCtx } from \"../lib/drawer-width\";\nimport { BulkBarHostCtx, BulkBarSpacer, useBulkBarHost, BULK_BAR_LAYER, BULK_BAR_GAP, bulkBarRoom } from \"../lib/bulk-bar-host\";\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 below the `lg` breakpoint, expanded from 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 (the aside slot's, or a page's own) is open beside the content. Pages may hide non-essential chrome on it. */\n asideOpen: boolean;\n /** For a docked panel of an app's own, not an AsidePanel, which tells the shell itself (`reportAside`); 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 /** As setAsideOpen: for a docked panel of an app's own; not for pages to call. */\n setAsideFloating: (floating: boolean) => void;\n /** The side of the docked AsidePanel that is open and floating, or null: a floating PageHeader drops its gutter on that side. */\n asideFloatingSide: \"right\" | \"left\" | null;\n /**\n * How each AsidePanel in the shell tells it where it stands, by its onClose (a ref to the latest), null as it goes. One\n * AsidePanel is open at a time in a shell, whatever its side or its form (docked, drawer or sheet): the one opened last\n * wins, and the shell closes the others through their own onClose. Read by AsidePanel; not for pages to call.\n */\n reportAside: (onClose: { readonly current: () => void }, state: AsidePanelReport | null) => void;\n /**\n * Where an AsidePanel a page renders docks (Sprint 32): beside the content column on its side, where the aside slot's\n * does, so a page's own panel (a dashboard editor's widget library) docks like the app's while it stays in the page's\n * tree, and the page's context reaches it. Read by AsidePanel; not for pages to read.\n */\n asideHosts: { left: HTMLElement | null; right: HTMLElement | null };\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 a bubble or pill launcher occupies, so the container's bottom padding reads that corner's inset variable. The page's padding ignores a ribbon, which hugs the window's edge (its claim keeps only toasts off it). */\n launcherCorner: \"bottom-right\" | \"bottom-left\" | null;\n /** Called by a Launcher inside the shell with the corner it occupies (null for a ribbon), so the padding follows the Launcher itself however the slot wraps it. Returns the unregister. */\n registerLauncher: (corner: \"bottom-right\" | \"bottom-left\" | null) => () => void;\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\n/** What an AsidePanel tells the shell it's in (AppShellContextValue's `reportAside`). */\nexport interface AsidePanelReport {\n open: boolean;\n /** Its `open` has just turned true (an onClose new each render is no opening). */\n opened: boolean;\n /** A page's own panel, not the aside slot's: of two opened together, the page's wins. */\n page: boolean;\n /** Docked beside the content column at this width, not the Drawer it becomes below its collapse width. */\n docked: boolean;\n floating: boolean;\n side: \"right\" | \"left\";\n /** The id of the heading that names it (its labelledBy), for a development warning. */\n name: string;\n}\n\nconst AppShellContext = createContext<AppShellContextValue | null>(null);\n\n/**\n * The app shell around this component, or null outside one: its layout state — whether it has a sidebar, a mobile menu\n * and a mobile nav, whether the sidebar is open or collapsed and the aside open (each with its setter), the viewport tier\n * (`isMobile`, `isTablet`), the theme it was given and whether its navbar and sidebar float. For telling the shell about\n * unsaved changes, use `useUnsavedChanges`.\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 from the sm breakpoint up, where Tailwind's `sm:` starts — a conditional\n * render, because the Launcher portals out of any wrapper — so below it, on phones, the Navbar button is the entry\n * point 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 // a docked panel of an app's own (setAsideOpen, setAsideFloating); an AsidePanel tells the shell through reportAside\n const [ownAsideOpen, setAsideOpen] = useState(false);\n const [ownAsideFloating, setAsideFloating] = useState(false);\n // where a page's own AsidePanel docks, beside the content column (Sprint 32)\n const [leftAsideHost, setLeftAsideHost] = useState<HTMLDivElement | null>(null);\n const [rightAsideHost, setRightAsideHost] = useState<HTMLDivElement | null>(null);\n // Sprint 32, G6: one AsidePanel open at a time, whatever its side or form, the one opened last winning (the owner's\n // answer of 20 October 2026, asked of a dashboard's widget library opening beside the docked assistant). Each panel, by\n // its onClose, and what it last told the shell; read in effects only.\n const asides = useRef(new Map<{ readonly current: () => void }, AsidePanelReport>());\n // the panels opened since the shell last looked, in the order they said so\n const opened = useRef<Array<{ readonly current: () => void }>>([]);\n const [openings, setOpenings] = useState(0);\n // the docked panel that's open, which the content column gives way to: its side, and whether it floats\n const [docked, setDocked] = useState<{ side: \"right\" | \"left\"; floating: boolean } | null>(null);\n // the panels asked to close, looked at again once their pages have answered\n const [asked, setAsked] = useState<Array<{ readonly current: () => void }>>([]);\n const reportAside = useCallback((onClose: { readonly current: () => void }, state: AsidePanelReport | null) => {\n if (state) asides.current.set(onClose, state);\n else asides.current.delete(onClose);\n if (state?.opened) {\n opened.current.push(onClose);\n setOpenings((n) => n + 1);\n }\n let next: { side: \"right\" | \"left\"; floating: boolean } | null = null;\n for (const s of asides.current.values()) if (s.open && s.docked) next = { side: s.side, floating: s.floating };\n setDocked((d) => (d?.side === next?.side && d?.floating === next?.floating ? d : next));\n }, []);\n // The panels opened since the shell last looked, all of one commit together (each panel tells the shell as it commits,\n // and this runs once they all have): the page's own wins over the slot's, as their order in the tree differs by side,\n // else the last to open. Every other open panel is closed through its own onClose, so the app's state follows (the\n // assistant's launcher comes back, the library's button reads closed); a panel kept mounted keeps its content.\n useLayoutEffect(() => {\n const keys = opened.current.filter((key) => asides.current.get(key)?.open);\n opened.current = [];\n if (keys.length === 0) return;\n let winner = keys[keys.length - 1];\n for (const key of keys) if (asides.current.get(key)?.page) winner = key;\n const closing = [...asides.current].filter(([key, s]) => key !== winner && s.open).map(([key]) => key);\n for (const key of closing) key.current();\n // looked at again once the pages have answered, which commits with this\n if (closing.length > 0) setAsked(closing);\n }, [openings]);\n // A panel asked to close is looked at once its page has answered (the answer commits with this render, the panel\n // telling the shell first): one still open is said in development, and never asked again\n useLayoutEffect(() => {\n for (const key of asked) {\n const s = asides.current.get(key);\n if (!s?.open) continue;\n const name = (typeof document !== \"undefined\" && document.getElementById(s.name)?.textContent?.trim()) || s.name;\n warnOnce(\"AsidePanel\", `\"${name}\" stayed open as another opened: one AsidePanel is open at a time in a shell, the last opened, so its onClose must close it (set its open to false).`);\n }\n }, [asked]);\n const asideOpen = docked !== null || ownAsideOpen;\n const asideFloating = docked ? docked.floating : ownAsideFloating;\n // the open docked panel's own side, which a page's panel may have on the other side from the slot's\n const asideFloatingSide = docked ? (docked.floating ? docked.side : null) : ownAsideOpen && ownAsideFloating ? asideSide : null;\n const isMobile = useBreakpoint(\"md\");\n const isSmallMobile = useBreakpoint(\"sm\");\n const isTablet = isMobile && !isSmallMobile;\n // Sidebar tiers, where Tailwind's md: and lg: start (Sprint 25.28): expanded from lg, the auto-rail from md to lg, the\n // drawer 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 // <main> on a page with nothing in it to Tab to, scrolling: a Tab stop, keeping its landmark's role and the skip link's\n // tabindex -1 for when it isn't (Sprint 25.29 item 10)\n const [mainEl, setMainEl] = useState<HTMLElement | null>(null);\n const setMain = useCallback((el: HTMLElement | null) => { mainRef.current = el; setMainEl(el); }, []);\n // the page's bulk-action bar floats in a layer across the content column's foot (Sprint 25.33)\n const { setLayer: setBarLayer, room: barStack, value: barHost } = useBulkBarHost();\n const barRoom = bulkBarRoom(barStack);\n // its foot is the window's, so the bar clears the safe area, but over a phone's tab bar, which clears it itself\n const barSafe = isSmallMobile && hasMobileNav ? \"0px\" : \"env(safe-area-inset-bottom)\";\n const barSpacer = <BulkBarSpacer room={barStack} extra={barSafe} />;\n useKeyboardScroll(mainEl, \"Main content\");\n // The navbar's slot: a box of its own for nothing (display: contents), so the phone menu can keep the navbar in its\n // scope (Sprint 25.29 item 9). A Navbar's own root differs by its form, and an app may bring its own bar.\n const navbarRef = useRef<HTMLDivElement | null>(null);\n const navbarSlot = navbar != null && navbar !== false ? <div ref={navbarRef} data-ds-navbar-slot=\"\" className=\"contents\">{navbar}</div> : navbar;\n const menuNameId = useId();\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 page's padding clears the corner the Launcher occupies, which the Launcher reports itself (a ribbon none), so\n // it holds however the slot wraps it: a preview's launcher beside an overlay of its own, an app's own wrapper. Read\n // from the slot's element, a Fragment or a wrapper read as bottom-right (the review of 21.6 session B).\n const hasLauncher = !!launcher && !isSmallMobile;\n const [launcherClaim, setLauncherClaim] = useState<{ corner: AppShellContextValue[\"launcherCorner\"] } | null>(null);\n const registerLauncher = useCallback((corner: AppShellContextValue[\"launcherCorner\"]) => {\n const claim = { corner };\n setLauncherClaim(claim);\n return () => setLauncherClaim((c) => (c === claim ? null : c));\n }, []);\n const launcherCorner: AppShellContextValue[\"launcherCorner\"] = hasLauncher ? (launcherClaim?.corner ?? null) : null;\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, asideFloatingSide, reportAside, asideHosts: { left: leftAsideHost, right: rightAsideHost }, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome, hasLauncher, launcherCorner, registerLauncher, hasFooter, focus: focus ?? null, hasUnsavedChanges: unsavedCount > 0, addUnsavedChanges, drawerWidth, navigate: navigate ?? null, flowLeft: leftCount > 0, markFlowLeft }}\n >\n {/* G7: a shell drawn inside another's aside slot docks its own pages' panels itself */}\n <AsideSlotContext value={false}>\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, so nothing hides under a phone browser's toolbar (100vh is the height\n // with the toolbar hidden). Sprint 25.21 S1: h-dvh alone, which an app's own height class replaces through cn();\n // the supports-[…] variant that stood beside it survived that merge and beat the app's class (the builder's\n // preview ran under its footer). Every browser that draws the themes' oklch() colours has dvh.\n // Sprint 25.8.7 item 31: clipped, not hidden. A box that hides its overflow is still a scroll container, which\n // the browser scrolls to show a focused element past its edge: on run 73's roles page at 390 px it had moved\n // 424 px after 15 Tab stops, and the next 50 stops sat in a blank band below <main>. Nothing can scroll a\n // clipped box. The page scrolls in <main>, never here, and holds what it positions (below), so in a browser\n // without overflow: clip (Safari 15) nothing of the library's runs past this box to need clipping.\n \"relative h-dvh flex flex-col bg-[var(--ds-bg-canvas)] overflow-clip\",\n className,\n )}>\n {skipLink && <SkipLink href={`#${mainId}`} />}\n {layout === \"sidebar-header\" && navbarSlot}\n {layout === \"multi-column\" && navbarSlot}\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\" && <AsideSlotContext value={true}>{aside}</AsideSlotContext>}\n {/* Sprint 32: a page's own AsidePanel docks here, next to the content (it portals in, staying in the page's\n tree); a box of its own for nothing */}\n <div ref={setLeftAsideHost} data-shell-aside-host=\"left\" className=\"contents\" />\n\n {/* relative: the bulk-action bar's layer sits across its foot (Sprint 25.33) */}\n <div className=\"relative flex-1 flex flex-col min-w-0 min-h-0\">\n {layout === \"sidebar\" && navbarSlot}\n {layout === \"stacked\" && navbarSlot}\n\n <BulkBarHostCtx value={barHost}>\n <main\n ref={setMain}\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 // Sprint 25.8.7 item 31: <main> is the page's containing block, so what the page positions with no\n // positioned box of its own (a Checkbox's visually hidden input) scrolls with the page, and Tab scrolls\n // <main> to it. Placed against the shell instead, it stayed where the unscrolled page had put it, out of\n // <main>'s reach, and focus scrolled the shell's outer box to show it\n \"relative flex-1 min-h-0 focus:outline-none\",\n // the skip link's target draws no ring (GOV.UK's); a Tab stop while it scrolls with nothing in it to Tab\n // to, it draws the inset ring (Sprint 25.29 item 10)\n FOCUS_INSET_WHILE_STOP,\n // the outline's reach at the foot as scroll padding, which a control Tab reaches across the bottom edge\n // stops short of (Sprint 25.29 item 19; a pinned PageHeader claims the top inline). The page's last control\n // has its room from the page's own foot (PageContainer's bottom padding): padding here would sit under a\n // view that fills the page, past the gutter its sides keep (Sprint 25.16 A42)\n \"scroll-pb-[4px]\",\n scrollable && \"overflow-y-auto\",\n layout === \"multi-column\" && \"flex\",\n )}\n // while a bulk-action bar shows, the keyboard stops short of it (WCAG 2.4.11), and the page's foot has room for\n // it (the spacer below): never padding here, which would sit under a view that fills the page\n style={{ containerType: \"inline-size\", ...(barRoom ? { scrollPaddingBottom: `calc(${barRoom}px + ${barSafe})` } : {}) }}\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 {barSpacer}\n </div>\n ) : <>{children}{barSpacer}</>\n ) : (\n <div className=\"absolute inset-0\">{children}</div>\n )}\n </main>\n </BulkBarHostCtx>\n <div ref={setBarLayer} data-bulk-bar-layer=\"\" className={BULK_BAR_LAYER} style={{ paddingBottom: `calc(${BULK_BAR_GAP}px + ${barSafe})` }} />\n </div>\n\n <div ref={setRightAsideHost} data-shell-aside-host=\"right\" className=\"contents\" />\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\" && <AsideSlotContext value={true}>{aside}</AsideSlotContext>}\n </div>\n\n {showMobileDrawer && isMobile && (\n // Under the navbar, the menu is modal over the page with the navbar in its scope: the rest inert, Tab cycling the\n // two, Escape closing it (the Authoring Practices; Sprint 25.29 item 9). The stacked shell, with no offset, traps\n // in the menu alone.\n <DrawerScopeCtx value={layout !== \"stacked\" && navbar != null ? navbarRef : null}>\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 labelledBy={menuNameId}\n >\n <span id={menuNameId} hidden>Menu</span>\n {mobileMenu}\n </Drawer>\n </DrawerScopeCtx>\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 </AsideSlotContext>\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, FOCUS_RING, FOCUS_INSET } from \"../lib/utils\";\nimport { useRevealFocus } from \"../lib/reveal-focus\";\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 // the menu scrolls: the arrows' item comes into view whole (Sprint 30, P3)\n const [menu, setMenu] = useState<HTMLDivElement | null>(null);\n const setDropdown = useCallback((node: HTMLDivElement | null) => { dropdownRef.current = node; setMenu(node); }, []);\n useRevealFocus(menu);\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 FOCUS_RING,\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 FOCUS_RING,\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={setDropdown}\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:bg-[var(--ds-bg-muted)] focus-visible:text-[var(--ds-text-primary)]\",\n // full-width rows the menu clips, never filled solid: the outline sits inside (P3, D8)\n FOCUS_INSET,\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"]}
|
|
1
|
+
{"version":3,"sources":["../../../showcase/src/lib/use-close-settle.ts","../../../showcase/src/lib/corner-insets.ts","../../../showcase/src/lib/edge-resize.tsx","../../../showcase/src/lib/drawer-width.ts","../../../showcase/src/lib/bulk-bar-host.tsx","../../../showcase/src/lib/use-scrollbar-inset.ts","../../../showcase/src/lib/aside-slot.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"],"names":["t","useEffect","createContext","useState","useRef","useCallback","jsx","useContext","useMemo","jsxs","AppShell","winner","useId","Fragment","forwardRef","Breadcrumbs","createPortal","label"],"mappings":"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","file":"chunk-NJG6JQGC.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 { useEffect } from \"react\";\n\n/**\n * Corner-inset registry.\n *\n * Fixed chrome that occupies a bottom corner — a Launcher, an open CornerPanel —\n * claims the corner so the toast stack lands above it rather than over it.\n * Each claim is a CSS length expression (usually a calc()), so claims cannot be\n * compared numerically; instead every claimant declares a priority and the\n * highest active priority wins, ties going to the most recent claim. The\n * winner is written to the matching --ds-toast-inset-* custom property on the\n * target element (document root by default; a preview frame when the chrome is\n * rendered inside a container). Releasing the last claim removes the override\n * so roots.css's default applies again.\n */\n\n/**\n * A bottom corner (Launcher, CornerPanel), the middle of the bottom edge (a mid-edge bottom ribbon, a bottom panel), a\n * whole side edge (a docked AsidePanel, a non-modal side Drawer, a mid-edge side ribbon), or the top edge (the app's\n * Navbar, round 21).\n */\nexport type InsetEdge = \"bottom-right\" | \"bottom-left\" | \"bottom-center\" | \"right\" | \"left\" | \"top\";\n\nexport const TOAST_INSET_VARS: Record<InsetEdge, string> = {\n \"bottom-right\": \"--ds-toast-inset-bottom-right\",\n \"bottom-left\": \"--ds-toast-inset-bottom-left\",\n \"bottom-center\": \"--ds-toast-inset-bottom-center\",\n right: \"--ds-toast-inset-right\",\n left: \"--ds-toast-inset-left\",\n top: \"--ds-toast-inset-top\",\n};\n\n/**\n * A side claim for a panel beside the stack, capped so a toast still fits beside it at its narrowest (Toast's min-w,\n * 280 px) with a gutter: on a window with no such room the stack overlaps the panel's outer part rather than leaving the\n * window. The percentage is the stack's containing block, the window (or the preview frame).\n */\nexport function besideRoom(room: string): string {\n return `min(${room}, calc(100% - 280px - var(--ds-space-4)))`;\n}\n\n/** Launcher sits under everything else in its corner. */\nexport const LAUNCHER_INSET_PRIORITY = 1;\n/** A corner panel is taller than the launcher beneath it. */\nexport const PANEL_INSET_PRIORITY = 2;\n/** The app's top bar: a toast at the top lands below it, not over the user menu (round 21). */\nexport const NAVBAR_INSET_PRIORITY = 1;\n\ninterface Claim {\n inset: string;\n priority: number;\n seq: number;\n}\n\ntype CornerClaims = Record<InsetEdge, Claim[]>;\n\nconst registry = new WeakMap<Element, CornerClaims>();\nlet seq = 0;\n\nfunction claimsFor(target: Element): CornerClaims {\n let entry = registry.get(target);\n if (!entry) {\n entry = { \"bottom-right\": [], \"bottom-left\": [], \"bottom-center\": [], right: [], left: [], top: [] };\n registry.set(target, entry);\n }\n return entry;\n}\n\nfunction winner(claims: Claim[]): Claim | null {\n let best: Claim | null = null;\n for (const c of claims) {\n if (!best || c.priority > best.priority || (c.priority === best.priority && c.seq > best.seq)) best = c;\n }\n return best;\n}\n\nfunction apply(target: Element, corner: InsetEdge) {\n const style = (target as HTMLElement).style;\n if (!style) return;\n const best = winner(claimsFor(target)[corner]);\n if (best) style.setProperty(TOAST_INSET_VARS[corner], best.inset);\n else style.removeProperty(TOAST_INSET_VARS[corner]);\n}\n\n/**\n * Register a claim on `corner` for `target`. Returns the release function.\n * Imperative form, used by the hook and directly testable.\n */\nexport function claimCornerInset(corner: InsetEdge, inset: string, priority: number, target: Element): () => void {\n const claim: Claim = { inset, priority, seq: ++seq };\n const list = claimsFor(target)[corner];\n list.push(claim);\n apply(target, corner);\n return () => {\n const i = list.indexOf(claim);\n if (i >= 0) list.splice(i, 1);\n apply(target, corner);\n };\n}\n\n/** Test seam: the active claims on a corner of `target`, winner first. */\nexport function getCornerInsetClaims(corner: InsetEdge, target: Element): { inset: string; priority: number }[] {\n const list = registry.get(target)?.[corner] ?? [];\n return [...list]\n .sort((a, b) => (b.priority - a.priority) || (b.seq - a.seq))\n .map(({ inset, priority }) => ({ inset, priority }));\n}\n\n/**\n * Hold a corner claim while `corner` and `inset` are non-null. Pass the\n * container element when the chrome renders inside a frame; otherwise the\n * document root is used so the app-level ToastProvider sees the inset.\n */\nexport function useCornerInset(corner: InsetEdge | null, inset: string | null, priority: number, target?: Element | null) {\n useEffect(() => {\n if (!corner || !inset) return;\n const el = target ?? document.documentElement;\n return claimCornerInset(corner, inset, priority, el);\n }, [corner, inset, priority, target]);\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { cn, GROUP_FOCUS_RING } from \"./utils\";\nimport { Icon } from \"./icons\";\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. Its keyboard focus is\n // drawn round a grip it shows while focused (Sprint 30): an outline round the whole strip would be cut off at its\n // ends, which run the panel's full height, as ResizablePanels' handle draws its own.\n \"group 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 {/* the grip, inside the panel beside its edge, so the panel, which clips what lies past it, shows its outline whole:\n the strip sits a space's width over the edge, and the outline reaches 4 px past the grip */}\n <div\n aria-hidden=\"true\"\n className={cn(\n \"absolute top-1/2 hidden h-4 w-3 -translate-y-1/2 items-center justify-center group-focus-visible:flex\",\n edge === \"left\" ? \"left-[calc(var(--ds-space-1)+4px)]\" : \"right-[calc(var(--ds-space-1)+4px)]\",\n \"rounded-[var(--ds-radius-sm)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] bg-[var(--ds-bg-surface)]\",\n GROUP_FOCUS_RING,\n )}\n >\n <Icon name=\"grip-vertical\" size={10} className=\"text-[var(--ds-text-muted)]\" />\n </div>\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 } 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","/**\n * Where a BulkActionBar floats (Sprint 25.33, the owner, 19 October: \"the floating bulk action bar at the bottom of the\n * screen, without a doubt\"). A surface that scrolls content — the AppShell's content column, a SplitView's pane, a\n * Drawer's or a Dialog's body — hosts the bar: a layer across the foot of what it shows, where the bar is drawn over the\n * content, so selecting a row moves nothing; and the room the bar takes, which the surface keeps at the foot of what\n * scrolls, so the last rows scroll clear of it and the keyboard never puts focus under it (WCAG 2.4.11).\n *\n * Why a layer the surface owns, not `position: fixed`: a fixed box is placed against the nearest ancestor with a filter or\n * a transform, and the library's own surfaces have them (the glass filter on a Card, a Table's frame, a Drawer's slide),\n * so a fixed bar inside a Card landed at the Card's foot (the plan review measured it).\n */\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface BulkBarHost {\n /** The layer the bar is drawn in, across the foot of the host's visible area. */\n layer: HTMLElement | null;\n /** A bar's height while it shows, 0 once it goes, so the host keeps room for the tallest at the foot of what scrolls. */\n setRoom: (bar: object, height: number) => void;\n}\n\nexport const BulkBarHostCtx = createContext<BulkBarHost | null>(null);\n\n/**\n * Internal (Sprint 25.33): the ToastProvider's side. A host (or a bar with none) reports the room its bars take at the\n * page's foot (0 once they go), so the stack at the bottom rises above them at every width; and a bar has its count said\n * in the provider's polite region, which is in the page before the bar is (the bar comes and goes with the selection, so a\n * region of its own is heard by no one).\n */\nexport interface BulkBarPresence {\n room: (owner: object, room: number) => void;\n say: (text: string) => void;\n}\nexport const BulkBarPresenceCtx = createContext<BulkBarPresence | null>(null);\n\n/** The gap between the bar and the host's foot, in px; the room kept above the bar is the bar's height and two of these. */\nexport const BULK_BAR_GAP = 16;\n\n// across the foot, the bar centred and clear of the edges; clicks pass through the layer, but not the bar. Two bars in one\n// host stack, a gap apart, in the order they came (the fix pass of 25.33, L-4: side by side they overflowed the column)\nconst LAYOUT = \"pointer-events-none inset-x-0 bottom-0 z-[var(--ds-z-sticky)] flex flex-col items-center gap-ds-2 px-ds-4 pb-ds-4\";\n/** A host's layer: across the foot of the host, which is positioned. */\nexport const BULK_BAR_LAYER = `absolute ${LAYOUT}`;\n/** With no host (a page outside the shell): across the window's foot, clear of its safe area. */\nexport const BULK_BAR_WINDOW_LAYER = `fixed ${LAYOUT} pb-[calc(var(--ds-space-4)+env(safe-area-inset-bottom))]`;\n\n/** The room to keep at the foot of what scrolls, while a bar of this height shows. */\nexport const bulkBarRoom = (height: number) => (height > 0 ? height + BULK_BAR_GAP * 2 : 0);\n\n/**\n * A host's side: the layer's setter (its ref), the height its bars take now (0 for none: their heights and the gaps between them, as\n * they stack), and the value to provide. The host tells the toasts the room its whole stack takes.\n */\nexport function useBulkBarHost() {\n const presence = useContext(BulkBarPresenceCtx);\n const [layer, setLayer] = useState<HTMLElement | null>(null);\n const [room, setRoomState] = useState(0);\n const bars = useRef(new Map<object, number>());\n const setRoom = useCallback((bar: object, height: number) => {\n if (height > 0) bars.current.set(bar, height);\n else bars.current.delete(bar);\n const heights = [...bars.current.values()];\n const gap = layer ? parseFloat(getComputedStyle(layer).rowGap) || 0 : 0;\n setRoomState(heights.length ? heights.reduce((sum, h) => sum + h, 0) + gap * (heights.length - 1) : 0);\n }, [layer]);\n // the host's own key in the toasts' record of the room taken\n const [owner] = useState(() => ({}));\n useEffect(() => {\n presence?.room(owner, bulkBarRoom(room));\n return () => presence?.room(owner, 0);\n }, [presence, owner, room]);\n const value = useMemo<BulkBarHost>(() => ({ layer, setRoom }), [layer, setRoom]);\n // a host destructures this: the React Compiler's lint reads an object whose value is passed to `ref` as a ref, and each\n // read of it while rendering as reading one (the fix pass of 25.33)\n return { setLayer, room, value };\n}\n\n/**\n * The room a host keeps after what scrolls while a bar shows, so the last rows scroll above it. `extra` adds what else\n * sits under the bar (the window's safe area). The fill-height logic never counts it as the page's content.\n */\nexport function BulkBarSpacer({ room, extra }: { room: number; extra?: string }) {\n const space = bulkBarRoom(room);\n if (!space) return null;\n return <div aria-hidden=\"true\" data-bulk-bar-spacer=\"\" style={{ height: extra ? `calc(${space}px + ${extra})` : space }} />;\n}\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 { createContext } from \"react\";\n\n/**\n * Sprint 32: true where an AsidePanel docks where it's drawn. Inside AppShell's `aside` slot, which is already beside the\n * content column; inside an overlay (a Dialog, a Drawer, a Sheet), which a panel drawn in it never leaves. Elsewhere in a\n * shell it's false (AppShell sets it so round its own content, so an inner shell's pages dock in the inner shell), and a\n * page's own panel docks beside the content column through the shell's host on its side. A file of its own: the shell\n * and the overlays both read it, and the shell imports the Drawer.\n */\nexport const AsideSlotContext = createContext(false);\n","import { useContext, useEffect, useRef, useState, useId, useCallback, useMemo, createContext, type ReactNode, type CSSProperties, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn, OVERLAY_SURFACE, GLASS_OVERLAY, FOCUS_RING, FOCUS_INSET, lockBodyScroll, unlockBodyScroll } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { focusInitial, useReturnFocus, useFocusTrap, useOverlayLayer, useNonModalDialog, inertOutside, OVERLAY_CLOSE_ATTR } from \"../lib/focus\";\nimport { useCloseSettle } from \"../lib/use-close-settle\";\nimport { besideRoom, PANEL_INSET_PRIORITY, useCornerInset } from \"../lib/corner-insets\";\nimport { ResizeEdge, useRememberedWidth, pxOf, defaultMaxWidth } from \"../lib/edge-resize\";\nimport { AutoTooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\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 { BulkBarHostCtx, BulkBarSpacer, useBulkBarHost, BULK_BAR_LAYER, bulkBarRoom } from \"../lib/bulk-bar-host\";\nimport { insetLessScrollbar, useScrollbarInset } from \"../lib/use-scrollbar-inset\";\nimport { AsideSlotContext } from \"../lib/aside-slot\";\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\n/**\n * What stays in a modal drawer's scope outside it (Sprint 25.29 item 9): the shell gives its phone menu, offset below the\n * navbar, the navbar. While the drawer is open everything else in its container is inert, and Tab cycles the two. The\n * panel isn't marked aria-modal, which would hide the navbar from a screen reader; the inert page is what makes it modal.\n */\nexport const DrawerScopeCtx = createContext<RefObject<HTMLElement | null> | 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, and for a non-modal drawer on any side): a draggable bottom Sheet with snap\n * points, always modal.\n * \"panel\" (default for a modal left drawer, 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 // A non-modal panel on a phone covers the page it was beside, so it becomes the modal sheet whatever its side: a left\n // one too, which would otherwise be a full-width panel with nothing to keep focus in it (the review of 21.6 session B).\n const mobileMode = mobile ?? (position === \"left\" && props.modal !== false ? \"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, pending, mark } = useOverlayMark(open);\n // text a control holds uncommitted (a half-typed tag) always asks, whatever the page's `dirty` says (Sprint 25.29 item 15)\n const guard = useDirtyGuard((dirty ?? marked) || pending, 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 wrapperRef = useRef<HTMLDivElement>(null);\n const scope = useContext(DrawerScopeCtx);\n const scoped = !!scope && blocking && !sheet;\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, so it does not trap focus, unless the navbar\n // is in its scope (the shell's phone menu: the two trap together, the rest inert); the phone's sheet always traps.\n useFocusTrap(panelRef, open && blocking && (sheet || !topOffset || scoped), isTopLayer, scoped ? scope : null);\n useEffect(() => {\n const keep = scope?.current;\n const own = wrapperRef.current;\n if (!open || !mounted || !scoped || !keep || !own) return;\n return inertOutside([keep, own], container instanceof Element ? container : document.body);\n }, [open, mounted, scoped, scope, container]);\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 panel the user works alongside keeps the toast stack off it while it is open, as the docked column and the corner\n // window do: a side panel holds its side (toasts slide past it), a bottom panel the bottom edge (toasts land above it,\n // by its measured height). A modal drawer and the phone's sheet cover the page under a backdrop, so they hold nothing.\n const holdsRoom = open && mounted && nonModal && !sheet;\n const horizontal = position === \"left\" || position === \"right\";\n const [panelHeight, setPanelHeight] = useState<number | null>(null);\n useEffect(() => {\n const el = panelRef.current;\n if (!holdsRoom || horizontal || !el || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(([entry]) => {\n const height = ((entry?.target ?? el) as HTMLElement).offsetHeight;\n setPanelHeight(height > 0 ? height : null);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [holdsRoom, horizontal]);\n const claimTarget = container instanceof Element ? container : null;\n const sideRoom = holdsRoom && horizontal ? besideRoom(`calc(${effectiveWidth} + var(--ds-space-4))`) : null;\n const bottomRoom = holdsRoom && !horizontal && panelHeight ? `calc(${panelHeight}px + var(--ds-space-3))` : null;\n useCornerInset(sideRoom ? (position as \"left\" | \"right\") : null, sideRoom, PANEL_INSET_PRIORITY, claimTarget);\n useCornerInset(bottomRoom ? \"bottom-right\" : null, bottomRoom, PANEL_INSET_PRIORITY, claimTarget);\n useCornerInset(bottomRoom ? \"bottom-left\" : null, bottomRoom, PANEL_INSET_PRIORITY, claimTarget);\n useCornerInset(bottomRoom ? \"bottom-center\" : null, bottomRoom, PANEL_INSET_PRIORITY, claimTarget);\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 bodyInset = useScrollbarInset<HTMLDivElement>();\n // a body that scrolls with nothing inside to Tab to is a Tab stop, named by the drawer's title (Sprint 25.29 item 10)\n const [bodyEl, setBodyEl] = useState<HTMLDivElement | null>(null);\n const bodyRef = useCallback((el: HTMLDivElement | null) => { bodyInset(el); setBodyEl(el); }, [bodyInset]);\n useKeyboardScroll(bodyEl, typeof title === \"string\" ? title : \"Content\", open);\n // a bulk-action bar inside floats at the body's foot, above the footer (Sprint 25.33)\n const { setLayer: setBarLayer, room: barStack, value: barHost } = useBulkBarHost();\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 ref={wrapperRef}\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 && !scoped ? \"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 <AutoTooltip content={title}>\n <h2 ref={titleOverflowRef} id={titleId} className={heading}>{title}</h2>\n </AutoTooltip>\n ) : (\n <h2 ref={titleOverflowRef} id={titleId} className={heading}>{title}</h2>\n )}\n {/* an icon button's one tooltip, its name (Sprint 25.29 item 18, accessibility#10) */}\n <AutoTooltip content=\"Close\">\n <button type=\"button\"\n onClick={onClose}\n {...{ [OVERLAY_CLOSE_ATTR]: \"\" }}\n className={cn(\"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer\", FOCUS_RING)}\n aria-label=\"Close\"\n >\n <Icon name=\"close\" size={18} />\n </button>\n </AutoTooltip>\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. Its box\n hosts a bulk-action bar from inside: at its foot, above the footer, with room kept under the last rows */}\n <div className=\"relative flex-1 min-h-0 flex flex-col\">\n <div\n ref={bodyRef}\n // a Tab stop while it scrolls with nothing inside to Tab to: the inset ring SplitView's panes draw (Sprint 25.29)\n className={cn(\"flex-1 min-h-0 overflow-y-auto\", FOCUS_INSET)}\n style={{\n ...(flush ? {} : { padding: `var(--ds-space-5) ${insetLessScrollbar(INSET)} var(--ds-space-5) ${INSET}` }),\n ...(barStack ? { scrollPaddingBottom: bulkBarRoom(barStack) } : {}),\n }}\n >\n {/* Sprint 32: an AsidePanel drawn in a drawer or a sheet (this panel draws both) docks there, never portalled out */}\n <BulkBarHostCtx value={barHost}><SurfaceBoundary><AsideSlotContext value={true}>{children}</AsideSlotContext></SurfaceBoundary></BulkBarHostCtx>\n <BulkBarSpacer room={barStack} />\n </div>\n <div ref={setBarLayer} data-bulk-bar-layer=\"\" className={BULK_BAR_LAYER} />\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, FOCUS_RING } 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_RING,\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 { useState, useCallback, useEffect, useLayoutEffect, useRef, useId, forwardRef, createContext, useContext, type ReactNode } from \"react\";\nimport { REACT_VERSION_PROBLEM } from \"../lib/react-version\";\nimport { AsideSlotContext } from \"../lib/aside-slot\";\nimport { warnOnce } from \"../lib/dev-warn\";\nimport type { AppShellTheme, ChromePosition } from \"../lib/shell-theme\";\nimport { PreferencesContext, type AppShellPreferences } from \"../lib/preferences\";\nimport { SkipLink } from \"./SkipLink\";\nimport { cn, FOCUS_INSET_WHILE_STOP } from \"../lib/utils\";\nimport { useBreakpoint } from \"../lib/use-breakpoint\";\nimport { Drawer, DrawerScopeCtx } from \"./Drawer\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\nimport { DrawerWidthCtx } from \"../lib/drawer-width\";\nimport { BulkBarHostCtx, BulkBarSpacer, useBulkBarHost, BULK_BAR_LAYER, BULK_BAR_GAP, bulkBarRoom } from \"../lib/bulk-bar-host\";\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 below the `lg` breakpoint, expanded from 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 (the aside slot's, or a page's own) is open beside the content. Pages may hide non-essential chrome on it. */\n asideOpen: boolean;\n /** For a docked panel of an app's own, not an AsidePanel, which tells the shell itself (`reportAside`); 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 /** As setAsideOpen: for a docked panel of an app's own; not for pages to call. */\n setAsideFloating: (floating: boolean) => void;\n /** The side of the docked AsidePanel that is open and floating, or null: a floating PageHeader drops its gutter on that side. */\n asideFloatingSide: \"right\" | \"left\" | null;\n /**\n * How each AsidePanel in the shell tells it where it stands, by its onClose (a ref to the latest), null as it goes. One\n * AsidePanel is open at a time in a shell, whatever its side or its form (docked, drawer or sheet): the one opened last\n * wins, and the shell closes the others through their own onClose. Read by AsidePanel; not for pages to call.\n */\n reportAside: (onClose: { readonly current: () => void }, state: AsidePanelReport | null) => void;\n /**\n * Where an AsidePanel a page renders docks (Sprint 32): beside the content column on its side, where the aside slot's\n * does, so a page's own panel (a dashboard editor's widget library) docks like the app's while it stays in the page's\n * tree, and the page's context reaches it. Read by AsidePanel; not for pages to read.\n */\n asideHosts: { left: HTMLElement | null; right: HTMLElement | null };\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 a bubble or pill launcher occupies, so the container's bottom padding reads that corner's inset variable. The page's padding ignores a ribbon, which hugs the window's edge (its claim keeps only toasts off it). */\n launcherCorner: \"bottom-right\" | \"bottom-left\" | null;\n /** Called by a Launcher inside the shell with the corner it occupies (null for a ribbon), so the padding follows the Launcher itself however the slot wraps it. Returns the unregister. */\n registerLauncher: (corner: \"bottom-right\" | \"bottom-left\" | null) => () => void;\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\n/** What an AsidePanel tells the shell it's in (AppShellContextValue's `reportAside`). */\nexport interface AsidePanelReport {\n open: boolean;\n /** Its `open` has just turned true (an onClose new each render is no opening). */\n opened: boolean;\n /** A page's own panel, not the aside slot's: of two opened together, the page's wins. */\n page: boolean;\n /** Docked beside the content column at this width, not the Drawer it becomes below its collapse width. */\n docked: boolean;\n floating: boolean;\n side: \"right\" | \"left\";\n /** The id of the heading that names it (its labelledBy), for a development warning. */\n name: string;\n}\n\nconst AppShellContext = createContext<AppShellContextValue | null>(null);\n\n/**\n * The app shell around this component, or null outside one: its layout state — whether it has a sidebar, a mobile menu\n * and a mobile nav, whether the sidebar is open or collapsed and the aside open (each with its setter), the viewport tier\n * (`isMobile`, `isTablet`), the theme it was given and whether its navbar and sidebar float. For telling the shell about\n * unsaved changes, use `useUnsavedChanges`.\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 from the sm breakpoint up, where Tailwind's `sm:` starts — a conditional\n * render, because the Launcher portals out of any wrapper — so below it, on phones, the Navbar button is the entry\n * point 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 // a docked panel of an app's own (setAsideOpen, setAsideFloating); an AsidePanel tells the shell through reportAside\n const [ownAsideOpen, setAsideOpen] = useState(false);\n const [ownAsideFloating, setAsideFloating] = useState(false);\n // where a page's own AsidePanel docks, beside the content column (Sprint 32)\n const [leftAsideHost, setLeftAsideHost] = useState<HTMLDivElement | null>(null);\n const [rightAsideHost, setRightAsideHost] = useState<HTMLDivElement | null>(null);\n // Sprint 32, G6: one AsidePanel open at a time, whatever its side or form, the one opened last winning (the owner's\n // answer of 20 October 2026, asked of a dashboard's widget library opening beside the docked assistant). Each panel, by\n // its onClose, and what it last told the shell; read in effects only.\n const asides = useRef(new Map<{ readonly current: () => void }, AsidePanelReport>());\n // the panels opened since the shell last looked, in the order they said so\n const opened = useRef<Array<{ readonly current: () => void }>>([]);\n const [openings, setOpenings] = useState(0);\n // the docked panel that's open, which the content column gives way to: its side, and whether it floats\n const [docked, setDocked] = useState<{ side: \"right\" | \"left\"; floating: boolean } | null>(null);\n // the panels asked to close, looked at again once their pages have answered\n const [asked, setAsked] = useState<Array<{ readonly current: () => void }>>([]);\n const reportAside = useCallback((onClose: { readonly current: () => void }, state: AsidePanelReport | null) => {\n if (state) asides.current.set(onClose, state);\n else asides.current.delete(onClose);\n if (state?.opened) {\n opened.current.push(onClose);\n setOpenings((n) => n + 1);\n }\n let next: { side: \"right\" | \"left\"; floating: boolean } | null = null;\n for (const s of asides.current.values()) if (s.open && s.docked) next = { side: s.side, floating: s.floating };\n setDocked((d) => (d?.side === next?.side && d?.floating === next?.floating ? d : next));\n }, []);\n // The panels opened since the shell last looked, all of one commit together (each panel tells the shell as it commits,\n // and this runs once they all have): the page's own wins over the slot's, as their order in the tree differs by side,\n // else the last to open. Every other open panel is closed through its own onClose, so the app's state follows (the\n // assistant's launcher comes back, the library's button reads closed); a panel kept mounted keeps its content.\n useLayoutEffect(() => {\n const keys = opened.current.filter((key) => asides.current.get(key)?.open);\n opened.current = [];\n if (keys.length === 0) return;\n let winner = keys[keys.length - 1];\n for (const key of keys) if (asides.current.get(key)?.page) winner = key;\n const closing = [...asides.current].filter(([key, s]) => key !== winner && s.open).map(([key]) => key);\n for (const key of closing) key.current();\n // looked at again once the pages have answered, which commits with this\n if (closing.length > 0) setAsked(closing);\n }, [openings]);\n // A panel asked to close is looked at once its page has answered (the answer commits with this render, the panel\n // telling the shell first): one still open is said in development, and never asked again\n useLayoutEffect(() => {\n for (const key of asked) {\n const s = asides.current.get(key);\n if (!s?.open) continue;\n const name = (typeof document !== \"undefined\" && document.getElementById(s.name)?.textContent?.trim()) || s.name;\n warnOnce(\"AsidePanel\", `\"${name}\" stayed open as another opened: one AsidePanel is open at a time in a shell, the last opened, so its onClose must close it (set its open to false).`);\n }\n }, [asked]);\n const asideOpen = docked !== null || ownAsideOpen;\n const asideFloating = docked ? docked.floating : ownAsideFloating;\n // the open docked panel's own side, which a page's panel may have on the other side from the slot's\n const asideFloatingSide = docked ? (docked.floating ? docked.side : null) : ownAsideOpen && ownAsideFloating ? asideSide : null;\n const isMobile = useBreakpoint(\"md\");\n const isSmallMobile = useBreakpoint(\"sm\");\n const isTablet = isMobile && !isSmallMobile;\n // Sidebar tiers, where Tailwind's md: and lg: start (Sprint 25.28): expanded from lg, the auto-rail from md to lg, the\n // drawer 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 // <main> on a page with nothing in it to Tab to, scrolling: a Tab stop, keeping its landmark's role and the skip link's\n // tabindex -1 for when it isn't (Sprint 25.29 item 10)\n const [mainEl, setMainEl] = useState<HTMLElement | null>(null);\n const setMain = useCallback((el: HTMLElement | null) => { mainRef.current = el; setMainEl(el); }, []);\n // the page's bulk-action bar floats in a layer across the content column's foot (Sprint 25.33)\n const { setLayer: setBarLayer, room: barStack, value: barHost } = useBulkBarHost();\n const barRoom = bulkBarRoom(barStack);\n // its foot is the window's, so the bar clears the safe area, but over a phone's tab bar, which clears it itself\n const barSafe = isSmallMobile && hasMobileNav ? \"0px\" : \"env(safe-area-inset-bottom)\";\n const barSpacer = <BulkBarSpacer room={barStack} extra={barSafe} />;\n useKeyboardScroll(mainEl, \"Main content\");\n // The navbar's slot: a box of its own for nothing (display: contents), so the phone menu can keep the navbar in its\n // scope (Sprint 25.29 item 9). A Navbar's own root differs by its form, and an app may bring its own bar.\n const navbarRef = useRef<HTMLDivElement | null>(null);\n const navbarSlot = navbar != null && navbar !== false ? <div ref={navbarRef} data-ds-navbar-slot=\"\" className=\"contents\">{navbar}</div> : navbar;\n const menuNameId = useId();\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 page's padding clears the corner the Launcher occupies, which the Launcher reports itself (a ribbon none), so\n // it holds however the slot wraps it: a preview's launcher beside an overlay of its own, an app's own wrapper. Read\n // from the slot's element, a Fragment or a wrapper read as bottom-right (the review of 21.6 session B).\n const hasLauncher = !!launcher && !isSmallMobile;\n const [launcherClaim, setLauncherClaim] = useState<{ corner: AppShellContextValue[\"launcherCorner\"] } | null>(null);\n const registerLauncher = useCallback((corner: AppShellContextValue[\"launcherCorner\"]) => {\n const claim = { corner };\n setLauncherClaim(claim);\n return () => setLauncherClaim((c) => (c === claim ? null : c));\n }, []);\n const launcherCorner: AppShellContextValue[\"launcherCorner\"] = hasLauncher ? (launcherClaim?.corner ?? null) : null;\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, asideFloatingSide, reportAside, asideHosts: { left: leftAsideHost, right: rightAsideHost }, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome, hasLauncher, launcherCorner, registerLauncher, hasFooter, focus: focus ?? null, hasUnsavedChanges: unsavedCount > 0, addUnsavedChanges, drawerWidth, navigate: navigate ?? null, flowLeft: leftCount > 0, markFlowLeft }}\n >\n {/* G7: a shell drawn inside another's aside slot docks its own pages' panels itself */}\n <AsideSlotContext value={false}>\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, so nothing hides under a phone browser's toolbar (100vh is the height\n // with the toolbar hidden). Sprint 25.21 S1: h-dvh alone, which an app's own height class replaces through cn();\n // the supports-[…] variant that stood beside it survived that merge and beat the app's class (the builder's\n // preview ran under its footer). Every browser that draws the themes' oklch() colours has dvh.\n // Sprint 25.8.7 item 31: clipped, not hidden. A box that hides its overflow is still a scroll container, which\n // the browser scrolls to show a focused element past its edge: on run 73's roles page at 390 px it had moved\n // 424 px after 15 Tab stops, and the next 50 stops sat in a blank band below <main>. Nothing can scroll a\n // clipped box. The page scrolls in <main>, never here, and holds what it positions (below), so in a browser\n // without overflow: clip (Safari 15) nothing of the library's runs past this box to need clipping.\n \"relative h-dvh flex flex-col bg-[var(--ds-bg-canvas)] overflow-clip\",\n className,\n )}>\n {skipLink && <SkipLink href={`#${mainId}`} />}\n {layout === \"sidebar-header\" && navbarSlot}\n {layout === \"multi-column\" && navbarSlot}\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\" && <AsideSlotContext value={true}>{aside}</AsideSlotContext>}\n {/* Sprint 32: a page's own AsidePanel docks here, next to the content (it portals in, staying in the page's\n tree); a box of its own for nothing */}\n <div ref={setLeftAsideHost} data-shell-aside-host=\"left\" className=\"contents\" />\n\n {/* relative: the bulk-action bar's layer sits across its foot (Sprint 25.33) */}\n <div className=\"relative flex-1 flex flex-col min-w-0 min-h-0\">\n {layout === \"sidebar\" && navbarSlot}\n {layout === \"stacked\" && navbarSlot}\n\n <BulkBarHostCtx value={barHost}>\n <main\n ref={setMain}\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 // Sprint 25.8.7 item 31: <main> is the page's containing block, so what the page positions with no\n // positioned box of its own (a Checkbox's visually hidden input) scrolls with the page, and Tab scrolls\n // <main> to it. Placed against the shell instead, it stayed where the unscrolled page had put it, out of\n // <main>'s reach, and focus scrolled the shell's outer box to show it\n \"relative flex-1 min-h-0 focus:outline-none\",\n // the skip link's target draws no ring (GOV.UK's); a Tab stop while it scrolls with nothing in it to Tab\n // to, it draws the inset ring (Sprint 25.29 item 10)\n FOCUS_INSET_WHILE_STOP,\n // the outline's reach at the foot as scroll padding, which a control Tab reaches across the bottom edge\n // stops short of (Sprint 25.29 item 19; a pinned PageHeader claims the top inline). The page's last control\n // has its room from the page's own foot (PageContainer's bottom padding): padding here would sit under a\n // view that fills the page, past the gutter its sides keep (Sprint 25.16 A42)\n \"scroll-pb-[4px]\",\n scrollable && \"overflow-y-auto\",\n layout === \"multi-column\" && \"flex\",\n )}\n // while a bulk-action bar shows, the keyboard stops short of it (WCAG 2.4.11), and the page's foot has room for\n // it (the spacer below): never padding here, which would sit under a view that fills the page\n style={{ containerType: \"inline-size\", ...(barRoom ? { scrollPaddingBottom: `calc(${barRoom}px + ${barSafe})` } : {}) }}\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 {barSpacer}\n </div>\n ) : <>{children}{barSpacer}</>\n ) : (\n <div className=\"absolute inset-0\">{children}</div>\n )}\n </main>\n </BulkBarHostCtx>\n <div ref={setBarLayer} data-bulk-bar-layer=\"\" className={BULK_BAR_LAYER} style={{ paddingBottom: `calc(${BULK_BAR_GAP}px + ${barSafe})` }} />\n </div>\n\n <div ref={setRightAsideHost} data-shell-aside-host=\"right\" className=\"contents\" />\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\" && <AsideSlotContext value={true}>{aside}</AsideSlotContext>}\n </div>\n\n {showMobileDrawer && isMobile && (\n // Under the navbar, the menu is modal over the page with the navbar in its scope: the rest inert, Tab cycling the\n // two, Escape closing it (the Authoring Practices; Sprint 25.29 item 9). The stacked shell, with no offset, traps\n // in the menu alone.\n <DrawerScopeCtx value={layout !== \"stacked\" && navbar != null ? navbarRef : null}>\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 labelledBy={menuNameId}\n >\n <span id={menuNameId} hidden>Menu</span>\n {mobileMenu}\n </Drawer>\n </DrawerScopeCtx>\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 </AsideSlotContext>\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, FOCUS_RING, FOCUS_INSET } from \"../lib/utils\";\nimport { useRevealFocus } from \"../lib/reveal-focus\";\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 // the menu scrolls: the arrows' item comes into view whole (Sprint 30, P3)\n const [menu, setMenu] = useState<HTMLDivElement | null>(null);\n const setDropdown = useCallback((node: HTMLDivElement | null) => { dropdownRef.current = node; setMenu(node); }, []);\n useRevealFocus(menu);\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 FOCUS_RING,\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 FOCUS_RING,\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={setDropdown}\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:bg-[var(--ds-bg-muted)] focus-visible:text-[var(--ds-text-primary)]\",\n // full-width rows the menu clips, never filled solid: the outline sits inside (P3, D8)\n FOCUS_INSET,\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"]}
|