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