@conscia-labs/design-system 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1764 @@
1
+ import {
2
+ appearanceOptions,
3
+ applyConsciaPreferences,
4
+ densityOptions
5
+ } from "./chunk-D5LYROOM.js";
6
+ import {
7
+ Button,
8
+ Card,
9
+ Checkbox,
10
+ Collapsible,
11
+ CollapsibleContent,
12
+ CollapsibleTrigger,
13
+ Dialog,
14
+ DialogBody,
15
+ DialogClose,
16
+ DialogContent,
17
+ DialogDescription,
18
+ DialogFooter,
19
+ DialogHeader,
20
+ DialogTitle,
21
+ DialogTrigger,
22
+ DropdownMenu,
23
+ DropdownMenuContent,
24
+ DropdownMenuGroup,
25
+ DropdownMenuItem,
26
+ DropdownMenuLabel,
27
+ DropdownMenuTrigger,
28
+ Select,
29
+ SelectContent,
30
+ SelectItem,
31
+ SelectTrigger,
32
+ SelectValue,
33
+ Separator,
34
+ Sheet,
35
+ SheetContent,
36
+ SheetDescription,
37
+ SheetHeader,
38
+ SheetTitle,
39
+ Skeleton,
40
+ Table,
41
+ TableBody,
42
+ TableCell,
43
+ TableHead,
44
+ TableHeader,
45
+ TableRow,
46
+ Tabs,
47
+ TabsContent,
48
+ TabsList,
49
+ TabsTrigger,
50
+ Tooltip,
51
+ TooltipContent,
52
+ TooltipProvider,
53
+ TooltipTrigger
54
+ } from "./chunk-YHPZ5CQU.js";
55
+ import {
56
+ cn
57
+ } from "./chunk-JU5DQXFC.js";
58
+
59
+ // src/patterns/pagination.tsx
60
+ import { ChevronLeft, ChevronRight } from "lucide-react";
61
+ import { jsx, jsxs } from "react/jsx-runtime";
62
+ function PaginationControls({
63
+ currentPage,
64
+ pageCount,
65
+ totalLabel,
66
+ onPrevious,
67
+ onNext,
68
+ onPageChange,
69
+ pageSize,
70
+ pageSizeOptions = [10, 25, 50],
71
+ onPageSizeChange,
72
+ className,
73
+ ...props
74
+ }) {
75
+ return /* @__PURE__ */ jsxs(
76
+ "div",
77
+ {
78
+ "data-slot": "pagination-controls",
79
+ className: cn("flex flex-col gap-2 border-t border-border-subtle px-5 py-3 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between", className),
80
+ ...props,
81
+ children: [
82
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
83
+ /* @__PURE__ */ jsx("span", { children: totalLabel }),
84
+ pageSize && onPageSizeChange ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
85
+ /* @__PURE__ */ jsx("span", { className: "text-[var(--ds-metadata)]", children: "Rows" }),
86
+ /* @__PURE__ */ jsxs(Select, { value: String(pageSize), onValueChange: (value) => onPageSizeChange(Number(value)), children: [
87
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-[4.5rem]", "aria-label": "Rows per page", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
88
+ /* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: String(size), children: size }, size)) })
89
+ ] })
90
+ ] }) : null
91
+ ] }),
92
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
93
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "icon", className: "size-8", "aria-label": "Previous page", onClick: onPrevious ?? (() => onPageChange?.(currentPage - 1)), disabled: currentPage <= 1, children: /* @__PURE__ */ jsx(ChevronLeft, {}) }),
94
+ onPageChange ? pageItems(currentPage, pageCount).map((item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx("span", { className: "flex size-8 items-center justify-center text-muted-foreground", "aria-hidden": "true", children: "\u2026" }, `ellipsis-${index}`) : /* @__PURE__ */ jsx(Button, { type: "button", variant: item === currentPage ? "secondary" : "ghost", size: "icon", className: "size-8", "aria-label": `Page ${item}`, "aria-current": item === currentPage ? "page" : void 0, onClick: () => onPageChange(item), children: item }, item)) : /* @__PURE__ */ jsxs("span", { className: "px-2 text-[var(--ds-metadata)]", children: [
95
+ "Page ",
96
+ currentPage,
97
+ " of ",
98
+ pageCount
99
+ ] }),
100
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "icon", className: "size-8", "aria-label": "Next page", onClick: onNext ?? (() => onPageChange?.(currentPage + 1)), disabled: currentPage >= pageCount, children: /* @__PURE__ */ jsx(ChevronRight, {}) })
101
+ ] })
102
+ ]
103
+ }
104
+ );
105
+ }
106
+ function pageItems(currentPage, pageCount) {
107
+ if (pageCount <= 7) return Array.from({ length: pageCount }, (_, index) => index + 1);
108
+ const pages = /* @__PURE__ */ new Set([1, pageCount, currentPage - 1, currentPage, currentPage + 1]);
109
+ const sorted = Array.from(pages).filter((page) => page > 0 && page <= pageCount).sort((a, b) => a - b);
110
+ const result = [];
111
+ sorted.forEach((page, index) => {
112
+ if (index && page - sorted[index - 1] > 1) result.push("ellipsis");
113
+ result.push(page);
114
+ });
115
+ return result;
116
+ }
117
+
118
+ // src/patterns/data-table.tsx
119
+ import * as React from "react";
120
+ import {
121
+ flexRender,
122
+ getCoreRowModel,
123
+ getPaginationRowModel,
124
+ getSortedRowModel,
125
+ useReactTable
126
+ } from "@tanstack/react-table";
127
+ import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
128
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
129
+ function DataTable({
130
+ data,
131
+ columns,
132
+ getRowId,
133
+ getRowLabel,
134
+ onRowClick,
135
+ isRowClickable,
136
+ rowActions,
137
+ selectedIds,
138
+ onSelectionChange,
139
+ sorting,
140
+ onSortingChange,
141
+ manualSorting = false,
142
+ pagination,
143
+ onPaginationChange,
144
+ manualPagination = false,
145
+ pageCount,
146
+ rowCount,
147
+ pageSizeOptions,
148
+ totalLabel,
149
+ mobileRow,
150
+ empty,
151
+ className
152
+ }) {
153
+ const rowSelection = React.useMemo(() => {
154
+ const selection = {};
155
+ selectedIds?.forEach((id) => {
156
+ selection[id] = true;
157
+ });
158
+ return selection;
159
+ }, [selectedIds]);
160
+ const tableColumns = React.useMemo(() => {
161
+ const result = [];
162
+ if (onSelectionChange) {
163
+ result.push({
164
+ id: "select",
165
+ enableSorting: false,
166
+ header: ({ table: table2 }) => /* @__PURE__ */ jsx2(
167
+ Checkbox,
168
+ {
169
+ "aria-label": "Select all rows on this page",
170
+ checked: table2.getIsAllPageRowsSelected() || table2.getIsSomePageRowsSelected() && "indeterminate",
171
+ onCheckedChange: (checked) => table2.toggleAllPageRowsSelected(Boolean(checked))
172
+ }
173
+ ),
174
+ cell: ({ row }) => /* @__PURE__ */ jsx2(
175
+ Checkbox,
176
+ {
177
+ "aria-label": `Select ${getRowLabel?.(row.original) ?? row.id}`,
178
+ checked: row.getIsSelected(),
179
+ onCheckedChange: (checked) => row.toggleSelected(Boolean(checked)),
180
+ onClick: (event) => event.stopPropagation()
181
+ }
182
+ ),
183
+ meta: { className: "w-10" }
184
+ });
185
+ }
186
+ result.push(...columns.map((column) => ({
187
+ id: column.id,
188
+ ...column.accessor ? { accessorFn: column.accessor } : {},
189
+ enableSorting: column.sortable ?? false,
190
+ header: () => column.header,
191
+ cell: ({ row }) => column.cell(row.original),
192
+ meta: { className: column.className, label: typeof column.header === "string" ? column.header : column.id }
193
+ })));
194
+ if (rowActions) {
195
+ result.push({
196
+ id: "actions",
197
+ enableSorting: false,
198
+ header: "Actions",
199
+ cell: ({ row }) => /* @__PURE__ */ jsx2(
200
+ "div",
201
+ {
202
+ onClick: (event) => event.stopPropagation(),
203
+ onKeyDown: (event) => event.stopPropagation(),
204
+ children: rowActions(row.original)
205
+ }
206
+ ),
207
+ meta: { className: "w-12 text-right" }
208
+ });
209
+ }
210
+ return result;
211
+ }, [columns, getRowLabel, onSelectionChange, rowActions]);
212
+ const table = useReactTable({
213
+ data,
214
+ columns: tableColumns,
215
+ getRowId: (row) => getRowId(row),
216
+ state: { rowSelection, ...sorting ? { sorting } : {}, ...pagination ? { pagination } : {} },
217
+ enableRowSelection: Boolean(onSelectionChange),
218
+ onRowSelectionChange: (updater) => {
219
+ if (!onSelectionChange) return;
220
+ const next = typeof updater === "function" ? updater(rowSelection) : updater;
221
+ onSelectionChange(new Set(Object.keys(next).filter((id) => next[id])));
222
+ },
223
+ onSortingChange: (updater) => {
224
+ if (!onSortingChange) return;
225
+ onSortingChange(typeof updater === "function" ? updater(sorting ?? []) : updater);
226
+ },
227
+ onPaginationChange: (updater) => {
228
+ if (!onPaginationChange || !pagination) return;
229
+ onPaginationChange(typeof updater === "function" ? updater(pagination) : updater);
230
+ },
231
+ manualSorting,
232
+ manualPagination,
233
+ pageCount,
234
+ rowCount,
235
+ getCoreRowModel: getCoreRowModel(),
236
+ getSortedRowModel: manualSorting ? void 0 : getSortedRowModel(),
237
+ getPaginationRowModel: pagination && !manualPagination ? getPaginationRowModel() : void 0
238
+ });
239
+ if (!data.length && empty) return /* @__PURE__ */ jsx2(Fragment, { children: empty });
240
+ const visibleRows = table.getRowModel().rows;
241
+ const showPagination = Boolean(pagination && onPaginationChange);
242
+ return /* @__PURE__ */ jsxs2("div", { "data-slot": "data-table", className: cn("bg-background", className), children: [
243
+ /* @__PURE__ */ jsx2("div", { className: mobileRow ? "hidden md:block" : void 0, children: /* @__PURE__ */ jsxs2(Table, { children: [
244
+ /* @__PURE__ */ jsx2(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx2(TableRow, { children: headerGroup.headers.map((header) => {
245
+ const meta = header.column.columnDef.meta;
246
+ const canSort = header.column.getCanSort();
247
+ const sorted = header.column.getIsSorted();
248
+ return /* @__PURE__ */ jsx2(
249
+ TableHead,
250
+ {
251
+ className: meta?.className,
252
+ "aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
253
+ children: header.isPlaceholder ? null : canSort ? /* @__PURE__ */ jsxs2(
254
+ Button,
255
+ {
256
+ type: "button",
257
+ variant: "ghost",
258
+ size: "sm",
259
+ className: "-ml-2 h-8 gap-1.5 px-2 text-[var(--ds-metadata)] font-semibold uppercase text-muted-foreground hover:text-foreground",
260
+ onClick: header.column.getToggleSortingHandler(),
261
+ "aria-label": `Sort by ${meta?.label ?? header.column.id}`,
262
+ children: [
263
+ flexRender(header.column.columnDef.header, header.getContext()),
264
+ sorted === "asc" ? /* @__PURE__ */ jsx2(ArrowUp, { className: "size-3.5" }) : sorted === "desc" ? /* @__PURE__ */ jsx2(ArrowDown, { className: "size-3.5" }) : /* @__PURE__ */ jsx2(ChevronsUpDown, { className: "size-3.5 opacity-60" })
265
+ ]
266
+ }
267
+ ) : flexRender(header.column.columnDef.header, header.getContext())
268
+ },
269
+ header.id
270
+ );
271
+ }) }, headerGroup.id)) }),
272
+ /* @__PURE__ */ jsx2(TableBody, { children: visibleRows.map((row) => {
273
+ const rowClickable = Boolean(
274
+ onRowClick && (isRowClickable?.(row.original) ?? true)
275
+ );
276
+ return /* @__PURE__ */ jsx2(
277
+ TableRow,
278
+ {
279
+ "data-state": row.getIsSelected() ? "selected" : void 0,
280
+ tabIndex: rowClickable ? 0 : void 0,
281
+ "aria-label": rowClickable ? getRowLabel?.(row.original) ?? row.id : void 0,
282
+ className: cn(rowClickable && "cursor-pointer outline-none focus-visible:ring-[3px] focus-visible:ring-ring/45"),
283
+ onClick: () => {
284
+ if (rowClickable) onRowClick?.(row.original);
285
+ },
286
+ onKeyDown: (event) => {
287
+ if (!rowClickable || event.key !== "Enter" && event.key !== " ") return;
288
+ event.preventDefault();
289
+ onRowClick?.(row.original);
290
+ },
291
+ children: row.getVisibleCells().map((cell) => {
292
+ const meta = cell.column.columnDef.meta;
293
+ return /* @__PURE__ */ jsx2(TableCell, { className: meta?.className, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
294
+ })
295
+ },
296
+ row.id
297
+ );
298
+ }) })
299
+ ] }) }),
300
+ mobileRow ? /* @__PURE__ */ jsx2("div", { className: "divide-y divide-border-subtle md:hidden", role: "list", children: visibleRows.map((row) => /* @__PURE__ */ jsx2("div", { role: "listitem", children: mobileRow(row.original) }, row.id)) }) : null,
301
+ showPagination ? /* @__PURE__ */ jsx2(
302
+ PaginationControls,
303
+ {
304
+ currentPage: pagination.pageIndex + 1,
305
+ pageCount: Math.max(1, table.getPageCount()),
306
+ pageSize: pagination.pageSize,
307
+ pageSizeOptions,
308
+ totalLabel,
309
+ onPageChange: (nextPage) => table.setPageIndex(nextPage - 1),
310
+ onPageSizeChange: (nextSize) => table.setPageSize(nextSize)
311
+ }
312
+ ) : null
313
+ ] });
314
+ }
315
+
316
+ // src/patterns/entity-table.tsx
317
+ import { jsx as jsx3 } from "react/jsx-runtime";
318
+ function EntityTable({
319
+ items,
320
+ columns,
321
+ getRowId,
322
+ selectedIds,
323
+ onSelectionChange,
324
+ onRowClick,
325
+ getRowLabel,
326
+ rowActions,
327
+ className
328
+ }) {
329
+ return /* @__PURE__ */ jsx3(
330
+ DataTable,
331
+ {
332
+ data: items,
333
+ columns: columns.map((column) => ({ ...column, id: column.key })),
334
+ getRowId,
335
+ selectedIds,
336
+ onSelectionChange,
337
+ onRowClick,
338
+ getRowLabel,
339
+ rowActions,
340
+ className
341
+ }
342
+ );
343
+ }
344
+
345
+ // src/patterns/detail-back-link.tsx
346
+ import { ArrowLeft } from "lucide-react";
347
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
348
+ function DetailBackLink({ label, className, ...props }) {
349
+ return /* @__PURE__ */ jsxs3(
350
+ "a",
351
+ {
352
+ "data-slot": "detail-back-link",
353
+ className: cn(
354
+ "inline-flex h-8 w-fit items-center gap-2 rounded-md px-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-surface-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/45",
355
+ className
356
+ ),
357
+ ...props,
358
+ children: [
359
+ /* @__PURE__ */ jsx4(ArrowLeft, { className: "size-4", "aria-hidden": "true" }),
360
+ label
361
+ ]
362
+ }
363
+ );
364
+ }
365
+
366
+ // src/patterns/app-shell.tsx
367
+ import * as React2 from "react";
368
+ import { Slot } from "@radix-ui/react-slot";
369
+ import { PanelLeftIcon } from "lucide-react";
370
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
371
+ var SIDEBAR_COOKIE_NAME = "conscia_sidebar_state";
372
+ var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
373
+ var SIDEBAR_KEYBOARD_SHORTCUT = "b";
374
+ var SIDEBAR_STORAGE_KEY = "conscia-sidebar-open:v1";
375
+ var SIDEBAR_STATE_CHANGE_EVENT = "conscia-sidebar-state-change";
376
+ function parseSidebarOpen(value) {
377
+ return value === "true" ? true : value === "false" ? false : null;
378
+ }
379
+ function readPersistedSidebarOpen() {
380
+ if (typeof document === "undefined") {
381
+ return null;
382
+ }
383
+ try {
384
+ const storedValue = window.localStorage.getItem(SIDEBAR_STORAGE_KEY);
385
+ const storedSidebarOpen = parseSidebarOpen(storedValue);
386
+ if (storedSidebarOpen !== null) {
387
+ return storedSidebarOpen;
388
+ }
389
+ } catch {
390
+ }
391
+ const cookie = document.cookie.split("; ").find((entry) => entry.startsWith(`${SIDEBAR_COOKIE_NAME}=`));
392
+ if (!cookie) {
393
+ return null;
394
+ }
395
+ const value = cookie.slice(SIDEBAR_COOKIE_NAME.length + 1);
396
+ return parseSidebarOpen(value);
397
+ }
398
+ function persistSidebarOpen(open) {
399
+ try {
400
+ window.localStorage.setItem(SIDEBAR_STORAGE_KEY, String(open));
401
+ } catch {
402
+ }
403
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
404
+ window.dispatchEvent(new Event(SIDEBAR_STATE_CHANGE_EVENT));
405
+ }
406
+ function subscribeToSidebarOpen(onStoreChange) {
407
+ function onStorage(event) {
408
+ if (event.key === SIDEBAR_STORAGE_KEY) {
409
+ onStoreChange();
410
+ }
411
+ }
412
+ window.addEventListener(SIDEBAR_STATE_CHANGE_EVENT, onStoreChange);
413
+ window.addEventListener("storage", onStorage);
414
+ return () => {
415
+ window.removeEventListener(SIDEBAR_STATE_CHANGE_EVENT, onStoreChange);
416
+ window.removeEventListener("storage", onStorage);
417
+ };
418
+ }
419
+ var AppShellContext = React2.createContext(null);
420
+ function useAppShell() {
421
+ const context = React2.useContext(AppShellContext);
422
+ if (!context) {
423
+ throw new Error("useAppShell must be used within AppShell.");
424
+ }
425
+ return context;
426
+ }
427
+ function useMediaQuery(query) {
428
+ const [matches, setMatches] = React2.useState(false);
429
+ React2.useEffect(() => {
430
+ const media = window.matchMedia(query);
431
+ const sync = () => setMatches(media.matches);
432
+ sync();
433
+ media.addEventListener("change", sync);
434
+ return () => media.removeEventListener("change", sync);
435
+ }, [query]);
436
+ return matches;
437
+ }
438
+ function AppShell({
439
+ defaultSidebarOpen = true,
440
+ children,
441
+ className,
442
+ style,
443
+ ...props
444
+ }) {
445
+ const isMobile = useMediaQuery("(max-width: 1023px)");
446
+ const [sidebarOpen, setSidebarOpenState] = React2.useState(defaultSidebarOpen);
447
+ const [sidebarSide, setSidebarSide] = React2.useState("left");
448
+ const [mobileOpen, setMobileOpen] = React2.useState(false);
449
+ React2.useEffect(() => {
450
+ function syncSidebarOpen() {
451
+ setSidebarOpenState(readPersistedSidebarOpen() ?? defaultSidebarOpen);
452
+ }
453
+ const unsubscribe = subscribeToSidebarOpen(syncSidebarOpen);
454
+ queueMicrotask(syncSidebarOpen);
455
+ return unsubscribe;
456
+ }, [defaultSidebarOpen]);
457
+ const setSidebarOpen = React2.useCallback((open) => {
458
+ persistSidebarOpen(open);
459
+ }, []);
460
+ const toggleSidebar = React2.useCallback(() => {
461
+ if (isMobile) {
462
+ setMobileOpen((current) => !current);
463
+ return;
464
+ }
465
+ persistSidebarOpen(!sidebarOpen);
466
+ }, [isMobile, sidebarOpen]);
467
+ React2.useEffect(() => {
468
+ const onKeyDown = (event) => {
469
+ if (event.key.toLowerCase() === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
470
+ event.preventDefault();
471
+ toggleSidebar();
472
+ }
473
+ };
474
+ window.addEventListener("keydown", onKeyDown);
475
+ return () => window.removeEventListener("keydown", onKeyDown);
476
+ }, [toggleSidebar]);
477
+ const contextValue = React2.useMemo(
478
+ () => ({
479
+ sidebarState: sidebarOpen ? "expanded" : "collapsed",
480
+ sidebarSide,
481
+ setSidebarSide,
482
+ sidebarOpen,
483
+ setSidebarOpen,
484
+ mobileOpen,
485
+ setMobileOpen,
486
+ isMobile,
487
+ toggleSidebar
488
+ }),
489
+ [
490
+ isMobile,
491
+ mobileOpen,
492
+ setSidebarOpen,
493
+ sidebarOpen,
494
+ sidebarSide,
495
+ toggleSidebar
496
+ ]
497
+ );
498
+ return /* @__PURE__ */ jsx5(AppShellContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx5(TooltipProvider, { delayDuration: 120, children: /* @__PURE__ */ jsx5(
499
+ "div",
500
+ {
501
+ "data-slot": "app-shell",
502
+ "data-sidebar-state": sidebarOpen ? "expanded" : "collapsed",
503
+ "data-sidebar-side": sidebarSide,
504
+ suppressHydrationWarning: true,
505
+ className: cn(
506
+ "group/shell min-h-svh bg-canvas text-foreground",
507
+ "[--ds-app-sidebar-width:16rem] [--ds-app-sidebar-width-mobile:18rem] data-[sidebar-state=collapsed]:[--ds-app-sidebar-width:3.5rem]",
508
+ className
509
+ ),
510
+ style,
511
+ ...props,
512
+ children
513
+ }
514
+ ) }) });
515
+ }
516
+ function AppSidebar({
517
+ side = "left",
518
+ className,
519
+ children,
520
+ title = "Application navigation",
521
+ description = "Primary product navigation.",
522
+ ...props
523
+ }) {
524
+ const { mobileOpen, setMobileOpen, setSidebarSide } = useAppShell();
525
+ React2.useEffect(() => {
526
+ setSidebarSide(side);
527
+ }, [setSidebarSide, side]);
528
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
529
+ /* @__PURE__ */ jsx5(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: /* @__PURE__ */ jsxs4(
530
+ SheetContent,
531
+ {
532
+ side,
533
+ className: "w-72 border-sidebar-border bg-sidebar p-0 text-sidebar-foreground [&>[data-slot=sheet-close]]:right-3 [&>[data-slot=sheet-close]]:top-3 [&>[data-slot=sheet-close]]:text-sidebar-foreground/64 [&>[data-slot=sheet-close]]:hover:text-sidebar-foreground",
534
+ children: [
535
+ /* @__PURE__ */ jsxs4(SheetHeader, { className: "sr-only", children: [
536
+ /* @__PURE__ */ jsx5(SheetTitle, { children: title }),
537
+ /* @__PURE__ */ jsx5(SheetDescription, { children: description })
538
+ ] }),
539
+ /* @__PURE__ */ jsx5("div", { className: "flex h-full min-h-0 flex-col", children })
540
+ ]
541
+ }
542
+ ) }),
543
+ /* @__PURE__ */ jsx5(
544
+ "aside",
545
+ {
546
+ "data-slot": "app-sidebar",
547
+ "data-side": side,
548
+ className: cn(
549
+ "fixed inset-y-0 z-20 hidden w-[var(--ds-app-sidebar-width)] shrink-0 flex-col border-sidebar-border bg-sidebar text-sidebar-foreground transition-[width] duration-200 ease-linear lg:flex",
550
+ side === "left" ? "left-0 border-r" : "right-0 border-l",
551
+ "group-data-[sidebar-state=collapsed]/shell:w-[var(--ds-app-sidebar-width)]",
552
+ className
553
+ ),
554
+ ...props,
555
+ children
556
+ }
557
+ )
558
+ ] });
559
+ }
560
+ function AppSidebarHeader({
561
+ className,
562
+ ...props
563
+ }) {
564
+ return /* @__PURE__ */ jsx5(
565
+ "div",
566
+ {
567
+ "data-slot": "app-sidebar-header",
568
+ className: cn(
569
+ "flex min-h-14 shrink-0 items-center border-b border-sidebar-border px-3",
570
+ className
571
+ ),
572
+ ...props
573
+ }
574
+ );
575
+ }
576
+ function AppSidebarContent({
577
+ className,
578
+ ...props
579
+ }) {
580
+ return /* @__PURE__ */ jsx5(
581
+ "div",
582
+ {
583
+ "data-slot": "app-sidebar-content",
584
+ className: cn(
585
+ "flex min-h-0 flex-1 flex-col gap-[var(--ds-space-control)] overflow-y-auto px-2.5 py-3",
586
+ className
587
+ ),
588
+ ...props
589
+ }
590
+ );
591
+ }
592
+ function AppSidebarFooter({
593
+ className,
594
+ ...props
595
+ }) {
596
+ return /* @__PURE__ */ jsx5(
597
+ "div",
598
+ {
599
+ "data-slot": "app-sidebar-footer",
600
+ className: cn(
601
+ "mt-auto flex shrink-0 flex-col gap-2 border-t border-sidebar-border p-2.5",
602
+ className
603
+ ),
604
+ ...props
605
+ }
606
+ );
607
+ }
608
+ function ProductIdentity({
609
+ label,
610
+ description,
611
+ icon,
612
+ className
613
+ }) {
614
+ return /* @__PURE__ */ jsxs4(
615
+ "div",
616
+ {
617
+ "data-slot": "product-identity",
618
+ className: cn("flex min-w-0 items-center gap-2", className),
619
+ children: [
620
+ icon ? /* @__PURE__ */ jsx5("div", { className: "flex size-7 shrink-0 items-center justify-center rounded-[var(--ds-radius-control)] bg-sidebar-accent text-sidebar-foreground", children: icon }) : null,
621
+ /* @__PURE__ */ jsxs4("div", { className: "min-w-0 group-data-[sidebar-state=collapsed]/shell:hidden", children: [
622
+ /* @__PURE__ */ jsx5("div", { className: "truncate text-sm font-semibold leading-5 text-sidebar-foreground", children: label }),
623
+ description ? /* @__PURE__ */ jsx5("div", { className: "truncate text-[var(--ds-metadata)] leading-4 text-sidebar-foreground/62", children: description }) : null
624
+ ] })
625
+ ]
626
+ }
627
+ );
628
+ }
629
+ function SidebarSeparator({
630
+ className,
631
+ ...props
632
+ }) {
633
+ return /* @__PURE__ */ jsx5(
634
+ Separator,
635
+ {
636
+ "data-slot": "app-sidebar-separator",
637
+ className: cn("bg-sidebar-border", className),
638
+ ...props
639
+ }
640
+ );
641
+ }
642
+ function NavigationGroup({
643
+ label,
644
+ children,
645
+ className
646
+ }) {
647
+ return /* @__PURE__ */ jsxs4(
648
+ "section",
649
+ {
650
+ "data-slot": "navigation-group",
651
+ className: cn("flex min-w-0 flex-col gap-1", className),
652
+ children: [
653
+ label ? /* @__PURE__ */ jsx5("div", { className: "px-2 pb-1 pt-2 text-[0.6875rem] font-medium uppercase tracking-normal text-sidebar-foreground/52 group-data-[sidebar-state=collapsed]/shell:hidden", children: label }) : null,
654
+ /* @__PURE__ */ jsx5("div", { className: "flex min-w-0 flex-col gap-1", children })
655
+ ]
656
+ }
657
+ );
658
+ }
659
+ function navigationItemClasses(active) {
660
+ return cn(
661
+ "flex h-11 min-w-0 items-center gap-2 rounded-[var(--ds-radius-control)] px-2 text-sm font-medium text-sidebar-foreground/78 outline-none transition-colors duration-150 lg:h-[var(--ds-sidebar-item-height)]",
662
+ "hover:bg-sidebar-accent hover:text-sidebar-foreground",
663
+ "focus-visible:ring-[3px] focus-visible:ring-ring/35",
664
+ "disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50",
665
+ "group-data-[sidebar-state=collapsed]/shell:justify-center group-data-[sidebar-state=collapsed]/shell:px-0",
666
+ "[&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-[1.75]",
667
+ active && "bg-sidebar-active text-sidebar-active-foreground shadow-[inset_2px_0_0_var(--sidebar-active-indicator)] hover:bg-sidebar-active hover:text-sidebar-active-foreground"
668
+ );
669
+ }
670
+ function NavigationItem({
671
+ asChild = false,
672
+ active = false,
673
+ tooltip,
674
+ type,
675
+ className,
676
+ children,
677
+ ...props
678
+ }) {
679
+ const Comp = asChild ? Slot : "button";
680
+ const { sidebarState, sidebarSide, isMobile } = useAppShell();
681
+ const item = /* @__PURE__ */ jsx5(
682
+ Comp,
683
+ {
684
+ "data-slot": "navigation-item",
685
+ "data-active": active ? "true" : void 0,
686
+ type: asChild ? void 0 : type ?? "button",
687
+ className: cn(navigationItemClasses(active), className),
688
+ ...props,
689
+ children
690
+ }
691
+ );
692
+ if (!tooltip) {
693
+ return item;
694
+ }
695
+ return /* @__PURE__ */ jsxs4(Tooltip, { children: [
696
+ /* @__PURE__ */ jsx5(TooltipTrigger, { asChild: true, children: item }),
697
+ /* @__PURE__ */ jsx5(
698
+ TooltipContent,
699
+ {
700
+ side: sidebarSide === "left" ? "right" : "left",
701
+ align: "center",
702
+ hidden: sidebarState !== "collapsed" || isMobile,
703
+ children: tooltip
704
+ }
705
+ )
706
+ ] });
707
+ }
708
+ function NavigationSubItem({
709
+ asChild = false,
710
+ active = false,
711
+ className,
712
+ ...props
713
+ }) {
714
+ const Comp = asChild ? Slot : "a";
715
+ return /* @__PURE__ */ jsx5(
716
+ Comp,
717
+ {
718
+ "data-slot": "navigation-sub-item",
719
+ "data-active": active ? "true" : void 0,
720
+ className: cn(
721
+ "flex h-11 min-w-0 items-center gap-2 rounded-[var(--ds-radius-control)] px-2 text-sm text-sidebar-foreground/72 outline-none transition-colors duration-150 lg:h-[calc(var(--ds-sidebar-item-height)-0.25rem)]",
722
+ "hover:bg-sidebar-accent hover:text-sidebar-foreground focus-visible:ring-[3px] focus-visible:ring-ring/35",
723
+ "group-data-[sidebar-state=collapsed]/shell:hidden [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-[1.75]",
724
+ active && "bg-sidebar-active text-sidebar-active-foreground shadow-[inset_2px_0_0_var(--sidebar-active-indicator)] hover:bg-sidebar-active hover:text-sidebar-active-foreground",
725
+ className
726
+ ),
727
+ ...props
728
+ }
729
+ );
730
+ }
731
+ function NavigationSubList({
732
+ className,
733
+ ...props
734
+ }) {
735
+ return /* @__PURE__ */ jsx5(
736
+ "div",
737
+ {
738
+ "data-slot": "navigation-sub-list",
739
+ className: cn(
740
+ "ml-4 flex min-w-0 flex-col gap-1 border-l border-sidebar-border pl-2 group-data-[sidebar-state=collapsed]/shell:hidden",
741
+ className
742
+ ),
743
+ ...props
744
+ }
745
+ );
746
+ }
747
+ function SidebarTrigger({
748
+ className,
749
+ onClick,
750
+ ...props
751
+ }) {
752
+ const { toggleSidebar } = useAppShell();
753
+ return /* @__PURE__ */ jsxs4(
754
+ Button,
755
+ {
756
+ "data-slot": "sidebar-trigger",
757
+ type: "button",
758
+ variant: "ghost",
759
+ size: "icon",
760
+ className: cn("shrink-0", className),
761
+ onClick: (event) => {
762
+ onClick?.(event);
763
+ toggleSidebar();
764
+ },
765
+ ...props,
766
+ children: [
767
+ /* @__PURE__ */ jsx5(PanelLeftIcon, {}),
768
+ /* @__PURE__ */ jsx5("span", { className: "sr-only", children: "Toggle navigation" })
769
+ ]
770
+ }
771
+ );
772
+ }
773
+ function MainRegion({
774
+ className,
775
+ ...props
776
+ }) {
777
+ return /* @__PURE__ */ jsx5(
778
+ "div",
779
+ {
780
+ "data-slot": "main-region",
781
+ className: cn(
782
+ "flex min-h-svh min-w-0 w-full flex-1 flex-col transition-[padding] duration-200 ease-linear",
783
+ "group-data-[sidebar-side=left]/shell:lg:pl-[var(--ds-app-sidebar-width)] group-data-[sidebar-side=right]/shell:lg:pr-[var(--ds-app-sidebar-width)]",
784
+ className
785
+ ),
786
+ ...props
787
+ }
788
+ );
789
+ }
790
+ function TopBar({
791
+ className,
792
+ ...props
793
+ }) {
794
+ return /* @__PURE__ */ jsx5(
795
+ "header",
796
+ {
797
+ "data-slot": "top-bar",
798
+ className: cn(
799
+ "sticky top-0 z-10 flex min-h-14 shrink-0 items-center justify-between gap-3 border-b border-border-subtle bg-background/96 px-3 backdrop-blur md:px-4",
800
+ "supports-[backdrop-filter]:bg-background/88",
801
+ className
802
+ ),
803
+ ...props
804
+ }
805
+ );
806
+ }
807
+ function PageFrame({
808
+ width = "full",
809
+ className,
810
+ ...props
811
+ }) {
812
+ return /* @__PURE__ */ jsx5(
813
+ "main",
814
+ {
815
+ "data-slot": "page-frame",
816
+ "data-width": width,
817
+ className: cn(
818
+ "min-w-0 w-full flex-1 px-3 py-[var(--ds-space-section)] md:px-[var(--ds-space-page)]",
819
+ width === "wide" && "mx-auto w-full max-w-[86rem]",
820
+ width === "focused" && "mx-auto w-full max-w-[64rem]",
821
+ width === "reading" && "mx-auto w-full max-w-[48rem]",
822
+ className
823
+ ),
824
+ ...props
825
+ }
826
+ );
827
+ }
828
+ function PageContent({
829
+ className,
830
+ ...props
831
+ }) {
832
+ return /* @__PURE__ */ jsx5(
833
+ "div",
834
+ {
835
+ "data-slot": "page-content",
836
+ className: cn("flex min-w-0 flex-col gap-[var(--ds-space-section)]", className),
837
+ ...props
838
+ }
839
+ );
840
+ }
841
+ function PageBoundary({
842
+ className,
843
+ ...props
844
+ }) {
845
+ return /* @__PURE__ */ jsx5(
846
+ "div",
847
+ {
848
+ "data-slot": "page-boundary",
849
+ className: cn(
850
+ "rounded-[var(--ds-radius-surface)] border border-border-subtle bg-surface p-[var(--ds-surface-padding)]",
851
+ className
852
+ ),
853
+ ...props
854
+ }
855
+ );
856
+ }
857
+ function InspectorRegion({
858
+ className,
859
+ ...props
860
+ }) {
861
+ return /* @__PURE__ */ jsx5(
862
+ "aside",
863
+ {
864
+ "data-slot": "inspector-region",
865
+ className: cn(
866
+ "w-full border-l border-border-subtle bg-surface md:w-[20rem] xl:w-[24rem]",
867
+ className
868
+ ),
869
+ ...props
870
+ }
871
+ );
872
+ }
873
+
874
+ // src/patterns/activity-list.tsx
875
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
876
+ function ActivityList({ className, ...props }) {
877
+ return /* @__PURE__ */ jsx6("div", { "data-slot": "activity-list", className: cn("divide-y divide-border-subtle", className), ...props });
878
+ }
879
+ function ActivityItem({ icon, title, description, metadata, status, className, ...props }) {
880
+ return /* @__PURE__ */ jsxs5("div", { "data-slot": "activity-item", className: cn("grid grid-cols-[auto_minmax(0,1fr)_auto] gap-3 py-3", className), ...props, children: [
881
+ /* @__PURE__ */ jsx6("div", { className: "flex size-8 items-center justify-center rounded-md bg-neutral-background text-neutral-foreground [&_svg]:size-4", children: icon }),
882
+ /* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
883
+ /* @__PURE__ */ jsx6("div", { className: "text-sm font-medium text-foreground", children: title }),
884
+ description ? /* @__PURE__ */ jsx6("div", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null,
885
+ metadata ? /* @__PURE__ */ jsx6("div", { className: "mt-1 text-[var(--ds-metadata)] text-muted-foreground", children: metadata }) : null
886
+ ] }),
887
+ status ? /* @__PURE__ */ jsx6("div", { className: "shrink-0", children: status }) : null
888
+ ] });
889
+ }
890
+
891
+ // src/patterns/confirmation-dialog.tsx
892
+ import * as React3 from "react";
893
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
894
+ function ConfirmationDialog({ trigger, title, description, children, confirmLabel = "Confirm", cancelLabel = "Cancel", confirmVariant = "destructive", pending = false, onConfirm, onError }) {
895
+ const [open, setOpen] = React3.useState(false);
896
+ const [confirming, setConfirming] = React3.useState(false);
897
+ const isPending = pending || confirming;
898
+ async function confirm() {
899
+ if (isPending) {
900
+ return;
901
+ }
902
+ setConfirming(true);
903
+ try {
904
+ await onConfirm();
905
+ setOpen(false);
906
+ } catch (error) {
907
+ onError?.(error);
908
+ } finally {
909
+ setConfirming(false);
910
+ }
911
+ }
912
+ return /* @__PURE__ */ jsxs6(Dialog, { open, onOpenChange: setOpen, children: [
913
+ /* @__PURE__ */ jsx7(DialogTrigger, { asChild: true, children: trigger }),
914
+ /* @__PURE__ */ jsxs6(DialogContent, { size: "small", children: [
915
+ /* @__PURE__ */ jsxs6(DialogHeader, { children: [
916
+ /* @__PURE__ */ jsx7(DialogTitle, { children: title }),
917
+ /* @__PURE__ */ jsx7(DialogDescription, { children: description })
918
+ ] }),
919
+ /* @__PURE__ */ jsx7(DialogBody, { children }),
920
+ /* @__PURE__ */ jsxs6(DialogFooter, { children: [
921
+ /* @__PURE__ */ jsx7(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx7(Button, { type: "button", variant: "outline", disabled: isPending, children: cancelLabel }) }),
922
+ /* @__PURE__ */ jsx7(Button, { type: "button", variant: confirmVariant, disabled: isPending, onClick: confirm, children: isPending ? "Working..." : confirmLabel })
923
+ ] })
924
+ ] })
925
+ ] });
926
+ }
927
+
928
+ // src/patterns/code-block.tsx
929
+ import * as React4 from "react";
930
+ import { Check, Copy } from "lucide-react";
931
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
932
+ function CodeBlock({
933
+ snippets,
934
+ defaultValue,
935
+ copyLabel = "Copy code",
936
+ className,
937
+ ...props
938
+ }) {
939
+ const initialValue = defaultValue ?? snippets[0]?.value ?? "";
940
+ const [activeValue, setActiveValue] = React4.useState(initialValue);
941
+ const [copiedValue, setCopiedValue] = React4.useState(null);
942
+ const [copyError, setCopyError] = React4.useState(false);
943
+ const copyStatusId = React4.useId();
944
+ const activeSnippet = snippets.find((snippet) => snippet.value === activeValue) ?? snippets[0];
945
+ if (!activeSnippet) return null;
946
+ return /* @__PURE__ */ jsx8(
947
+ "div",
948
+ {
949
+ "data-slot": "code-block",
950
+ className: cn("overflow-hidden rounded-lg border border-border-subtle bg-surface", className),
951
+ ...props,
952
+ children: /* @__PURE__ */ jsxs7(Tabs, { value: activeSnippet.value, onValueChange: setActiveValue, variant: "segmented", className: "gap-0", children: [
953
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3 border-b border-border-subtle bg-surface-muted px-3 py-2", children: [
954
+ /* @__PURE__ */ jsx8(TabsList, { variant: "segmented", size: "compact", "aria-label": "Code language", children: snippets.map((snippet) => /* @__PURE__ */ jsx8(TabsTrigger, { value: snippet.value, children: snippet.label }, snippet.value)) }),
955
+ /* @__PURE__ */ jsxs7(
956
+ Button,
957
+ {
958
+ type: "button",
959
+ variant: "ghost",
960
+ size: "sm",
961
+ onClick: async () => {
962
+ try {
963
+ await navigator.clipboard.writeText(activeSnippet.code);
964
+ setCopiedValue(activeSnippet.value);
965
+ setCopyError(false);
966
+ } catch {
967
+ setCopiedValue(null);
968
+ setCopyError(true);
969
+ }
970
+ },
971
+ "aria-describedby": copyStatusId,
972
+ children: [
973
+ copiedValue === activeSnippet.value ? /* @__PURE__ */ jsx8(Check, {}) : /* @__PURE__ */ jsx8(Copy, {}),
974
+ copiedValue === activeSnippet.value ? "Copied" : copyLabel
975
+ ]
976
+ }
977
+ ),
978
+ /* @__PURE__ */ jsx8("span", { id: copyStatusId, className: "sr-only", role: "status", "aria-live": "polite", children: copyError ? "Code could not be copied. Select the code and copy it manually." : copiedValue === activeSnippet.value ? "Code copied to clipboard." : "" })
979
+ ] }),
980
+ snippets.map((snippet) => /* @__PURE__ */ jsx8(TabsContent, { value: snippet.value, className: "m-0", children: /* @__PURE__ */ jsx8("pre", { className: "max-h-[32rem] overflow-auto p-4 text-sm leading-6", children: /* @__PURE__ */ jsx8("code", { children: snippet.code }) }) }, snippet.value))
981
+ ] })
982
+ }
983
+ );
984
+ }
985
+
986
+ // src/patterns/inventory-surface.tsx
987
+ import { jsx as jsx9 } from "react/jsx-runtime";
988
+ function InventorySurface({ className, ...props }) {
989
+ return /* @__PURE__ */ jsx9(
990
+ Card,
991
+ {
992
+ "data-slot": "inventory-surface",
993
+ className: cn("gap-0 overflow-hidden py-0", className),
994
+ ...props
995
+ }
996
+ );
997
+ }
998
+ function InventoryDesktop({ className, ...props }) {
999
+ return /* @__PURE__ */ jsx9("div", { "data-slot": "inventory-desktop", className: cn("hidden lg:block", className), ...props });
1000
+ }
1001
+ function InventoryMobile({ className, ...props }) {
1002
+ return /* @__PURE__ */ jsx9("div", { "data-slot": "inventory-mobile", className: cn("divide-y divide-border-subtle lg:hidden", className), ...props });
1003
+ }
1004
+
1005
+ // src/patterns/metric-band.tsx
1006
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1007
+ function MetricBand({ columns = 4, className, ...props }) {
1008
+ return /* @__PURE__ */ jsx10(
1009
+ "div",
1010
+ {
1011
+ "data-slot": "metric-band",
1012
+ "data-columns": columns,
1013
+ className: cn(
1014
+ "grid grid-cols-2 border-b border-border-subtle",
1015
+ columns === 2 && "lg:grid-cols-2",
1016
+ columns === 3 && "lg:grid-cols-3",
1017
+ columns === 4 && "lg:grid-cols-4",
1018
+ columns === 5 && "lg:grid-cols-5",
1019
+ className
1020
+ ),
1021
+ ...props
1022
+ }
1023
+ );
1024
+ }
1025
+ function MetricBandItem({
1026
+ label,
1027
+ value,
1028
+ detail,
1029
+ icon,
1030
+ iconClassName,
1031
+ loading = false,
1032
+ className,
1033
+ ...props
1034
+ }) {
1035
+ return /* @__PURE__ */ jsxs8(
1036
+ "div",
1037
+ {
1038
+ "data-slot": "metric-band-item",
1039
+ className: cn(
1040
+ "flex min-h-28 flex-col items-start gap-3 border-r border-border-subtle p-4 last:border-r-0 sm:flex-row sm:items-center sm:gap-4 sm:p-5",
1041
+ "[&:nth-child(-n+2)]:border-b lg:[&:nth-child(-n+2)]:border-b-0",
1042
+ className
1043
+ ),
1044
+ ...props,
1045
+ children: [
1046
+ icon ? /* @__PURE__ */ jsx10(
1047
+ "div",
1048
+ {
1049
+ className: cn(
1050
+ "flex size-10 shrink-0 items-center justify-center rounded-md bg-neutral-background text-neutral-foreground [&_svg]:size-5",
1051
+ iconClassName
1052
+ ),
1053
+ children: icon
1054
+ }
1055
+ ) : null,
1056
+ /* @__PURE__ */ jsxs8("div", { className: "grid min-w-0 gap-1", children: [
1057
+ /* @__PURE__ */ jsx10("div", { className: "text-sm leading-snug text-muted-foreground", children: label }),
1058
+ loading ? /* @__PURE__ */ jsx10(Skeleton, { className: "h-7 w-14" }) : /* @__PURE__ */ jsx10("div", { className: "text-2xl font-semibold tracking-tight", children: value ?? 0 }),
1059
+ detail ? /* @__PURE__ */ jsx10("div", { className: "text-[var(--ds-metadata)] leading-snug text-muted-foreground", children: detail }) : null
1060
+ ] })
1061
+ ]
1062
+ }
1063
+ );
1064
+ }
1065
+
1066
+ // src/patterns/page-header.tsx
1067
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1068
+ function PageHeader({
1069
+ title,
1070
+ description,
1071
+ status,
1072
+ metadata,
1073
+ actions,
1074
+ action,
1075
+ actionNode,
1076
+ className,
1077
+ ...props
1078
+ }) {
1079
+ const resolvedActions = actions ?? actionNode ?? (action ? /* @__PURE__ */ jsx11(
1080
+ "a",
1081
+ {
1082
+ className: "inline-flex h-[var(--ds-control-height)] items-center justify-center gap-2 whitespace-nowrap rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground shadow-xs outline-none transition-colors hover:bg-accent-hover focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
1083
+ href: action.href,
1084
+ children: action.label
1085
+ }
1086
+ ) : null);
1087
+ return /* @__PURE__ */ jsxs9(
1088
+ "header",
1089
+ {
1090
+ "data-slot": "page-header",
1091
+ className: cn("flex flex-col gap-3 border-b border-border-subtle bg-background px-5 py-4 lg:flex-row lg:items-start lg:justify-between", className),
1092
+ ...props,
1093
+ children: [
1094
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
1095
+ /* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
1096
+ /* @__PURE__ */ jsx11("h1", { className: "truncate text-[length:var(--ds-page-title)] font-semibold leading-tight", children: title }),
1097
+ status
1098
+ ] }),
1099
+ description ? /* @__PURE__ */ jsx11("p", { className: "mt-1 max-w-3xl text-sm text-muted-foreground", children: description }) : null,
1100
+ metadata ? /* @__PURE__ */ jsx11("div", { className: "mt-2 text-[var(--ds-metadata)] text-muted-foreground", children: metadata }) : null
1101
+ ] }),
1102
+ resolvedActions ? /* @__PURE__ */ jsx11("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: resolvedActions }) : null
1103
+ ]
1104
+ }
1105
+ );
1106
+ }
1107
+
1108
+ // src/patterns/page-toolbar.tsx
1109
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1110
+ function PageToolbar({
1111
+ search,
1112
+ filters,
1113
+ viewControls,
1114
+ bulkActions,
1115
+ className,
1116
+ children,
1117
+ ...props
1118
+ }) {
1119
+ return /* @__PURE__ */ jsxs10(
1120
+ "div",
1121
+ {
1122
+ "data-slot": "page-toolbar",
1123
+ className: cn("grid gap-2 border-b border-border-subtle bg-background px-5 py-3 lg:grid-cols-[minmax(0,1fr)_auto] lg:items-center", className),
1124
+ ...props,
1125
+ children: [
1126
+ /* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 flex-1 flex-col gap-2 sm:flex-row sm:items-center", children: [
1127
+ search ? /* @__PURE__ */ jsx12("div", { className: "min-w-0 flex-1 sm:min-w-48 sm:max-w-sm", children: search }) : null,
1128
+ filters ? /* @__PURE__ */ jsx12("div", { className: "flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:flex-wrap sm:items-center", children: filters }) : null
1129
+ ] }),
1130
+ /* @__PURE__ */ jsxs10("div", { className: "flex min-h-[var(--ds-control-height)] flex-wrap items-center gap-2 lg:justify-end", children: [
1131
+ bulkActions ? /* @__PURE__ */ jsx12("div", { "data-slot": "page-toolbar-bulk-actions", className: "contents", children: bulkActions }) : null,
1132
+ viewControls,
1133
+ children
1134
+ ] })
1135
+ ]
1136
+ }
1137
+ );
1138
+ }
1139
+
1140
+ // src/patterns/preference-controls.tsx
1141
+ import * as React5 from "react";
1142
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1143
+ var APPEARANCE_KEY = "conscia-appearance:v1";
1144
+ var DENSITY_KEY = "conscia-density:v1";
1145
+ var PREFERENCE_EVENT = "conscia-preferences";
1146
+ var volatilePreferences = /* @__PURE__ */ new Map();
1147
+ function readPreference(key, fallback, allowedValues) {
1148
+ if (typeof window === "undefined") {
1149
+ return fallback;
1150
+ }
1151
+ try {
1152
+ const value = window.localStorage.getItem(key) ?? volatilePreferences.get(key);
1153
+ return value && allowedValues.includes(value) ? value : fallback;
1154
+ } catch {
1155
+ const value = volatilePreferences.get(key);
1156
+ return value && allowedValues.includes(value) ? value : fallback;
1157
+ }
1158
+ }
1159
+ function writePreference(key, value) {
1160
+ volatilePreferences.set(key, value);
1161
+ try {
1162
+ window.localStorage.setItem(key, value);
1163
+ } catch {
1164
+ }
1165
+ window.dispatchEvent(new Event(PREFERENCE_EVENT));
1166
+ }
1167
+ function useStoredPreference(key, fallback, allowedValues) {
1168
+ return React5.useSyncExternalStore(
1169
+ (onStoreChange) => {
1170
+ window.addEventListener("storage", onStoreChange);
1171
+ window.addEventListener(PREFERENCE_EVENT, onStoreChange);
1172
+ return () => {
1173
+ window.removeEventListener("storage", onStoreChange);
1174
+ window.removeEventListener(PREFERENCE_EVENT, onStoreChange);
1175
+ };
1176
+ },
1177
+ () => readPreference(key, fallback, allowedValues),
1178
+ () => fallback
1179
+ );
1180
+ }
1181
+ function useConsciaPreferences() {
1182
+ const appearance = useStoredPreference(
1183
+ APPEARANCE_KEY,
1184
+ "system",
1185
+ appearanceOptions
1186
+ );
1187
+ const density = useStoredPreference(
1188
+ DENSITY_KEY,
1189
+ "comfortable",
1190
+ densityOptions
1191
+ );
1192
+ return { appearance, density };
1193
+ }
1194
+ function DesignSystemPreferenceSync() {
1195
+ const { appearance, density } = useConsciaPreferences();
1196
+ React5.useEffect(() => {
1197
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
1198
+ const sync = () => applyConsciaPreferences(
1199
+ document.documentElement,
1200
+ appearance,
1201
+ density,
1202
+ media.matches
1203
+ );
1204
+ sync();
1205
+ media.addEventListener("change", sync);
1206
+ return () => media.removeEventListener("change", sync);
1207
+ }, [appearance, density]);
1208
+ return null;
1209
+ }
1210
+ function AppearanceControl({ className }) {
1211
+ const { appearance } = useConsciaPreferences();
1212
+ return /* @__PURE__ */ jsx13(
1213
+ SegmentedControl,
1214
+ {
1215
+ className,
1216
+ label: "Appearance",
1217
+ value: appearance,
1218
+ values: appearanceOptions,
1219
+ onChange: (value) => writePreference(APPEARANCE_KEY, value)
1220
+ }
1221
+ );
1222
+ }
1223
+ function DensityControl({ className }) {
1224
+ const { density } = useConsciaPreferences();
1225
+ return /* @__PURE__ */ jsx13(
1226
+ SegmentedControl,
1227
+ {
1228
+ className,
1229
+ label: "Density",
1230
+ value: density,
1231
+ values: densityOptions,
1232
+ onChange: (value) => writePreference(DENSITY_KEY, value)
1233
+ }
1234
+ );
1235
+ }
1236
+ function DesignPreferenceControls({ className }) {
1237
+ return /* @__PURE__ */ jsxs11("div", { className: cn("flex flex-col gap-3 text-sm", className), children: [
1238
+ /* @__PURE__ */ jsx13(AppearanceControl, {}),
1239
+ /* @__PURE__ */ jsx13(DensityControl, {})
1240
+ ] });
1241
+ }
1242
+ function SegmentedControl({
1243
+ className,
1244
+ label,
1245
+ value,
1246
+ values,
1247
+ onChange
1248
+ }) {
1249
+ return /* @__PURE__ */ jsxs11("fieldset", { className: cn("flex flex-col gap-2", className), children: [
1250
+ /* @__PURE__ */ jsx13("legend", { className: "text-[var(--ds-metadata)] font-medium text-muted-foreground", children: label }),
1251
+ /* @__PURE__ */ jsx13("div", { className: "inline-flex rounded-[var(--ds-radius-control)] bg-muted p-1", children: values.map((item) => /* @__PURE__ */ jsx13(
1252
+ "button",
1253
+ {
1254
+ type: "button",
1255
+ "aria-pressed": value === item,
1256
+ suppressHydrationWarning: true,
1257
+ onClick: () => onChange(item),
1258
+ className: "h-7 rounded-[calc(var(--ds-radius-control)-2px)] px-2.5 text-[var(--ds-metadata)] font-medium capitalize text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:shadow-xs",
1259
+ children: item
1260
+ },
1261
+ item
1262
+ )) })
1263
+ ] });
1264
+ }
1265
+
1266
+ // src/patterns/provider-mark.tsx
1267
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1268
+ function ProviderMark({ name, shortName, description, size = "default", className, ...props }) {
1269
+ return /* @__PURE__ */ jsxs12("div", { "data-slot": "provider-mark", className: cn("flex min-w-0 items-center gap-3", className), ...props, children: [
1270
+ /* @__PURE__ */ jsx14(
1271
+ "div",
1272
+ {
1273
+ "aria-hidden": "true",
1274
+ className: cn(
1275
+ "flex shrink-0 items-center justify-center rounded-md border border-border-subtle bg-surface-muted font-semibold tracking-tight text-foreground",
1276
+ size === "sm" ? "size-8 text-[10px]" : "size-10 text-xs"
1277
+ ),
1278
+ children: shortName
1279
+ }
1280
+ ),
1281
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
1282
+ /* @__PURE__ */ jsx14("div", { className: "truncate text-sm font-medium text-foreground", children: name }),
1283
+ description ? /* @__PURE__ */ jsx14("div", { className: "mt-0.5 truncate text-[var(--ds-metadata)] text-muted-foreground", children: description }) : null
1284
+ ] })
1285
+ ] });
1286
+ }
1287
+
1288
+ // src/patterns/resource-detail.tsx
1289
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1290
+ function ResourceSummary({
1291
+ variant = "plain",
1292
+ title,
1293
+ description,
1294
+ status,
1295
+ metadata,
1296
+ actions,
1297
+ className,
1298
+ children,
1299
+ ...props
1300
+ }) {
1301
+ return /* @__PURE__ */ jsxs13(
1302
+ "section",
1303
+ {
1304
+ "data-slot": "resource-summary",
1305
+ className: cn(
1306
+ "px-5 py-4",
1307
+ variant === "plain" && "border-b border-border-subtle bg-background",
1308
+ variant === "surface" && "rounded-[var(--ds-radius-surface)] border border-border-subtle bg-surface",
1309
+ className
1310
+ ),
1311
+ ...props,
1312
+ children: [
1313
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
1314
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
1315
+ title || status ? /* @__PURE__ */ jsxs13("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
1316
+ title ? /* @__PURE__ */ jsx15("h2", { className: "truncate text-[var(--ds-section-title)] font-semibold", children: title }) : null,
1317
+ status
1318
+ ] }) : null,
1319
+ description ? /* @__PURE__ */ jsx15("p", { className: "mt-1 max-w-3xl text-sm text-muted-foreground", children: description }) : null,
1320
+ metadata ? /* @__PURE__ */ jsx15("div", { className: "mt-2 text-[var(--ds-metadata)] text-muted-foreground", children: metadata }) : null
1321
+ ] }),
1322
+ actions ? /* @__PURE__ */ jsx15("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
1323
+ ] }),
1324
+ children ? /* @__PURE__ */ jsx15("div", { className: "mt-4", children }) : null
1325
+ ]
1326
+ }
1327
+ );
1328
+ }
1329
+ function DetailSections({
1330
+ className,
1331
+ ...props
1332
+ }) {
1333
+ return /* @__PURE__ */ jsx15(
1334
+ "div",
1335
+ {
1336
+ "data-slot": "detail-sections",
1337
+ className: cn("flex flex-col gap-[var(--ds-space-section)]", className),
1338
+ ...props
1339
+ }
1340
+ );
1341
+ }
1342
+ function DetailSection({
1343
+ variant = "surface",
1344
+ title,
1345
+ description,
1346
+ actions,
1347
+ className,
1348
+ children,
1349
+ ...props
1350
+ }) {
1351
+ return /* @__PURE__ */ jsxs13(
1352
+ "section",
1353
+ {
1354
+ "data-slot": "detail-section",
1355
+ className: cn(
1356
+ variant === "surface" && "rounded-[var(--ds-radius-surface)] border border-border-subtle bg-surface p-[var(--ds-surface-padding)]",
1357
+ variant === "open" && "border-b border-border-subtle pb-[var(--ds-space-section)]",
1358
+ className
1359
+ ),
1360
+ ...props,
1361
+ children: [
1362
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [
1363
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
1364
+ /* @__PURE__ */ jsx15("h2", { className: "text-[var(--ds-section-title)] font-semibold", children: title }),
1365
+ description ? /* @__PURE__ */ jsx15("p", { className: "mt-1 max-w-3xl text-sm text-muted-foreground", children: description }) : null
1366
+ ] }),
1367
+ actions ? /* @__PURE__ */ jsx15("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null
1368
+ ] }),
1369
+ children ? /* @__PURE__ */ jsx15("div", { className: "mt-4", children }) : null
1370
+ ]
1371
+ }
1372
+ );
1373
+ }
1374
+ function KeyValueList({
1375
+ className,
1376
+ ...props
1377
+ }) {
1378
+ return /* @__PURE__ */ jsx15(
1379
+ "dl",
1380
+ {
1381
+ "data-slot": "key-value-list",
1382
+ className: cn("grid gap-3 text-sm", className),
1383
+ ...props
1384
+ }
1385
+ );
1386
+ }
1387
+ function KeyValueItem({
1388
+ label,
1389
+ value,
1390
+ breakValue = false
1391
+ }) {
1392
+ return /* @__PURE__ */ jsxs13("div", { "data-slot": "key-value-item", className: "flex justify-between gap-4", children: [
1393
+ /* @__PURE__ */ jsx15("dt", { className: "text-muted-foreground", children: label }),
1394
+ /* @__PURE__ */ jsx15(
1395
+ "dd",
1396
+ {
1397
+ className: cn(
1398
+ "text-right font-medium",
1399
+ breakValue && "break-all"
1400
+ ),
1401
+ children: value
1402
+ }
1403
+ )
1404
+ ] });
1405
+ }
1406
+
1407
+ // src/patterns/sidebar-navigation.tsx
1408
+ import * as React6 from "react";
1409
+ import { ChevronRight as ChevronRight2 } from "lucide-react";
1410
+ import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1411
+ function isSection(entry) {
1412
+ return "items" in entry;
1413
+ }
1414
+ function readOpenSections(storageKey) {
1415
+ if (!storageKey || typeof window === "undefined") {
1416
+ return {};
1417
+ }
1418
+ try {
1419
+ const storedValue = window.localStorage.getItem(storageKey);
1420
+ if (!storedValue) {
1421
+ return {};
1422
+ }
1423
+ const parsedValue = JSON.parse(storedValue);
1424
+ return typeof parsedValue === "object" && parsedValue !== null ? parsedValue : {};
1425
+ } catch {
1426
+ return {};
1427
+ }
1428
+ }
1429
+ function SidebarNavigation({
1430
+ entries,
1431
+ renderLink,
1432
+ onNavigate,
1433
+ storageKey,
1434
+ className
1435
+ }) {
1436
+ const { isMobile, sidebarSide, sidebarState } = useAppShell();
1437
+ const [openSections, setOpenSections] = React6.useState({});
1438
+ const storageReady = React6.useRef(false);
1439
+ React6.useEffect(() => {
1440
+ storageReady.current = false;
1441
+ const storedSections = readOpenSections(storageKey);
1442
+ queueMicrotask(() => {
1443
+ storageReady.current = true;
1444
+ setOpenSections(storedSections);
1445
+ });
1446
+ }, [storageKey]);
1447
+ React6.useEffect(() => {
1448
+ if (!storageReady.current || !storageKey || !entries.some(isSection)) {
1449
+ return;
1450
+ }
1451
+ try {
1452
+ window.localStorage.setItem(storageKey, JSON.stringify(openSections));
1453
+ } catch {
1454
+ }
1455
+ }, [entries, openSections, storageKey]);
1456
+ const handleNavigate = React6.useCallback(() => {
1457
+ onNavigate?.();
1458
+ }, [onNavigate]);
1459
+ return /* @__PURE__ */ jsx16(
1460
+ "nav",
1461
+ {
1462
+ "data-slot": "sidebar-navigation",
1463
+ "aria-label": "Primary navigation",
1464
+ className: cn("flex flex-col gap-1", className),
1465
+ children: entries.map((entry) => {
1466
+ if (!isSection(entry)) {
1467
+ return /* @__PURE__ */ jsx16(
1468
+ NavigationGroup,
1469
+ {
1470
+ className: entry.startsSection ? "mt-2" : void 0,
1471
+ children: /* @__PURE__ */ jsx16(NavigationItem, { asChild: true, active: entry.active, tooltip: entry.label, children: renderLink(entry, {
1472
+ "aria-current": entry.active ? "page" : void 0,
1473
+ "aria-label": entry.label,
1474
+ onClick: handleNavigate,
1475
+ children: /* @__PURE__ */ jsxs14(Fragment3, { children: [
1476
+ entry.icon,
1477
+ /* @__PURE__ */ jsx16("span", { className: "truncate group-data-[sidebar-state=collapsed]/shell:hidden", children: entry.label })
1478
+ ] })
1479
+ }) })
1480
+ },
1481
+ entry.id
1482
+ );
1483
+ }
1484
+ const sectionOpen = (openSections[entry.id] ?? false) || entry.active;
1485
+ if (sidebarState === "collapsed" && !isMobile) {
1486
+ return /* @__PURE__ */ jsxs14(DropdownMenu, { children: [
1487
+ /* @__PURE__ */ jsx16(
1488
+ NavigationGroup,
1489
+ {
1490
+ className: entry.startsSection ? "mt-2" : void 0,
1491
+ children: /* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs14(
1492
+ NavigationItem,
1493
+ {
1494
+ active: entry.active,
1495
+ "aria-label": `${entry.label} menu`,
1496
+ children: [
1497
+ entry.icon,
1498
+ /* @__PURE__ */ jsx16("span", { className: "sr-only", children: entry.label })
1499
+ ]
1500
+ }
1501
+ ) })
1502
+ }
1503
+ ),
1504
+ /* @__PURE__ */ jsxs14(
1505
+ DropdownMenuContent,
1506
+ {
1507
+ side: sidebarSide === "left" ? "right" : "left",
1508
+ align: "start",
1509
+ sideOffset: 8,
1510
+ className: "min-w-56 rounded-[var(--ds-radius-surface)] p-1.5",
1511
+ children: [
1512
+ /* @__PURE__ */ jsx16(DropdownMenuLabel, { className: "px-2 py-1.5 font-semibold text-muted-foreground", children: entry.label }),
1513
+ /* @__PURE__ */ jsx16(DropdownMenuGroup, { children: entry.items.map((item) => /* @__PURE__ */ jsx16(
1514
+ DropdownMenuItem,
1515
+ {
1516
+ asChild: true,
1517
+ className: cn(
1518
+ "min-h-9 cursor-pointer rounded-[var(--ds-radius-control)] [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-[1.75]",
1519
+ item.active && "bg-selection-background text-selection-foreground shadow-[inset_2px_0_0_var(--selection-indicator)] focus:bg-selection-background focus:text-selection-foreground"
1520
+ ),
1521
+ children: renderLink(item, {
1522
+ "aria-current": item.active ? "page" : void 0,
1523
+ "aria-label": item.label,
1524
+ onClick: handleNavigate,
1525
+ children: /* @__PURE__ */ jsxs14(Fragment3, { children: [
1526
+ item.icon,
1527
+ /* @__PURE__ */ jsx16("span", { className: "truncate", children: item.label })
1528
+ ] })
1529
+ })
1530
+ },
1531
+ item.id
1532
+ )) })
1533
+ ]
1534
+ }
1535
+ )
1536
+ ] }, entry.id);
1537
+ }
1538
+ return /* @__PURE__ */ jsx16(
1539
+ Collapsible,
1540
+ {
1541
+ open: sectionOpen,
1542
+ onOpenChange: (open) => setOpenSections((current) => ({
1543
+ ...current,
1544
+ [entry.id]: open
1545
+ })),
1546
+ className: cn(
1547
+ "group/collapsible",
1548
+ entry.startsSection && "mt-2"
1549
+ ),
1550
+ children: /* @__PURE__ */ jsxs14(NavigationGroup, { children: [
1551
+ /* @__PURE__ */ jsx16(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs14(
1552
+ NavigationItem,
1553
+ {
1554
+ active: entry.active,
1555
+ tooltip: entry.label,
1556
+ "aria-label": entry.label,
1557
+ "aria-expanded": sectionOpen,
1558
+ children: [
1559
+ entry.icon,
1560
+ /* @__PURE__ */ jsx16("span", { className: "truncate group-data-[sidebar-state=collapsed]/shell:hidden", children: entry.label }),
1561
+ /* @__PURE__ */ jsx16(ChevronRight2, { className: "ml-auto transition-transform duration-150 ease-out group-data-[sidebar-state=collapsed]/shell:hidden group-data-[state=open]/collapsible:rotate-90" })
1562
+ ]
1563
+ }
1564
+ ) }),
1565
+ /* @__PURE__ */ jsx16(
1566
+ CollapsibleContent,
1567
+ {
1568
+ "data-slot": "sidebar-collapsible-content",
1569
+ className: "overflow-hidden",
1570
+ children: /* @__PURE__ */ jsx16(NavigationSubList, { children: entry.items.map((item) => /* @__PURE__ */ jsx16(
1571
+ NavigationSubItem,
1572
+ {
1573
+ asChild: true,
1574
+ active: item.active,
1575
+ children: renderLink(item, {
1576
+ "aria-current": item.active ? "page" : void 0,
1577
+ "aria-label": item.label,
1578
+ onClick: handleNavigate,
1579
+ children: /* @__PURE__ */ jsxs14(Fragment3, { children: [
1580
+ item.icon,
1581
+ /* @__PURE__ */ jsx16("span", { className: "truncate", children: item.label })
1582
+ ] })
1583
+ })
1584
+ },
1585
+ item.id
1586
+ )) })
1587
+ }
1588
+ )
1589
+ ] })
1590
+ },
1591
+ entry.id
1592
+ );
1593
+ })
1594
+ }
1595
+ );
1596
+ }
1597
+
1598
+ // src/patterns/state-views.tsx
1599
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1600
+ function StateView({ title, description, action, icon, className, ...props }) {
1601
+ return /* @__PURE__ */ jsxs15(
1602
+ "div",
1603
+ {
1604
+ "data-slot": "state-view",
1605
+ className: cn("flex min-h-72 flex-col items-center justify-center gap-3 border-b px-6 py-12 text-center", className),
1606
+ ...props,
1607
+ children: [
1608
+ icon ? /* @__PURE__ */ jsx17("div", { className: "flex size-10 items-center justify-center rounded-md bg-neutral-background text-neutral-foreground [&_svg]:size-5", children: icon }) : null,
1609
+ /* @__PURE__ */ jsx17("h2", { className: "text-base font-semibold", children: title }),
1610
+ description ? /* @__PURE__ */ jsx17("p", { className: "max-w-md text-sm text-muted-foreground", children: description }) : null,
1611
+ action ? /* @__PURE__ */ jsx17("div", { className: "mt-1", children: action }) : null
1612
+ ]
1613
+ }
1614
+ );
1615
+ }
1616
+ function LoadingRows({
1617
+ rows = 6,
1618
+ columns = 5
1619
+ }) {
1620
+ return /* @__PURE__ */ jsx17("div", { "data-slot": "loading-rows", className: "border-b", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsx17(
1621
+ "div",
1622
+ {
1623
+ className: "grid h-[var(--ds-row-height)] items-center gap-4 border-b px-5 last:border-b-0",
1624
+ style: { gridTemplateColumns: `2fr repeat(${Math.max(columns - 1, 1)}, minmax(5rem, 1fr))` },
1625
+ children: Array.from({ length: columns }).map((_2, columnIndex) => /* @__PURE__ */ jsx17(
1626
+ "div",
1627
+ {
1628
+ className: cn(
1629
+ "h-3 rounded bg-muted",
1630
+ columnIndex === 0 ? "w-44" : "w-24"
1631
+ )
1632
+ },
1633
+ columnIndex
1634
+ ))
1635
+ },
1636
+ index
1637
+ )) });
1638
+ }
1639
+ function ErrorState({ title, description, action, className, ...props }) {
1640
+ return /* @__PURE__ */ jsx17(
1641
+ StateView,
1642
+ {
1643
+ title,
1644
+ description,
1645
+ action,
1646
+ className: cn("bg-danger-background/60", className),
1647
+ role: "alert",
1648
+ "aria-live": "assertive",
1649
+ ...props
1650
+ }
1651
+ );
1652
+ }
1653
+
1654
+ // src/patterns/value-meter.tsx
1655
+ import * as React7 from "react";
1656
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1657
+ function ValueMeter({
1658
+ label,
1659
+ value,
1660
+ maximum,
1661
+ valueLabel,
1662
+ detail,
1663
+ tone = "neutral",
1664
+ className,
1665
+ ...props
1666
+ }) {
1667
+ const labelId = React7.useId();
1668
+ const hasMaximum = typeof maximum === "number" && maximum > 0;
1669
+ const boundedValue = hasMaximum ? Math.min(maximum, Math.max(0, value)) : value;
1670
+ const percentage = hasMaximum ? boundedValue / maximum * 100 : null;
1671
+ const resolvedValueLabel = valueLabel ?? (hasMaximum ? `${boundedValue} of ${maximum}` : String(boundedValue));
1672
+ return /* @__PURE__ */ jsxs16(
1673
+ "div",
1674
+ {
1675
+ "data-slot": "value-meter",
1676
+ className: cn("grid gap-2", className),
1677
+ ...props,
1678
+ children: [
1679
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-baseline justify-between gap-4 text-sm", children: [
1680
+ /* @__PURE__ */ jsx18("span", { id: labelId, className: "font-medium text-foreground", children: label }),
1681
+ /* @__PURE__ */ jsx18("span", { className: "text-muted-foreground", children: resolvedValueLabel })
1682
+ ] }),
1683
+ percentage === null ? null : /* @__PURE__ */ jsx18(
1684
+ "div",
1685
+ {
1686
+ role: "progressbar",
1687
+ "aria-labelledby": labelId,
1688
+ "aria-valuemin": 0,
1689
+ "aria-valuemax": maximum ?? void 0,
1690
+ "aria-valuenow": boundedValue,
1691
+ className: "h-2 overflow-hidden rounded-full bg-surface-muted",
1692
+ children: /* @__PURE__ */ jsx18(
1693
+ "div",
1694
+ {
1695
+ className: cn(
1696
+ "h-full rounded-full bg-neutral-foreground transition-[width]",
1697
+ tone === "success" && "bg-success-foreground",
1698
+ tone === "warning" && "bg-warning-foreground",
1699
+ tone === "danger" && "bg-danger-foreground"
1700
+ ),
1701
+ style: { width: `${percentage}%` }
1702
+ }
1703
+ )
1704
+ }
1705
+ ),
1706
+ detail ? /* @__PURE__ */ jsx18("div", { className: "text-xs text-muted-foreground", children: detail }) : null
1707
+ ]
1708
+ }
1709
+ );
1710
+ }
1711
+
1712
+ export {
1713
+ PaginationControls,
1714
+ DataTable,
1715
+ EntityTable,
1716
+ DetailBackLink,
1717
+ useAppShell,
1718
+ AppShell,
1719
+ AppSidebar,
1720
+ AppSidebarHeader,
1721
+ AppSidebarContent,
1722
+ AppSidebarFooter,
1723
+ ProductIdentity,
1724
+ SidebarSeparator,
1725
+ NavigationGroup,
1726
+ NavigationItem,
1727
+ NavigationSubItem,
1728
+ NavigationSubList,
1729
+ SidebarTrigger,
1730
+ MainRegion,
1731
+ TopBar,
1732
+ PageFrame,
1733
+ PageContent,
1734
+ PageBoundary,
1735
+ InspectorRegion,
1736
+ ActivityList,
1737
+ ActivityItem,
1738
+ ConfirmationDialog,
1739
+ CodeBlock,
1740
+ InventorySurface,
1741
+ InventoryDesktop,
1742
+ InventoryMobile,
1743
+ MetricBand,
1744
+ MetricBandItem,
1745
+ PageHeader,
1746
+ PageToolbar,
1747
+ useConsciaPreferences,
1748
+ DesignSystemPreferenceSync,
1749
+ AppearanceControl,
1750
+ DensityControl,
1751
+ DesignPreferenceControls,
1752
+ ProviderMark,
1753
+ ResourceSummary,
1754
+ DetailSections,
1755
+ DetailSection,
1756
+ KeyValueList,
1757
+ KeyValueItem,
1758
+ SidebarNavigation,
1759
+ StateView,
1760
+ LoadingRows,
1761
+ ErrorState,
1762
+ ValueMeter
1763
+ };
1764
+ //# sourceMappingURL=chunk-5MGPU2JE.js.map