@mirror-physics/fractal-ui 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1136 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Alert: () => Alert,
34
+ AlertDescription: () => AlertDescription,
35
+ AlertTitle: () => AlertTitle,
36
+ Button: () => Button,
37
+ Card: () => Card,
38
+ CardContent: () => CardContent,
39
+ CardDescription: () => CardDescription,
40
+ CardFooter: () => CardFooter,
41
+ CardHeader: () => CardHeader,
42
+ CardTitle: () => CardTitle,
43
+ Chip: () => Chip,
44
+ DataTable: () => DataTable,
45
+ Disclosure: () => Disclosure,
46
+ Dropdown: () => Dropdown,
47
+ FeatureCard: () => FeatureCard,
48
+ FolderCard: () => FolderCard,
49
+ Input: () => Input,
50
+ Label: () => Label,
51
+ Link: () => Link,
52
+ Modal: () => Modal,
53
+ PromptCard: () => PromptCard,
54
+ PromptGrid: () => PromptGrid,
55
+ Sidebar: () => Sidebar,
56
+ SidebarBrand: () => SidebarBrand,
57
+ SidebarFooter: () => SidebarFooter,
58
+ SidebarHeader: () => SidebarHeader,
59
+ SidebarNav: () => SidebarNav,
60
+ SidebarNavItem: () => SidebarNavItem,
61
+ SidebarSection: () => SidebarSection,
62
+ SortableTable: () => SortableTable,
63
+ Tabs: () => Tabs,
64
+ Toggle: () => Toggle,
65
+ cn: () => cn,
66
+ useEscapeDismiss: () => useEscapeDismiss
67
+ });
68
+ module.exports = __toCommonJS(index_exports);
69
+
70
+ // src/components/Button/Button.tsx
71
+ var React = __toESM(require("react"), 1);
72
+
73
+ // src/utils/cn.ts
74
+ var import_clsx = require("clsx");
75
+ function cn(...inputs) {
76
+ return (0, import_clsx.clsx)(inputs);
77
+ }
78
+
79
+ // src/components/Button/Button.tsx
80
+ var import_jsx_runtime = require("react/jsx-runtime");
81
+ var colorPalette = {
82
+ blue: {
83
+ 0: "var(--blue-0)",
84
+ 50: "var(--blue-50)",
85
+ 100: "var(--blue-100)",
86
+ 200: "var(--blue-200)",
87
+ 500: "var(--blue-500)",
88
+ 600: "var(--blue-600)",
89
+ 700: "var(--blue-700)"
90
+ },
91
+ pink: {
92
+ 0: "var(--pink-0)",
93
+ 50: "var(--pink-50)",
94
+ 100: "var(--pink-100)",
95
+ 200: "var(--pink-200)",
96
+ 500: "var(--pink-500)",
97
+ 600: "var(--pink-600)",
98
+ 700: "var(--pink-700)"
99
+ },
100
+ orange: {
101
+ 0: "var(--orange-0)",
102
+ 50: "var(--orange-50)",
103
+ 100: "var(--orange-100)",
104
+ 200: "var(--orange-200)",
105
+ 500: "var(--orange-500)",
106
+ 600: "var(--orange-600)",
107
+ 700: "var(--orange-700)"
108
+ },
109
+ green: {
110
+ 0: "var(--green-0)",
111
+ 50: "var(--green-50)",
112
+ 100: "var(--green-100)",
113
+ 200: "var(--green-200)",
114
+ 500: "var(--green-500)",
115
+ 600: "var(--green-600)",
116
+ 700: "var(--green-700)"
117
+ }
118
+ };
119
+ var sizeConfig = {
120
+ xs: { height: "28px", padding: "4px 8px", iconOnly: "28px", fontSize: "0.75rem" },
121
+ sm: { height: "32px", padding: "6px 12px", iconOnly: "32px", fontSize: "0.75rem" },
122
+ md: { height: "38px", padding: "8px 16px", iconOnly: "38px", fontSize: "0.875rem" },
123
+ lg: { height: "44px", padding: "10px 20px", iconOnly: "44px", fontSize: "1rem" },
124
+ xl: { height: "56px", padding: "14px 28px", iconOnly: "56px", fontSize: "1rem" }
125
+ };
126
+ function getButtonStyles(buttonType, isHovered, isActive, buttonSize, disabled, color, hasIconOnly) {
127
+ const palette = colorPalette[color];
128
+ const size = sizeConfig[buttonSize];
129
+ const base = {
130
+ height: size.height,
131
+ padding: hasIconOnly ? "0" : size.padding,
132
+ borderRadius: hasIconOnly ? "var(--radius-lg, 8px)" : "var(--radius-full, 9999px)",
133
+ cursor: disabled ? "not-allowed" : "pointer",
134
+ fontSize: size.fontSize,
135
+ transition: "background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease"
136
+ };
137
+ if (hasIconOnly) {
138
+ base.width = size.iconOnly;
139
+ base.justifyContent = "center";
140
+ }
141
+ if (disabled) {
142
+ if (buttonType === "ghost") {
143
+ return { ...base, backgroundColor: "transparent", border: "none", color: "var(--fg-disabled)" };
144
+ }
145
+ return { ...base, backgroundColor: "transparent", border: "1px solid var(--fg-disabled)", color: "var(--fg-disabled)" };
146
+ }
147
+ switch (buttonType) {
148
+ // Primary with text: dark pill. Icon-only: color palette (Synapse style).
149
+ case "primary":
150
+ if (hasIconOnly) {
151
+ return {
152
+ ...base,
153
+ backgroundColor: isActive ? palette[700] : isHovered ? palette[500] : palette[600],
154
+ border: "none",
155
+ color: "var(--fg-inverse)"
156
+ };
157
+ }
158
+ return {
159
+ ...base,
160
+ backgroundColor: "var(--fg-primary)",
161
+ border: "1px solid var(--fg-primary)",
162
+ color: "var(--fg-inverse)",
163
+ ...isHovered || isActive ? { opacity: 0.85 } : {}
164
+ };
165
+ // Secondary: neutral. Rest=canvas, hover=surface-1 (darken), pressed=surface-2. Subtle border, dark text.
166
+ case "secondary":
167
+ return {
168
+ ...base,
169
+ backgroundColor: isActive ? "var(--bg-surface-2)" : isHovered ? "var(--bg-surface-1)" : "var(--bg-canvas)",
170
+ border: "1px solid var(--border-subtle)",
171
+ color: "var(--fg-primary)"
172
+ };
173
+ // Ghost: no border. Rest=transparent, hover/press=surface-1.
174
+ case "ghost":
175
+ return {
176
+ ...base,
177
+ backgroundColor: isHovered || isActive ? "var(--bg-surface-1)" : "transparent",
178
+ border: "none",
179
+ color: "var(--fg-primary)"
180
+ };
181
+ // Danger: low-intensity destructive action. Text stays steady; hover deepens the light red surface.
182
+ case "danger":
183
+ return {
184
+ ...base,
185
+ backgroundColor: isHovered || isActive ? "var(--danger-button-surface-hover)" : "var(--danger-button-surface)",
186
+ border: "none",
187
+ color: "var(--danger-button-fg)"
188
+ };
189
+ default:
190
+ return base;
191
+ }
192
+ }
193
+ var Button = React.forwardRef(
194
+ ({ className, buttonType = "primary", buttonSize = "md", color = "blue", icon, hasIconOnly, iconPosition = "left", style, disabled, children, ...props }, ref) => {
195
+ const [isHovered, setIsHovered] = React.useState(false);
196
+ const [isActive, setIsActive] = React.useState(false);
197
+ const typeStyles = getButtonStyles(buttonType, isHovered, isActive, buttonSize, !!disabled, color, hasIconOnly);
198
+ const hasIconAndText = icon && children && !hasIconOnly;
199
+ const finalStyles = hasIconAndText ? { ...typeStyles, gap: "var(--space-2, 8px)", ...style } : { ...typeStyles, ...style };
200
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
201
+ "button",
202
+ {
203
+ ref,
204
+ type: "button",
205
+ className: cn("fractal-button", `fractal-button--${buttonType}`, className),
206
+ style: finalStyles,
207
+ disabled,
208
+ onMouseEnter: (e) => {
209
+ setIsHovered(true);
210
+ props.onMouseEnter?.(e);
211
+ },
212
+ onMouseLeave: (e) => {
213
+ setIsHovered(false);
214
+ setIsActive(false);
215
+ props.onMouseLeave?.(e);
216
+ },
217
+ onMouseDown: (e) => {
218
+ setIsActive(true);
219
+ props.onMouseDown?.(e);
220
+ },
221
+ onMouseUp: (e) => {
222
+ setIsActive(false);
223
+ props.onMouseUp?.(e);
224
+ },
225
+ ...props,
226
+ children: [
227
+ iconPosition !== "right" && icon,
228
+ !hasIconOnly && children,
229
+ iconPosition === "right" && icon
230
+ ]
231
+ }
232
+ );
233
+ }
234
+ );
235
+ Button.displayName = "Button";
236
+
237
+ // src/components/Card/Card.tsx
238
+ var React2 = __toESM(require("react"), 1);
239
+ var import_fractal_icons = require("@mirror-physics/fractal-icons");
240
+ var import_jsx_runtime2 = require("react/jsx-runtime");
241
+ var Card = React2.forwardRef(
242
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card", className), ...props })
243
+ );
244
+ Card.displayName = "Card";
245
+ var CardHeader = React2.forwardRef(
246
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card-header", className), ...props })
247
+ );
248
+ CardHeader.displayName = "CardHeader";
249
+ var CardTitle = React2.forwardRef(
250
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { ref, className: cn("fractal-card-title", className), ...props })
251
+ );
252
+ CardTitle.displayName = "CardTitle";
253
+ var CardDescription = React2.forwardRef(
254
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { ref, className: cn("fractal-card-description", className), ...props })
255
+ );
256
+ CardDescription.displayName = "CardDescription";
257
+ var CardContent = React2.forwardRef(
258
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card-content", className), ...props })
259
+ );
260
+ CardContent.displayName = "CardContent";
261
+ var CardFooter = React2.forwardRef(
262
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, className: cn("fractal-card-footer", className), ...props })
263
+ );
264
+ CardFooter.displayName = "CardFooter";
265
+ var FeatureCard = React2.forwardRef(
266
+ ({ icon, title, description, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { ref, className: cn("fractal-feature-card", className), ...props, children: [
267
+ icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fractal-feature-card__icon", children: icon }),
268
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "fractal-feature-card__title", children: title }),
269
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "fractal-feature-card__description", children: description })
270
+ ] })
271
+ );
272
+ FeatureCard.displayName = "FeatureCard";
273
+ var FolderCard = React2.forwardRef(
274
+ ({ name, sessionCount, selected, className, onClick, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
275
+ "div",
276
+ {
277
+ ref,
278
+ role: "button",
279
+ tabIndex: 0,
280
+ onClick,
281
+ onKeyDown: (e) => {
282
+ if (e.key === "Enter" || e.key === " ") {
283
+ e.preventDefault();
284
+ onClick?.(e);
285
+ }
286
+ },
287
+ className: cn("fractal-folder-card", selected && "fractal-folder-card--selected", className),
288
+ ...props,
289
+ children: [
290
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fractal-folder-card__header", children: [
291
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_fractal_icons.Folder, { size: 16, className: "fractal-folder-card__icon", "aria-hidden": true }),
292
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fractal-folder-card__name", children: name })
293
+ ] }),
294
+ 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: [
295
+ sessionCount,
296
+ " ",
297
+ sessionCount === 1 ? "session" : "sessions"
298
+ ] }) })
299
+ ]
300
+ }
301
+ )
302
+ );
303
+ FolderCard.displayName = "FolderCard";
304
+
305
+ // src/components/PromptCard/PromptCard.tsx
306
+ var React3 = __toESM(require("react"), 1);
307
+ var import_jsx_runtime3 = require("react/jsx-runtime");
308
+ var titleToPrompt = (title) => typeof title === "string" || typeof title === "number" ? String(title) : "";
309
+ var PromptCard = React3.forwardRef(
310
+ ({
311
+ title,
312
+ icon,
313
+ prompt,
314
+ tone = "blue",
315
+ highlighted,
316
+ disabled,
317
+ className,
318
+ onClick,
319
+ onPromptSelect,
320
+ ...props
321
+ }, ref) => {
322
+ const handleClick = (event) => {
323
+ onClick?.(event);
324
+ if (!event.defaultPrevented) {
325
+ onPromptSelect?.(prompt ?? titleToPrompt(title));
326
+ }
327
+ };
328
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
329
+ "button",
330
+ {
331
+ ref,
332
+ type: "button",
333
+ disabled,
334
+ className: cn(
335
+ "fractal-prompt-card",
336
+ `fractal-prompt-card--${tone}`,
337
+ highlighted && "fractal-prompt-card--highlighted",
338
+ className
339
+ ),
340
+ onClick: handleClick,
341
+ ...props,
342
+ children: [
343
+ icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fractal-prompt-card__icon", "aria-hidden": "true", children: icon }),
344
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fractal-prompt-card__title", children: title })
345
+ ]
346
+ }
347
+ );
348
+ }
349
+ );
350
+ PromptCard.displayName = "PromptCard";
351
+ var PromptGrid = React3.forwardRef(
352
+ ({ compact, padded, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
353
+ "div",
354
+ {
355
+ ref,
356
+ className: cn(
357
+ "fractal-prompt-grid",
358
+ compact && "fractal-prompt-grid--compact",
359
+ padded && "fractal-prompt-grid--padded",
360
+ className
361
+ ),
362
+ ...props
363
+ }
364
+ )
365
+ );
366
+ PromptGrid.displayName = "PromptGrid";
367
+
368
+ // src/components/Input/Input.tsx
369
+ var React4 = __toESM(require("react"), 1);
370
+ var import_jsx_runtime4 = require("react/jsx-runtime");
371
+ var Input = React4.forwardRef(
372
+ ({ className, type, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
373
+ "input",
374
+ {
375
+ type,
376
+ ref,
377
+ className: cn("fractal-input", className),
378
+ ...props
379
+ }
380
+ )
381
+ );
382
+ Input.displayName = "Input";
383
+
384
+ // src/components/Label/Label.tsx
385
+ var React5 = __toESM(require("react"), 1);
386
+ var import_jsx_runtime5 = require("react/jsx-runtime");
387
+ var Label = React5.forwardRef(
388
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
389
+ "label",
390
+ {
391
+ ref,
392
+ className: cn("fractal-label", className),
393
+ ...props
394
+ }
395
+ )
396
+ );
397
+ Label.displayName = "Label";
398
+
399
+ // src/components/Alert/Alert.tsx
400
+ var React6 = __toESM(require("react"), 1);
401
+ var import_jsx_runtime6 = require("react/jsx-runtime");
402
+ var defaultIcons = {
403
+ default: "\u2139",
404
+ info: "\u2139",
405
+ success: "\u2713",
406
+ warning: "\u26A0",
407
+ error: "\u2715"
408
+ };
409
+ var Alert = React6.forwardRef(
410
+ ({ className, variant = "default", icon, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
411
+ "div",
412
+ {
413
+ ref,
414
+ role: "alert",
415
+ className: cn("fractal-alert", `fractal-alert--${variant}`, className),
416
+ ...props,
417
+ children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "fractal-alert-icon", "aria-hidden": true, children: icon ?? defaultIcons[variant] }),
419
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "fractal-alert-content", children })
420
+ ]
421
+ }
422
+ )
423
+ );
424
+ Alert.displayName = "Alert";
425
+ var AlertTitle = React6.forwardRef(
426
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h5", { ref, className: cn("fractal-alert-title", className), ...props })
427
+ );
428
+ AlertTitle.displayName = "AlertTitle";
429
+ var AlertDescription = React6.forwardRef(
430
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref, className: cn("fractal-alert-description", className), ...props })
431
+ );
432
+ AlertDescription.displayName = "AlertDescription";
433
+
434
+ // src/components/Toggle/Toggle.tsx
435
+ var import_jsx_runtime7 = require("react/jsx-runtime");
436
+ function Toggle({ checked, onChange, label, className }) {
437
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
438
+ "button",
439
+ {
440
+ type: "button",
441
+ role: "switch",
442
+ "aria-checked": checked,
443
+ className: cn("fractal-toggle", className),
444
+ onClick: () => onChange(!checked),
445
+ children: [
446
+ /* @__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") }) }),
447
+ label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fractal-toggle-label", children: label })
448
+ ]
449
+ }
450
+ );
451
+ }
452
+
453
+ // src/components/Modal/Modal.tsx
454
+ var import_react_dom = require("react-dom");
455
+
456
+ // src/hooks/useEscapeDismiss.ts
457
+ var import_react = require("react");
458
+ var nextId = 0;
459
+ var stack = [];
460
+ function insertSorted(entry) {
461
+ let i = 0;
462
+ while (i < stack.length && stack[i].priority >= entry.priority) {
463
+ if (stack[i].priority === entry.priority) break;
464
+ i++;
465
+ }
466
+ stack.splice(i, 0, entry);
467
+ }
468
+ function remove(id) {
469
+ const idx = stack.findIndex((e) => e.id === id);
470
+ if (idx >= 0) stack.splice(idx, 1);
471
+ }
472
+ var listenerInstalled = false;
473
+ function ensureGlobalListener() {
474
+ if (listenerInstalled) return;
475
+ listenerInstalled = true;
476
+ window.addEventListener(
477
+ "keydown",
478
+ (e) => {
479
+ if (e.key !== "Escape") return;
480
+ if (stack.length === 0) return;
481
+ e.preventDefault();
482
+ e.stopImmediatePropagation();
483
+ const top = stack[0];
484
+ top.handler();
485
+ },
486
+ { capture: true }
487
+ );
488
+ }
489
+ function useEscapeDismiss(priority, handler, enabled = true) {
490
+ const handlerRef = (0, import_react.useRef)(handler);
491
+ handlerRef.current = handler;
492
+ (0, import_react.useEffect)(() => {
493
+ if (!enabled) return;
494
+ ensureGlobalListener();
495
+ const id = nextId++;
496
+ const entry = {
497
+ id,
498
+ priority,
499
+ handler: () => handlerRef.current()
500
+ };
501
+ insertSorted(entry);
502
+ return () => remove(id);
503
+ }, [priority, enabled]);
504
+ }
505
+
506
+ // src/components/Modal/Modal.tsx
507
+ var import_jsx_runtime8 = require("react/jsx-runtime");
508
+ 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" }) });
509
+ function Modal({ open, onClose, title, children, danger, warn, footer, noClose, size = "sm", className }) {
510
+ useEscapeDismiss(80, onClose, open && !noClose);
511
+ if (!open) return null;
512
+ const sizeClass = `fractal-modal-panel--${size}`;
513
+ const accentClass = danger ? "fractal-modal-panel--danger" : warn ? "fractal-modal-panel--warn" : "";
514
+ return (0, import_react_dom.createPortal)(
515
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fractal-modal-overlay", onClick: noClose ? void 0 : onClose, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
516
+ "div",
517
+ {
518
+ className: cn("fractal-modal-panel", sizeClass, accentClass, className),
519
+ onClick: (e) => e.stopPropagation(),
520
+ children: [
521
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "fractal-modal-title-row", children: [
522
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: cn("fractal-modal-title", danger && "fractal-modal-title--danger", warn && "fractal-modal-title--warn"), children: title }),
523
+ !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, {}) })
524
+ ] }),
525
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn("fractal-modal-body", size === "lg" && "fractal-modal-body--lg"), children }),
526
+ footer && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fractal-modal-footer", children: footer })
527
+ ]
528
+ }
529
+ ) }),
530
+ document.body
531
+ );
532
+ }
533
+
534
+ // src/components/DataTable/DataTable.tsx
535
+ var import_jsx_runtime9 = require("react/jsx-runtime");
536
+ function DataTable({ columns, data, emptyMessage, header, size = "md", className }) {
537
+ 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: [
538
+ header && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fractal-datatable-header", children: header }),
539
+ 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: [
540
+ /* @__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)) }) }),
541
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
542
+ "tr",
543
+ {
544
+ className: "fractal-datatable-row",
545
+ 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))
546
+ },
547
+ rowIndex
548
+ )) })
549
+ ] })
550
+ ] }) });
551
+ }
552
+
553
+ // src/components/Dropdown/Dropdown.tsx
554
+ var React7 = __toESM(require("react"), 1);
555
+ var import_fractal_icons2 = require("@mirror-physics/fractal-icons");
556
+ var import_jsx_runtime10 = require("react/jsx-runtime");
557
+ var MARGIN = 4;
558
+ function Dropdown({
559
+ items,
560
+ selectedValue,
561
+ onSelect,
562
+ triggerLabel = "Options",
563
+ direction = "down",
564
+ align = "left",
565
+ triggerContent,
566
+ label,
567
+ noChevron = false,
568
+ size = "md",
569
+ triggerVariant = "outline",
570
+ className,
571
+ triggerClassName,
572
+ panelClassName,
573
+ closeOnSelect = true
574
+ }) {
575
+ const [open, setOpen] = React7.useState(false);
576
+ const triggerRef = React7.useRef(null);
577
+ const panelRef = React7.useRef(null);
578
+ const [panelStyle, setPanelStyle] = React7.useState({});
579
+ const visibleItems = items.filter(
580
+ (item) => item.icon != null || item.description != null && (typeof item.description === "string" ? item.description !== "" : true)
581
+ );
582
+ if (visibleItems.length === 0) return null;
583
+ const selectableItems = visibleItems.filter((i) => i.kind !== "header");
584
+ const selected = items.find((i) => i.value === selectedValue && i.kind !== "header") ?? selectableItems[0] ?? visibleItems[0];
585
+ const isUp = direction === "up";
586
+ const ChevronIcon = isUp ? import_fractal_icons2.ChevronUp : import_fractal_icons2.ChevronDown;
587
+ React7.useLayoutEffect(() => {
588
+ if (!open || !triggerRef.current || !panelRef.current) return;
589
+ const triggerRect = triggerRef.current.getBoundingClientRect();
590
+ const panelRect = panelRef.current.getBoundingClientRect();
591
+ const vw = window.innerWidth;
592
+ const vh = window.innerHeight;
593
+ const spaceBelow = vh - triggerRect.bottom - MARGIN;
594
+ const spaceAbove = triggerRect.top - MARGIN;
595
+ let placeAbove = isUp;
596
+ if (placeAbove && panelRect.height > spaceAbove && spaceBelow > spaceAbove) {
597
+ placeAbove = false;
598
+ } else if (!placeAbove && panelRect.height > spaceBelow && spaceAbove > spaceBelow) {
599
+ placeAbove = true;
600
+ }
601
+ const top = placeAbove ? -(panelRect.height + MARGIN) : triggerRect.height + MARGIN;
602
+ let left;
603
+ let right;
604
+ if (align === "right") {
605
+ right = 0;
606
+ const panelLeft = triggerRect.right - panelRect.width;
607
+ if (panelLeft < 0) {
608
+ right = void 0;
609
+ left = 0;
610
+ }
611
+ } else {
612
+ left = 0;
613
+ const panelRight = triggerRect.left + panelRect.width;
614
+ if (panelRight > vw) {
615
+ left = void 0;
616
+ right = 0;
617
+ }
618
+ }
619
+ setPanelStyle({ top, left, right });
620
+ }, [open, isUp, align]);
621
+ React7.useEffect(() => {
622
+ if (!open) return;
623
+ const handleClickOutside = (e) => {
624
+ const target = e.target;
625
+ if (triggerRef.current?.contains(target) || panelRef.current?.contains(target)) return;
626
+ setOpen(false);
627
+ };
628
+ document.addEventListener("mousedown", handleClickOutside);
629
+ return () => document.removeEventListener("mousedown", handleClickOutside);
630
+ }, [open]);
631
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: cn("fractal-dropdown", className), children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
633
+ "button",
634
+ {
635
+ ref: triggerRef,
636
+ type: "button",
637
+ "aria-haspopup": "listbox",
638
+ "aria-expanded": open,
639
+ "aria-label": triggerLabel,
640
+ onClick: () => setOpen((o) => !o),
641
+ className: cn(
642
+ "fractal-dropdown-trigger",
643
+ `fractal-dropdown-trigger--${size}`,
644
+ `fractal-dropdown-trigger--${triggerVariant}`,
645
+ triggerClassName
646
+ ),
647
+ children: [
648
+ triggerContent != null ? triggerContent : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
649
+ selected.icon != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected.icon }),
650
+ selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-selected-text", children: selected.description })
651
+ ] }),
652
+ !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 }) })
653
+ ]
654
+ }
655
+ ),
656
+ open && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
657
+ "div",
658
+ {
659
+ ref: panelRef,
660
+ role: "listbox",
661
+ "aria-label": triggerLabel,
662
+ className: cn("fractal-dropdown-panel", `fractal-dropdown-panel--${size}`, panelClassName),
663
+ style: panelStyle,
664
+ children: [
665
+ label != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-dropdown-label", children: label }),
666
+ visibleItems.map((item, index) => {
667
+ const topDivider = item.border === "top" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
668
+ const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
669
+ if (item.kind === "header") {
670
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(React7.Fragment, { children: [
671
+ topDivider,
672
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
673
+ bottomDivider
674
+ ] }, `header-${index}`);
675
+ }
676
+ const isSelected = item.value === selectedValue;
677
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(React7.Fragment, { children: [
678
+ topDivider,
679
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
680
+ "button",
681
+ {
682
+ type: "button",
683
+ role: "option",
684
+ "aria-selected": isSelected,
685
+ onClick: () => {
686
+ onSelect(item.value);
687
+ if (closeOnSelect) setOpen(false);
688
+ },
689
+ className: "fractal-dropdown-option",
690
+ children: [
691
+ item.icon != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-icon", children: item.icon }),
692
+ item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-option-text", children: item.description }),
693
+ item.trailing != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fractal-dropdown-trailing", children: item.trailing })
694
+ ]
695
+ }
696
+ ),
697
+ bottomDivider
698
+ ] }, item.value);
699
+ })
700
+ ]
701
+ }
702
+ )
703
+ ] });
704
+ }
705
+
706
+ // src/components/Link/Link.tsx
707
+ var React8 = __toESM(require("react"), 1);
708
+ var import_jsx_runtime11 = require("react/jsx-runtime");
709
+ var Link = React8.forwardRef(
710
+ ({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
711
+ "a",
712
+ {
713
+ ref,
714
+ className: cn("fractal-link", `fractal-link--${theme}`, `fractal-link--${size}`, className),
715
+ ...props
716
+ }
717
+ )
718
+ );
719
+ Link.displayName = "Link";
720
+
721
+ // src/components/Chip/Chip.tsx
722
+ var React9 = __toESM(require("react"), 1);
723
+ var import_jsx_runtime12 = require("react/jsx-runtime");
724
+ var Chip = React9.forwardRef(
725
+ ({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
726
+ "span",
727
+ {
728
+ ref,
729
+ className: cn("fractal-chip", `fractal-chip--${tone}`, className),
730
+ ...props
731
+ }
732
+ )
733
+ );
734
+ Chip.displayName = "Chip";
735
+
736
+ // src/components/SortableTable/SortableTable.tsx
737
+ var import_react2 = require("react");
738
+ var import_fractal_icons3 = require("@mirror-physics/fractal-icons");
739
+ var import_jsx_runtime13 = require("react/jsx-runtime");
740
+ function SortableTable({
741
+ columns,
742
+ data,
743
+ emptyMessage,
744
+ header,
745
+ size = "md",
746
+ className,
747
+ defaultSortKey = void 0,
748
+ defaultSortDirection = null,
749
+ sortKey: controlledKey,
750
+ sortDirection: controlledDirection,
751
+ onSortChange,
752
+ highlightRow
753
+ }) {
754
+ const [internalKey, setInternalKey] = (0, import_react2.useState)(defaultSortKey ?? null);
755
+ const [internalDirection, setInternalDirection] = (0, import_react2.useState)(defaultSortDirection);
756
+ const isControlled = controlledKey !== void 0 && controlledDirection !== void 0;
757
+ const activeKey = isControlled ? controlledKey : internalKey;
758
+ const activeDirection = isControlled ? controlledDirection : internalDirection;
759
+ const sorted = (0, import_react2.useMemo)(() => {
760
+ if (!activeKey || !activeDirection) return data;
761
+ const col = columns.find((c) => c.key === activeKey);
762
+ if (!col) return data;
763
+ const accessor = col.sortAccessor ?? ((row) => {
764
+ const value = row[activeKey];
765
+ return typeof value === "string" || typeof value === "number" ? value : null;
766
+ });
767
+ const copy = [...data];
768
+ copy.sort((a, b) => {
769
+ const av = accessor(a);
770
+ const bv = accessor(b);
771
+ if (av == null && bv == null) return 0;
772
+ if (av == null) return 1;
773
+ if (bv == null) return -1;
774
+ if (typeof av === "number" && typeof bv === "number") {
775
+ return activeDirection === "asc" ? av - bv : bv - av;
776
+ }
777
+ const as = String(av).toLowerCase();
778
+ const bs = String(bv).toLowerCase();
779
+ if (as < bs) return activeDirection === "asc" ? -1 : 1;
780
+ if (as > bs) return activeDirection === "asc" ? 1 : -1;
781
+ return 0;
782
+ });
783
+ return copy;
784
+ }, [data, columns, activeKey, activeDirection]);
785
+ const handleSortClick = (key) => {
786
+ let nextDirection;
787
+ if (activeKey !== key) {
788
+ nextDirection = "asc";
789
+ } else if (activeDirection === "asc") {
790
+ nextDirection = "desc";
791
+ } else if (activeDirection === "desc") {
792
+ nextDirection = null;
793
+ } else {
794
+ nextDirection = "asc";
795
+ }
796
+ const nextKey = nextDirection === null ? null : key;
797
+ if (isControlled) {
798
+ onSortChange?.(nextKey, nextDirection);
799
+ } else {
800
+ setInternalKey(nextKey);
801
+ setInternalDirection(nextDirection);
802
+ onSortChange?.(nextKey, nextDirection);
803
+ }
804
+ };
805
+ 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: [
806
+ header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fractal-sortable-table-header", children: header }),
807
+ 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: [
808
+ /* @__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) => {
809
+ const isActive = activeKey === col.key && activeDirection !== null;
810
+ if (!col.sortable) {
811
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
812
+ "th",
813
+ {
814
+ className: "fractal-sortable-table-th",
815
+ style: { width: col.width },
816
+ children: col.header
817
+ },
818
+ col.key
819
+ );
820
+ }
821
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
822
+ "th",
823
+ {
824
+ className: "fractal-sortable-table-th fractal-sortable-table-th--sortable",
825
+ style: { width: col.width },
826
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
827
+ "button",
828
+ {
829
+ type: "button",
830
+ className: cn(
831
+ "fractal-sortable-table-sort-button",
832
+ isActive && "fractal-sortable-table-sort-button--active"
833
+ ),
834
+ onClick: () => handleSortClick(col.key),
835
+ "aria-sort": isActive ? activeDirection === "asc" ? "ascending" : "descending" : "none",
836
+ children: [
837
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: col.header }),
838
+ /* @__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 }) })
839
+ ]
840
+ }
841
+ )
842
+ },
843
+ col.key
844
+ );
845
+ }) }) }),
846
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: sorted.map((row, rowIndex) => {
847
+ const highlighted = highlightRow?.(row, rowIndex) ?? false;
848
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
849
+ "tr",
850
+ {
851
+ className: cn(
852
+ "fractal-sortable-table-row",
853
+ highlighted && "fractal-sortable-table-row--highlighted"
854
+ ),
855
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
856
+ "td",
857
+ {
858
+ className: "fractal-sortable-table-td",
859
+ style: { width: col.width, textAlign: col.align ?? "left" },
860
+ children: col.render(row, rowIndex)
861
+ },
862
+ col.key
863
+ ))
864
+ },
865
+ rowIndex
866
+ );
867
+ }) })
868
+ ] })
869
+ ] }) });
870
+ }
871
+
872
+ // src/components/Tabs/Tabs.tsx
873
+ var import_react3 = require("react");
874
+ var import_jsx_runtime14 = require("react/jsx-runtime");
875
+ function Tabs({
876
+ items,
877
+ defaultValue,
878
+ value: controlledValue,
879
+ onValueChange,
880
+ className,
881
+ ariaLabel
882
+ }) {
883
+ const reactId = (0, import_react3.useId)();
884
+ const [internalValue, setInternalValue] = (0, import_react3.useState)(
885
+ defaultValue ?? items.find((i) => !i.disabled)?.id ?? items[0]?.id ?? ""
886
+ );
887
+ const isControlled = controlledValue !== void 0;
888
+ const activeId = isControlled ? controlledValue : internalValue;
889
+ const tabRefs = (0, import_react3.useRef)({});
890
+ const selectTab = (id) => {
891
+ if (isControlled) {
892
+ onValueChange?.(id);
893
+ } else {
894
+ setInternalValue(id);
895
+ onValueChange?.(id);
896
+ }
897
+ };
898
+ const focusable = items.filter((i) => !i.disabled);
899
+ const onKeyDown = (event) => {
900
+ const currentIndex = focusable.findIndex((i) => i.id === activeId);
901
+ if (currentIndex === -1) return;
902
+ let nextIndex = currentIndex;
903
+ switch (event.key) {
904
+ case "ArrowRight":
905
+ nextIndex = (currentIndex + 1) % focusable.length;
906
+ break;
907
+ case "ArrowLeft":
908
+ nextIndex = (currentIndex - 1 + focusable.length) % focusable.length;
909
+ break;
910
+ case "Home":
911
+ nextIndex = 0;
912
+ break;
913
+ case "End":
914
+ nextIndex = focusable.length - 1;
915
+ break;
916
+ default:
917
+ return;
918
+ }
919
+ event.preventDefault();
920
+ const nextId2 = focusable[nextIndex].id;
921
+ selectTab(nextId2);
922
+ requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
923
+ };
924
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("fractal-tabs", className), children: [
925
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "tablist", "aria-label": ariaLabel, className: "fractal-tabs-list", children: items.map((item) => {
926
+ const isActive = item.id === activeId;
927
+ const tabId = `${reactId}-tab-${item.id}`;
928
+ const panelId = `${reactId}-panel-${item.id}`;
929
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
930
+ "button",
931
+ {
932
+ ref: (el) => {
933
+ tabRefs.current[item.id] = el;
934
+ },
935
+ id: tabId,
936
+ role: "tab",
937
+ type: "button",
938
+ "aria-selected": isActive,
939
+ "aria-controls": panelId,
940
+ tabIndex: isActive ? 0 : -1,
941
+ disabled: item.disabled,
942
+ className: cn(
943
+ "fractal-tabs-trigger",
944
+ isActive && "fractal-tabs-trigger--active",
945
+ item.disabled && "fractal-tabs-trigger--disabled"
946
+ ),
947
+ onClick: () => !item.disabled && selectTab(item.id),
948
+ onKeyDown,
949
+ children: item.label
950
+ },
951
+ item.id
952
+ );
953
+ }) }),
954
+ items.map((item) => {
955
+ const tabId = `${reactId}-tab-${item.id}`;
956
+ const panelId = `${reactId}-panel-${item.id}`;
957
+ const isActive = item.id === activeId;
958
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
959
+ "div",
960
+ {
961
+ id: panelId,
962
+ role: "tabpanel",
963
+ "aria-labelledby": tabId,
964
+ hidden: !isActive,
965
+ className: "fractal-tabs-panel",
966
+ children: isActive && item.content
967
+ },
968
+ item.id
969
+ );
970
+ })
971
+ ] });
972
+ }
973
+
974
+ // src/components/Disclosure/Disclosure.tsx
975
+ var import_react4 = require("react");
976
+ var import_fractal_icons4 = require("@mirror-physics/fractal-icons");
977
+ var import_jsx_runtime15 = require("react/jsx-runtime");
978
+ function Disclosure({
979
+ title,
980
+ meta,
981
+ children,
982
+ defaultOpen = false,
983
+ open: controlledOpen,
984
+ onOpenChange,
985
+ className,
986
+ variant = "card"
987
+ }) {
988
+ const reactId = (0, import_react4.useId)();
989
+ const headerId = `${reactId}-header`;
990
+ const panelId = `${reactId}-panel`;
991
+ const [internalOpen, setInternalOpen] = (0, import_react4.useState)(defaultOpen);
992
+ const isControlled = controlledOpen !== void 0;
993
+ const isOpen = isControlled ? controlledOpen : internalOpen;
994
+ const toggle = () => {
995
+ const next = !isOpen;
996
+ if (isControlled) {
997
+ onOpenChange?.(next);
998
+ } else {
999
+ setInternalOpen(next);
1000
+ onOpenChange?.(next);
1001
+ }
1002
+ };
1003
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1004
+ "div",
1005
+ {
1006
+ className: cn(
1007
+ "fractal-disclosure",
1008
+ variant === "card" && "fractal-disclosure--card",
1009
+ isOpen && "fractal-disclosure--open",
1010
+ className
1011
+ ),
1012
+ children: [
1013
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1014
+ "button",
1015
+ {
1016
+ type: "button",
1017
+ id: headerId,
1018
+ className: "fractal-disclosure-trigger",
1019
+ "aria-expanded": isOpen,
1020
+ "aria-controls": panelId,
1021
+ onClick: toggle,
1022
+ children: [
1023
+ /* @__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 }) }),
1024
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-title", children: title }),
1025
+ meta && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fractal-disclosure-meta", children: meta })
1026
+ ]
1027
+ }
1028
+ ),
1029
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1030
+ "div",
1031
+ {
1032
+ id: panelId,
1033
+ role: "region",
1034
+ "aria-labelledby": headerId,
1035
+ className: "fractal-disclosure-panel",
1036
+ hidden: !isOpen,
1037
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "fractal-disclosure-panel-inner", children })
1038
+ }
1039
+ )
1040
+ ]
1041
+ }
1042
+ );
1043
+ }
1044
+
1045
+ // src/components/Sidebar/Sidebar.tsx
1046
+ var React10 = __toESM(require("react"), 1);
1047
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1048
+ var Sidebar = React10.forwardRef(
1049
+ ({ className, width, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1050
+ "aside",
1051
+ {
1052
+ ref,
1053
+ className: cn("fractal-sidebar", className),
1054
+ style: { ...style, ...width ? { "--fractal-sidebar-width": width } : {} },
1055
+ ...props
1056
+ }
1057
+ )
1058
+ );
1059
+ Sidebar.displayName = "Sidebar";
1060
+ var SidebarHeader = React10.forwardRef(
1061
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
1062
+ );
1063
+ SidebarHeader.displayName = "SidebarHeader";
1064
+ var SidebarBrand = React10.forwardRef(
1065
+ ({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
1066
+ );
1067
+ SidebarBrand.displayName = "SidebarBrand";
1068
+ var SidebarNav = React10.forwardRef(
1069
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
1070
+ );
1071
+ SidebarNav.displayName = "SidebarNav";
1072
+ var SidebarSection = React10.forwardRef(
1073
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
1074
+ );
1075
+ SidebarSection.displayName = "SidebarSection";
1076
+ var SidebarNavItem = React10.forwardRef(
1077
+ ({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1078
+ "button",
1079
+ {
1080
+ ref,
1081
+ type,
1082
+ className: cn("fractal-sidebar__nav-item", className),
1083
+ "data-active": active || void 0,
1084
+ "aria-current": active ? "page" : void 0,
1085
+ ...props,
1086
+ children: [
1087
+ icon && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
1088
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-label", children }),
1089
+ endAdornment && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
1090
+ ]
1091
+ }
1092
+ )
1093
+ );
1094
+ SidebarNavItem.displayName = "SidebarNavItem";
1095
+ var SidebarFooter = React10.forwardRef(
1096
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
1097
+ );
1098
+ SidebarFooter.displayName = "SidebarFooter";
1099
+ // Annotate the CommonJS export names for ESM import in node:
1100
+ 0 && (module.exports = {
1101
+ Alert,
1102
+ AlertDescription,
1103
+ AlertTitle,
1104
+ Button,
1105
+ Card,
1106
+ CardContent,
1107
+ CardDescription,
1108
+ CardFooter,
1109
+ CardHeader,
1110
+ CardTitle,
1111
+ Chip,
1112
+ DataTable,
1113
+ Disclosure,
1114
+ Dropdown,
1115
+ FeatureCard,
1116
+ FolderCard,
1117
+ Input,
1118
+ Label,
1119
+ Link,
1120
+ Modal,
1121
+ PromptCard,
1122
+ PromptGrid,
1123
+ Sidebar,
1124
+ SidebarBrand,
1125
+ SidebarFooter,
1126
+ SidebarHeader,
1127
+ SidebarNav,
1128
+ SidebarNavItem,
1129
+ SidebarSection,
1130
+ SortableTable,
1131
+ Tabs,
1132
+ Toggle,
1133
+ cn,
1134
+ useEscapeDismiss
1135
+ });
1136
+ //# sourceMappingURL=index.cjs.map