@conscia-labs/design-system 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2574 +0,0 @@
1
- import {
2
- appearanceOptions,
3
- applyConsciaPreferences,
4
- densityOptions
5
- } from "./chunk-YNQWIH6V.js";
6
- import {
7
- AlertDialog,
8
- AlertDialogAction,
9
- AlertDialogBody,
10
- AlertDialogCancel,
11
- AlertDialogContent,
12
- AlertDialogDescription,
13
- AlertDialogFooter,
14
- AlertDialogHeader,
15
- AlertDialogTitle,
16
- AlertDialogTrigger,
17
- Button,
18
- Card,
19
- Checkbox,
20
- Collapsible,
21
- CollapsibleContent,
22
- CollapsibleTrigger,
23
- Dialog,
24
- DialogBody,
25
- DialogContent,
26
- DialogDescription,
27
- DialogHeader,
28
- DialogTitle,
29
- DialogTrigger,
30
- DropdownMenu,
31
- DropdownMenuContent,
32
- DropdownMenuGroup,
33
- DropdownMenuLabel,
34
- DropdownMenuLinkItem,
35
- DropdownMenuTrigger,
36
- IconButton,
37
- Input,
38
- Select,
39
- SelectContent,
40
- SelectItem,
41
- SelectTrigger,
42
- SelectValue,
43
- Separator,
44
- Sheet,
45
- SheetContent,
46
- SheetDescription,
47
- SheetHeader,
48
- SheetTitle,
49
- ShortcutHint,
50
- Skeleton,
51
- Table,
52
- TableBody,
53
- TableCaption,
54
- TableCell,
55
- TableHead,
56
- TableHeader,
57
- TableRow,
58
- Tabs,
59
- TabsContent,
60
- TabsList,
61
- TabsTrigger,
62
- Tooltip,
63
- TooltipContent,
64
- TooltipProvider,
65
- TooltipTrigger,
66
- index_parts_exports,
67
- useRender
68
- } from "./chunk-HWUUODVE.js";
69
- import {
70
- cn
71
- } from "./chunk-JU5DQXFC.js";
72
-
73
- // src/patterns/pagination.tsx
74
- import { ChevronLeft, ChevronRight } from "lucide-react";
75
- import { jsx, jsxs } from "react/jsx-runtime";
76
- function PaginationControls({
77
- currentPage,
78
- pageCount,
79
- totalLabel,
80
- onPrevious,
81
- onNext,
82
- onPageChange,
83
- pageSize,
84
- pageSizeOptions = [10, 25, 50],
85
- onPageSizeChange,
86
- className,
87
- ...props
88
- }) {
89
- return /* @__PURE__ */ jsxs(
90
- "div",
91
- {
92
- "data-slot": "pagination-controls",
93
- className: cn("flex flex-col gap-2 border-t border-border-subtle px-5 py-3 text-sm text-text-supporting sm:flex-row sm:items-center sm:justify-between", className),
94
- ...props,
95
- children: [
96
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
97
- /* @__PURE__ */ jsx("span", { children: totalLabel }),
98
- pageSize && onPageSizeChange ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
99
- /* @__PURE__ */ jsx("span", { className: "text-[var(--ds-metadata)]", children: "Rows" }),
100
- /* @__PURE__ */ jsxs(Select, { value: String(pageSize), onValueChange: (value) => onPageSizeChange(Number(value)), children: [
101
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-[4.5rem]", "aria-label": "Rows per page", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
102
- /* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx(SelectItem, { value: String(size), children: size }, size)) })
103
- ] })
104
- ] }) : null
105
- ] }),
106
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
107
- /* @__PURE__ */ jsx(IconButton, { type: "button", variant: "outline", size: "sm", className: "size-8", "aria-label": "Previous page", onClick: onPrevious ?? (() => onPageChange?.(currentPage - 1)), disabled: currentPage <= 1, children: /* @__PURE__ */ jsx(ChevronLeft, {}) }),
108
- onPageChange ? pageItems(currentPage, pageCount).map((item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx("span", { className: "flex size-8 items-center justify-center text-text-supporting", "aria-hidden": "true", children: "\u2026" }, `ellipsis-${index}`) : /* @__PURE__ */ jsx(IconButton, { type: "button", variant: item === currentPage ? "secondary" : "ghost", size: "sm", 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: [
109
- "Page ",
110
- currentPage,
111
- " of ",
112
- pageCount
113
- ] }),
114
- /* @__PURE__ */ jsx(IconButton, { type: "button", variant: "outline", size: "sm", className: "size-8", "aria-label": "Next page", onClick: onNext ?? (() => onPageChange?.(currentPage + 1)), disabled: currentPage >= pageCount, children: /* @__PURE__ */ jsx(ChevronRight, {}) })
115
- ] })
116
- ]
117
- }
118
- );
119
- }
120
- function pageItems(currentPage, pageCount) {
121
- if (pageCount <= 7) return Array.from({ length: pageCount }, (_, index) => index + 1);
122
- const pages = /* @__PURE__ */ new Set([1, pageCount, currentPage - 1, currentPage, currentPage + 1]);
123
- const sorted = Array.from(pages).filter((page) => page > 0 && page <= pageCount).sort((a, b) => a - b);
124
- const result = [];
125
- sorted.forEach((page, index) => {
126
- if (index && page - sorted[index - 1] > 1) result.push("ellipsis");
127
- result.push(page);
128
- });
129
- return result;
130
- }
131
-
132
- // src/patterns/data-table.tsx
133
- import * as React from "react";
134
- import {
135
- flexRender,
136
- getCoreRowModel,
137
- getPaginationRowModel,
138
- getSortedRowModel,
139
- useReactTable
140
- } from "@tanstack/react-table";
141
- import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
142
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
143
- function DataTable({
144
- data,
145
- columns,
146
- getRowId,
147
- getRowLabel,
148
- onRowClick,
149
- isRowClickable,
150
- rowActions,
151
- selectedIds,
152
- onSelectionChange,
153
- sorting,
154
- onSortingChange,
155
- manualSorting = false,
156
- pagination,
157
- onPaginationChange,
158
- manualPagination = false,
159
- pageCount,
160
- rowCount,
161
- pageSizeOptions,
162
- totalLabel,
163
- mobileRow,
164
- caption,
165
- empty,
166
- className
167
- }) {
168
- const rowSelection = React.useMemo(() => {
169
- const selection = {};
170
- selectedIds?.forEach((id) => {
171
- selection[id] = true;
172
- });
173
- return selection;
174
- }, [selectedIds]);
175
- const tableColumns = React.useMemo(() => {
176
- const result = [];
177
- if (onSelectionChange) {
178
- result.push({
179
- id: "select",
180
- enableSorting: false,
181
- header: ({ table: table2 }) => /* @__PURE__ */ jsx2(
182
- Checkbox,
183
- {
184
- "aria-label": "Select all rows on this page",
185
- checked: table2.getIsAllPageRowsSelected(),
186
- indeterminate: table2.getIsSomePageRowsSelected() && !table2.getIsAllPageRowsSelected(),
187
- onCheckedChange: (checked) => table2.toggleAllPageRowsSelected(Boolean(checked))
188
- }
189
- ),
190
- cell: ({ row }) => /* @__PURE__ */ jsx2(
191
- Checkbox,
192
- {
193
- "aria-label": `Select ${getRowLabel?.(row.original) ?? row.id}`,
194
- checked: row.getIsSelected(),
195
- onCheckedChange: (checked) => row.toggleSelected(Boolean(checked)),
196
- onClick: (event) => event.stopPropagation()
197
- }
198
- ),
199
- meta: { className: "w-10" }
200
- });
201
- }
202
- result.push(...columns.map((column) => ({
203
- id: column.id,
204
- ...column.accessor ? { accessorFn: column.accessor } : {},
205
- enableSorting: column.sortable ?? false,
206
- header: () => column.header,
207
- cell: ({ row }) => column.cell(row.original),
208
- meta: { className: column.className, label: typeof column.header === "string" ? column.header : column.id }
209
- })));
210
- if (rowActions) {
211
- result.push({
212
- id: "actions",
213
- enableSorting: false,
214
- header: "Actions",
215
- cell: ({ row }) => /* @__PURE__ */ jsx2(
216
- "div",
217
- {
218
- onClick: (event) => event.stopPropagation(),
219
- onKeyDown: (event) => event.stopPropagation(),
220
- children: rowActions(row.original)
221
- }
222
- ),
223
- meta: { className: "w-12 text-right" }
224
- });
225
- }
226
- return result;
227
- }, [columns, getRowLabel, onSelectionChange, rowActions]);
228
- const table = useReactTable({
229
- data,
230
- columns: tableColumns,
231
- getRowId: (row) => getRowId(row),
232
- state: { rowSelection, ...sorting ? { sorting } : {}, ...pagination ? { pagination } : {} },
233
- enableRowSelection: Boolean(onSelectionChange),
234
- onRowSelectionChange: (updater) => {
235
- if (!onSelectionChange) return;
236
- const next = typeof updater === "function" ? updater(rowSelection) : updater;
237
- onSelectionChange(new Set(Object.keys(next).filter((id) => next[id])));
238
- },
239
- onSortingChange: (updater) => {
240
- if (!onSortingChange) return;
241
- onSortingChange(typeof updater === "function" ? updater(sorting ?? []) : updater);
242
- },
243
- onPaginationChange: (updater) => {
244
- if (!onPaginationChange || !pagination) return;
245
- onPaginationChange(typeof updater === "function" ? updater(pagination) : updater);
246
- },
247
- manualSorting,
248
- manualPagination,
249
- pageCount,
250
- rowCount,
251
- getCoreRowModel: getCoreRowModel(),
252
- getSortedRowModel: manualSorting ? void 0 : getSortedRowModel(),
253
- getPaginationRowModel: pagination && !manualPagination ? getPaginationRowModel() : void 0
254
- });
255
- if (!data.length && empty) return /* @__PURE__ */ jsx2(Fragment, { children: empty });
256
- const visibleRows = table.getRowModel().rows;
257
- const showPagination = Boolean(pagination && onPaginationChange);
258
- return /* @__PURE__ */ jsxs2("div", { "data-slot": "data-table", className: cn("bg-canvas", className), children: [
259
- /* @__PURE__ */ jsx2("div", { className: mobileRow ? "hidden md:block" : void 0, children: /* @__PURE__ */ jsxs2(Table, { children: [
260
- caption ? /* @__PURE__ */ jsx2(TableCaption, { children: caption }) : null,
261
- /* @__PURE__ */ jsx2(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx2(TableRow, { children: headerGroup.headers.map((header) => {
262
- const meta = header.column.columnDef.meta;
263
- const canSort = header.column.getCanSort();
264
- const sorted = header.column.getIsSorted();
265
- return /* @__PURE__ */ jsx2(
266
- TableHead,
267
- {
268
- className: meta?.className,
269
- "aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
270
- children: header.isPlaceholder ? null : canSort ? /* @__PURE__ */ jsxs2(
271
- Button,
272
- {
273
- type: "button",
274
- variant: "ghost",
275
- size: "sm",
276
- className: "-ml-2 h-8 gap-1.5 px-2 text-[var(--ds-metadata)] font-semibold uppercase text-text-supporting hover:text-text-primary",
277
- onClick: header.column.getToggleSortingHandler(),
278
- "aria-label": `Sort by ${meta?.label ?? header.column.id}`,
279
- children: [
280
- flexRender(header.column.columnDef.header, header.getContext()),
281
- 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" })
282
- ]
283
- }
284
- ) : flexRender(header.column.columnDef.header, header.getContext())
285
- },
286
- header.id
287
- );
288
- }) }, headerGroup.id)) }),
289
- /* @__PURE__ */ jsx2(TableBody, { children: visibleRows.map((row) => {
290
- const rowClickable = Boolean(
291
- onRowClick && (isRowClickable?.(row.original) ?? true)
292
- );
293
- return /* @__PURE__ */ jsx2(
294
- TableRow,
295
- {
296
- "data-selected": row.getIsSelected() ? "true" : void 0,
297
- "aria-selected": row.getIsSelected() ? "true" : void 0,
298
- tabIndex: rowClickable ? 0 : void 0,
299
- "aria-label": rowClickable ? getRowLabel?.(row.original) ?? row.id : void 0,
300
- className: cn(rowClickable && "cursor-pointer outline-none focus-visible:ring-[3px] focus-visible:ring-focus/45"),
301
- onClick: () => {
302
- if (rowClickable) onRowClick?.(row.original);
303
- },
304
- onKeyDown: (event) => {
305
- if (!rowClickable || event.key !== "Enter" && event.key !== " ") return;
306
- event.preventDefault();
307
- onRowClick?.(row.original);
308
- },
309
- children: row.getVisibleCells().map((cell) => {
310
- const meta = cell.column.columnDef.meta;
311
- return /* @__PURE__ */ jsx2(TableCell, { className: meta?.className, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
312
- })
313
- },
314
- row.id
315
- );
316
- }) })
317
- ] }) }),
318
- 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,
319
- showPagination ? /* @__PURE__ */ jsx2(
320
- PaginationControls,
321
- {
322
- currentPage: pagination.pageIndex + 1,
323
- pageCount: Math.max(1, table.getPageCount()),
324
- pageSize: pagination.pageSize,
325
- pageSizeOptions,
326
- totalLabel,
327
- onPageChange: (nextPage) => table.setPageIndex(nextPage - 1),
328
- onPageSizeChange: (nextSize) => table.setPageSize(nextSize)
329
- }
330
- ) : null
331
- ] });
332
- }
333
-
334
- // src/patterns/entity-table.tsx
335
- import { jsx as jsx3 } from "react/jsx-runtime";
336
- function EntityTable({
337
- items,
338
- columns,
339
- getRowId,
340
- selectedIds,
341
- onSelectionChange,
342
- onRowClick,
343
- getRowLabel,
344
- rowActions,
345
- caption,
346
- className
347
- }) {
348
- return /* @__PURE__ */ jsx3(
349
- DataTable,
350
- {
351
- data: items,
352
- columns: columns.map((column) => ({ ...column, id: column.key })),
353
- getRowId,
354
- selectedIds,
355
- onSelectionChange,
356
- onRowClick,
357
- getRowLabel,
358
- rowActions,
359
- caption,
360
- className
361
- }
362
- );
363
- }
364
-
365
- // src/patterns/command-palette.tsx
366
- import * as React2 from "react";
367
- import { SearchIcon } from "lucide-react";
368
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
369
- function CommandPalette({
370
- className,
371
- closeOnSelect = true,
372
- defaultOpen = false,
373
- description,
374
- emptyMessage = "No commands found.",
375
- items,
376
- onOpenChange,
377
- onSelect,
378
- open,
379
- placeholder = "Search commands...",
380
- title = "Command menu",
381
- trigger,
382
- ...props
383
- }) {
384
- const [query, setQuery] = React2.useState("");
385
- const [internalOpen, setInternalOpen] = React2.useState(defaultOpen);
386
- const isControlled = open !== void 0;
387
- const isOpen = open ?? internalOpen;
388
- const filteredItems = React2.useMemo(() => {
389
- const normalizedQuery = query.trim().toLocaleLowerCase();
390
- if (!normalizedQuery) {
391
- return items;
392
- }
393
- return items.filter(
394
- (item) => [item.label, ...item.keywords ?? []].some(
395
- (value) => value.toLocaleLowerCase().includes(normalizedQuery)
396
- )
397
- );
398
- }, [items, query]);
399
- const handleOpenChange = React2.useCallback(
400
- (nextOpen) => {
401
- if (!isControlled) {
402
- setInternalOpen(nextOpen);
403
- }
404
- if (nextOpen) {
405
- setQuery("");
406
- }
407
- onOpenChange?.(nextOpen);
408
- },
409
- [isControlled, onOpenChange]
410
- );
411
- const handleSelect = React2.useCallback(
412
- (item) => {
413
- onSelect(item);
414
- if (closeOnSelect) {
415
- handleOpenChange(false);
416
- }
417
- },
418
- [closeOnSelect, handleOpenChange, onSelect]
419
- );
420
- return /* @__PURE__ */ jsx4("div", { "data-slot": "command-palette", className: cn("contents", className), ...props, children: /* @__PURE__ */ jsxs3(Dialog, { open: isOpen, onOpenChange: handleOpenChange, children: [
421
- trigger ? /* @__PURE__ */ jsx4(DialogTrigger, { render: trigger }) : null,
422
- /* @__PURE__ */ jsxs3(
423
- DialogContent,
424
- {
425
- showCloseButton: false,
426
- size: "small",
427
- "aria-label": typeof title === "string" ? void 0 : "Command menu",
428
- className: "max-w-xl gap-0 p-0",
429
- children: [
430
- /* @__PURE__ */ jsxs3(DialogHeader, { className: "sr-only", children: [
431
- /* @__PURE__ */ jsx4(DialogTitle, { children: title }),
432
- description ? /* @__PURE__ */ jsx4(DialogDescription, { children: description }) : null
433
- ] }),
434
- /* @__PURE__ */ jsx4(DialogBody, { className: "overflow-hidden", children: /* @__PURE__ */ jsxs3(
435
- index_parts_exports.Root,
436
- {
437
- items: filteredItems,
438
- filter: () => true,
439
- open: true,
440
- autoHighlight: true,
441
- inputValue: query,
442
- onInputValueChange: setQuery,
443
- onValueChange: (item) => {
444
- if (item) {
445
- handleSelect(item);
446
- }
447
- },
448
- itemToStringLabel: (item) => [item.label, ...item.keywords ?? []].join(" "),
449
- itemToStringValue: (item) => item.id,
450
- children: [
451
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 border-b border-border-subtle px-4", children: [
452
- /* @__PURE__ */ jsx4(SearchIcon, { "aria-hidden": "true", className: "size-4 shrink-0 text-text-supporting" }),
453
- /* @__PURE__ */ jsx4(
454
- index_parts_exports.Input,
455
- {
456
- "aria-label": "Search commands",
457
- autoFocus: true,
458
- className: "ds-type-control h-12 min-w-0 flex-1 bg-transparent outline-none placeholder:text-text-supporting",
459
- onKeyDown: (event) => {
460
- if (event.key === "Escape") {
461
- event.preventDefault();
462
- handleOpenChange(false);
463
- }
464
- },
465
- placeholder
466
- }
467
- )
468
- ] }),
469
- filteredItems.length === 0 ? /* @__PURE__ */ jsx4("div", { role: "status", className: "px-3 py-8 text-center text-sm text-text-supporting", children: emptyMessage }) : null,
470
- /* @__PURE__ */ jsx4(
471
- index_parts_exports.List,
472
- {
473
- "aria-label": "Commands",
474
- className: "max-h-[min(24rem,calc(100vh-10rem))] overflow-y-auto p-2 outline-none",
475
- children: filteredItems.map((item, index) => /* @__PURE__ */ jsxs3(React2.Fragment, { children: [
476
- item.group && (index === 0 || filteredItems[index - 1]?.group !== item.group) ? /* @__PURE__ */ jsx4("div", { role: "presentation", className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-text-supporting first:pt-1", children: item.group }) : null,
477
- /* @__PURE__ */ jsxs3(
478
- index_parts_exports.Item,
479
- {
480
- index,
481
- value: item,
482
- disabled: item.disabled,
483
- className: "data-highlighted:bg-surface-muted data-highlighted:text-text-primary relative flex min-w-0 items-start gap-3 rounded-md px-3 py-2.5 text-left outline-none data-disabled:pointer-events-none data-disabled:opacity-50",
484
- children: [
485
- item.icon ? /* @__PURE__ */ jsx4("span", { className: "mt-0.5 flex size-4 shrink-0 items-center justify-center text-text-supporting", children: item.icon }) : null,
486
- /* @__PURE__ */ jsxs3("span", { className: "min-w-0 flex-1", children: [
487
- /* @__PURE__ */ jsx4("span", { className: "block truncate text-sm font-medium", children: item.label }),
488
- item.description ? /* @__PURE__ */ jsx4("span", { className: "mt-0.5 block truncate text-xs text-text-supporting", children: item.description }) : null
489
- ] }),
490
- item.shortcut ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-xs text-text-supporting", children: item.shortcut }) : null
491
- ]
492
- }
493
- )
494
- ] }, item.id))
495
- }
496
- )
497
- ]
498
- }
499
- ) })
500
- ]
501
- }
502
- )
503
- ] }) });
504
- }
505
-
506
- // src/patterns/data-panel.tsx
507
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
508
- function DataPanel({ className, ...props }) {
509
- return /* @__PURE__ */ jsx5("section", { "data-slot": "data-panel", className: cn("min-w-0 overflow-hidden rounded-[var(--ds-radius-surface)] border border-border-default bg-surface text-text-primary shadow-[var(--ds-shadow-raised)]", className), ...props });
510
- }
511
- function DataPanelHeader({ title, description, status, actions, className, ...props }) {
512
- return /* @__PURE__ */ jsxs4("header", { "data-slot": "data-panel-header", className: cn("flex min-w-0 items-start justify-between gap-4 border-b border-border-subtle px-[var(--ds-surface-padding)] py-3", className), ...props, children: [
513
- /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
514
- /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-2", children: [
515
- /* @__PURE__ */ jsx5("h2", { className: "ds-type-card-title", children: title }),
516
- status
517
- ] }),
518
- description ? /* @__PURE__ */ jsx5("p", { className: "ds-type-metadata mt-0.5 text-text-supporting", children: description }) : null
519
- ] }),
520
- actions ? /* @__PURE__ */ jsx5("div", { className: "shrink-0", children: actions }) : null
521
- ] });
522
- }
523
- function DataPanelContent({ padded = false, className, ...props }) {
524
- return /* @__PURE__ */ jsx5("div", { "data-slot": "data-panel-content", "data-padded": padded ? "true" : void 0, className: cn(padded && "p-[var(--ds-surface-padding)]", className), ...props });
525
- }
526
- function DataPanelFooter({ className, ...props }) {
527
- return /* @__PURE__ */ jsx5("footer", { "data-slot": "data-panel-footer", className: cn("border-t border-border-subtle px-[var(--ds-surface-padding)] py-3 ds-type-metadata text-text-supporting", className), ...props });
528
- }
529
-
530
- // src/patterns/detail-back-link.tsx
531
- import { ArrowLeft } from "lucide-react";
532
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
533
- function DetailBackLink({ label, className, ...props }) {
534
- return /* @__PURE__ */ jsxs5(
535
- "a",
536
- {
537
- "data-slot": "detail-back-link",
538
- className: cn(
539
- "inline-flex h-8 w-fit items-center gap-2 rounded-md px-2 text-sm font-medium text-text-supporting outline-none transition-colors hover:bg-surface-muted hover:text-text-primary focus-visible:ring-[3px] focus-visible:ring-focus/45",
540
- className
541
- ),
542
- ...props,
543
- children: [
544
- /* @__PURE__ */ jsx6(ArrowLeft, { className: "size-4", "aria-hidden": "true" }),
545
- label
546
- ]
547
- }
548
- );
549
- }
550
-
551
- // src/patterns/filter-bar.tsx
552
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
553
- function FilterBar({
554
- children,
555
- clearAllLabel = "Clear all",
556
- className,
557
- onClearAll,
558
- ...props
559
- }) {
560
- return /* @__PURE__ */ jsxs6(
561
- "div",
562
- {
563
- "data-slot": "filter-bar",
564
- className: cn(
565
- "flex min-w-0 flex-wrap items-center gap-2 rounded-[var(--ds-radius-control)] border border-border-subtle bg-surface-muted/60 px-2 py-1.5",
566
- className
567
- ),
568
- role: "group",
569
- "aria-label": props["aria-label"] ?? "Active filters",
570
- ...props,
571
- children: [
572
- /* @__PURE__ */ jsx7("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1.5", children }),
573
- onClearAll ? /* @__PURE__ */ jsx7(Button, { type: "button", variant: "ghost", size: "sm", onClick: onClearAll, className: "shrink-0", children: clearAllLabel }) : null
574
- ]
575
- }
576
- );
577
- }
578
-
579
- // src/patterns/app-shell.tsx
580
- import * as React3 from "react";
581
- import { PanelLeftIcon, Search, X } from "lucide-react";
582
- import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
583
- var SIDEBAR_COOKIE_NAME = "conscia_sidebar_state";
584
- var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
585
- var SIDEBAR_KEYBOARD_SHORTCUT = "b";
586
- var SIDEBAR_STORAGE_KEY = "conscia-sidebar-open:v1";
587
- var SIDEBAR_STATE_CHANGE_EVENT = "conscia-sidebar-state-change";
588
- function parseSidebarOpen(value) {
589
- return value === "true" ? true : value === "false" ? false : null;
590
- }
591
- function readPersistedSidebarOpen() {
592
- if (typeof document === "undefined") {
593
- return null;
594
- }
595
- try {
596
- const storedValue = window.localStorage.getItem(SIDEBAR_STORAGE_KEY);
597
- const storedSidebarOpen = parseSidebarOpen(storedValue);
598
- if (storedSidebarOpen !== null) {
599
- return storedSidebarOpen;
600
- }
601
- } catch {
602
- }
603
- const cookie = document.cookie.split("; ").find((entry) => entry.startsWith(`${SIDEBAR_COOKIE_NAME}=`));
604
- if (!cookie) {
605
- return null;
606
- }
607
- const value = cookie.slice(SIDEBAR_COOKIE_NAME.length + 1);
608
- return parseSidebarOpen(value);
609
- }
610
- function persistSidebarOpen(open) {
611
- try {
612
- window.localStorage.setItem(SIDEBAR_STORAGE_KEY, String(open));
613
- } catch {
614
- }
615
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
616
- window.dispatchEvent(new Event(SIDEBAR_STATE_CHANGE_EVENT));
617
- }
618
- function subscribeToSidebarOpen(onStoreChange) {
619
- function onStorage(event) {
620
- if (event.key === SIDEBAR_STORAGE_KEY) {
621
- onStoreChange();
622
- }
623
- }
624
- window.addEventListener(SIDEBAR_STATE_CHANGE_EVENT, onStoreChange);
625
- window.addEventListener("storage", onStorage);
626
- return () => {
627
- window.removeEventListener(SIDEBAR_STATE_CHANGE_EVENT, onStoreChange);
628
- window.removeEventListener("storage", onStorage);
629
- };
630
- }
631
- var AppShellContext = React3.createContext(null);
632
- function useAppShell() {
633
- const context = React3.useContext(AppShellContext);
634
- if (!context) {
635
- throw new Error("useAppShell must be used within AppShell.");
636
- }
637
- return context;
638
- }
639
- function useMediaQuery(query) {
640
- const [matches, setMatches] = React3.useState(false);
641
- React3.useEffect(() => {
642
- const media = window.matchMedia(query);
643
- const sync = () => setMatches(media.matches);
644
- sync();
645
- media.addEventListener("change", sync);
646
- return () => media.removeEventListener("change", sync);
647
- }, [query]);
648
- return matches;
649
- }
650
- function useSidebarOverflow() {
651
- const contentRef = React3.useRef(null);
652
- const subscribe = React3.useCallback((onStoreChange) => {
653
- const element = contentRef.current;
654
- if (!element) {
655
- return () => void 0;
656
- }
657
- const handleScroll = () => onStoreChange();
658
- element.addEventListener("scroll", handleScroll, { passive: true });
659
- const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(onStoreChange);
660
- resizeObserver?.observe(element);
661
- window.addEventListener("resize", onStoreChange);
662
- return () => {
663
- element.removeEventListener("scroll", handleScroll);
664
- resizeObserver?.disconnect();
665
- window.removeEventListener("resize", onStoreChange);
666
- };
667
- }, []);
668
- const getSnapshot = React3.useCallback(() => {
669
- const element = contentRef.current;
670
- if (!element) {
671
- return 0;
672
- }
673
- const hasScrollBefore = element.scrollTop > 1;
674
- const hasScrollAfter = element.scrollHeight - element.clientHeight - element.scrollTop > 1;
675
- return (hasScrollBefore ? 1 : 0) | (hasScrollAfter ? 2 : 0);
676
- }, []);
677
- const scrollState = React3.useSyncExternalStore(
678
- subscribe,
679
- getSnapshot,
680
- () => 0
681
- );
682
- return {
683
- contentRef,
684
- hasScrollBefore: Boolean(scrollState & 1),
685
- hasScrollAfter: Boolean(scrollState & 2)
686
- };
687
- }
688
- function AppShell({
689
- defaultSidebarOpen = true,
690
- headerLayout = "split",
691
- children,
692
- className,
693
- style,
694
- ...props
695
- }) {
696
- const isMobile = useMediaQuery("(max-width: 1023px)");
697
- const [sidebarOpen, setSidebarOpenState] = React3.useState(defaultSidebarOpen);
698
- const [sidebarSide, setSidebarSide] = React3.useState("left");
699
- const [mobileOpen, setMobileOpen] = React3.useState(false);
700
- React3.useEffect(() => {
701
- function syncSidebarOpen() {
702
- setSidebarOpenState(readPersistedSidebarOpen() ?? defaultSidebarOpen);
703
- }
704
- const unsubscribe = subscribeToSidebarOpen(syncSidebarOpen);
705
- queueMicrotask(syncSidebarOpen);
706
- return unsubscribe;
707
- }, [defaultSidebarOpen]);
708
- const setSidebarOpen = React3.useCallback((open) => {
709
- persistSidebarOpen(open);
710
- }, []);
711
- const toggleSidebar = React3.useCallback(() => {
712
- if (isMobile) {
713
- setMobileOpen((current) => !current);
714
- return;
715
- }
716
- persistSidebarOpen(!sidebarOpen);
717
- }, [isMobile, sidebarOpen]);
718
- React3.useEffect(() => {
719
- const onKeyDown = (event) => {
720
- if (event.key.toLowerCase() === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
721
- event.preventDefault();
722
- toggleSidebar();
723
- }
724
- };
725
- window.addEventListener("keydown", onKeyDown);
726
- return () => window.removeEventListener("keydown", onKeyDown);
727
- }, [toggleSidebar]);
728
- const contextValue = React3.useMemo(
729
- () => ({
730
- sidebarState: sidebarOpen ? "expanded" : "collapsed",
731
- sidebarSide,
732
- setSidebarSide,
733
- sidebarOpen,
734
- setSidebarOpen,
735
- mobileOpen,
736
- setMobileOpen,
737
- isMobile,
738
- toggleSidebar
739
- }),
740
- [
741
- isMobile,
742
- mobileOpen,
743
- setSidebarOpen,
744
- sidebarOpen,
745
- sidebarSide,
746
- toggleSidebar
747
- ]
748
- );
749
- return /* @__PURE__ */ jsx8(AppShellContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 120, children: /* @__PURE__ */ jsx8(
750
- "div",
751
- {
752
- "data-slot": "app-shell",
753
- "data-sidebar-state": sidebarOpen ? "expanded" : "collapsed",
754
- "data-sidebar-side": sidebarSide,
755
- "data-header-layout": headerLayout,
756
- suppressHydrationWarning: true,
757
- className: cn(
758
- "group/shell min-h-svh bg-canvas text-text-primary",
759
- "[--ds-app-sidebar-width:var(--ds-sidebar-width)] [--ds-app-sidebar-width-mobile:var(--ds-sidebar-width-mobile)] data-[sidebar-state=collapsed]:[--ds-app-sidebar-width:3.5rem]",
760
- className
761
- ),
762
- style,
763
- ...props,
764
- children
765
- }
766
- ) }) });
767
- }
768
- function AppSidebar({
769
- side = "left",
770
- variant = "auto",
771
- className,
772
- children,
773
- title = "Application navigation",
774
- description = "Primary product navigation.",
775
- ...props
776
- }) {
777
- const { mobileOpen, setMobileOpen, setSidebarSide } = useAppShell();
778
- React3.useEffect(() => {
779
- setSidebarSide(side);
780
- }, [setSidebarSide, side]);
781
- return /* @__PURE__ */ jsxs7(Fragment3, { children: [
782
- /* @__PURE__ */ jsx8(Sheet, { side, open: mobileOpen, onOpenChange: setMobileOpen, children: /* @__PURE__ */ jsxs7(
783
- SheetContent,
784
- {
785
- side,
786
- "data-sidebar-variant": variant,
787
- className: "w-[var(--ds-sidebar-width-mobile)] border-sidebar-border bg-sidebar-canvas p-0 text-sidebar-primary-text [&>[data-slot=sheet-close]]:right-3 [&>[data-slot=sheet-close]]:top-3 [&>[data-slot=sheet-close]]:text-sidebar-secondary-text [&>[data-slot=sheet-close]]:hover:text-sidebar-primary-text",
788
- children: [
789
- /* @__PURE__ */ jsxs7(SheetHeader, { className: "sr-only", children: [
790
- /* @__PURE__ */ jsx8(SheetTitle, { children: title }),
791
- /* @__PURE__ */ jsx8(SheetDescription, { children: description })
792
- ] }),
793
- /* @__PURE__ */ jsx8("div", { className: "flex h-full min-h-0 flex-col", children })
794
- ]
795
- }
796
- ) }),
797
- /* @__PURE__ */ jsx8(
798
- "aside",
799
- {
800
- "data-slot": "app-sidebar",
801
- "data-side": side,
802
- "data-sidebar-variant": variant,
803
- className: cn(
804
- "fixed inset-y-0 z-20 hidden w-[var(--ds-app-sidebar-width)] shrink-0 flex-col border-sidebar-border bg-sidebar-canvas text-sidebar-primary-text transition-[width] duration-200 ease-linear lg:flex",
805
- side === "left" ? "left-0 border-r" : "right-0 border-l",
806
- "group-data-[sidebar-state=collapsed]/shell:w-[var(--ds-app-sidebar-width)]",
807
- "group-data-[header-layout=integrated]/shell:top-[var(--ds-topbar-height)]",
808
- className
809
- ),
810
- ...props,
811
- children
812
- }
813
- )
814
- ] });
815
- }
816
- function AppSidebarHeader({
817
- className,
818
- ...props
819
- }) {
820
- return /* @__PURE__ */ jsx8(
821
- "div",
822
- {
823
- "data-slot": "app-sidebar-header",
824
- className: cn(
825
- "flex min-h-[var(--ds-topbar-height)] min-w-0 shrink-0 items-center overflow-hidden border-b border-sidebar-border bg-sidebar-header px-3",
826
- className
827
- ),
828
- ...props
829
- }
830
- );
831
- }
832
- function AppSidebarContent({
833
- className,
834
- ...props
835
- }) {
836
- const { contentRef, hasScrollBefore, hasScrollAfter } = useSidebarOverflow();
837
- return /* @__PURE__ */ jsx8(
838
- "div",
839
- {
840
- "data-slot": "app-sidebar-content",
841
- "data-scroll-before": hasScrollBefore ? "true" : void 0,
842
- "data-scroll-after": hasScrollAfter ? "true" : void 0,
843
- ref: contentRef,
844
- className: cn(
845
- "relative flex min-h-0 min-w-0 flex-1 flex-col gap-[var(--ds-sidebar-group-gap)] overflow-x-clip overflow-y-auto bg-sidebar-content px-[var(--ds-sidebar-content-padding-x)] py-[var(--ds-sidebar-content-padding-y)]",
846
- className
847
- ),
848
- ...props
849
- }
850
- );
851
- }
852
- function AppSidebarFooter({
853
- className,
854
- ...props
855
- }) {
856
- return /* @__PURE__ */ jsx8(
857
- "div",
858
- {
859
- "data-slot": "app-sidebar-footer",
860
- className: cn(
861
- "mt-auto flex min-w-0 shrink-0 flex-col gap-2 overflow-hidden border-t border-sidebar-border bg-sidebar-footer p-[var(--ds-sidebar-footer-padding)]",
862
- className
863
- ),
864
- ...props
865
- }
866
- );
867
- }
868
- function ProductIdentity({
869
- label,
870
- description,
871
- icon,
872
- collapsedLabel,
873
- className
874
- }) {
875
- return /* @__PURE__ */ jsxs7(
876
- "div",
877
- {
878
- "data-slot": "product-identity",
879
- className: cn("flex min-w-0 items-center gap-2", className),
880
- children: [
881
- icon ? /* @__PURE__ */ jsx8("div", { className: "flex size-7 shrink-0 items-center justify-center rounded-[var(--ds-radius-control)] bg-sidebar-hover text-sidebar-icon", children: icon }) : null,
882
- collapsedLabel && !icon ? /* @__PURE__ */ jsx8("div", { className: "hidden shrink-0 items-center justify-center rounded-[var(--ds-radius-control)] bg-sidebar-hover px-2 py-1 text-xs font-semibold text-sidebar-primary-text group-data-[sidebar-state=collapsed]/shell:flex", children: collapsedLabel }) : null,
883
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0 group-data-[sidebar-state=collapsed]/shell:hidden", children: [
884
- /* @__PURE__ */ jsx8("div", { className: "ds-type-navigation truncate font-semibold text-sidebar-primary-text", children: label }),
885
- description ? /* @__PURE__ */ jsx8("div", { className: "ds-type-metadata truncate text-sidebar-metadata-text", children: description }) : null
886
- ] })
887
- ]
888
- }
889
- );
890
- }
891
- function SidebarSeparator({
892
- className,
893
- ...props
894
- }) {
895
- return /* @__PURE__ */ jsx8(
896
- Separator,
897
- {
898
- "data-slot": "app-sidebar-separator",
899
- className: cn("bg-sidebar-border", className),
900
- ...props
901
- }
902
- );
903
- }
904
- function NavigationGroup({
905
- label,
906
- count,
907
- children,
908
- className
909
- }) {
910
- const labelId = React3.useId();
911
- return /* @__PURE__ */ jsxs7(
912
- "section",
913
- {
914
- "data-slot": "navigation-group",
915
- "aria-labelledby": label ? labelId : void 0,
916
- className: cn(
917
- "flex min-w-0 flex-col gap-[var(--ds-sidebar-label-gap)]",
918
- className
919
- ),
920
- children: [
921
- label ? /* @__PURE__ */ jsxs7(
922
- "div",
923
- {
924
- "data-slot": "navigation-group-label",
925
- id: labelId,
926
- className: "flex min-h-6 items-center gap-2 px-2 pb-0 pt-2 text-[length:var(--ds-sidebar-group-label-size)] font-semibold uppercase leading-[var(--ds-sidebar-group-label-line-height)] tracking-[0.04em] text-sidebar-group-label group-data-[sidebar-state=collapsed]/shell:hidden",
927
- children: [
928
- label,
929
- count !== void 0 ? /* @__PURE__ */ jsx8("span", { className: "ds-type-metadata ml-auto shrink-0 font-medium normal-case tracking-normal text-sidebar-group-count", children: count }) : null
930
- ]
931
- }
932
- ) : null,
933
- /* @__PURE__ */ jsx8("div", { className: "flex min-w-0 flex-col gap-[var(--ds-sidebar-item-gap)]", children })
934
- ]
935
- }
936
- );
937
- }
938
- function navigationItemClasses(active) {
939
- return cn(
940
- "ds-type-navigation flex min-h-[var(--ds-sidebar-item-height-touch)] min-w-0 cursor-pointer items-center gap-2 rounded-[var(--ds-radius-control)] px-2 font-medium text-sidebar-secondary-text outline-none transition-colors duration-150 lg:h-[var(--ds-sidebar-item-height)] lg:min-h-0",
941
- "hover:bg-sidebar-hover hover:text-sidebar-primary-text",
942
- "focus-visible:ring-[3px] focus-visible:ring-sidebar-focus-ring",
943
- "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:cursor-not-allowed aria-disabled:opacity-50",
944
- "group-data-[sidebar-state=collapsed]/shell:justify-center group-data-[sidebar-state=collapsed]/shell:px-0",
945
- "[&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-[1.75] [&>svg]:text-sidebar-icon",
946
- active && "bg-sidebar-active-background font-semibold text-sidebar-active-foreground hover:bg-sidebar-active-background hover:text-sidebar-active-foreground [&>svg]:text-sidebar-active-foreground"
947
- );
948
- }
949
- var NavigationItem = React3.forwardRef(
950
- function NavigationItem2({
951
- active = false,
952
- tooltip,
953
- render,
954
- type,
955
- "aria-expanded": ariaExpanded,
956
- className,
957
- children,
958
- ...props
959
- }, ref) {
960
- const { sidebarState, sidebarSide, isMobile } = useAppShell();
961
- const item = useRender({
962
- defaultTagName: "button",
963
- render,
964
- ref,
965
- props: {
966
- "data-slot": "navigation-item",
967
- "data-active": active ? "true" : void 0,
968
- "aria-expanded": ariaExpanded,
969
- type: render ? void 0 : type ?? "button",
970
- className: cn(navigationItemClasses(active), className),
971
- ...props,
972
- ...render ? {} : { children }
973
- }
974
- });
975
- if (!tooltip) {
976
- return item;
977
- }
978
- return /* @__PURE__ */ jsxs7(Tooltip, { children: [
979
- /* @__PURE__ */ jsx8(TooltipTrigger, { render: item }),
980
- /* @__PURE__ */ jsx8(
981
- TooltipContent,
982
- {
983
- side: sidebarSide === "left" ? "right" : "left",
984
- align: "center",
985
- hidden: sidebarState !== "collapsed" || isMobile,
986
- children: tooltip
987
- }
988
- )
989
- ] });
990
- }
991
- );
992
- var NavigationSubItem = React3.forwardRef(
993
- function NavigationSubItem2({
994
- active = false,
995
- render,
996
- className,
997
- ...props
998
- }, ref) {
999
- return useRender({
1000
- defaultTagName: "a",
1001
- render,
1002
- ref,
1003
- props: {
1004
- "data-slot": "navigation-sub-item",
1005
- "data-active": active ? "true" : void 0,
1006
- className: cn(
1007
- "ds-type-navigation flex min-h-[var(--ds-sidebar-item-height-touch)] min-w-0 cursor-pointer items-center gap-2 rounded-[var(--ds-radius-control)] px-2 text-sidebar-secondary-text outline-none transition-colors duration-150 lg:h-[calc(var(--ds-sidebar-item-height)-0.25rem)] lg:min-h-0",
1008
- "hover:bg-sidebar-hover hover:text-sidebar-primary-text focus-visible:ring-[3px] focus-visible:ring-sidebar-focus-ring",
1009
- "group-data-[sidebar-state=collapsed]/shell:hidden [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-[1.75] [&>svg]:text-sidebar-icon",
1010
- active && "bg-sidebar-active-background font-semibold text-sidebar-active-foreground hover:bg-sidebar-active-background hover:text-sidebar-active-foreground [&>svg]:text-sidebar-active-foreground",
1011
- className
1012
- ),
1013
- ...props
1014
- }
1015
- });
1016
- }
1017
- );
1018
- function NavigationSubList({
1019
- className,
1020
- ...props
1021
- }) {
1022
- return /* @__PURE__ */ jsx8(
1023
- "div",
1024
- {
1025
- "data-slot": "navigation-sub-list",
1026
- className: cn(
1027
- "ml-4 flex min-w-0 flex-col gap-[var(--ds-sidebar-item-gap)] border-l border-sidebar-border pl-2 group-data-[sidebar-state=collapsed]/shell:hidden",
1028
- className
1029
- ),
1030
- ...props
1031
- }
1032
- );
1033
- }
1034
- function SidebarTrigger({
1035
- className,
1036
- "aria-label": ariaLabel,
1037
- onClick,
1038
- ...props
1039
- }) {
1040
- const { isMobile, mobileOpen, sidebarOpen, toggleSidebar } = useAppShell();
1041
- const triggerProps = {
1042
- ...props,
1043
- "data-slot": "sidebar-trigger",
1044
- type: "button",
1045
- variant: "ghost",
1046
- className: cn(
1047
- "shrink-0 cursor-pointer text-text-supporting hover:bg-surface-muted hover:text-text-primary focus-visible:ring-focus",
1048
- className
1049
- ),
1050
- "aria-label": ariaLabel ?? "Toggle navigation",
1051
- "aria-expanded": isMobile ? mobileOpen : sidebarOpen,
1052
- onClick: (event) => {
1053
- onClick?.(event);
1054
- toggleSidebar();
1055
- }
1056
- };
1057
- return /* @__PURE__ */ jsxs7(IconButton, { ...triggerProps, children: [
1058
- /* @__PURE__ */ jsx8(PanelLeftIcon, {}),
1059
- /* @__PURE__ */ jsx8("span", { className: "sr-only", children: "Toggle navigation" })
1060
- ] });
1061
- }
1062
- function SidebarSearch({
1063
- expanded: expandedProp,
1064
- defaultExpanded = false,
1065
- onExpandedChange,
1066
- triggerLabel = "Search navigation",
1067
- shortcut,
1068
- className,
1069
- onKeyDown,
1070
- ...props
1071
- }) {
1072
- const [expandedState, setExpandedState] = React3.useState(defaultExpanded);
1073
- const expanded = expandedProp ?? expandedState;
1074
- const inputRef = React3.useRef(null);
1075
- const triggerRef = React3.useRef(null);
1076
- const mountedRef = React3.useRef(false);
1077
- const setExpanded = React3.useCallback(
1078
- (nextExpanded) => {
1079
- if (expandedProp === void 0) {
1080
- setExpandedState(nextExpanded);
1081
- }
1082
- onExpandedChange?.(nextExpanded);
1083
- },
1084
- [expandedProp, onExpandedChange]
1085
- );
1086
- React3.useEffect(() => {
1087
- if (expanded) {
1088
- queueMicrotask(() => inputRef.current?.focus());
1089
- } else if (mountedRef.current) {
1090
- queueMicrotask(() => triggerRef.current?.focus());
1091
- }
1092
- mountedRef.current = true;
1093
- }, [expanded]);
1094
- if (!expanded) {
1095
- return /* @__PURE__ */ jsxs7(
1096
- "button",
1097
- {
1098
- ref: triggerRef,
1099
- type: "button",
1100
- "data-slot": "sidebar-search-trigger",
1101
- className: cn(
1102
- "ds-type-navigation flex min-h-[var(--ds-sidebar-item-height-touch)] w-full cursor-pointer items-center gap-2 rounded-[var(--ds-radius-control)] px-2 text-left font-medium text-sidebar-secondary-text outline-none transition-colors hover:bg-sidebar-hover hover:text-sidebar-primary-text focus-visible:ring-[3px] focus-visible:ring-sidebar-focus-ring lg:min-h-[var(--ds-sidebar-item-height)]",
1103
- "group-data-[sidebar-state=collapsed]/shell:justify-center group-data-[sidebar-state=collapsed]/shell:px-0",
1104
- className
1105
- ),
1106
- onClick: () => setExpanded(true),
1107
- "aria-label": triggerLabel,
1108
- children: [
1109
- /* @__PURE__ */ jsx8(Search, { className: "size-4 shrink-0 text-sidebar-icon" }),
1110
- /* @__PURE__ */ jsx8("span", { className: "truncate group-data-[sidebar-state=collapsed]/shell:hidden", children: triggerLabel }),
1111
- shortcut ? /* @__PURE__ */ jsx8(ShortcutHint, { className: "ds-type-metadata ml-auto border-sidebar-border bg-transparent text-sidebar-metadata-text group-data-[sidebar-state=collapsed]/shell:hidden", children: shortcut }) : null
1112
- ]
1113
- }
1114
- );
1115
- }
1116
- return /* @__PURE__ */ jsxs7(
1117
- "div",
1118
- {
1119
- "data-slot": "sidebar-search",
1120
- "data-expanded": "true",
1121
- className: cn(
1122
- "flex min-h-[var(--ds-sidebar-item-height-touch)] items-center gap-2 rounded-[var(--ds-radius-control)] border border-sidebar-border bg-sidebar-search px-2 text-sidebar-primary-text shadow-[var(--ds-shadow-raised)] lg:min-h-[var(--ds-sidebar-item-height)]",
1123
- className
1124
- ),
1125
- children: [
1126
- /* @__PURE__ */ jsx8(Search, { className: "size-4 shrink-0 text-sidebar-icon" }),
1127
- /* @__PURE__ */ jsx8(
1128
- Input,
1129
- {
1130
- ref: inputRef,
1131
- type: "search",
1132
- className: "ds-type-control h-auto min-w-0 flex-1 border-0 bg-transparent px-0 py-1 shadow-none focus-visible:border-0 focus-visible:ring-0",
1133
- onKeyDown: (event) => {
1134
- if (event.key === "Escape") {
1135
- event.preventDefault();
1136
- setExpanded(false);
1137
- }
1138
- onKeyDown?.(event);
1139
- },
1140
- ...props
1141
- }
1142
- ),
1143
- /* @__PURE__ */ jsx8(
1144
- "button",
1145
- {
1146
- type: "button",
1147
- "data-slot": "sidebar-search-close",
1148
- className: "grid size-7 shrink-0 cursor-pointer place-items-center rounded-[var(--ds-radius-control)] text-sidebar-secondary-text outline-none transition-colors hover:bg-sidebar-hover hover:text-sidebar-primary-text focus-visible:ring-2 focus-visible:ring-sidebar-focus-ring",
1149
- onClick: () => {
1150
- setExpanded(false);
1151
- },
1152
- "aria-label": "Close search",
1153
- children: /* @__PURE__ */ jsx8(X, { className: "size-4" })
1154
- }
1155
- )
1156
- ]
1157
- }
1158
- );
1159
- }
1160
- function MainRegion({
1161
- className,
1162
- ...props
1163
- }) {
1164
- return /* @__PURE__ */ jsx8(
1165
- "div",
1166
- {
1167
- "data-slot": "main-region",
1168
- className: cn(
1169
- "flex min-h-svh min-w-0 w-full flex-1 flex-col transition-[padding] duration-200 ease-linear",
1170
- "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)]",
1171
- "group-data-[header-layout=integrated]/shell:pt-[var(--ds-topbar-height)]",
1172
- className
1173
- ),
1174
- ...props
1175
- }
1176
- );
1177
- }
1178
- function AppHeader({
1179
- className,
1180
- ...props
1181
- }) {
1182
- return /* @__PURE__ */ jsx8(
1183
- "header",
1184
- {
1185
- "data-slot": "app-header",
1186
- className: cn(
1187
- "fixed inset-x-0 top-0 z-30 flex h-[var(--ds-topbar-height)] min-h-[var(--ds-topbar-height)] items-center gap-2 border-b border-border-subtle bg-canvas/96 px-[var(--ds-topbar-padding-x)] backdrop-blur supports-[backdrop-filter]:bg-canvas/88 md:gap-3 md:px-[var(--ds-topbar-padding-x-wide)]",
1188
- className
1189
- ),
1190
- ...props
1191
- }
1192
- );
1193
- }
1194
- function AppHeaderStart({
1195
- className,
1196
- ...props
1197
- }) {
1198
- return /* @__PURE__ */ jsx8(
1199
- "div",
1200
- {
1201
- "data-slot": "app-header-start",
1202
- className: cn("flex min-w-0 flex-1 items-center gap-2", className),
1203
- ...props
1204
- }
1205
- );
1206
- }
1207
- function AppHeaderSearch({
1208
- mobileTrigger,
1209
- children,
1210
- className,
1211
- ...props
1212
- }) {
1213
- return /* @__PURE__ */ jsxs7(
1214
- "div",
1215
- {
1216
- "data-slot": "app-header-search",
1217
- className: cn("ml-auto flex shrink-0 items-center", className),
1218
- ...props,
1219
- children: [
1220
- /* @__PURE__ */ jsx8("div", { className: "hidden w-[min(22rem,32vw)] md:block", children }),
1221
- /* @__PURE__ */ jsx8("div", { className: "md:hidden", children: mobileTrigger })
1222
- ]
1223
- }
1224
- );
1225
- }
1226
- function AppHeaderActions({
1227
- className,
1228
- ...props
1229
- }) {
1230
- return /* @__PURE__ */ jsx8(
1231
- "div",
1232
- {
1233
- "data-slot": "app-header-actions",
1234
- className: cn("flex shrink-0 items-center gap-1", className),
1235
- ...props
1236
- }
1237
- );
1238
- }
1239
- function TopBar({
1240
- className,
1241
- ...props
1242
- }) {
1243
- return /* @__PURE__ */ jsx8(
1244
- "header",
1245
- {
1246
- "data-slot": "top-bar",
1247
- className: cn(
1248
- "sticky top-0 z-10 flex h-[var(--ds-topbar-height)] min-h-[var(--ds-topbar-height)] shrink-0 items-center justify-between gap-3 border-b border-border-subtle bg-canvas/96 px-[var(--ds-topbar-padding-x)] backdrop-blur md:px-[var(--ds-topbar-padding-x-wide)]",
1249
- "supports-[backdrop-filter]:bg-canvas/88",
1250
- className
1251
- ),
1252
- ...props
1253
- }
1254
- );
1255
- }
1256
- function PageFrame({
1257
- width = "full",
1258
- className,
1259
- ...props
1260
- }) {
1261
- return /* @__PURE__ */ jsx8(
1262
- "main",
1263
- {
1264
- "data-slot": "page-frame",
1265
- "data-width": width,
1266
- className: cn(
1267
- "min-w-0 w-full flex-1 px-3 py-[var(--ds-space-section)] md:px-[var(--ds-space-page)]",
1268
- width === "wide" && "mx-auto w-full max-w-[86rem]",
1269
- width === "focused" && "mx-auto w-full max-w-[64rem]",
1270
- width === "reading" && "mx-auto w-full max-w-[48rem]",
1271
- className
1272
- ),
1273
- ...props
1274
- }
1275
- );
1276
- }
1277
- function PageContent({
1278
- className,
1279
- ...props
1280
- }) {
1281
- return /* @__PURE__ */ jsx8(
1282
- "div",
1283
- {
1284
- "data-slot": "page-content",
1285
- className: cn("flex min-w-0 flex-col gap-[var(--ds-space-section)]", className),
1286
- ...props
1287
- }
1288
- );
1289
- }
1290
- function PageBoundary({
1291
- className,
1292
- ...props
1293
- }) {
1294
- return /* @__PURE__ */ jsx8(
1295
- "div",
1296
- {
1297
- "data-slot": "page-boundary",
1298
- className: cn(
1299
- "rounded-[var(--ds-radius-surface)] border border-border-subtle bg-surface p-[var(--ds-surface-padding)]",
1300
- className
1301
- ),
1302
- ...props
1303
- }
1304
- );
1305
- }
1306
- function InspectorRegion({
1307
- className,
1308
- ...props
1309
- }) {
1310
- return /* @__PURE__ */ jsx8(
1311
- "aside",
1312
- {
1313
- "data-slot": "inspector-region",
1314
- className: cn(
1315
- "w-full border-l border-border-subtle bg-surface md:w-[20rem] xl:w-[24rem]",
1316
- className
1317
- ),
1318
- ...props
1319
- }
1320
- );
1321
- }
1322
-
1323
- // src/patterns/activity-list.tsx
1324
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1325
- function ActivityList({ className, ...props }) {
1326
- return /* @__PURE__ */ jsx9("div", { "data-slot": "activity-list", className: cn("divide-y divide-border-subtle", className), ...props });
1327
- }
1328
- function ActivityItem({
1329
- leading,
1330
- icon,
1331
- title,
1332
- description,
1333
- metadata,
1334
- trailing,
1335
- status,
1336
- layout = "standard",
1337
- className,
1338
- ...props
1339
- }) {
1340
- const hasLeading = leading !== void 0 || icon !== void 0;
1341
- const resolvedTrailing = trailing ?? status;
1342
- return /* @__PURE__ */ jsxs8(
1343
- "div",
1344
- {
1345
- "data-slot": "activity-item",
1346
- "data-layout": layout,
1347
- className: cn(
1348
- "grid gap-3 py-3",
1349
- hasLeading && resolvedTrailing && "grid-cols-[auto_minmax(0,1fr)_auto]",
1350
- hasLeading && !resolvedTrailing && "grid-cols-[auto_minmax(0,1fr)]",
1351
- !hasLeading && resolvedTrailing && "grid-cols-[minmax(0,1fr)_auto]",
1352
- !hasLeading && !resolvedTrailing && "grid-cols-1",
1353
- layout === "compact" && "py-2",
1354
- className
1355
- ),
1356
- ...props,
1357
- children: [
1358
- leading !== void 0 ? /* @__PURE__ */ jsx9("div", { "data-slot": "activity-item-leading", className: "shrink-0", children: leading }) : icon !== void 0 ? /* @__PURE__ */ jsx9("div", { "data-slot": "activity-item-leading", className: "flex size-8 items-center justify-center rounded-md bg-neutral-background text-neutral-foreground [&_svg]:size-4", children: icon }) : null,
1359
- /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
1360
- /* @__PURE__ */ jsx9("div", { className: "ds-type-ui font-medium text-text-primary", children: title }),
1361
- description ? /* @__PURE__ */ jsx9("div", { className: "ds-type-ui mt-0.5 text-text-supporting", children: description }) : null,
1362
- metadata ? /* @__PURE__ */ jsx9("div", { className: "ds-type-metadata mt-1 text-text-supporting", children: metadata }) : null
1363
- ] }),
1364
- resolvedTrailing ? /* @__PURE__ */ jsx9("div", { "data-slot": "activity-item-trailing", className: "shrink-0", children: resolvedTrailing }) : null
1365
- ]
1366
- }
1367
- );
1368
- }
1369
-
1370
- // src/patterns/attention-list.tsx
1371
- import { CheckCircle2, CircleAlert, CircleX, Info } from "lucide-react";
1372
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1373
- function AttentionList({ className, ...props }) {
1374
- return /* @__PURE__ */ jsx10("ul", { "data-slot": "attention-list", className: cn("grid gap-2", className), ...props });
1375
- }
1376
- var toneClasses = {
1377
- neutral: "border-neutral-border bg-neutral-background text-neutral-foreground",
1378
- information: "border-information-border bg-information-background text-information-foreground",
1379
- success: "border-success-border bg-success-background text-success-foreground",
1380
- warning: "border-warning-border bg-warning-background text-warning-foreground",
1381
- danger: "border-danger-border bg-danger-background text-danger-foreground"
1382
- };
1383
- function AttentionItem({ title, description, metadata, action, tone = "neutral", severityLabel = `${tone[0].toUpperCase()}${tone.slice(1)}`, icon, className, ...props }) {
1384
- const Icon = tone === "danger" ? CircleX : tone === "warning" ? CircleAlert : tone === "success" ? CheckCircle2 : Info;
1385
- return /* @__PURE__ */ jsxs9("li", { "data-slot": "attention-item", "data-tone": tone, className: cn("grid grid-cols-[auto_minmax(0,1fr)_auto] items-start gap-3 rounded-[var(--ds-radius-control)] border px-3 py-2.5", toneClasses[tone], className), ...props, children: [
1386
- /* @__PURE__ */ jsx10("span", { className: "mt-0.5 [&>svg]:size-4", "aria-hidden": "true", children: icon ?? /* @__PURE__ */ jsx10(Icon, {}) }),
1387
- /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
1388
- /* @__PURE__ */ jsxs9("span", { className: "sr-only", children: [
1389
- severityLabel,
1390
- ": "
1391
- ] }),
1392
- /* @__PURE__ */ jsx10("div", { className: "ds-type-ui font-medium", children: title }),
1393
- description ? /* @__PURE__ */ jsx10("div", { className: "ds-type-metadata mt-0.5 opacity-85", children: description }) : null,
1394
- metadata ? /* @__PURE__ */ jsx10("div", { className: "ds-type-metadata mt-1 opacity-85", children: metadata }) : null
1395
- ] }),
1396
- action ? /* @__PURE__ */ jsx10("div", { className: "shrink-0", children: action }) : null
1397
- ] });
1398
- }
1399
-
1400
- // src/patterns/confirmation-dialog.tsx
1401
- import * as React4 from "react";
1402
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1403
- function ConfirmationDialog({ trigger, title, description, children, confirmLabel = "Confirm", cancelLabel = "Cancel", confirmVariant = "destructive", pending = false, onConfirm, onError }) {
1404
- const [open, setOpen] = React4.useState(false);
1405
- const [confirming, setConfirming] = React4.useState(false);
1406
- const isPending = pending || confirming;
1407
- async function confirm() {
1408
- if (isPending) {
1409
- return;
1410
- }
1411
- setConfirming(true);
1412
- try {
1413
- await onConfirm();
1414
- setOpen(false);
1415
- } catch (error) {
1416
- onError?.(error);
1417
- } finally {
1418
- setConfirming(false);
1419
- }
1420
- }
1421
- return /* @__PURE__ */ jsxs10(AlertDialog, { open, onOpenChange: setOpen, children: [
1422
- /* @__PURE__ */ jsx11(AlertDialogTrigger, { render: trigger, children: trigger }),
1423
- /* @__PURE__ */ jsxs10(AlertDialogContent, { children: [
1424
- /* @__PURE__ */ jsxs10(AlertDialogHeader, { children: [
1425
- /* @__PURE__ */ jsx11(AlertDialogTitle, { children: title }),
1426
- /* @__PURE__ */ jsx11(AlertDialogDescription, { children: description })
1427
- ] }),
1428
- /* @__PURE__ */ jsx11(AlertDialogBody, { children }),
1429
- /* @__PURE__ */ jsxs10(AlertDialogFooter, { children: [
1430
- /* @__PURE__ */ jsx11(AlertDialogCancel, { render: /* @__PURE__ */ jsx11(Button, { type: "button", variant: "outline", disabled: isPending }), children: cancelLabel }),
1431
- /* @__PURE__ */ jsx11(AlertDialogAction, { render: /* @__PURE__ */ jsx11(Button, { type: "button", variant: confirmVariant, disabled: isPending, onClick: confirm }), children: isPending ? "Working..." : confirmLabel })
1432
- ] })
1433
- ] })
1434
- ] });
1435
- }
1436
-
1437
- // src/patterns/code-block.tsx
1438
- import * as React5 from "react";
1439
- import { Check, Copy } from "lucide-react";
1440
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1441
- function CodeBlock({
1442
- snippets,
1443
- defaultValue,
1444
- copyLabel = "Copy code",
1445
- className,
1446
- ...props
1447
- }) {
1448
- const initialValue = defaultValue ?? snippets[0]?.value ?? "";
1449
- const [activeValue, setActiveValue] = React5.useState(initialValue);
1450
- const [copiedValue, setCopiedValue] = React5.useState(null);
1451
- const [copyError, setCopyError] = React5.useState(false);
1452
- const copyStatusId = React5.useId();
1453
- const activeSnippet = snippets.find((snippet) => snippet.value === activeValue) ?? snippets[0];
1454
- if (!activeSnippet) return null;
1455
- return /* @__PURE__ */ jsx12(
1456
- "div",
1457
- {
1458
- "data-slot": "code-block",
1459
- className: cn("overflow-hidden rounded-lg border border-border-subtle bg-surface", className),
1460
- ...props,
1461
- children: /* @__PURE__ */ jsxs11(Tabs, { value: activeSnippet.value, onValueChange: setActiveValue, variant: "segmented", className: "gap-0", children: [
1462
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3 border-b border-border-subtle bg-surface-muted px-3 py-2", children: [
1463
- /* @__PURE__ */ jsx12(TabsList, { variant: "segmented", size: "compact", "aria-label": "Code language", children: snippets.map((snippet) => /* @__PURE__ */ jsx12(TabsTrigger, { value: snippet.value, children: snippet.label }, snippet.value)) }),
1464
- /* @__PURE__ */ jsxs11(
1465
- Button,
1466
- {
1467
- type: "button",
1468
- variant: "ghost",
1469
- size: "sm",
1470
- onClick: async () => {
1471
- try {
1472
- await navigator.clipboard.writeText(activeSnippet.code);
1473
- setCopiedValue(activeSnippet.value);
1474
- setCopyError(false);
1475
- } catch {
1476
- setCopiedValue(null);
1477
- setCopyError(true);
1478
- }
1479
- },
1480
- "aria-describedby": copyStatusId,
1481
- children: [
1482
- copiedValue === activeSnippet.value ? /* @__PURE__ */ jsx12(Check, {}) : /* @__PURE__ */ jsx12(Copy, {}),
1483
- copiedValue === activeSnippet.value ? "Copied" : copyLabel
1484
- ]
1485
- }
1486
- ),
1487
- /* @__PURE__ */ jsx12("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." : "" })
1488
- ] }),
1489
- snippets.map((snippet) => /* @__PURE__ */ jsx12(TabsContent, { value: snippet.value, className: "m-0", children: /* @__PURE__ */ jsx12(
1490
- "pre",
1491
- {
1492
- "aria-label": `${snippet.label} code example`,
1493
- tabIndex: 0,
1494
- className: "max-h-[32rem] overflow-auto p-4 text-sm leading-6 outline-none focus-visible:ring-[3px] focus-visible:ring-inset focus-visible:ring-focus/50",
1495
- children: /* @__PURE__ */ jsx12("code", { children: snippet.code })
1496
- }
1497
- ) }, snippet.value))
1498
- ] })
1499
- }
1500
- );
1501
- }
1502
-
1503
- // src/patterns/inventory-surface.tsx
1504
- import { jsx as jsx13 } from "react/jsx-runtime";
1505
- function InventorySurface({ className, ...props }) {
1506
- return /* @__PURE__ */ jsx13(
1507
- Card,
1508
- {
1509
- "data-slot": "inventory-surface",
1510
- className: cn("gap-0 overflow-hidden py-0", className),
1511
- ...props
1512
- }
1513
- );
1514
- }
1515
- function InventoryDesktop({ className, ...props }) {
1516
- return /* @__PURE__ */ jsx13("div", { "data-slot": "inventory-desktop", className: cn("hidden lg:block", className), ...props });
1517
- }
1518
- function InventoryMobile({ className, ...props }) {
1519
- return /* @__PURE__ */ jsx13("div", { "data-slot": "inventory-mobile", className: cn("divide-y divide-border-subtle lg:hidden", className), ...props });
1520
- }
1521
-
1522
- // src/patterns/metric-band.tsx
1523
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1524
- function MetricBand({ columns = 4, className, ...props }) {
1525
- return /* @__PURE__ */ jsx14(
1526
- "div",
1527
- {
1528
- "data-slot": "metric-band",
1529
- "data-columns": columns,
1530
- className: cn(
1531
- "grid grid-cols-2 border-b border-border-subtle",
1532
- columns === 2 && "lg:grid-cols-2",
1533
- columns === 3 && "lg:grid-cols-3",
1534
- columns === 4 && "lg:grid-cols-4",
1535
- columns === 5 && "lg:grid-cols-5",
1536
- className
1537
- ),
1538
- ...props
1539
- }
1540
- );
1541
- }
1542
- function MetricBandItem({
1543
- label,
1544
- value,
1545
- detail,
1546
- icon,
1547
- iconClassName,
1548
- loading = false,
1549
- className,
1550
- ...props
1551
- }) {
1552
- return /* @__PURE__ */ jsxs12(
1553
- "div",
1554
- {
1555
- "data-slot": "metric-band-item",
1556
- className: cn(
1557
- "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",
1558
- "[&:nth-child(-n+2)]:border-b lg:[&:nth-child(-n+2)]:border-b-0",
1559
- className
1560
- ),
1561
- ...props,
1562
- children: [
1563
- icon ? /* @__PURE__ */ jsx14(
1564
- "div",
1565
- {
1566
- className: cn(
1567
- "flex size-10 shrink-0 items-center justify-center rounded-md bg-neutral-background text-neutral-foreground [&_svg]:size-5",
1568
- iconClassName
1569
- ),
1570
- children: icon
1571
- }
1572
- ) : null,
1573
- /* @__PURE__ */ jsxs12("div", { className: "grid min-w-0 gap-1", children: [
1574
- /* @__PURE__ */ jsx14("div", { className: "ds-type-ui text-text-supporting", children: label }),
1575
- loading ? /* @__PURE__ */ jsx14(Skeleton, { className: "h-7 w-14" }) : /* @__PURE__ */ jsx14("div", { className: "text-2xl font-semibold tracking-tight", children: value ?? 0 }),
1576
- detail ? /* @__PURE__ */ jsx14("div", { className: "ds-type-metadata text-text-supporting", children: detail }) : null
1577
- ] })
1578
- ]
1579
- }
1580
- );
1581
- }
1582
-
1583
- // src/patterns/metric-card.tsx
1584
- import * as React6 from "react";
1585
- import { ArrowDown as ArrowDown2, ArrowUp as ArrowUp2, Minus } from "lucide-react";
1586
- import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1587
- function MetricTrend({
1588
- direction,
1589
- sentiment = "neutral",
1590
- value,
1591
- accessibleLabel,
1592
- className,
1593
- ...props
1594
- }) {
1595
- const Icon = direction === "up" ? ArrowUp2 : direction === "down" ? ArrowDown2 : Minus;
1596
- return /* @__PURE__ */ jsxs13(
1597
- "span",
1598
- {
1599
- "data-slot": "metric-trend",
1600
- "data-direction": direction,
1601
- "data-sentiment": sentiment,
1602
- role: "img",
1603
- "aria-label": accessibleLabel,
1604
- className: cn(
1605
- "inline-flex items-center gap-1 ds-type-metadata font-medium text-trend-neutral",
1606
- sentiment === "positive" && "text-trend-positive",
1607
- sentiment === "negative" && "text-trend-negative",
1608
- className
1609
- ),
1610
- ...props,
1611
- children: [
1612
- /* @__PURE__ */ jsx15(Icon, { "aria-hidden": "true", className: "size-3.5 stroke-[2]" }),
1613
- /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: value })
1614
- ]
1615
- }
1616
- );
1617
- }
1618
- function MetricCard({
1619
- label,
1620
- description,
1621
- value,
1622
- unit,
1623
- trend,
1624
- status,
1625
- emphasis = "supporting",
1626
- loading = false,
1627
- visualization,
1628
- visualizationSummary,
1629
- className,
1630
- ...props
1631
- }) {
1632
- const labelId = React6.useId();
1633
- return /* @__PURE__ */ jsxs13(
1634
- "section",
1635
- {
1636
- "data-slot": "metric-card",
1637
- "data-emphasis": emphasis,
1638
- "aria-labelledby": labelId,
1639
- className: cn(
1640
- "flex min-w-0 flex-col overflow-hidden rounded-[var(--ds-radius-surface)] border border-border-default bg-surface text-text-primary shadow-[var(--ds-shadow-raised)]",
1641
- emphasis === "primary" ? "min-h-80" : "min-h-40",
1642
- className
1643
- ),
1644
- ...props,
1645
- children: [
1646
- /* @__PURE__ */ jsxs13("div", { className: "flex items-start justify-between gap-4 px-[var(--ds-surface-padding)] pt-[var(--ds-surface-padding)]", children: [
1647
- /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
1648
- /* @__PURE__ */ jsx15("h2", { id: labelId, className: "ds-type-card-title", children: label }),
1649
- description ? /* @__PURE__ */ jsx15("p", { className: "ds-type-metadata mt-0.5 text-text-supporting", children: description }) : null
1650
- ] }),
1651
- status ? /* @__PURE__ */ jsx15("div", { className: "shrink-0", children: status }) : null
1652
- ] }),
1653
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1 px-[var(--ds-surface-padding)] pt-3", children: [
1654
- loading ? /* @__PURE__ */ jsx15(Skeleton, { className: cn("h-8", emphasis === "primary" ? "w-24" : "w-16") }) : /* @__PURE__ */ jsxs13(Fragment4, { children: [
1655
- /* @__PURE__ */ jsx15("span", { className: cn("font-semibold tabular-nums tracking-tight", emphasis === "primary" ? "text-4xl" : "text-2xl"), children: value ?? 0 }),
1656
- unit ? /* @__PURE__ */ jsx15("span", { className: "ds-type-ui text-text-supporting", children: unit }) : null
1657
- ] }),
1658
- trend ? /* @__PURE__ */ jsx15("div", { className: "ml-1", children: trend }) : null
1659
- ] }),
1660
- visualization ? /* @__PURE__ */ jsxs13("figure", { className: "mt-auto min-h-0 flex-1 pt-4", children: [
1661
- /* @__PURE__ */ jsx15("div", { "data-slot": "metric-card-visualization", className: "h-full min-h-20 w-full", children: visualization }),
1662
- /* @__PURE__ */ jsx15("figcaption", { className: "sr-only", children: visualizationSummary })
1663
- ] }) : null
1664
- ]
1665
- }
1666
- );
1667
- }
1668
-
1669
- // src/patterns/page-header.tsx
1670
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1671
- function PageHeader({
1672
- title,
1673
- description,
1674
- status,
1675
- metadata,
1676
- actions,
1677
- action,
1678
- actionNode,
1679
- className,
1680
- ...props
1681
- }) {
1682
- const resolvedActions = actions ?? actionNode ?? (action ? /* @__PURE__ */ jsx16(
1683
- "a",
1684
- {
1685
- className: "ds-type-button inline-flex h-[var(--ds-control-height)] items-center justify-center gap-2 whitespace-nowrap rounded-md bg-action px-3 py-2 text-action-foreground shadow-xs outline-none transition-colors hover:bg-action-hover focus-visible:border-focus focus-visible:ring-3 focus-visible:ring-focus/50",
1686
- href: action.href,
1687
- children: action.label
1688
- }
1689
- ) : null);
1690
- return /* @__PURE__ */ jsxs14(
1691
- "header",
1692
- {
1693
- "data-slot": "page-header",
1694
- className: cn("flex flex-col gap-3 border-b border-border-subtle bg-canvas px-5 py-4 lg:flex-row lg:items-start lg:justify-between", className),
1695
- ...props,
1696
- children: [
1697
- /* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
1698
- /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
1699
- /* @__PURE__ */ jsx16("h1", { className: "ds-type-page-title truncate", children: title }),
1700
- status
1701
- ] }),
1702
- description ? /* @__PURE__ */ jsx16("p", { className: "ds-type-ui mt-1 max-w-3xl text-text-supporting", children: description }) : null,
1703
- metadata ? /* @__PURE__ */ jsx16("div", { className: "ds-type-metadata mt-2 text-text-supporting", children: metadata }) : null
1704
- ] }),
1705
- resolvedActions ? /* @__PURE__ */ jsx16("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: resolvedActions }) : null
1706
- ]
1707
- }
1708
- );
1709
- }
1710
-
1711
- // src/patterns/page-toolbar.tsx
1712
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1713
- function PageToolbar({
1714
- search,
1715
- filters,
1716
- viewControls,
1717
- bulkActions,
1718
- className,
1719
- children,
1720
- ...props
1721
- }) {
1722
- return /* @__PURE__ */ jsxs15(
1723
- "div",
1724
- {
1725
- "data-slot": "page-toolbar",
1726
- className: cn("grid gap-2 border-b border-border-subtle bg-canvas px-5 py-3 lg:grid-cols-[minmax(0,1fr)_auto] lg:items-center", className),
1727
- ...props,
1728
- children: [
1729
- /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-1 flex-col gap-2 sm:flex-row sm:items-center", children: [
1730
- search ? /* @__PURE__ */ jsx17("div", { className: "min-w-0 flex-1 sm:min-w-48 sm:max-w-sm", children: search }) : null,
1731
- filters ? /* @__PURE__ */ jsx17("div", { className: "flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:flex-wrap sm:items-center", children: filters }) : null
1732
- ] }),
1733
- /* @__PURE__ */ jsxs15("div", { className: "flex min-h-[var(--ds-control-height)] flex-wrap items-center gap-2 lg:justify-end", children: [
1734
- bulkActions ? /* @__PURE__ */ jsx17("div", { "data-slot": "page-toolbar-bulk-actions", className: "contents", children: bulkActions }) : null,
1735
- viewControls,
1736
- children
1737
- ] })
1738
- ]
1739
- }
1740
- );
1741
- }
1742
-
1743
- // src/patterns/preference-controls.tsx
1744
- import * as React7 from "react";
1745
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1746
- var APPEARANCE_KEY = "conscia-appearance:v1";
1747
- var DENSITY_KEY = "conscia-density:v1";
1748
- var PREFERENCE_EVENT = "conscia-preferences";
1749
- var volatilePreferences = /* @__PURE__ */ new Map();
1750
- function readPreference(key, fallback, allowedValues) {
1751
- if (typeof window === "undefined") {
1752
- return fallback;
1753
- }
1754
- try {
1755
- const value = window.localStorage.getItem(key) ?? volatilePreferences.get(key);
1756
- return value && allowedValues.includes(value) ? value : fallback;
1757
- } catch {
1758
- const value = volatilePreferences.get(key);
1759
- return value && allowedValues.includes(value) ? value : fallback;
1760
- }
1761
- }
1762
- function writePreference(key, value) {
1763
- volatilePreferences.set(key, value);
1764
- try {
1765
- window.localStorage.setItem(key, value);
1766
- } catch {
1767
- }
1768
- window.dispatchEvent(new Event(PREFERENCE_EVENT));
1769
- }
1770
- function useStoredPreference(key, fallback, allowedValues) {
1771
- return React7.useSyncExternalStore(
1772
- (onStoreChange) => {
1773
- window.addEventListener("storage", onStoreChange);
1774
- window.addEventListener(PREFERENCE_EVENT, onStoreChange);
1775
- return () => {
1776
- window.removeEventListener("storage", onStoreChange);
1777
- window.removeEventListener(PREFERENCE_EVENT, onStoreChange);
1778
- };
1779
- },
1780
- () => readPreference(key, fallback, allowedValues),
1781
- () => fallback
1782
- );
1783
- }
1784
- function useConsciaPreferences() {
1785
- const appearance = useStoredPreference(
1786
- APPEARANCE_KEY,
1787
- "system",
1788
- appearanceOptions
1789
- );
1790
- const density = useStoredPreference(
1791
- DENSITY_KEY,
1792
- "comfortable",
1793
- densityOptions
1794
- );
1795
- return { appearance, density };
1796
- }
1797
- function DesignSystemPreferenceSync() {
1798
- const { appearance, density } = useConsciaPreferences();
1799
- React7.useEffect(() => {
1800
- const media = window.matchMedia("(prefers-color-scheme: dark)");
1801
- const sync = () => applyConsciaPreferences(
1802
- document.documentElement,
1803
- appearance,
1804
- density,
1805
- media.matches
1806
- );
1807
- sync();
1808
- media.addEventListener("change", sync);
1809
- return () => media.removeEventListener("change", sync);
1810
- }, [appearance, density]);
1811
- return null;
1812
- }
1813
- function AppearanceControl({ className }) {
1814
- const { appearance } = useConsciaPreferences();
1815
- return /* @__PURE__ */ jsx18(
1816
- SegmentedControl,
1817
- {
1818
- className,
1819
- label: "Appearance",
1820
- value: appearance,
1821
- values: appearanceOptions,
1822
- onChange: (value) => writePreference(APPEARANCE_KEY, value)
1823
- }
1824
- );
1825
- }
1826
- function DensityControl({ className }) {
1827
- const { density } = useConsciaPreferences();
1828
- return /* @__PURE__ */ jsx18(
1829
- SegmentedControl,
1830
- {
1831
- className,
1832
- label: "Density",
1833
- value: density,
1834
- values: densityOptions,
1835
- onChange: (value) => writePreference(DENSITY_KEY, value)
1836
- }
1837
- );
1838
- }
1839
- function DesignPreferenceControls({ className }) {
1840
- return /* @__PURE__ */ jsxs16("div", { className: cn("flex flex-col gap-3 text-sm", className), children: [
1841
- /* @__PURE__ */ jsx18(AppearanceControl, {}),
1842
- /* @__PURE__ */ jsx18(DensityControl, {})
1843
- ] });
1844
- }
1845
- function SegmentedControl({
1846
- className,
1847
- label,
1848
- value,
1849
- values,
1850
- onChange
1851
- }) {
1852
- return /* @__PURE__ */ jsxs16("fieldset", { className: cn("flex flex-col gap-2", className), children: [
1853
- /* @__PURE__ */ jsx18("legend", { className: "text-[var(--ds-metadata)] font-medium text-text-supporting", children: label }),
1854
- /* @__PURE__ */ jsx18("div", { className: "grid w-full grid-cols-3 rounded-[var(--ds-radius-control)] bg-surface-muted p-1", children: values.map((item) => /* @__PURE__ */ jsx18(
1855
- "button",
1856
- {
1857
- type: "button",
1858
- "aria-pressed": value === item,
1859
- suppressHydrationWarning: true,
1860
- onClick: () => onChange(item),
1861
- className: "min-w-0 h-7 rounded-[calc(var(--ds-radius-control)-2px)] px-1.5 text-[var(--ds-metadata)] font-medium capitalize text-text-supporting outline-none transition-colors hover:text-text-primary focus-visible:ring-[3px] focus-visible:ring-focus/50 aria-pressed:bg-canvas aria-pressed:text-text-primary aria-pressed:shadow-xs",
1862
- children: item
1863
- },
1864
- item
1865
- )) })
1866
- ] });
1867
- }
1868
-
1869
- // src/patterns/provider-mark.tsx
1870
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
1871
- function ProviderMark({ name, shortName, description, size = "default", className, ...props }) {
1872
- return /* @__PURE__ */ jsxs17("div", { "data-slot": "provider-mark", className: cn("flex min-w-0 items-center gap-3", className), ...props, children: [
1873
- /* @__PURE__ */ jsx19(
1874
- "div",
1875
- {
1876
- "aria-hidden": "true",
1877
- className: cn(
1878
- "flex shrink-0 items-center justify-center rounded-md border border-border-subtle bg-surface-muted font-semibold tracking-tight text-text-primary",
1879
- size === "sm" ? "size-8 text-[10px]" : "size-10 text-xs"
1880
- ),
1881
- children: shortName
1882
- }
1883
- ),
1884
- /* @__PURE__ */ jsxs17("div", { className: "min-w-0", children: [
1885
- /* @__PURE__ */ jsx19("div", { className: "ds-type-ui truncate font-medium text-text-primary", children: name }),
1886
- description ? /* @__PURE__ */ jsx19("div", { className: "ds-type-metadata mt-0.5 truncate text-text-supporting", children: description }) : null
1887
- ] })
1888
- ] });
1889
- }
1890
-
1891
- // src/patterns/resource-detail.tsx
1892
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
1893
- function ResourceSummary({
1894
- variant = "plain",
1895
- title,
1896
- description,
1897
- status,
1898
- metadata,
1899
- actions,
1900
- className,
1901
- children,
1902
- ...props
1903
- }) {
1904
- return /* @__PURE__ */ jsxs18(
1905
- "section",
1906
- {
1907
- "data-slot": "resource-summary",
1908
- className: cn(
1909
- "px-5 py-4",
1910
- variant === "plain" && "border-b border-border-subtle bg-canvas",
1911
- variant === "surface" && "rounded-[var(--ds-radius-surface)] border border-border-subtle bg-surface",
1912
- className
1913
- ),
1914
- ...props,
1915
- children: [
1916
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
1917
- /* @__PURE__ */ jsxs18("div", { className: "min-w-0", children: [
1918
- title || status ? /* @__PURE__ */ jsxs18("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
1919
- title ? /* @__PURE__ */ jsx20("h2", { className: "ds-type-section-title truncate", children: title }) : null,
1920
- status
1921
- ] }) : null,
1922
- description ? /* @__PURE__ */ jsx20("p", { className: "ds-type-ui mt-1 max-w-3xl text-text-supporting", children: description }) : null,
1923
- metadata ? /* @__PURE__ */ jsx20("div", { className: "ds-type-metadata mt-2 text-text-supporting", children: metadata }) : null
1924
- ] }),
1925
- actions ? /* @__PURE__ */ jsx20("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
1926
- ] }),
1927
- children ? /* @__PURE__ */ jsx20("div", { className: "mt-4", children }) : null
1928
- ]
1929
- }
1930
- );
1931
- }
1932
- function DetailSections({
1933
- className,
1934
- ...props
1935
- }) {
1936
- return /* @__PURE__ */ jsx20(
1937
- "div",
1938
- {
1939
- "data-slot": "detail-sections",
1940
- className: cn("flex flex-col gap-[var(--ds-space-section)]", className),
1941
- ...props
1942
- }
1943
- );
1944
- }
1945
- function DetailSection({
1946
- variant = "surface",
1947
- title,
1948
- description,
1949
- actions,
1950
- className,
1951
- children,
1952
- ...props
1953
- }) {
1954
- return /* @__PURE__ */ jsxs18(
1955
- "section",
1956
- {
1957
- "data-slot": "detail-section",
1958
- className: cn(
1959
- variant === "surface" && "rounded-[var(--ds-radius-surface)] border border-border-subtle bg-surface p-[var(--ds-surface-padding)]",
1960
- variant === "open" && "border-b border-border-subtle pb-[var(--ds-space-section)]",
1961
- className
1962
- ),
1963
- ...props,
1964
- children: [
1965
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [
1966
- /* @__PURE__ */ jsxs18("div", { className: "min-w-0", children: [
1967
- /* @__PURE__ */ jsx20("h2", { className: "ds-type-section-title", children: title }),
1968
- description ? /* @__PURE__ */ jsx20("p", { className: "ds-type-ui mt-1 max-w-3xl text-text-supporting", children: description }) : null
1969
- ] }),
1970
- actions ? /* @__PURE__ */ jsx20("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null
1971
- ] }),
1972
- children ? /* @__PURE__ */ jsx20("div", { className: "mt-4", children }) : null
1973
- ]
1974
- }
1975
- );
1976
- }
1977
- function KeyValueList({
1978
- className,
1979
- ...props
1980
- }) {
1981
- return /* @__PURE__ */ jsx20(
1982
- "dl",
1983
- {
1984
- "data-slot": "key-value-list",
1985
- className: cn("ds-type-ui grid gap-3", className),
1986
- ...props
1987
- }
1988
- );
1989
- }
1990
- function KeyValueItem({
1991
- label,
1992
- value,
1993
- breakValue = false
1994
- }) {
1995
- return /* @__PURE__ */ jsxs18("div", { "data-slot": "key-value-item", className: "flex justify-between gap-4", children: [
1996
- /* @__PURE__ */ jsx20("dt", { className: "text-text-supporting", children: label }),
1997
- /* @__PURE__ */ jsx20(
1998
- "dd",
1999
- {
2000
- className: cn(
2001
- "text-right font-medium",
2002
- breakValue && "break-all"
2003
- ),
2004
- children: value
2005
- }
2006
- )
2007
- ] });
2008
- }
2009
-
2010
- // src/patterns/sidebar-navigation.tsx
2011
- import * as React8 from "react";
2012
- import { ChevronRight as ChevronRight2 } from "lucide-react";
2013
- import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
2014
- function hasItems(entry) {
2015
- return "items" in entry;
2016
- }
2017
- function isStaticGroup(entry) {
2018
- return hasItems(entry) && entry.type === "group";
2019
- }
2020
- function isCollapsibleSection(entry) {
2021
- return hasItems(entry) && entry.type !== "group";
2022
- }
2023
- function getNavigationAccessibleLabel(item) {
2024
- const metadata = [item.badgeLabel, item.countLabel].filter(Boolean);
2025
- return metadata.length > 0 ? `${item.label}, ${metadata.join(", ")}` : item.label;
2026
- }
2027
- function NavigationMetadata({
2028
- badge,
2029
- count
2030
- }) {
2031
- if (badge === void 0 && count === void 0) {
2032
- return null;
2033
- }
2034
- return /* @__PURE__ */ jsxs19(
2035
- "span",
2036
- {
2037
- "aria-hidden": "true",
2038
- className: "ml-auto flex min-w-0 shrink-0 items-center gap-1.5 text-sidebar-metadata-text",
2039
- children: [
2040
- badge !== void 0 ? /* @__PURE__ */ jsx21("span", { className: "max-w-28 truncate rounded-full bg-sidebar-hover px-1.5 py-0.5 text-[length:var(--ds-metadata)] font-semibold leading-none", children: badge }) : null,
2041
- count !== void 0 ? /* @__PURE__ */ jsx21("span", { className: "ds-type-metadata tabular-nums", children: count }) : null
2042
- ]
2043
- }
2044
- );
2045
- }
2046
- function NavigationItemContent({ item }) {
2047
- return /* @__PURE__ */ jsxs19(Fragment5, { children: [
2048
- item.icon,
2049
- !item.icon && item.collapsedLabel ? /* @__PURE__ */ jsx21("span", { className: "hidden shrink-0 font-semibold group-data-[sidebar-state=collapsed]/shell:inline", children: item.collapsedLabel }) : null,
2050
- /* @__PURE__ */ jsx21("span", { className: "truncate group-data-[sidebar-state=collapsed]/shell:hidden", children: item.label }),
2051
- /* @__PURE__ */ jsx21(NavigationMetadata, { badge: item.badge, count: item.count })
2052
- ] });
2053
- }
2054
- function readOpenSections(storageKey) {
2055
- if (!storageKey || typeof window === "undefined") {
2056
- return {};
2057
- }
2058
- try {
2059
- const storedValue = window.localStorage.getItem(storageKey);
2060
- if (!storedValue) {
2061
- return {};
2062
- }
2063
- const parsedValue = JSON.parse(storedValue);
2064
- return typeof parsedValue === "object" && parsedValue !== null ? parsedValue : {};
2065
- } catch {
2066
- return {};
2067
- }
2068
- }
2069
- function SidebarNavigation({
2070
- entries,
2071
- renderLink,
2072
- onNavigate,
2073
- storageKey,
2074
- className
2075
- }) {
2076
- const { isMobile, setMobileOpen, sidebarSide, sidebarState } = useAppShell();
2077
- const [openSections, setOpenSections] = React8.useState({});
2078
- const storageReady = React8.useRef(false);
2079
- React8.useEffect(() => {
2080
- storageReady.current = false;
2081
- const storedSections = readOpenSections(storageKey);
2082
- queueMicrotask(() => {
2083
- storageReady.current = true;
2084
- setOpenSections(storedSections);
2085
- });
2086
- }, [storageKey]);
2087
- React8.useEffect(() => {
2088
- if (!storageReady.current || !storageKey || !entries.some(isCollapsibleSection)) {
2089
- return;
2090
- }
2091
- try {
2092
- window.localStorage.setItem(storageKey, JSON.stringify(openSections));
2093
- } catch {
2094
- }
2095
- }, [entries, openSections, storageKey]);
2096
- const handleNavigate = React8.useCallback(() => {
2097
- if (isMobile) {
2098
- setMobileOpen(false);
2099
- }
2100
- onNavigate?.();
2101
- }, [isMobile, onNavigate, setMobileOpen]);
2102
- return /* @__PURE__ */ jsx21(
2103
- "nav",
2104
- {
2105
- "data-slot": "sidebar-navigation",
2106
- "aria-label": "Primary navigation",
2107
- className: cn(
2108
- "flex flex-col gap-[var(--ds-sidebar-group-gap)]",
2109
- className
2110
- ),
2111
- children: entries.map((entry) => {
2112
- if (isStaticGroup(entry)) {
2113
- return /* @__PURE__ */ jsx21(NavigationGroup, { label: entry.label, count: entry.count, children: entry.items.map((item) => /* @__PURE__ */ jsx21(
2114
- NavigationItem,
2115
- {
2116
- active: item.active,
2117
- tooltip: item.label,
2118
- render: renderLink(item, {
2119
- "aria-current": item.active ? "page" : void 0,
2120
- "aria-label": getNavigationAccessibleLabel(item),
2121
- onClick: handleNavigate,
2122
- children: /* @__PURE__ */ jsx21(NavigationItemContent, { item })
2123
- })
2124
- },
2125
- item.id
2126
- )) }, entry.id);
2127
- }
2128
- if (!hasItems(entry)) {
2129
- return /* @__PURE__ */ jsx21(
2130
- NavigationGroup,
2131
- {
2132
- className: entry.startsSection ? "mt-[var(--ds-sidebar-group-gap)]" : void 0,
2133
- children: /* @__PURE__ */ jsx21(
2134
- NavigationItem,
2135
- {
2136
- active: entry.active,
2137
- tooltip: entry.label,
2138
- render: renderLink(entry, {
2139
- "aria-current": entry.active ? "page" : void 0,
2140
- "aria-label": getNavigationAccessibleLabel(entry),
2141
- onClick: handleNavigate,
2142
- children: /* @__PURE__ */ jsx21(NavigationItemContent, { item: entry })
2143
- })
2144
- }
2145
- )
2146
- },
2147
- entry.id
2148
- );
2149
- }
2150
- const activeChild = entry.items.some((item) => item.active);
2151
- const defaultOpen = entry.type === "submenu" ? entry.defaultOpen : false;
2152
- const legacyActive = entry.type === void 0 ? entry.active : false;
2153
- const sectionOpen = (openSections[entry.id] ?? defaultOpen) || activeChild || legacyActive;
2154
- if (sidebarState === "collapsed" && !isMobile) {
2155
- return /* @__PURE__ */ jsxs19(DropdownMenu, { children: [
2156
- /* @__PURE__ */ jsx21(
2157
- NavigationGroup,
2158
- {
2159
- className: entry.startsSection ? "mt-[var(--ds-sidebar-group-gap)]" : void 0,
2160
- children: /* @__PURE__ */ jsx21(
2161
- DropdownMenuTrigger,
2162
- {
2163
- render: /* @__PURE__ */ jsxs19(
2164
- NavigationItem,
2165
- {
2166
- "aria-label": `${getNavigationAccessibleLabel(entry)} menu`,
2167
- className: activeChild ? "text-sidebar-primary-text" : void 0,
2168
- children: [
2169
- entry.icon,
2170
- /* @__PURE__ */ jsx21("span", { className: "sr-only", children: entry.label })
2171
- ]
2172
- }
2173
- )
2174
- }
2175
- )
2176
- }
2177
- ),
2178
- /* @__PURE__ */ jsxs19(
2179
- DropdownMenuContent,
2180
- {
2181
- side: sidebarSide === "left" ? "right" : "left",
2182
- align: "start",
2183
- sideOffset: 8,
2184
- className: "min-w-56 rounded-[var(--ds-radius-surface)] p-1.5",
2185
- children: [
2186
- /* @__PURE__ */ jsx21(DropdownMenuLabel, { className: "px-2 py-1.5 font-semibold text-text-supporting", children: entry.label }),
2187
- /* @__PURE__ */ jsx21(DropdownMenuGroup, { children: entry.items.map((item) => /* @__PURE__ */ jsx21(
2188
- DropdownMenuLinkItem,
2189
- {
2190
- closeOnClick: true,
2191
- render: renderLink(item, {
2192
- "aria-current": item.active ? "page" : void 0,
2193
- "aria-label": getNavigationAccessibleLabel(item),
2194
- onClick: handleNavigate,
2195
- children: /* @__PURE__ */ jsxs19(Fragment5, { children: [
2196
- item.icon,
2197
- /* @__PURE__ */ jsx21("span", { className: "truncate", children: item.label }),
2198
- /* @__PURE__ */ jsx21(NavigationMetadata, { badge: item.badge, count: item.count })
2199
- ] })
2200
- }),
2201
- className: cn(
2202
- "min-h-9 cursor-pointer rounded-[var(--ds-radius-control)] [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-[1.75]",
2203
- item.active && "bg-selection-background font-semibold text-selection-foreground focus:bg-selection-background focus:text-selection-foreground"
2204
- )
2205
- },
2206
- item.id
2207
- )) })
2208
- ]
2209
- }
2210
- )
2211
- ] }, entry.id);
2212
- }
2213
- return /* @__PURE__ */ jsx21(
2214
- Collapsible,
2215
- {
2216
- open: sectionOpen,
2217
- onOpenChange: (open) => setOpenSections((current) => ({
2218
- ...current,
2219
- [entry.id]: open
2220
- })),
2221
- className: cn(
2222
- "group/collapsible",
2223
- entry.startsSection && "mt-2"
2224
- ),
2225
- children: /* @__PURE__ */ jsxs19(NavigationGroup, { children: [
2226
- /* @__PURE__ */ jsx21(
2227
- CollapsibleTrigger,
2228
- {
2229
- render: /* @__PURE__ */ jsxs19(
2230
- NavigationItem,
2231
- {
2232
- tooltip: entry.label,
2233
- "aria-label": getNavigationAccessibleLabel(entry),
2234
- className: activeChild ? "text-sidebar-primary-text" : void 0,
2235
- children: [
2236
- entry.icon,
2237
- /* @__PURE__ */ jsx21("span", { className: "truncate group-data-[sidebar-state=collapsed]/shell:hidden", children: entry.label }),
2238
- /* @__PURE__ */ jsx21(NavigationMetadata, { badge: entry.badge, count: entry.count }),
2239
- /* @__PURE__ */ jsx21(ChevronRight2, { className: "ml-auto transition-transform duration-150 ease-out group-data-[sidebar-state=collapsed]/shell:hidden group-data-[open]/collapsible:rotate-90" })
2240
- ]
2241
- }
2242
- )
2243
- }
2244
- ),
2245
- /* @__PURE__ */ jsx21(
2246
- CollapsibleContent,
2247
- {
2248
- "data-slot": "sidebar-collapsible-content",
2249
- className: "overflow-hidden",
2250
- children: /* @__PURE__ */ jsx21(NavigationSubList, { children: entry.items.map((item) => /* @__PURE__ */ jsx21(
2251
- NavigationSubItem,
2252
- {
2253
- active: item.active,
2254
- render: renderLink(item, {
2255
- "aria-current": item.active ? "page" : void 0,
2256
- "aria-label": getNavigationAccessibleLabel(item),
2257
- onClick: handleNavigate,
2258
- children: /* @__PURE__ */ jsxs19(Fragment5, { children: [
2259
- item.icon,
2260
- /* @__PURE__ */ jsx21("span", { className: "truncate", children: item.label }),
2261
- /* @__PURE__ */ jsx21(NavigationMetadata, { badge: item.badge, count: item.count })
2262
- ] })
2263
- })
2264
- },
2265
- item.id
2266
- )) })
2267
- }
2268
- )
2269
- ] })
2270
- },
2271
- entry.id
2272
- );
2273
- })
2274
- }
2275
- );
2276
- }
2277
-
2278
- // src/patterns/state-views.tsx
2279
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
2280
- function StateView({ title, description, action, icon, className, ...props }) {
2281
- return /* @__PURE__ */ jsxs20(
2282
- "div",
2283
- {
2284
- "data-slot": "state-view",
2285
- className: cn("flex min-h-72 flex-col items-center justify-center gap-3 border-b px-6 py-12 text-center", className),
2286
- ...props,
2287
- children: [
2288
- icon ? /* @__PURE__ */ jsx22("div", { className: "flex size-10 items-center justify-center rounded-md bg-neutral-background text-neutral-foreground [&_svg]:size-5", children: icon }) : null,
2289
- /* @__PURE__ */ jsx22("h2", { className: "ds-type-section-title", children: title }),
2290
- description ? /* @__PURE__ */ jsx22("p", { className: "ds-type-ui max-w-md text-text-supporting", children: description }) : null,
2291
- action ? /* @__PURE__ */ jsx22("div", { className: "mt-1", children: action }) : null
2292
- ]
2293
- }
2294
- );
2295
- }
2296
- function LoadingRows({
2297
- rows = 6,
2298
- columns = 5
2299
- }) {
2300
- return /* @__PURE__ */ jsx22("div", { "data-slot": "loading-rows", className: "border-b", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsx22(
2301
- "div",
2302
- {
2303
- className: "grid h-[var(--ds-row-height)] items-center gap-4 border-b px-5 last:border-b-0",
2304
- style: { gridTemplateColumns: `2fr repeat(${Math.max(columns - 1, 1)}, minmax(5rem, 1fr))` },
2305
- children: Array.from({ length: columns }).map((_2, columnIndex) => /* @__PURE__ */ jsx22(
2306
- "div",
2307
- {
2308
- className: cn(
2309
- "h-3 rounded bg-surface-muted",
2310
- columnIndex === 0 ? "w-44" : "w-24"
2311
- )
2312
- },
2313
- columnIndex
2314
- ))
2315
- },
2316
- index
2317
- )) });
2318
- }
2319
- function ErrorState({ title, description, action, className, ...props }) {
2320
- return /* @__PURE__ */ jsx22(
2321
- StateView,
2322
- {
2323
- title,
2324
- description,
2325
- action,
2326
- className: cn("bg-danger-background/60", className),
2327
- role: "alert",
2328
- "aria-live": "assertive",
2329
- ...props
2330
- }
2331
- );
2332
- }
2333
-
2334
- // src/patterns/value-meter.tsx
2335
- import * as React9 from "react";
2336
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
2337
- function ValueMeter({
2338
- label,
2339
- value,
2340
- maximum,
2341
- valueLabel,
2342
- detail,
2343
- tone = "neutral",
2344
- className,
2345
- ...props
2346
- }) {
2347
- const labelId = React9.useId();
2348
- const hasMaximum = typeof maximum === "number" && maximum > 0;
2349
- const boundedValue = hasMaximum ? Math.min(maximum, Math.max(0, value)) : value;
2350
- const percentage = hasMaximum ? boundedValue / maximum * 100 : null;
2351
- const resolvedValueLabel = valueLabel ?? (hasMaximum ? `${boundedValue} of ${maximum}` : String(boundedValue));
2352
- return /* @__PURE__ */ jsxs21(
2353
- "div",
2354
- {
2355
- "data-slot": "value-meter",
2356
- className: cn("grid gap-2", className),
2357
- ...props,
2358
- children: [
2359
- /* @__PURE__ */ jsxs21("div", { className: "flex items-baseline justify-between gap-4 text-sm", children: [
2360
- /* @__PURE__ */ jsx23("span", { id: labelId, className: "font-medium text-text-primary", children: label }),
2361
- /* @__PURE__ */ jsx23("span", { className: "text-text-supporting", children: resolvedValueLabel })
2362
- ] }),
2363
- percentage === null ? null : /* @__PURE__ */ jsx23(
2364
- "div",
2365
- {
2366
- role: "progressbar",
2367
- "aria-labelledby": labelId,
2368
- "aria-valuemin": 0,
2369
- "aria-valuemax": maximum ?? void 0,
2370
- "aria-valuenow": boundedValue,
2371
- className: "h-2 overflow-hidden rounded-full bg-surface-muted",
2372
- children: /* @__PURE__ */ jsx23(
2373
- "div",
2374
- {
2375
- className: cn(
2376
- "h-full rounded-full bg-neutral-foreground transition-[width]",
2377
- tone === "success" && "bg-success-foreground",
2378
- tone === "warning" && "bg-warning-foreground",
2379
- tone === "danger" && "bg-danger-foreground"
2380
- ),
2381
- style: { width: `${percentage}%` }
2382
- }
2383
- )
2384
- }
2385
- ),
2386
- detail ? /* @__PURE__ */ jsx23("div", { className: "text-xs text-text-supporting", children: detail }) : null
2387
- ]
2388
- }
2389
- );
2390
- }
2391
-
2392
- // src/patterns/workbench.tsx
2393
- import * as React10 from "react";
2394
- import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
2395
- function WorkbenchShell({ className, ...props }) {
2396
- return /* @__PURE__ */ jsx24("div", { "data-slot": "workbench-shell", className: cn("min-w-0", className), ...props });
2397
- }
2398
- function WorkbenchRail({ variant = "secondary", open = true, className, ...props }) {
2399
- return /* @__PURE__ */ jsx24(
2400
- "aside",
2401
- {
2402
- "data-slot": "workbench-rail",
2403
- "data-variant": variant,
2404
- "data-open": open ? "true" : "false",
2405
- className: cn("min-w-0", className),
2406
- ...props
2407
- }
2408
- );
2409
- }
2410
- function WorkbenchMain({ className, ...props }) {
2411
- return /* @__PURE__ */ jsx24("main", { "data-slot": "workbench-main", className: cn("min-w-0", className), ...props });
2412
- }
2413
- function WorkbenchInspector({ className, ...props }) {
2414
- return /* @__PURE__ */ jsx24("aside", { "data-slot": "workbench-inspector", className: cn("min-w-0", className), ...props });
2415
- }
2416
- function WorkbenchMobileToolbar({ className, ...props }) {
2417
- return /* @__PURE__ */ jsx24("div", { "data-slot": "workbench-mobile-toolbar", className: cn(className), ...props });
2418
- }
2419
- function WorkbenchBackdrop({ open = true, className, ...props }) {
2420
- return /* @__PURE__ */ jsx24(
2421
- "button",
2422
- {
2423
- type: "button",
2424
- "data-slot": "workbench-backdrop",
2425
- "data-open": open ? "true" : "false",
2426
- className: cn(className),
2427
- ...props
2428
- }
2429
- );
2430
- }
2431
- function WorkbenchSection({ className, ...props }) {
2432
- return /* @__PURE__ */ jsx24("section", { "data-slot": "workbench-section", className: cn(className), ...props });
2433
- }
2434
- function WorkbenchSectionHeader({ title, metadata, action, className, ...props }) {
2435
- return /* @__PURE__ */ jsxs22("div", { "data-slot": "workbench-section-header", className: cn(className), ...props, children: [
2436
- /* @__PURE__ */ jsxs22("div", { "data-slot": "workbench-section-heading", children: [
2437
- /* @__PURE__ */ jsx24("h2", { children: title }),
2438
- metadata ? /* @__PURE__ */ jsx24("span", { children: metadata }) : null
2439
- ] }),
2440
- action ? /* @__PURE__ */ jsx24("div", { "data-slot": "workbench-section-action", children: action }) : null
2441
- ] });
2442
- }
2443
- function ResourceRow({ as = "div", href, selected = false, className, children, ...props }) {
2444
- return React10.createElement(
2445
- as,
2446
- {
2447
- ...props,
2448
- ...as === "a" && href ? { href } : {},
2449
- ...as === "button" ? { type: "button" } : {},
2450
- "data-slot": "resource-row",
2451
- "data-selected": selected ? "true" : "false",
2452
- className: cn(className)
2453
- },
2454
- children
2455
- );
2456
- }
2457
- function ResourceRowIcon({ className, ...props }) {
2458
- return /* @__PURE__ */ jsx24("span", { "data-slot": "resource-row-icon", className: cn(className), ...props });
2459
- }
2460
- function ResourceRowContent({ className, ...props }) {
2461
- return /* @__PURE__ */ jsx24("span", { "data-slot": "resource-row-content", className: cn(className), ...props });
2462
- }
2463
- function ResourceRowTitle({ className, ...props }) {
2464
- return /* @__PURE__ */ jsx24("strong", { "data-slot": "resource-row-title", className: cn(className), ...props });
2465
- }
2466
- function ResourceRowDescription({ className, ...props }) {
2467
- return /* @__PURE__ */ jsx24("span", { "data-slot": "resource-row-description", className: cn(className), ...props });
2468
- }
2469
- function ResourceRowMeta({ className, ...props }) {
2470
- return /* @__PURE__ */ jsx24("span", { "data-slot": "resource-row-meta", className: cn(className), ...props });
2471
- }
2472
- function WorkbenchInspectorSection({ label, action, className, children, ...props }) {
2473
- return /* @__PURE__ */ jsxs22("section", { "data-slot": "workbench-inspector-section", className: cn(className), ...props, children: [
2474
- /* @__PURE__ */ jsxs22("div", { "data-slot": "workbench-inspector-label", children: [
2475
- /* @__PURE__ */ jsx24("h3", { children: label }),
2476
- action ? /* @__PURE__ */ jsx24("div", { children: action }) : null
2477
- ] }),
2478
- children
2479
- ] });
2480
- }
2481
- function IdentityRow({ initials, name, detail, compact = false, className, ...props }) {
2482
- return /* @__PURE__ */ jsxs22("div", { "data-slot": "identity-row", "data-compact": compact ? "true" : "false", className: cn(className), ...props, children: [
2483
- /* @__PURE__ */ jsx24("span", { "data-slot": "identity-avatar", children: initials }),
2484
- /* @__PURE__ */ jsxs22("span", { "data-slot": "identity-copy", children: [
2485
- /* @__PURE__ */ jsx24("strong", { children: name }),
2486
- detail ? /* @__PURE__ */ jsx24("small", { children: detail }) : null
2487
- ] })
2488
- ] });
2489
- }
2490
-
2491
- export {
2492
- PaginationControls,
2493
- DataTable,
2494
- EntityTable,
2495
- CommandPalette,
2496
- DataPanel,
2497
- DataPanelHeader,
2498
- DataPanelContent,
2499
- DataPanelFooter,
2500
- DetailBackLink,
2501
- FilterBar,
2502
- useAppShell,
2503
- AppShell,
2504
- AppSidebar,
2505
- AppSidebarHeader,
2506
- AppSidebarContent,
2507
- AppSidebarFooter,
2508
- ProductIdentity,
2509
- SidebarSeparator,
2510
- NavigationGroup,
2511
- NavigationItem,
2512
- NavigationSubItem,
2513
- NavigationSubList,
2514
- SidebarTrigger,
2515
- SidebarSearch,
2516
- MainRegion,
2517
- AppHeader,
2518
- AppHeaderStart,
2519
- AppHeaderSearch,
2520
- AppHeaderActions,
2521
- TopBar,
2522
- PageFrame,
2523
- PageContent,
2524
- PageBoundary,
2525
- InspectorRegion,
2526
- ActivityList,
2527
- ActivityItem,
2528
- AttentionList,
2529
- AttentionItem,
2530
- ConfirmationDialog,
2531
- CodeBlock,
2532
- InventorySurface,
2533
- InventoryDesktop,
2534
- InventoryMobile,
2535
- MetricBand,
2536
- MetricBandItem,
2537
- MetricTrend,
2538
- MetricCard,
2539
- PageHeader,
2540
- PageToolbar,
2541
- useConsciaPreferences,
2542
- DesignSystemPreferenceSync,
2543
- AppearanceControl,
2544
- DensityControl,
2545
- DesignPreferenceControls,
2546
- ProviderMark,
2547
- ResourceSummary,
2548
- DetailSections,
2549
- DetailSection,
2550
- KeyValueList,
2551
- KeyValueItem,
2552
- SidebarNavigation,
2553
- StateView,
2554
- LoadingRows,
2555
- ErrorState,
2556
- ValueMeter,
2557
- WorkbenchShell,
2558
- WorkbenchRail,
2559
- WorkbenchMain,
2560
- WorkbenchInspector,
2561
- WorkbenchMobileToolbar,
2562
- WorkbenchBackdrop,
2563
- WorkbenchSection,
2564
- WorkbenchSectionHeader,
2565
- ResourceRow,
2566
- ResourceRowIcon,
2567
- ResourceRowContent,
2568
- ResourceRowTitle,
2569
- ResourceRowDescription,
2570
- ResourceRowMeta,
2571
- WorkbenchInspectorSection,
2572
- IdentityRow
2573
- };
2574
- //# sourceMappingURL=chunk-OYJH5CVD.js.map