@ai-matrx/design-system 0.86.334 → 0.86.336
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -68
- package/dist/carousel.cjs.map +1 -1
- package/dist/carousel.js +4 -4
- package/dist/{chunk-MFUNGDHO.js → chunk-B24DLFWR.js} +2 -2
- package/dist/{chunk-CSSD6NS4.js → chunk-DQUCOMAC.js} +2 -2
- package/dist/chunk-L5OACQXS.js +409 -0
- package/dist/chunk-L5OACQXS.js.map +1 -0
- package/dist/{chunk-6YZMGSQY.js → chunk-M34WPTPX.js} +2 -2
- package/dist/{chunk-7NEVJKDZ.js → chunk-MAMZGJJ3.js} +36 -7
- package/dist/chunk-MAMZGJJ3.js.map +1 -0
- package/dist/{chunk-VV6WZTH5.js → chunk-PBDQZPKV.js} +2 -2
- package/dist/{chunk-E4GS5QH7.js → chunk-Q2HWDJED.js} +2 -2
- package/dist/{chunk-ZOQ2XKXF.js → chunk-QOEKPR37.js} +5 -5
- package/dist/chunk-QOEKPR37.js.map +1 -0
- package/dist/{chunk-MEJVHDYJ.js → chunk-RGJPHRU3.js} +2 -2
- package/dist/{chunk-3MQMVPKO.js → chunk-VQ3G6AFN.js} +4 -4
- package/dist/{chunk-677JS6TX.js → chunk-WZC3K7SO.js} +75 -158
- package/dist/chunk-WZC3K7SO.js.map +1 -0
- package/dist/clipboard-fallback-dialog.cjs.map +1 -1
- package/dist/clipboard-fallback-dialog.js +1 -1
- package/dist/controls.cjs +4 -4
- package/dist/controls.cjs.map +1 -1
- package/dist/controls.css +6 -0
- package/dist/controls.js +4 -4
- package/dist/data-table/data-row-inspector.cjs.map +1 -1
- package/dist/data-table/data-row-inspector.js +4 -4
- package/dist/data-table/data-row-window.cjs.map +1 -1
- package/dist/data-table/data-row-window.js +5 -5
- package/dist/data-table/index.cjs +4 -4
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.js +7 -7
- package/dist/data-table/pagination.cjs +4 -4
- package/dist/data-table/pagination.cjs.map +1 -1
- package/dist/data-table/pagination.js +2 -2
- package/dist/data-table/uuid-cell.cjs.map +1 -1
- package/dist/data-table/uuid-cell.js +2 -2
- package/dist/desktop.cjs.map +1 -1
- package/dist/desktop.js +9 -8
- package/dist/desktop.js.map +1 -1
- package/dist/index.cjs +1508 -1187
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +24 -23
- package/dist/index.js.map +1 -1
- package/dist/item.cjs +646 -372
- package/dist/item.cjs.map +1 -1
- package/dist/item.d.cts +1 -3
- package/dist/item.d.ts +1 -3
- package/dist/item.js +26 -34
- package/dist/item.js.map +1 -1
- package/dist/lite-table.cjs.map +1 -1
- package/dist/lite-table.js +1 -1
- package/dist/menu-look.cjs +521 -36
- package/dist/menu-look.cjs.map +1 -1
- package/dist/menu-look.css +96 -1
- package/dist/menu-look.d.cts +320 -37
- package/dist/menu-look.d.ts +320 -37
- package/dist/menu-look.js +60 -121
- package/dist/menu-look.js.map +1 -1
- package/dist/record-list.cjs +533 -253
- package/dist/record-list.cjs.map +1 -1
- package/dist/record-list.js +4 -2
- package/dist/record-list.js.map +1 -1
- package/dist/settings.cjs.map +1 -1
- package/dist/settings.js +2 -2
- package/dist/writing-field.cjs.map +1 -1
- package/dist/writing-field.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-677JS6TX.js.map +0 -1
- package/dist/chunk-7NEVJKDZ.js.map +0 -1
- package/dist/chunk-ZOQ2XKXF.js.map +0 -1
- /package/dist/{chunk-MFUNGDHO.js.map → chunk-B24DLFWR.js.map} +0 -0
- /package/dist/{chunk-CSSD6NS4.js.map → chunk-DQUCOMAC.js.map} +0 -0
- /package/dist/{chunk-6YZMGSQY.js.map → chunk-M34WPTPX.js.map} +0 -0
- /package/dist/{chunk-VV6WZTH5.js.map → chunk-PBDQZPKV.js.map} +0 -0
- /package/dist/{chunk-E4GS5QH7.js.map → chunk-Q2HWDJED.js.map} +0 -0
- /package/dist/{chunk-MEJVHDYJ.js.map → chunk-RGJPHRU3.js.map} +0 -0
- /package/dist/{chunk-3MQMVPKO.js.map → chunk-VQ3G6AFN.js.map} +0 -0
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
MENU_LOOK_CLASS,
|
|
4
|
+
MenuLookRowBody
|
|
5
|
+
} from "./chunk-L5OACQXS.js";
|
|
2
6
|
import {
|
|
3
7
|
ARCHIVE_LABEL
|
|
4
8
|
} from "./chunk-VQQ3O7J5.js";
|
|
5
9
|
import {
|
|
6
10
|
ConfirmDialog
|
|
7
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-B24DLFWR.js";
|
|
8
12
|
import {
|
|
9
13
|
ErrorBox
|
|
10
14
|
} from "./chunk-HKLIRHT2.js";
|
|
@@ -16,7 +20,7 @@ import {
|
|
|
16
20
|
} from "./chunk-TDMVH77G.js";
|
|
17
21
|
import {
|
|
18
22
|
Button
|
|
19
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QOEKPR37.js";
|
|
20
24
|
import {
|
|
21
25
|
Tooltip,
|
|
22
26
|
TooltipContent,
|
|
@@ -203,7 +207,7 @@ function OrganizationPicker({
|
|
|
203
207
|
onSelect,
|
|
204
208
|
onToggleFavorite,
|
|
205
209
|
hideHeading = false,
|
|
206
|
-
|
|
210
|
+
look = "default",
|
|
207
211
|
foldedLabel = "More",
|
|
208
212
|
className,
|
|
209
213
|
more
|
|
@@ -227,7 +231,33 @@ function OrganizationPicker({
|
|
|
227
231
|
const isActive2 = org.id === activeOrganizationId;
|
|
228
232
|
const favorite = isFavorite(org.id);
|
|
229
233
|
return /* @__PURE__ */ jsxs2("li", { role: "none", className: "group/org relative flex items-center", children: [
|
|
230
|
-
/* @__PURE__ */
|
|
234
|
+
look === "menu" ? /* @__PURE__ */ jsx3(
|
|
235
|
+
"button",
|
|
236
|
+
{
|
|
237
|
+
type: "button",
|
|
238
|
+
role: "option",
|
|
239
|
+
"aria-selected": isActive2,
|
|
240
|
+
"aria-pressed": isActive2,
|
|
241
|
+
onClick: (event) => {
|
|
242
|
+
event.stopPropagation();
|
|
243
|
+
onSelect(org);
|
|
244
|
+
},
|
|
245
|
+
className: MENU_LOOK_CLASS.item,
|
|
246
|
+
"data-active": isActive2 ? "" : void 0,
|
|
247
|
+
"data-current": isActive2 ? "" : void 0,
|
|
248
|
+
"data-end-button": onToggleFavorite || favorite ? "" : void 0,
|
|
249
|
+
children: /* @__PURE__ */ jsx3(
|
|
250
|
+
MenuLookRowBody,
|
|
251
|
+
{
|
|
252
|
+
icon: /* @__PURE__ */ jsx3(OrganizationMark, { id: org.id, name: org.name, abbreviation: org.abbreviation, size: 16 }),
|
|
253
|
+
label: org.name,
|
|
254
|
+
description: sharesItsName(org) && org.distinguisher ? org.distinguisher : void 0,
|
|
255
|
+
trail: org.detail ?? void 0,
|
|
256
|
+
current: isActive2
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
) : /* @__PURE__ */ jsxs2(
|
|
231
261
|
"button",
|
|
232
262
|
{
|
|
233
263
|
type: "button",
|
|
@@ -240,8 +270,7 @@ function OrganizationPicker({
|
|
|
240
270
|
},
|
|
241
271
|
className: cn(
|
|
242
272
|
"flex w-full min-w-0 items-center gap-2.5 rounded-md py-1.5 pl-2 pr-8 text-left text-sm text-foreground transition-colors hover:bg-accent",
|
|
243
|
-
isActive2 && "bg-primary/10 font-semibold text-primary-ink ring-1 ring-inset ring-primary/30 hover:bg-primary/15"
|
|
244
|
-
itemClassName
|
|
273
|
+
isActive2 && "bg-primary/10 font-semibold text-primary-ink ring-1 ring-inset ring-primary/30 hover:bg-primary/15"
|
|
245
274
|
),
|
|
246
275
|
"data-active": isActive2 ? "" : void 0,
|
|
247
276
|
children: [
|
|
@@ -735,4 +764,4 @@ export {
|
|
|
735
764
|
CanvasLayout,
|
|
736
765
|
ModeSwitch
|
|
737
766
|
};
|
|
738
|
-
//# sourceMappingURL=chunk-
|
|
767
|
+
//# sourceMappingURL=chunk-MAMZGJJ3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/confirm-host.tsx","../src/archived-disclosure.tsx","../src/organization-picker.tsx","../src/app-shell/status-dot.tsx","../src/app-shell/app-rail.tsx","../src/resizable.tsx","../src/app-shell/canvas.tsx","../src/app-shell/mode-switch.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * `<ConfirmDialogHost />` — render ONCE, near the root of every provider tree,\n * so the imperative `confirm()` always has a live host to dispatch to.\n *\n * THE SPLIT (census row 19i, 2026-09-07). The confirm system is two halves in\n * two packages, on purpose:\n *\n * `@ai-matrx/kit/confirm-opener` the OPENER — `confirm()`, the host\n * registry, the request queue. Pure TS: zero\n * React, zero markup, zero CSS. Statically\n * importable from a Redux thunk, a util, a\n * sync handler — hundreds of call sites at\n * near-zero bundle cost.\n * `@ai-matrx/design-system` the BODY — this host and `ConfirmDialog`,\n * built on the package AlertDialog so the\n * surface gets the shipped motion layer and\n * the themed scrim instead of the host-plugin\n * classes and the hardcoded black scrim\n * kit could neither style nor animate.\n *\n * Design-system depends on kit, so this direction is the acyclic one; kit\n * re-exports nothing of the body. A consumer mounts `<ConfirmDialogHost />`\n * from here and calls `confirm()` from there — the two find each other through\n * the opener's `Symbol.for(\"ai-matrx.kit.confirm-opener-state\")` globalThis\n * slot, which is deliberately NOT a module-level variable: with unsplit dual\n * ESM/CJS bundles each loader graph instantiates its own module, and a module\n * local would silently split host registration from callers. Never \"clean that\n * up\".\n *\n * Pre-mount `confirm()` calls queue inside the opener and resolve as soon as\n * this host registers — a destructive action triggered in the first ~50ms after\n * load still gets a real confirmation, never a silent default-yes/no.\n *\n * NO FRAMEWORK IMPORT. The matrx-frontend original split shell + impl and\n * loaded the impl through `next/dynamic({ ssr: false })` to keep radix out of\n * route entry chunks. A framework-agnostic package cannot do that, so this is\n * ONE directly-imported component; hosts that want the code-splitting lazy-load\n * it themselves:\n * `dynamic(() => import(\"@ai-matrx/design-system\").then(m => m.ConfirmDialogHost), { ssr: false })`\n * The \"render `<ConfirmDialogHost/>` once\" contract is unchanged either way.\n *\n * Imperative model: calls to `confirm(...)` push a request into the opener's\n * queue; `useOpenerHost` (`@ai-matrx/kit/opener-react`) drains it one at a time\n * and this component renders a `<ConfirmDialog>` for the active request. The promise resolves `true` on Confirm, `false` on\n * cancel/dismiss. The dialog closes immediately on click — callers that need an\n * in-dialog busy spinner during async work use the inline `<ConfirmDialog>`\n * with the `busy` prop instead.\n */\n\nimport { confirmOpener } from \"@ai-matrx/kit/confirm-opener\";\nimport { useOpenerHost } from \"@ai-matrx/kit/opener-react\";\nimport * as React from \"react\";\n\nimport { ConfirmDialog } from \"./confirm-dialog\";\n\nexport function ConfirmDialogHost() {\n // The registration, the ref-backed queue, the drain effect and the\n // settle-once callback are ALL `useOpenerHost` (kit 0.10.0). They used to be\n // written out here — and identically in three matrx-frontend dialog hosts,\n // which is exactly the duplication the opener primitive ends. What is left\n // below is the only part that was ever this package's: the dialog body.\n // `shown`, not `request`: the dialog animates out AFTER it is answered, and\n // `request` is already null by then — the body used to fade out empty\n // (reviewer, 2026-10-02). `shown` keeps the answered words until the next\n // question replaces them.\n const { shown, open, settle } = useOpenerHost(confirmOpener);\n\n // `ready` (kit 0.22.0): Confirm is held until the question can say what it\n // will do. Settling either way releases it — a failed read never traps the\n // person. Keyed by the request object, so the next question starts held.\n const [readyFor, setReadyFor] = React.useState<object | null>(null);\n const ready = shown?.ready;\n React.useEffect(() => {\n if (!shown || !ready) return undefined;\n let live = true;\n const release = () => {\n if (live) setReadyFor(shown);\n };\n Promise.resolve(ready).then(release, release);\n return () => {\n live = false;\n };\n }, [shown, ready]);\n const held = !!ready && readyFor !== shown;\n\n const handleConfirm = React.useCallback(() => settle(true), [settle]);\n const handleOpenChange = React.useCallback(\n (next: boolean) => {\n // Any dismiss (Esc / backdrop / Cancel) is a \"no\" — never a silent yes.\n if (!next) settle(false);\n },\n [settle],\n );\n\n return (\n <ConfirmDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={shown?.title ?? \"\"}\n description={shown?.description}\n confirmLabel={shown?.confirmLabel}\n cancelLabel={shown?.cancelLabel}\n variant={shown?.variant}\n confirmHeld={held}\n onConfirm={handleConfirm}\n />\n );\n}\n","\"use client\";\n\n/**\n * ArchivedDisclosure — THE ARCHIVED-ITEMS LAW, card-list half.\n * (`common-docs/policies/archived-items.md`, Arman 2026-09-09.)\n *\n * Every list over an entity that can be archived carries an archive control,\n * it defaults to HIDING archived rows, and revealing them is one or two\n * clicks — on the surface itself. There are exactly TWO implementations of\n * that control in the platform, and both live in THIS package:\n *\n * • `ArchiveFilter` — the tri-state segmented control (Active only /\n * Archived only / Active + archived) for table and browse surfaces whose\n * reader takes an archive parameter. Prefer it whenever the surface can\n * express the request server-side.\n * • `ArchivedDisclosure` — THIS component: a one-click \"Archived (N)\"\n * disclosure, closed by default, revealing the archived rows in place\n * underneath. For card lists, panels and pickers that are not table\n * shaped.\n *\n * Never invent a third. The disclosure was proven first in matrx-frontend's\n * Transcript Studio, lived as `components/official/ArchivedDisclosure` there,\n * and moved here (0.14.0) verbatim so every client inherits the same control\n * instead of re-growing it per app.\n *\n * Both controls share one vocabulary: `ARCHIVE_LABEL` is the single noun, and\n * `archiveFilterFromDisclosure(open)` says a disclosure's state in the\n * tri-state words for a host whose toggle IS a server request.\n *\n * Two shapes, one primitive:\n *\n * <ArchivedDisclosure count={n} open={open} onOpenChange={setOpen}>\n * …archived rows…\n * </ArchivedDisclosure>\n *\n * renders the button AND the revealed block. Omit `children` when the caller\n * merges the archived rows into an existing table/grid itself — the button is\n * then the whole control.\n *\n * The count is ALWAYS the true number of archived rows the surface holds. A\n * screen never lies: when there is nothing archived the control renders\n * nothing at all rather than an empty promise. A surface whose archive view is\n * a SERVER request (the rows below the button are the archived page itself,\n * not children of it) passes `keepWhileOpen` so the revealed view never loses\n * its way back.\n *\n * `countLabel` exists for the one case a bare integer cannot tell the truth: a\n * server-side count that hit its cap (render `\"12+\"`), or a count that has not\n * landed yet (pass `null` and no parenthetical is printed at all).\n */\n\nimport * as React from \"react\";\n\nimport { ARCHIVE_LABEL } from \"./archive-filter\";\nimport { cn } from \"./cn\";\nimport { ArchiveIcon, ChevronDownIcon, ChevronRightIcon } from \"./icons\";\n\n/** What every archive on this platform promises, said once (the noun voice opens with it). */\nexport const ARCHIVED_NEVER_DESTROYED =\n \"Archiving never destroys anything. What you put away waits here until somebody brings it back.\";\n\nexport interface ArchivedDisclosureProps {\n /**\n * True number of archived rows this surface holds. 0 renders nothing. Absent = not read yet:\n * the control still draws (a count nobody has read is not a reason to hide the way in) and no\n * parenthetical is printed — a \"(0)\" the screen guessed would be a lie.\n */\n count?: number | undefined;\n /** Whether archived rows are revealed (controlled). Omit to let the control hold it itself. */\n open?: boolean | undefined;\n /** Uncontrolled only: open on first render (the address asked for the archive). */\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n /**\n * The archived rows. Omit when the host merges them into its own list and\n * only needs the toggle.\n */\n children?: React.ReactNode;\n /** Noun for the rows, so the button reads in the surface's own words. */\n label?: string;\n /**\n * THE NOUN VOICE: the archived things in the plural (\"portals\", \"pick lists\"). The button then\n * says \"Show archived portals (3)\" / \"Hide archived portals\", and the revealed block opens with\n * {@link ARCHIVED_NEVER_DESTROYED} (override with `note`). Takes precedence over `label`.\n */\n noun?: string | undefined;\n /** A line at the top of the revealed block. `null` = none. Default: the noun voice's promise, else none. */\n note?: React.ReactNode;\n /**\n * Override the parenthetical. A string replaces the number (`\"12+\"` for a\n * capped server count); `null` prints no parenthetical at all, for a count\n * that has not arrived yet. Omit it and the honest `count` is printed.\n */\n countLabel?: string | null;\n /**\n * Keep the control rendered while `open` even at `count === 0`. For surfaces\n * where opening SWITCHES the list to the archive (a server-side filter)\n * rather than nesting rows inside this component: without it the way back\n * would vanish the moment the count read zero or had not landed.\n */\n keepWhileOpen?: boolean;\n /**\n * Draw the way in even when the count reads 0 — the revealed block then says the archive is\n * empty in its own words (a rail whose archive is a sentence, never a blank). Default: on in\n * the noun voice, off otherwise. A 0 is never printed as \"(0)\" in the noun voice.\n */\n showWhenEmpty?: boolean;\n className?: string | undefined;\n contentClassName?: string;\n}\n\nexport function ArchivedDisclosure({\n count,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n children,\n label = ARCHIVE_LABEL,\n noun,\n note,\n countLabel,\n keepWhileOpen = false,\n showWhenEmpty,\n className,\n contentClassName,\n}: ArchivedDisclosureProps) {\n const [ownOpen, setOwnOpen] = React.useState(defaultOpen);\n const open = openProp ?? ownOpen;\n // Nothing archived: an empty promise, so render nothing — unless this\n // surface's open state IS the archive view, whose way back must never vanish.\n const drawEmpty = showWhenEmpty ?? noun !== undefined;\n if (count !== undefined && count <= 0 && !drawEmpty && !(open && keepWhileOpen)) return null;\n const toggle = () => {\n const next = !open;\n if (openProp === undefined) setOwnOpen(next);\n onOpenChange?.(next);\n };\n const parenthetical =\n countLabel !== undefined ? countLabel : count === undefined || (noun !== undefined && count <= 0) ? null : String(count);\n const words = noun ? `${open ? \"Hide\" : \"Show\"} archived ${noun}` : label;\n const shownNote = note !== undefined ? note : noun ? ARCHIVED_NEVER_DESTROYED : null;\n return (\n <div className={cn(\"min-w-0\", className)} data-slot=\"archived-disclosure\">\n <button\n type=\"button\"\n onClick={toggle}\n aria-expanded={open}\n data-slot=\"archived-disclosure-toggle\"\n className=\"flex w-full items-center gap-2 rounded-lg px-2 py-2 text-sm text-muted-foreground hover:bg-accent active:bg-accent\"\n >\n {open ? (\n <ChevronDownIcon className=\"h-4 w-4 shrink-0\" />\n ) : (\n <ChevronRightIcon className=\"h-4 w-4 shrink-0\" />\n )}\n <ArchiveIcon className=\"h-4 w-4 shrink-0\" />\n <span className=\"truncate\">\n {parenthetical === null ? words : `${words} (${parenthetical})`}\n </span>\n </button>\n {open && (children || shownNote) ? (\n <div className={cn(\"mt-1\", contentClassName)}>\n {shownNote ? <p className=\"px-2 pb-2 text-xs text-muted-foreground\">{shownNote}</p> : null}\n {children}\n </div>\n ) : null}\n </div>\n );\n}\n\nexport default ArchivedDisclosure;\n","\"use client\";\n\n/**\n * OrganizationPicker — THE ONE \"which organization am I acting in\" control,\n * identical on every Matrx surface (the main app's user menu and header nudge,\n * Workflow Studio's sidebar, the admin dashboard's settings).\n *\n * Ported from matrx-frontend `features/organizations/components/\n * OrganizationPickerPanel.tsx` + `UserMenuOrgSection.tsx` + `DefaultOrgSwitch.tsx`\n * (2026-09-08), which until then were the ONLY surfaces with the full picker;\n * Studio and the dashboard each had a bare `<Select>` with different copy,\n * different placement and no default control. Three UIs for one fact.\n *\n * THE ACTIVE ROW IS THE ANSWER (owner, 2026-10-01). The active organization is\n * the highlighted row — tinted, bold, ringed and checked — and nothing else:\n * the \"Working in …\" sentence above the list is gone (\"It should be\n * highlighted and clear\"), and so is the \"Keep it at the top\" switch.\n *\n * FAVORITES (owner, 2026-10-01: \"add a star you can click to favorite any of\n * them\"). Every row carries its own star; a person favorites as many as they\n * like, and favorites are drawn first. The star never selects the row — it is\n * a sibling button, not part of the row — and it picks no organization for\n * anyone: which organization you are working in is this device's own\n * remembered choice (the host's resolver), never a star.\n *\n * 🚨 A HUNDRED ROWS IS NOT A LIST (VERIFIER-8 MEDIUM-3, 2026-09-21).\n * The first screen of the data product offered the admin account's 116\n * organizations nine at a time, with no search, most of them lane fixtures.\n * Three things answer that, and all three are here rather than in one host:\n * • SEARCH over name and abbreviation, once the list passes eight rows.\n * • TEST ORGANIZATIONS HIDDEN by default behind the platform's one\n * archive-style disclosure (`ArchivedDisclosure`), with their count always\n * on screen. Hidden, never dropped.\n * • THE PERSON'S OWN organizations drawn first, under the starred one.\n * The host classifies (`isTestFixture`, `isOwn`); this component decides\n * nothing about a name it is given.\n *\n * Seam inversions from the origin: lucide `Check`/`Star` become package\n * SVGs (C19); the host `Switch` becomes this package's; `cn` is local.\n */\n\nimport * as React from \"react\";\n\nimport { ArchivedDisclosure } from \"./archived-disclosure\";\nimport { cn } from \"./cn\";\nimport { ErrorBox } from \"./error-box\";\nimport { CheckIcon, StarIcon } from \"./icons\";\nimport { Input } from \"./input\";\nimport { Skeleton } from \"./skeleton\";\nimport { Button } from \"./controls/controls\";\nimport { MENU_LOOK_CLASS, MenuLookRowBody } from \"./menu-look\";\n\n/**\n * Above this many rows the list stops being something a person reads and\n * starts being something they hunt through, so the search box appears. Below\n * it a search box is one more control over a list the eye already took in.\n */\nconst SEARCH_APPEARS_ABOVE = 8;\n\n/**\n * Case-insensitive substring over the two things a person actually types. Exported once: every\n * organization picker (this one, the desktop sheet) searches the same way.\n */\nexport function matchesOrganizationQuery(org: Pick<OrganizationPickerOrganization, \"name\" | \"abbreviation\">, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n if (org.name.toLowerCase().includes(q)) return true;\n const abbreviation = org.abbreviation?.trim().toLowerCase();\n return !!abbreviation && abbreviation.includes(q);\n}\n\nexport interface OrganizationPickerOrganization {\n id: string;\n name: string;\n /** Database-validated 2–3 uppercase letters. Optional — not every report carries it. */\n abbreviation?: string | null;\n /**\n * THE ADDRESS, for when the NAME is not enough — its slug, or whatever else the\n * host has that tells two of them apart.\n *\n * 🚨 WHY (crew D2, 2026-09-21). Two organizations called \"Kessler Lab for Applied\n * Microbial Ecology\" and two called \"Wraithmoor Regional Museum of Art & Craft\" sat\n * in one list, identical down to the abbreviation tile, and a person had no way of\n * knowing which one they were about to work in. The list drew the name and nothing\n * else, so there was nothing for it to draw.\n *\n * It is shown ONLY on the rows whose name another row in the list also carries —\n * the way Slack shows a workspace's URL and Google shows the account's email, and\n * only where it settles the question. A list of distinct names stays exactly as it\n * was, because a second line under every row is noise a person learns to skip.\n */\n distinguisher?: string | null;\n /**\n * This organization is a TEST FIXTURE — a lane's scratch organization, not a\n * business anybody works in. Classified in `iam.organizations.settings`\n * (`test_fixture`), never guessed from its name.\n *\n * 🚨 WHY (VERIFIER-8 MEDIUM-3, 2026-09-21). The admin account belongs to 116\n * organizations and 59 of them are fixtures. The first screen of the data\n * product offered all of them, nine at a time, with no search — so the two\n * or three a person actually works in were buried under lane debris. The\n * archived-items law already answers this shape everywhere else in the\n * platform: hide by default, ONE disclosure to reveal, and the count of what\n * is hidden is always on screen. It is hidden, never dropped: a fixture the\n * person genuinely wants is one click away.\n */\n isTestFixture?: boolean;\n /**\n * The signed-in person created this organization. Drawn before the rest,\n * under the starred one — the same reason Slack puts your own workspace\n * first: in a list of a hundred, yours must not be something you search for.\n */\n isOwn?: boolean;\n /**\n * A short trailing label for the row — what a click does or the row's state\n * (\"Open\", \"Finish setup\", \"Turn on HR\"). Muted text, right-aligned; the row\n * stays one button. Omitted, the row is exactly as before.\n */\n detail?: string | null;\n /**\n * Fold this row behind the host's second disclosure (`foldedLabel`) — for rows\n * the person rarely came for (organizations without HR). Hidden, counted,\n * one click away; a search that matches only folded rows opens the fold.\n */\n folded?: boolean;\n}\n\n/**\n * THE LIST IS A PAGE (bounded organizations, 2026-10-16). A person in hundreds of organizations\n * (an agency with a client organization each) is never sent all of them: the host passes the\n * first page and this. The box then always shows; every keystroke goes to `onQueryChange` and the\n * host answers with the matching rows from its FULL list (server-side), which are drawn as given —\n * no second local filter. \"Show more\" appears while `hasMore`.\n */\nexport interface OrganizationPickerMore {\n onQueryChange: (query: string) => void;\n /** More rows exist past these, for the current query. */\n hasMore: boolean;\n onLoadMore: () => void;\n loadingMore?: boolean;\n /** How many the person has in all, for the current query. */\n total?: number;\n}\n\nexport interface OrganizationPickerProps {\n organizations: readonly OrganizationPickerOrganization[];\n /** The list is the first page of a longer one; omit when it is the whole list. */\n more?: OrganizationPickerMore;\n /** The organization the person is acting in right now; null = nothing chosen. */\n activeOrganizationId: string | null;\n /** The person's favorite organizations, drawn first and starred. */\n favoriteOrganizationIds?: readonly string[];\n loading?: boolean;\n /** Memberships could not be read. The panel says so instead of showing an empty list. */\n loadFailed?: boolean;\n /** Choose the active organization. Hosts persist + refetch here. */\n onSelect: (organization: OrganizationPickerOrganization) => void;\n /**\n * Favorite (true) or unfavorite (false) one organization. Omit to draw no\n * star buttons — a host with no write path must not show a control that\n * does nothing (a favorite is still marked, read-only).\n */\n onToggleFavorite?: ((organizationId: string, favorite: boolean) => void) | undefined;\n /** Hide the \"Organization\" eyebrow when the host already labels the section. */\n hideHeading?: boolean;\n /**\n * `\"menu\"`: the rows are the one menu look's rows (`cm-item`: a 16px mark in the icon slot, the name,\n * the active one marked by a check at its END) — the picker inside a menu-look panel (the account\n * rail's organization menu). Default: the picker's own rows.\n */\n look?: \"default\" | \"menu\";\n /** The noun on the disclosure that holds `folded` rows. Default \"More\". */\n foldedLabel?: string;\n className?: string;\n}\n\n/**\n * An organization's color — one of a fixed set of hues, chosen from its id so\n * the same organization wears the same color on every surface and every\n * device. Color tells organizations apart at a glance; the letters still say\n * which one (owner, 2026-10-01: \"a bit of color for the logos\").\n */\nconst ORGANIZATION_HUES = [217, 262, 330, 12, 32, 152, 189, 290] as const;\nexport function organizationColor(seed: string): { background: string; color: string } {\n let hash = 0;\n for (let index = 0; index < seed.length; index += 1) {\n hash = (hash * 31 + seed.charCodeAt(index)) >>> 0;\n }\n const hue = ORGANIZATION_HUES[hash % ORGANIZATION_HUES.length];\n return { background: `hsl(${hue} 62% 46%)`, color: \"#fff\" };\n}\n\n/**\n * THE organization mark — its own logo when it has one, otherwise its 2–3\n * letter abbreviation on its color tile (the first letter of the name when the\n * report has no abbreviation, so a tile is never empty). Three letters get a\n * smaller face than two so they fit the tile. Every Matrx surface draws this.\n */\nexport function OrganizationMark({\n id,\n name,\n abbreviation,\n logoUrl,\n size = 20,\n className,\n}: {\n /** Seeds the color; the name is used when absent. */\n id?: string | null | undefined;\n name: string;\n abbreviation?: string | null | undefined;\n logoUrl?: string | null | undefined;\n size?: number;\n className?: string | undefined;\n}) {\n const box = { width: size, height: size };\n if (logoUrl) {\n return (\n <span\n style={box}\n className={cn(\"relative inline-flex shrink-0 overflow-hidden rounded-md bg-muted\", className)}\n data-slot=\"organization-mark\"\n >\n <img src={logoUrl} alt={name} className=\"h-full w-full object-cover\" />\n </span>\n );\n }\n const letters = ((abbreviation && abbreviation.trim()) || name.trim().slice(0, 1) || \"?\")\n .slice(0, 3)\n .toUpperCase();\n const fontSize = Math.round(size * (letters.length >= 3 ? 0.36 : 0.44));\n return (\n <span\n style={{ ...box, ...organizationColor(id || name), fontSize }}\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-md font-bold leading-none tracking-tight\",\n className,\n )}\n aria-label={`Organization abbreviation ${letters}`}\n title={letters}\n data-slot=\"organization-mark\"\n >\n {letters}\n </span>\n );\n}\n\n/**\n * THE ORDER every organization list uses: the ACTIVE organization (where the person is working, and\n * where new things go by default), then their favorites, then their OWN organizations, then everything\n * else. Inside each band the host's order is kept exactly as given — this reorders bands, it never sorts\n * names. Exported once for every picker (this one, the desktop sheet).\n */\nexport function orderOrganizationsForPicker<T extends { id: string; isOwn?: boolean | undefined }>(\n organizations: readonly T[],\n favoriteOrganizationIds: readonly string[],\n activeOrganizationId: string | null = null,\n): T[] {\n const favorites = new Set(favoriteOrganizationIds);\n const rank = (org: T) => (org.id === activeOrganizationId ? -1 : favorites.has(org.id) ? 0 : org.isOwn ? 1 : 2);\n return [...organizations].sort((a, b) => rank(a) - rank(b));\n}\n\nexport function OrganizationPicker({\n organizations,\n activeOrganizationId,\n favoriteOrganizationIds = [],\n loading = false,\n loadFailed = false,\n onSelect,\n onToggleFavorite,\n hideHeading = false,\n look = \"default\",\n foldedLabel = \"More\",\n className,\n more,\n}: OrganizationPickerProps) {\n const [query, setQuery] = React.useState(\"\");\n const [showFixtures, setShowFixtures] = React.useState(false);\n const [showFolded, setShowFolded] = React.useState(false);\n\n const favorites = new Set(favoriteOrganizationIds);\n const isFavorite = (id: string) => favorites.has(id);\n /**\n * THE ORDER, and it is the whole point of this control on an account with a\n * hundred memberships: the person's favorites, then their OWN organizations,\n * then everything else. Inside each band the host's order is kept exactly as\n * given — this reorders bands, it never sorts names.\n */\n const ordered = orderOrganizationsForPicker(organizations, favoriteOrganizationIds, activeOrganizationId);\n\n // A paged host already answered the query from its full list; filtering again would drop its\n // slug matches.\n const matching = more ? ordered : ordered.filter((org) => matchesOrganizationQuery(org, query));\n // The ACTIVE organization is always in the main list, first: a test organization the person is working in\n // is never behind the \"Test organizations\" disclosure, and a folded one is never behind \"More\".\n const isActive = (org: OrganizationPickerOrganization) => org.id === activeOrganizationId;\n const listed = matching.filter((org) => isActive(org) || (!org.isTestFixture && !org.folded));\n const folded = matching.filter((org) => !isActive(org) && !org.isTestFixture && org.folded);\n const fixtures = matching.filter((org) => !isActive(org) && org.isTestFixture);\n // The fold opens by itself when it is all there is, or when a search found\n // something inside it — a match is never hidden behind a closed disclosure.\n const foldOpen =\n showFolded || (folded.length > 0 && (listed.length === 0 || query.trim().length > 0));\n // Same rule for the test organizations: when they are ALL the person has\n // (an account whose only workspace is a test fixture) the disclosure opens by\n // itself — a collapsed group holding the only choice reads as \"no workspace\"\n // (feedback 6717c61d: \"An organization is needed\" with the one workspace\n // hidden under \"Test organizations (n)\").\n const fixturesOpen =\n showFixtures ||\n (fixtures.length > 0 &&\n listed.length === 0 &&\n folded.length === 0 &&\n query.trim().length === 0);\n const searchable = Boolean(more) || organizations.length > SEARCH_APPEARS_ABOVE;\n /**\n * Which display names appear more than once in THIS list — the only rows where the\n * second line earns its space. Computed from the list itself, so the answer is right\n * for the person looking at it rather than for organizations they cannot see.\n */\n const sharesItsName = (org: OrganizationPickerOrganization) =>\n organizations.filter((other) => other.name.trim() === org.name.trim()).length > 1;\n\n const renderRow = (org: OrganizationPickerOrganization) => {\n const isActive = org.id === activeOrganizationId;\n const favorite = isFavorite(org.id);\n return (\n <li key={org.id} role=\"none\" className=\"group/org relative flex items-center\">\n {look === \"menu\" ? (\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n aria-pressed={isActive}\n onClick={(event) => {\n event.stopPropagation();\n onSelect(org);\n }}\n className={MENU_LOOK_CLASS.item}\n data-active={isActive ? \"\" : undefined}\n data-current={isActive ? \"\" : undefined}\n data-end-button={onToggleFavorite || favorite ? \"\" : undefined}\n >\n <MenuLookRowBody\n icon={<OrganizationMark id={org.id} name={org.name} abbreviation={org.abbreviation} size={16} />}\n label={org.name}\n description={sharesItsName(org) && org.distinguisher ? org.distinguisher : undefined}\n trail={org.detail ?? undefined}\n current={isActive}\n />\n </button>\n ) : (\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n aria-pressed={isActive}\n onClick={(event) => {\n // Inside a host menu the click must not also close/route the menu.\n event.stopPropagation();\n onSelect(org);\n }}\n className={cn(\n \"flex w-full min-w-0 items-center gap-2.5 rounded-md py-1.5 pl-2 pr-8 text-left text-sm text-foreground transition-colors hover:bg-accent\",\n isActive && \"bg-primary/10 font-semibold text-primary-ink ring-1 ring-inset ring-primary/30 hover:bg-primary/15\",\n )}\n data-active={isActive ? \"\" : undefined}\n >\n <OrganizationMark id={org.id} name={org.name} abbreviation={org.abbreviation} size={20} />\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate\">{org.name}</span>\n {/* Only where the name does not settle it — see `distinguisher`. */}\n {sharesItsName(org) && org.distinguisher ? (\n <span className=\"truncate text-[10px] font-normal text-muted-foreground\">\n {org.distinguisher}\n </span>\n ) : null}\n </span>\n {org.detail ? (\n <span\n className=\"shrink-0 text-xs font-normal text-muted-foreground\"\n data-slot=\"organization-picker-detail\"\n >\n {org.detail}\n </span>\n ) : null}\n {isActive && (\n <CheckIcon className=\"h-[15px] w-[15px] shrink-0 text-primary-ink\" />\n )}\n </button>\n )}\n {/* THE STAR — its own button beside the row, never part of it: a star\n favorites, it never selects. Shown on hover/focus, always shown\n while favorited. Read-only (a mark) when the host has no write. */}\n {onToggleFavorite ? (\n <button\n type=\"button\"\n aria-pressed={favorite}\n aria-label={favorite ? `Remove ${org.name} from favorites` : `Add ${org.name} to favorites`}\n title={favorite ? \"Remove from favorites\" : \"Add to favorites\"}\n onClick={(event) => {\n event.stopPropagation();\n onToggleFavorite(org.id, !favorite);\n }}\n className={cn(\n \"absolute right-1 flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100\",\n favorite ? \"opacity-100\" : \"opacity-0 group-hover/org:opacity-100\",\n )}\n data-slot=\"organization-picker-favorite\"\n >\n <StarIcon\n className={cn(\"h-[14px] w-[14px]\", favorite && \"fill-warning text-warning-ink\")}\n />\n </button>\n ) : favorite ? (\n <StarIcon\n className=\"absolute right-2 h-[13px] w-[13px] fill-warning text-warning-ink\"\n aria-hidden={false}\n aria-label=\"Favorite\"\n role=\"img\"\n />\n ) : null}\n </li>\n );\n };\n\n return (\n <div className={cn(\"flex flex-col\", className)} data-slot=\"organization-picker\">\n {!hideHeading && (\n <p className=\"px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Organization\n </p>\n )}\n\n {loading ? (\n <div className=\"space-y-1 px-1 py-1\" aria-busy=\"true\" aria-label=\"Loading organizations\">\n <Skeleton className=\"h-7 rounded-md\" />\n <Skeleton className=\"h-7 rounded-md\" />\n </div>\n ) : loadFailed ? (\n <ErrorBox\n className=\"px-2 py-2 text-xs text-destructive-ink\"\n operation=\"Load your organizations\"\n origin=\"design-system/OrganizationPicker\"\n >\n Could not load organizations.\n </ErrorBox>\n ) : organizations.length === 0 && !(more && query.trim()) ? (\n <p className=\"px-2 py-2 text-xs text-muted-foreground\">\n Your account is not a member of any organization. Ask an administrator to add you to one.\n </p>\n ) : (\n <>\n {/* SEARCH. A list a person scrolls nine rows at a time is not a\n control, it is a filing cabinet (VERIFIER-8 MEDIUM-3). Name and\n abbreviation, case-insensitive substring; an empty box is exactly\n the list that was there before. */}\n {searchable && (\n <div className=\"px-2 pb-1.5\">\n <Input\n type=\"search\"\n value={query}\n onChange={(event) => {\n setQuery(event.target.value);\n more?.onQueryChange(event.target.value);\n }}\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n placeholder=\"Search organizations\"\n aria-label=\"Search organizations by name or abbreviation\"\n className=\"h-8 text-sm\"\n data-slot=\"organization-picker-search\"\n />\n </div>\n )}\n\n {listed.length === 0 && folded.length === 0 && fixtures.length === 0 ? (\n <p\n className=\"px-2 py-2 text-xs text-muted-foreground\"\n data-slot=\"organization-picker-no-match\"\n >\n No organization matches “{query.trim()}”.\n </p>\n ) : listed.length === 0 && folded.length > 0 ? null : listed.length === 0 ? (\n /* THE ARCHIVED-ITEMS LAW, honesty half: \"nothing\" may only be said\n when both halves are empty. Here the other half is one line down.\n AND IT SAYS WHAT IS TRUE, NOT WHAT IS EMPTY. The earlier sentence\n read \"Nothing matches “X” outside the test organizations below\" —\n which opens by negating the very rows sitting one click away, and\n `fixtures` IS query-filtered, so those rows ARE matches for X. A\n person reading \"nothing matches\" retypes their search instead of\n clicking. So: count the matches, say where they are, and carry\n the click that reveals them — the same shape as the honest\n empty-filter twin one line down. (TAILS-3) */\n <p\n className=\"px-2 py-2 text-xs text-muted-foreground\"\n data-slot=\"organization-picker-only-fixtures\"\n >\n {query.trim() ? (\n <>\n {fixtures.length === 1\n ? `1 match for “${query.trim()}” is in your test organizations`\n : `All ${fixtures.length} matches for “${query.trim()}” are in your test organizations`}\n {showFixtures ? (\n \", listed below.\"\n ) : (\n <>\n {\" — \"}\n <button\n type=\"button\"\n className=\"underline underline-offset-2 hover:text-foreground\"\n data-slot=\"organization-picker-show-fixtures\"\n onClick={(event) => {\n event.stopPropagation();\n setShowFixtures(true);\n }}\n >\n show them\n </button>\n .\n </>\n )}\n </>\n ) : (\n `Every organization you belong to is a test organization — all ${fixtures.length} are below.`\n )}\n </p>\n ) : (\n <ul className=\"max-h-72 overflow-y-auto\" role=\"listbox\" aria-label=\"Organizations\">\n {listed.map(renderRow)}\n {more?.hasMore && (\n <li role=\"none\">\n <Button\n type=\"button\"\n variant=\"quiet\"\n className=\"w-full justify-start\"\n disabled={more.loadingMore}\n onClick={(event) => {\n event.stopPropagation();\n more.onLoadMore();\n }}\n data-slot=\"organization-picker-more\"\n >\n {more.loadingMore\n ? \"Loading more…\"\n : more.total !== undefined\n ? `Show more (${organizations.length} of ${more.total})`\n : \"Show more\"}\n </Button>\n </li>\n )}\n </ul>\n )}\n\n {/* THE HOST'S FOLD — rows it marked `folded`, counted, one click away. */}\n <ArchivedDisclosure\n count={folded.length}\n open={foldOpen}\n onOpenChange={setShowFolded}\n label={foldedLabel}\n className=\"mt-0.5\"\n >\n <ul className=\"max-h-72 overflow-y-auto\" role=\"listbox\" aria-label={foldedLabel}>\n {folded.map(renderRow)}\n </ul>\n </ArchivedDisclosure>\n\n {/* THE TEST ORGANIZATIONS, behind the platform's ONE archive-style\n disclosure (`ArchivedDisclosure`, the archived-items law). Hidden\n by default, counted out loud, one click away — never silently\n dropped. */}\n <ArchivedDisclosure\n count={fixtures.length}\n open={fixturesOpen}\n onOpenChange={setShowFixtures}\n label=\"Test organizations\"\n className=\"mt-0.5\"\n >\n <ul\n className=\"max-h-72 overflow-y-auto\"\n role=\"listbox\"\n aria-label=\"Test organizations\"\n >\n {fixtures.map(renderRow)}\n </ul>\n </ArchivedDisclosure>\n\n </>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\n\n/**\n * A 6 px status mark. Fills are SIGNAL colors — bright, saturated, the same family the leading\n * agent tools use (blue working, amber waiting, green done, red failed) — never the text-contrast\n * `--warning`/`--success` tokens, which a host darkens for readable text and which read as brown\n * and olive at dot size. A host re-tints any tone with `--dot-<tone>` (HSL triplet).\n * `ring` is the hollow variant for icon corners, where a filled dot reads as \"unread\".\n */\nexport type StatusTone = \"info\" | \"warning\" | \"danger\" | \"success\" | \"neutral\";\n\nconst FILL: Record<StatusTone, string> = {\n info: \"bg-[hsl(var(--dot-info,217_91%_60%))]\",\n warning: \"bg-[hsl(var(--dot-warning,38_92%_50%))]\",\n danger: \"bg-[hsl(var(--dot-danger,0_84%_60%))]\",\n success: \"bg-[hsl(var(--dot-success,142_71%_45%))]\",\n neutral: \"bg-muted-foreground/50\",\n};\n\nconst RING: Record<StatusTone, string> = {\n info: \"border-[hsl(var(--dot-info,217_91%_60%))]\",\n warning: \"border-[hsl(var(--dot-warning,38_92%_50%))]\",\n danger: \"border-[hsl(var(--dot-danger,0_84%_60%))]\",\n success: \"border-[hsl(var(--dot-success,142_71%_45%))]\",\n neutral: \"border-muted-foreground/50\",\n};\n\nexport interface StatusDotProps extends React.HTMLAttributes<HTMLSpanElement> {\n tone: StatusTone;\n variant?: \"solid\" | \"ring\";\n /** Accessible name; without it the dot is decorative. */\n label?: string;\n}\n\nexport function StatusDot({ tone, variant = \"solid\", label, className, ...props }: StatusDotProps) {\n return (\n <span\n data-slot=\"status-dot\"\n data-tone={tone}\n data-variant={variant}\n {...(label ? { role: \"img\", \"aria-label\": label } : { \"aria-hidden\": true })}\n className={cn(\n \"inline-block shrink-0 rounded-full\",\n variant === \"solid\" ? cn(\"size-1.5\", FILL[tone]) : cn(\"size-2 border-[1.5px] bg-transparent\", RING[tone]),\n className,\n )}\n {...props}\n />\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../tooltip\";\nimport { StatusDot, type StatusTone } from \"./status-dot\";\n\n/**\n * The app rail: a narrow, never-changing strip of area icons on the far left, with the\n * person at the bottom (Codex, VS Code, Slack, Teams). It answers \"where am I\"; the panel\n * beside it answers \"what can I do here\". Width is the `--app-rail-width` knob (48 px).\n */\n\nexport function AppRail({ className, style, onKeyDown, ...props }: React.HTMLAttributes<HTMLElement>) {\n return (\n <nav\n data-slot=\"app-rail\"\n aria-label=\"Areas\"\n // Up/Down move between the rail's items, Home/End jump to the ends (a source list's keys).\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || ![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(event.key)) return;\n const items = Array.from(event.currentTarget.querySelectorAll<HTMLElement>(\"[data-slot=app-rail-item]:not(:disabled), [data-slot=app-rail-avatar]\"));\n const at = items.indexOf(event.target as HTMLElement);\n if (at === -1) return;\n const next = event.key === \"Home\" ? 0 : event.key === \"End\" ? items.length - 1 : at + (event.key === \"ArrowDown\" ? 1 : -1);\n const target = items[Math.max(0, Math.min(items.length - 1, next))];\n if (target) {\n event.preventDefault();\n target.focus();\n }\n }}\n className={cn(\"flex h-full w-(--app-rail-width) shrink-0 flex-col items-center gap-1 py-2\", className)}\n style={{ \"--app-rail-width\": \"48px\", ...style } as React.CSSProperties}\n {...props}\n />\n );\n}\n\nexport function AppRailGroup({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div data-slot=\"app-rail-group\" className={cn(\"flex flex-col items-center gap-1\", className)} {...props} />;\n}\n\n/** Pushes everything after it to the bottom of the rail. */\nexport function AppRailSpacer() {\n return <div data-slot=\"app-rail-spacer\" className=\"flex-1\" />;\n}\n\nexport interface AppRailItemProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n icon: React.ReactNode;\n label: string;\n /** Shown in the tooltip after the label, e.g. \"⌘1\". */\n shortcut?: string;\n active?: boolean;\n /** A hollow corner mark when the area needs attention; healthy areas carry none. */\n attention?: StatusTone;\n attentionLabel?: string;\n}\n\nexport const AppRailItem = React.forwardRef<HTMLButtonElement, AppRailItemProps>(function AppRailItem(\n { icon, label, shortcut, active = false, attention, attentionLabel, className, ...props },\n ref,\n) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n data-slot=\"app-rail-item\"\n data-active={active}\n aria-label={label}\n aria-current={active ? \"page\" : undefined}\n className={cn(\n \"relative flex size-8 items-center justify-center rounded-lg text-muted-foreground outline-none transition-colors\",\n \"hover:bg-foreground/[0.06] hover:text-foreground\",\n \"data-[active=true]:bg-foreground/[0.08] data-[active=true]:text-foreground\",\n \"focus-visible:ring-2 focus-visible:ring-ring\",\n \"[&_svg]:size-[18px] [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n {icon}\n {attention ? (\n <StatusDot\n tone={attention}\n variant=\"ring\"\n {...(attentionLabel ? { label: attentionLabel } : {})}\n className=\"absolute right-0.5 bottom-0.5\"\n />\n ) : null}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\" align=\"center\">\n <span className=\"flex items-center gap-2\">\n {label}\n {shortcut ? <span className=\"opacity-60\">{shortcut}</span> : null}\n </span>\n </TooltipContent>\n </Tooltip>\n );\n});\n\nexport interface AppRailAvatarProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n /** Up to two letters. Ignored when `children` is given. */\n initials?: string;\n label: string;\n /** A glyph instead of initials (e.g. a neutral person while signed out). */\n children?: React.ReactNode;\n}\n\n/** The person, at the bottom of the rail (Codex's initials circle). */\nexport const AppRailAvatar = React.forwardRef<HTMLButtonElement, AppRailAvatarProps>(function AppRailAvatar(\n { initials = \"\", label, className, children, ...props },\n ref,\n) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n data-slot=\"app-rail-avatar\"\n aria-label={label}\n className={cn(\n \"flex size-6 items-center justify-center rounded-full bg-foreground/[0.12] text-[10px] font-semibold leading-none text-muted-foreground outline-none [&_svg]:size-3.5\",\n \"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n className,\n )}\n {...props}\n >\n {children ?? initials.slice(0, 2).toUpperCase()}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\" align=\"center\">\n {label}\n </TooltipContent>\n </Tooltip>\n );\n});\n","\"use client\";\n\n/**\n * Resizable — the split-pane family, on react-resizable-panels **v4**.\n *\n * TWO FORKS COLLAPSE INTO ONE COMPONENT. matrx-frontend shipped\n * `components/ui/resizable.tsx` (38 import sites, one fixed handle width) AND\n * `components/ui/matrx/resizable.tsx` (6 sites, an eight-step `size` scale).\n * They disagreed about exactly one thing — how thick the handle is — which is\n * the C18 density-as-a-fork pattern this package exists to end. `size` is a\n * prop here; both forks die.\n *\n * v4 IS NOT v1/v2, and the differences are the reason a wrapper exists at all:\n * - the group prop is `orientation`, not `direction`;\n * - `data-panel-group-direction` is gone — the separator states\n * `aria-orientation`, and it is `vertical` in a HORIZONTAL group (it is the\n * separator's own axis, not the group's), which is why every orientation\n * selector below reads the way it does;\n * - `Group` sets `height:100%/width:100%/overflow:hidden` internally;\n * - `Panel` renders an outer flex-sizing div wrapping an inner\n * `overflow:auto` div that receives `className`/`style` — to make a panel\n * clip instead of scroll, pass `style={{ overflow: \"hidden\", height: \"100%\" }}`;\n * - numeric size props are PIXELS; percentages are strings (`\"30%\"`).\n *\n * THE DRAG OUTLINE BUG, kept fixed. The library sets `tabIndex=0` on the\n * separator, so a mouse drag FOCUSES it and the browser's default outline\n * flashes — which rendered as a near-white bar in dark mode. `focus-visible:`\n * does not suppress it (that is keyboard-only); `focus:outline-none` does, and\n * the keyboard ring is restored explicitly on `focus-visible`.\n *\n * MOUSE TOLERANCE IS AN INVISIBLE TARGET. A 2px line is not grabbable; an\n * `::after` overlay widens the hit area without widening the rule, and goes to\n * 44px on coarse pointers.\n *\n * `react-resizable-panels` is an ordinary dependency, not a peer (C23): the\n * panel geometry IS this component's product.\n */\n\nimport * as React from \"react\";\nimport { Group, Panel, Separator } from \"react-resizable-panels\";\n\nimport { cn } from \"./cn\";\nimport { DragHandleDots2Icon } from \"./icons\";\n\nexport type ResizableHandleSize =\n | \"xs\"\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"3xl\"\n | \"4xl\";\n\n/**\n * The separator's own thickness. `aria-orientation=horizontal` means a\n * separator lying across a VERTICAL group, so its thickness is a height.\n */\nconst HANDLE_SIZES: Record<ResizableHandleSize, string> = {\n xs: \"w-0.5 [&[aria-orientation=horizontal]]:h-0.5 [&[aria-orientation=horizontal]]:w-full\",\n sm: \"w-1 [&[aria-orientation=horizontal]]:h-1 [&[aria-orientation=horizontal]]:w-full\",\n md: \"w-1.5 [&[aria-orientation=horizontal]]:h-1.5 [&[aria-orientation=horizontal]]:w-full\",\n lg: \"w-2 [&[aria-orientation=horizontal]]:h-2 [&[aria-orientation=horizontal]]:w-full\",\n xl: \"w-3 [&[aria-orientation=horizontal]]:h-3 [&[aria-orientation=horizontal]]:w-full\",\n \"2xl\":\n \"w-4 [&[aria-orientation=horizontal]]:h-4 [&[aria-orientation=horizontal]]:w-full\",\n \"3xl\":\n \"w-6 [&[aria-orientation=horizontal]]:h-6 [&[aria-orientation=horizontal]]:w-full\",\n \"4xl\":\n \"w-8 [&[aria-orientation=horizontal]]:h-8 [&[aria-orientation=horizontal]]:w-full\",\n};\n\nconst ResizablePanelGroup = ({\n className,\n ...props\n}: React.ComponentProps<typeof Group>) => (\n <Group\n data-slot=\"resizable-group\"\n className={cn(\"flex h-full w-full\", className)}\n {...props}\n />\n);\nResizablePanelGroup.displayName = \"ResizablePanelGroup\";\n\nconst ResizablePanel = Panel;\n\nexport interface ResizableHandleProps\n extends React.ComponentProps<typeof Separator> {\n /** Render the centered grip. */\n withHandle?: boolean;\n /** Separator thickness. Default `xs` — matrx-frontend's original 2px line. */\n size?: ResizableHandleSize;\n}\n\nconst ResizableHandle = ({\n withHandle,\n size = \"xs\",\n className,\n ...props\n}: ResizableHandleProps) => (\n <Separator\n data-slot=\"resizable-handle\"\n className={cn(\n \"group/handle relative flex shrink-0 items-center justify-center bg-border transition-colors\",\n // Invisible hit target centered on the line; wider still on touch.\n \"after:absolute after:inset-y-0 after:left-1/2 after:w-1.5 after:-translate-x-1/2 after:content-['']\",\n \"pointer-coarse:after:w-11\",\n \"[&[aria-orientation=horizontal]]:after:inset-x-0 [&[aria-orientation=horizontal]]:after:left-0 [&[aria-orientation=horizontal]]:after:top-1/2 [&[aria-orientation=horizontal]]:after:h-1.5 [&[aria-orientation=horizontal]]:after:w-full [&[aria-orientation=horizontal]]:after:-translate-x-0 [&[aria-orientation=horizontal]]:after:-translate-y-1/2\",\n \"pointer-coarse:[&[aria-orientation=horizontal]]:after:h-11\",\n // The drag-outline bug: suppress for ALL focus, restore for keyboard.\n \"focus:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1\",\n // Library-driven state feedback.\n \"data-[separator=hover]:bg-primary data-[separator=active]:bg-primary\",\n HANDLE_SIZES[size],\n \"cursor-col-resize [&[aria-orientation=horizontal]]:cursor-row-resize\",\n className,\n )}\n {...props}\n >\n {withHandle ? (\n <div className=\"z-10 flex h-8 w-4 items-center justify-center rounded-sm border bg-border group-aria-[orientation=horizontal]/handle:h-4 group-aria-[orientation=horizontal]/handle:w-8\">\n <DragHandleDots2Icon className=\"h-2.5 w-2.5 group-aria-[orientation=horizontal]/handle:rotate-90\" />\n </div>\n ) : null}\n </Separator>\n);\nResizableHandle.displayName = \"ResizableHandle\";\n\nexport { ResizableHandle, ResizablePanel, ResizablePanelGroup };\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"../resizable\";\n\n/**\n * The canvas: a right-hand workspace of panels (terminal, files, browser, info) beside the\n * main content, as in Claude desktop and Codex. Panels stack in columns, resize by dragging\n * the gaps between them, and any one can expand to fill the whole canvas region.\n *\n * The layout is presentational: the host owns which panels are open, which is expanded and\n * what each renders. The panel CHROME (CanvasPanel, CanvasPanelEmpty, BrowserTabs, BrowserBar)\n * lives in @ai-matrx/canvas/react — the one canvas chrome; this package cannot depend on it\n * (canvas → tap-target → design-system would be a cycle).\n */\n\nexport interface CanvasPanelDef {\n id: string;\n node: React.ReactNode;\n /** Pixels (number) or percent of the column (string). */\n minSize?: number | string;\n defaultSize?: number | string;\n}\n\nexport interface CanvasColumnDef {\n id: string;\n panels: CanvasPanelDef[];\n minSize?: number | string;\n defaultSize?: number | string;\n}\n\nexport interface CanvasLayoutProps {\n columns: CanvasColumnDef[];\n /** When set, only this panel renders, filling the layout. */\n expandedId?: string | null;\n className?: string;\n}\n\nconst GAP = \"bg-transparent data-[separator=hover]:bg-foreground/15 data-[separator=active]:bg-foreground/25\";\n\nexport function CanvasLayout({ columns, expandedId = null, className }: CanvasLayoutProps) {\n const visible = columns.filter((c) => c.panels.length > 0);\n const expanded = expandedId ? visible.flatMap((c) => c.panels).find((p) => p.id === expandedId) : undefined;\n\n if (expanded) {\n return (\n <div data-slot=\"canvas-layout\" data-expanded={expanded.id} className={cn(\"flex h-full w-full\", className)}>\n {expanded.node}\n </div>\n );\n }\n\n return (\n <ResizablePanelGroup data-slot=\"canvas-layout\" orientation=\"horizontal\" className={cn(\"gap-0\", className)}>\n {visible.map((column, ci) => (\n <React.Fragment key={column.id}>\n {ci > 0 ? <ResizableHandle data-canvas-gap=\"column\" size=\"md\" className={GAP} /> : null}\n <ResizablePanel\n id={column.id}\n minSize={column.minSize ?? 220}\n {...(column.defaultSize !== undefined ? { defaultSize: column.defaultSize } : {})}\n >\n <ResizablePanelGroup data-canvas-column={column.id} orientation=\"vertical\">\n {column.panels.map((panel, pi) => (\n <React.Fragment key={panel.id}>\n {pi > 0 ? <ResizableHandle data-canvas-gap=\"row\" size=\"md\" className={GAP} /> : null}\n <ResizablePanel\n id={panel.id}\n minSize={panel.minSize ?? 120}\n {...(panel.defaultSize !== undefined ? { defaultSize: panel.defaultSize } : {})}\n >\n {panel.node}\n </ResizablePanel>\n </React.Fragment>\n ))}\n </ResizablePanelGroup>\n </ResizablePanel>\n </React.Fragment>\n ))}\n </ResizablePanelGroup>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../tooltip\";\n\n/**\n * A small segmented group of icon buttons for switching the app's mode (Claude desktop's\n * chat | code pair in the title bar). A radio group: arrow keys move, one is always checked.\n */\n\nexport interface ModeSwitchOption<T extends string> {\n value: T;\n label: string;\n icon: React.ReactNode;\n shortcut?: string;\n}\n\nexport interface ModeSwitchProps<T extends string> {\n value: T;\n onValueChange: (value: T) => void;\n options: ReadonlyArray<ModeSwitchOption<T>>;\n label?: string;\n className?: string;\n}\n\nexport function ModeSwitch<T extends string>({ value, onValueChange, options, label = \"Mode\", className }: ModeSwitchProps<T>) {\n const refs = React.useRef<Array<HTMLButtonElement | null>>([]);\n\n const move = (from: number, delta: number) => {\n const next = (from + delta + options.length) % options.length;\n const option = options[next];\n if (!option) return;\n onValueChange(option.value);\n refs.current[next]?.focus();\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={label}\n data-slot=\"mode-switch\"\n className={cn(\"inline-flex items-center gap-0.5 rounded-lg bg-foreground/[0.06] p-0.5\", className)}\n >\n {options.map((option, index) => {\n const checked = option.value === value;\n return (\n <Tooltip key={option.value}>\n <TooltipTrigger asChild>\n <button\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n aria-label={option.label}\n data-slot=\"mode-switch-item\"\n data-value={option.value}\n tabIndex={checked ? 0 : -1}\n onClick={() => onValueChange(option.value)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n move(index, 1);\n } else if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n move(index, -1);\n }\n }}\n className={cn(\n \"flex h-6 w-7 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors\",\n \"hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring\",\n \"aria-checked:bg-background aria-checked:text-foreground aria-checked:shadow-[0_0_0_0.5px_hsl(var(--foreground)/0.12),0_1px_2px_hsl(var(--foreground)/0.08)]\",\n \"dark:aria-checked:bg-foreground/[0.14] dark:aria-checked:shadow-none\",\n \"[&_svg]:size-[15px] [&_svg]:shrink-0\",\n )}\n >\n {option.icon}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n <span className=\"flex items-center gap-2\">\n {option.label}\n {option.shortcut ? <span className=\"opacity-60\">{option.shortcut}</span> : null}\n </span>\n </TooltipContent>\n </Tooltip>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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","names":["React","jsx","React","jsx","jsxs","isActive","jsx","React","jsx","jsxs","AppRailItem","AppRailAvatar","jsx","React","jsx","jsxs","React","jsx","jsxs"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
4
|
Select
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QOEKPR37.js";
|
|
6
6
|
import {
|
|
7
7
|
Tooltip,
|
|
8
8
|
TooltipContent,
|
|
@@ -367,4 +367,4 @@ export {
|
|
|
367
367
|
DEFAULT_TABLE_PAGE_SIZES,
|
|
368
368
|
GenericTablePagination
|
|
369
369
|
};
|
|
370
|
-
//# sourceMappingURL=chunk-
|
|
370
|
+
//# sourceMappingURL=chunk-PBDQZPKV.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
Button
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QOEKPR37.js";
|
|
5
5
|
import {
|
|
6
6
|
Tooltip,
|
|
7
7
|
TooltipContent,
|
|
@@ -293,4 +293,4 @@ export {
|
|
|
293
293
|
displayId,
|
|
294
294
|
RecordId
|
|
295
295
|
};
|
|
296
|
-
//# sourceMappingURL=chunk-
|
|
296
|
+
//# sourceMappingURL=chunk-Q2HWDJED.js.map
|
|
@@ -178,7 +178,7 @@ function Select({
|
|
|
178
178
|
/* @__PURE__ */ jsxs("span", { className: "matrx-control-select-value", children: [
|
|
179
179
|
icon,
|
|
180
180
|
/* @__PURE__ */ jsx("span", { children: current?.label ?? value }),
|
|
181
|
-
current?.hint ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: current.hint }) : null
|
|
181
|
+
current?.hint ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", "data-select-hint": "", children: current.hint }) : null
|
|
182
182
|
] }),
|
|
183
183
|
/* @__PURE__ */ jsx(SelectChevron, {})
|
|
184
184
|
]
|
|
@@ -205,9 +205,9 @@ function Select({
|
|
|
205
205
|
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: o.group })
|
|
206
206
|
] }) : null,
|
|
207
207
|
/* @__PURE__ */ jsxs(DropdownMenuRadioItem, { value: o.value, disabled: o.disabled === true, className: "text-[0.8125rem]", children: [
|
|
208
|
-
/* @__PURE__ */ jsxs("span", { className: "flex-1
|
|
209
|
-
o.label,
|
|
210
|
-
o.hint ? /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-muted-foreground", children: o.hint }) : null
|
|
208
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-baseline", children: [
|
|
209
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: o.label }),
|
|
210
|
+
o.hint ? /* @__PURE__ */ jsx("span", { className: "ml-1.5 shrink-0 text-muted-foreground", "data-select-hint": "", children: o.hint }) : null
|
|
211
211
|
] }),
|
|
212
212
|
o.meta ? /* @__PURE__ */ jsx("span", { className: "ml-3 text-[0.6875rem] text-muted-foreground", children: o.meta }) : null
|
|
213
213
|
] })
|
|
@@ -462,4 +462,4 @@ export {
|
|
|
462
462
|
Switch,
|
|
463
463
|
Textarea
|
|
464
464
|
};
|
|
465
|
-
//# sourceMappingURL=chunk-
|
|
465
|
+
//# sourceMappingURL=chunk-QOEKPR37.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/controls/controls.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE ONE CONTROL — the settled control family (owner, 2026-10-02/03).\n *\n * Every control here is the same object: 28px visible height, capsule, 13px/500\n * label, 16px glyph inset 6px, text inset 10px, and HALF A GAP (3px) of its own\n * on each side so containers add no gap. There is NO size prop: agents get no\n * choice. Geometry and color live in `controls.css`, locked inside\n * `@layer matrx-tap-lock` (`!important` in the host's first layer), so a call\n * site's `className` can place a control (width, flex, grid, position) but can\n * never restyle it. The rare big control is a different component behind a\n * `// ui-exception:` comment, never a prop.\n *\n * Built on the package's own internals — Radix Slot / Switch / DropdownMenu, the\n * cursor law's `swallowClick`, `SelectChevron`, the package icons — so nothing\n * here is a second implementation of a behavior the package already owns.\n */\n\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\nimport { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { swallowClick } from \"../button\";\nimport { cn } from \"../cn\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../dropdown-menu\";\nimport { MagnifyingGlassIcon, PlusIcon } from \"../icons\";\nimport { SelectChevron } from \"../select\";\nimport { isIconOnly } from \"./icon-only\";\nimport { boxStyle, useAutoGrow, useMergedTextareaRef } from \"../textarea\";\n\n/* ------------------------------------------------------------------ */\n/* Layout: the row and the scope */\n/* ------------------------------------------------------------------ */\n\nexport interface ControlRowProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Keep the controls on one line (a row's trailing actions). */\n nowrap?: boolean;\n}\n\n/** A row of controls. It adds no gap: each control carries its own half-gap. */\nexport const ControlRow = React.forwardRef<HTMLDivElement, ControlRowProps>(\n ({ className, nowrap, ...props }, ref) => (\n <div\n ref={ref}\n data-matrx-control-row=\"\"\n data-nowrap={nowrap ? \"\" : undefined}\n className={cn(\"matrx-control-row\", className)}\n {...props}\n />\n ),\n);\nControlRow.displayName = \"ControlRow\";\n\n/**\n * Until the tap tokens move to 28/34 app-wide (the rollout), a tap button\n * inside a ControlScope matches the controls beside it: a 28px pill in a 34px\n * box. Wrap a page (or a region) that mixes tap buttons and controls.\n */\nexport const ControlScope = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n (props, ref) => <div ref={ref} data-matrx-controls=\"\" {...props} />,\n);\nControlScope.displayName = \"ControlScope\";\n\n/**\n * THE CONTAINER a collapsing control measures (`Button collapse=\"container\"`).\n * A host declares it on the box whose WIDTH decides — a list pane, a panel,\n * never the viewport: beside a chat panel a 1024px screen holds a 540px list.\n * `className={CONTROLS_CONTAINER_CLASS}`, or add the name to the box's own\n * `container-name` when it already names a container (`list matrx-controls`).\n */\nexport const CONTROLS_CONTAINER_NAME = \"matrx-controls\";\nexport const CONTROLS_CONTAINER_CLASS = \"matrx-controls-container\";\n/** Below this container width a `collapse=\"container\"` button is its icon alone (48rem). */\nexport const CONTROLS_COLLAPSE_BELOW_REM = 48;\n\n/* ------------------------------------------------------------------ */\n/* Button */\n/* ------------------------------------------------------------------ */\n\n/**\n * Tone, never size. `success` is the solid confirm-a-good-outcome fill (approve,\n * publish, mark done); `link` is a text action at the control's height — no\n * fill, no border, primary ink, underline on hover (an inline \"View all\").\n */\nexport type ControlVariant = \"primary\" | \"quiet\" | \"outline\" | \"danger\" | \"success\" | \"link\";\n\n/**\n * THE NAMED CONTROL WIDTHS (0.68.22) — a button, field or select trigger that should not fill\n * its row takes one of these instead of a pasted `w-40`. Derived from the call sites:\n * `xs` 6rem (a unit, a short enum), `sm` 8rem, `md` 10rem (a date, a status), `lg` 14rem (a\n * name, an account), `xl` 20rem (a search, a URL). Never wider than its container.\n */\nexport type ControlWidth = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\ninterface ButtonBase extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n /** Tone, never size. Default `outline`. */\n variant?: ControlVariant;\n /** A status tint from the role tokens (the Badge's), for a button that\n * reports a state — a drift door, an alert count. Default: none. */\n tone?: BadgeTone;\n /** Leading 16px glyph. */\n icon?: React.ReactNode;\n /** Trailing 16px glyph (a menu chevron, an external-link mark). */\n iconEnd?: React.ReactNode;\n /** Render the one child element (a link) with the button's skin. */\n asChild?: boolean;\n /**\n * `\"container\"`: below 48rem of the nearest `matrx-controls` container\n * (CONTROLS_CONTAINER_NAME) the button is its leading `icon` alone — a 28px\n * circle; the label stays its accessible name and its tooltip. Needs `icon`;\n * without one it never collapses. Outside such a container it never does.\n */\n collapse?: \"container\";\n /**\n * A TOGGLE (a choice in a set, a mode, a tab-like switch): `true` is on —\n * the accent fill and full ink; `false` is off — no fill, quiet ink. Sets\n * `aria-pressed`. Omit for an ordinary action.\n */\n pressed?: boolean;\n /**\n * A count or a dot on the button's top-right corner, for something waiting\n * behind it (items added, unread). A number draws the count (99+ above 99;\n * 0 draws nothing); `true` draws an 8px dot. On a button with a text label\n * the count sits in the row after the label instead (never over it). Name it in `aria-label` too —\n * the mark is decoration.\n */\n badge?: number | boolean;\n /**\n * The glyph's own status ink, for a glyph whose COLOR carries meaning (the\n * green check after a copy, an amber debug bug) while the button stays\n * quiet. Tints only the icon(s), never the fill. Default: none.\n */\n glyphTone?: GlyphTone;\n /**\n * A removing act (clear, remove, disconnect): muted until hover,\n * destructive on hover — the delete tier-1 skin on any glyph or label.\n * Quiet variant only.\n */\n removes?: boolean;\n /**\n * MIXED CONTENT (0.68.12): a short muted fact after the label — a count, a\n * size, a shortcut, a \"3 of 12\" — in the 12px secondary ink. The button\n * stays 28px; the fact is part of the button, never a second element styled\n * beside it. Never a sentence.\n */\n meta?: React.ReactNode;\n /** A named width instead of the label's own (see `ControlWidth`). */\n width?: ControlWidth;\n /**\n * THE INVITING-PAGE CALL TO ACTION (0.68.22): a 44px capsule with a 16px/600 label and a\n * 24px inset — the size a marketing hero, a module landing or a kit's front door asks for.\n * Inviting pages are never densified; functional pages never use it. A `primary` hero\n * carries a soft primary glow.\n */\n hero?: boolean;\n}\n/** The status inks a glyph may carry (the role tokens). */\nexport type GlyphTone = \"success\" | \"warning\" | \"destructive\" | \"info\" | \"primary\";\ninterface LabelledButton extends ButtonBase {\n children: React.ReactNode;\n}\ninterface IconOnlyButton extends ButtonBase {\n children?: undefined;\n /** An icon-only button must say what it does. */\n \"aria-label\": string;\n}\nexport type ButtonProps = LabelledButton | IconOnlyButton;\n\nfunction glyphSlot(icon: unknown, iconEnd: unknown, label: unknown): string | undefined {\n if (!label && (icon || iconEnd)) return \"only\";\n if (icon && iconEnd) return \"both\";\n if (icon) return \"start\";\n if (iconEnd) return \"end\";\n return undefined;\n}\n\n/**\n * THE button: primary / quiet / outline / danger / success / link, one 28px geometry; text,\n * icon + text, or icon-only (a 28px circle). `asChild` puts the skin on a link.\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = \"outline\", tone, icon, iconEnd, asChild = false, collapse, pressed, badge, glyphTone, removes, meta, width, hero, children, onClick, type, ...props }, ref) => {\n const Component = asChild ? Slot : \"button\";\n const badgeText =\n typeof badge === \"number\" ? (badge > 0 ? (badge > 99 ? \"99+\" : String(badge)) : null) : badge ? \"\" : null;\n const ariaDisabled = props[\"aria-disabled\"];\n const disabledChild = asChild && Boolean(props.disabled);\n const inert = disabledChild || ariaDisabled === true || ariaDisabled === \"true\";\n // asChild: the child element carries the label, so the glyph slot reads\n // the child's own children.\n const label = asChild && React.isValidElement<{ children?: React.ReactNode }>(children)\n ? children.props.children\n : children;\n const collapses = collapse === \"container\" && Boolean(icon) && Boolean(label);\n return (\n <Component\n ref={ref}\n type={asChild ? undefined : (type ?? \"button\")}\n data-matrx-control=\"button\"\n data-variant={variant}\n data-tone={tone && tone !== \"neutral\" ? tone : undefined}\n data-glyph={glyphSlot(icon, iconEnd, label)}\n data-collapse={collapses ? \"container\" : undefined}\n data-pressed={pressed === undefined ? undefined : pressed ? \"true\" : \"false\"}\n aria-pressed={pressed}\n data-badge={badgeText === null ? undefined : badgeText === \"\" ? \"dot\" : \"count\"}\n // A labeled button carries its count IN the row after the label: the\n // corner count sat over the label's last letter (\"HR 28\" on /tasks).\n data-badge-place={badgeText && label ? \"inline\" : undefined}\n data-glyph-tone={glyphTone}\n data-delete={removes ? \"\" : undefined}\n data-width={width}\n data-hero={hero ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-button matrx-glyph-trim\", className)}\n // A collapsed button still says what it does on hover.\n title={collapses && typeof label === \"string\" && props.title === undefined ? label : undefined}\n {...props}\n aria-disabled={disabledChild ? true : ariaDisabled}\n tabIndex={disabledChild ? -1 : props.tabIndex}\n onClick={inert ? swallowClick : onClick}\n >\n {icon}\n <Slottable>\n {/* A text label NEVER spills past its button (owner, 2026-10-05: a\n long chat title ran under the mode switch beside it). It sits in\n its own box so a capped button ellipsizes instead of overflowing. */}\n {!asChild && (typeof children === \"string\" || typeof children === \"number\") ? (\n <span className=\"matrx-control-button-label\">{children}</span>\n ) : (\n children\n )}\n </Slottable>\n {meta === undefined || meta === null || meta === false ? null : (\n <span className=\"matrx-control-button-meta\">{meta}</span>\n )}\n {iconEnd}\n {badgeText === null ? null : (\n <span className=\"matrx-control-button-badge\" aria-hidden=\"true\">\n {badgeText}\n </span>\n )}\n </Component>\n );\n },\n);\nButton.displayName = \"Button\";\n\n/** A split button: two Buttons joined — the act, and its menu of variants. */\nexport const SplitButton = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} role=\"group\" data-matrx-control=\"split\" className={cn(\"matrx-control-split\", className)} {...props} />\n ),\n);\nSplitButton.displayName = \"SplitButton\";\n\n/* ------------------------------------------------------------------ */\n/* Field (input capsule) and SearchField */\n/* ------------------------------------------------------------------ */\n\nexport interface FieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n /** Leading 16px glyph. */\n icon?: React.ReactNode;\n /** Trailing content inside the capsule — a clear button, a unit. */\n end?: React.ReactNode;\n /** A named width instead of filling the row (see `ControlWidth`). */\n width?: ControlWidth;\n /**\n * THE INVITING-PAGE INPUT: a 56px capsule with an 18px value and a 24px inset — the big,\n * friendly field a welcome / onboarding front door asks for (pairs with Button `hero`).\n * Inviting pages only; functional pages never use it.\n */\n hero?: boolean;\n /**\n * THE LEADING SEARCH: a 48px filled capsule — no frame, the muted fill, a 16px value, a 20px\n * glyph — that turns the card color with a soft lift on focus. The one search a home page leads\n * with (a file home's search, as on Google Docs / Drive). One per page; never in a form or toolbar.\n */\n filled?: boolean;\n}\n\n/** The input capsule. `className`/`style` place the capsule (width, flex). */\nexport const Field = React.forwardRef<HTMLInputElement, FieldProps>(\n ({ className, style, icon, end, width, hero, filled, ...props }, ref) => (\n <label\n data-matrx-control=\"field\"\n data-glyph={icon ? \"start\" : undefined}\n data-width={width}\n data-hero={hero ? \"\" : undefined}\n data-filled={filled ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-field\", className)}\n style={style}\n >\n {icon}\n <input ref={ref} {...props} />\n {end}\n </label>\n ),\n);\nField.displayName = \"Field\";\n\n/** The search capsule: a Field with the magnifier, `type=\"search\"`. */\nexport const SearchField = React.forwardRef<HTMLInputElement, Omit<FieldProps, \"icon\">>(\n ({ placeholder = \"Search\", ...props }, ref) => (\n <Field\n ref={ref}\n type=\"search\"\n icon={<MagnifyingGlassIcon aria-hidden=\"true\" />}\n placeholder={placeholder}\n aria-label={props[\"aria-label\"] ?? placeholder}\n {...props}\n />\n ),\n);\nSearchField.displayName = \"SearchField\";\n\n/* ------------------------------------------------------------------ */\n/* Select — a capsule trigger over a radio menu */\n/* ------------------------------------------------------------------ */\n\nexport interface SelectOption<T extends string = string> {\n value: T;\n label: string;\n /** 11px trailing text in the menu (a count, a shortcut). */\n meta?: string;\n /** Muted text right after the label, menu and trigger alike: what tells two same-named options apart (a short id, an owner). */\n hint?: string;\n /** A section heading: the menu shows it (foreground weight) above the first option of each consecutive run. */\n group?: string;\n /** Shown but not choosable (an unavailable tool, a sentinel the URL set). */\n disabled?: boolean;\n}\n\nexport interface SelectProps<T extends string = string> {\n value: T;\n options: readonly SelectOption<T>[];\n onValueChange: (value: T) => void;\n \"aria-label\": string;\n /** Leading 16px glyph on the trigger. */\n icon?: React.ReactNode;\n align?: \"start\" | \"end\";\n disabled?: boolean;\n /**\n * `field` (default): the capsule a form row uses. `inline`: the value as text with a small chevron,\n * no capsule — for a choice that sits inside a dense row or a toolbar sentence (\"Full ⌄\"), where a\n * row of capsules reads as clutter (Arman, 2026-10-14).\n */\n variant?: \"field\" | \"inline\";\n /**\n * A search row at the top of the menu once there are at least this many options (a long list of\n * organizations). It matches label, hint and group. Omitted: never.\n */\n searchAt?: number;\n /** Placement only (width, flex). */\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function Select<T extends string = string>({\n value,\n options,\n onValueChange,\n icon,\n align = \"start\",\n disabled,\n className,\n style,\n \"aria-label\": ariaLabel,\n variant = \"field\",\n searchAt,\n}: SelectProps<T>) {\n const current = options.find((o) => o.value === value);\n const [query, setQuery] = React.useState(\"\");\n const searchable = searchAt !== undefined && options.length >= searchAt;\n const q = searchable ? query.trim().toLowerCase() : \"\";\n const shown = q ? options.filter((o) => [o.label, o.hint, o.group].some((t) => t?.toLowerCase().includes(q))) : options;\n return (\n <DropdownMenu onOpenChange={(open) => !open && setQuery(\"\")}>\n <DropdownMenuTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n data-matrx-control=\"select\"\n data-variant={variant === \"inline\" ? \"inline\" : undefined}\n data-glyph={icon ? \"start\" : undefined}\n className={cn(\"matrx-control matrx-control-select\", className)}\n style={style}\n aria-label={ariaLabel}\n >\n <span className=\"matrx-control-select-value\">\n {icon}\n <span>{current?.label ?? value}</span>\n {current?.hint ? <span className=\"text-muted-foreground\" data-select-hint=\"\">{current.hint}</span> : null}\n </span>\n <SelectChevron />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"max-h-80 w-max min-w-[max(10rem,var(--radix-dropdown-menu-trigger-width))] max-w-[min(24rem,var(--radix-dropdown-menu-content-available-width))] overflow-y-auto\">\n {searchable ? (\n <div className=\"sticky top-0 z-10 bg-popover p-1\" data-select-search=\"\">\n <SearchField\n className=\"w-full\"\n value={query}\n autoFocus\n aria-label={`Search ${ariaLabel}`}\n onChange={(e) => setQuery(e.target.value)}\n // The menu's type-ahead never takes the letters; arrows and Escape still drive the menu.\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\" && e.key !== \"Escape\" && e.key !== \"Tab\") e.stopPropagation();\n }}\n />\n </div>\n ) : null}\n {searchable && shown.length === 0 ? <div className=\"px-2 py-1.5 text-[0.8125rem] text-muted-foreground\" role=\"status\">No match</div> : null}\n <DropdownMenuRadioGroup value={value} onValueChange={(v) => onValueChange(v as T)}>\n {shown.map((o, i) => (\n <React.Fragment key={o.value}>\n {o.group && o.group !== shown[i - 1]?.group ? (\n <>\n {i > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuLabel>{o.group}</DropdownMenuLabel>\n </>\n ) : null}\n <DropdownMenuRadioItem value={o.value} disabled={o.disabled === true} className=\"text-[0.8125rem]\">\n {/* The label truncates; the hint never does (it is what tells two same-named options apart). */}\n <span className=\"flex min-w-0 flex-1 items-baseline\">\n <span className=\"min-w-0 truncate\">{o.label}</span>\n {o.hint ? <span className=\"ml-1.5 shrink-0 text-muted-foreground\" data-select-hint=\"\">{o.hint}</span> : null}\n </span>\n {o.meta ? <span className=\"ml-3 text-[0.6875rem] text-muted-foreground\">{o.meta}</span> : null}\n </DropdownMenuRadioItem>\n </React.Fragment>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* SegmentedControl and Tabs */\n/* ------------------------------------------------------------------ */\n\nexport interface SegmentOption<T extends string = string> {\n value: T;\n label: React.ReactNode;\n /** An 11px count after the label. */\n count?: number | null;\n ariaLabel?: string;\n /** Hover text (an icon-only segment's name). */\n title?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps<T extends string = string> {\n /** The selected segment; `null` = none is selected (an optional choice). */\n value: T | null;\n onValueChange: (value: T) => void;\n data: readonly SegmentOption<T>[];\n \"aria-label\": string;\n /** The segments share the row's whole width equally (a full-width choice: levels, modes). */\n fill?: boolean;\n /** Placement only. */\n className?: string;\n style?: React.CSSProperties;\n}\n\nfunction SegmentItems<T extends string>({\n data,\n value,\n onValueChange,\n role,\n}: {\n data: readonly SegmentOption<T>[];\n value: T | null;\n onValueChange: (value: T) => void;\n role: \"tab\" | undefined;\n}) {\n return (\n <>\n {data.map((o) => {\n const on = o.value === value;\n return (\n <button\n key={o.value}\n type=\"button\"\n role={role}\n aria-selected={role ? on : undefined}\n aria-pressed={role ? undefined : on}\n aria-label={o.ariaLabel}\n title={o.title}\n disabled={o.disabled}\n data-state={on ? \"on\" : \"off\"}\n data-icon-only={o.count == null && isIconOnly(o.label) ? \"\" : undefined}\n className=\"matrx-control-segment\"\n onClick={() => onValueChange(o.value)}\n >\n {o.label}\n {o.count != null ? <span className=\"matrx-control-count\">{o.count}</span> : null}\n </button>\n );\n })}\n </>\n );\n}\n\n/** The capsule toggle group: a muted track, the selected thumb inset 2px. */\nexport function SegmentedControl<T extends string = string>({\n value,\n onValueChange,\n data,\n fill,\n className,\n style,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n data-matrx-control=\"segmented\"\n data-fill={fill ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-segmented\", className)}\n style={style}\n >\n <SegmentItems data={data} value={value} onValueChange={onValueChange} role={undefined} />\n </div>\n );\n}\n\nexport interface TabsProps<T extends string = string> extends SegmentedControlProps<T> {\n /** `underline` for page sections (default); `capsule` for filters. */\n variant?: \"underline\" | \"capsule\";\n /** Underline tabs draw their own hairline (default). Pass `false` when the row the tabs\n * sit in already draws it — the selected underline then lands on that row's rule. */\n rule?: boolean;\n /** Underline tabs inside a framed panel (a card, a bordered box): the labels start at the\n * panel's 12px content inset while the hairline still runs edge to edge. Page-level tabs\n * stay flush with the page gutter (default). Arman, 2026-10-21. */\n inset?: boolean;\n}\n\n/** Tabs: underline for page sections, capsule for filters. */\nexport function Tabs<T extends string = string>({\n variant = \"underline\",\n rule = true,\n inset = false,\n value,\n onValueChange,\n data,\n className,\n style,\n \"aria-label\": ariaLabel,\n}: TabsProps<T>) {\n if (variant === \"capsule\") {\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n data-matrx-control=\"tabs\"\n className={cn(\"matrx-control matrx-control-segmented\", className)}\n style={style}\n >\n <SegmentItems data={data} value={value} onValueChange={onValueChange} role=\"tab\" />\n </div>\n );\n }\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n data-matrx-control=\"tabs\"\n data-rule={rule ? undefined : \"none\"}\n data-inset={inset ? \"\" : undefined}\n className={cn(\"matrx-control-tabs\", className)}\n style={style}\n >\n {data.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={o.value === value}\n aria-label={o.ariaLabel}\n disabled={o.disabled}\n className=\"matrx-control-tab\"\n onClick={() => onValueChange(o.value)}\n >\n {o.label}\n {o.count != null ? <span className=\"matrx-control-count\">{o.count}</span> : null}\n </button>\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Badge */\n/* ------------------------------------------------------------------ */\n\nexport type BadgeTone = \"neutral\" | \"primary\" | \"success\" | \"warning\" | \"destructive\" | \"info\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** A status tint from the role tokens. Default `neutral` (plain outline). */\n tone?: BadgeTone;\n /** A 12px glyph before the label, 4px gap, in the badge's own tone color. */\n icon?: React.ReactNode;\n}\n\n/** Outline, 18px, 11px text, clamped to one line (≤20rem) — never a sentence. */\nexport function Badge({ tone = \"neutral\", icon, className, children, ...props }: BadgeProps) {\n return (\n <span\n data-matrx-control=\"badge\"\n data-tone={tone}\n className={cn(\"matrx-control-badge\", className)}\n title={typeof children === \"string\" ? children : undefined}\n {...props}\n >\n {icon ? (\n <span className=\"matrx-control-badge-icon\" aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span>{children}</span>\n </span>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Chip and ChipSet */\n/* ------------------------------------------------------------------ */\n\n/**\n * The status tones (the Badge's) plus a FIXED set of categorical hues, each a\n * token pair in `controls.css` (`--matrx-chip-<hue>`, stepped for dark). A\n * feature maps its kinds onto these through ONE table of its own\n * (`kind → ChipTone`) — never a class string.\n */\nexport type ChipHue =\n | \"sky\"\n | \"blue\"\n | \"indigo\"\n | \"violet\"\n | \"fuchsia\"\n | \"rose\"\n | \"orange\"\n | \"amber\"\n | \"lime\"\n | \"emerald\"\n | \"teal\"\n | \"cyan\"\n | \"slate\";\nexport type ChipTone = BadgeTone | ChipHue;\n\n/** Every tone a chip accepts, in a fixed order (tests, pickers, demos). */\nexport const CHIP_TONES: readonly ChipTone[] = [\n \"neutral\",\n \"primary\",\n \"success\",\n \"warning\",\n \"destructive\",\n \"info\",\n \"sky\",\n \"blue\",\n \"indigo\",\n \"violet\",\n \"fuchsia\",\n \"rose\",\n \"orange\",\n \"amber\",\n \"lime\",\n \"emerald\",\n \"teal\",\n \"cyan\",\n \"slate\",\n] as const;\n\nexport interface ChipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The one line of text. Truncates; the full text is the tooltip. */\n label: string;\n /** `item` (default): an existing thing, tinted. `add`: a suggestion to make\n * one — dashed, quiet, with the package's own leading `+`. */\n variant?: \"item\" | \"add\";\n /** A named tone, never a class. Default `neutral`. Ignored by `add`. */\n tone?: ChipTone;\n /** Leading glyph (drawn 14px, optically trimmed). */\n icon?: React.ReactNode;\n /** Put the chip's skin on the one child element (a link or a button); the\n * child carries no children of its own — the chip draws glyph + label. */\n asChild?: boolean;\n /**\n * A FILTER chip (a toggle in a set of choices): `true` is on — tinted in its\n * `tone` (default `primary`); `false` is off — untinted outline, quiet ink.\n * Sets `aria-pressed`. Use with `asChild` on a `<button>`. Omit for a tag.\n */\n pressed?: boolean;\n children?: React.ReactElement;\n}\n\n/**\n * THE chip: a tag that names a thing (a format, a kind, a status, a source).\n * ONE 24px height, one 6px radius, one 12px/500 label, 14px glyph, matched\n * insets, single line with an ellipsis and a tooltip, and the controls' 3px\n * half-gap of its own so a `ChipSet` adds none. Geometry and tint are locked\n * in `controls.css`; a call site may place it, never restyle it.\n */\nexport const Chip = React.forwardRef<HTMLSpanElement, ChipProps>(\n ({ label, variant = \"item\", tone, icon, asChild = false, pressed, children, className, title, ...props }, ref) => {\n const Component = asChild ? Slot : \"span\";\n const glyph = variant === \"add\" ? <PlusIcon className=\"lucide lucide-plus\" /> : icon;\n const toggle = pressed !== undefined && variant === \"item\";\n const resolvedTone = tone ?? (toggle ? \"primary\" : \"neutral\");\n return (\n <Component\n ref={ref}\n data-matrx-control=\"chip\"\n data-variant={variant}\n data-tone={variant === \"add\" ? undefined : resolvedTone}\n data-pressed={toggle ? String(pressed) : undefined}\n aria-pressed={toggle ? pressed : undefined}\n data-glyph={glyph ? (variant === \"add\" && icon ? \"both\" : \"start\") : undefined}\n className={cn(\"matrx-control-chip matrx-glyph-trim\", className)}\n title={title ?? label}\n {...props}\n >\n {glyph}\n {variant === \"add\" ? icon : null}\n {asChild ? <Slottable>{children}</Slottable> : null}\n <span className=\"matrx-control-chip-label\">{label}</span>\n </Component>\n );\n },\n);\nChip.displayName = \"Chip\";\n\nexport interface ChipSetProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * `flow` (default): chips sit at their own width and wrap.\n * `grid`: every chip is the same width (auto-filled columns of at least\n * 7.5rem), labels truncate — for a SET of siblings (a kit's formats).\n */\n layout?: \"flow\" | \"grid\";\n}\n\n/** A set of chips: same height, one baseline, the chips space themselves. */\nexport const ChipSet = React.forwardRef<HTMLDivElement, ChipSetProps>(\n ({ layout = \"flow\", className, ...props }, ref) => (\n <div\n ref={ref}\n data-matrx-control=\"chip-set\"\n data-layout={layout}\n className={cn(\"matrx-control-chip-set\", className)}\n {...props}\n />\n ),\n);\nChipSet.displayName = \"ChipSet\";\n\n/* ------------------------------------------------------------------ */\n/* Switch and Textarea */\n/* ------------------------------------------------------------------ */\n\nexport type SwitchProps = Omit<React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>, \"children\">;\n\n/** A 20px track in the 28px control box, so it lines up with every control. */\nexport const Switch = React.forwardRef<React.ComponentRef<typeof SwitchPrimitives.Root>, SwitchProps>(\n ({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n ref={ref}\n data-matrx-control=\"switch\"\n className={cn(\"matrx-control matrx-control-switch\", className)}\n {...props}\n >\n <span className=\"matrx-control-switch-track\">\n <SwitchPrimitives.Thumb className=\"matrx-control-switch-thumb\" />\n </span>\n </SwitchPrimitives.Root>\n ),\n);\nSwitch.displayName = \"Switch\";\n\nexport interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** The roomy writing surface used by inviting prompt boxes. */\n hero?: boolean;\n /** Join a pinned status row below this field from the small breakpoint upward. */\n joinedBottom?: boolean;\n /** `field` (default): the field skin. `bare`: the surrounding surface draws the frame (a\n * composer) — no border, no fill, no inset, no focus ring of its own. */\n variant?: \"field\" | \"bare\";\n /** Monospace text — code, JSON, keys. */\n mono?: boolean;\n /** Grow with the content (stopping at `maxHeight`, then scroll). */\n autoGrow?: boolean;\n /** Minimum height in px (a writing area that must start tall). `rows` also sizes it. */\n minHeight?: number;\n /** Maximum height in px; past it the field scrolls. */\n maxHeight?: number;\n /** Space occupied by an overlaid control cluster, so editable text stays clear of it. */\n reservedInlineEnd?: number;\n /** Space occupied by an overlaid row of controls at the bottom of the writing area. */\n reservedBlockEnd?: number;\n}\n\n/**\n * The field skin, multi-line (8px radius — a capsule cannot hold paragraphs). Height is the\n * textarea's own business — `rows`, `minHeight`/`maxHeight`, `autoGrow`, `resize` — never a class.\n */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, style, variant = \"field\", mono, hero, joinedBottom, autoGrow, minHeight, maxHeight, reservedInlineEnd, reservedBlockEnd, ...props }, forwarded) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n return (\n <textarea\n ref={callback}\n data-matrx-control=\"textarea\"\n data-variant={variant === \"bare\" ? \"bare\" : undefined}\n data-mono={mono ? \"\" : undefined}\n data-hero={hero ? \"\" : undefined}\n data-joined-bottom={joinedBottom ? \"\" : undefined}\n className={cn(\"matrx-control-textarea\", className)}\n style={{ ...boxStyle(minHeight, maxHeight), ...style,\n ...(reservedInlineEnd === undefined ? {} : { \"--matrx-textarea-reserved-inline-end\": `${Math.max(0, reservedInlineEnd)}px` }),\n ...(reservedBlockEnd === undefined ? {} : { \"--matrx-textarea-reserved-block-end\": `${Math.max(0, reservedBlockEnd)}px` }),\n } as React.CSSProperties}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = \"Textarea\";\n"],"mappings":"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","names":["Fragment"]}
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
import {
|
|
50
50
|
Button as Button2,
|
|
51
51
|
Chip
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-QOEKPR37.js";
|
|
53
53
|
import {
|
|
54
54
|
Tooltip,
|
|
55
55
|
TooltipContent,
|
|
@@ -3860,4 +3860,4 @@ export {
|
|
|
3860
3860
|
TileCard,
|
|
3861
3861
|
TileCardGrid
|
|
3862
3862
|
};
|
|
3863
|
-
//# sourceMappingURL=chunk-
|
|
3863
|
+
//# sourceMappingURL=chunk-RGJPHRU3.js.map
|
|
@@ -10,17 +10,17 @@ import {
|
|
|
10
10
|
} from "./chunk-FRJ4PPA2.js";
|
|
11
11
|
import {
|
|
12
12
|
PropertyRow
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DQUCOMAC.js";
|
|
14
14
|
import {
|
|
15
15
|
completeLayeredFilterRules,
|
|
16
16
|
layeredFilterMatchesValue
|
|
17
17
|
} from "./chunk-7ZCD4AZS.js";
|
|
18
18
|
import {
|
|
19
19
|
RecordId
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-Q2HWDJED.js";
|
|
21
21
|
import {
|
|
22
22
|
Button
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QOEKPR37.js";
|
|
24
24
|
import {
|
|
25
25
|
useMatrxDataTableHost
|
|
26
26
|
} from "./chunk-POJ3RR3K.js";
|
|
@@ -671,4 +671,4 @@ export {
|
|
|
671
671
|
isUuidValue,
|
|
672
672
|
DataRowInspector
|
|
673
673
|
};
|
|
674
|
-
//# sourceMappingURL=chunk-
|
|
674
|
+
//# sourceMappingURL=chunk-VQ3G6AFN.js.map
|