@mirror-physics/fractal-ui 0.2.0-next.4 → 0.2.0-next.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -32,37 +32,72 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  Alert: () => Alert,
34
34
  AlertDescription: () => AlertDescription,
35
+ AlertGhost: () => AlertGhost,
35
36
  AlertTitle: () => AlertTitle,
37
+ Breadcrumbs: () => Breadcrumbs,
36
38
  Button: () => Button,
39
+ ButtonGhost: () => ButtonGhost,
37
40
  Card: () => Card,
38
41
  CardContent: () => CardContent,
39
42
  CardDescription: () => CardDescription,
40
43
  CardFooter: () => CardFooter,
44
+ CardGhost: () => CardGhost,
41
45
  CardHeader: () => CardHeader,
42
46
  CardTitle: () => CardTitle,
47
+ Checkbox: () => Checkbox,
48
+ CheckboxGhost: () => CheckboxGhost,
43
49
  Chip: () => Chip,
50
+ ChipGhost: () => ChipGhost,
51
+ ContentSwitcher: () => ContentSwitcher,
52
+ ContentSwitcherGhost: () => ContentSwitcherGhost,
44
53
  DataTable: () => DataTable,
54
+ DataTableGhost: () => DataTableGhost,
45
55
  Disclosure: () => Disclosure,
56
+ DisclosureGhost: () => DisclosureGhost,
46
57
  Dropdown: () => Dropdown,
58
+ DropdownGhost: () => DropdownGhost,
47
59
  FeatureCard: () => FeatureCard,
60
+ FileDropzone: () => FileDropzone,
61
+ FileDropzoneGhost: () => FileDropzoneGhost,
48
62
  FolderCard: () => FolderCard,
63
+ Ghost: () => Ghost,
64
+ GhostLine: () => GhostLine,
49
65
  Input: () => Input,
66
+ InputGhost: () => InputGhost,
50
67
  Label: () => Label,
68
+ LabelGhost: () => LabelGhost,
69
+ LatticeLoader: () => LatticeLoader,
51
70
  Link: () => Link,
71
+ LinkGhost: () => LinkGhost,
52
72
  Modal: () => Modal,
53
- PageHeader: () => PageHeader,
73
+ ModalGhost: () => ModalGhost,
74
+ Pagination: () => Pagination,
75
+ PaginationGhost: () => PaginationGhost,
54
76
  PromptCard: () => PromptCard,
77
+ PromptCardGhost: () => PromptCardGhost,
55
78
  PromptGrid: () => PromptGrid,
79
+ SidePanel: () => SidePanel,
80
+ SidePanelGhost: () => SidePanelGhost,
56
81
  Sidebar: () => Sidebar,
82
+ SidebarAccountMenu: () => SidebarAccountMenu,
57
83
  SidebarBrand: () => SidebarBrand,
58
84
  SidebarFooter: () => SidebarFooter,
85
+ SidebarGhost: () => SidebarGhost,
59
86
  SidebarHeader: () => SidebarHeader,
60
87
  SidebarNav: () => SidebarNav,
61
88
  SidebarNavItem: () => SidebarNavItem,
62
89
  SidebarSection: () => SidebarSection,
63
90
  SortableTable: () => SortableTable,
91
+ SortableTableGhost: () => SortableTableGhost,
64
92
  Tabs: () => Tabs,
93
+ TabsGhost: () => TabsGhost,
94
+ TextButton: () => TextButton,
95
+ TextButtonGhost: () => TextButtonGhost,
96
+ Textarea: () => Textarea,
97
+ TextareaGhost: () => TextareaGhost,
65
98
  Toggle: () => Toggle,
99
+ ToggleGhost: () => ToggleGhost,
100
+ UILoader: () => UILoader,
66
101
  cn: () => cn,
67
102
  useEscapeDismiss: () => useEscapeDismiss
68
103
  });
@@ -120,7 +155,7 @@ var colorPalette = {
120
155
  var sizeConfig = {
121
156
  xs: { height: "28px", padding: "4px 8px", iconOnly: "28px", fontSize: "0.75rem" },
122
157
  sm: { height: "32px", padding: "6px 12px", iconOnly: "32px", fontSize: "0.75rem" },
123
- md: { height: "38px", padding: "8px 16px", iconOnly: "38px", fontSize: "0.875rem" },
158
+ md: { height: "40px", padding: "8px 16px", iconOnly: "40px", fontSize: "0.875rem" },
124
159
  lg: { height: "44px", padding: "10px 20px", iconOnly: "44px", fontSize: "1rem" },
125
160
  xl: { height: "56px", padding: "14px 28px", iconOnly: "56px", fontSize: "1rem" }
126
161
  };
@@ -235,44 +270,65 @@ var Button = React.forwardRef(
235
270
  );
236
271
  Button.displayName = "Button";
237
272
 
238
- // src/components/Card/Card.tsx
239
- var React2 = __toESM(require("react"), 1);
273
+ // src/components/Breadcrumbs/Breadcrumbs.tsx
240
274
  var import_fractal_icons = require("@mirror-physics/fractal-icons");
241
275
  var import_jsx_runtime2 = require("react/jsx-runtime");
276
+ function Breadcrumbs({
277
+ items,
278
+ ariaLabel = "Breadcrumbs",
279
+ separator = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_fractal_icons.ChevronRight, { "aria-hidden": "true", size: 14 }),
280
+ className,
281
+ ...props
282
+ }) {
283
+ if (items.length === 0) return null;
284
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("nav", { "aria-label": ariaLabel, className: cn("fractal-breadcrumbs", className), ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ol", { className: "fractal-breadcrumbs__list", children: items.map((item, index) => {
285
+ const isCurrent = index === items.length - 1;
286
+ const content = isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-current": "page", className: "fractal-breadcrumbs__current", children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { className: "fractal-breadcrumbs__link", href: item.href ?? "#", onClick: item.onClick, children: item.label });
287
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "fractal-breadcrumbs__item", children: [
288
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": "true", className: "fractal-breadcrumbs__separator", children: separator }),
289
+ content
290
+ ] }, index);
291
+ }) }) });
292
+ }
293
+
294
+ // src/components/Card/Card.tsx
295
+ var React2 = __toESM(require("react"), 1);
296
+ var import_fractal_icons2 = require("@mirror-physics/fractal-icons");
297
+ var import_jsx_runtime3 = require("react/jsx-runtime");
242
298
  var Card = React2.forwardRef(
243
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card", className), ...props })
299
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref, className: cn("fractal-card", className), ...props })
244
300
  );
245
301
  Card.displayName = "Card";
246
302
  var CardHeader = React2.forwardRef(
247
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card-header", className), ...props })
303
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref, className: cn("fractal-card-header", className), ...props })
248
304
  );
249
305
  CardHeader.displayName = "CardHeader";
250
306
  var CardTitle = React2.forwardRef(
251
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { ref, className: cn("fractal-card-title", className), ...props })
307
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { ref, className: cn("fractal-card-title", className), ...props })
252
308
  );
253
309
  CardTitle.displayName = "CardTitle";
254
310
  var CardDescription = React2.forwardRef(
255
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { ref, className: cn("fractal-card-description", className), ...props })
311
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { ref, className: cn("fractal-card-description", className), ...props })
256
312
  );
257
313
  CardDescription.displayName = "CardDescription";
258
314
  var CardContent = React2.forwardRef(
259
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card-content", className), ...props })
315
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref, className: cn("fractal-card-content", className), ...props })
260
316
  );
261
317
  CardContent.displayName = "CardContent";
262
318
  var CardFooter = React2.forwardRef(
263
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card-footer", className), ...props })
319
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref, className: cn("fractal-card-footer", className), ...props })
264
320
  );
265
321
  CardFooter.displayName = "CardFooter";
266
322
  var FeatureCard = React2.forwardRef(
267
- ({ icon, title, description, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { ref, className: cn("fractal-feature-card", className), ...props, children: [
268
- icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fractal-feature-card__icon", children: icon }),
269
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "fractal-feature-card__title", children: title }),
270
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "fractal-feature-card__description", children: description })
323
+ ({ icon, title, description, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref, className: cn("fractal-feature-card", className), ...props, children: [
324
+ icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fractal-feature-card__icon", children: icon }),
325
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: "fractal-feature-card__title", children: title }),
326
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "fractal-feature-card__description", children: description })
271
327
  ] })
272
328
  );
273
329
  FeatureCard.displayName = "FeatureCard";
274
330
  var FolderCard = React2.forwardRef(
275
- ({ name, sessionCount, selected, className, onClick, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
331
+ ({ name, sessionCount, selected, className, onClick, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
276
332
  "div",
277
333
  {
278
334
  ref,
@@ -288,11 +344,11 @@ var FolderCard = React2.forwardRef(
288
344
  className: cn("fractal-folder-card", selected && "fractal-folder-card--selected", className),
289
345
  ...props,
290
346
  children: [
291
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fractal-folder-card__header", children: [
292
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_fractal_icons.Folder, { size: 16, className: "fractal-folder-card__icon", "aria-hidden": true }),
293
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fractal-folder-card__name", children: name })
347
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fractal-folder-card__header", children: [
348
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_fractal_icons2.Folder, { size: 16, className: "fractal-folder-card__icon", "aria-hidden": true }),
349
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fractal-folder-card__name", children: name })
294
350
  ] }),
295
- sessionCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fractal-folder-card__footer", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "fractal-folder-card__sessions", children: [
351
+ sessionCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fractal-folder-card__footer", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "fractal-folder-card__sessions", children: [
296
352
  sessionCount,
297
353
  " ",
298
354
  sessionCount === 1 ? "session" : "sessions"
@@ -305,7 +361,7 @@ FolderCard.displayName = "FolderCard";
305
361
 
306
362
  // src/components/PromptCard/PromptCard.tsx
307
363
  var React3 = __toESM(require("react"), 1);
308
- var import_jsx_runtime3 = require("react/jsx-runtime");
364
+ var import_jsx_runtime4 = require("react/jsx-runtime");
309
365
  var titleToPrompt = (title) => typeof title === "string" || typeof title === "number" ? String(title) : "";
310
366
  var PromptCard = React3.forwardRef(
311
367
  ({
@@ -326,7 +382,7 @@ var PromptCard = React3.forwardRef(
326
382
  onPromptSelect?.(prompt ?? titleToPrompt(title));
327
383
  }
328
384
  };
329
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
385
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
330
386
  "button",
331
387
  {
332
388
  ref,
@@ -341,8 +397,8 @@ var PromptCard = React3.forwardRef(
341
397
  onClick: handleClick,
342
398
  ...props,
343
399
  children: [
344
- icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fractal-prompt-card__icon", "aria-hidden": "true", children: icon }),
345
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fractal-prompt-card__title", children: title })
400
+ icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "fractal-prompt-card__icon", "aria-hidden": "true", children: icon }),
401
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "fractal-prompt-card__title", children: title })
346
402
  ]
347
403
  }
348
404
  );
@@ -350,7 +406,7 @@ var PromptCard = React3.forwardRef(
350
406
  );
351
407
  PromptCard.displayName = "PromptCard";
352
408
  var PromptGrid = React3.forwardRef(
353
- ({ compact, padded, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
409
+ ({ compact, padded, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
354
410
  "div",
355
411
  {
356
412
  ref,
@@ -368,9 +424,9 @@ PromptGrid.displayName = "PromptGrid";
368
424
 
369
425
  // src/components/Input/Input.tsx
370
426
  var React4 = __toESM(require("react"), 1);
371
- var import_jsx_runtime4 = require("react/jsx-runtime");
427
+ var import_jsx_runtime5 = require("react/jsx-runtime");
372
428
  var Input = React4.forwardRef(
373
- ({ className, type, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
429
+ ({ className, type, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
374
430
  "input",
375
431
  {
376
432
  type,
@@ -384,9 +440,9 @@ Input.displayName = "Input";
384
440
 
385
441
  // src/components/Label/Label.tsx
386
442
  var React5 = __toESM(require("react"), 1);
387
- var import_jsx_runtime5 = require("react/jsx-runtime");
443
+ var import_jsx_runtime6 = require("react/jsx-runtime");
388
444
  var Label = React5.forwardRef(
389
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
445
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
390
446
  "label",
391
447
  {
392
448
  ref,
@@ -399,43 +455,47 @@ Label.displayName = "Label";
399
455
 
400
456
  // src/components/Alert/Alert.tsx
401
457
  var React6 = __toESM(require("react"), 1);
402
- var import_jsx_runtime6 = require("react/jsx-runtime");
458
+ var import_fractal_icons3 = require("@mirror-physics/fractal-icons");
459
+ var import_jsx_runtime7 = require("react/jsx-runtime");
403
460
  var defaultIcons = {
404
- default: "\u2139",
405
- info: "\u2139",
406
- success: "\u2713",
407
- warning: "\u26A0",
408
- error: "\u2715"
461
+ default: import_fractal_icons3.CircleInfo,
462
+ info: import_fractal_icons3.CircleInfo,
463
+ success: import_fractal_icons3.CircleCheck,
464
+ warning: import_fractal_icons3.Warning,
465
+ error: import_fractal_icons3.CircleClose
409
466
  };
410
467
  var Alert = React6.forwardRef(
411
- ({ className, variant = "default", icon, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
412
- "div",
413
- {
414
- ref,
415
- role: "alert",
416
- className: cn("fractal-alert", `fractal-alert--${variant}`, className),
417
- ...props,
418
- children: [
419
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "fractal-alert-icon", "aria-hidden": true, children: icon ?? defaultIcons[variant] }),
420
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "fractal-alert-content", children })
421
- ]
422
- }
423
- )
468
+ ({ className, variant = "default", icon, children, ...props }, ref) => {
469
+ const DefaultIcon = defaultIcons[variant];
470
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
471
+ "div",
472
+ {
473
+ ref,
474
+ role: "alert",
475
+ className: cn("fractal-alert", `fractal-alert--${variant}`, className),
476
+ ...props,
477
+ children: [
478
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fractal-alert-icon", "aria-hidden": true, children: icon ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DefaultIcon, { size: 18 }) }),
479
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fractal-alert-content", children })
480
+ ]
481
+ }
482
+ );
483
+ }
424
484
  );
425
485
  Alert.displayName = "Alert";
426
486
  var AlertTitle = React6.forwardRef(
427
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h5", { ref, className: cn("fractal-alert-title", className), ...props })
487
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h5", { ref, className: cn("fractal-alert-title", className), ...props })
428
488
  );
429
489
  AlertTitle.displayName = "AlertTitle";
430
490
  var AlertDescription = React6.forwardRef(
431
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref, className: cn("fractal-alert-description", className), ...props })
491
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref, className: cn("fractal-alert-description", className), ...props })
432
492
  );
433
493
  AlertDescription.displayName = "AlertDescription";
434
494
 
435
495
  // src/components/Toggle/Toggle.tsx
436
- var import_jsx_runtime7 = require("react/jsx-runtime");
496
+ var import_jsx_runtime8 = require("react/jsx-runtime");
437
497
  function Toggle({ checked, onChange, label, className }) {
438
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
498
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
439
499
  "button",
440
500
  {
441
501
  type: "button",
@@ -444,8 +504,8 @@ function Toggle({ checked, onChange, label, className }) {
444
504
  className: cn("fractal-toggle", className),
445
505
  onClick: () => onChange(!checked),
446
506
  children: [
447
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: cn("fractal-toggle-track", checked && "fractal-toggle-track--checked"), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: cn("fractal-toggle-thumb", checked && "fractal-toggle-thumb--checked") }) }),
448
- label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fractal-toggle-label", children: label })
507
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: cn("fractal-toggle-track", checked && "fractal-toggle-track--checked"), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: cn("fractal-toggle-thumb", checked && "fractal-toggle-thumb--checked") }) }),
508
+ label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "fractal-toggle-label", children: label })
449
509
  ]
450
510
  }
451
511
  );
@@ -504,27 +564,72 @@ function useEscapeDismiss(priority, handler, enabled = true) {
504
564
  }, [priority, enabled]);
505
565
  }
506
566
 
567
+ // src/components/UILoader/UILoader.tsx
568
+ var import_react2 = require("react");
569
+ var import_jsx_runtime9 = require("react/jsx-runtime");
570
+ var LEFT = "M0 53C0 51 1.6 49.5 3.6 49.5h16.5c1 0 1.9.4 2.5 1L42.1 69.6c.7.7 1.1 1.6 1.1 2.5v16.2c0 2-1.6 3.5-3.6 3.5H23.1c-1 0-1.9-.4-2.5-1L1.1 71.7C.4 71 0 70.1 0 69.2V53Z";
571
+ var CENTER = "M0 3.5C0 1.6 1.6 0 3.6 0h16.5c1 0 1.9.4 2.5 1L92.5 69.6c.7.7 1 1.6 1 2.5v16.2c0 2-1.6 3.5-3.6 3.5H73.4c-1 0-1.9-.4-2.5-1L1.1 22.2C.4 21.6 0 20.7 0 19.7V3.5Z";
572
+ var RIGHT = "M50.4 3.5C50.4 1.6 52 0 54 0h16.5c1 0 1.9.4 2.5 1l69.8 68.6c.7.7 1.1 1.6 1.1 2.5v16.2c0 2-1.6 3.5-3.6 3.5h-16.5c-1 0-1.9-.4-2.5-1L51.4 22.2c-.7-.6-1-1.5-1-2.5V3.5Z";
573
+ function UILoader({ size = 48, tone = "neutral", className, style, label = "Loading", ariaHidden = false }) {
574
+ const rawId = (0, import_react2.useId)().replace(/[^a-zA-Z0-9_-]/g, "");
575
+ const clipId = `fractal-ui-loader-clip-${rawId}`;
576
+ const gradientId = `fractal-ui-loader-gradient-${rawId}`;
577
+ const height = typeof size === "number" ? `${size}px` : size;
578
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
579
+ "span",
580
+ {
581
+ "aria-hidden": ariaHidden || void 0,
582
+ "aria-label": ariaHidden ? void 0 : label,
583
+ className: cn("fractal-ui-loader", `fractal-ui-loader--${tone}`, className),
584
+ role: ariaHidden ? void 0 : "status",
585
+ style,
586
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 144 92", style: { height, width: "auto" }, children: [
587
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("defs", { children: [
588
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("linearGradient", { id: gradientId, x1: "59", x2: "94.3", y1: "0", y2: "89.1", gradientUnits: "userSpaceOnUse", children: [
589
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("stop", { className: "fractal-ui-loader__stop-start", offset: "0" }),
590
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("stop", { className: "fractal-ui-loader__stop-end", offset: "1" })
591
+ ] }),
592
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("linearGradient", { id: `${gradientId}-shine`, x1: "0", x2: "1", y1: "0", y2: "0", children: [
593
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("stop", { offset: "0.4", stopColor: "white", stopOpacity: "0" }),
594
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("stop", { offset: "0.5", stopColor: "white", stopOpacity: "0.62" }),
595
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("stop", { offset: "0.6", stopColor: "white", stopOpacity: "0" })
596
+ ] }),
597
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("clipPath", { id: clipId, children: [
598
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: LEFT }),
599
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: CENTER }),
600
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: RIGHT })
601
+ ] })
602
+ ] }),
603
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: CENTER, fill: `url(#${gradientId})` }),
604
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: RIGHT, fill: `url(#${gradientId})` }),
605
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: LEFT, fill: `url(#${gradientId})` }),
606
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("g", { clipPath: `url(#${clipId})`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("g", { className: "fractal-ui-loader__shine-axis", transform: "translate(72 46) rotate(68.4)", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("rect", { className: "fractal-ui-loader__shine", x: "-160", y: "-100", width: "320", height: "200", fill: `url(#${gradientId}-shine)` }) }) })
607
+ ] })
608
+ }
609
+ );
610
+ }
611
+
507
612
  // src/components/Modal/Modal.tsx
508
- var import_jsx_runtime8 = require("react/jsx-runtime");
509
- var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
510
- function Modal({ open, onClose, title, children, danger, warn, footer, noClose, size = "sm", className }) {
511
- useEscapeDismiss(80, onClose, open && !noClose);
613
+ var import_jsx_runtime10 = require("react/jsx-runtime");
614
+ var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
615
+ function Modal({ open, onClose, title, children, danger, warn, footer, noClose, closeDisabled = false, size = "sm", loading = false, loadingLabel = "Loading", className }) {
616
+ useEscapeDismiss(80, onClose, open && !noClose && !closeDisabled);
512
617
  if (!open) return null;
513
618
  const sizeClass = `fractal-modal-panel--${size}`;
514
619
  const accentClass = danger ? "fractal-modal-panel--danger" : warn ? "fractal-modal-panel--warn" : "";
515
620
  return (0, import_react_dom.createPortal)(
516
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fractal-modal-overlay", onClick: noClose ? void 0 : onClose, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
621
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-modal-overlay", onClick: noClose || closeDisabled ? void 0 : onClose, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
517
622
  "div",
518
623
  {
519
624
  className: cn("fractal-modal-panel", sizeClass, accentClass, className),
520
625
  onClick: (e) => e.stopPropagation(),
521
626
  children: [
522
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "fractal-modal-title-row", children: [
523
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: cn("fractal-modal-title", danger && "fractal-modal-title--danger", warn && "fractal-modal-title--warn"), children: title }),
524
- !noClose && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: onClose, title: "Close", className: "fractal-modal-close", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {}) })
627
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "fractal-modal-title-row", children: [
628
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: cn("fractal-modal-title", danger && "fractal-modal-title--danger", warn && "fractal-modal-title--warn"), children: title }),
629
+ !noClose && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: onClose, title: "Close", disabled: closeDisabled, className: "fractal-modal-close", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CloseIcon, {}) })
525
630
  ] }),
526
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn("fractal-modal-body", size === "lg" && "fractal-modal-body--lg"), children }),
527
- footer && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fractal-modal-footer", children: footer })
631
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "aria-busy": loading || void 0, className: cn("fractal-modal-body", size === "lg" && "fractal-modal-body--lg", loading && "fractal-modal-body--loading"), children: loading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(UILoader, { label: loadingLabel }) : children }),
632
+ footer && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-modal-footer", children: footer })
528
633
  ]
529
634
  }
530
635
  ) }),
@@ -533,17 +638,17 @@ function Modal({ open, onClose, title, children, danger, warn, footer, noClose,
533
638
  }
534
639
 
535
640
  // src/components/DataTable/DataTable.tsx
536
- var import_jsx_runtime9 = require("react/jsx-runtime");
641
+ var import_jsx_runtime11 = require("react/jsx-runtime");
537
642
  function DataTable({ columns, data, emptyMessage, header, size = "md", className }) {
538
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: cn("fractal-datatable", `fractal-datatable--${size}`, className), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "fractal-datatable-surface", children: [
539
- header && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fractal-datatable-header", children: header }),
540
- data.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fractal-datatable-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "fractal-datatable-table", children: [
541
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { className: "fractal-datatable-thead-row", children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "fractal-datatable-th", style: { width: col.width }, children: col.header }, col.key)) }) }),
542
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
643
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: cn("fractal-datatable", `fractal-datatable--${size}`, className), children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "fractal-datatable-surface", children: [
644
+ header && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "fractal-datatable-header", children: header }),
645
+ data.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "fractal-datatable-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { className: "fractal-datatable-table", children: [
646
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { className: "fractal-datatable-thead-row", children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { className: "fractal-datatable-th", style: { width: col.width }, children: col.header }, col.key)) }) }),
647
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
543
648
  "tr",
544
649
  {
545
650
  className: "fractal-datatable-row",
546
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "fractal-datatable-td", style: { width: col.width }, children: col.render(row, rowIndex) }, col.key))
651
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "fractal-datatable-td", style: { width: col.width }, children: col.render(row, rowIndex) }, col.key))
547
652
  },
548
653
  rowIndex
549
654
  )) })
@@ -553,8 +658,8 @@ function DataTable({ columns, data, emptyMessage, header, size = "md", className
553
658
 
554
659
  // src/components/Dropdown/Dropdown.tsx
555
660
  var React7 = __toESM(require("react"), 1);
556
- var import_fractal_icons2 = require("@mirror-physics/fractal-icons");
557
- var import_jsx_runtime10 = require("react/jsx-runtime");
661
+ var import_fractal_icons4 = require("@mirror-physics/fractal-icons");
662
+ var import_jsx_runtime12 = require("react/jsx-runtime");
558
663
  var MARGIN = 4;
559
664
  function Dropdown({
560
665
  items,
@@ -565,13 +670,15 @@ function Dropdown({
565
670
  align = "left",
566
671
  triggerContent,
567
672
  label,
673
+ iconOnly = false,
568
674
  noChevron = false,
569
675
  size = "md",
570
676
  triggerVariant = "outline",
571
677
  className,
572
678
  triggerClassName,
573
679
  panelClassName,
574
- closeOnSelect = true
680
+ closeOnSelect = true,
681
+ disabled = false
575
682
  }) {
576
683
  const [open, setOpen] = React7.useState(false);
577
684
  const triggerRef = React7.useRef(null);
@@ -584,7 +691,7 @@ function Dropdown({
584
691
  const selectableItems = visibleItems.filter((i) => i.kind !== "header");
585
692
  const selected = items.find((i) => i.value === selectedValue && i.kind !== "header") ?? selectableItems[0] ?? visibleItems[0];
586
693
  const isUp = direction === "up";
587
- const ChevronIcon = isUp ? import_fractal_icons2.ChevronUp : import_fractal_icons2.ChevronDown;
694
+ const ChevronIcon = isUp ? import_fractal_icons4.ChevronUp : import_fractal_icons4.ChevronDown;
588
695
  React7.useLayoutEffect(() => {
589
696
  if (!open || !triggerRef.current || !panelRef.current) return;
590
697
  const triggerRect = triggerRef.current.getBoundingClientRect();
@@ -629,12 +736,13 @@ function Dropdown({
629
736
  document.addEventListener("mousedown", handleClickOutside);
630
737
  return () => document.removeEventListener("mousedown", handleClickOutside);
631
738
  }, [open]);
632
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: cn("fractal-dropdown", className), children: [
633
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
739
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("fractal-dropdown", className), children: [
740
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
634
741
  "button",
635
742
  {
636
743
  ref: triggerRef,
637
744
  type: "button",
745
+ disabled,
638
746
  "aria-haspopup": "listbox",
639
747
  "aria-expanded": open,
640
748
  "aria-label": triggerLabel,
@@ -643,18 +751,19 @@ function Dropdown({
643
751
  "fractal-dropdown-trigger",
644
752
  `fractal-dropdown-trigger--${size}`,
645
753
  `fractal-dropdown-trigger--${triggerVariant}`,
754
+ iconOnly && "fractal-dropdown-trigger--icon-only",
646
755
  triggerClassName
647
756
  ),
648
757
  children: [
649
- triggerContent != null ? triggerContent : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
650
- selected.icon != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected.icon }),
651
- selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-selected-text", children: selected.description })
758
+ triggerContent != null ? triggerContent : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
759
+ selected.icon != null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected.icon }),
760
+ selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "fractal-dropdown-selected-text", children: selected.description })
652
761
  ] }),
653
- !noChevron && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-chevron", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChevronIcon, { size: size === "sm" ? 14 : 16 }) })
762
+ !noChevron && !iconOnly && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "fractal-dropdown-chevron", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronIcon, { size: size === "sm" ? 14 : 16 }) })
654
763
  ]
655
764
  }
656
765
  ),
657
- open && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
766
+ open && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
658
767
  "div",
659
768
  {
660
769
  ref: panelRef,
@@ -663,21 +772,21 @@ function Dropdown({
663
772
  className: cn("fractal-dropdown-panel", `fractal-dropdown-panel--${size}`, panelClassName),
664
773
  style: panelStyle,
665
774
  children: [
666
- label != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-dropdown-label", children: label }),
775
+ label != null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fractal-dropdown-label", children: label }),
667
776
  visibleItems.map((item, index) => {
668
- const topDivider = item.border === "top" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
669
- const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
777
+ const topDivider = item.border === "top" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
778
+ const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
670
779
  if (item.kind === "header") {
671
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(React7.Fragment, { children: [
780
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(React7.Fragment, { children: [
672
781
  topDivider,
673
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
782
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
674
783
  bottomDivider
675
784
  ] }, `header-${index}`);
676
785
  }
677
786
  const isSelected = item.value === selectedValue;
678
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(React7.Fragment, { children: [
787
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(React7.Fragment, { children: [
679
788
  topDivider,
680
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
789
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
681
790
  "button",
682
791
  {
683
792
  type: "button",
@@ -689,9 +798,9 @@ function Dropdown({
689
798
  },
690
799
  className: "fractal-dropdown-option",
691
800
  children: [
692
- item.icon != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-icon", children: item.icon }),
693
- item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-option-text", children: item.description }),
694
- item.trailing != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-trailing", children: item.trailing })
801
+ item.icon != null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "fractal-dropdown-icon", children: item.icon }),
802
+ item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "fractal-dropdown-option-text", children: item.description }),
803
+ item.trailing != null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "fractal-dropdown-trailing", children: item.trailing })
695
804
  ]
696
805
  }
697
806
  ),
@@ -706,9 +815,9 @@ function Dropdown({
706
815
 
707
816
  // src/components/Link/Link.tsx
708
817
  var React8 = __toESM(require("react"), 1);
709
- var import_jsx_runtime11 = require("react/jsx-runtime");
818
+ var import_jsx_runtime13 = require("react/jsx-runtime");
710
819
  var Link = React8.forwardRef(
711
- ({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
820
+ ({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
712
821
  "a",
713
822
  {
714
823
  ref,
@@ -721,9 +830,9 @@ Link.displayName = "Link";
721
830
 
722
831
  // src/components/Chip/Chip.tsx
723
832
  var React9 = __toESM(require("react"), 1);
724
- var import_jsx_runtime12 = require("react/jsx-runtime");
833
+ var import_jsx_runtime14 = require("react/jsx-runtime");
725
834
  var Chip = React9.forwardRef(
726
- ({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
835
+ ({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
727
836
  "span",
728
837
  {
729
838
  ref,
@@ -734,35 +843,69 @@ var Chip = React9.forwardRef(
734
843
  );
735
844
  Chip.displayName = "Chip";
736
845
 
846
+ // src/components/Checkbox/Checkbox.tsx
847
+ var import_fractal_icons5 = require("@mirror-physics/fractal-icons");
848
+ var import_jsx_runtime15 = require("react/jsx-runtime");
849
+ function Checkbox({ checked, onCheckedChange, className, disabled, onClick, onKeyDown, ...props }) {
850
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
851
+ "button",
852
+ {
853
+ ...props,
854
+ className: cn("fractal-checkbox", checked && "fractal-checkbox--checked", className),
855
+ type: "button",
856
+ role: "checkbox",
857
+ "aria-checked": checked,
858
+ disabled,
859
+ onClick: (event) => {
860
+ onClick?.(event);
861
+ if (!event.defaultPrevented) onCheckedChange(!checked);
862
+ },
863
+ onKeyDown: (event) => {
864
+ onKeyDown?.(event);
865
+ if (event.key === " " || event.key === "Enter") event.stopPropagation();
866
+ },
867
+ children: checked ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_fractal_icons5.CheckboxChecked, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_fractal_icons5.Checkbox, { "aria-hidden": "true", size: 18 })
868
+ }
869
+ );
870
+ }
871
+
737
872
  // src/components/SortableTable/SortableTable.tsx
738
- var import_react2 = require("react");
739
- var import_fractal_icons3 = require("@mirror-physics/fractal-icons");
740
- var import_jsx_runtime13 = require("react/jsx-runtime");
873
+ var import_react3 = require("react");
874
+ var import_fractal_icons6 = require("@mirror-physics/fractal-icons");
875
+ var import_jsx_runtime16 = require("react/jsx-runtime");
741
876
  function SortableTable({
742
877
  columns,
743
878
  data,
744
879
  emptyMessage,
745
880
  header,
746
881
  size = "md",
882
+ embedded = false,
747
883
  className,
884
+ defaultSort,
748
885
  defaultSortKey = void 0,
749
886
  defaultSortDirection = null,
750
887
  sortKey: controlledKey,
751
888
  sortDirection: controlledDirection,
752
889
  onSortChange,
753
- highlightRow
890
+ highlightRow,
891
+ onRowClick,
892
+ rowAction
754
893
  }) {
755
- const [internalKey, setInternalKey] = (0, import_react2.useState)(defaultSortKey ?? null);
756
- const [internalDirection, setInternalDirection] = (0, import_react2.useState)(defaultSortDirection);
894
+ const [internalKey, setInternalKey] = (0, import_react3.useState)(defaultSortKey ?? null);
895
+ const [internalDirection, setInternalDirection] = (0, import_react3.useState)(defaultSortDirection);
757
896
  const isControlled = controlledKey !== void 0 && controlledDirection !== void 0;
758
897
  const activeKey = isControlled ? controlledKey : internalKey;
759
898
  const activeDirection = isControlled ? controlledDirection : internalDirection;
760
- const sorted = (0, import_react2.useMemo)(() => {
761
- if (!activeKey || !activeDirection) return data;
762
- const col = columns.find((c) => c.key === activeKey);
899
+ const baselineKey = defaultSort?.key ?? null;
900
+ const baselineDirection = defaultSort?.direction ?? null;
901
+ const effectiveKey = activeKey && activeDirection ? activeKey : baselineKey;
902
+ const effectiveDirection = activeKey && activeDirection ? activeDirection : baselineDirection;
903
+ const sorted = (0, import_react3.useMemo)(() => {
904
+ if (!effectiveKey || !effectiveDirection) return data;
905
+ const col = columns.find((c) => c.key === effectiveKey);
763
906
  if (!col) return data;
764
907
  const accessor = col.sortAccessor ?? ((row) => {
765
- const value = row[activeKey];
908
+ const value = row[effectiveKey];
766
909
  return typeof value === "string" || typeof value === "number" ? value : null;
767
910
  });
768
911
  const copy = [...data];
@@ -773,26 +916,28 @@ function SortableTable({
773
916
  if (av == null) return 1;
774
917
  if (bv == null) return -1;
775
918
  if (typeof av === "number" && typeof bv === "number") {
776
- return activeDirection === "asc" ? av - bv : bv - av;
919
+ return effectiveDirection === "asc" ? av - bv : bv - av;
777
920
  }
778
921
  const as = String(av).toLowerCase();
779
922
  const bs = String(bv).toLowerCase();
780
- if (as < bs) return activeDirection === "asc" ? -1 : 1;
781
- if (as > bs) return activeDirection === "asc" ? 1 : -1;
923
+ if (as < bs) return effectiveDirection === "asc" ? -1 : 1;
924
+ if (as > bs) return effectiveDirection === "asc" ? 1 : -1;
782
925
  return 0;
783
926
  });
784
927
  return copy;
785
- }, [data, columns, activeKey, activeDirection]);
928
+ }, [data, columns, effectiveKey, effectiveDirection]);
786
929
  const handleSortClick = (key) => {
787
930
  let nextDirection;
788
- if (activeKey !== key) {
931
+ if (!activeKey || !activeDirection) {
932
+ nextDirection = baselineKey === key && baselineDirection ? baselineDirection : "asc";
933
+ } else if (activeKey !== key) {
789
934
  nextDirection = "asc";
935
+ } else if (baselineKey === key && baselineDirection) {
936
+ nextDirection = activeDirection === baselineDirection ? baselineDirection === "asc" ? "desc" : "asc" : null;
790
937
  } else if (activeDirection === "asc") {
791
938
  nextDirection = "desc";
792
- } else if (activeDirection === "desc") {
793
- nextDirection = null;
794
939
  } else {
795
- nextDirection = "asc";
940
+ nextDirection = null;
796
941
  }
797
942
  const nextKey = nextDirection === null ? null : key;
798
943
  if (isControlled) {
@@ -803,13 +948,13 @@ function SortableTable({
803
948
  onSortChange?.(nextKey, nextDirection);
804
949
  }
805
950
  };
806
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("fractal-sortable-table", `fractal-sortable-table--${size}`, className), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "fractal-sortable-table-surface", children: [
807
- header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fractal-sortable-table-header", children: header }),
808
- sorted.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("table", { className: "fractal-sortable-table-table", children: [
809
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { className: "fractal-sortable-table-thead-row", children: columns.map((col) => {
951
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cn("fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "fractal-sortable-table-surface", children: [
952
+ header && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "fractal-sortable-table-header", children: header }),
953
+ sorted.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("table", { className: "fractal-sortable-table-table", children: [
954
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("tr", { className: "fractal-sortable-table-thead-row", children: columns.map((col) => {
810
955
  const isActive = activeKey === col.key && activeDirection !== null;
811
956
  if (!col.sortable) {
812
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
957
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
813
958
  "th",
814
959
  {
815
960
  className: "fractal-sortable-table-th",
@@ -819,12 +964,12 @@ function SortableTable({
819
964
  col.key
820
965
  );
821
966
  }
822
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
967
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
823
968
  "th",
824
969
  {
825
970
  className: "fractal-sortable-table-th fractal-sortable-table-th--sortable",
826
971
  style: { width: col.width },
827
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
972
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
828
973
  "button",
829
974
  {
830
975
  type: "button",
@@ -835,8 +980,8 @@ function SortableTable({
835
980
  onClick: () => handleSortClick(col.key),
836
981
  "aria-sort": isActive ? activeDirection === "asc" ? "ascending" : "descending" : "none",
837
982
  children: [
838
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: col.header }),
839
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.ArrowDown, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_fractal_icons3.ArrowsUpDown, { size: 14 }) })
983
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: col.header }),
984
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_fractal_icons6.ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_fractal_icons6.ArrowDown, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_fractal_icons6.ArrowsUpDown, { size: 14 }) })
840
985
  ]
841
986
  }
842
987
  )
@@ -844,21 +989,42 @@ function SortableTable({
844
989
  col.key
845
990
  );
846
991
  }) }) }),
847
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: sorted.map((row, rowIndex) => {
992
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("tbody", { children: sorted.map((row, rowIndex) => {
848
993
  const highlighted = highlightRow?.(row, rowIndex) ?? false;
849
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
994
+ const action = rowAction ? {
995
+ label: rowAction.label(row, rowIndex),
996
+ icon: rowAction.icon(row, rowIndex)
997
+ } : null;
998
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
850
999
  "tr",
851
1000
  {
852
1001
  className: cn(
853
1002
  "fractal-sortable-table-row",
854
- highlighted && "fractal-sortable-table-row--highlighted"
1003
+ highlighted && "fractal-sortable-table-row--highlighted",
1004
+ onRowClick && "fractal-sortable-table-row--interactive"
855
1005
  ),
856
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1006
+ onClick: onRowClick ? () => onRowClick(row, rowIndex) : void 0,
1007
+ onKeyDown: onRowClick ? (event) => {
1008
+ if (event.key === "Enter" || event.key === " ") {
1009
+ event.preventDefault();
1010
+ onRowClick(row, rowIndex);
1011
+ }
1012
+ } : void 0,
1013
+ "aria-label": action?.label,
1014
+ role: onRowClick ? "button" : void 0,
1015
+ tabIndex: onRowClick ? 0 : void 0,
1016
+ children: columns.map((col, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
857
1017
  "td",
858
1018
  {
859
- className: "fractal-sortable-table-td",
1019
+ className: cn(
1020
+ "fractal-sortable-table-td",
1021
+ action && columnIndex === columns.length - 1 && "fractal-sortable-table-td--row-action"
1022
+ ),
860
1023
  style: { width: col.width, textAlign: col.align ?? "left" },
861
- children: col.render(row, rowIndex)
1024
+ children: [
1025
+ col.render(row, rowIndex),
1026
+ action && columnIndex === columns.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sortable-table-row-action", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sortable-table-row-action__icon", children: action.icon }) })
1027
+ ]
862
1028
  },
863
1029
  col.key
864
1030
  ))
@@ -871,23 +1037,40 @@ function SortableTable({
871
1037
  }
872
1038
 
873
1039
  // src/components/Tabs/Tabs.tsx
874
- var import_react3 = require("react");
875
- var import_jsx_runtime14 = require("react/jsx-runtime");
1040
+ var import_react4 = require("react");
1041
+ var import_jsx_runtime17 = require("react/jsx-runtime");
876
1042
  function Tabs({
877
1043
  items,
878
1044
  defaultValue,
879
1045
  value: controlledValue,
880
1046
  onValueChange,
881
1047
  className,
882
- ariaLabel
1048
+ ariaLabel,
1049
+ divider = false,
1050
+ variant = "line"
883
1051
  }) {
884
- const reactId = (0, import_react3.useId)();
885
- const [internalValue, setInternalValue] = (0, import_react3.useState)(
1052
+ const reactId = (0, import_react4.useId)();
1053
+ const [internalValue, setInternalValue] = (0, import_react4.useState)(
886
1054
  defaultValue ?? items.find((i) => !i.disabled)?.id ?? items[0]?.id ?? ""
887
1055
  );
888
1056
  const isControlled = controlledValue !== void 0;
889
1057
  const activeId = isControlled ? controlledValue : internalValue;
890
- const tabRefs = (0, import_react3.useRef)({});
1058
+ const tabListRef = (0, import_react4.useRef)(null);
1059
+ const tabRefs = (0, import_react4.useRef)({});
1060
+ const [indicator, setIndicator] = (0, import_react4.useState)(null);
1061
+ (0, import_react4.useLayoutEffect)(() => {
1062
+ const updateIndicator = () => {
1063
+ const activeTab = tabRefs.current[activeId];
1064
+ if (!activeTab) return;
1065
+ setIndicator({ offset: activeTab.offsetLeft, width: activeTab.offsetWidth });
1066
+ };
1067
+ updateIndicator();
1068
+ const list = tabListRef.current;
1069
+ if (!list || typeof ResizeObserver === "undefined") return;
1070
+ const observer = new ResizeObserver(updateIndicator);
1071
+ observer.observe(list);
1072
+ return () => observer.disconnect();
1073
+ }, [activeId, items.length]);
891
1074
  const selectTab = (id) => {
892
1075
  if (isControlled) {
893
1076
  onValueChange?.(id);
@@ -897,6 +1080,10 @@ function Tabs({
897
1080
  }
898
1081
  };
899
1082
  const focusable = items.filter((i) => !i.disabled);
1083
+ const indicatorStyle = indicator ? {
1084
+ "--fractal-tabs-indicator-offset": `${indicator.offset}px`,
1085
+ "--fractal-tabs-indicator-width": `${indicator.width}px`
1086
+ } : void 0;
900
1087
  const onKeyDown = (event) => {
901
1088
  const currentIndex = focusable.findIndex((i) => i.id === activeId);
902
1089
  if (currentIndex === -1) return;
@@ -922,41 +1109,52 @@ function Tabs({
922
1109
  selectTab(nextId2);
923
1110
  requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
924
1111
  };
925
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("fractal-tabs", className), children: [
926
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "tablist", "aria-label": ariaLabel, className: "fractal-tabs-list", children: items.map((item) => {
927
- const isActive = item.id === activeId;
928
- const tabId = `${reactId}-tab-${item.id}`;
929
- const panelId = `${reactId}-panel-${item.id}`;
930
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
931
- "button",
932
- {
933
- ref: (el) => {
934
- tabRefs.current[item.id] = el;
935
- },
936
- id: tabId,
937
- role: "tab",
938
- type: "button",
939
- "aria-selected": isActive,
940
- "aria-controls": panelId,
941
- tabIndex: isActive ? 0 : -1,
942
- disabled: item.disabled,
943
- className: cn(
944
- "fractal-tabs-trigger",
945
- isActive && "fractal-tabs-trigger--active",
946
- item.disabled && "fractal-tabs-trigger--disabled"
947
- ),
948
- onClick: () => !item.disabled && selectTab(item.id),
949
- onKeyDown,
950
- children: item.label
951
- },
952
- item.id
953
- );
954
- }) }),
1112
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cn("fractal-tabs", `fractal-tabs--${variant}`, divider && "fractal-tabs--divider", className), children: [
1113
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1114
+ "div",
1115
+ {
1116
+ ref: tabListRef,
1117
+ role: "tablist",
1118
+ "aria-label": ariaLabel,
1119
+ className: "fractal-tabs-list",
1120
+ "data-indicator-ready": indicator ? "true" : void 0,
1121
+ style: indicatorStyle,
1122
+ children: items.map((item) => {
1123
+ const isActive = item.id === activeId;
1124
+ const tabId = `${reactId}-tab-${item.id}`;
1125
+ const panelId = `${reactId}-panel-${item.id}`;
1126
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1127
+ "button",
1128
+ {
1129
+ ref: (el) => {
1130
+ tabRefs.current[item.id] = el;
1131
+ },
1132
+ id: tabId,
1133
+ role: "tab",
1134
+ type: "button",
1135
+ "aria-selected": isActive,
1136
+ "aria-controls": panelId,
1137
+ tabIndex: isActive ? 0 : -1,
1138
+ disabled: item.disabled,
1139
+ className: cn(
1140
+ "fractal-tabs-trigger",
1141
+ isActive && "fractal-tabs-trigger--active",
1142
+ item.disabled && "fractal-tabs-trigger--disabled"
1143
+ ),
1144
+ onClick: () => !item.disabled && selectTab(item.id),
1145
+ onKeyDown,
1146
+ children: item.label
1147
+ },
1148
+ item.id
1149
+ );
1150
+ })
1151
+ }
1152
+ ),
955
1153
  items.map((item) => {
956
1154
  const tabId = `${reactId}-tab-${item.id}`;
957
1155
  const panelId = `${reactId}-panel-${item.id}`;
958
1156
  const isActive = item.id === activeId;
959
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1157
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
960
1158
  "div",
961
1159
  {
962
1160
  id: panelId,
@@ -972,10 +1170,112 @@ function Tabs({
972
1170
  ] });
973
1171
  }
974
1172
 
1173
+ // src/components/ContentSwitcher/ContentSwitcher.tsx
1174
+ var React10 = __toESM(require("react"), 1);
1175
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1176
+ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = false, className }) {
1177
+ const switcherRef = React10.useRef(null);
1178
+ const buttonRefs = React10.useRef([]);
1179
+ const indicatorMotionReadyRef = React10.useRef(false);
1180
+ const activeIndex = items.findIndex((item) => item.value === value);
1181
+ React10.useLayoutEffect(() => {
1182
+ const switcher = switcherRef.current;
1183
+ const activeButton = buttonRefs.current[activeIndex];
1184
+ let motionFrame = 0;
1185
+ if (!switcher || !activeButton) {
1186
+ switcher?.removeAttribute("data-indicator-ready");
1187
+ switcher?.removeAttribute("data-indicator-animate");
1188
+ indicatorMotionReadyRef.current = false;
1189
+ return;
1190
+ }
1191
+ const updateIndicator = () => {
1192
+ const switcherRect = switcher.getBoundingClientRect();
1193
+ const activeButtonRect = activeButton.getBoundingClientRect();
1194
+ switcher.style.setProperty("--fractal-content-switcher-indicator-x", `${activeButtonRect.left - switcherRect.left - switcher.clientLeft}px`);
1195
+ switcher.style.setProperty("--fractal-content-switcher-indicator-y", `${activeButtonRect.top - switcherRect.top - switcher.clientTop}px`);
1196
+ switcher.style.setProperty("--fractal-content-switcher-indicator-width", `${activeButtonRect.width}px`);
1197
+ switcher.style.setProperty("--fractal-content-switcher-indicator-height", `${activeButtonRect.height}px`);
1198
+ switcher.setAttribute("data-indicator-ready", "true");
1199
+ if (!indicatorMotionReadyRef.current && motionFrame === 0) {
1200
+ motionFrame = window.requestAnimationFrame(() => {
1201
+ indicatorMotionReadyRef.current = true;
1202
+ switcher.setAttribute("data-indicator-animate", "true");
1203
+ motionFrame = 0;
1204
+ });
1205
+ }
1206
+ };
1207
+ updateIndicator();
1208
+ if (typeof ResizeObserver === "undefined") {
1209
+ return () => {
1210
+ if (motionFrame !== 0) window.cancelAnimationFrame(motionFrame);
1211
+ };
1212
+ }
1213
+ const resizeObserver = new ResizeObserver(updateIndicator);
1214
+ resizeObserver.observe(switcher);
1215
+ buttonRefs.current.forEach((button) => {
1216
+ if (button) resizeObserver.observe(button);
1217
+ });
1218
+ return () => {
1219
+ resizeObserver.disconnect();
1220
+ if (motionFrame !== 0) window.cancelAnimationFrame(motionFrame);
1221
+ };
1222
+ }, [activeIndex, items.length]);
1223
+ const moveFocus = (index, direction) => {
1224
+ let nextIndex = index;
1225
+ do {
1226
+ nextIndex = (nextIndex + direction + items.length) % items.length;
1227
+ } while (items[nextIndex]?.disabled && nextIndex !== index);
1228
+ if (!items[nextIndex]?.disabled) {
1229
+ buttonRefs.current[nextIndex]?.focus();
1230
+ onValueChange(items[nextIndex].value);
1231
+ }
1232
+ };
1233
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1234
+ "div",
1235
+ {
1236
+ className: cn("fractal-content-switcher", fullWidth && "fractal-content-switcher--full-width", className),
1237
+ role: "group",
1238
+ "aria-label": ariaLabel,
1239
+ ref: switcherRef,
1240
+ children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "fractal-content-switcher__indicator", "aria-hidden": true }),
1242
+ items.map((item, index) => {
1243
+ const active = item.value === value;
1244
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1245
+ "button",
1246
+ {
1247
+ className: cn("fractal-content-switcher__item", active && "fractal-content-switcher__item--active"),
1248
+ type: "button",
1249
+ "aria-pressed": active,
1250
+ disabled: item.disabled,
1251
+ onClick: () => onValueChange(item.value),
1252
+ onKeyDown: (event) => {
1253
+ if (event.key === "ArrowRight") {
1254
+ event.preventDefault();
1255
+ moveFocus(index, 1);
1256
+ }
1257
+ if (event.key === "ArrowLeft") {
1258
+ event.preventDefault();
1259
+ moveFocus(index, -1);
1260
+ }
1261
+ },
1262
+ ref: (element) => {
1263
+ buttonRefs.current[index] = element;
1264
+ },
1265
+ children: item.label
1266
+ },
1267
+ item.value
1268
+ );
1269
+ })
1270
+ ]
1271
+ }
1272
+ );
1273
+ }
1274
+
975
1275
  // src/components/Disclosure/Disclosure.tsx
976
- var import_react4 = require("react");
977
- var import_fractal_icons4 = require("@mirror-physics/fractal-icons");
978
- var import_jsx_runtime15 = require("react/jsx-runtime");
1276
+ var import_react5 = require("react");
1277
+ var import_fractal_icons7 = require("@mirror-physics/fractal-icons");
1278
+ var import_jsx_runtime19 = require("react/jsx-runtime");
979
1279
  function Disclosure({
980
1280
  title,
981
1281
  meta,
@@ -983,16 +1283,18 @@ function Disclosure({
983
1283
  defaultOpen = false,
984
1284
  open: controlledOpen,
985
1285
  onOpenChange,
1286
+ disabled = false,
986
1287
  className,
987
1288
  variant = "card"
988
1289
  }) {
989
- const reactId = (0, import_react4.useId)();
1290
+ const reactId = (0, import_react5.useId)();
990
1291
  const headerId = `${reactId}-header`;
991
1292
  const panelId = `${reactId}-panel`;
992
- const [internalOpen, setInternalOpen] = (0, import_react4.useState)(defaultOpen);
1293
+ const [internalOpen, setInternalOpen] = (0, import_react5.useState)(defaultOpen);
993
1294
  const isControlled = controlledOpen !== void 0;
994
1295
  const isOpen = isControlled ? controlledOpen : internalOpen;
995
1296
  const toggle = () => {
1297
+ if (disabled) return;
996
1298
  const next = !isOpen;
997
1299
  if (isControlled) {
998
1300
  onOpenChange?.(next);
@@ -1001,17 +1303,18 @@ function Disclosure({
1001
1303
  onOpenChange?.(next);
1002
1304
  }
1003
1305
  };
1004
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1306
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1005
1307
  "div",
1006
1308
  {
1007
1309
  className: cn(
1008
1310
  "fractal-disclosure",
1009
1311
  variant === "card" && "fractal-disclosure--card",
1010
1312
  isOpen && "fractal-disclosure--open",
1313
+ disabled && "fractal-disclosure--disabled",
1011
1314
  className
1012
1315
  ),
1013
1316
  children: [
1014
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1317
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1015
1318
  "button",
1016
1319
  {
1017
1320
  type: "button",
@@ -1019,15 +1322,16 @@ function Disclosure({
1019
1322
  className: "fractal-disclosure-trigger",
1020
1323
  "aria-expanded": isOpen,
1021
1324
  "aria-controls": panelId,
1325
+ disabled,
1022
1326
  onClick: toggle,
1023
1327
  children: [
1024
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_fractal_icons4.ChevronDown, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_fractal_icons4.ChevronRight, { size: 16 }) }),
1025
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-title", children: title }),
1026
- meta && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-meta", children: meta })
1328
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_fractal_icons7.ChevronDown, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_fractal_icons7.ChevronRight, { size: 16 }) }),
1329
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-disclosure-title", children: title }),
1330
+ meta && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fractal-disclosure-meta", children: meta })
1027
1331
  ]
1028
1332
  }
1029
1333
  ),
1030
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1334
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1031
1335
  "div",
1032
1336
  {
1033
1337
  id: panelId,
@@ -1035,7 +1339,7 @@ function Disclosure({
1035
1339
  "aria-labelledby": headerId,
1036
1340
  className: "fractal-disclosure-panel",
1037
1341
  hidden: !isOpen,
1038
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "fractal-disclosure-panel-inner", children })
1342
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "fractal-disclosure-panel-inner", children })
1039
1343
  }
1040
1344
  )
1041
1345
  ]
@@ -1043,39 +1347,232 @@ function Disclosure({
1043
1347
  );
1044
1348
  }
1045
1349
 
1350
+ // src/components/LatticeLoader/LatticeLoader.tsx
1351
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1352
+ var LATTICE_COUNT = 160;
1353
+ var WAVE_PERIOD = 80;
1354
+ function LatticeLoader({ className, label = "Loading", ...props }) {
1355
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1356
+ "span",
1357
+ {
1358
+ "aria-label": label,
1359
+ className: cn("fractal-lattice-loader", className),
1360
+ role: "progressbar",
1361
+ ...props,
1362
+ children: Array.from({ length: LATTICE_COUNT }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1363
+ "span",
1364
+ {
1365
+ "aria-hidden": "true",
1366
+ className: "fractal-lattice-loader__cell",
1367
+ style: { "--fractal-lattice-index": index % WAVE_PERIOD }
1368
+ },
1369
+ index
1370
+ ))
1371
+ }
1372
+ );
1373
+ }
1374
+
1375
+ // src/components/Ghost/Ghost.tsx
1376
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1377
+ var toCssLength = (value) => typeof value === "number" ? `${value}px` : value;
1378
+ function Ghost({ className, width, height, radius, style, ...props }) {
1379
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1380
+ "div",
1381
+ {
1382
+ "aria-hidden": "true",
1383
+ className: cn("fractal-ghost", className),
1384
+ style: {
1385
+ width: toCssLength(width),
1386
+ height: toCssLength(height),
1387
+ borderRadius: toCssLength(radius),
1388
+ ...style
1389
+ },
1390
+ ...props
1391
+ }
1392
+ );
1393
+ }
1394
+ function GhostLine({ className, size = "md", width = "100%", ...props }) {
1395
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: cn("fractal-ghost-line", `fractal-ghost-line--${size}`, className), width, ...props });
1396
+ }
1397
+ function ButtonGhost({ className, size = "md", iconOnly = false, width, ...props }) {
1398
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: cn("fractal-ghost-button", `fractal-ghost-button--${size}`, iconOnly && "fractal-ghost-button--icon-only", className), width, ...props });
1399
+ }
1400
+ function CardGhost({ className, lines = 3, showHeader = true, ...props }) {
1401
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-card", className), ...props, children: [
1402
+ showHeader && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "38%" }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: index === lines - 1 ? "62%" : "100%" }, index)) })
1404
+ ] });
1405
+ }
1406
+ function DataTableGhost({
1407
+ className,
1408
+ showHeader = true,
1409
+ headers,
1410
+ columns = 4,
1411
+ rows = 5,
1412
+ columnWidths,
1413
+ size = "md",
1414
+ ...props
1415
+ }) {
1416
+ const cells = Array.from({ length: columns }, (_, index) => index);
1417
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { "aria-busy": "true", "aria-label": "Loading table", className: cn("fractal-ghost-table", `fractal-ghost-table--${size}`, className), role: "status", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("table", { className: "fractal-ghost-table__table", children: [
1418
+ (showHeader || headers) && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { className: "fractal-ghost-table__head-row", children: cells.map((index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("th", { style: { width: columnWidths?.[index] }, children: headers?.[index] ?? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { size: "sm", width: index === columns - 1 ? "62%" : "76%" }) }, index)) }) }),
1419
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tbody", { children: Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { className: "fractal-ghost-table__row", children: cells.map((columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { style: { width: columnWidths?.[columnIndex] }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: `${[72, 54, 82, 63, 46][(rowIndex + columnIndex) % 5]}%` }) }, columnIndex)) }, rowIndex)) })
1420
+ ] }) });
1421
+ }
1422
+ function InputGhost({ className, labelWidth = "26%", ...props }) {
1423
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FormFieldGhost, { className, labelWidth, ...props });
1424
+ }
1425
+ function TextareaGhost({ className, labelWidth = "26%", ...props }) {
1426
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FormFieldGhost, { className, labelWidth, multiline: true, ...props });
1427
+ }
1428
+ function LabelGhost({ className, width = "26%", ...props }) {
1429
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { className: cn("fractal-ghost-label", className), size: "sm", width, ...props });
1430
+ }
1431
+ function FormFieldGhost({ className, labelWidth = "26%", multiline = false, ...props }) {
1432
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-field", className), ...props, children: [
1433
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LabelGhost, { width: labelWidth }),
1434
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: cn("fractal-ghost-field__control", multiline && "fractal-ghost-field__control--multiline") })
1435
+ ] });
1436
+ }
1437
+ function AlertGhost({ className, ...props }) {
1438
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-alert", className), ...props, children: [
1439
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "30%" }),
1440
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { size: "sm", width: "78%" })
1441
+ ] });
1442
+ }
1443
+ function CheckboxGhost({ className, ...props }) {
1444
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-choice", className), ...props, children: [
1445
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: "fractal-ghost-choice__control" }),
1446
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "42%" })
1447
+ ] });
1448
+ }
1449
+ var ToggleGhost = CheckboxGhost;
1450
+ function ChipGhost({ className, width = 74, ...props }) {
1451
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: cn("fractal-ghost-chip", className), height: 24, width, ...props });
1452
+ }
1453
+ function LinkGhost({ className, width = 96, ...props }) {
1454
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { className: cn("fractal-ghost-link", className), size: "sm", width, ...props });
1455
+ }
1456
+ var TextButtonGhost = LinkGhost;
1457
+ function DropdownGhost({ className, ...props }) {
1458
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropdown", className), ...props, children: [
1459
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "38%" }),
1460
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: "fractal-ghost-dropdown__chevron" })
1461
+ ] });
1462
+ }
1463
+ function ContentSwitcherGhost({ className, options = 3, ...props }) {
1464
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { "aria-hidden": "true", className: cn("fractal-ghost-switcher", className), ...props, children: Array.from({ length: options }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, {}, index)) });
1465
+ }
1466
+ var TabsGhost = ContentSwitcherGhost;
1467
+ function DisclosureGhost({ className, ...props }) {
1468
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-disclosure", className), ...props, children: [
1469
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: "fractal-ghost-disclosure__icon" }),
1470
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "42%" })
1471
+ ] });
1472
+ }
1473
+ function PaginationGhost({ className, pages = 5, ...props }) {
1474
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { "aria-hidden": "true", className: cn("fractal-ghost-pagination", className), ...props, children: Array.from({ length: pages }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, {}, index)) });
1475
+ }
1476
+ function FileDropzoneGhost({ className, ...props }) {
1477
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropzone", className), ...props, children: [
1478
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: "fractal-ghost-dropzone__icon" }),
1479
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "26%" }),
1480
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { size: "sm", width: "46%" })
1481
+ ] });
1482
+ }
1483
+ function PromptCardGhost({ className, ...props }) {
1484
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardGhost, { className: cn("fractal-ghost-prompt-card", className), lines: 4, ...props });
1485
+ }
1486
+ function SortableTableGhost(props) {
1487
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DataTableGhost, { ...props });
1488
+ }
1489
+ function SidebarGhost({ className, items = 6, ...props }) {
1490
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("aside", { "aria-hidden": "true", className: cn("fractal-ghost-sidebar", className), ...props, children: [
1491
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: "fractal-ghost-sidebar__brand" }),
1492
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "fractal-ghost-sidebar__items", children: Array.from({ length: items }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "fractal-ghost-sidebar__item", children: [
1493
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, {}),
1494
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: `${[54, 68, 44, 61][index % 4]}%` })
1495
+ ] }, index)) })
1496
+ ] });
1497
+ }
1498
+ function ModalGhost({ className, title, lines = 3, ...props }) {
1499
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SurfaceGhost, { className: cn("fractal-ghost-modal", className), title, lines, ...props });
1500
+ }
1501
+ function SidePanelGhost({ className, title, lines = 5, ...props }) {
1502
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SurfaceGhost, { className: cn("fractal-ghost-side-panel", className), title, lines, ...props });
1503
+ }
1504
+ function SurfaceGhost({ className, title, lines = 3, ...props }) {
1505
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-surface", className), ...props, children: [
1506
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "fractal-ghost-surface__header", children: [
1507
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: "42%" }),
1508
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Ghost, { className: "fractal-ghost-surface__close" })
1509
+ ] }),
1510
+ title && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "fractal-ghost-surface__title", children: title }),
1511
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GhostLine, { width: index === lines - 1 ? "64%" : "100%" }, index)) })
1512
+ ] });
1513
+ }
1514
+
1046
1515
  // src/components/Sidebar/Sidebar.tsx
1047
- var React10 = __toESM(require("react"), 1);
1048
- var import_jsx_runtime16 = require("react/jsx-runtime");
1049
- var Sidebar = React10.forwardRef(
1050
- ({ className, width, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1516
+ var React11 = __toESM(require("react"), 1);
1517
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1518
+ var Sidebar = React11.forwardRef(
1519
+ ({ className, width, compact = false, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1051
1520
  "aside",
1052
1521
  {
1053
1522
  ref,
1054
1523
  className: cn("fractal-sidebar", className),
1524
+ "data-compact": compact || void 0,
1055
1525
  style: { ...style, ...width ? { "--fractal-sidebar-width": width } : {} },
1056
1526
  ...props
1057
1527
  }
1058
1528
  )
1059
1529
  );
1060
1530
  Sidebar.displayName = "Sidebar";
1061
- var SidebarHeader = React10.forwardRef(
1062
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
1531
+ var SidebarHeader = React11.forwardRef(
1532
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
1063
1533
  );
1064
1534
  SidebarHeader.displayName = "SidebarHeader";
1065
- var SidebarBrand = React10.forwardRef(
1066
- ({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
1535
+ var SidebarBrand = React11.forwardRef(
1536
+ ({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
1067
1537
  );
1068
1538
  SidebarBrand.displayName = "SidebarBrand";
1069
- var SidebarNav = React10.forwardRef(
1070
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
1539
+ function SidebarAccountMenu({
1540
+ name,
1541
+ items,
1542
+ onSelect,
1543
+ triggerLabel = "Account menu",
1544
+ icon,
1545
+ className
1546
+ }) {
1547
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1548
+ Dropdown,
1549
+ {
1550
+ align: "left",
1551
+ className: cn("fractal-sidebar__account", className),
1552
+ items,
1553
+ onSelect,
1554
+ panelClassName: "fractal-sidebar__account-panel",
1555
+ selectedValue: "",
1556
+ triggerClassName: "fractal-sidebar__account-trigger",
1557
+ triggerContent: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
1558
+ icon && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-sidebar__account-icon", "aria-hidden": "true", children: icon }),
1559
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-sidebar__account-name", children: name })
1560
+ ] }),
1561
+ triggerLabel,
1562
+ triggerVariant: "tertiary"
1563
+ }
1564
+ );
1565
+ }
1566
+ var SidebarNav = React11.forwardRef(
1567
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
1071
1568
  );
1072
1569
  SidebarNav.displayName = "SidebarNav";
1073
- var SidebarSection = React10.forwardRef(
1074
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
1570
+ var SidebarSection = React11.forwardRef(
1571
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
1075
1572
  );
1076
1573
  SidebarSection.displayName = "SidebarSection";
1077
- var SidebarNavItem = React10.forwardRef(
1078
- ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1574
+ var SidebarNavItem = React11.forwardRef(
1575
+ ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
1079
1576
  "button",
1080
1577
  {
1081
1578
  ref,
@@ -1085,67 +1582,315 @@ var SidebarNavItem = React10.forwardRef(
1085
1582
  "aria-current": active ? "page" : void 0,
1086
1583
  ...props,
1087
1584
  children: [
1088
- icon && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
1089
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-label", children }),
1090
- endAdornment && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
1585
+ icon && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
1586
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-sidebar__nav-item-label", children }),
1587
+ endAdornment && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
1091
1588
  ]
1092
1589
  }
1093
1590
  )
1094
1591
  );
1095
1592
  SidebarNavItem.displayName = "SidebarNavItem";
1096
- var SidebarFooter = React10.forwardRef(
1097
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
1593
+ var SidebarFooter = React11.forwardRef(
1594
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
1098
1595
  );
1099
1596
  SidebarFooter.displayName = "SidebarFooter";
1100
1597
 
1101
- // src/components/PageHeader/PageHeader.tsx
1102
- var React11 = __toESM(require("react"), 1);
1103
- var import_jsx_runtime17 = require("react/jsx-runtime");
1104
- var PageHeader = React11.forwardRef(
1105
- ({ title, description, actions, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref, className: cn("fractal-page-header", className), ...props, children: [
1106
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "fractal-page-header__content", children: [
1107
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h1", { className: "fractal-page-header__title", children: title }),
1108
- description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "fractal-page-header__description", children: description })
1109
- ] }),
1110
- actions && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "fractal-page-header__actions", children: actions })
1111
- ] })
1598
+ // src/components/SidePanel/SidePanel.tsx
1599
+ var import_react_dom2 = require("react-dom");
1600
+ var import_fractal_icons8 = require("@mirror-physics/fractal-icons");
1601
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1602
+ function SidePanel({ open, onClose, title, description, children, footer, size = "md", loading = false, loadingLabel = "Loading", className }) {
1603
+ useEscapeDismiss(80, onClose, open);
1604
+ if (!open) return null;
1605
+ return (0, import_react_dom2.createPortal)(
1606
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1607
+ "aside",
1608
+ {
1609
+ className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
1610
+ "aria-modal": "true",
1611
+ "aria-label": typeof title === "string" ? title : "Side panel",
1612
+ role: "dialog",
1613
+ onMouseDown: (event) => event.stopPropagation(),
1614
+ children: [
1615
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("header", { className: "fractal-side-panel__header", children: [
1616
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "fractal-side-panel__heading", children: [
1617
+ typeof title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "fractal-side-panel__title", children: title }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "fractal-side-panel__title", children: title }),
1618
+ description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "fractal-side-panel__description", children: description })
1619
+ ] }),
1620
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons8.Close, { size: 18 }) })
1621
+ ] }),
1622
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { "aria-busy": loading || void 0, className: cn("fractal-side-panel__body", loading && "fractal-side-panel__body--loading"), children: loading ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UILoader, { label: loadingLabel }) : children }),
1623
+ footer && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("footer", { className: "fractal-side-panel__footer", children: footer })
1624
+ ]
1625
+ }
1626
+ ) }),
1627
+ document.body
1628
+ );
1629
+ }
1630
+
1631
+ // src/components/Textarea/Textarea.tsx
1632
+ var React12 = __toESM(require("react"), 1);
1633
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1634
+ var Textarea = React12.forwardRef(
1635
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("textarea", { ref, className: cn("fractal-textarea", className), ...props })
1636
+ );
1637
+ Textarea.displayName = "Textarea";
1638
+
1639
+ // src/components/TextButton/TextButton.tsx
1640
+ var React13 = __toESM(require("react"), 1);
1641
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1642
+ var TextButton = React13.forwardRef(
1643
+ ({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1644
+ "button",
1645
+ {
1646
+ ref,
1647
+ className: cn("fractal-text-button", `fractal-text-button--${size}`, `fractal-text-button--${tone}`, className),
1648
+ type: "button",
1649
+ ...props,
1650
+ children: [
1651
+ icon && iconPosition === "start" && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon }),
1652
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children }),
1653
+ icon && iconPosition === "end" && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon })
1654
+ ]
1655
+ }
1656
+ )
1112
1657
  );
1113
- PageHeader.displayName = "PageHeader";
1658
+ TextButton.displayName = "TextButton";
1659
+
1660
+ // src/components/FileDropzone/FileDropzone.tsx
1661
+ var React14 = __toESM(require("react"), 1);
1662
+ var import_fractal_icons9 = require("@mirror-physics/fractal-icons");
1663
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1664
+ function FileDropzone({
1665
+ files,
1666
+ onFilesChange,
1667
+ accept,
1668
+ multiple = true,
1669
+ disabled = false,
1670
+ title = "Drop files here or click to browse",
1671
+ description = "Files stay attached to this record.",
1672
+ className
1673
+ }) {
1674
+ const inputId = React14.useId();
1675
+ const inputRef = React14.useRef(null);
1676
+ const [isDragging, setIsDragging] = React14.useState(false);
1677
+ const addFiles = (nextFiles) => {
1678
+ if (disabled) return;
1679
+ const additions = Array.from(nextFiles);
1680
+ if (additions.length === 0) return;
1681
+ onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
1682
+ };
1683
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("fractal-file-dropzone", className), children: [
1684
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1685
+ "input",
1686
+ {
1687
+ ref: inputRef,
1688
+ id: inputId,
1689
+ className: "fractal-file-dropzone__input",
1690
+ type: "file",
1691
+ accept,
1692
+ multiple,
1693
+ disabled,
1694
+ onChange: (event) => {
1695
+ if (event.target.files) addFiles(event.target.files);
1696
+ event.target.value = "";
1697
+ }
1698
+ }
1699
+ ),
1700
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1701
+ "button",
1702
+ {
1703
+ className: "fractal-file-dropzone__target",
1704
+ "data-dragging": isDragging || void 0,
1705
+ type: "button",
1706
+ disabled,
1707
+ onClick: () => inputRef.current?.click(),
1708
+ onDragEnter: (event) => {
1709
+ event.preventDefault();
1710
+ if (!disabled) setIsDragging(true);
1711
+ },
1712
+ onDragOver: (event) => event.preventDefault(),
1713
+ onDragLeave: (event) => {
1714
+ event.preventDefault();
1715
+ setIsDragging(false);
1716
+ },
1717
+ onDrop: (event) => {
1718
+ event.preventDefault();
1719
+ setIsDragging(false);
1720
+ addFiles(event.dataTransfer.files);
1721
+ },
1722
+ children: [
1723
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_fractal_icons9.FileArrowUp, { "aria-hidden": "true", size: 20 }),
1724
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "fractal-file-dropzone__copy", children: [
1725
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fractal-file-dropzone__title", children: title }),
1726
+ description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fractal-file-dropzone__description", children: description })
1727
+ ] })
1728
+ ]
1729
+ }
1730
+ ),
1731
+ files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("li", { className: "fractal-file-dropzone__file", children: [
1732
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
1733
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
1734
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1735
+ "button",
1736
+ {
1737
+ className: "fractal-file-dropzone__remove",
1738
+ type: "button",
1739
+ "aria-label": `Remove ${file.name}`,
1740
+ disabled,
1741
+ onClick: () => onFilesChange(files.filter((_, fileIndex) => fileIndex !== index)),
1742
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_fractal_icons9.Close, { "aria-hidden": "true", size: 14 })
1743
+ }
1744
+ )
1745
+ ] }, `${file.name}-${file.size}-${index}`)) })
1746
+ ] });
1747
+ }
1748
+ function formatFileSize(bytes) {
1749
+ if (bytes < 1024) return `${bytes} B`;
1750
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
1751
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1752
+ }
1753
+
1754
+ // src/components/Pagination/Pagination.tsx
1755
+ var import_fractal_icons10 = require("@mirror-physics/fractal-icons");
1756
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1757
+ function Pagination({
1758
+ page,
1759
+ pageSize,
1760
+ totalItems,
1761
+ onPageChange,
1762
+ pageSizeOptions,
1763
+ onPageSizeChange,
1764
+ ariaLabel = "Pagination",
1765
+ className
1766
+ }) {
1767
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
1768
+ const currentPage = Math.min(Math.max(page, 1), totalPages);
1769
+ const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
1770
+ const end = Math.min(currentPage * pageSize, totalItems);
1771
+ const canChangePageSize = pageSizeOptions != null && pageSizeOptions.length > 0 && onPageSizeChange != null;
1772
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
1773
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fractal-pagination__summary", children: totalItems === 0 ? "No results" : `${start}-${end} of ${totalItems}` }),
1774
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "fractal-pagination__controls", children: [
1775
+ canChangePageSize && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1776
+ Dropdown,
1777
+ {
1778
+ align: "right",
1779
+ className: "fractal-pagination__page-size",
1780
+ direction: "up",
1781
+ items: pageSizeOptions.map((option) => ({
1782
+ value: String(option),
1783
+ description: `${option} per page`
1784
+ })),
1785
+ onSelect: (value) => onPageSizeChange(Number(value)),
1786
+ selectedValue: String(pageSize),
1787
+ size: "sm",
1788
+ triggerLabel: "Results per page",
1789
+ triggerVariant: "tertiary"
1790
+ }
1791
+ ),
1792
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1793
+ "button",
1794
+ {
1795
+ className: "fractal-pagination__button",
1796
+ type: "button",
1797
+ "aria-label": "Previous page",
1798
+ title: "Previous page",
1799
+ disabled: currentPage === 1 || totalItems === 0,
1800
+ onClick: () => onPageChange(currentPage - 1),
1801
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fractal_icons10.ArrowLeft, { "aria-hidden": "true", size: 16 })
1802
+ }
1803
+ ),
1804
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
1805
+ currentPage,
1806
+ " of ",
1807
+ totalPages
1808
+ ] }),
1809
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1810
+ "button",
1811
+ {
1812
+ className: "fractal-pagination__button",
1813
+ type: "button",
1814
+ "aria-label": "Next page",
1815
+ title: "Next page",
1816
+ disabled: currentPage === totalPages || totalItems === 0,
1817
+ onClick: () => onPageChange(currentPage + 1),
1818
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fractal_icons10.ArrowRight, { "aria-hidden": "true", size: 16 })
1819
+ }
1820
+ )
1821
+ ] })
1822
+ ] });
1823
+ }
1114
1824
  // Annotate the CommonJS export names for ESM import in node:
1115
1825
  0 && (module.exports = {
1116
1826
  Alert,
1117
1827
  AlertDescription,
1828
+ AlertGhost,
1118
1829
  AlertTitle,
1830
+ Breadcrumbs,
1119
1831
  Button,
1832
+ ButtonGhost,
1120
1833
  Card,
1121
1834
  CardContent,
1122
1835
  CardDescription,
1123
1836
  CardFooter,
1837
+ CardGhost,
1124
1838
  CardHeader,
1125
1839
  CardTitle,
1840
+ Checkbox,
1841
+ CheckboxGhost,
1126
1842
  Chip,
1843
+ ChipGhost,
1844
+ ContentSwitcher,
1845
+ ContentSwitcherGhost,
1127
1846
  DataTable,
1847
+ DataTableGhost,
1128
1848
  Disclosure,
1849
+ DisclosureGhost,
1129
1850
  Dropdown,
1851
+ DropdownGhost,
1130
1852
  FeatureCard,
1853
+ FileDropzone,
1854
+ FileDropzoneGhost,
1131
1855
  FolderCard,
1856
+ Ghost,
1857
+ GhostLine,
1132
1858
  Input,
1859
+ InputGhost,
1133
1860
  Label,
1861
+ LabelGhost,
1862
+ LatticeLoader,
1134
1863
  Link,
1864
+ LinkGhost,
1135
1865
  Modal,
1136
- PageHeader,
1866
+ ModalGhost,
1867
+ Pagination,
1868
+ PaginationGhost,
1137
1869
  PromptCard,
1870
+ PromptCardGhost,
1138
1871
  PromptGrid,
1872
+ SidePanel,
1873
+ SidePanelGhost,
1139
1874
  Sidebar,
1875
+ SidebarAccountMenu,
1140
1876
  SidebarBrand,
1141
1877
  SidebarFooter,
1878
+ SidebarGhost,
1142
1879
  SidebarHeader,
1143
1880
  SidebarNav,
1144
1881
  SidebarNavItem,
1145
1882
  SidebarSection,
1146
1883
  SortableTable,
1884
+ SortableTableGhost,
1147
1885
  Tabs,
1886
+ TabsGhost,
1887
+ TextButton,
1888
+ TextButtonGhost,
1889
+ Textarea,
1890
+ TextareaGhost,
1148
1891
  Toggle,
1892
+ ToggleGhost,
1893
+ UILoader,
1149
1894
  cn,
1150
1895
  useEscapeDismiss
1151
1896
  });