@nimblebrain/synapse 0.17.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -18
- package/dist/chunk-54W6IAHM.js +24 -0
- package/dist/chunk-54W6IAHM.js.map +1 -0
- package/dist/{chunk-UPDBDXQB.js → chunk-DRLVEHCD.js} +6 -13
- package/dist/chunk-DRLVEHCD.js.map +1 -0
- package/dist/chunk-NP7ROSH2.cjs +33 -0
- package/dist/chunk-NP7ROSH2.cjs.map +1 -0
- package/dist/{chunk-SRQNQ26I.js → chunk-OYLZ5OCK.js} +4 -4
- package/dist/chunk-OYLZ5OCK.js.map +1 -0
- package/dist/chunk-P5DBJFSQ.js +8459 -0
- package/dist/chunk-P5DBJFSQ.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +9 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-Q7SFCCGT.cjs +11 -0
- package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
- package/dist/chunk-QXDCA7QW.cjs +8466 -0
- package/dist/chunk-QXDCA7QW.cjs.map +1 -0
- package/dist/{chunk-EHLQWCYV.cjs → chunk-RU64F5RS.cjs} +7 -7
- package/dist/chunk-RU64F5RS.cjs.map +1 -0
- package/dist/{chunk-TXJMGQYF.cjs → chunk-SZWHFTXV.cjs} +5 -13
- package/dist/chunk-SZWHFTXV.cjs.map +1 -0
- package/dist/codegen/cli.cjs +4 -4
- package/dist/codegen/cli.js +4 -4
- package/dist/codegen/index.cjs +1 -0
- package/dist/codegen/index.d.cts +1 -1
- package/dist/codegen/index.d.ts +1 -1
- package/dist/codegen/index.js +1 -0
- package/dist/connect.iife.global.js +66 -43
- package/dist/{detect-Bf8Q_0dK.d.ts → detect-DBwc8a21.d.ts} +2 -2
- package/dist/{detect-BHYg26_d.d.cts → detect-DZMJsyvZ.d.cts} +2 -2
- package/dist/host/index.cjs +15 -14
- package/dist/host/index.d.cts +3 -3
- package/dist/host/index.d.ts +3 -3
- package/dist/host/index.js +3 -2
- package/dist/index.cjs +42 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -13
- package/dist/index.d.ts +40 -13
- package/dist/index.js +35 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +12 -10
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +14 -5
- package/dist/react/index.d.ts +14 -5
- package/dist/react/index.js +7 -5
- package/dist/react/index.js.map +1 -1
- package/dist/schema-reader-GM4A4L44.js +4 -0
- package/dist/{schema-reader-776246MJ.js.map → schema-reader-GM4A4L44.js.map} +1 -1
- package/dist/{schema-reader-B6LTGBMJ.cjs → schema-reader-MWBRQ2TQ.cjs} +3 -2
- package/dist/{schema-reader-B6LTGBMJ.cjs.map → schema-reader-MWBRQ2TQ.cjs.map} +1 -1
- package/dist/{server-QIYIJHD5.cjs → server-LR6T6C44.cjs} +32 -20
- package/dist/server-LR6T6C44.cjs.map +1 -0
- package/dist/{server-5N76YCWC.js → server-UHPEE55X.js} +32 -21
- package/dist/server-UHPEE55X.js.map +1 -0
- package/dist/synapse-runtime.iife.global.js +66 -43
- package/dist/synapse-ui.iife.global.js +2 -2
- package/dist/{type-generator-UA3L4OIA.cjs → type-generator-YTPFWLVG.cjs} +3 -2
- package/dist/{type-generator-UA3L4OIA.cjs.map → type-generator-YTPFWLVG.cjs.map} +1 -1
- package/dist/type-generator-ZYSVFK3X.js +4 -0
- package/dist/{type-generator-MZ4X4DE5.js.map → type-generator-ZYSVFK3X.js.map} +1 -1
- package/dist/{types-uEO4VFJ2.d.ts → types-CG08aO82.d.cts} +14 -83
- package/dist/{types-uEO4VFJ2.d.cts → types-CG08aO82.d.ts} +14 -83
- package/dist/ui/base.cjs +1 -0
- package/dist/ui/base.cjs.map +1 -1
- package/dist/ui/base.js +1 -0
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/index.cjs +314 -87
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +29 -2
- package/dist/ui/index.d.ts +29 -2
- package/dist/ui/index.js +315 -89
- package/dist/ui/index.js.map +1 -1
- package/dist/vite/index.cjs +74 -30
- package/dist/vite/index.cjs.map +1 -1
- package/dist/vite/index.d.cts +5 -1
- package/dist/vite/index.d.ts +5 -1
- package/dist/vite/index.js +74 -30
- package/dist/vite/index.js.map +1 -1
- package/dist/{writer-NDK4U6C5.cjs → writer-HDRCQSX2.cjs} +3 -3
- package/dist/{writer-NDK4U6C5.cjs.map → writer-HDRCQSX2.cjs.map} +1 -1
- package/dist/{writer-ZNBXYUYC.js → writer-QNDPMEYD.js} +3 -3
- package/dist/{writer-ZNBXYUYC.js.map → writer-QNDPMEYD.js.map} +1 -1
- package/package.json +8 -5
- package/dist/chunk-EHLQWCYV.cjs.map +0 -1
- package/dist/chunk-FDMRJZKT.cjs +0 -788
- package/dist/chunk-FDMRJZKT.cjs.map +0 -1
- package/dist/chunk-SRQNQ26I.js.map +0 -1
- package/dist/chunk-TXJMGQYF.cjs.map +0 -1
- package/dist/chunk-UPDBDXQB.js.map +0 -1
- package/dist/chunk-VYR6V47N.js +0 -781
- package/dist/chunk-VYR6V47N.js.map +0 -1
- package/dist/schema-reader-776246MJ.js +0 -3
- package/dist/server-5N76YCWC.js.map +0 -1
- package/dist/server-QIYIJHD5.cjs.map +0 -1
- package/dist/type-generator-MZ4X4DE5.js +0 -3
package/dist/ui/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/tokens.ts","../../src/ui/components/Avatar.tsx","../../src/ui/components/Badge.tsx","../../src/ui/typography.tsx","../../src/ui/components/Button.tsx","../../src/ui/components/Breadcrumb.tsx","../../src/ui/components/Card.tsx","../../src/ui/components/Drawer.tsx","../../src/ui/primitives.tsx","../../src/ui/components/EmptyState.tsx","../../src/ui/components/ListRow.tsx","../../src/ui/components/PageHeader.tsx","../../src/ui/components/Pagination.tsx","../../src/ui/components/Prose.tsx","../../src/ui/components/SearchField.tsx","../../src/ui/components/SegmentedControl.tsx","../../src/ui/components/Spinner.tsx","../../src/ui/components/StatusDot.tsx","../../src/ui/components/Table.tsx","../../src/ui/components/Tabs.tsx","../../src/ui/layouts/AppFrame.tsx","../../src/ui/layouts/use-container-width.ts","../../src/ui/layouts/ListDetailLayout.tsx","../../src/ui/layouts/PageLayout.tsx","../../src/ui/layouts/SidebarLayout.tsx"],"names":["useState","useEffect","jsx","TONE","ensureStyle","Fragment","STYLE_ID","RULES","createContext","useRef","useId","useMemo","useContext","jsxs","injectBaseReset","Header","Body","Footer","useLayoutEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * The token contract for `@nimblebrain/synapse/ui`.\n *\n * Values are NOT brand hexes — they are `var(--token, fallback)` references to\n * the CSS custom properties the host injects into the app iframe (the MCP\n * ext-apps `hostContext.styles.variables`). Because styling resolves through\n * CSS variables, theme changes (including light↔dark) reflect automatically\n * with no React re-render: the host swaps the `:root` vars and every `var()`\n * re-resolves.\n *\n * The fallbacks are deliberately **unbranded** — system fonts, neutral grays, a\n * generic blue, and generic semantic hues for the status channels. NOT\n * NimbleBrain brand. Brand arrives by injection when the app runs inside the\n * NimbleBrain host; standalone/static renders get a sane\n * unbranded default. This keeps the library host-agnostic.\n * `__tests__/ui/tokens.test.ts` holds the line: every hex in these fallbacks\n * must be in the sanctioned set, same as `theme-defaults.ts`.\n *\n * Components import the static `tokens` object and style with CSS `var()`, so\n * theming (incl. light/dark) resolves in CSS with no re-render.\n */\n\nimport type { CSSProperties } from \"react\";\n\n/** Resolved design tokens as CSS `var()` references with neutral fallbacks. */\nexport const tokens = {\n // ── Surfaces ──\n bg: \"var(--color-background-primary, #ffffff)\",\n bgRaised: \"var(--color-background-secondary, #fafafa)\",\n bgSubtle: \"var(--color-background-tertiary, #f3f4f6)\",\n\n // ── Text ──\n fg: \"var(--color-text-primary, #111827)\",\n fgMuted: \"var(--color-text-secondary, #6b7280)\",\n fgFaint: \"var(--color-text-tertiary, #9ca3af)\",\n accent: \"var(--color-text-accent, #2563eb)\",\n accentFg: \"var(--nb-color-accent-foreground, #ffffff)\",\n\n // ── Border / ring ──\n border: \"var(--color-border-primary, #e5e7eb)\",\n borderStrong: \"var(--color-border-secondary, #d1d5db)\",\n ring: \"var(--color-ring-primary, #2563eb)\",\n\n // ── Status / brand semantics ──\n danger: \"var(--nb-color-danger, #dc2626)\",\n success: \"var(--nb-color-success, #059669)\",\n warning: \"var(--nb-color-warning, #f59e0b)\",\n processing: \"var(--nb-color-processing, #7c3aed)\",\n processingLight: \"var(--nb-color-processing-light, #f3eeff)\",\n infoLight: \"var(--nb-color-info-light, #eef4ff)\",\n\n // ── Typography ──\n fontSans: \"var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)\",\n fontMono: \"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)\",\n fontHeading: \"var(--nb-font-heading, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)\",\n weightNormal: \"var(--font-weight-normal, 400)\",\n weightMedium: \"var(--font-weight-medium, 500)\",\n weightSemibold: \"var(--font-weight-semibold, 600)\",\n weightBold: \"var(--font-weight-bold, 700)\",\n\n // ── Type scale (size + line-height pairs) ──\n textXsSize: \"var(--font-text-xs-size, 0.75rem)\",\n textXsLine: \"var(--font-text-xs-line-height, 1rem)\",\n textSmSize: \"var(--font-text-sm-size, 0.875rem)\",\n textSmLine: \"var(--font-text-sm-line-height, 1.25rem)\",\n textBaseSize: \"var(--font-text-base-size, 1rem)\",\n textBaseLine: \"var(--font-text-base-line-height, 1.5rem)\",\n textLgSize: \"var(--font-text-lg-size, 1.125rem)\",\n textLgLine: \"var(--font-text-lg-line-height, 1.75rem)\",\n headingSmSize: \"var(--font-heading-sm-size, 1.25rem)\",\n headingSmLine: \"var(--font-heading-sm-line-height, 1.75rem)\",\n headingMdSize: \"var(--font-heading-md-size, 1.5rem)\",\n headingMdLine: \"var(--font-heading-md-line-height, 2rem)\",\n headingLgSize: \"var(--font-heading-lg-size, 2rem)\",\n headingLgLine: \"var(--font-heading-lg-line-height, 2.5rem)\",\n\n // ── Radius / border width ──\n radiusXs: \"var(--border-radius-xs, 0.25rem)\",\n radiusSm: \"var(--border-radius-sm, 0.5rem)\",\n radiusMd: \"var(--border-radius-md, 0.75rem)\",\n radiusLg: \"var(--border-radius-lg, 1rem)\",\n radiusXl: \"var(--border-radius-xl, 1.5rem)\",\n borderWidth: \"var(--border-width-regular, 1px)\",\n\n // ── Shadows ──\n shadowHairline: \"var(--shadow-hairline, 0 0 0 1px rgba(0,0,0,0.06))\",\n shadowSm: \"var(--shadow-sm, 0 1px 2px rgba(0,0,0,0.05))\",\n shadowMd: \"var(--shadow-md, 0 4px 6px -1px rgba(0,0,0,0.1))\",\n shadowLg: \"var(--shadow-lg, 0 10px 15px -3px rgba(0,0,0,0.1))\",\n} as const;\n\nexport type Tokens = typeof tokens;\n\n/**\n * A style object that also permits CSS custom properties (`--foo`). React's\n * `CSSProperties` rejects custom-property keys; components that set CSS vars\n * inline (for `:hover`/keyframe plumbing) type their style as this, then pass\n * it to `style` (it down-casts cleanly to `CSSProperties`).\n */\nexport type StyleWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/** Body text sizes. */\nexport type TextSize = \"xs\" | \"sm\" | \"base\" | \"lg\";\n/** Heading sizes. */\nexport type HeadingSize = \"sm\" | \"md\" | \"lg\";\n\nconst TEXT_SCALE: Record<TextSize, CSSProperties> = {\n xs: { fontSize: tokens.textXsSize, lineHeight: tokens.textXsLine },\n sm: { fontSize: tokens.textSmSize, lineHeight: tokens.textSmLine },\n base: { fontSize: tokens.textBaseSize, lineHeight: tokens.textBaseLine },\n lg: { fontSize: tokens.textLgSize, lineHeight: tokens.textLgLine },\n};\n\nconst HEADING_SCALE: Record<HeadingSize, CSSProperties> = {\n sm: { fontSize: tokens.headingSmSize, lineHeight: tokens.headingSmLine },\n md: { fontSize: tokens.headingMdSize, lineHeight: tokens.headingMdLine },\n lg: { fontSize: tokens.headingLgSize, lineHeight: tokens.headingLgLine },\n};\n\n/** `{ fontSize, lineHeight }` for a body-text level. */\nexport function textStyle(size: TextSize): CSSProperties {\n return TEXT_SCALE[size];\n}\n\n/** `{ fontSize, lineHeight }` for a heading level. */\nexport function headingStyle(size: HeadingSize): CSSProperties {\n return HEADING_SCALE[size];\n}\n","/**\n * Avatar — a circular identity chip. Renders an image when `src` is given,\n * otherwise initials derived from `name` on a subtle tinted background.\n */\n\nimport { type HTMLAttributes, useEffect, useState } from \"react\";\nimport { tokens } from \"../tokens.js\";\n\n/** Up to two initials from a name (\"Jordan Ratner\" → \"JR\", \"mat\" → \"M\"). */\nfunction initialsOf(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"?\";\n const first = parts[0] ?? \"\";\n if (parts.length === 1) return first.charAt(0).toUpperCase();\n const last = parts[parts.length - 1] ?? \"\";\n return (first.charAt(0) + last.charAt(0)).toUpperCase();\n}\n\ninterface AvatarProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** Name used for initials and the image alt text. */\n name: string;\n /** Optional image URL; falls back to initials when absent or on error. */\n src?: string;\n /** Diameter in px. Default 28. */\n size?: number;\n}\n\nexport function Avatar({ name, src, size = 28, style, ...rest }: AvatarProps) {\n // Fall back to initials if the image fails to load. Reset on `src` change.\n const [failed, setFailed] = useState(false);\n // biome-ignore lint/correctness/useExhaustiveDependencies: reset only when src changes\n useEffect(() => setFailed(false), [src]);\n const showImage = Boolean(src) && !failed;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n width: size,\n height: size,\n borderRadius: \"50%\",\n overflow: \"hidden\",\n background: tokens.bgSubtle,\n color: tokens.fgMuted,\n fontFamily: tokens.fontSans,\n fontSize: Math.round(size * 0.4),\n fontWeight: tokens.weightSemibold,\n userSelect: \"none\",\n ...style,\n }}\n {...rest}\n >\n {showImage ? (\n <img\n src={src}\n alt={name}\n width={size}\n height={size}\n onError={() => setFailed(true)}\n style={{ width: \"100%\", height: \"100%\", objectFit: \"cover\" }}\n />\n ) : (\n initialsOf(name)\n )}\n </span>\n );\n}\n","/**\n * Badge — a small pill for status and priority labels (e.g. MEDIUM/HIGH,\n * open/resolved). Soft tinted background with a same-hue label.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { tokens } from \"../tokens.js\";\n\nexport type BadgeTone = \"neutral\" | \"accent\" | \"success\" | \"warning\" | \"danger\" | \"processing\";\n\n/** `{ bg, fg }` per tone. Soft tinted background, same-hue label. The status\n * tones have no `*Light` token so their tint is derived from the fg color. */\nconst TONE: Record<BadgeTone, { bg: string; fg: string }> = {\n neutral: { bg: tokens.bgSubtle, fg: tokens.fgMuted },\n accent: { bg: tokens.infoLight, fg: tokens.accent },\n success: { bg: `color-mix(in oklab, ${tokens.success} 14%, transparent)`, fg: tokens.success },\n warning: { bg: `color-mix(in oklab, ${tokens.warning} 14%, transparent)`, fg: tokens.warning },\n danger: { bg: `color-mix(in oklab, ${tokens.danger} 14%, transparent)`, fg: tokens.danger },\n processing: { bg: tokens.processingLight, fg: tokens.processing },\n};\n\ninterface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n tone?: BadgeTone;\n children?: ReactNode;\n}\n\nexport function Badge({ tone = \"neutral\", style, children, ...rest }: BadgeProps) {\n const { bg, fg } = TONE[tone];\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"0.25rem\",\n padding: \"0.1rem 0.45rem\",\n borderRadius: tokens.radiusXs,\n background: bg,\n color: fg,\n fontFamily: tokens.fontSans,\n fontSize: tokens.textXsSize,\n lineHeight: tokens.textXsLine,\n fontWeight: tokens.weightSemibold,\n letterSpacing: \"0.02em\",\n textTransform: \"uppercase\",\n whiteSpace: \"nowrap\",\n ...style,\n }}\n {...rest}\n >\n {children}\n </span>\n );\n}\n","/**\n * Typography components bound to the type scale and the sans/heading font\n * slots. `Text` for body copy, `Heading` for display type (uses the heading\n * font — Hanken Grotesk in the NimbleBrain host, `system-ui` elsewhere).\n */\n\nimport type { CSSProperties, ElementType, HTMLAttributes, ReactNode } from \"react\";\nimport { type HeadingSize, headingStyle, type TextSize, textStyle, tokens } from \"./tokens.js\";\n\ntype Tone = \"default\" | \"muted\" | \"faint\" | \"accent\" | \"danger\" | \"success\";\ntype Weight = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\n\nconst TONE: Record<Tone, string> = {\n default: tokens.fg,\n muted: tokens.fgMuted,\n faint: tokens.fgFaint,\n accent: tokens.accent,\n danger: tokens.danger,\n success: tokens.success,\n};\n\nconst WEIGHT: Record<Weight, string> = {\n normal: tokens.weightNormal,\n medium: tokens.weightMedium,\n semibold: tokens.weightSemibold,\n bold: tokens.weightBold,\n};\n\ninterface TextProps extends Omit<HTMLAttributes<HTMLElement>, \"color\"> {\n size?: TextSize;\n weight?: Weight;\n tone?: Tone;\n mono?: boolean;\n /**\n * Single-line ellipsis truncation.\n *\n * Sets `display: block` alongside the ellipsis rules, and that is load-bearing rather\n * than incidental: `overflow` and `text-overflow` do not apply to a non-replaced INLINE\n * box, so on the default `<span>` the only declaration that survived was\n * `white-space: nowrap` — and the prop did the exact opposite of its name, making text\n * unwrappable instead of clipping it. Inside an auto-layout `<table>` that widened the\n * column to the full string and pushed every later column off the pane.\n *\n * `min-width: 0` comes with it so the box can actually shrink as a flex item; without it\n * a truncating `Text` inside `Inline`/`Stack` refuses to go below its content width and\n * pushes its container instead, which is the same bug one layer out.\n *\n * A truncating cell in a `Table` also needs its column to declare a `width` — see\n * `Column.width`. Auto table layout sizes to content, so the ellipsis has nothing to\n * clip against until some column is pinned.\n */\n truncate?: boolean;\n as?: ElementType;\n children?: ReactNode;\n}\n\n/** Body text. Defaults to base size, normal weight, primary tone, sans font. */\nexport function Text({\n size = \"base\",\n weight = \"normal\",\n tone = \"default\",\n mono = false,\n truncate = false,\n as: As = \"span\",\n style,\n children,\n ...rest\n}: TextProps) {\n const truncation: CSSProperties = truncate\n ? {\n display: \"block\",\n minWidth: 0,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : {};\n return (\n <As\n style={{\n margin: 0,\n fontFamily: mono ? tokens.fontMono : tokens.fontSans,\n fontWeight: WEIGHT[weight],\n color: TONE[tone],\n ...textStyle(size),\n ...truncation,\n ...style,\n }}\n {...rest}\n >\n {children}\n </As>\n );\n}\n\ninterface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, \"color\"> {\n size?: HeadingSize;\n weight?: Weight;\n tone?: Tone;\n as?: ElementType;\n children?: ReactNode;\n}\n\n/** Display heading using the heading font slot. Defaults to md, semibold. */\nexport function Heading({\n size = \"md\",\n weight = \"semibold\",\n tone = \"default\",\n as: As = \"h2\",\n style,\n children,\n ...rest\n}: HeadingProps) {\n return (\n <As\n style={{\n margin: 0,\n fontFamily: tokens.fontHeading,\n fontWeight: WEIGHT[weight],\n color: TONE[tone],\n letterSpacing: \"-0.015em\",\n ...headingStyle(size),\n ...style,\n }}\n {...rest}\n >\n {children}\n </As>\n );\n}\n","/**\n * Button and TextLink. Pseudo-states (`:hover`/`:active`/`:disabled`) live in a\n * once-injected stylesheet that reads token-driven CSS custom properties set\n * inline — so the base values stay token-driven while hover still works.\n */\n\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-button\";\nconst RULES = `\n.nb-btn {\n --nb-btn-bg: transparent;\n --nb-btn-bg-hover: transparent;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.4rem;\n border: var(--nb-btn-border, none);\n border-radius: var(--nb-btn-radius);\n background: var(--nb-btn-bg);\n color: var(--nb-btn-fg);\n font-family: var(--nb-btn-font);\n font-weight: var(--nb-btn-weight);\n cursor: pointer;\n transition: background 130ms ease, color 130ms ease, opacity 130ms ease;\n white-space: nowrap;\n}\n.nb-btn:hover { background: var(--nb-btn-bg-hover); }\n.nb-btn:active { transform: translateY(0.5px); }\n.nb-btn:disabled { opacity: 0.5; cursor: default; }\n.nb-btn:disabled:hover { background: var(--nb-btn-bg); }\n.nb-textlink {\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n font-family: var(--nb-tl-font);\n color: var(--nb-tl-fg);\n transition: color 130ms ease, opacity 130ms ease;\n}\n.nb-textlink:hover { color: var(--nb-tl-fg-hover); }\n.nb-textlink:disabled { opacity: 0.45; cursor: default; }\n`;\n\ntype Variant = \"primary\" | \"secondary\" | \"ghost\";\ntype Size = \"sm\" | \"md\";\n\nconst SIZE_PAD: Record<Size, string> = {\n sm: \"0.3rem 0.6rem\",\n md: \"0.45rem 0.85rem\",\n};\n\ninterface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: Variant;\n size?: Size;\n children?: ReactNode;\n}\n\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n style,\n className,\n children,\n ...rest\n}: ButtonProps) {\n ensureStyle(STYLE_ID, RULES);\n const vars: Record<`--${string}`, string> = {\n \"--nb-btn-radius\": tokens.radiusSm,\n \"--nb-btn-font\": tokens.fontSans,\n \"--nb-btn-weight\": tokens.weightMedium,\n };\n if (variant === \"primary\") {\n vars[\"--nb-btn-bg\"] = tokens.accent;\n vars[\"--nb-btn-bg-hover\"] = `color-mix(in oklab, ${tokens.accent} 88%, black)`;\n vars[\"--nb-btn-fg\"] = tokens.accentFg;\n } else if (variant === \"secondary\") {\n vars[\"--nb-btn-bg\"] = tokens.bgSubtle;\n vars[\"--nb-btn-bg-hover\"] = tokens.bgRaised;\n vars[\"--nb-btn-fg\"] = tokens.fg;\n vars[\"--nb-btn-border\"] = `${tokens.borderWidth} solid ${tokens.border}`;\n } else {\n vars[\"--nb-btn-bg\"] = \"transparent\";\n vars[\"--nb-btn-bg-hover\"] = tokens.bgSubtle;\n vars[\"--nb-btn-fg\"] = tokens.fg;\n }\n const btnStyle: StyleWithVars = {\n ...vars,\n padding: SIZE_PAD[size],\n fontSize: size === \"sm\" ? tokens.textSmSize : tokens.textBaseSize,\n lineHeight: size === \"sm\" ? tokens.textSmLine : tokens.textBaseLine,\n ...style,\n };\n return (\n <button type=\"button\" className={`nb-btn ${className ?? \"\"}`.trim()} style={btnStyle} {...rest}>\n {children}\n </button>\n );\n}\n\ninterface TextLinkProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Resting tone. Hover always moves toward `accent` (or `danger`). */\n tone?: \"muted\" | \"default\" | \"danger\";\n children?: ReactNode;\n}\n\n/** A chrome-less text button — for back / delete / retry affordances. */\nexport function TextLink({ tone = \"muted\", style, className, children, ...rest }: TextLinkProps) {\n ensureStyle(STYLE_ID, RULES);\n const resting =\n tone === \"danger\" ? tokens.danger : tone === \"default\" ? tokens.fg : tokens.fgMuted;\n const hover = tone === \"danger\" ? tokens.danger : tokens.accent;\n const linkStyle: StyleWithVars = {\n \"--nb-tl-font\": tokens.fontSans,\n \"--nb-tl-fg\": resting,\n \"--nb-tl-fg-hover\": hover,\n fontSize: tokens.textXsSize,\n lineHeight: tokens.textXsLine,\n letterSpacing: \"0.02em\",\n ...style,\n };\n return (\n <button\n type=\"button\"\n className={`nb-textlink ${className ?? \"\"}`.trim()}\n style={linkStyle}\n {...rest}\n >\n {children}\n </button>\n );\n}\n","/**\n * Breadcrumb — the trail back, and where you are.\n *\n * A hierarchy deeper than two levels cannot be navigated by a back button: \"up one\" and\n * \"up two\" need separate controls, and an app that grows a second one ends up rendering\n * both adjacent, differently labelled, with only one correct at any depth. A trail has no\n * such limit — every level is named, so every jump is the same gesture — and it answers\n * a question a back button never does, which is where the reader currently is.\n *\n * The last crumb renders as text, never as a disabled control. A control that looks\n * clickable and does nothing is worse than no control, and the reader is already there.\n *\n * Steps are BUTTONS, not anchors, and that is deliberate: a Synapse app lives in an iframe\n * with no address of its own, so a crumb changes app state rather than navigating to a URL.\n * There is no href to put on an anchor, and a `<span>` with a click handler is reachable by\n * neither keyboard nor screen reader.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { Fragment } from \"react\";\nimport { tokens } from \"../tokens.js\";\nimport { Text } from \"../typography.js\";\nimport { TextLink } from \"./Button.js\";\n\nexport interface Crumb {\n label: string;\n /** Omit on the current step. A crumb with no handler renders as plain text. */\n onClick?: () => void;\n}\n\ninterface BreadcrumbProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n crumbs: Crumb[];\n /** The glyph between steps. */\n separator?: string;\n}\n\nexport function Breadcrumb({ crumbs, separator = \"›\", style, ...rest }: BreadcrumbProps) {\n return (\n <nav\n aria-label=\"Breadcrumb\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.4rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n ...style,\n }}\n {...rest}\n >\n {crumbs.map((crumb, i) => {\n const last = i === crumbs.length - 1;\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: a crumb's POSITION is its identity — \"the second level\" is what the step means, and two levels can legitimately carry the same label. There is no id to key on, and a trail that changed shape SHOULD remount rather than reconcile a step into a different depth.\n <Fragment key={`${crumb.label}:${i}`}>\n {last || !crumb.onClick ? (\n <Text\n size=\"xs\"\n tone={last ? \"muted\" : \"default\"}\n aria-current={last ? \"page\" : undefined}\n >\n {crumb.label}\n </Text>\n ) : (\n <TextLink onClick={crumb.onClick} style={{ fontSize: tokens.textXsSize }}>\n {crumb.label}\n </TextLink>\n )}\n {last ? null : (\n <Text size=\"xs\" tone=\"faint\" aria-hidden=\"true\">\n {separator}\n </Text>\n )}\n </Fragment>\n );\n })}\n </nav>\n );\n}\n","/**\n * Card — a raised surface with a hairline border. The default container for\n * grouped content (deal cards, task cards, panels). `interactive` adds a hover\n * lift via a once-injected stylesheet (no per-card handlers).\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-card\";\nconst RULES = `\n.nb-card--interactive {\n cursor: pointer;\n transition: box-shadow 140ms ease, border-color 140ms ease;\n}\n.nb-card--interactive:hover {\n box-shadow: var(--nb-card-shadow-hover);\n border-color: var(--nb-card-border-hover);\n}\n`;\n\ninterface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Inner padding (CSS length or px number). Default `0.875rem`. */\n padding?: number | string;\n /** Lift on hover — for clickable cards. */\n interactive?: boolean;\n children?: ReactNode;\n}\n\nexport function Card({\n padding = \"0.875rem\",\n interactive = false,\n style,\n className,\n children,\n ...rest\n}: CardProps) {\n if (interactive) ensureStyle(STYLE_ID, RULES);\n const cardStyle: StyleWithVars = {\n background: tokens.bgRaised,\n border: `${tokens.borderWidth} solid ${tokens.border}`,\n borderRadius: tokens.radiusMd,\n padding,\n boxShadow: tokens.shadowSm,\n \"--nb-card-shadow-hover\": tokens.shadowMd,\n \"--nb-card-border-hover\": tokens.borderStrong,\n ...style,\n };\n return (\n <div\n className={interactive ? `nb-card--interactive ${className ?? \"\"}`.trim() : className}\n style={cardStyle}\n {...rest}\n >\n {children}\n </div>\n );\n}\n","/**\n * Drawer — an off-canvas overlay panel that slides in from an edge, over a\n * scrim. The general overlay the apps need (e.g. CRM's detail panel).\n *\n * A plain positioned `<div>` overlay — **not** a native `<dialog>`. The platform\n * mounts every app in a sandboxed iframe that withholds `allow-modals`, so\n * `HTMLDialogElement.showModal()` throws there and white-screens the app; a\n * `<dialog>` is unusable in the one environment these apps run in. So the panel\n * hand-rolls what `showModal()` gave for free: a scrim, a Tab/Shift+Tab focus\n * trap (while focus is inside the panel — not the full native `inert`; see the\n * scope note on the open effect and #43), focus-into-panel on open with focus\n * restored on close, background scroll lock, and Escape. Controlled via\n * `open`/`onClose` (renders nothing when closed). Escape routes through `onEscape`\n * (defaults to `onClose`); clicking the scrim calls `onClose`. The slide-in is a\n * CSS keyframe on the panel.\n *\n * Compose with the `Header` / `Body` / `Footer` slots, or pass plain children.\n * `Header` owns the standard affordances — `title` (a real heading, wired as\n * the dialog's accessible name), an optional `onBack` button, an `actions`\n * slot, and the close button — so consumers don't re-roll them. The icon\n * buttons grow to a 44px hit target under `@media (pointer: coarse)`, keyed to\n * input modality rather than viewport width.\n *\n * `side` is `right` (default), `left`, or `bottom` (a bottom sheet — full width,\n * content height capped at 92%). A multi-level \"panel stack\" (push/pop) is an\n * app concern built on top of this.\n */\n\nimport {\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\ntype Side = \"left\" | \"right\" | \"bottom\";\n\nconst STYLE_ID = \"nb-synapse-drawer\";\nconst RULES = `\n.nb-drawer-scrim {\n position: fixed; inset: 0; z-index: 1000;\n display: flex; background: rgba(0, 0, 0, 0.32);\n animation: nb-drawer-fade 200ms ease;\n}\n.nb-drawer-scrim--right { justify-content: flex-end; }\n.nb-drawer-scrim--left { justify-content: flex-start; }\n.nb-drawer-scrim--bottom { align-items: flex-end; }\n.nb-drawer {\n margin: 0; padding: 0; border: none; max-width: 92%;\n height: 100%; max-height: 100%; display: flex; flex-direction: column;\n outline: none;\n}\n.nb-drawer--bottom { width: 100%; max-width: 100%; height: auto; max-height: 92%; }\n.nb-drawer--right { animation: nb-drawer-in-right 240ms cubic-bezier(0.2, 0, 0, 1); }\n.nb-drawer--left { animation: nb-drawer-in-left 240ms cubic-bezier(0.2, 0, 0, 1); }\n.nb-drawer--bottom { animation: nb-drawer-in-bottom 240ms cubic-bezier(0.2, 0, 0, 1); }\n@keyframes nb-drawer-in-right { from { transform: translateX(100%); } }\n@keyframes nb-drawer-in-left { from { transform: translateX(-100%); } }\n@keyframes nb-drawer-in-bottom { from { transform: translateY(100%); } }\n@keyframes nb-drawer-fade { from { opacity: 0; } }\n.nb-drawer-iconbtn { width: 28px; height: 28px; }\n@media (pointer: coarse) {\n .nb-drawer-iconbtn { min-width: 44px; min-height: 44px; }\n}\n`;\n\n// A control inside a *closed* <details> (other than its own <summary>) is not\n// reachable, even though its tabIndex is 0 — the collapse is a UA `display:none`\n// on the disclosure content. It's structural (the `open` attribute + DOM\n// position), so it's detectable without layout and belongs in the filter below,\n// alongside `[hidden]` (also a UA `display:none` rule).\nfunction inClosedDetails(el: HTMLElement): boolean {\n const details = el.closest(\"details:not([open])\");\n if (!details) return false;\n const summary = details.querySelector(\"summary\");\n return !summary || !summary.contains(el);\n}\n\n// Tabbable elements inside the panel, in DOM order — the focus-trap boundary.\n// A broad candidate query filtered by a positive predicate, in place of a\n// `:not(...)` denylist that had to enumerate every non-tabbable case per clause.\n// The filter is the set of non-tabbable cases detectable *without layout*:\n// `tabIndex >= 0` rejects any negative tabindex, `:disabled` inherits through\n// `<fieldset disabled>`, `[hidden]` and closed-<details> collapse are tested on\n// the element and its ancestors. CSS-hidden focusables (`display:none` /\n// `visibility:hidden` set in a stylesheet) need layout to detect, so they're NOT\n// filtered (worst case: one Tab exits).\n//\n// CANDIDATES is an allowlist of mainstream focusables, not `*`: a bare `<a>` (no\n// href) reports tabIndex 0 but isn't focusable, so `*` would admit a phantom\n// boundary — `a[href]` is load-bearing. It is deliberately not exhaustive:\n// media/embeds (`<audio controls>`, `<iframe>`) and `[contenteditable]` are\n// omitted until a consumer needs one, to keep the set honest.\nconst CANDIDATES = \"a[href], button, input, select, textarea, summary, [tabindex]\";\nfunction tabbables(panel: HTMLElement): HTMLElement[] {\n return Array.from(panel.querySelectorAll<HTMLElement>(CANDIDATES)).filter(\n (el) =>\n el.tabIndex >= 0 &&\n !el.matches(\":disabled\") &&\n !el.closest(\"[hidden]\") &&\n !inClosedDetails(el) &&\n (el as HTMLInputElement).type !== \"hidden\",\n );\n}\n\ninterface DrawerContextValue {\n labelId: string;\n setHasTitle: (has: boolean) => void;\n}\n\nconst DrawerContext = createContext<DrawerContextValue | null>(null);\n\ninterface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"onClick\"> {\n open: boolean;\n /** Called by the scrim and the Header close button. */\n onClose: () => void;\n /** Called on Escape. Defaults to `onClose` — override to do something else\n * (e.g. pop one level of a panel stack before closing). */\n onEscape?: () => void;\n side?: Side;\n /** Panel width (ignored for `side=\"bottom\"`, which is full width). Default 480. */\n width?: number | string;\n children?: ReactNode;\n}\n\nfunction DrawerRoot({\n open,\n onClose,\n onEscape,\n side = \"right\",\n width = 480,\n style,\n children,\n ...rest\n}: DrawerProps) {\n ensureStyle(STYLE_ID, RULES);\n const panelRef = useRef<HTMLDivElement>(null);\n const labelId = useId();\n // A `Header` with a `title` registers itself here so the panel can name\n // itself via `aria-labelledby` (preferred over a consumer-passed aria-label).\n const [hasTitle, setHasTitle] = useState(false);\n\n // Escape → onEscape (defaults to onClose). A window keydown listener replaces\n // the native <dialog> `onCancel`, which required showModal() — blocked in the\n // app iframe sandbox (no `allow-modals`).\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n (onEscape ?? onClose)();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open, onEscape, onClose]);\n\n // On open: focus into the panel, lock background scroll, and trap Tab/Shift+Tab\n // within it (the focus-into + Tab containment showModal()'s top-layer gave).\n // Restore focus + scroll on close.\n //\n // Scope: this contains Tab while focus is *inside* the panel — the modal case.\n // It is NOT the full native `inert`: it doesn't recover focus that drops to\n // <body> when a focused child unmounts (that fires focusout, not focusin), nor\n // fence off portal'd overlays a consumer opens outside the panel. A\n // document-scoped focus backstop would do neither reliably and would yank focus\n // out of legitimate nested overlays — so full containment is a FocusScope-style\n // owner stack, deferred to #43.\n useEffect(() => {\n if (!open) return;\n const panel = panelRef.current;\n const previouslyFocused = document.activeElement as HTMLElement | null;\n panel?.focus();\n const { body } = document;\n const prevOverflow = body.style.overflow;\n body.style.overflow = \"hidden\";\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || !panel) return;\n const focusables = tabbables(panel);\n if (focusables.length === 0) {\n // Nothing tabbable inside — preventDefault keeps focus on the panel it's\n // already on (the open effect focused it), so Tab can't leave.\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (e.shiftKey && (active === first || active === panel)) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n };\n panel?.addEventListener(\"keydown\", onKeyDown);\n\n return () => {\n panel?.removeEventListener(\"keydown\", onKeyDown);\n body.style.overflow = prevOverflow;\n previouslyFocused?.focus?.();\n };\n }, [open]);\n\n const ctxValue = useMemo<DrawerContextValue>(() => ({ labelId, setHasTitle }), [labelId]);\n\n if (!open) return null;\n\n const isBottom = side === \"bottom\";\n const panelStyle: StyleWithVars = {\n ...(isBottom ? { width: \"100%\", maxWidth: \"100%\" } : { width }),\n background: tokens.bg,\n color: tokens.fg,\n boxShadow: tokens.shadowLg,\n outline: \"none\",\n ...(side === \"right\"\n ? { borderLeft: `${tokens.borderWidth} solid ${tokens.border}` }\n : side === \"left\"\n ? { borderRight: `${tokens.borderWidth} solid ${tokens.border}` }\n : { borderTop: `${tokens.borderWidth} solid ${tokens.border}` }),\n ...style,\n };\n\n return (\n <DrawerContext.Provider value={ctxValue}>\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: scrim click is a bonus mouse affordance; Escape (the window keydown above) and the Header close button are the keyboard dismissal paths. */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: the scrim is a decorative dismissal backdrop; the panel below owns the dialog role/semantics. */}\n <div\n className={`nb-drawer-scrim nb-drawer-scrim--${side}`}\n onClick={(e) => {\n // A click whose target is the scrim itself (not the panel) dismisses.\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={hasTitle ? labelId : undefined}\n tabIndex={-1}\n className={`nb-drawer nb-drawer--${side}`}\n style={panelStyle}\n {...rest}\n >\n {children}\n </div>\n </div>\n </DrawerContext.Provider>\n );\n}\n\ninterface HeaderProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Heading text — rendered as an `<h2>` and wired as the drawer's accessible\n * name. Renders **instead of** `children` (pass one or the other, not both).\n */\n title?: ReactNode;\n /** Show a leading back button (e.g. pop one level of a panel stack). */\n onBack?: () => void;\n /** Trailing controls placed before the close button. */\n actions?: ReactNode;\n /** Show a close button that calls this. */\n onClose?: () => void;\n children?: ReactNode;\n}\n\nfunction Header({ title, onBack, actions, onClose, style, children, ...rest }: HeaderProps) {\n const ctx = useContext(DrawerContext);\n const hasTitle = title != null;\n\n // Register the title's presence so the dialog can name itself via this h2.\n useEffect(() => {\n if (!ctx || !hasTitle) return;\n ctx.setHasTitle(true);\n return () => ctx.setHasTitle(false);\n }, [ctx, hasTitle]);\n\n return (\n <header\n style={{\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.75rem\",\n padding: \"0.875rem 1rem\",\n borderBottom: `${tokens.borderWidth} solid ${tokens.border}`,\n fontFamily: tokens.fontSans,\n fontWeight: tokens.weightSemibold,\n color: tokens.fg,\n ...style,\n }}\n {...rest}\n >\n {onBack ? (\n <IconButton label=\"Back\" onClick={onBack}>\n <path\n d=\"M10 3L5 8l5 5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </IconButton>\n ) : null}\n {hasTitle ? (\n <h2\n id={ctx?.labelId}\n style={{\n flex: 1,\n minWidth: 0,\n margin: 0,\n fontFamily: tokens.fontSans,\n fontSize: tokens.textBaseSize,\n lineHeight: tokens.textBaseLine,\n fontWeight: tokens.weightSemibold,\n color: tokens.fg,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {title}\n </h2>\n ) : (\n <div style={{ flex: 1, minWidth: 0 }}>{children}</div>\n )}\n {actions ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"0.4rem\", flexShrink: 0 }}>\n {actions}\n </div>\n ) : null}\n {onClose ? (\n <IconButton label=\"Close\" onClick={onClose}>\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </IconButton>\n ) : null}\n </header>\n );\n}\n\n/** Shared 28px (→44px on coarse pointers) icon button for the header affordances. */\nfunction IconButton({\n label,\n onClick,\n children,\n}: {\n label: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n onClick={onClick}\n className=\"nb-drawer-iconbtn\"\n style={{\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n background: \"transparent\",\n color: tokens.fgMuted,\n cursor: \"pointer\",\n borderRadius: tokens.radiusSm,\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n {children}\n </svg>\n </button>\n );\n}\n\nfunction Body({ style, children, ...rest }: HTMLAttributes<HTMLDivElement>) {\n return (\n <div style={{ flex: 1, minHeight: 0, overflowY: \"auto\", padding: \"1rem\", ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\nfunction Footer({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n return (\n <footer\n style={{\n flexShrink: 0,\n padding: \"0.75rem 1rem\",\n borderTop: `${tokens.borderWidth} solid ${tokens.border}`,\n ...style,\n }}\n {...rest}\n >\n {children}\n </footer>\n );\n}\n\n/** `Drawer` with `.Header`, `.Body`, `.Footer` slots. */\nexport const Drawer = Object.assign(DrawerRoot, { Header, Body, Footer });\n","/**\n * Layout primitives — the composition atoms. `Stack` (vertical) and `Inline`\n * (horizontal) replace ad-hoc `display:flex` style objects; `Spacer` and\n * `Divider` cover the two other recurring layout needs. Deliberately minimal\n * (no `Box`, no grid system) — the layout scaffolds handle page structure.\n */\n\nimport type { CSSProperties, HTMLAttributes, ReactNode } from \"react\";\nimport { tokens } from \"./tokens.js\";\n\ntype Align = \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\";\ntype Justify = \"start\" | \"center\" | \"end\" | \"between\" | \"around\";\n\nconst ALIGN: Record<Align, CSSProperties[\"alignItems\"]> = {\n start: \"flex-start\",\n center: \"center\",\n end: \"flex-end\",\n stretch: \"stretch\",\n baseline: \"baseline\",\n};\n\nconst JUSTIFY: Record<Justify, CSSProperties[\"justifyContent\"]> = {\n start: \"flex-start\",\n center: \"center\",\n end: \"flex-end\",\n between: \"space-between\",\n around: \"space-around\",\n};\n\ninterface FlexProps extends HTMLAttributes<HTMLDivElement> {\n gap?: number | string;\n align?: Align;\n justify?: Justify;\n wrap?: boolean;\n children?: ReactNode;\n}\n\nfunction flexStyle(\n direction: \"row\" | \"column\",\n { gap, align, justify, wrap }: FlexProps,\n): CSSProperties {\n return {\n display: \"flex\",\n flexDirection: direction,\n gap,\n alignItems: align ? ALIGN[align] : undefined,\n justifyContent: justify ? JUSTIFY[justify] : undefined,\n flexWrap: wrap ? \"wrap\" : undefined,\n };\n}\n\n/** Vertical flex container with `gap`. Defaults to `align: stretch`. */\nexport function Stack({ gap, align, justify, wrap, style, children, ...rest }: FlexProps) {\n return (\n <div style={{ ...flexStyle(\"column\", { gap, align, justify, wrap }), ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\n/** Horizontal flex container with `gap`. Defaults to `align: center`. */\nexport function Inline({\n gap,\n align = \"center\",\n justify,\n wrap,\n style,\n children,\n ...rest\n}: FlexProps) {\n return (\n <div style={{ ...flexStyle(\"row\", { gap, align, justify, wrap }), ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\n/** Flexible gap that pushes siblings apart inside a `Stack`/`Inline`. */\nexport function Spacer({ style, ...rest }: HTMLAttributes<HTMLDivElement>) {\n return <div style={{ flex: 1, ...style }} {...rest} />;\n}\n\ninterface DividerProps extends HTMLAttributes<HTMLDivElement> {\n orientation?: \"horizontal\" | \"vertical\";\n}\n\n/** A hairline rule using the border token. Horizontal by default. Decorative\n * (`aria-hidden`) — it's a visual divider, not a focusable/valued separator. */\nexport function Divider({ orientation = \"horizontal\", style, ...rest }: DividerProps) {\n const isVertical = orientation === \"vertical\";\n return (\n <div\n aria-hidden=\"true\"\n style={{\n flexShrink: 0,\n background: tokens.border,\n ...(isVertical\n ? { width: tokens.borderWidth, alignSelf: \"stretch\" }\n : { height: tokens.borderWidth, width: \"100%\" }),\n ...style,\n }}\n {...rest}\n />\n );\n}\n","/**\n * EmptyState — centered placeholder for empty lists/views. Optional icon,\n * title, description, and an action slot (e.g. a Button).\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Stack } from \"../primitives.js\";\nimport { tokens } from \"../tokens.js\";\nimport { Heading, Text } from \"../typography.js\";\n\ninterface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n icon?: ReactNode;\n title?: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n}\n\nexport function EmptyState({ icon, title, description, action, style, ...rest }: EmptyStateProps) {\n return (\n <Stack\n align=\"center\"\n gap=\"0.5rem\"\n style={{\n textAlign: \"center\",\n padding: \"4rem 1.5rem\",\n color: tokens.fgMuted,\n ...style,\n }}\n {...rest}\n >\n {icon ? <div style={{ color: tokens.fgFaint, marginBottom: \"0.25rem\" }}>{icon}</div> : null}\n {title ? <Heading size=\"sm\">{title}</Heading> : null}\n {description ? (\n <Text size=\"sm\" tone=\"muted\" style={{ maxWidth: 360 }}>\n {description}\n </Text>\n ) : null}\n {action ? <div style={{ marginTop: \"0.75rem\" }}>{action}</div> : null}\n </Stack>\n );\n}\n","/**\n * ListRow — the recurring list item: an optional leading slot (status dot,\n * avatar), a title with optional meta line, and a trailing slot (timestamp,\n * actions). Rounded hover tint, flat at rest — the pattern Research,\n * Conversations, and the Collateral sidebar each re-rolled.\n */\n\nimport type { HTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-listrow\";\nconst RULES = `\n.nb-listrow { transition: background 140ms ease; }\n.nb-listrow--interactive { cursor: pointer; }\n.nb-listrow--interactive:hover { background: var(--nb-listrow-hover); }\n`;\n\ninterface ListRowProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n title: ReactNode;\n /** Secondary line under the title. */\n meta?: ReactNode;\n /** Leading slot — e.g. a StatusDot or Avatar. */\n leading?: ReactNode;\n /** Trailing slot — e.g. a timestamp or actions. */\n trailing?: ReactNode;\n /** Enables pointer cursor + hover tint. */\n interactive?: boolean;\n}\n\nexport function ListRow({\n title,\n meta,\n leading,\n trailing,\n interactive = false,\n style,\n className,\n ...rest\n}: ListRowProps) {\n ensureStyle(STYLE_ID, RULES);\n const rowStyle: StyleWithVars = {\n \"--nb-listrow-hover\": tokens.bgSubtle,\n display: \"grid\",\n gridTemplateColumns: `${leading ? \"auto \" : \"\"}minmax(0, 1fr)${trailing ? \" auto\" : \"\"}`,\n columnGap: \"0.75rem\",\n alignItems: \"baseline\",\n padding: \"0.65rem 0.75rem\",\n borderRadius: tokens.radiusSm,\n ...style,\n };\n // When interactive, make the row keyboard-operable (matches Table's rows):\n // role=\"button\" + tabIndex, and Enter/Space synthesize the click that drives\n // the consumer's onClick (passed via ...rest). Placed before ...rest so a\n // consumer can still override any of these explicitly.\n const interactiveProps = interactive\n ? {\n role: \"button\",\n tabIndex: 0,\n onKeyDown: (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n e.currentTarget.click();\n }\n },\n }\n : {};\n return (\n <div\n className={`nb-listrow ${interactive ? \"nb-listrow--interactive\" : \"\"} ${className ?? \"\"}`.trim()}\n style={rowStyle}\n {...interactiveProps}\n {...rest}\n >\n {leading ? <div style={{ alignSelf: \"center\", display: \"flex\" }}>{leading}</div> : null}\n <div style={{ minWidth: 0 }}>\n <div\n style={{\n fontFamily: tokens.fontSans,\n fontSize: tokens.textBaseSize,\n lineHeight: tokens.textBaseLine,\n fontWeight: tokens.weightMedium,\n color: tokens.fg,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {title}\n </div>\n {meta ? (\n <div\n style={{\n marginTop: \"0.15rem\",\n fontFamily: tokens.fontSans,\n fontSize: tokens.textXsSize,\n lineHeight: tokens.textXsLine,\n color: tokens.fgMuted,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {meta}\n </div>\n ) : null}\n </div>\n {trailing ? (\n <div\n style={{\n alignSelf: \"center\",\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n fontSize: tokens.textXsSize,\n color: tokens.fgMuted,\n whiteSpace: \"nowrap\",\n }}\n >\n {trailing}\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * PageHeader — the top of a page: where you are, what this is, and what you can do to it.\n *\n * One component rather than each screen assembling its own, because the parts have to keep\n * one order and one rhythm for a multi-screen app to read as one app. It is also what makes\n * a full-width screen legible as a LEVEL in a hierarchy rather than as a page that happens\n * to be open — the trail above the title is doing that work, not decoration.\n *\n * The order is fixed and the reasons are not interchangeable: the trail comes first because\n * orientation precedes identity; actions sit on the title's row because they act on the\n * thing the title names; the description comes last because it is the only part a reader\n * can skip.\n *\n * **The description is clamped to two lines.** Descriptions here are frequently\n * agent-authored and of no bounded length, and an unbounded paragraph at the top of every\n * screen pushes the content the reader came for below the fold. Two lines is enough to\n * identify the thing and not enough to become the page. Callers with genuinely short,\n * curated copy can raise it; the default protects the common case rather than the tidy one.\n *\n * `status` and `actions` are ReactNode slots, not typed vocabularies. A page header has no\n * business knowing what states a caller's entity can be in or which of its verbs are primary —\n * that knowledge belongs to the app, and a kit that encoded it would need extending for every\n * app that arrived with a different one.\n *\n * **There is no slot for an app's top-level destinations, and that is the design.** They are\n * facets of the app exactly as a record's tabs are facets of the record, so they go in a `Tabs`\n * bar under this header — the same shape at every level, with only the tab bar's contents\n * changing as you descend. Giving them a slot up here put two right-aligned clusters on top of\n * each other, destinations above actions, and made the quieter of the two the more important\n * one. An embedded app has one column and cannot afford a corner that dense.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport type { StyleWithVars } from \"../tokens.js\";\nimport { Heading, Text } from \"../typography.js\";\nimport { Breadcrumb, type Crumb } from \"./Breadcrumb.js\";\n\nconst STYLE_ID = \"nb-synapse-page-header\";\n// The clamp lives in a stylesheet rule rather than an inline style, following the same\n// pattern Table/Tabs/SegmentedControl use. Two reasons beyond consistency: `display:\n// -webkit-box` and `-webkit-line-clamp` are a matched pair that only works together, so they\n// belong in one place a caller cannot half-override with `style`; and the line count stays\n// parameterized through a custom property, which is how every other knob in this kit travels.\nconst RULES = `\n.nb-page-header__desc {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--nb-ph-desc-lines, 2);\n line-clamp: var(--nb-ph-desc-lines, 2);\n overflow: hidden;\n}\n`;\n\ninterface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** The trail. Omit on a top-level page, which has nothing above it to name. */\n crumbs?: Crumb[];\n title: ReactNode;\n /** Sits beside the title — typically a `Badge`. */\n status?: ReactNode;\n /** Sits at the far end of the title's row. Buttons, a menu. */\n actions?: ReactNode;\n description?: ReactNode;\n /** Lines the description is clamped to before ellipsis. `0` removes the clamp. */\n descriptionLines?: number;\n}\n\nexport function PageHeader({\n crumbs,\n title,\n status,\n actions,\n description,\n descriptionLines = 2,\n style,\n ...rest\n}: PageHeaderProps) {\n ensureStyle(STYLE_ID, RULES);\n const descVars: StyleWithVars =\n descriptionLines > 0 ? { \"--nb-ph-desc-lines\": String(descriptionLines) } : {};\n return (\n <header\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.5rem\", minWidth: 0, ...style }}\n {...rest}\n >\n {crumbs && crumbs.length > 0 ? <Breadcrumb crumbs={crumbs} /> : null}\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"1rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.6rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n }}\n >\n <Heading size=\"md\">{title}</Heading>\n {status}\n </div>\n {/* Rendered only when given. An empty actions box still occupies its row and pulls\n the title off centre, which reads as a control that failed to load. */}\n {actions ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"0.5rem\", flexShrink: 0 }}>\n {actions}\n </div>\n ) : null}\n </div>\n\n {description ? (\n <Text\n size=\"sm\"\n tone=\"muted\"\n className={descriptionLines > 0 ? \"nb-page-header__desc\" : undefined}\n // A measure, clamped or not. The clamp needs a width to resolve line boxes\n // against, and unclamped prose past ~72 characters a line is hard to track back\n // to the next line's start whatever its length.\n style={{ maxWidth: \"72ch\", ...descVars }}\n >\n {description}\n </Text>\n ) : null}\n </header>\n );\n}\n","/**\n * Pagination — chrome-less prev/next text links with a \"page X of Y\" counter.\n * 1-based `page`. Buttons disable at the ends.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { Inline } from \"../primitives.js\";\nimport { tokens } from \"../tokens.js\";\nimport { TextLink } from \"./Button.js\";\n\ninterface PaginationProps extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n /** Current page, 1-based. */\n page: number;\n /** Total number of pages. */\n pageCount: number;\n onChange: (page: number) => void;\n}\n\nexport function Pagination({ page, pageCount, onChange, style, ...rest }: PaginationProps) {\n const total = Math.max(1, pageCount);\n const atStart = page <= 1;\n const atEnd = page >= total;\n return (\n <Inline\n justify=\"between\"\n style={{\n fontFamily: tokens.fontSans,\n fontSize: tokens.textXsSize,\n color: tokens.fgMuted,\n letterSpacing: \"0.02em\",\n ...style,\n }}\n {...rest}\n >\n <span style={{ fontVariantNumeric: \"tabular-nums\" }}>\n Page {page} of {total}\n </span>\n <Inline gap=\"1rem\">\n <TextLink disabled={atStart} onClick={() => onChange(page - 1)}>\n ← Prev\n </TextLink>\n <TextLink disabled={atEnd} onClick={() => onChange(page + 1)}>\n Next →\n </TextLink>\n </Inline>\n </Inline>\n );\n}\n","/**\n * Prose — a token-styled container for rendered rich text. It applies the\n * NimbleBrain reading typography (ported from the Research app's markdown\n * element map) to whatever HTML it wraps, via a once-injected scoped\n * stylesheet — so it stays dependency-free.\n *\n * Pass pre-rendered nodes as `children`, or a trusted HTML string as `html`.\n * Bring your own markdown parser (`marked`, `react-markdown`, …) upstream; this\n * owns the *styling*, not the parsing — keeping the SDK free of a parser dep.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-prose\";\nconst RULES = `\n.nb-prose {\n font-family: ${tokens.fontSans};\n font-size: ${tokens.textBaseSize};\n line-height: 1.7;\n color: ${tokens.fg};\n}\n.nb-prose > :first-child { margin-top: 0; }\n.nb-prose > :last-child { margin-bottom: 0; }\n.nb-prose h1, .nb-prose h2 { font-family: ${tokens.fontHeading}; letter-spacing: -0.015em; color: ${tokens.fg}; }\n.nb-prose h1 { font-size: ${tokens.headingMdSize}; line-height: ${tokens.headingMdLine}; margin: 2rem 0 0.75rem; }\n.nb-prose h2 { font-size: ${tokens.headingSmSize}; line-height: ${tokens.headingSmLine}; margin: 1.75rem 0 0.5rem; }\n.nb-prose h3 { font-size: ${tokens.textBaseSize}; font-weight: ${tokens.weightSemibold}; margin: 1.5rem 0 0.35rem; color: ${tokens.fg}; }\n.nb-prose p { margin: 0 0 1rem; }\n.nb-prose ul, .nb-prose ol { margin: 0 0 1rem; padding-left: 1.25rem; }\n.nb-prose li { margin: 0.25rem 0; }\n.nb-prose a { color: ${tokens.accent}; text-decoration: underline; text-underline-offset: 2px; }\n.nb-prose blockquote { margin: 0 0 1rem; padding-left: 1rem; border-left: 2px solid ${tokens.accent}; color: ${tokens.fgMuted}; font-style: italic; }\n.nb-prose code { font-family: ${tokens.fontMono}; font-size: 0.88em; padding: 0.08rem 0.32rem; border-radius: ${tokens.radiusXs}; background: ${tokens.bgSubtle}; }\n.nb-prose pre { font-family: ${tokens.fontMono}; font-size: ${tokens.textSmSize}; line-height: 1.55; margin: 0 0 1.25rem; padding: 0.875rem 1rem; background: ${tokens.bgSubtle}; border-radius: ${tokens.radiusSm}; overflow-x: auto; }\n.nb-prose pre code { padding: 0; background: none; }\n.nb-prose hr { border: none; border-top: 1px solid ${tokens.border}; margin: 2rem 0; }\n.nb-prose strong { font-weight: ${tokens.weightSemibold}; }\n`;\n\ninterface ProseProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\" | \"dangerouslySetInnerHTML\"> {\n /** Trusted, pre-sanitized HTML string. */\n html?: string;\n children?: ReactNode;\n}\n\nexport function Prose({ html, children, className, ...rest }: ProseProps) {\n ensureStyle(STYLE_ID, RULES);\n const cls = `nb-prose ${className ?? \"\"}`.trim();\n if (html !== undefined) {\n // biome-ignore lint/security/noDangerouslySetInnerHtml: caller supplies trusted, pre-sanitized HTML by contract.\n return <div className={cls} dangerouslySetInnerHTML={{ __html: html }} {...rest} />;\n }\n return (\n <div className={cls} {...rest}>\n {children}\n </div>\n );\n}\n","/**\n * SearchField — a text input in two postures: `underline` (invisible at rest,\n * reveals an underline on focus — the Research editorial style) and `boxed`\n * (a bordered field). Focus styling lives in a once-injected stylesheet.\n */\n\nimport type { InputHTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-searchfield\";\nconst RULES = `\n.nb-search { font-family: var(--nb-search-font); color: var(--nb-search-fg); outline: none; }\n.nb-search::placeholder { color: var(--nb-search-placeholder); }\n.nb-search--underline {\n border: none;\n border-bottom: 1px solid transparent;\n background: transparent;\n padding: 0.3rem 0.1rem;\n transition: border-color 160ms ease;\n}\n.nb-search--underline:focus { border-bottom-color: var(--nb-search-accent); }\n.nb-search--boxed {\n border: 1px solid var(--nb-search-border);\n border-radius: var(--nb-search-radius);\n background: var(--nb-search-bg);\n padding: 0.4rem 0.6rem;\n transition: border-color 160ms ease, box-shadow 160ms ease;\n}\n.nb-search--boxed:focus {\n border-color: var(--nb-search-accent);\n box-shadow: 0 0 0 3px color-mix(in oklab, var(--nb-search-accent) 18%, transparent);\n}\n`;\n\ninterface SearchFieldProps extends InputHTMLAttributes<HTMLInputElement> {\n variant?: \"underline\" | \"boxed\";\n}\n\nexport function SearchField({\n variant = \"underline\",\n style,\n className,\n type = \"search\",\n ...rest\n}: SearchFieldProps) {\n ensureStyle(STYLE_ID, RULES);\n const fieldStyle: StyleWithVars = {\n \"--nb-search-font\": tokens.fontSans,\n \"--nb-search-fg\": tokens.fg,\n \"--nb-search-placeholder\": tokens.fgFaint,\n \"--nb-search-accent\": tokens.accent,\n \"--nb-search-border\": tokens.border,\n \"--nb-search-bg\": tokens.bgSubtle,\n \"--nb-search-radius\": tokens.radiusSm,\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n ...style,\n };\n return (\n <input\n type={type}\n className={`nb-search nb-search--${variant} ${className ?? \"\"}`.trim()}\n style={fieldStyle}\n {...rest}\n />\n );\n}\n","/**\n * SegmentedControl — the view-toggle pattern (Board/Table, All/Today/Week).\n * A small set of mutually-exclusive options; the active one gets a raised pill.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-segmented\";\nconst RULES = `\n.nb-seg {\n display: inline-flex;\n gap: 2px;\n padding: 2px;\n border-radius: var(--nb-seg-radius);\n background: var(--nb-seg-track);\n}\n.nb-seg__btn {\n border: none;\n background: transparent;\n color: var(--nb-seg-fg);\n font-family: var(--nb-seg-font);\n font-weight: var(--nb-seg-weight);\n padding: 0.25rem 0.7rem;\n border-radius: calc(var(--nb-seg-radius) - 2px);\n cursor: pointer;\n transition: color 130ms ease, background 130ms ease;\n white-space: nowrap;\n}\n.nb-seg__btn:hover:not([aria-pressed=\"true\"]) { color: var(--nb-seg-fg-strong); }\n.nb-seg__btn[aria-pressed=\"true\"] {\n background: var(--nb-seg-active-bg);\n color: var(--nb-seg-fg-strong);\n box-shadow: var(--nb-seg-active-shadow);\n}\n`;\n\ninterface Option<T extends string> {\n label: string;\n value: T;\n}\n\ninterface SegmentedControlProps<T extends string>\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n options: Option<T>[];\n value: T;\n onChange: (value: T) => void;\n}\n\nexport function SegmentedControl<T extends string>({\n options,\n value,\n onChange,\n style,\n className,\n ...rest\n}: SegmentedControlProps<T>) {\n ensureStyle(STYLE_ID, RULES);\n const trackStyle: StyleWithVars = {\n \"--nb-seg-radius\": tokens.radiusSm,\n \"--nb-seg-track\": tokens.bgSubtle,\n \"--nb-seg-fg\": tokens.fgMuted,\n \"--nb-seg-fg-strong\": tokens.fg,\n \"--nb-seg-font\": tokens.fontSans,\n \"--nb-seg-weight\": tokens.weightMedium,\n \"--nb-seg-active-bg\": tokens.bgRaised,\n \"--nb-seg-active-shadow\": tokens.shadowSm,\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n ...style,\n };\n return (\n // biome-ignore lint/a11y/useSemanticElements: role=\"group\" with aria-label is the correct grouping for a set of toggle buttons; <fieldset> would impose form semantics this control doesn't have.\n <div className={`nb-seg ${className ?? \"\"}`.trim()} role=\"group\" style={trackStyle} {...rest}>\n {options.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className=\"nb-seg__btn\"\n aria-pressed={opt.value === value}\n onClick={() => onChange(opt.value)}\n >\n {opt.label}\n </button>\n ))}\n </div>\n );\n}\n","/**\n * Spinner — a minimal rotating indicator for inline/button loading states.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-spinner\";\nconst RULES = `\n@keyframes nb-spin { to { transform: rotate(360deg); } }\n.nb-spinner { animation: nb-spin 0.7s linear infinite; }\n@media (prefers-reduced-motion: reduce) { .nb-spinner { animation-duration: 1.6s; } }\n`;\n\ninterface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {\n /** Diameter in px. Default 16. */\n size?: number;\n /** Arc color. Defaults to the accent token. */\n color?: string;\n}\n\nexport function Spinner({ size = 16, color, style, className, ...rest }: SpinnerProps) {\n ensureStyle(STYLE_ID, RULES);\n const spinnerStyle: StyleWithVars = {\n display: \"inline-block\",\n flexShrink: 0,\n width: size,\n height: size,\n borderRadius: \"50%\",\n border: `2px solid ${tokens.border}`,\n borderTopColor: color ?? tokens.accent,\n boxSizing: \"border-box\",\n ...style,\n };\n return (\n <span\n className={`nb-spinner ${className ?? \"\"}`.trim()}\n role=\"status\"\n aria-label=\"Loading\"\n style={spinnerStyle}\n {...rest}\n />\n );\n}\n","/**\n * StatusDot — a small colored dot for run/task status. The `working` state\n * gets a living ripple-pulse (ported from the Research app), gated on\n * `prefers-reduced-motion`. Same component in list rows and detail headers so\n * status reads identically everywhere.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nexport type Status = \"working\" | \"completed\" | \"failed\" | \"idle\";\n\nconst COLOR: Record<Status, string> = {\n working: tokens.accent,\n completed: tokens.success,\n failed: tokens.danger,\n idle: tokens.fgFaint,\n};\n\nconst STYLE_ID = \"nb-synapse-statusdot\";\nconst KEYFRAMES = `\n@keyframes nb-statusdot-pulse {\n 0% { box-shadow: 0 0 0 0 var(--nb-statusdot-ring); transform: scale(1); }\n 70% { box-shadow: 0 0 0 7px transparent; transform: scale(1.15); }\n 100% { box-shadow: 0 0 0 0 transparent; transform: scale(1); }\n}\n.nb-statusdot--working {\n animation: nb-statusdot-pulse 1.6s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n .nb-statusdot--working { animation: none; box-shadow: 0 0 0 2px var(--nb-statusdot-ring); }\n}\n`;\n\ninterface StatusDotProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"color\"> {\n status?: Status;\n /** Override the dot color (any CSS color / token). */\n color?: string;\n /** Diameter in px. Default 8. */\n size?: number;\n}\n\nexport function StatusDot({\n status = \"idle\",\n color,\n size = 8,\n style,\n className,\n ...rest\n}: StatusDotProps) {\n ensureStyle(STYLE_ID, KEYFRAMES);\n const dotColor = color ?? COLOR[status];\n const working = status === \"working\";\n const dotStyle: StyleWithVars = {\n display: \"inline-block\",\n flexShrink: 0,\n width: size,\n height: size,\n borderRadius: \"50%\",\n background: dotColor,\n // Ring color for the pulse keyframe — a faded copy of the dot color.\n \"--nb-statusdot-ring\": `color-mix(in oklab, ${dotColor} 45%, transparent)`,\n ...style,\n };\n return (\n <span\n className={working ? `nb-statusdot--working ${className ?? \"\"}`.trim() : className}\n style={dotStyle}\n {...rest}\n />\n );\n}\n","/**\n * Table — a token-styled data table with declarative columns. For the tabular\n * list surfaces (CRM contacts/deals) that simple `ListRow`s don't fit. Renders\n * a real `<table>` for semantics; header is sticky; rows hover-tint and can be\n * clickable. Sorting / selection / virtualization are deliberately out of v1 —\n * compose `Pagination` for paging.\n *\n * **A column that truncates must declare a `width`.** The default is CSS auto\n * table layout, which sizes every column to its content — so a long cell has no\n * width to be clipped against and instead widens the table past its container,\n * carrying the later columns off the pane. Declaring a width on ANY column\n * switches the table to fixed layout, which is what gives a truncating cell\n * something to overflow. This is the whole reason `width` exists on `Column`,\n * and it is easy to leave off because nothing fails loudly when you do: the\n * table renders, the text is there, and the columns you cannot see are simply\n * past the right edge.\n *\n * Horizontal scrolling is opt-in via `minWidth` — the width below which the\n * table scrolls rather than crushing. It is not the default because it costs\n * the sticky header: an `overflow-x` container captures the stickiness that\n * `position: sticky` resolves against the page's own scroller, and CSS gives no\n * way to scroll one axis while leaving the other visible. A table that fits does\n * not need it; a genuinely wide one is worth the trade, and the caller is the\n * one who knows which it is.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\ntype Align = \"left\" | \"right\" | \"center\";\n\nexport interface Column<T> {\n /** Stable column id. */\n key: string;\n header: ReactNode;\n /** Cell content for a row. */\n render: (row: T, index: number) => ReactNode;\n align?: Align;\n /**\n * Column width (`\"40%\"`, `220`, `\"12rem\"`). Declaring one on any column switches\n * the table to `table-layout: fixed`, and columns without a width then divide the\n * remainder equally. Required on any column whose cell truncates — see the note on\n * the module above.\n */\n width?: number | string;\n}\n\ninterface TableProps<T> extends Omit<HTMLAttributes<HTMLTableElement>, \"children\"> {\n data: T[];\n columns: Column<T>[];\n /** Stable key per row. */\n rowKey: (row: T, index: number) => string | number;\n onRowClick?: (row: T, index: number) => void;\n /** Shown when `data` is empty. */\n empty?: ReactNode;\n /**\n * The narrowest this table stays readable, and the switch that turns scrolling on.\n *\n * A fixed-layout table has no lower bound of its own, so seven columns in a 400px pane\n * become seven clipped headers and a badge overflowing its cell. Below this width the\n * table scrolls inside its own container instead of crushing — and setting the floor is\n * the only way to ask for that, because a scroller with no floor has no defined moment to\n * engage: under fixed layout the table always fits its container, and under auto layout it\n * engages at whatever width the content happens to reach.\n *\n * The cost is the sticky header. An `overflow-x` container captures the stickiness\n * `position: sticky` resolves against the page's own scroller, and CSS gives no way to\n * scroll one axis while leaving the other visible — so a table without a floor keeps its\n * sticky header, and one with a floor trades it.\n */\n minWidth?: number | string;\n}\n\nconst STYLE_ID = \"nb-synapse-table\";\nconst RULES = `\n.nb-table { width: 100%; border-collapse: collapse; font-family: var(--nb-table-font); }\n.nb-table th, .nb-table td {\n padding: 0.55rem 0.75rem;\n border-bottom: var(--nb-table-border);\n font-size: var(--nb-table-size); line-height: var(--nb-table-line);\n}\n.nb-table thead th {\n position: sticky; top: 0; z-index: 1;\n background: var(--nb-table-head-bg);\n color: var(--nb-table-muted);\n font-weight: var(--nb-table-semibold);\n font-size: var(--nb-table-xs); text-align: left;\n text-transform: uppercase; letter-spacing: 0.04em;\n}\n.nb-table tbody td { color: var(--nb-table-fg); }\n.nb-table tbody tr.nb-table__row--clickable { cursor: pointer; }\n.nb-table tbody tr.nb-table__row--clickable:hover { background: var(--nb-table-hover); }\n`;\n\nexport function Table<T>({\n data,\n columns,\n rowKey,\n onRowClick,\n empty,\n minWidth,\n style,\n className,\n ...rest\n}: TableProps<T>) {\n ensureStyle(STYLE_ID, RULES);\n\n const vars: Record<`--${string}`, string> = {\n \"--nb-table-font\": tokens.fontSans,\n \"--nb-table-fg\": tokens.fg,\n \"--nb-table-muted\": tokens.fgMuted,\n \"--nb-table-head-bg\": tokens.bg,\n \"--nb-table-hover\": tokens.bgSubtle,\n \"--nb-table-border\": `${tokens.borderWidth} solid ${tokens.border}`,\n \"--nb-table-size\": tokens.textSmSize,\n \"--nb-table-line\": tokens.textSmLine,\n \"--nb-table-xs\": tokens.textXsSize,\n \"--nb-table-semibold\": tokens.weightSemibold,\n };\n\n if (data.length === 0 && empty !== undefined) {\n return <>{empty}</>;\n }\n\n // Any declared width means the caller has an opinion about proportions, and auto layout\n // would ignore it in favour of content — so one width switches the whole table to fixed.\n // Derived rather than a separate prop: a `width` that silently did nothing is the trap\n // this replaces, not a second knob to remember alongside it.\n const fixed = columns.some((col) => col.width !== undefined);\n const tableStyle: StyleWithVars = {\n ...vars,\n ...(fixed ? { tableLayout: \"fixed\" as const } : {}),\n ...(minWidth !== undefined ? { minWidth } : {}),\n ...style,\n };\n\n const table = (\n <table className={`nb-table ${className ?? \"\"}`.trim()} style={tableStyle} {...rest}>\n <thead>\n <tr>\n {columns.map((col) => (\n <th\n key={col.key}\n scope=\"col\"\n style={{ width: col.width, textAlign: col.align ?? \"left\" }}\n >\n {col.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((row, i) => {\n const clickable = Boolean(onRowClick);\n return (\n <tr\n key={rowKey(row, i)}\n className={clickable ? \"nb-table__row--clickable\" : undefined}\n tabIndex={clickable ? 0 : undefined}\n onClick={clickable ? () => onRowClick?.(row, i) : undefined}\n onKeyDown={\n clickable\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRowClick?.(row, i);\n }\n }\n : undefined\n }\n >\n {columns.map((col) => (\n <td key={col.key} style={{ textAlign: col.align ?? \"left\" }}>\n {col.render(row, i)}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n\n if (minWidth === undefined) return table;\n // `tabIndex={0}` is not decoration. A scroll container that is neither focusable nor holds\n // a focusable descendant cannot be scrolled by keyboard at all (WCAG 2.1.1; axe's\n // `scrollable-region-focusable`), and a read-only table has no focusable descendants —\n // rows take a tabIndex only when `onRowClick` is set. Without this, every column past the\n // right edge is reachable with a pointer and by nothing else.\n //\n // `role=\"region\"` only when the caller named the table, because a region without an\n // accessible name is its own violation. The name is mirrored from the caller's own\n // `aria-label` rather than taken as a new prop: the label already reaches the table\n // through `rest`, and inventing a second way to say the same thing under review is how a\n // kit grows two spellings of one idea.\n const label = (rest as { \"aria-label\"?: string })[\"aria-label\"];\n // Role and name travel together or not at all — an `aria-label` on a roleless element names\n // nothing, and a `region` without a name is its own violation.\n const named = label ? ({ role: \"region\", \"aria-label\": label } as const) : {};\n return (\n <div\n // biome-ignore lint/a11y/noNoninteractiveTabindex: the two requirements point opposite ways here, and a scroll container is the case this rule does not model. axe's `scrollable-region-focusable` REQUIRES the tabIndex, because a container that is neither focusable nor holds a focusable descendant cannot be scrolled by keyboard at all (WCAG 2.1.1) — and a read-only table has no focusable descendants, since rows take a tabIndex only when `onRowClick` is set. Removing this makes every column past the right edge pointer-only.\n tabIndex={0}\n {...named}\n // `max-width: 100%` as well as `overflow-x`, because a flex or grid item's default\n // `min-width: auto` lets it grow to its content and the scroller never engages — the\n // container would widen instead, which is the failure this exists to stop.\n style={{ overflowX: \"auto\", maxWidth: \"100%\" }}\n >\n {table}\n </div>\n );\n}\n","/**\n * Tabs — facets of ONE entity, rendered as an underlined bar.\n *\n * **Why this exists beside `SegmentedControl`, which is also a row of exclusive choices.**\n * They are the same control mechanically and different jobs, and an app that uses one\n * component for both stacks two or three identical pill rows down the page — app\n * navigation, then entity facets, then a list filter, all wearing one costume. The reader\n * cannot tell which row changes what, and the screen reads as noise rather than hierarchy.\n * So the distinction is carried in the FORM: tabs are an underlined bar that belongs to the\n * thing above them, pills are a raised track that belongs to the thing below them.\n *\n * The rule that decides which to reach for:\n *\n * - **Tabs** change which FACET of one chosen entity is shown. They add no selection, so\n * they add no level — the entity is the same before and after.\n * - **SegmentedControl** narrows or reshapes a SET. A status filter over a list, a\n * board/table toggle.\n *\n * Full ARIA tab semantics (`role=\"tablist\"`, roving focus, arrow keys) because a tab bar is\n * a documented pattern a screen reader user already knows, and half of it — buttons with no\n * relationship declared between them — is worse than plain buttons, which at least do not\n * promise a structure that is not there.\n */\n\nimport { type HTMLAttributes, type KeyboardEvent, useRef } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-tabs\";\nconst RULES = `\n.nb-tabs {\n display: flex;\n align-items: stretch;\n gap: var(--nb-tabs-gap);\n border-bottom: var(--nb-tabs-rule);\n overflow-x: auto;\n scrollbar-width: none;\n}\n.nb-tabs::-webkit-scrollbar { display: none; }\n.nb-tabs__tab {\n border: none;\n background: transparent;\n color: var(--nb-tabs-fg);\n font-family: var(--nb-tabs-font);\n font-weight: var(--nb-tabs-weight);\n font-size: var(--nb-tabs-size);\n line-height: var(--nb-tabs-line);\n padding: 0.4rem 0.15rem 0.55rem;\n cursor: pointer;\n white-space: nowrap;\n position: relative;\n transition: color 130ms ease;\n}\n.nb-tabs__tab::after {\n content: \"\";\n position: absolute;\n /* bottom 0, not -1px. overflow-x auto makes the computed overflow-y auto as well, and\n clipping happens at the PADDING box - so a negative offset put 1px of the 2px accent\n outside it: the underline rendered half-height and left 1px of phantom overflow. */\n left: 0; right: 0; bottom: 0;\n height: 2px;\n border-radius: 2px 2px 0 0;\n background: transparent;\n transition: background 130ms ease;\n}\n.nb-tabs__tab:hover { color: var(--nb-tabs-fg-strong); }\n.nb-tabs__tab[aria-selected=\"true\"] {\n color: var(--nb-tabs-fg-strong);\n font-weight: var(--nb-tabs-weight-active);\n}\n.nb-tabs__tab[aria-selected=\"true\"]::after { background: var(--nb-tabs-accent); }\n.nb-tabs__tab:focus-visible {\n outline: 2px solid var(--nb-tabs-ring);\n outline-offset: -2px;\n border-radius: var(--nb-tabs-radius);\n}\n`;\n\ninterface Tab<T extends string> {\n label: string;\n value: T;\n /** A small trailing count. Rendered muted, and omitted entirely when undefined. */\n count?: number;\n}\n\ninterface TabsProps<T extends string> extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n tabs: Tab<T>[];\n value: T;\n onChange: (value: T) => void;\n /** Accessible name for the tab set — what these are facets OF. */\n label?: string;\n}\n\nexport function Tabs<T extends string>({\n tabs,\n value,\n onChange,\n label,\n style,\n className,\n onKeyDown: callerKeyDown,\n ...rest\n}: TabsProps<T>) {\n ensureStyle(STYLE_ID, RULES);\n const barRef = useRef<HTMLDivElement>(null);\n\n const barStyle: StyleWithVars = {\n \"--nb-tabs-gap\": \"1.25rem\",\n \"--nb-tabs-rule\": `${tokens.borderWidth} solid ${tokens.border}`,\n \"--nb-tabs-fg\": tokens.fgMuted,\n \"--nb-tabs-fg-strong\": tokens.fg,\n \"--nb-tabs-accent\": tokens.accent,\n \"--nb-tabs-ring\": tokens.ring,\n \"--nb-tabs-font\": tokens.fontSans,\n \"--nb-tabs-weight\": tokens.weightMedium,\n \"--nb-tabs-weight-active\": tokens.weightSemibold,\n \"--nb-tabs-size\": tokens.textSmSize,\n \"--nb-tabs-line\": tokens.textSmLine,\n \"--nb-tabs-radius\": tokens.radiusXs,\n ...style,\n };\n\n // Arrow keys move FOCUS, and selection follows it.\n //\n // Moving selection alone was the bug this replaces: the roving tabindex handed tabIndex=0\n // to the newly selected tab while the browser's focus stayed on the previous one, so the\n // focus ring sat on an unselected tab, a screen reader announced nothing (AT announces\n // focus, not aria-selected), and tabbing out and back landed somewhere else. The APG tabs\n // pattern specifies that arrows move focus with activation following it, and half of a\n // pattern a reader already knows is worse than none of it.\n //\n // Focused imperatively off the bar's own DOM rather than through an effect keyed on value:\n // the buttons are already rendered so the target exists now, and an effect would also\n // steal focus when a PARENT changed the value - a tab bar grabbing focus because something\n // else navigated.\n //\n // The caller's own handler runs FIRST and can suppress navigation with preventDefault().\n // `onKeyDown` is part of this component's public prop type, so accepting one and never\n // calling it is the same silent lie as letting it replace the contract outright - the two\n // failures a caller cannot tell apart from the type. Opting out is now something they do\n // on purpose, in one visible line.\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n callerKeyDown?.(e);\n if (e.defaultPrevented) return;\n const at = tabs.findIndex((t) => t.value === value);\n if (at < 0) return;\n let to: number;\n if (e.key === \"ArrowRight\") to = (at + 1) % tabs.length;\n else if (e.key === \"ArrowLeft\") to = (at - 1 + tabs.length) % tabs.length;\n else if (e.key === \"Home\") to = 0;\n else if (e.key === \"End\") to = tabs.length - 1;\n else return;\n e.preventDefault();\n // Arrows wrap, because a bar with a dead end makes the reader reverse direction to reach\n // the tab one step past the one they are on. Home and End are absolute and do not - so\n // they are the two keys that can land on the tab already held, and a change event for a\n // value that did not change is one a caller has to defend against (a refetch, a route\n // push, an analytics event). Focus still moves, because the key was still pressed.\n if (to !== at) onChange(tabs[to].value);\n barRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]')[to]?.focus();\n };\n\n return (\n <div\n // `rest` FIRST, so nothing a caller passes can overwrite what makes this a tablist.\n // `role` and `aria-label` are the contract the pattern rests on; a caller who could\n // replace them would have a bar announcing something it does not implement.\n {...rest}\n ref={barRef}\n role=\"tablist\"\n aria-label={label}\n className={`nb-tabs ${className ?? \"\"}`.trim()}\n style={barStyle}\n onKeyDown={onKeyDown}\n >\n {tabs.map((tab) => {\n const selected = tab.value === value;\n return (\n <button\n key={tab.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n // Roving tabindex: one stop for the whole bar, then arrows within it.\n tabIndex={selected ? 0 : -1}\n className=\"nb-tabs__tab\"\n onClick={() => onChange(tab.value)}\n >\n {tab.label}\n {tab.count !== undefined ? (\n <span style={{ marginLeft: \"0.35rem\", color: tokens.fgFaint }}>{tab.count}</span>\n ) : null}\n </button>\n );\n })}\n </div>\n );\n}\n","/**\n * AppFrame — the universal app chrome: a fixed header, a scrollable body, and\n * an optional fixed footer, filling the iframe pane. Every Synapse app uses it;\n * a body layout (SidebarLayout, ListView, …) goes inside `AppFrame.Body`.\n *\n * The shell fills the pane with `height: 100%`, which needs a definite-height\n * ancestor chain (`#root` → `body` → `html`) — something a bare app document\n * does not supply on its own. So AppFrame establishes that chain itself on\n * render via `injectBaseReset()`; without it the shell would collapse to\n * content height. Apps wanting the chain before first paint can also\n * `import \"@nimblebrain/synapse/ui/base\"` in their entry.\n *\n * The `contentWidth` knob is a personality lever: `reading` centers header,\n * body, and footer in a ~760px column (Conversations, Research), while `full`\n * uses the whole pane (CRM, dashboards). Header/body/footer share the same\n * column so the composition reads as one page.\n *\n * **There is deliberately no chrome slot here.** A Synapse app does not own its\n * window: the host spends the left edge on a rail and the right on chat, so an\n * app-level bar is a third chrome layer whose rule lands a few pixels off the\n * chat panel's — two near-parallel lines that read as a mistake and that no\n * amount of styling reconciles. Top-level destinations go in a tab bar under\n * the page header instead; see `PageLayout`.\n */\n\nimport {\n type CSSProperties,\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n} from \"react\";\nimport { injectBaseReset } from \"../internal/base-reset.js\";\nimport { tokens } from \"../tokens.js\";\n\ntype ContentWidth = \"reading\" | \"full\";\nconst READING_MAX = 760;\nconst ContentWidthCtx = createContext<ContentWidth>(\"full\");\n\nfunction columnStyle(width: ContentWidth): CSSProperties {\n return width === \"reading\" ? { maxWidth: READING_MAX, marginInline: \"auto\", width: \"100%\" } : {};\n}\n\ninterface AppFrameProps extends HTMLAttributes<HTMLDivElement> {\n contentWidth?: ContentWidth;\n children?: ReactNode;\n}\n\nfunction AppFrameRoot({ contentWidth = \"full\", style, children, ...rest }: AppFrameProps) {\n // The shell's `height: 100%` only resolves against a definite-height ancestor\n // chain; supply it (same render-time pattern as the components' `ensureStyle`).\n injectBaseReset();\n return (\n <ContentWidthCtx.Provider value={contentWidth}>\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n minHeight: 0,\n background: tokens.bg,\n color: tokens.fg,\n fontFamily: tokens.fontSans,\n ...style,\n }}\n {...rest}\n >\n {children}\n </div>\n </ContentWidthCtx.Provider>\n );\n}\n\nfunction Header({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const width = useContext(ContentWidthCtx);\n return (\n <header style={{ flexShrink: 0, padding: \"1.25rem 1.5rem 0.75rem\", ...style }} {...rest}>\n <div style={columnStyle(width)}>{children}</div>\n </header>\n );\n}\n\ninterface BodyProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Host a full-bleed body layout (SidebarLayout, BoardLayout) edge-to-edge:\n * no padding, no reading column, and the body itself doesn't scroll — the\n * layout's panes manage their own scroll. Leave off for plain content\n * (lists, forms), which get the padded reading/full column.\n */\n bleed?: boolean;\n}\n\nfunction Body({ bleed = false, style, children, ...rest }: BodyProps) {\n const width = useContext(ContentWidthCtx);\n if (bleed) {\n return (\n <div\n style={{\n flex: 1,\n minHeight: 0,\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n ...style,\n }}\n {...rest}\n >\n {children}\n </div>\n );\n }\n return (\n <div style={{ flex: 1, minHeight: 0, overflowY: \"auto\", ...style }} {...rest}>\n <div style={{ ...columnStyle(width), padding: \"0.75rem 1.5rem 1.5rem\" }}>{children}</div>\n </div>\n );\n}\n\nfunction Footer({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const width = useContext(ContentWidthCtx);\n return (\n <footer\n style={{\n flexShrink: 0,\n padding: \"0.75rem 1.5rem\",\n borderTop: `${tokens.borderWidth} solid ${tokens.border}`,\n ...style,\n }}\n {...rest}\n >\n <div style={columnStyle(width)}>{children}</div>\n </footer>\n );\n}\n\n/** `AppFrame` with `.Header`, `.Body`, `.Footer` slots. */\nexport const AppFrame = Object.assign(AppFrameRoot, { Header, Body, Footer });\n","/**\n * `useBreakpoint` — responsive hook keyed to an element's OWN width, not the\n * device viewport. Synapse apps render in an iframe pane whose width the host\n * controls (fullscreen, split, or a narrow sidebar), so layouts must react to\n * the space they're actually given.\n *\n * Attach the returned `ref` to the element whose width drives the decision.\n * Width is measured synchronously on mount (no first-frame flash) and kept live\n * via `ResizeObserver`. SSR/test-safe: without a DOM/`ResizeObserver` it simply\n * reports `isNarrow: false`.\n */\n\nimport { type RefObject, useLayoutEffect, useRef, useState } from \"react\";\n\nexport function useBreakpoint<T extends HTMLElement = HTMLDivElement>(\n breakpoint: number,\n): { ref: RefObject<T | null>; isNarrow: boolean } {\n const ref = useRef<T>(null);\n const [width, setWidth] = useState<number | null>(null);\n\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n // Synchronous initial measure — runs before paint, so the first painted\n // frame already reflects the real width. Border-box, matching the observer\n // below (so there's no jump on the first resize if the element has padding).\n setWidth(el.getBoundingClientRect().width);\n if (typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver((entries) => {\n const entry = entries[0];\n const w = entry?.borderBoxSize?.[0]?.inlineSize ?? entry?.contentRect.width;\n if (typeof w === \"number\") setWidth(w);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n return { ref, isNarrow: width !== null && width < breakpoint };\n}\n","/**\n * ListDetailLayout — a master list beside a detail pane (CRM contacts → record,\n * Research runs → report, conversations → thread). Responsive to the layout's\n * own width: side-by-side when wide; below `breakpoint` it shows one at a time —\n * the list, or the detail when something is `selected`, with a `Back`\n * affordance to return.\n *\n * `selected` is driven by the app's own selection state. Place\n * `<ListDetailLayout.Back />` at the top of `Detail`; it renders only on a\n * narrow pane and calls `onBack`.\n */\n\nimport { createContext, type HTMLAttributes, type ReactNode, useContext } from \"react\";\nimport { TextLink } from \"../components/Button.js\";\nimport { tokens } from \"../tokens.js\";\nimport { useBreakpoint } from \"./use-container-width.js\";\n\ninterface ListDetailState {\n collapsed: boolean;\n selected: boolean;\n listWidth: number | string;\n onBack?: () => void;\n}\n\nconst ListDetailCtx = createContext<ListDetailState | null>(null);\n\n/** Read the list/detail responsive state — for custom back affordances. */\nexport function useListDetail(): ListDetailState {\n const ctx = useContext(ListDetailCtx);\n if (!ctx) throw new Error(\"useListDetail must be used within <ListDetailLayout>\");\n return ctx;\n}\n\ninterface ListDetailLayoutProps extends HTMLAttributes<HTMLDivElement> {\n /** Is a detail open? Drives which pane shows on a narrow layout. */\n selected?: boolean;\n /** Called by `Back` (and custom triggers) to return to the list when narrow. */\n onBack?: () => void;\n /** Master list width when side-by-side. Default 320. */\n listWidth?: number | string;\n /** Collapse to one-at-a-time below this layout width (px). Default 720. */\n breakpoint?: number;\n children?: ReactNode;\n}\n\nfunction ListDetailLayoutRoot({\n selected = false,\n onBack,\n listWidth = 320,\n breakpoint = 720,\n style,\n children,\n ...rest\n}: ListDetailLayoutProps) {\n const { ref, isNarrow } = useBreakpoint<HTMLDivElement>(breakpoint);\n return (\n <ListDetailCtx.Provider value={{ collapsed: isNarrow, selected, listWidth, onBack }}>\n <div\n ref={ref}\n style={{ display: \"flex\", flexDirection: \"row\", height: \"100%\", minHeight: 0, ...style }}\n {...rest}\n >\n {children}\n </div>\n </ListDetailCtx.Provider>\n );\n}\n\nfunction List({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const { collapsed, selected, listWidth } = useListDetail();\n if (collapsed && selected) return null; // detail has the stage\n const border = `${tokens.borderWidth} solid ${tokens.border}`;\n return (\n <section\n style={{\n // Clip horizontally, scroll vertically. A too-wide child (e.g. an\n // auto-layout <table> that won't shrink below its content) would\n // otherwise spill out of this fixed-width rail and paint over the\n // detail pane. `minWidth: 0` lets the rail participate in flex\n // sizing without being forced wider by its content.\n overflow: \"hidden auto\",\n ...(collapsed\n ? { flex: 1, minWidth: 0 }\n : { width: listWidth, minWidth: 0, flexShrink: 0, borderRight: border }),\n ...style,\n }}\n {...rest}\n >\n {children}\n </section>\n );\n}\n\nfunction Detail({ style, children, ...rest }: HTMLAttributes<HTMLDivElement>) {\n const { collapsed, selected } = useListDetail();\n if (collapsed && !selected) return null; // list has the stage\n return (\n <div style={{ flex: 1, minWidth: 0, minHeight: 0, overflowY: \"auto\", ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\ninterface BackProps {\n children?: ReactNode;\n style?: React.CSSProperties;\n}\n\n/** \"← Back\" affordance — renders only on a narrow pane with a detail open. */\nfunction Back({ children, style }: BackProps) {\n const { collapsed, selected, onBack } = useListDetail();\n if (!collapsed || !selected) return null;\n return (\n <TextLink onClick={() => onBack?.()} style={{ marginBottom: \"0.5rem\", ...style }}>\n {children ?? \"← Back\"}\n </TextLink>\n );\n}\n\n/** `ListDetailLayout` with `.List`, `.Detail`, and `.Back` slots. */\nexport const ListDetailLayout = Object.assign(ListDetailLayoutRoot, { List, Detail, Back });\n","/**\n * PageLayout — one screen of a Synapse app, assembled in the one order that works.\n *\n * A header naming what you are looking at, a tab bar of that thing's facets, an optional\n * toolbar over the content, then the content. Every level of an app is this shape, and the\n * only thing descending changes is whose facets the tab bar holds: at the root the header\n * names the app and the tabs are its sections; a level down a trail appears above the header,\n * the header names the record, and the tabs are the record's own.\n *\n * **Why this is a component when the kit says thin compositions stay recipes.** That rule\n * measures mechanical complexity, and by it this is a recipe — it is a vertical stack in a\n * fixed order. But the reason to own it is not that assembling it is hard; it is that\n * assembling it DIFFERENTLY is a defect rather than a preference, and a recipe written down\n * in prose does not stop that. The failures are real ones, all found in a shipped app: two\n * tab bars stacked until the reader could not tell which row changed what; an app-level\n * chrome bar whose rule landed a few pixels off the host's chat panel; an unbounded\n * agent-authored description pushing the content below the fold. Each is an ordering or\n * composition mistake that a component makes unavailable and a convention only discourages.\n *\n * So the amended rule: a layout becomes a component when it is complex to build OR when\n * getting its arrangement wrong is a bug. This is the second kind.\n *\n * **What it deliberately does not have is a chrome slot.** A Synapse app does not own its\n * window — the host spends the left edge on a rail and the right on a chat panel — so an\n * app-level bar is a third chrome layer, and its rule cannot agree with the chat panel's.\n * Everything here is page content, which is the only thing on screen the app unambiguously\n * owns.\n *\n * Compose it inside `AppFrame.Body`; it manages its own vertical rhythm and nothing else.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport type { Crumb } from \"../components/Breadcrumb.js\";\nimport { PageHeader } from \"../components/PageHeader.js\";\n\ninterface PageLayoutProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** The trail. Omit at the top level, which has nothing above it to name. */\n crumbs?: Crumb[];\n title: ReactNode;\n /** Beside the title — typically a `Badge`. */\n status?: ReactNode;\n /** The far end of the title's row. */\n actions?: ReactNode;\n description?: ReactNode;\n /** Lines the description is clamped to. `0` removes the clamp. */\n descriptionLines?: number;\n /**\n * ONE tab bar, of the facets of whatever the title names. A `Tabs`.\n *\n * A slot rather than typed props because `Tabs` already has an API worth having, and\n * wrapping it here would mean maintaining a second copy of it that drifts. What the layout\n * owns is the bar's POSITION — under the header, above the content — which is the part\n * apps get wrong.\n */\n tabs?: ReactNode;\n /**\n * Controls that narrow the content below: a search field, a status filter, a view toggle.\n *\n * Distinct from `tabs` on purpose. A tab changes which facet of one entity is shown; a\n * toolbar reshapes a set within that facet. Rendering them as one row is how an app ends up\n * with two identical-looking control strips whose difference nobody can see.\n */\n toolbar?: ReactNode;\n children?: ReactNode;\n}\n\nexport function PageLayout({\n crumbs,\n title,\n status,\n actions,\n description,\n descriptionLines,\n tabs,\n toolbar,\n children,\n style,\n ...rest\n}: PageLayoutProps) {\n return (\n // A `<section>`, not a `<div>`, and it is the header below that makes it load-bearing.\n // `<header>` maps to the `banner` landmark UNLESS it descends from sectioning content, so\n // a page inside a page — a `PageLayout` in a pane of one — produced TWO banners, both\n // claiming to head the document. That is the same defect as the app-chrome bar this\n // layout exists without, one layer down and invisible on screen: it shows up only in the\n // landmark list a screen-reader user navigates by.\n //\n // Scoping it here rather than asking callers to wrap is the point. A consuming app hit\n // this, diagnosed it, and wrapped its own instance — correct, and not a thing every app\n // should have to rediscover. An embedded app is not the document anyway: the host owns\n // the real banner, and what this renders is a section of the host's page.\n <section\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"1.1rem\", minWidth: 0, ...style }}\n {...rest}\n >\n <PageHeader\n crumbs={crumbs}\n title={title}\n status={status}\n actions={actions}\n description={description}\n descriptionLines={descriptionLines}\n />\n {tabs}\n {/* The toolbar sits closer to the content it filters than to the tabs above it, so the\n gap is tightened here rather than inheriting the stack's rhythm. A control that looks\n equally attached to both is a control whose scope the reader has to guess. */}\n {toolbar ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n marginBottom: \"-0.35rem\",\n }}\n >\n {toolbar}\n </div>\n ) : null}\n {children}\n </section>\n );\n}\n","/**\n * SidebarLayout — the responsive two-column layout for inside an app pane: a\n * nav/list rail plus main content. It reacts to the layout's OWN width (not the\n * device), and below `breakpoint` collapses one of two ways:\n *\n * - `reflow` (default) — the rail moves to a horizontal strip on top and the\n * content goes full-width. Best for short navs (a settings page's sections).\n * - `drawer` — the rail becomes an off-canvas overlay opened by a `Trigger`.\n * Best for long lists (a document browser) where reflowing would be absurd.\n *\n * Place nav items as flat children of `Sidebar`; it controls direction\n * (column when expanded, row when reflowed). For `drawer`, place a\n * `<SidebarLayout.Trigger />` *inside* the layout (e.g. a toolbar in `Main`) —\n * in v1 the open-state context lives on `SidebarLayout`, so the trigger must be\n * within it, NOT in a sibling `AppFrame.Header`. Or read state via `useSidebar()`.\n * (Header placement would need a hoisted provider — a deliberate later refinement.)\n */\n\nimport {\n type ButtonHTMLAttributes,\n type CSSProperties,\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\nimport { useBreakpoint } from \"./use-container-width.js\";\n\ntype CollapseMode = \"reflow\" | \"drawer\";\ntype Side = \"left\" | \"right\";\n\ninterface SidebarState {\n collapsed: boolean;\n mode: CollapseMode;\n side: Side;\n width: number | string;\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nconst SidebarCtx = createContext<SidebarState | null>(null);\n\n/** Read the sidebar's responsive state — for custom triggers or nav re-orientation. */\nexport function useSidebar(): SidebarState {\n const ctx = useContext(SidebarCtx);\n if (!ctx) throw new Error(\"useSidebar must be used within <SidebarLayout>\");\n return ctx;\n}\n\nconst STYLE_ID = \"nb-synapse-sidebarlayout\";\n// Distinct class names from the Drawer component (which owns `.nb-drawer`).\nconst RULES = `\n.nb-sidebar-drawer { transition: transform 220ms cubic-bezier(0.2, 0, 0, 1); }\n.nb-sidebar-scrim { animation: nb-sidebar-fade 180ms ease; }\n@keyframes nb-sidebar-fade { from { opacity: 0; } to { opacity: 1; } }\n@media (prefers-reduced-motion: reduce) {\n .nb-sidebar-drawer { transition: none; }\n .nb-sidebar-scrim { animation: none; }\n}\n`;\n\ninterface SidebarLayoutProps extends HTMLAttributes<HTMLDivElement> {\n side?: Side;\n /** Expanded rail / drawer width. Default 240. */\n width?: number | string;\n /** Collapse below this pane width (px). Default 640. */\n breakpoint?: number;\n collapseMode?: CollapseMode;\n children?: ReactNode;\n}\n\nfunction SidebarLayoutRoot({\n side = \"left\",\n width = 240,\n breakpoint = 640,\n collapseMode = \"reflow\",\n style,\n children,\n ...rest\n}: SidebarLayoutProps) {\n const { ref, isNarrow } = useBreakpoint<HTMLDivElement>(breakpoint);\n const [open, setOpen] = useState(false);\n\n // Close the drawer on Escape.\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open]);\n\n // Collapsing back to expanded should drop any open drawer state.\n useEffect(() => {\n if (!isNarrow && open) setOpen(false);\n }, [isNarrow, open]);\n\n const reflowed = isNarrow && collapseMode === \"reflow\";\n const rootStyle: CSSProperties = {\n position: \"relative\",\n display: \"flex\",\n flexDirection: reflowed ? \"column\" : side === \"right\" ? \"row-reverse\" : \"row\",\n height: \"100%\",\n minHeight: 0,\n ...style,\n };\n\n return (\n <SidebarCtx.Provider\n value={{ collapsed: isNarrow, mode: collapseMode, side, width, open, setOpen }}\n >\n <div ref={ref} style={rootStyle} {...rest}>\n {children}\n </div>\n </SidebarCtx.Provider>\n );\n}\n\nfunction Sidebar({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const { collapsed, mode, side, width, open, setOpen } = useSidebar();\n ensureStyle(STYLE_ID, RULES);\n\n // Expanded: a fixed-width rail beside the content.\n if (!collapsed) {\n const border = `${tokens.borderWidth} solid ${tokens.border}`;\n return (\n <aside\n style={{\n width,\n flexShrink: 0,\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"0.125rem\",\n padding: \"0.5rem 0.5rem\",\n ...(side === \"right\" ? { borderLeft: border } : { borderRight: border }),\n ...style,\n }}\n {...rest}\n >\n {children}\n </aside>\n );\n }\n\n // Reflowed: a horizontal strip on top, content below.\n if (mode === \"reflow\") {\n return (\n <aside\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: \"0.25rem\",\n width: \"100%\",\n overflowX: \"auto\",\n padding: \"0.5rem 0.75rem\",\n borderBottom: `${tokens.borderWidth} solid ${tokens.border}`,\n ...style,\n }}\n {...rest}\n >\n {children}\n </aside>\n );\n }\n\n // Drawer: off-canvas overlay + scrim.\n const closed = side === \"right\" ? \"translateX(100%)\" : \"translateX(-100%)\";\n const drawerStyle: StyleWithVars = {\n position: \"absolute\",\n top: 0,\n bottom: 0,\n [side]: 0,\n width,\n maxWidth: \"85%\",\n overflowY: \"auto\",\n background: tokens.bgRaised,\n boxShadow: tokens.shadowLg,\n transform: open ? \"translateX(0)\" : closed,\n zIndex: 11,\n ...(side === \"right\"\n ? { borderLeft: `${tokens.borderWidth} solid ${tokens.border}` }\n : { borderRight: `${tokens.borderWidth} solid ${tokens.border}` }),\n ...style,\n };\n return (\n <>\n {open ? (\n <button\n type=\"button\"\n aria-label=\"Close sidebar\"\n className=\"nb-sidebar-scrim\"\n onClick={() => setOpen(false)}\n style={{\n position: \"absolute\",\n inset: 0,\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n background: \"rgba(0,0,0,0.32)\",\n zIndex: 10,\n }}\n />\n ) : null}\n {/* `inert` when closed removes the off-canvas rail from the tab order and\n the a11y tree (vs `aria-hidden`, which leaves focusables reachable). */}\n <aside className=\"nb-sidebar-drawer\" inert={!open} style={drawerStyle} {...rest}>\n {children}\n </aside>\n </>\n );\n}\n\nfunction Main({ style, children, ...rest }: HTMLAttributes<HTMLDivElement>) {\n return (\n <div style={{ flex: 1, minWidth: 0, minHeight: 0, overflowY: \"auto\", ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\ninterface TriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Override the default hamburger glyph. */\n children?: ReactNode;\n}\n\n/**\n * Hamburger that opens the drawer. Renders only when collapsed in `drawer`\n * mode, and only when it can see a `SidebarLayout` context — so it's safe to\n * place anywhere inside the layout subtree (it no-ops elsewhere). Note: in v1\n * the context lives on `SidebarLayout` itself, so the trigger must sit inside\n * it (e.g. a toolbar in `Main`), not in a sibling `AppFrame.Header`.\n */\nfunction Trigger({ children, style, onClick, ...rest }: TriggerProps) {\n const ctx = useContext(SidebarCtx);\n if (!ctx?.collapsed || ctx.mode !== \"drawer\") return null;\n const { open, setOpen } = ctx;\n return (\n <button\n type=\"button\"\n aria-label=\"Toggle sidebar\"\n aria-expanded={open}\n onClick={(e) => {\n setOpen(!open);\n onClick?.(e);\n }}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 32,\n height: 32,\n border: \"none\",\n background: \"transparent\",\n color: tokens.fg,\n cursor: \"pointer\",\n borderRadius: tokens.radiusSm,\n ...style,\n }}\n {...rest}\n >\n {children ?? (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <path\n d=\"M2 4.5h14M2 9h14M2 13.5h14\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n )}\n </button>\n );\n}\n\n/** `SidebarLayout` with `.Sidebar`, `.Main`, and `.Trigger` slots. */\nexport const SidebarLayout = Object.assign(SidebarLayoutRoot, { Sidebar, Main, Trigger });\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ui/tokens.ts","../../src/ui/components/Avatar.tsx","../../src/ui/components/Badge.tsx","../../src/ui/typography.tsx","../../src/ui/components/Button.tsx","../../src/ui/components/Breadcrumb.tsx","../../src/ui/components/Card.tsx","../../src/ui/internal/modal.ts","../../src/ui/components/ConfirmDialog.tsx","../../src/ui/components/Drawer.tsx","../../src/ui/primitives.tsx","../../src/ui/components/EmptyState.tsx","../../src/ui/components/ListRow.tsx","../../src/ui/components/PageHeader.tsx","../../src/ui/components/Pagination.tsx","../../src/ui/components/Prose.tsx","../../src/ui/components/SearchField.tsx","../../src/ui/components/SegmentedControl.tsx","../../src/ui/components/Spinner.tsx","../../src/ui/components/StatusDot.tsx","../../src/ui/components/Table.tsx","../../src/ui/components/Tabs.tsx","../../src/ui/layouts/AppFrame.tsx","../../src/ui/layouts/use-container-width.ts","../../src/ui/layouts/ListDetailLayout.tsx","../../src/ui/layouts/PageLayout.tsx","../../src/ui/layouts/SidebarLayout.tsx"],"names":["useState","useEffect","jsx","TONE","ensureStyle","Fragment","STYLE_ID","RULES","useRef","useId","jsxs","createContext","useMemo","useContext","injectBaseReset","Header","Body","Footer","useLayoutEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * The token contract for `@nimblebrain/synapse/ui`.\n *\n * Values are NOT brand hexes — they are `var(--token, fallback)` references to\n * the CSS custom properties the host injects into the app iframe (the MCP\n * ext-apps `hostContext.styles.variables`). Because styling resolves through\n * CSS variables, theme changes (including light↔dark) reflect automatically\n * with no React re-render: the host swaps the `:root` vars and every `var()`\n * re-resolves.\n *\n * The fallbacks are deliberately **unbranded** — system fonts, neutral grays, a\n * generic blue, and generic semantic hues for the status channels. NOT\n * NimbleBrain brand. Brand arrives by injection when the app runs inside the\n * NimbleBrain host; standalone/static renders get a sane\n * unbranded default. This keeps the library host-agnostic.\n * `__tests__/ui/tokens.test.ts` holds the line: every hex in these fallbacks\n * must be in the sanctioned set, same as `theme-defaults.ts`.\n *\n * Components import the static `tokens` object and style with CSS `var()`, so\n * theming (incl. light/dark) resolves in CSS with no re-render.\n */\n\nimport type { CSSProperties } from \"react\";\n\n/** Resolved design tokens as CSS `var()` references with neutral fallbacks. */\nexport const tokens = {\n // ── Surfaces ──\n bg: \"var(--color-background-primary, #ffffff)\",\n bgRaised: \"var(--color-background-secondary, #fafafa)\",\n bgSubtle: \"var(--color-background-tertiary, #f3f4f6)\",\n\n // ── Text ──\n fg: \"var(--color-text-primary, #111827)\",\n fgMuted: \"var(--color-text-secondary, #6b7280)\",\n fgFaint: \"var(--color-text-tertiary, #9ca3af)\",\n accent: \"var(--color-text-accent, #2563eb)\",\n accentFg: \"var(--nb-color-accent-foreground, #ffffff)\",\n\n // ── Border / ring ──\n border: \"var(--color-border-primary, #e5e7eb)\",\n borderStrong: \"var(--color-border-secondary, #d1d5db)\",\n ring: \"var(--color-ring-primary, #2563eb)\",\n\n // ── Status / brand semantics ──\n danger: \"var(--nb-color-danger, #dc2626)\",\n dangerFg: \"var(--nb-color-danger-foreground, #ffffff)\",\n success: \"var(--nb-color-success, #059669)\",\n warning: \"var(--nb-color-warning, #f59e0b)\",\n processing: \"var(--nb-color-processing, #7c3aed)\",\n processingLight: \"var(--nb-color-processing-light, #f3eeff)\",\n infoLight: \"var(--nb-color-info-light, #eef4ff)\",\n\n // ── Typography ──\n fontSans: \"var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)\",\n fontMono: \"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)\",\n fontHeading: \"var(--nb-font-heading, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)\",\n weightNormal: \"var(--font-weight-normal, 400)\",\n weightMedium: \"var(--font-weight-medium, 500)\",\n weightSemibold: \"var(--font-weight-semibold, 600)\",\n weightBold: \"var(--font-weight-bold, 700)\",\n\n // ── Type scale (size + line-height pairs) ──\n textXsSize: \"var(--font-text-xs-size, 0.75rem)\",\n textXsLine: \"var(--font-text-xs-line-height, 1rem)\",\n textSmSize: \"var(--font-text-sm-size, 0.875rem)\",\n textSmLine: \"var(--font-text-sm-line-height, 1.25rem)\",\n textBaseSize: \"var(--font-text-base-size, 1rem)\",\n textBaseLine: \"var(--font-text-base-line-height, 1.5rem)\",\n textLgSize: \"var(--font-text-lg-size, 1.125rem)\",\n textLgLine: \"var(--font-text-lg-line-height, 1.75rem)\",\n headingSmSize: \"var(--font-heading-sm-size, 1.25rem)\",\n headingSmLine: \"var(--font-heading-sm-line-height, 1.75rem)\",\n headingMdSize: \"var(--font-heading-md-size, 1.5rem)\",\n headingMdLine: \"var(--font-heading-md-line-height, 2rem)\",\n headingLgSize: \"var(--font-heading-lg-size, 2rem)\",\n headingLgLine: \"var(--font-heading-lg-line-height, 2.5rem)\",\n\n // ── Radius / border width ──\n radiusXs: \"var(--border-radius-xs, 0.25rem)\",\n radiusSm: \"var(--border-radius-sm, 0.5rem)\",\n radiusMd: \"var(--border-radius-md, 0.75rem)\",\n radiusLg: \"var(--border-radius-lg, 1rem)\",\n radiusXl: \"var(--border-radius-xl, 1.5rem)\",\n borderWidth: \"var(--border-width-regular, 1px)\",\n\n // ── Shadows ──\n shadowHairline: \"var(--shadow-hairline, 0 0 0 1px rgba(0,0,0,0.06))\",\n shadowSm: \"var(--shadow-sm, 0 1px 2px rgba(0,0,0,0.05))\",\n shadowMd: \"var(--shadow-md, 0 4px 6px -1px rgba(0,0,0,0.1))\",\n shadowLg: \"var(--shadow-lg, 0 10px 15px -3px rgba(0,0,0,0.1))\",\n} as const;\n\nexport type Tokens = typeof tokens;\n\n/**\n * A style object that also permits CSS custom properties (`--foo`). React's\n * `CSSProperties` rejects custom-property keys; components that set CSS vars\n * inline (for `:hover`/keyframe plumbing) type their style as this, then pass\n * it to `style` (it down-casts cleanly to `CSSProperties`).\n */\nexport type StyleWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/** Body text sizes. */\nexport type TextSize = \"xs\" | \"sm\" | \"base\" | \"lg\";\n/** Heading sizes. */\nexport type HeadingSize = \"sm\" | \"md\" | \"lg\";\n\nconst TEXT_SCALE: Record<TextSize, CSSProperties> = {\n xs: { fontSize: tokens.textXsSize, lineHeight: tokens.textXsLine },\n sm: { fontSize: tokens.textSmSize, lineHeight: tokens.textSmLine },\n base: { fontSize: tokens.textBaseSize, lineHeight: tokens.textBaseLine },\n lg: { fontSize: tokens.textLgSize, lineHeight: tokens.textLgLine },\n};\n\nconst HEADING_SCALE: Record<HeadingSize, CSSProperties> = {\n sm: { fontSize: tokens.headingSmSize, lineHeight: tokens.headingSmLine },\n md: { fontSize: tokens.headingMdSize, lineHeight: tokens.headingMdLine },\n lg: { fontSize: tokens.headingLgSize, lineHeight: tokens.headingLgLine },\n};\n\n/** `{ fontSize, lineHeight }` for a body-text level. */\nexport function textStyle(size: TextSize): CSSProperties {\n return TEXT_SCALE[size];\n}\n\n/** `{ fontSize, lineHeight }` for a heading level. */\nexport function headingStyle(size: HeadingSize): CSSProperties {\n return HEADING_SCALE[size];\n}\n","/**\n * Avatar — a circular identity chip. Renders an image when `src` is given,\n * otherwise initials derived from `name` on a subtle tinted background.\n */\n\nimport { type HTMLAttributes, useEffect, useState } from \"react\";\nimport { tokens } from \"../tokens.js\";\n\n/** Up to two initials from a name (\"Jordan Ratner\" → \"JR\", \"mat\" → \"M\"). */\nfunction initialsOf(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"?\";\n const first = parts[0] ?? \"\";\n if (parts.length === 1) return first.charAt(0).toUpperCase();\n const last = parts[parts.length - 1] ?? \"\";\n return (first.charAt(0) + last.charAt(0)).toUpperCase();\n}\n\ninterface AvatarProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** Name used for initials and the image alt text. */\n name: string;\n /** Optional image URL; falls back to initials when absent or on error. */\n src?: string;\n /** Diameter in px. Default 28. */\n size?: number;\n}\n\nexport function Avatar({ name, src, size = 28, style, ...rest }: AvatarProps) {\n // Fall back to initials if the image fails to load. Reset on `src` change.\n const [failed, setFailed] = useState(false);\n // biome-ignore lint/correctness/useExhaustiveDependencies: reset only when src changes\n useEffect(() => setFailed(false), [src]);\n const showImage = Boolean(src) && !failed;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n width: size,\n height: size,\n borderRadius: \"50%\",\n overflow: \"hidden\",\n background: tokens.bgSubtle,\n color: tokens.fgMuted,\n fontFamily: tokens.fontSans,\n fontSize: Math.round(size * 0.4),\n fontWeight: tokens.weightSemibold,\n userSelect: \"none\",\n ...style,\n }}\n {...rest}\n >\n {showImage ? (\n <img\n src={src}\n alt={name}\n width={size}\n height={size}\n onError={() => setFailed(true)}\n style={{ width: \"100%\", height: \"100%\", objectFit: \"cover\" }}\n />\n ) : (\n initialsOf(name)\n )}\n </span>\n );\n}\n","/**\n * Badge — a small pill for status and priority labels (e.g. MEDIUM/HIGH,\n * open/resolved). Soft tinted background with a same-hue label.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { tokens } from \"../tokens.js\";\n\nexport type BadgeTone = \"neutral\" | \"accent\" | \"success\" | \"warning\" | \"danger\" | \"processing\";\n\n/** `{ bg, fg }` per tone. Soft tinted background, same-hue label. The status\n * tones have no `*Light` token so their tint is derived from the fg color. */\nconst TONE: Record<BadgeTone, { bg: string; fg: string }> = {\n neutral: { bg: tokens.bgSubtle, fg: tokens.fgMuted },\n accent: { bg: tokens.infoLight, fg: tokens.accent },\n success: { bg: `color-mix(in oklab, ${tokens.success} 14%, transparent)`, fg: tokens.success },\n warning: { bg: `color-mix(in oklab, ${tokens.warning} 14%, transparent)`, fg: tokens.warning },\n danger: { bg: `color-mix(in oklab, ${tokens.danger} 14%, transparent)`, fg: tokens.danger },\n processing: { bg: tokens.processingLight, fg: tokens.processing },\n};\n\ninterface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n tone?: BadgeTone;\n children?: ReactNode;\n}\n\nexport function Badge({ tone = \"neutral\", style, children, ...rest }: BadgeProps) {\n const { bg, fg } = TONE[tone];\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"0.25rem\",\n padding: \"0.1rem 0.45rem\",\n borderRadius: tokens.radiusXs,\n background: bg,\n color: fg,\n fontFamily: tokens.fontSans,\n fontSize: tokens.textXsSize,\n lineHeight: tokens.textXsLine,\n fontWeight: tokens.weightSemibold,\n letterSpacing: \"0.02em\",\n textTransform: \"uppercase\",\n whiteSpace: \"nowrap\",\n ...style,\n }}\n {...rest}\n >\n {children}\n </span>\n );\n}\n","/**\n * Typography components bound to the type scale and the sans/heading font\n * slots. `Text` for body copy, `Heading` for display type (uses the heading\n * font — Hanken Grotesk in the NimbleBrain host, `system-ui` elsewhere).\n */\n\nimport type { CSSProperties, ElementType, HTMLAttributes, ReactNode } from \"react\";\nimport { type HeadingSize, headingStyle, type TextSize, textStyle, tokens } from \"./tokens.js\";\n\ntype Tone = \"default\" | \"muted\" | \"faint\" | \"accent\" | \"danger\" | \"success\";\ntype Weight = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\n\nconst TONE: Record<Tone, string> = {\n default: tokens.fg,\n muted: tokens.fgMuted,\n faint: tokens.fgFaint,\n accent: tokens.accent,\n danger: tokens.danger,\n success: tokens.success,\n};\n\nconst WEIGHT: Record<Weight, string> = {\n normal: tokens.weightNormal,\n medium: tokens.weightMedium,\n semibold: tokens.weightSemibold,\n bold: tokens.weightBold,\n};\n\ninterface TextProps extends Omit<HTMLAttributes<HTMLElement>, \"color\"> {\n size?: TextSize;\n weight?: Weight;\n tone?: Tone;\n mono?: boolean;\n /**\n * Single-line ellipsis truncation.\n *\n * Sets `display: block` alongside the ellipsis rules, and that is load-bearing rather\n * than incidental: `overflow` and `text-overflow` do not apply to a non-replaced INLINE\n * box, so on the default `<span>` the only declaration that survived was\n * `white-space: nowrap` — and the prop did the exact opposite of its name, making text\n * unwrappable instead of clipping it. Inside an auto-layout `<table>` that widened the\n * column to the full string and pushed every later column off the pane.\n *\n * `min-width: 0` comes with it so the box can actually shrink as a flex item; without it\n * a truncating `Text` inside `Inline`/`Stack` refuses to go below its content width and\n * pushes its container instead, which is the same bug one layer out.\n *\n * A truncating cell in a `Table` also needs its column to declare a `width` — see\n * `Column.width`. Auto table layout sizes to content, so the ellipsis has nothing to\n * clip against until some column is pinned.\n */\n truncate?: boolean;\n as?: ElementType;\n children?: ReactNode;\n}\n\n/** Body text. Defaults to base size, normal weight, primary tone, sans font. */\nexport function Text({\n size = \"base\",\n weight = \"normal\",\n tone = \"default\",\n mono = false,\n truncate = false,\n as: As = \"span\",\n style,\n children,\n ...rest\n}: TextProps) {\n const truncation: CSSProperties = truncate\n ? {\n display: \"block\",\n minWidth: 0,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }\n : {};\n return (\n <As\n style={{\n margin: 0,\n fontFamily: mono ? tokens.fontMono : tokens.fontSans,\n fontWeight: WEIGHT[weight],\n color: TONE[tone],\n ...textStyle(size),\n ...truncation,\n ...style,\n }}\n {...rest}\n >\n {children}\n </As>\n );\n}\n\ninterface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, \"color\"> {\n size?: HeadingSize;\n weight?: Weight;\n tone?: Tone;\n as?: ElementType;\n children?: ReactNode;\n}\n\n/** Display heading using the heading font slot. Defaults to md, semibold. */\nexport function Heading({\n size = \"md\",\n weight = \"semibold\",\n tone = \"default\",\n as: As = \"h2\",\n style,\n children,\n ...rest\n}: HeadingProps) {\n return (\n <As\n style={{\n margin: 0,\n fontFamily: tokens.fontHeading,\n fontWeight: WEIGHT[weight],\n color: TONE[tone],\n letterSpacing: \"-0.015em\",\n ...headingStyle(size),\n ...style,\n }}\n {...rest}\n >\n {children}\n </As>\n );\n}\n","/**\n * Button and TextLink. Pseudo-states (`:hover`/`:active`/`:disabled`) live in a\n * once-injected stylesheet that reads token-driven CSS custom properties set\n * inline — so the base values stay token-driven while hover still works.\n */\n\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-button\";\nconst RULES = `\n.nb-btn {\n --nb-btn-bg: transparent;\n --nb-btn-bg-hover: transparent;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.4rem;\n border: var(--nb-btn-border, none);\n border-radius: var(--nb-btn-radius);\n background: var(--nb-btn-bg);\n color: var(--nb-btn-fg);\n font-family: var(--nb-btn-font);\n font-weight: var(--nb-btn-weight);\n cursor: pointer;\n transition: background 130ms ease, color 130ms ease, opacity 130ms ease;\n white-space: nowrap;\n}\n.nb-btn:hover { background: var(--nb-btn-bg-hover); }\n.nb-btn:active { transform: translateY(0.5px); }\n.nb-btn:disabled { opacity: 0.5; cursor: default; }\n.nb-btn:disabled:hover { background: var(--nb-btn-bg); }\n.nb-textlink {\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n font-family: var(--nb-tl-font);\n color: var(--nb-tl-fg);\n transition: color 130ms ease, opacity 130ms ease;\n}\n.nb-textlink:hover { color: var(--nb-tl-fg-hover); }\n.nb-textlink:disabled { opacity: 0.45; cursor: default; }\n`;\n\n/**\n * `danger` is for the verb that destroys something — Delete, Remove, Forget. It is\n * filled like `primary`, so it is never the quiet option beside one, and red so the\n * difference reads before the label does.\n */\ntype Variant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\ntype Size = \"sm\" | \"md\";\n\nconst SIZE_PAD: Record<Size, string> = {\n sm: \"0.3rem 0.6rem\",\n md: \"0.45rem 0.85rem\",\n};\n\ninterface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: Variant;\n size?: Size;\n children?: ReactNode;\n}\n\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n style,\n className,\n children,\n ...rest\n}: ButtonProps) {\n ensureStyle(STYLE_ID, RULES);\n const vars: Record<`--${string}`, string> = {\n \"--nb-btn-radius\": tokens.radiusSm,\n \"--nb-btn-font\": tokens.fontSans,\n \"--nb-btn-weight\": tokens.weightMedium,\n };\n if (variant === \"primary\") {\n vars[\"--nb-btn-bg\"] = tokens.accent;\n vars[\"--nb-btn-bg-hover\"] = `color-mix(in oklab, ${tokens.accent} 88%, black)`;\n vars[\"--nb-btn-fg\"] = tokens.accentFg;\n } else if (variant === \"danger\") {\n vars[\"--nb-btn-bg\"] = tokens.danger;\n vars[\"--nb-btn-bg-hover\"] = `color-mix(in oklab, ${tokens.danger} 88%, black)`;\n vars[\"--nb-btn-fg\"] = tokens.dangerFg;\n } else if (variant === \"secondary\") {\n vars[\"--nb-btn-bg\"] = tokens.bgSubtle;\n vars[\"--nb-btn-bg-hover\"] = tokens.bgRaised;\n vars[\"--nb-btn-fg\"] = tokens.fg;\n vars[\"--nb-btn-border\"] = `${tokens.borderWidth} solid ${tokens.border}`;\n } else {\n vars[\"--nb-btn-bg\"] = \"transparent\";\n vars[\"--nb-btn-bg-hover\"] = tokens.bgSubtle;\n vars[\"--nb-btn-fg\"] = tokens.fg;\n }\n const btnStyle: StyleWithVars = {\n ...vars,\n padding: SIZE_PAD[size],\n fontSize: size === \"sm\" ? tokens.textSmSize : tokens.textBaseSize,\n lineHeight: size === \"sm\" ? tokens.textSmLine : tokens.textBaseLine,\n ...style,\n };\n return (\n <button type=\"button\" className={`nb-btn ${className ?? \"\"}`.trim()} style={btnStyle} {...rest}>\n {children}\n </button>\n );\n}\n\ninterface TextLinkProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Resting tone. Hover always moves toward `accent` (or `danger`). */\n tone?: \"muted\" | \"default\" | \"danger\";\n children?: ReactNode;\n}\n\n/** A chrome-less text button — for back / delete / retry affordances. */\nexport function TextLink({ tone = \"muted\", style, className, children, ...rest }: TextLinkProps) {\n ensureStyle(STYLE_ID, RULES);\n const resting =\n tone === \"danger\" ? tokens.danger : tone === \"default\" ? tokens.fg : tokens.fgMuted;\n const hover = tone === \"danger\" ? tokens.danger : tokens.accent;\n const linkStyle: StyleWithVars = {\n \"--nb-tl-font\": tokens.fontSans,\n \"--nb-tl-fg\": resting,\n \"--nb-tl-fg-hover\": hover,\n fontSize: tokens.textXsSize,\n lineHeight: tokens.textXsLine,\n letterSpacing: \"0.02em\",\n ...style,\n };\n return (\n <button\n type=\"button\"\n className={`nb-textlink ${className ?? \"\"}`.trim()}\n style={linkStyle}\n {...rest}\n >\n {children}\n </button>\n );\n}\n","/**\n * Breadcrumb — the trail back, and where you are.\n *\n * A hierarchy deeper than two levels cannot be navigated by a back button: \"up one\" and\n * \"up two\" need separate controls, and an app that grows a second one ends up rendering\n * both adjacent, differently labelled, with only one correct at any depth. A trail has no\n * such limit — every level is named, so every jump is the same gesture — and it answers\n * a question a back button never does, which is where the reader currently is.\n *\n * The last crumb renders as text, never as a disabled control. A control that looks\n * clickable and does nothing is worse than no control, and the reader is already there.\n *\n * Steps are BUTTONS, not anchors, and that is deliberate: a Synapse app lives in an iframe\n * with no address of its own, so a crumb changes app state rather than navigating to a URL.\n * There is no href to put on an anchor, and a `<span>` with a click handler is reachable by\n * neither keyboard nor screen reader.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { Fragment } from \"react\";\nimport { tokens } from \"../tokens.js\";\nimport { Text } from \"../typography.js\";\nimport { TextLink } from \"./Button.js\";\n\nexport interface Crumb {\n label: string;\n /** Omit on the current step. A crumb with no handler renders as plain text. */\n onClick?: () => void;\n}\n\ninterface BreadcrumbProps extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n crumbs: Crumb[];\n /** The glyph between steps. */\n separator?: string;\n}\n\nexport function Breadcrumb({ crumbs, separator = \"›\", style, ...rest }: BreadcrumbProps) {\n return (\n <nav\n aria-label=\"Breadcrumb\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.4rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n ...style,\n }}\n {...rest}\n >\n {crumbs.map((crumb, i) => {\n const last = i === crumbs.length - 1;\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: a crumb's POSITION is its identity — \"the second level\" is what the step means, and two levels can legitimately carry the same label. There is no id to key on, and a trail that changed shape SHOULD remount rather than reconcile a step into a different depth.\n <Fragment key={`${crumb.label}:${i}`}>\n {last || !crumb.onClick ? (\n <Text\n size=\"xs\"\n tone={last ? \"muted\" : \"default\"}\n aria-current={last ? \"page\" : undefined}\n >\n {crumb.label}\n </Text>\n ) : (\n <TextLink onClick={crumb.onClick} style={{ fontSize: tokens.textXsSize }}>\n {crumb.label}\n </TextLink>\n )}\n {last ? null : (\n <Text size=\"xs\" tone=\"faint\" aria-hidden=\"true\">\n {separator}\n </Text>\n )}\n </Fragment>\n );\n })}\n </nav>\n );\n}\n","/**\n * Card — a raised surface with a hairline border. The default container for\n * grouped content (deal cards, task cards, panels). `interactive` adds a hover\n * lift via a once-injected stylesheet (no per-card handlers).\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-card\";\nconst RULES = `\n.nb-card--interactive {\n cursor: pointer;\n transition: box-shadow 140ms ease, border-color 140ms ease;\n}\n.nb-card--interactive:hover {\n box-shadow: var(--nb-card-shadow-hover);\n border-color: var(--nb-card-border-hover);\n}\n`;\n\ninterface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Inner padding (CSS length or px number). Default `0.875rem`. */\n padding?: number | string;\n /** Lift on hover — for clickable cards. */\n interactive?: boolean;\n children?: ReactNode;\n}\n\nexport function Card({\n padding = \"0.875rem\",\n interactive = false,\n style,\n className,\n children,\n ...rest\n}: CardProps) {\n if (interactive) ensureStyle(STYLE_ID, RULES);\n const cardStyle: StyleWithVars = {\n background: tokens.bgRaised,\n border: `${tokens.borderWidth} solid ${tokens.border}`,\n borderRadius: tokens.radiusMd,\n padding,\n boxShadow: tokens.shadowSm,\n \"--nb-card-shadow-hover\": tokens.shadowMd,\n \"--nb-card-border-hover\": tokens.borderStrong,\n ...style,\n };\n return (\n <div\n className={interactive ? `nb-card--interactive ${className ?? \"\"}`.trim() : className}\n style={cardStyle}\n {...rest}\n >\n {children}\n </div>\n );\n}\n","/**\n * What `HTMLDialogElement.showModal()` gives for free, hand-rolled for the overlays\n * in this kit (`Drawer`, `ConfirmDialog`).\n *\n * The platform mounts every app in a sandboxed iframe that withholds `allow-modals`,\n * so `showModal()` throws there and white-screens the app; a native `<dialog>` is\n * unusable in the one environment these apps run in. Each overlay is a plain\n * positioned `<div>` instead, and this hook supplies the modal behaviour: focus\n * moved into the panel on open and restored on close, background scroll locked,\n * Tab/Shift+Tab contained while focus is inside the panel, and Escape.\n *\n * Overlays nest — a confirmation raised from inside a drawer is the ordinary case —\n * so the open ones form a stack, and only the innermost answers Escape and Tab. Every\n * overlay listens for Escape on `window`, so without the stack one keypress would\n * close all of them; and a nested panel renders inside its parent's DOM, so its Tab\n * keydown bubbles to the parent's trap, which would otherwise compute a boundary\n * that contains both.\n *\n * Scope: this contains Tab while focus is *inside* the panel — the modal case. It is\n * NOT the full native `inert`: it doesn't recover focus that drops to `<body>` when a\n * focused child unmounts (that fires focusout, not focusin), nor fence off portal'd\n * overlays a consumer opens outside the panel. A document-scoped focus backstop would\n * do neither reliably and would yank focus out of legitimate nested overlays — so\n * full containment is a FocusScope-style owner stack, deferred to #43.\n */\n\nimport { type RefObject, useEffect, useRef } from \"react\";\n\n// A control inside a *closed* <details> (other than its own <summary>) is not\n// reachable, even though its tabIndex is 0 — the collapse is a UA `display:none`\n// on the disclosure content. It's structural (the `open` attribute + DOM\n// position), so it's detectable without layout and belongs in the filter below,\n// alongside `[hidden]` (also a UA `display:none` rule).\nfunction inClosedDetails(el: HTMLElement): boolean {\n const details = el.closest(\"details:not([open])\");\n if (!details) return false;\n const summary = details.querySelector(\"summary\");\n return !summary || !summary.contains(el);\n}\n\n// Tabbable elements inside the panel, in DOM order — the focus-trap boundary.\n// A broad candidate query filtered by a positive predicate, in place of a\n// `:not(...)` denylist that had to enumerate every non-tabbable case per clause.\n// The filter is the set of non-tabbable cases detectable *without layout*:\n// `tabIndex >= 0` rejects any negative tabindex, `:disabled` inherits through\n// `<fieldset disabled>`, `[hidden]` and closed-<details> collapse are tested on\n// the element and its ancestors. CSS-hidden focusables (`display:none` /\n// `visibility:hidden` set in a stylesheet) need layout to detect, so they're NOT\n// filtered (worst case: one Tab exits).\n//\n// CANDIDATES is an allowlist of mainstream focusables, not `*`: a bare `<a>` (no\n// href) reports tabIndex 0 but isn't focusable, so `*` would admit a phantom\n// boundary — `a[href]` is load-bearing. It is deliberately not exhaustive:\n// media/embeds (`<audio controls>`, `<iframe>`) and `[contenteditable]` are\n// omitted until a consumer needs one, to keep the set honest.\nconst CANDIDATES = \"a[href], button, input, select, textarea, summary, [tabindex]\";\nfunction tabbables(panel: HTMLElement): HTMLElement[] {\n return Array.from(panel.querySelectorAll<HTMLElement>(CANDIDATES)).filter(\n (el) =>\n el.tabIndex >= 0 &&\n !el.matches(\":disabled\") &&\n !el.closest(\"[hidden]\") &&\n !inClosedDetails(el) &&\n (el as HTMLInputElement).type !== \"hidden\",\n );\n}\n\n// The open overlays, in the order they opened. Module-level because the questions it\n// answers — \"am I the one on top?\", \"am I the last one open?\" — span every overlay on\n// the page, not one component tree.\ninterface OpenOverlay {\n panel: HTMLElement | null;\n /** Where focus goes when this overlay closes. */\n restoreTo: HTMLElement | null;\n}\nconst openOverlays: OpenOverlay[] = [];\n// The body's overflow from before the first overlay opened. Page-level state is\n// owned by the stack, not by each overlay: the page is locked while any overlay is\n// open, whichever order they opened and closed in.\nlet lockedOverflow = \"\";\n// Escapes an overlay has already acted on, so one keypress closes one overlay.\n// See the window listener for why this is recorded rather than inferred.\nconst handledEscapes = new WeakSet<Event>();\n\n// Innermost means: no open overlay sits inside this one's panel, and none that is\n// not its ancestor opened after it. DOM nesting decides first because open order\n// cannot: when a drawer and the confirmation inside it mount in the same commit,\n// React runs the child's effect before the parent's, so the drawer registers\n// second. Open order decides between overlays that do not nest.\nfunction isInnermost(self: OpenOverlay): boolean {\n const selfAt = openOverlays.indexOf(self);\n return openOverlays.every((other, at) => {\n if (other === self || !other.panel || !self.panel) return true;\n if (self.panel.contains(other.panel)) return false;\n if (other.panel.contains(self.panel)) return true;\n return at < selfAt;\n });\n}\n\ninterface ModalOptions {\n /** Called on Escape while this overlay is the innermost one open. */\n onEscape: () => void;\n /**\n * Where focus lands on open. Defaults to the panel itself. Read once, when the\n * overlay opens, so it may return an element rendered in the same commit.\n */\n initialFocus?: () => HTMLElement | null | undefined;\n}\n\nexport function useModal(\n open: boolean,\n panelRef: RefObject<HTMLElement | null>,\n { onEscape, initialFocus }: ModalOptions,\n): void {\n // Read through refs so a new callback identity each render neither re-subscribes\n // nor moves this overlay's place in the stack.\n const escapeRef = useRef(onEscape);\n escapeRef.current = onEscape;\n const initialFocusRef = useRef(initialFocus);\n initialFocusRef.current = initialFocus;\n\n useEffect(() => {\n if (!open) return;\n const panel = panelRef.current;\n const previouslyFocused = document.activeElement as HTMLElement | null;\n const entry: OpenOverlay = { panel, restoreTo: previouslyFocused };\n // An overlay nested in this one that is already open opened in the same commit —\n // React runs the child's effect first — so it recorded this overlay's opener as\n // its own, and this one would record the nested overlay's control. Swap: this\n // overlay returns focus to the opener, the nested one returns it to this panel.\n //\n // The swap is with the overlay directly below this one, which is the *outermost*\n // of the ones nested inside it: the effects ran deepest-first, so each has already\n // swapped with the one below it, and only the outermost still holds this overlay's\n // opener. That same deepest-first order puts it last in the stack, so it is the\n // last match, not the first.\n const nested = openOverlays.filter((o) => panel && o.panel && panel.contains(o.panel)).at(-1);\n if (nested) {\n entry.restoreTo = nested.restoreTo;\n nested.restoreTo = panel;\n }\n const { body } = document;\n if (openOverlays.length === 0) lockedOverflow = body.style.overflow;\n openOverlays.push(entry);\n const innermost = () => isInnermost(entry);\n\n // Focus already inside the panel is left where it is: it is the nested overlay's\n // initial focus, from the same commit.\n if (!(panel && previouslyFocused && panel.contains(previouslyFocused))) {\n (initialFocusRef.current?.() ?? panel)?.focus();\n }\n body.style.overflow = \"hidden\";\n\n // Escape on `window` rather than the panel, so it works wherever focus sits —\n // including on <body> after a focused control inside the panel unmounted.\n //\n // One Escape closes one overlay. In a browser the nested overlay's listener\n // can close it and let React commit before this listener runs for the same\n // keypress, which would leave this overlay innermost and close it too — so\n // the overlay that acts records the event and the rest stand down.\n //\n // Recorded on the event rather than read off `defaultPrevented`, which\n // answers a different question: \"did anyone cancel this?\" rather than \"did\n // an overlay act on it?\". The SDK's own key forwarder cancels every Escape\n // it forwards, on `document`, which a bubbling keydown reaches before\n // `window` — so an overlay reading `defaultPrevented` finds it already true\n // for an Escape nothing has handled, and no overlay ever closes. Only the\n // overlays can answer the question the guard is asking.\n const onWindowKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || handledEscapes.has(e) || !innermost()) return;\n handledEscapes.add(e);\n e.preventDefault();\n escapeRef.current();\n };\n window.addEventListener(\"keydown\", onWindowKeyDown);\n\n const onPanelKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || !panel || !innermost()) return;\n const focusables = tabbables(panel);\n if (focusables.length === 0) {\n // Nothing tabbable inside — preventDefault keeps focus on the panel it's\n // already on (the open step focused it), so Tab can't leave.\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (e.shiftKey && (active === first || active === panel)) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n };\n panel?.addEventListener(\"keydown\", onPanelKeyDown);\n\n return () => {\n window.removeEventListener(\"keydown\", onWindowKeyDown);\n panel?.removeEventListener(\"keydown\", onPanelKeyDown);\n const at = openOverlays.indexOf(entry);\n if (at !== -1) openOverlays.splice(at, 1);\n if (openOverlays.length === 0) body.style.overflow = lockedOverflow;\n entry.restoreTo?.focus?.();\n };\n }, [open, panelRef]);\n}\n","/**\n * ConfirmDialog — ask before doing something, and say what \"it\" is.\n *\n * A destructive action that cannot say what it will take with it is an action nobody\n * consented to, which is why `children` is arbitrary: the caller renders what the\n * action does, and any per-action control it needs, in the body. The dialog returns\n * approve or deny and nothing else. A choice inside the body — a checkbox, a mode —\n * belongs to the caller: it owns the state, renders the control in `children`, and\n * reads it in its own `onConfirm`. A primitive that returned a payload would be a\n * form, and it would grow one field per caller.\n *\n * **The action's outcome is reported here.** `onConfirm` may return a promise. While\n * it runs, both buttons are disabled, Confirm shows `pendingLabel`, and no dismissal\n * path — Escape, the scrim, Cancel — closes the dialog, because closing over a running\n * action would leave its outcome with nowhere to be reported. If it resolves, the\n * dialog asks to close (`onOpenChange(false)`). If it throws, the dialog stays open\n * with the error's message shown above the buttons, so the failure lands where the\n * user can retry or cancel rather than behind a dialog that has already gone.\n *\n * **Where focus lands.** On a `destructive` dialog, focus opens on Cancel, so a\n * reflexive Enter declines rather than deletes. Otherwise it opens on Confirm, the\n * decision the dialog is asking about.\n *\n * A plain positioned `<div>`, not a native `<dialog>` (the app iframe sandbox cannot\n * open one — see `internal/modal.ts`). It renders in place and `position: fixed`\n * lifts it out of layout, so it can be declared beside the control that opens it,\n * including inside a `Drawer`: the modal behaviour is shared with `Drawer` and knows\n * the innermost overlay owns Escape and Tab.\n */\n\nimport { type ReactNode, useEffect, useId, useRef, useState } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { useModal } from \"../internal/modal.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\nimport { Button } from \"./Button.js\";\n\nconst STYLE_ID = \"nb-synapse-confirm-dialog\";\nconst RULES = `\n/* border-box on both, because the kit cannot assume the host resets it: under\n content-box a full-width panel is its padding wider than a phone screen. */\n.nb-confirm-scrim {\n box-sizing: border-box;\n position: fixed; inset: 0; z-index: 1010;\n display: flex; align-items: center; justify-content: center;\n padding: 1rem;\n background: rgba(0, 0, 0, 0.4);\n animation: nb-confirm-fade 160ms ease;\n}\n.nb-confirm {\n box-sizing: border-box;\n width: 100%; max-width: 28rem; max-height: 100%;\n overflow-y: auto;\n outline: none;\n animation: nb-confirm-in 160ms cubic-bezier(0.2, 0, 0, 1);\n}\n.nb-confirm__actions {\n display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem;\n}\n@keyframes nb-confirm-fade { from { opacity: 0; } }\n@keyframes nb-confirm-in { from { opacity: 0; transform: translateY(4px); } }\n@media (pointer: coarse) {\n .nb-confirm__actions .nb-btn { min-height: 44px; }\n}\n`;\n\ninterface ConfirmDialogProps {\n open: boolean;\n /** Every dismissal path — Escape, the scrim, Cancel — calls this with `false`. */\n onOpenChange: (open: boolean) => void;\n /** Names the dialog (`aria-labelledby`). */\n title: ReactNode;\n /** One line under the title. Becomes the dialog's accessible description. */\n description?: ReactNode;\n /** What the action will do, and any control that shapes it. */\n children?: ReactNode;\n confirmLabel?: string;\n cancelLabel?: string;\n /** Confirm's label while `onConfirm` is in flight. Defaults to `confirmLabel`. */\n pendingLabel?: string;\n /** Render Confirm as a `danger` button, and open with focus on Cancel. */\n destructive?: boolean;\n /** Resolve to close. Throw to stay open with the error's message shown. */\n onConfirm: () => void | Promise<void>;\n}\n\nexport function ConfirmDialog({\n open,\n onOpenChange,\n title,\n description,\n children,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n pendingLabel,\n destructive = false,\n onConfirm,\n}: ConfirmDialogProps) {\n ensureStyle(STYLE_ID, RULES);\n const panelRef = useRef<HTMLDivElement>(null);\n const titleId = useId();\n const descriptionId = useId();\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // A reopen starts clean: an error from the previous open describes a run the\n // user has already dismissed.\n useEffect(() => {\n if (open) {\n setError(null);\n setPending(false);\n }\n }, [open]);\n\n const dismiss = () => {\n if (!pending) onOpenChange(false);\n };\n\n const focusTarget = () =>\n panelRef.current?.querySelector<HTMLElement>(\n destructive ? \"[data-nb-confirm-cancel]\" : \"[data-nb-confirm-confirm]\",\n );\n\n useModal(open, panelRef, { onEscape: dismiss, initialFocus: focusTarget });\n\n // Disabling the focused button while the action ran can drop focus to <body>,\n // outside the panel's Tab trap. A failure hands it back to the same place the\n // dialog opened on, with the error now above it.\n // biome-ignore lint/correctness/useExhaustiveDependencies: keyed on the failure alone; focusTarget reads a ref.\n useEffect(() => {\n if (error) focusTarget()?.focus();\n }, [error]);\n\n const confirm = async () => {\n if (pending) return;\n setPending(true);\n setError(null);\n try {\n await onConfirm();\n setPending(false);\n onOpenChange(false);\n } catch (err) {\n // An empty message (`new Error(res.statusText)` over HTTP/2, where statusText\n // is always \"\") must still show that it failed.\n const message = err instanceof Error ? err.message : String(err);\n setError(message || \"That didn't go through. Try again.\");\n setPending(false);\n }\n };\n\n if (!open) return null;\n\n const panelStyle: StyleWithVars = {\n padding: \"1.25rem\",\n borderRadius: tokens.radiusMd,\n border: `${tokens.borderWidth} solid ${tokens.border}`,\n background: tokens.bg,\n color: tokens.fg,\n boxShadow: tokens.shadowLg,\n fontFamily: tokens.fontSans,\n };\n\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: scrim click is a bonus mouse affordance; Escape and Cancel are the keyboard dismissal paths.\n // biome-ignore lint/a11y/noStaticElementInteractions: the scrim is a decorative dismissal backdrop; the panel below owns the alertdialog role/semantics.\n <div\n className=\"nb-confirm-scrim\"\n onClick={(e) => {\n // A click whose target is the scrim itself (not the panel) dismisses.\n if (e.target === e.currentTarget) dismiss();\n }}\n >\n <div\n ref={panelRef}\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={description != null ? descriptionId : undefined}\n aria-busy={pending || undefined}\n tabIndex={-1}\n className=\"nb-confirm\"\n style={panelStyle}\n >\n <h2\n id={titleId}\n style={{\n margin: 0,\n fontFamily: tokens.fontSans,\n fontSize: tokens.textBaseSize,\n lineHeight: tokens.textBaseLine,\n fontWeight: tokens.weightSemibold,\n color: tokens.fg,\n }}\n >\n {title}\n </h2>\n {description != null ? (\n <p\n id={descriptionId}\n style={{\n margin: \"0.25rem 0 0\",\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n color: tokens.fgMuted,\n }}\n >\n {description}\n </p>\n ) : null}\n\n {children != null ? (\n <div\n style={{\n marginTop: \"1rem\",\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n }}\n >\n {children}\n </div>\n ) : null}\n\n {error ? (\n <p\n role=\"alert\"\n style={{\n margin: \"0.75rem 0 0\",\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n color: tokens.danger,\n }}\n >\n {error}\n </p>\n ) : null}\n\n <div className=\"nb-confirm__actions\" style={{ marginTop: \"1.25rem\" }}>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n data-nb-confirm-cancel=\"\"\n disabled={pending}\n onClick={dismiss}\n >\n {cancelLabel}\n </Button>\n <Button\n variant={destructive ? \"danger\" : \"primary\"}\n size=\"sm\"\n data-nb-confirm-confirm=\"\"\n disabled={pending}\n onClick={() => void confirm()}\n >\n {pending ? (pendingLabel ?? confirmLabel) : confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Drawer — an off-canvas overlay panel that slides in from an edge, over a\n * scrim. The general overlay the apps need (e.g. CRM's detail panel).\n *\n * A plain positioned `<div>` overlay — **not** a native `<dialog>`, which the app\n * iframe sandbox cannot open (see `internal/modal.ts`). The scrim is drawn here;\n * the modal behaviour — focus into the panel on open and back on close, the Tab\n * trap, background scroll lock, and Escape — comes from `useModal`, shared with\n * `ConfirmDialog` so a confirmation raised inside a drawer stacks correctly. Controlled via\n * `open`/`onClose` (renders nothing when closed). Escape routes through `onEscape`\n * (defaults to `onClose`); clicking the scrim calls `onClose`. The slide-in is a\n * CSS keyframe on the panel.\n *\n * Compose with the `Header` / `Body` / `Footer` slots, or pass plain children.\n * `Header` owns the standard affordances — `title` (a real heading, wired as\n * the dialog's accessible name), an optional `onBack` button, an `actions`\n * slot, and the close button — so consumers don't re-roll them. The icon\n * buttons grow to a 44px hit target under `@media (pointer: coarse)`, keyed to\n * input modality rather than viewport width.\n *\n * `side` is `right` (default), `left`, or `bottom` (a bottom sheet — full width,\n * content height capped at 92%). A multi-level \"panel stack\" (push/pop) is an\n * app concern built on top of this.\n */\n\nimport {\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { useModal } from \"../internal/modal.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\ntype Side = \"left\" | \"right\" | \"bottom\";\n\nconst STYLE_ID = \"nb-synapse-drawer\";\nconst RULES = `\n.nb-drawer-scrim {\n position: fixed; inset: 0; z-index: 1000;\n display: flex; background: rgba(0, 0, 0, 0.32);\n animation: nb-drawer-fade 200ms ease;\n}\n.nb-drawer-scrim--right { justify-content: flex-end; }\n.nb-drawer-scrim--left { justify-content: flex-start; }\n.nb-drawer-scrim--bottom { align-items: flex-end; }\n.nb-drawer {\n margin: 0; padding: 0; border: none; max-width: 92%;\n height: 100%; max-height: 100%; display: flex; flex-direction: column;\n outline: none;\n}\n.nb-drawer--bottom { width: 100%; max-width: 100%; height: auto; max-height: 92%; }\n.nb-drawer--right { animation: nb-drawer-in-right 240ms cubic-bezier(0.2, 0, 0, 1); }\n.nb-drawer--left { animation: nb-drawer-in-left 240ms cubic-bezier(0.2, 0, 0, 1); }\n.nb-drawer--bottom { animation: nb-drawer-in-bottom 240ms cubic-bezier(0.2, 0, 0, 1); }\n@keyframes nb-drawer-in-right { from { transform: translateX(100%); } }\n@keyframes nb-drawer-in-left { from { transform: translateX(-100%); } }\n@keyframes nb-drawer-in-bottom { from { transform: translateY(100%); } }\n@keyframes nb-drawer-fade { from { opacity: 0; } }\n.nb-drawer-iconbtn { width: 28px; height: 28px; }\n@media (pointer: coarse) {\n .nb-drawer-iconbtn { min-width: 44px; min-height: 44px; }\n}\n`;\n\ninterface DrawerContextValue {\n labelId: string;\n setHasTitle: (has: boolean) => void;\n}\n\nconst DrawerContext = createContext<DrawerContextValue | null>(null);\n\ninterface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"onClick\"> {\n open: boolean;\n /** Called by the scrim and the Header close button. */\n onClose: () => void;\n /** Called on Escape. Defaults to `onClose` — override to do something else\n * (e.g. pop one level of a panel stack before closing). */\n onEscape?: () => void;\n side?: Side;\n /** Panel width (ignored for `side=\"bottom\"`, which is full width). Default 480. */\n width?: number | string;\n children?: ReactNode;\n}\n\nfunction DrawerRoot({\n open,\n onClose,\n onEscape,\n side = \"right\",\n width = 480,\n style,\n children,\n ...rest\n}: DrawerProps) {\n ensureStyle(STYLE_ID, RULES);\n const panelRef = useRef<HTMLDivElement>(null);\n const labelId = useId();\n // A `Header` with a `title` registers itself here so the panel can name\n // itself via `aria-labelledby` (preferred over a consumer-passed aria-label).\n const [hasTitle, setHasTitle] = useState(false);\n\n useModal(open, panelRef, { onEscape: onEscape ?? onClose });\n\n const ctxValue = useMemo<DrawerContextValue>(() => ({ labelId, setHasTitle }), [labelId]);\n\n if (!open) return null;\n\n const isBottom = side === \"bottom\";\n const panelStyle: StyleWithVars = {\n ...(isBottom ? { width: \"100%\", maxWidth: \"100%\" } : { width }),\n background: tokens.bg,\n color: tokens.fg,\n boxShadow: tokens.shadowLg,\n outline: \"none\",\n ...(side === \"right\"\n ? { borderLeft: `${tokens.borderWidth} solid ${tokens.border}` }\n : side === \"left\"\n ? { borderRight: `${tokens.borderWidth} solid ${tokens.border}` }\n : { borderTop: `${tokens.borderWidth} solid ${tokens.border}` }),\n ...style,\n };\n\n return (\n <DrawerContext.Provider value={ctxValue}>\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: scrim click is a bonus mouse affordance; Escape (the window keydown above) and the Header close button are the keyboard dismissal paths. */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: the scrim is a decorative dismissal backdrop; the panel below owns the dialog role/semantics. */}\n <div\n className={`nb-drawer-scrim nb-drawer-scrim--${side}`}\n onClick={(e) => {\n // A click whose target is the scrim itself (not the panel) dismisses.\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={hasTitle ? labelId : undefined}\n tabIndex={-1}\n className={`nb-drawer nb-drawer--${side}`}\n style={panelStyle}\n {...rest}\n >\n {children}\n </div>\n </div>\n </DrawerContext.Provider>\n );\n}\n\ninterface HeaderProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Heading text — rendered as an `<h2>` and wired as the drawer's accessible\n * name. Renders **instead of** `children` (pass one or the other, not both).\n */\n title?: ReactNode;\n /** Show a leading back button (e.g. pop one level of a panel stack). */\n onBack?: () => void;\n /** Trailing controls placed before the close button. */\n actions?: ReactNode;\n /** Show a close button that calls this. */\n onClose?: () => void;\n children?: ReactNode;\n}\n\nfunction Header({ title, onBack, actions, onClose, style, children, ...rest }: HeaderProps) {\n const ctx = useContext(DrawerContext);\n const hasTitle = title != null;\n\n // Register the title's presence so the dialog can name itself via this h2.\n useEffect(() => {\n if (!ctx || !hasTitle) return;\n ctx.setHasTitle(true);\n return () => ctx.setHasTitle(false);\n }, [ctx, hasTitle]);\n\n return (\n <header\n style={{\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.75rem\",\n padding: \"0.875rem 1rem\",\n borderBottom: `${tokens.borderWidth} solid ${tokens.border}`,\n fontFamily: tokens.fontSans,\n fontWeight: tokens.weightSemibold,\n color: tokens.fg,\n ...style,\n }}\n {...rest}\n >\n {onBack ? (\n <IconButton label=\"Back\" onClick={onBack}>\n <path\n d=\"M10 3L5 8l5 5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </IconButton>\n ) : null}\n {hasTitle ? (\n <h2\n id={ctx?.labelId}\n style={{\n flex: 1,\n minWidth: 0,\n margin: 0,\n fontFamily: tokens.fontSans,\n fontSize: tokens.textBaseSize,\n lineHeight: tokens.textBaseLine,\n fontWeight: tokens.weightSemibold,\n color: tokens.fg,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {title}\n </h2>\n ) : (\n <div style={{ flex: 1, minWidth: 0 }}>{children}</div>\n )}\n {actions ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"0.4rem\", flexShrink: 0 }}>\n {actions}\n </div>\n ) : null}\n {onClose ? (\n <IconButton label=\"Close\" onClick={onClose}>\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </IconButton>\n ) : null}\n </header>\n );\n}\n\n/** Shared 28px (→44px on coarse pointers) icon button for the header affordances. */\nfunction IconButton({\n label,\n onClick,\n children,\n}: {\n label: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n onClick={onClick}\n className=\"nb-drawer-iconbtn\"\n style={{\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n background: \"transparent\",\n color: tokens.fgMuted,\n cursor: \"pointer\",\n borderRadius: tokens.radiusSm,\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n {children}\n </svg>\n </button>\n );\n}\n\nfunction Body({ style, children, ...rest }: HTMLAttributes<HTMLDivElement>) {\n return (\n <div style={{ flex: 1, minHeight: 0, overflowY: \"auto\", padding: \"1rem\", ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\nfunction Footer({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n return (\n <footer\n style={{\n flexShrink: 0,\n padding: \"0.75rem 1rem\",\n borderTop: `${tokens.borderWidth} solid ${tokens.border}`,\n ...style,\n }}\n {...rest}\n >\n {children}\n </footer>\n );\n}\n\n/** `Drawer` with `.Header`, `.Body`, `.Footer` slots. */\nexport const Drawer = Object.assign(DrawerRoot, { Header, Body, Footer });\n","/**\n * Layout primitives — the composition atoms. `Stack` (vertical) and `Inline`\n * (horizontal) replace ad-hoc `display:flex` style objects; `Spacer` and\n * `Divider` cover the two other recurring layout needs. Deliberately minimal\n * (no `Box`, no grid system) — the layout scaffolds handle page structure.\n */\n\nimport type { CSSProperties, HTMLAttributes, ReactNode } from \"react\";\nimport { tokens } from \"./tokens.js\";\n\ntype Align = \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\";\ntype Justify = \"start\" | \"center\" | \"end\" | \"between\" | \"around\";\n\nconst ALIGN: Record<Align, CSSProperties[\"alignItems\"]> = {\n start: \"flex-start\",\n center: \"center\",\n end: \"flex-end\",\n stretch: \"stretch\",\n baseline: \"baseline\",\n};\n\nconst JUSTIFY: Record<Justify, CSSProperties[\"justifyContent\"]> = {\n start: \"flex-start\",\n center: \"center\",\n end: \"flex-end\",\n between: \"space-between\",\n around: \"space-around\",\n};\n\ninterface FlexProps extends HTMLAttributes<HTMLDivElement> {\n gap?: number | string;\n align?: Align;\n justify?: Justify;\n wrap?: boolean;\n children?: ReactNode;\n}\n\nfunction flexStyle(\n direction: \"row\" | \"column\",\n { gap, align, justify, wrap }: FlexProps,\n): CSSProperties {\n return {\n display: \"flex\",\n flexDirection: direction,\n gap,\n alignItems: align ? ALIGN[align] : undefined,\n justifyContent: justify ? JUSTIFY[justify] : undefined,\n flexWrap: wrap ? \"wrap\" : undefined,\n };\n}\n\n/** Vertical flex container with `gap`. Defaults to `align: stretch`. */\nexport function Stack({ gap, align, justify, wrap, style, children, ...rest }: FlexProps) {\n return (\n <div style={{ ...flexStyle(\"column\", { gap, align, justify, wrap }), ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\n/** Horizontal flex container with `gap`. Defaults to `align: center`. */\nexport function Inline({\n gap,\n align = \"center\",\n justify,\n wrap,\n style,\n children,\n ...rest\n}: FlexProps) {\n return (\n <div style={{ ...flexStyle(\"row\", { gap, align, justify, wrap }), ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\n/** Flexible gap that pushes siblings apart inside a `Stack`/`Inline`. */\nexport function Spacer({ style, ...rest }: HTMLAttributes<HTMLDivElement>) {\n return <div style={{ flex: 1, ...style }} {...rest} />;\n}\n\ninterface DividerProps extends HTMLAttributes<HTMLDivElement> {\n orientation?: \"horizontal\" | \"vertical\";\n}\n\n/** A hairline rule using the border token. Horizontal by default. Decorative\n * (`aria-hidden`) — it's a visual divider, not a focusable/valued separator. */\nexport function Divider({ orientation = \"horizontal\", style, ...rest }: DividerProps) {\n const isVertical = orientation === \"vertical\";\n return (\n <div\n aria-hidden=\"true\"\n style={{\n flexShrink: 0,\n background: tokens.border,\n ...(isVertical\n ? { width: tokens.borderWidth, alignSelf: \"stretch\" }\n : { height: tokens.borderWidth, width: \"100%\" }),\n ...style,\n }}\n {...rest}\n />\n );\n}\n","/**\n * EmptyState — centered placeholder for empty lists/views. Optional icon,\n * title, description, and an action slot (e.g. a Button).\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Stack } from \"../primitives.js\";\nimport { tokens } from \"../tokens.js\";\nimport { Heading, Text } from \"../typography.js\";\n\ninterface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n icon?: ReactNode;\n title?: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n}\n\nexport function EmptyState({ icon, title, description, action, style, ...rest }: EmptyStateProps) {\n return (\n <Stack\n align=\"center\"\n gap=\"0.5rem\"\n style={{\n textAlign: \"center\",\n padding: \"4rem 1.5rem\",\n color: tokens.fgMuted,\n ...style,\n }}\n {...rest}\n >\n {icon ? <div style={{ color: tokens.fgFaint, marginBottom: \"0.25rem\" }}>{icon}</div> : null}\n {title ? <Heading size=\"sm\">{title}</Heading> : null}\n {description ? (\n <Text size=\"sm\" tone=\"muted\" style={{ maxWidth: 360 }}>\n {description}\n </Text>\n ) : null}\n {action ? <div style={{ marginTop: \"0.75rem\" }}>{action}</div> : null}\n </Stack>\n );\n}\n","/**\n * ListRow — the recurring list item: an optional leading slot (status dot,\n * avatar), a title with optional meta line, and a trailing slot (timestamp,\n * actions). Rounded hover tint, flat at rest — the pattern Research,\n * Conversations, and the Collateral sidebar each re-rolled.\n */\n\nimport type { HTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-listrow\";\nconst RULES = `\n.nb-listrow { transition: background 140ms ease; }\n.nb-listrow--interactive { cursor: pointer; }\n.nb-listrow--interactive:hover { background: var(--nb-listrow-hover); }\n`;\n\ninterface ListRowProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n title: ReactNode;\n /** Secondary line under the title. */\n meta?: ReactNode;\n /** Leading slot — e.g. a StatusDot or Avatar. */\n leading?: ReactNode;\n /** Trailing slot — e.g. a timestamp or actions. */\n trailing?: ReactNode;\n /** Enables pointer cursor + hover tint. */\n interactive?: boolean;\n}\n\nexport function ListRow({\n title,\n meta,\n leading,\n trailing,\n interactive = false,\n style,\n className,\n ...rest\n}: ListRowProps) {\n ensureStyle(STYLE_ID, RULES);\n const rowStyle: StyleWithVars = {\n \"--nb-listrow-hover\": tokens.bgSubtle,\n display: \"grid\",\n gridTemplateColumns: `${leading ? \"auto \" : \"\"}minmax(0, 1fr)${trailing ? \" auto\" : \"\"}`,\n columnGap: \"0.75rem\",\n alignItems: \"baseline\",\n padding: \"0.65rem 0.75rem\",\n borderRadius: tokens.radiusSm,\n ...style,\n };\n // When interactive, make the row keyboard-operable (matches Table's rows):\n // role=\"button\" + tabIndex, and Enter/Space synthesize the click that drives\n // the consumer's onClick (passed via ...rest). Placed before ...rest so a\n // consumer can still override any of these explicitly.\n const interactiveProps = interactive\n ? {\n role: \"button\",\n tabIndex: 0,\n onKeyDown: (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n e.currentTarget.click();\n }\n },\n }\n : {};\n return (\n <div\n className={`nb-listrow ${interactive ? \"nb-listrow--interactive\" : \"\"} ${className ?? \"\"}`.trim()}\n style={rowStyle}\n {...interactiveProps}\n {...rest}\n >\n {leading ? <div style={{ alignSelf: \"center\", display: \"flex\" }}>{leading}</div> : null}\n <div style={{ minWidth: 0 }}>\n <div\n style={{\n fontFamily: tokens.fontSans,\n fontSize: tokens.textBaseSize,\n lineHeight: tokens.textBaseLine,\n fontWeight: tokens.weightMedium,\n color: tokens.fg,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {title}\n </div>\n {meta ? (\n <div\n style={{\n marginTop: \"0.15rem\",\n fontFamily: tokens.fontSans,\n fontSize: tokens.textXsSize,\n lineHeight: tokens.textXsLine,\n color: tokens.fgMuted,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {meta}\n </div>\n ) : null}\n </div>\n {trailing ? (\n <div\n style={{\n alignSelf: \"center\",\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n fontSize: tokens.textXsSize,\n color: tokens.fgMuted,\n whiteSpace: \"nowrap\",\n }}\n >\n {trailing}\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * PageHeader — the top of a page: where you are, what this is, and what you can do to it.\n *\n * One component rather than each screen assembling its own, because the parts have to keep\n * one order and one rhythm for a multi-screen app to read as one app. It is also what makes\n * a full-width screen legible as a LEVEL in a hierarchy rather than as a page that happens\n * to be open — the trail above the title is doing that work, not decoration.\n *\n * The order is fixed and the reasons are not interchangeable: the trail comes first because\n * orientation precedes identity; actions sit on the title's row because they act on the\n * thing the title names; the description comes last because it is the only part a reader\n * can skip.\n *\n * **The description is clamped to two lines.** Descriptions here are frequently\n * agent-authored and of no bounded length, and an unbounded paragraph at the top of every\n * screen pushes the content the reader came for below the fold. Two lines is enough to\n * identify the thing and not enough to become the page. Callers with genuinely short,\n * curated copy can raise it; the default protects the common case rather than the tidy one.\n *\n * `status` and `actions` are ReactNode slots, not typed vocabularies. A page header has no\n * business knowing what states a caller's entity can be in or which of its verbs are primary —\n * that knowledge belongs to the app, and a kit that encoded it would need extending for every\n * app that arrived with a different one.\n *\n * **There is no slot for an app's top-level destinations, and that is the design.** They are\n * facets of the app exactly as a record's tabs are facets of the record, so they go in a `Tabs`\n * bar under this header — the same shape at every level, with only the tab bar's contents\n * changing as you descend. Giving them a slot up here put two right-aligned clusters on top of\n * each other, destinations above actions, and made the quieter of the two the more important\n * one. An embedded app has one column and cannot afford a corner that dense.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport type { StyleWithVars } from \"../tokens.js\";\nimport { Heading, Text } from \"../typography.js\";\nimport { Breadcrumb, type Crumb } from \"./Breadcrumb.js\";\n\nconst STYLE_ID = \"nb-synapse-page-header\";\n// The clamp lives in a stylesheet rule rather than an inline style, following the same\n// pattern Table/Tabs/SegmentedControl use. Two reasons beyond consistency: `display:\n// -webkit-box` and `-webkit-line-clamp` are a matched pair that only works together, so they\n// belong in one place a caller cannot half-override with `style`; and the line count stays\n// parameterized through a custom property, which is how every other knob in this kit travels.\nconst RULES = `\n.nb-page-header__desc {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--nb-ph-desc-lines, 2);\n line-clamp: var(--nb-ph-desc-lines, 2);\n overflow: hidden;\n}\n`;\n\ninterface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** The trail. Omit on a top-level page, which has nothing above it to name. */\n crumbs?: Crumb[];\n title: ReactNode;\n /** Sits beside the title — typically a `Badge`. */\n status?: ReactNode;\n /** Sits at the far end of the title's row. Buttons, a menu. */\n actions?: ReactNode;\n description?: ReactNode;\n /** Lines the description is clamped to before ellipsis. `0` removes the clamp. */\n descriptionLines?: number;\n}\n\nexport function PageHeader({\n crumbs,\n title,\n status,\n actions,\n description,\n descriptionLines = 2,\n style,\n ...rest\n}: PageHeaderProps) {\n ensureStyle(STYLE_ID, RULES);\n const descVars: StyleWithVars =\n descriptionLines > 0 ? { \"--nb-ph-desc-lines\": String(descriptionLines) } : {};\n return (\n <header\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"0.5rem\", minWidth: 0, ...style }}\n {...rest}\n >\n {crumbs && crumbs.length > 0 ? <Breadcrumb crumbs={crumbs} /> : null}\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"1rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.6rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n }}\n >\n <Heading size=\"md\">{title}</Heading>\n {status}\n </div>\n {/* Rendered only when given. An empty actions box still occupies its row and pulls\n the title off centre, which reads as a control that failed to load. */}\n {actions ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"0.5rem\", flexShrink: 0 }}>\n {actions}\n </div>\n ) : null}\n </div>\n\n {description ? (\n <Text\n size=\"sm\"\n tone=\"muted\"\n className={descriptionLines > 0 ? \"nb-page-header__desc\" : undefined}\n // A measure, clamped or not. The clamp needs a width to resolve line boxes\n // against, and unclamped prose past ~72 characters a line is hard to track back\n // to the next line's start whatever its length.\n style={{ maxWidth: \"72ch\", ...descVars }}\n >\n {description}\n </Text>\n ) : null}\n </header>\n );\n}\n","/**\n * Pagination — chrome-less prev/next text links with a \"page X of Y\" counter.\n * 1-based `page`. Buttons disable at the ends.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { Inline } from \"../primitives.js\";\nimport { tokens } from \"../tokens.js\";\nimport { TextLink } from \"./Button.js\";\n\ninterface PaginationProps extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n /** Current page, 1-based. */\n page: number;\n /** Total number of pages. */\n pageCount: number;\n onChange: (page: number) => void;\n}\n\nexport function Pagination({ page, pageCount, onChange, style, ...rest }: PaginationProps) {\n const total = Math.max(1, pageCount);\n const atStart = page <= 1;\n const atEnd = page >= total;\n return (\n <Inline\n justify=\"between\"\n style={{\n fontFamily: tokens.fontSans,\n fontSize: tokens.textXsSize,\n color: tokens.fgMuted,\n letterSpacing: \"0.02em\",\n ...style,\n }}\n {...rest}\n >\n <span style={{ fontVariantNumeric: \"tabular-nums\" }}>\n Page {page} of {total}\n </span>\n <Inline gap=\"1rem\">\n <TextLink disabled={atStart} onClick={() => onChange(page - 1)}>\n ← Prev\n </TextLink>\n <TextLink disabled={atEnd} onClick={() => onChange(page + 1)}>\n Next →\n </TextLink>\n </Inline>\n </Inline>\n );\n}\n","/**\n * Prose — a token-styled container for rendered rich text. It applies the\n * NimbleBrain reading typography (ported from the Research app's markdown\n * element map) to whatever HTML it wraps, via a once-injected scoped\n * stylesheet — so it stays dependency-free.\n *\n * Pass pre-rendered nodes as `children`, or a trusted HTML string as `html`.\n * Bring your own markdown parser (`marked`, `react-markdown`, …) upstream; this\n * owns the *styling*, not the parsing — keeping the SDK free of a parser dep.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-prose\";\nconst RULES = `\n.nb-prose {\n font-family: ${tokens.fontSans};\n font-size: ${tokens.textBaseSize};\n line-height: 1.7;\n color: ${tokens.fg};\n}\n.nb-prose > :first-child { margin-top: 0; }\n.nb-prose > :last-child { margin-bottom: 0; }\n.nb-prose h1, .nb-prose h2 { font-family: ${tokens.fontHeading}; letter-spacing: -0.015em; color: ${tokens.fg}; }\n.nb-prose h1 { font-size: ${tokens.headingMdSize}; line-height: ${tokens.headingMdLine}; margin: 2rem 0 0.75rem; }\n.nb-prose h2 { font-size: ${tokens.headingSmSize}; line-height: ${tokens.headingSmLine}; margin: 1.75rem 0 0.5rem; }\n.nb-prose h3 { font-size: ${tokens.textBaseSize}; font-weight: ${tokens.weightSemibold}; margin: 1.5rem 0 0.35rem; color: ${tokens.fg}; }\n.nb-prose p { margin: 0 0 1rem; }\n.nb-prose ul, .nb-prose ol { margin: 0 0 1rem; padding-left: 1.25rem; }\n.nb-prose li { margin: 0.25rem 0; }\n.nb-prose a { color: ${tokens.accent}; text-decoration: underline; text-underline-offset: 2px; }\n.nb-prose blockquote { margin: 0 0 1rem; padding-left: 1rem; border-left: 2px solid ${tokens.accent}; color: ${tokens.fgMuted}; font-style: italic; }\n.nb-prose code { font-family: ${tokens.fontMono}; font-size: 0.88em; padding: 0.08rem 0.32rem; border-radius: ${tokens.radiusXs}; background: ${tokens.bgSubtle}; }\n.nb-prose pre { font-family: ${tokens.fontMono}; font-size: ${tokens.textSmSize}; line-height: 1.55; margin: 0 0 1.25rem; padding: 0.875rem 1rem; background: ${tokens.bgSubtle}; border-radius: ${tokens.radiusSm}; overflow-x: auto; }\n.nb-prose pre code { padding: 0; background: none; }\n.nb-prose hr { border: none; border-top: 1px solid ${tokens.border}; margin: 2rem 0; }\n.nb-prose strong { font-weight: ${tokens.weightSemibold}; }\n`;\n\ninterface ProseProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\" | \"dangerouslySetInnerHTML\"> {\n /** Trusted, pre-sanitized HTML string. */\n html?: string;\n children?: ReactNode;\n}\n\nexport function Prose({ html, children, className, ...rest }: ProseProps) {\n ensureStyle(STYLE_ID, RULES);\n const cls = `nb-prose ${className ?? \"\"}`.trim();\n if (html !== undefined) {\n // biome-ignore lint/security/noDangerouslySetInnerHtml: caller supplies trusted, pre-sanitized HTML by contract.\n return <div className={cls} dangerouslySetInnerHTML={{ __html: html }} {...rest} />;\n }\n return (\n <div className={cls} {...rest}>\n {children}\n </div>\n );\n}\n","/**\n * SearchField — a text input in two postures: `underline` (invisible at rest,\n * reveals an underline on focus — the Research editorial style) and `boxed`\n * (a bordered field). Focus styling lives in a once-injected stylesheet.\n */\n\nimport type { InputHTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-searchfield\";\nconst RULES = `\n.nb-search { font-family: var(--nb-search-font); color: var(--nb-search-fg); outline: none; }\n.nb-search::placeholder { color: var(--nb-search-placeholder); }\n.nb-search--underline {\n border: none;\n border-bottom: 1px solid transparent;\n background: transparent;\n padding: 0.3rem 0.1rem;\n transition: border-color 160ms ease;\n}\n.nb-search--underline:focus { border-bottom-color: var(--nb-search-accent); }\n.nb-search--boxed {\n border: 1px solid var(--nb-search-border);\n border-radius: var(--nb-search-radius);\n background: var(--nb-search-bg);\n padding: 0.4rem 0.6rem;\n transition: border-color 160ms ease, box-shadow 160ms ease;\n}\n.nb-search--boxed:focus {\n border-color: var(--nb-search-accent);\n box-shadow: 0 0 0 3px color-mix(in oklab, var(--nb-search-accent) 18%, transparent);\n}\n`;\n\ninterface SearchFieldProps extends InputHTMLAttributes<HTMLInputElement> {\n variant?: \"underline\" | \"boxed\";\n}\n\nexport function SearchField({\n variant = \"underline\",\n style,\n className,\n type = \"search\",\n ...rest\n}: SearchFieldProps) {\n ensureStyle(STYLE_ID, RULES);\n const fieldStyle: StyleWithVars = {\n \"--nb-search-font\": tokens.fontSans,\n \"--nb-search-fg\": tokens.fg,\n \"--nb-search-placeholder\": tokens.fgFaint,\n \"--nb-search-accent\": tokens.accent,\n \"--nb-search-border\": tokens.border,\n \"--nb-search-bg\": tokens.bgSubtle,\n \"--nb-search-radius\": tokens.radiusSm,\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n ...style,\n };\n return (\n <input\n type={type}\n className={`nb-search nb-search--${variant} ${className ?? \"\"}`.trim()}\n style={fieldStyle}\n {...rest}\n />\n );\n}\n","/**\n * SegmentedControl — the view-toggle pattern (Board/Table, All/Today/Week).\n * A small set of mutually-exclusive options; the active one gets a raised pill.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-segmented\";\nconst RULES = `\n.nb-seg {\n display: inline-flex;\n gap: 2px;\n padding: 2px;\n border-radius: var(--nb-seg-radius);\n background: var(--nb-seg-track);\n}\n.nb-seg__btn {\n border: none;\n background: transparent;\n color: var(--nb-seg-fg);\n font-family: var(--nb-seg-font);\n font-weight: var(--nb-seg-weight);\n padding: 0.25rem 0.7rem;\n border-radius: calc(var(--nb-seg-radius) - 2px);\n cursor: pointer;\n transition: color 130ms ease, background 130ms ease;\n white-space: nowrap;\n}\n.nb-seg__btn:hover:not([aria-pressed=\"true\"]) { color: var(--nb-seg-fg-strong); }\n.nb-seg__btn[aria-pressed=\"true\"] {\n background: var(--nb-seg-active-bg);\n color: var(--nb-seg-fg-strong);\n box-shadow: var(--nb-seg-active-shadow);\n}\n`;\n\ninterface Option<T extends string> {\n label: string;\n value: T;\n}\n\ninterface SegmentedControlProps<T extends string>\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n options: Option<T>[];\n value: T;\n onChange: (value: T) => void;\n}\n\nexport function SegmentedControl<T extends string>({\n options,\n value,\n onChange,\n style,\n className,\n ...rest\n}: SegmentedControlProps<T>) {\n ensureStyle(STYLE_ID, RULES);\n const trackStyle: StyleWithVars = {\n \"--nb-seg-radius\": tokens.radiusSm,\n \"--nb-seg-track\": tokens.bgSubtle,\n \"--nb-seg-fg\": tokens.fgMuted,\n \"--nb-seg-fg-strong\": tokens.fg,\n \"--nb-seg-font\": tokens.fontSans,\n \"--nb-seg-weight\": tokens.weightMedium,\n \"--nb-seg-active-bg\": tokens.bgRaised,\n \"--nb-seg-active-shadow\": tokens.shadowSm,\n fontSize: tokens.textSmSize,\n lineHeight: tokens.textSmLine,\n ...style,\n };\n return (\n // biome-ignore lint/a11y/useSemanticElements: role=\"group\" with aria-label is the correct grouping for a set of toggle buttons; <fieldset> would impose form semantics this control doesn't have.\n <div className={`nb-seg ${className ?? \"\"}`.trim()} role=\"group\" style={trackStyle} {...rest}>\n {options.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className=\"nb-seg__btn\"\n aria-pressed={opt.value === value}\n onClick={() => onChange(opt.value)}\n >\n {opt.label}\n </button>\n ))}\n </div>\n );\n}\n","/**\n * Spinner — a minimal rotating indicator for inline/button loading states.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-spinner\";\nconst RULES = `\n@keyframes nb-spin { to { transform: rotate(360deg); } }\n.nb-spinner { animation: nb-spin 0.7s linear infinite; }\n@media (prefers-reduced-motion: reduce) { .nb-spinner { animation-duration: 1.6s; } }\n`;\n\ninterface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {\n /** Diameter in px. Default 16. */\n size?: number;\n /** Arc color. Defaults to the accent token. */\n color?: string;\n}\n\nexport function Spinner({ size = 16, color, style, className, ...rest }: SpinnerProps) {\n ensureStyle(STYLE_ID, RULES);\n const spinnerStyle: StyleWithVars = {\n display: \"inline-block\",\n flexShrink: 0,\n width: size,\n height: size,\n borderRadius: \"50%\",\n border: `2px solid ${tokens.border}`,\n borderTopColor: color ?? tokens.accent,\n boxSizing: \"border-box\",\n ...style,\n };\n return (\n <span\n className={`nb-spinner ${className ?? \"\"}`.trim()}\n role=\"status\"\n aria-label=\"Loading\"\n style={spinnerStyle}\n {...rest}\n />\n );\n}\n","/**\n * StatusDot — a small colored dot for run/task status. The `working` state\n * gets a living ripple-pulse (ported from the Research app), gated on\n * `prefers-reduced-motion`. Same component in list rows and detail headers so\n * status reads identically everywhere.\n */\n\nimport type { HTMLAttributes } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nexport type Status = \"working\" | \"completed\" | \"failed\" | \"idle\";\n\nconst COLOR: Record<Status, string> = {\n working: tokens.accent,\n completed: tokens.success,\n failed: tokens.danger,\n idle: tokens.fgFaint,\n};\n\nconst STYLE_ID = \"nb-synapse-statusdot\";\nconst KEYFRAMES = `\n@keyframes nb-statusdot-pulse {\n 0% { box-shadow: 0 0 0 0 var(--nb-statusdot-ring); transform: scale(1); }\n 70% { box-shadow: 0 0 0 7px transparent; transform: scale(1.15); }\n 100% { box-shadow: 0 0 0 0 transparent; transform: scale(1); }\n}\n.nb-statusdot--working {\n animation: nb-statusdot-pulse 1.6s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n .nb-statusdot--working { animation: none; box-shadow: 0 0 0 2px var(--nb-statusdot-ring); }\n}\n`;\n\ninterface StatusDotProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"color\"> {\n status?: Status;\n /** Override the dot color (any CSS color / token). */\n color?: string;\n /** Diameter in px. Default 8. */\n size?: number;\n}\n\nexport function StatusDot({\n status = \"idle\",\n color,\n size = 8,\n style,\n className,\n ...rest\n}: StatusDotProps) {\n ensureStyle(STYLE_ID, KEYFRAMES);\n const dotColor = color ?? COLOR[status];\n const working = status === \"working\";\n const dotStyle: StyleWithVars = {\n display: \"inline-block\",\n flexShrink: 0,\n width: size,\n height: size,\n borderRadius: \"50%\",\n background: dotColor,\n // Ring color for the pulse keyframe — a faded copy of the dot color.\n \"--nb-statusdot-ring\": `color-mix(in oklab, ${dotColor} 45%, transparent)`,\n ...style,\n };\n return (\n <span\n className={working ? `nb-statusdot--working ${className ?? \"\"}`.trim() : className}\n style={dotStyle}\n {...rest}\n />\n );\n}\n","/**\n * Table — a token-styled data table with declarative columns. For the tabular\n * list surfaces (CRM contacts/deals) that simple `ListRow`s don't fit. Renders\n * a real `<table>` for semantics; header is sticky; rows hover-tint and can be\n * clickable. Sorting / selection / virtualization are deliberately out of v1 —\n * compose `Pagination` for paging.\n *\n * **A column that truncates must declare a `width`.** The default is CSS auto\n * table layout, which sizes every column to its content — so a long cell has no\n * width to be clipped against and instead widens the table past its container,\n * carrying the later columns off the pane. Declaring a width on ANY column\n * switches the table to fixed layout, which is what gives a truncating cell\n * something to overflow. This is the whole reason `width` exists on `Column`,\n * and it is easy to leave off because nothing fails loudly when you do: the\n * table renders, the text is there, and the columns you cannot see are simply\n * past the right edge.\n *\n * Horizontal scrolling is opt-in via `minWidth` — the width below which the\n * table scrolls rather than crushing. It is not the default because it costs\n * the sticky header: an `overflow-x` container captures the stickiness that\n * `position: sticky` resolves against the page's own scroller, and CSS gives no\n * way to scroll one axis while leaving the other visible. A table that fits does\n * not need it; a genuinely wide one is worth the trade, and the caller is the\n * one who knows which it is.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\ntype Align = \"left\" | \"right\" | \"center\";\n\nexport interface Column<T> {\n /** Stable column id. */\n key: string;\n header: ReactNode;\n /** Cell content for a row. */\n render: (row: T, index: number) => ReactNode;\n align?: Align;\n /**\n * Column width (`\"40%\"`, `220`, `\"12rem\"`). Declaring one on any column switches\n * the table to `table-layout: fixed`, and columns without a width then divide the\n * remainder equally. Required on any column whose cell truncates — see the note on\n * the module above.\n */\n width?: number | string;\n}\n\ninterface TableProps<T> extends Omit<HTMLAttributes<HTMLTableElement>, \"children\"> {\n data: T[];\n columns: Column<T>[];\n /** Stable key per row. */\n rowKey: (row: T, index: number) => string | number;\n onRowClick?: (row: T, index: number) => void;\n /** Shown when `data` is empty. */\n empty?: ReactNode;\n /**\n * The narrowest this table stays readable, and the switch that turns scrolling on.\n *\n * A fixed-layout table has no lower bound of its own, so seven columns in a 400px pane\n * become seven clipped headers and a badge overflowing its cell. Below this width the\n * table scrolls inside its own container instead of crushing — and setting the floor is\n * the only way to ask for that, because a scroller with no floor has no defined moment to\n * engage: under fixed layout the table always fits its container, and under auto layout it\n * engages at whatever width the content happens to reach.\n *\n * The cost is the sticky header. An `overflow-x` container captures the stickiness\n * `position: sticky` resolves against the page's own scroller, and CSS gives no way to\n * scroll one axis while leaving the other visible — so a table without a floor keeps its\n * sticky header, and one with a floor trades it.\n */\n minWidth?: number | string;\n}\n\nconst STYLE_ID = \"nb-synapse-table\";\nconst RULES = `\n.nb-table { width: 100%; border-collapse: collapse; font-family: var(--nb-table-font); }\n.nb-table th, .nb-table td {\n padding: 0.55rem 0.75rem;\n border-bottom: var(--nb-table-border);\n font-size: var(--nb-table-size); line-height: var(--nb-table-line);\n}\n.nb-table thead th {\n position: sticky; top: 0; z-index: 1;\n background: var(--nb-table-head-bg);\n color: var(--nb-table-muted);\n font-weight: var(--nb-table-semibold);\n font-size: var(--nb-table-xs); text-align: left;\n text-transform: uppercase; letter-spacing: 0.04em;\n}\n.nb-table tbody td { color: var(--nb-table-fg); }\n.nb-table tbody tr.nb-table__row--clickable { cursor: pointer; }\n.nb-table tbody tr.nb-table__row--clickable:hover { background: var(--nb-table-hover); }\n`;\n\nexport function Table<T>({\n data,\n columns,\n rowKey,\n onRowClick,\n empty,\n minWidth,\n style,\n className,\n ...rest\n}: TableProps<T>) {\n ensureStyle(STYLE_ID, RULES);\n\n const vars: Record<`--${string}`, string> = {\n \"--nb-table-font\": tokens.fontSans,\n \"--nb-table-fg\": tokens.fg,\n \"--nb-table-muted\": tokens.fgMuted,\n \"--nb-table-head-bg\": tokens.bg,\n \"--nb-table-hover\": tokens.bgSubtle,\n \"--nb-table-border\": `${tokens.borderWidth} solid ${tokens.border}`,\n \"--nb-table-size\": tokens.textSmSize,\n \"--nb-table-line\": tokens.textSmLine,\n \"--nb-table-xs\": tokens.textXsSize,\n \"--nb-table-semibold\": tokens.weightSemibold,\n };\n\n if (data.length === 0 && empty !== undefined) {\n return <>{empty}</>;\n }\n\n // Any declared width means the caller has an opinion about proportions, and auto layout\n // would ignore it in favour of content — so one width switches the whole table to fixed.\n // Derived rather than a separate prop: a `width` that silently did nothing is the trap\n // this replaces, not a second knob to remember alongside it.\n const fixed = columns.some((col) => col.width !== undefined);\n const tableStyle: StyleWithVars = {\n ...vars,\n ...(fixed ? { tableLayout: \"fixed\" as const } : {}),\n ...(minWidth !== undefined ? { minWidth } : {}),\n ...style,\n };\n\n const table = (\n <table className={`nb-table ${className ?? \"\"}`.trim()} style={tableStyle} {...rest}>\n <thead>\n <tr>\n {columns.map((col) => (\n <th\n key={col.key}\n scope=\"col\"\n style={{ width: col.width, textAlign: col.align ?? \"left\" }}\n >\n {col.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((row, i) => {\n const clickable = Boolean(onRowClick);\n return (\n <tr\n key={rowKey(row, i)}\n className={clickable ? \"nb-table__row--clickable\" : undefined}\n tabIndex={clickable ? 0 : undefined}\n onClick={clickable ? () => onRowClick?.(row, i) : undefined}\n onKeyDown={\n clickable\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRowClick?.(row, i);\n }\n }\n : undefined\n }\n >\n {columns.map((col) => (\n <td key={col.key} style={{ textAlign: col.align ?? \"left\" }}>\n {col.render(row, i)}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n\n if (minWidth === undefined) return table;\n // `tabIndex={0}` is not decoration. A scroll container that is neither focusable nor holds\n // a focusable descendant cannot be scrolled by keyboard at all (WCAG 2.1.1; axe's\n // `scrollable-region-focusable`), and a read-only table has no focusable descendants —\n // rows take a tabIndex only when `onRowClick` is set. Without this, every column past the\n // right edge is reachable with a pointer and by nothing else.\n //\n // `role=\"region\"` only when the caller named the table, because a region without an\n // accessible name is its own violation. The name is mirrored from the caller's own\n // `aria-label` rather than taken as a new prop: the label already reaches the table\n // through `rest`, and inventing a second way to say the same thing under review is how a\n // kit grows two spellings of one idea.\n const label = (rest as { \"aria-label\"?: string })[\"aria-label\"];\n // Role and name travel together or not at all — an `aria-label` on a roleless element names\n // nothing, and a `region` without a name is its own violation.\n const named = label ? ({ role: \"region\", \"aria-label\": label } as const) : {};\n return (\n <div\n // biome-ignore lint/a11y/noNoninteractiveTabindex: the two requirements point opposite ways here, and a scroll container is the case this rule does not model. axe's `scrollable-region-focusable` REQUIRES the tabIndex, because a container that is neither focusable nor holds a focusable descendant cannot be scrolled by keyboard at all (WCAG 2.1.1) — and a read-only table has no focusable descendants, since rows take a tabIndex only when `onRowClick` is set. Removing this makes every column past the right edge pointer-only.\n tabIndex={0}\n {...named}\n // `max-width: 100%` as well as `overflow-x`, because a flex or grid item's default\n // `min-width: auto` lets it grow to its content and the scroller never engages — the\n // container would widen instead, which is the failure this exists to stop.\n style={{ overflowX: \"auto\", maxWidth: \"100%\" }}\n >\n {table}\n </div>\n );\n}\n","/**\n * Tabs — facets of ONE entity, rendered as an underlined bar.\n *\n * **Why this exists beside `SegmentedControl`, which is also a row of exclusive choices.**\n * They are the same control mechanically and different jobs, and an app that uses one\n * component for both stacks two or three identical pill rows down the page — app\n * navigation, then entity facets, then a list filter, all wearing one costume. The reader\n * cannot tell which row changes what, and the screen reads as noise rather than hierarchy.\n * So the distinction is carried in the FORM: tabs are an underlined bar that belongs to the\n * thing above them, pills are a raised track that belongs to the thing below them.\n *\n * The rule that decides which to reach for:\n *\n * - **Tabs** change which FACET of one chosen entity is shown. They add no selection, so\n * they add no level — the entity is the same before and after.\n * - **SegmentedControl** narrows or reshapes a SET. A status filter over a list, a\n * board/table toggle.\n *\n * Full ARIA tab semantics (`role=\"tablist\"`, roving focus, arrow keys) because a tab bar is\n * a documented pattern a screen reader user already knows, and half of it — buttons with no\n * relationship declared between them — is worse than plain buttons, which at least do not\n * promise a structure that is not there.\n */\n\nimport { type HTMLAttributes, type KeyboardEvent, useRef } from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\n\nconst STYLE_ID = \"nb-synapse-tabs\";\nconst RULES = `\n.nb-tabs {\n display: flex;\n align-items: stretch;\n gap: var(--nb-tabs-gap);\n border-bottom: var(--nb-tabs-rule);\n overflow-x: auto;\n scrollbar-width: none;\n}\n.nb-tabs::-webkit-scrollbar { display: none; }\n.nb-tabs__tab {\n border: none;\n background: transparent;\n color: var(--nb-tabs-fg);\n font-family: var(--nb-tabs-font);\n font-weight: var(--nb-tabs-weight);\n font-size: var(--nb-tabs-size);\n line-height: var(--nb-tabs-line);\n padding: 0.4rem 0.15rem 0.55rem;\n cursor: pointer;\n white-space: nowrap;\n position: relative;\n transition: color 130ms ease;\n}\n.nb-tabs__tab::after {\n content: \"\";\n position: absolute;\n /* bottom 0, not -1px. overflow-x auto makes the computed overflow-y auto as well, and\n clipping happens at the PADDING box - so a negative offset put 1px of the 2px accent\n outside it: the underline rendered half-height and left 1px of phantom overflow. */\n left: 0; right: 0; bottom: 0;\n height: 2px;\n border-radius: 2px 2px 0 0;\n background: transparent;\n transition: background 130ms ease;\n}\n.nb-tabs__tab:hover { color: var(--nb-tabs-fg-strong); }\n.nb-tabs__tab[aria-selected=\"true\"] {\n color: var(--nb-tabs-fg-strong);\n font-weight: var(--nb-tabs-weight-active);\n}\n.nb-tabs__tab[aria-selected=\"true\"]::after { background: var(--nb-tabs-accent); }\n.nb-tabs__tab:focus-visible {\n outline: 2px solid var(--nb-tabs-ring);\n outline-offset: -2px;\n border-radius: var(--nb-tabs-radius);\n}\n`;\n\ninterface Tab<T extends string> {\n label: string;\n value: T;\n /** A small trailing count. Rendered muted, and omitted entirely when undefined. */\n count?: number;\n}\n\ninterface TabsProps<T extends string> extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n tabs: Tab<T>[];\n value: T;\n onChange: (value: T) => void;\n /** Accessible name for the tab set — what these are facets OF. */\n label?: string;\n}\n\nexport function Tabs<T extends string>({\n tabs,\n value,\n onChange,\n label,\n style,\n className,\n onKeyDown: callerKeyDown,\n ...rest\n}: TabsProps<T>) {\n ensureStyle(STYLE_ID, RULES);\n const barRef = useRef<HTMLDivElement>(null);\n\n const barStyle: StyleWithVars = {\n \"--nb-tabs-gap\": \"1.25rem\",\n \"--nb-tabs-rule\": `${tokens.borderWidth} solid ${tokens.border}`,\n \"--nb-tabs-fg\": tokens.fgMuted,\n \"--nb-tabs-fg-strong\": tokens.fg,\n \"--nb-tabs-accent\": tokens.accent,\n \"--nb-tabs-ring\": tokens.ring,\n \"--nb-tabs-font\": tokens.fontSans,\n \"--nb-tabs-weight\": tokens.weightMedium,\n \"--nb-tabs-weight-active\": tokens.weightSemibold,\n \"--nb-tabs-size\": tokens.textSmSize,\n \"--nb-tabs-line\": tokens.textSmLine,\n \"--nb-tabs-radius\": tokens.radiusXs,\n ...style,\n };\n\n // Arrow keys move FOCUS, and selection follows it.\n //\n // Moving selection alone was the bug this replaces: the roving tabindex handed tabIndex=0\n // to the newly selected tab while the browser's focus stayed on the previous one, so the\n // focus ring sat on an unselected tab, a screen reader announced nothing (AT announces\n // focus, not aria-selected), and tabbing out and back landed somewhere else. The APG tabs\n // pattern specifies that arrows move focus with activation following it, and half of a\n // pattern a reader already knows is worse than none of it.\n //\n // Focused imperatively off the bar's own DOM rather than through an effect keyed on value:\n // the buttons are already rendered so the target exists now, and an effect would also\n // steal focus when a PARENT changed the value - a tab bar grabbing focus because something\n // else navigated.\n //\n // The caller's own handler runs FIRST and can suppress navigation with preventDefault().\n // `onKeyDown` is part of this component's public prop type, so accepting one and never\n // calling it is the same silent lie as letting it replace the contract outright - the two\n // failures a caller cannot tell apart from the type. Opting out is now something they do\n // on purpose, in one visible line.\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n callerKeyDown?.(e);\n if (e.defaultPrevented) return;\n const at = tabs.findIndex((t) => t.value === value);\n if (at < 0) return;\n let to: number;\n if (e.key === \"ArrowRight\") to = (at + 1) % tabs.length;\n else if (e.key === \"ArrowLeft\") to = (at - 1 + tabs.length) % tabs.length;\n else if (e.key === \"Home\") to = 0;\n else if (e.key === \"End\") to = tabs.length - 1;\n else return;\n e.preventDefault();\n // Arrows wrap, because a bar with a dead end makes the reader reverse direction to reach\n // the tab one step past the one they are on. Home and End are absolute and do not - so\n // they are the two keys that can land on the tab already held, and a change event for a\n // value that did not change is one a caller has to defend against (a refetch, a route\n // push, an analytics event). Focus still moves, because the key was still pressed.\n if (to !== at) onChange(tabs[to].value);\n barRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]')[to]?.focus();\n };\n\n return (\n <div\n // `rest` FIRST, so nothing a caller passes can overwrite what makes this a tablist.\n // `role` and `aria-label` are the contract the pattern rests on; a caller who could\n // replace them would have a bar announcing something it does not implement.\n {...rest}\n ref={barRef}\n role=\"tablist\"\n aria-label={label}\n className={`nb-tabs ${className ?? \"\"}`.trim()}\n style={barStyle}\n onKeyDown={onKeyDown}\n >\n {tabs.map((tab) => {\n const selected = tab.value === value;\n return (\n <button\n key={tab.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n // Roving tabindex: one stop for the whole bar, then arrows within it.\n tabIndex={selected ? 0 : -1}\n className=\"nb-tabs__tab\"\n onClick={() => onChange(tab.value)}\n >\n {tab.label}\n {tab.count !== undefined ? (\n <span style={{ marginLeft: \"0.35rem\", color: tokens.fgFaint }}>{tab.count}</span>\n ) : null}\n </button>\n );\n })}\n </div>\n );\n}\n","/**\n * AppFrame — the universal app chrome: a fixed header, a scrollable body, and\n * an optional fixed footer, filling the iframe pane. Every Synapse app uses it;\n * a body layout (SidebarLayout, ListView, …) goes inside `AppFrame.Body`.\n *\n * The shell fills the pane with `height: 100%`, which needs a definite-height\n * ancestor chain (`#root` → `body` → `html`) — something a bare app document\n * does not supply on its own. So AppFrame establishes that chain itself on\n * render via `injectBaseReset()`; without it the shell would collapse to\n * content height. Apps wanting the chain before first paint can also\n * `import \"@nimblebrain/synapse/ui/base\"` in their entry.\n *\n * The `contentWidth` knob is a personality lever: `reading` centers header,\n * body, and footer in a ~760px column (Conversations, Research), while `full`\n * uses the whole pane (CRM, dashboards). Header/body/footer share the same\n * column so the composition reads as one page.\n *\n * **There is deliberately no chrome slot here.** A Synapse app does not own its\n * window: the host spends the left edge on a rail and the right on chat, so an\n * app-level bar is a third chrome layer whose rule lands a few pixels off the\n * chat panel's — two near-parallel lines that read as a mistake and that no\n * amount of styling reconciles. Top-level destinations go in a tab bar under\n * the page header instead; see `PageLayout`.\n */\n\nimport {\n type CSSProperties,\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n} from \"react\";\nimport { injectBaseReset } from \"../internal/base-reset.js\";\nimport { tokens } from \"../tokens.js\";\n\ntype ContentWidth = \"reading\" | \"full\";\nconst READING_MAX = 760;\nconst ContentWidthCtx = createContext<ContentWidth>(\"full\");\n\nfunction columnStyle(width: ContentWidth): CSSProperties {\n return width === \"reading\" ? { maxWidth: READING_MAX, marginInline: \"auto\", width: \"100%\" } : {};\n}\n\ninterface AppFrameProps extends HTMLAttributes<HTMLDivElement> {\n contentWidth?: ContentWidth;\n children?: ReactNode;\n}\n\nfunction AppFrameRoot({ contentWidth = \"full\", style, children, ...rest }: AppFrameProps) {\n // The shell's `height: 100%` only resolves against a definite-height ancestor\n // chain; supply it (same render-time pattern as the components' `ensureStyle`).\n injectBaseReset();\n return (\n <ContentWidthCtx.Provider value={contentWidth}>\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n minHeight: 0,\n background: tokens.bg,\n color: tokens.fg,\n fontFamily: tokens.fontSans,\n ...style,\n }}\n {...rest}\n >\n {children}\n </div>\n </ContentWidthCtx.Provider>\n );\n}\n\nfunction Header({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const width = useContext(ContentWidthCtx);\n return (\n <header style={{ flexShrink: 0, padding: \"1.25rem 1.5rem 0.75rem\", ...style }} {...rest}>\n <div style={columnStyle(width)}>{children}</div>\n </header>\n );\n}\n\ninterface BodyProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Host a full-bleed body layout (SidebarLayout, BoardLayout) edge-to-edge:\n * no padding, no reading column, and the body itself doesn't scroll — the\n * layout's panes manage their own scroll. Leave off for plain content\n * (lists, forms), which get the padded reading/full column.\n */\n bleed?: boolean;\n}\n\nfunction Body({ bleed = false, style, children, ...rest }: BodyProps) {\n const width = useContext(ContentWidthCtx);\n if (bleed) {\n return (\n <div\n style={{\n flex: 1,\n minHeight: 0,\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n ...style,\n }}\n {...rest}\n >\n {children}\n </div>\n );\n }\n return (\n <div style={{ flex: 1, minHeight: 0, overflowY: \"auto\", ...style }} {...rest}>\n <div style={{ ...columnStyle(width), padding: \"0.75rem 1.5rem 1.5rem\" }}>{children}</div>\n </div>\n );\n}\n\nfunction Footer({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const width = useContext(ContentWidthCtx);\n return (\n <footer\n style={{\n flexShrink: 0,\n padding: \"0.75rem 1.5rem\",\n borderTop: `${tokens.borderWidth} solid ${tokens.border}`,\n ...style,\n }}\n {...rest}\n >\n <div style={columnStyle(width)}>{children}</div>\n </footer>\n );\n}\n\n/** `AppFrame` with `.Header`, `.Body`, `.Footer` slots. */\nexport const AppFrame = Object.assign(AppFrameRoot, { Header, Body, Footer });\n","/**\n * `useBreakpoint` — responsive hook keyed to an element's OWN width, not the\n * device viewport. Synapse apps render in an iframe pane whose width the host\n * controls (fullscreen, split, or a narrow sidebar), so layouts must react to\n * the space they're actually given.\n *\n * Attach the returned `ref` to the element whose width drives the decision.\n * Width is measured synchronously on mount (no first-frame flash) and kept live\n * via `ResizeObserver`. SSR/test-safe: without a DOM/`ResizeObserver` it simply\n * reports `isNarrow: false`.\n */\n\nimport { type RefObject, useLayoutEffect, useRef, useState } from \"react\";\n\nexport function useBreakpoint<T extends HTMLElement = HTMLDivElement>(\n breakpoint: number,\n): { ref: RefObject<T | null>; isNarrow: boolean } {\n const ref = useRef<T>(null);\n const [width, setWidth] = useState<number | null>(null);\n\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n // Synchronous initial measure — runs before paint, so the first painted\n // frame already reflects the real width. Border-box, matching the observer\n // below (so there's no jump on the first resize if the element has padding).\n setWidth(el.getBoundingClientRect().width);\n if (typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver((entries) => {\n const entry = entries[0];\n const w = entry?.borderBoxSize?.[0]?.inlineSize ?? entry?.contentRect.width;\n if (typeof w === \"number\") setWidth(w);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n return { ref, isNarrow: width !== null && width < breakpoint };\n}\n","/**\n * ListDetailLayout — a master list beside a detail pane (CRM contacts → record,\n * Research runs → report, conversations → thread). Responsive to the layout's\n * own width: side-by-side when wide; below `breakpoint` it shows one at a time —\n * the list, or the detail when something is `selected`, with a `Back`\n * affordance to return.\n *\n * `selected` is driven by the app's own selection state. Place\n * `<ListDetailLayout.Back />` at the top of `Detail`; it renders only on a\n * narrow pane and calls `onBack`.\n */\n\nimport { createContext, type HTMLAttributes, type ReactNode, useContext } from \"react\";\nimport { TextLink } from \"../components/Button.js\";\nimport { tokens } from \"../tokens.js\";\nimport { useBreakpoint } from \"./use-container-width.js\";\n\ninterface ListDetailState {\n collapsed: boolean;\n selected: boolean;\n listWidth: number | string;\n onBack?: () => void;\n}\n\nconst ListDetailCtx = createContext<ListDetailState | null>(null);\n\n/** Read the list/detail responsive state — for custom back affordances. */\nexport function useListDetail(): ListDetailState {\n const ctx = useContext(ListDetailCtx);\n if (!ctx) throw new Error(\"useListDetail must be used within <ListDetailLayout>\");\n return ctx;\n}\n\ninterface ListDetailLayoutProps extends HTMLAttributes<HTMLDivElement> {\n /** Is a detail open? Drives which pane shows on a narrow layout. */\n selected?: boolean;\n /** Called by `Back` (and custom triggers) to return to the list when narrow. */\n onBack?: () => void;\n /** Master list width when side-by-side. Default 320. */\n listWidth?: number | string;\n /** Collapse to one-at-a-time below this layout width (px). Default 720. */\n breakpoint?: number;\n children?: ReactNode;\n}\n\nfunction ListDetailLayoutRoot({\n selected = false,\n onBack,\n listWidth = 320,\n breakpoint = 720,\n style,\n children,\n ...rest\n}: ListDetailLayoutProps) {\n const { ref, isNarrow } = useBreakpoint<HTMLDivElement>(breakpoint);\n return (\n <ListDetailCtx.Provider value={{ collapsed: isNarrow, selected, listWidth, onBack }}>\n <div\n ref={ref}\n style={{ display: \"flex\", flexDirection: \"row\", height: \"100%\", minHeight: 0, ...style }}\n {...rest}\n >\n {children}\n </div>\n </ListDetailCtx.Provider>\n );\n}\n\nfunction List({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const { collapsed, selected, listWidth } = useListDetail();\n if (collapsed && selected) return null; // detail has the stage\n const border = `${tokens.borderWidth} solid ${tokens.border}`;\n return (\n <section\n style={{\n // Clip horizontally, scroll vertically. A too-wide child (e.g. an\n // auto-layout <table> that won't shrink below its content) would\n // otherwise spill out of this fixed-width rail and paint over the\n // detail pane. `minWidth: 0` lets the rail participate in flex\n // sizing without being forced wider by its content.\n overflow: \"hidden auto\",\n ...(collapsed\n ? { flex: 1, minWidth: 0 }\n : { width: listWidth, minWidth: 0, flexShrink: 0, borderRight: border }),\n ...style,\n }}\n {...rest}\n >\n {children}\n </section>\n );\n}\n\nfunction Detail({ style, children, ...rest }: HTMLAttributes<HTMLDivElement>) {\n const { collapsed, selected } = useListDetail();\n if (collapsed && !selected) return null; // list has the stage\n return (\n <div style={{ flex: 1, minWidth: 0, minHeight: 0, overflowY: \"auto\", ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\ninterface BackProps {\n children?: ReactNode;\n style?: React.CSSProperties;\n}\n\n/** \"← Back\" affordance — renders only on a narrow pane with a detail open. */\nfunction Back({ children, style }: BackProps) {\n const { collapsed, selected, onBack } = useListDetail();\n if (!collapsed || !selected) return null;\n return (\n <TextLink onClick={() => onBack?.()} style={{ marginBottom: \"0.5rem\", ...style }}>\n {children ?? \"← Back\"}\n </TextLink>\n );\n}\n\n/** `ListDetailLayout` with `.List`, `.Detail`, and `.Back` slots. */\nexport const ListDetailLayout = Object.assign(ListDetailLayoutRoot, { List, Detail, Back });\n","/**\n * PageLayout — one screen of a Synapse app, assembled in the one order that works.\n *\n * A header naming what you are looking at, a tab bar of that thing's facets, an optional\n * toolbar over the content, then the content. Every level of an app is this shape, and the\n * only thing descending changes is whose facets the tab bar holds: at the root the header\n * names the app and the tabs are its sections; a level down a trail appears above the header,\n * the header names the record, and the tabs are the record's own.\n *\n * **Why this is a component when the kit says thin compositions stay recipes.** That rule\n * measures mechanical complexity, and by it this is a recipe — it is a vertical stack in a\n * fixed order. But the reason to own it is not that assembling it is hard; it is that\n * assembling it DIFFERENTLY is a defect rather than a preference, and a recipe written down\n * in prose does not stop that. The failures are real ones, all found in a shipped app: two\n * tab bars stacked until the reader could not tell which row changed what; an app-level\n * chrome bar whose rule landed a few pixels off the host's chat panel; an unbounded\n * agent-authored description pushing the content below the fold. Each is an ordering or\n * composition mistake that a component makes unavailable and a convention only discourages.\n *\n * So the amended rule: a layout becomes a component when it is complex to build OR when\n * getting its arrangement wrong is a bug. This is the second kind.\n *\n * **What it deliberately does not have is a chrome slot.** A Synapse app does not own its\n * window — the host spends the left edge on a rail and the right on a chat panel — so an\n * app-level bar is a third chrome layer, and its rule cannot agree with the chat panel's.\n * Everything here is page content, which is the only thing on screen the app unambiguously\n * owns.\n *\n * Compose it inside `AppFrame.Body`; it manages its own vertical rhythm and nothing else.\n */\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport type { Crumb } from \"../components/Breadcrumb.js\";\nimport { PageHeader } from \"../components/PageHeader.js\";\n\ninterface PageLayoutProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** The trail. Omit at the top level, which has nothing above it to name. */\n crumbs?: Crumb[];\n title: ReactNode;\n /** Beside the title — typically a `Badge`. */\n status?: ReactNode;\n /** The far end of the title's row. */\n actions?: ReactNode;\n description?: ReactNode;\n /** Lines the description is clamped to. `0` removes the clamp. */\n descriptionLines?: number;\n /**\n * ONE tab bar, of the facets of whatever the title names. A `Tabs`.\n *\n * A slot rather than typed props because `Tabs` already has an API worth having, and\n * wrapping it here would mean maintaining a second copy of it that drifts. What the layout\n * owns is the bar's POSITION — under the header, above the content — which is the part\n * apps get wrong.\n */\n tabs?: ReactNode;\n /**\n * Controls that narrow the content below: a search field, a status filter, a view toggle.\n *\n * Distinct from `tabs` on purpose. A tab changes which facet of one entity is shown; a\n * toolbar reshapes a set within that facet. Rendering them as one row is how an app ends up\n * with two identical-looking control strips whose difference nobody can see.\n */\n toolbar?: ReactNode;\n children?: ReactNode;\n}\n\nexport function PageLayout({\n crumbs,\n title,\n status,\n actions,\n description,\n descriptionLines,\n tabs,\n toolbar,\n children,\n style,\n ...rest\n}: PageLayoutProps) {\n return (\n // A `<section>`, not a `<div>`, and it is the header below that makes it load-bearing.\n // `<header>` maps to the `banner` landmark UNLESS it descends from sectioning content, so\n // a page inside a page — a `PageLayout` in a pane of one — produced TWO banners, both\n // claiming to head the document. That is the same defect as the app-chrome bar this\n // layout exists without, one layer down and invisible on screen: it shows up only in the\n // landmark list a screen-reader user navigates by.\n //\n // Scoping it here rather than asking callers to wrap is the point. A consuming app hit\n // this, diagnosed it, and wrapped its own instance — correct, and not a thing every app\n // should have to rediscover. An embedded app is not the document anyway: the host owns\n // the real banner, and what this renders is a section of the host's page.\n <section\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"1.1rem\", minWidth: 0, ...style }}\n {...rest}\n >\n <PageHeader\n crumbs={crumbs}\n title={title}\n status={status}\n actions={actions}\n description={description}\n descriptionLines={descriptionLines}\n />\n {tabs}\n {/* The toolbar sits closer to the content it filters than to the tabs above it, so the\n gap is tightened here rather than inheriting the stack's rhythm. A control that looks\n equally attached to both is a control whose scope the reader has to guess. */}\n {toolbar ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n flexWrap: \"wrap\",\n minWidth: 0,\n marginBottom: \"-0.35rem\",\n }}\n >\n {toolbar}\n </div>\n ) : null}\n {children}\n </section>\n );\n}\n","/**\n * SidebarLayout — the responsive two-column layout for inside an app pane: a\n * nav/list rail plus main content. It reacts to the layout's OWN width (not the\n * device), and below `breakpoint` collapses one of two ways:\n *\n * - `reflow` (default) — the rail moves to a horizontal strip on top and the\n * content goes full-width. Best for short navs (a settings page's sections).\n * - `drawer` — the rail becomes an off-canvas overlay opened by a `Trigger`.\n * Best for long lists (a document browser) where reflowing would be absurd.\n *\n * Place nav items as flat children of `Sidebar`; it controls direction\n * (column when expanded, row when reflowed). For `drawer`, place a\n * `<SidebarLayout.Trigger />` *inside* the layout (e.g. a toolbar in `Main`) —\n * in v1 the open-state context lives on `SidebarLayout`, so the trigger must be\n * within it, NOT in a sibling `AppFrame.Header`. Or read state via `useSidebar()`.\n * (Header placement would need a hoisted provider — a deliberate later refinement.)\n */\n\nimport {\n type ButtonHTMLAttributes,\n type CSSProperties,\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { ensureStyle } from \"../internal/inject-style.js\";\nimport { type StyleWithVars, tokens } from \"../tokens.js\";\nimport { useBreakpoint } from \"./use-container-width.js\";\n\ntype CollapseMode = \"reflow\" | \"drawer\";\ntype Side = \"left\" | \"right\";\n\ninterface SidebarState {\n collapsed: boolean;\n mode: CollapseMode;\n side: Side;\n width: number | string;\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nconst SidebarCtx = createContext<SidebarState | null>(null);\n\n/** Read the sidebar's responsive state — for custom triggers or nav re-orientation. */\nexport function useSidebar(): SidebarState {\n const ctx = useContext(SidebarCtx);\n if (!ctx) throw new Error(\"useSidebar must be used within <SidebarLayout>\");\n return ctx;\n}\n\nconst STYLE_ID = \"nb-synapse-sidebarlayout\";\n// Distinct class names from the Drawer component (which owns `.nb-drawer`).\nconst RULES = `\n.nb-sidebar-drawer { transition: transform 220ms cubic-bezier(0.2, 0, 0, 1); }\n.nb-sidebar-scrim { animation: nb-sidebar-fade 180ms ease; }\n@keyframes nb-sidebar-fade { from { opacity: 0; } to { opacity: 1; } }\n@media (prefers-reduced-motion: reduce) {\n .nb-sidebar-drawer { transition: none; }\n .nb-sidebar-scrim { animation: none; }\n}\n`;\n\ninterface SidebarLayoutProps extends HTMLAttributes<HTMLDivElement> {\n side?: Side;\n /** Expanded rail / drawer width. Default 240. */\n width?: number | string;\n /** Collapse below this pane width (px). Default 640. */\n breakpoint?: number;\n collapseMode?: CollapseMode;\n children?: ReactNode;\n}\n\nfunction SidebarLayoutRoot({\n side = \"left\",\n width = 240,\n breakpoint = 640,\n collapseMode = \"reflow\",\n style,\n children,\n ...rest\n}: SidebarLayoutProps) {\n const { ref, isNarrow } = useBreakpoint<HTMLDivElement>(breakpoint);\n const [open, setOpen] = useState(false);\n\n // Close the drawer on Escape.\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open]);\n\n // Collapsing back to expanded should drop any open drawer state.\n useEffect(() => {\n if (!isNarrow && open) setOpen(false);\n }, [isNarrow, open]);\n\n const reflowed = isNarrow && collapseMode === \"reflow\";\n const rootStyle: CSSProperties = {\n position: \"relative\",\n display: \"flex\",\n flexDirection: reflowed ? \"column\" : side === \"right\" ? \"row-reverse\" : \"row\",\n height: \"100%\",\n minHeight: 0,\n ...style,\n };\n\n return (\n <SidebarCtx.Provider\n value={{ collapsed: isNarrow, mode: collapseMode, side, width, open, setOpen }}\n >\n <div ref={ref} style={rootStyle} {...rest}>\n {children}\n </div>\n </SidebarCtx.Provider>\n );\n}\n\nfunction Sidebar({ style, children, ...rest }: HTMLAttributes<HTMLElement>) {\n const { collapsed, mode, side, width, open, setOpen } = useSidebar();\n ensureStyle(STYLE_ID, RULES);\n\n // Expanded: a fixed-width rail beside the content.\n if (!collapsed) {\n const border = `${tokens.borderWidth} solid ${tokens.border}`;\n return (\n <aside\n style={{\n width,\n flexShrink: 0,\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"0.125rem\",\n padding: \"0.5rem 0.5rem\",\n ...(side === \"right\" ? { borderLeft: border } : { borderRight: border }),\n ...style,\n }}\n {...rest}\n >\n {children}\n </aside>\n );\n }\n\n // Reflowed: a horizontal strip on top, content below.\n if (mode === \"reflow\") {\n return (\n <aside\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: \"0.25rem\",\n width: \"100%\",\n overflowX: \"auto\",\n padding: \"0.5rem 0.75rem\",\n borderBottom: `${tokens.borderWidth} solid ${tokens.border}`,\n ...style,\n }}\n {...rest}\n >\n {children}\n </aside>\n );\n }\n\n // Drawer: off-canvas overlay + scrim.\n const closed = side === \"right\" ? \"translateX(100%)\" : \"translateX(-100%)\";\n const drawerStyle: StyleWithVars = {\n position: \"absolute\",\n top: 0,\n bottom: 0,\n [side]: 0,\n width,\n maxWidth: \"85%\",\n overflowY: \"auto\",\n background: tokens.bgRaised,\n boxShadow: tokens.shadowLg,\n transform: open ? \"translateX(0)\" : closed,\n zIndex: 11,\n ...(side === \"right\"\n ? { borderLeft: `${tokens.borderWidth} solid ${tokens.border}` }\n : { borderRight: `${tokens.borderWidth} solid ${tokens.border}` }),\n ...style,\n };\n return (\n <>\n {open ? (\n <button\n type=\"button\"\n aria-label=\"Close sidebar\"\n className=\"nb-sidebar-scrim\"\n onClick={() => setOpen(false)}\n style={{\n position: \"absolute\",\n inset: 0,\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n background: \"rgba(0,0,0,0.32)\",\n zIndex: 10,\n }}\n />\n ) : null}\n {/* `inert` when closed removes the off-canvas rail from the tab order and\n the a11y tree (vs `aria-hidden`, which leaves focusables reachable). */}\n <aside className=\"nb-sidebar-drawer\" inert={!open} style={drawerStyle} {...rest}>\n {children}\n </aside>\n </>\n );\n}\n\nfunction Main({ style, children, ...rest }: HTMLAttributes<HTMLDivElement>) {\n return (\n <div style={{ flex: 1, minWidth: 0, minHeight: 0, overflowY: \"auto\", ...style }} {...rest}>\n {children}\n </div>\n );\n}\n\ninterface TriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Override the default hamburger glyph. */\n children?: ReactNode;\n}\n\n/**\n * Hamburger that opens the drawer. Renders only when collapsed in `drawer`\n * mode, and only when it can see a `SidebarLayout` context — so it's safe to\n * place anywhere inside the layout subtree (it no-ops elsewhere). Note: in v1\n * the context lives on `SidebarLayout` itself, so the trigger must sit inside\n * it (e.g. a toolbar in `Main`), not in a sibling `AppFrame.Header`.\n */\nfunction Trigger({ children, style, onClick, ...rest }: TriggerProps) {\n const ctx = useContext(SidebarCtx);\n if (!ctx?.collapsed || ctx.mode !== \"drawer\") return null;\n const { open, setOpen } = ctx;\n return (\n <button\n type=\"button\"\n aria-label=\"Toggle sidebar\"\n aria-expanded={open}\n onClick={(e) => {\n setOpen(!open);\n onClick?.(e);\n }}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 32,\n height: 32,\n border: \"none\",\n background: \"transparent\",\n color: tokens.fg,\n cursor: \"pointer\",\n borderRadius: tokens.radiusSm,\n ...style,\n }}\n {...rest}\n >\n {children ?? (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <path\n d=\"M2 4.5h14M2 9h14M2 13.5h14\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n )}\n </button>\n );\n}\n\n/** `SidebarLayout` with `.Sidebar`, `.Main`, and `.Trigger` slots. */\nexport const SidebarLayout = Object.assign(SidebarLayoutRoot, { Sidebar, Main, Trigger });\n"]}
|