@mirror-physics/fractal-ui 0.2.0-next.5 → 0.2.0-next.50
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 +1316 -246
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1345 -105
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +273 -20
- package/dist/index.d.ts +273 -20
- package/dist/index.js +1273 -240
- package/dist/index.js.map +1 -1
- package/dist/lattice-FAYE5KWW.svg +3 -0
- package/dist/tokens.css +5 -3
- package/package.json +7 -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,251 @@ var Button = React.forwardRef(
|
|
|
165
165
|
);
|
|
166
166
|
Button.displayName = "Button";
|
|
167
167
|
|
|
168
|
+
// src/components/CodeBlock/CodeBlock.tsx
|
|
169
|
+
import { useEffect, useMemo, useRef, useState as useState2 } from "react";
|
|
170
|
+
import CodeMirror from "@uiw/react-codemirror";
|
|
171
|
+
import { HighlightStyle, foldGutter, syntaxHighlighting } from "@codemirror/language";
|
|
172
|
+
import { json } from "@codemirror/lang-json";
|
|
173
|
+
import { EditorView, lineNumbers as lineNumberGutter } from "@codemirror/view";
|
|
174
|
+
import { tags } from "@lezer/highlight";
|
|
175
|
+
import { Check, Copy } from "@mirror-physics/fractal-icons";
|
|
176
|
+
import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
177
|
+
var codeTheme = EditorView.theme({
|
|
178
|
+
"&": {
|
|
179
|
+
backgroundColor: "transparent",
|
|
180
|
+
color: "var(--fg-primary)",
|
|
181
|
+
fontSize: "0.75rem"
|
|
182
|
+
},
|
|
183
|
+
"&.cm-focused": { outline: "none" },
|
|
184
|
+
".cm-scroller": {
|
|
185
|
+
fontFamily: "var(--font-mono)",
|
|
186
|
+
lineHeight: "1.55",
|
|
187
|
+
overscrollBehavior: "contain"
|
|
188
|
+
},
|
|
189
|
+
".cm-content": { padding: "10px 0" },
|
|
190
|
+
".cm-line": { padding: "0 12px" },
|
|
191
|
+
".cm-cursor, .cm-dropCursor": { borderLeftColor: "var(--fg-primary)" },
|
|
192
|
+
".cm-gutters": {
|
|
193
|
+
backgroundColor: "var(--bg-canvas)",
|
|
194
|
+
borderRight: "1px solid var(--border-subtle)",
|
|
195
|
+
color: "var(--fg-tertiary)"
|
|
196
|
+
},
|
|
197
|
+
".cm-lineNumbers .cm-gutterElement": { padding: "0 10px 0 12px" },
|
|
198
|
+
".cm-foldGutter .cm-gutterElement": { padding: "0 8px 0 2px" },
|
|
199
|
+
".cm-activeLine, .cm-activeLineGutter": { backgroundColor: "var(--bg-surface-1)" },
|
|
200
|
+
".cm-selectionBackground, &.cm-focused .cm-selectionBackground, ::selection": {
|
|
201
|
+
backgroundColor: "var(--accent-surface-stroke) !important"
|
|
202
|
+
},
|
|
203
|
+
".cm-searchMatch": {
|
|
204
|
+
backgroundColor: "var(--warning-surface)",
|
|
205
|
+
outline: "1px solid var(--warning-surface-stroke)"
|
|
206
|
+
},
|
|
207
|
+
".cm-searchMatch.cm-searchMatch-selected": { backgroundColor: "var(--warning-subtle)" },
|
|
208
|
+
".cm-panels": { backgroundColor: "var(--bg-surface-1)", color: "var(--fg-primary)" },
|
|
209
|
+
".cm-tooltip": {
|
|
210
|
+
borderColor: "var(--border-subtle)",
|
|
211
|
+
backgroundColor: "var(--bg-canvas)",
|
|
212
|
+
color: "var(--fg-primary)"
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
var fractalHighlightStyle = HighlightStyle.define([
|
|
216
|
+
{ tag: tags.comment, color: "var(--fg-tertiary)", fontStyle: "italic" },
|
|
217
|
+
{ tag: [tags.keyword, tags.controlKeyword, tags.operatorKeyword], color: "var(--purple-default)" },
|
|
218
|
+
{ tag: [tags.string, tags.special(tags.string)], color: "var(--purple-default)" },
|
|
219
|
+
{ tag: [tags.number, tags.bool, tags.null], color: "var(--orange-default)" },
|
|
220
|
+
{ tag: [tags.function(tags.variableName), tags.labelName], color: "var(--accent-default)" },
|
|
221
|
+
{ tag: [tags.typeName, tags.className, tags.namespace], color: "var(--pink-default)" },
|
|
222
|
+
{ tag: [tags.propertyName, tags.attributeName], color: "var(--success-default)" },
|
|
223
|
+
{ tag: [tags.operator, tags.punctuation], color: "var(--fg-secondary)" },
|
|
224
|
+
{ tag: tags.bracket, color: "var(--accent-default)" },
|
|
225
|
+
{ tag: [tags.heading, tags.strong], color: "var(--fg-primary)", fontWeight: "600" },
|
|
226
|
+
{ tag: tags.emphasis, fontStyle: "italic" },
|
|
227
|
+
{ tag: tags.link, color: "var(--accent-default)", textDecoration: "underline" },
|
|
228
|
+
{ tag: tags.invalid, color: "var(--error-default)", textDecoration: "underline wavy" }
|
|
229
|
+
]);
|
|
230
|
+
var jsonSupport = json();
|
|
231
|
+
var JSON_LANGUAGE_NAMES = /* @__PURE__ */ new Set(["json", "jsonl", "ndjson", "geojson"]);
|
|
232
|
+
function resolveLanguage(language, fileName) {
|
|
233
|
+
const normalized = language?.trim().toLowerCase();
|
|
234
|
+
const extension = fileName?.split(/[?#]/, 1)[0].split(".").pop()?.toLowerCase();
|
|
235
|
+
if (normalized && JSON_LANGUAGE_NAMES.has(normalized) || extension && JSON_LANGUAGE_NAMES.has(extension)) {
|
|
236
|
+
return { label: normalized === "jsonl" || extension === "jsonl" ? "JSONL" : "JSON", support: jsonSupport };
|
|
237
|
+
}
|
|
238
|
+
if (normalized && !["text", "txt", "plaintext", "plain"].includes(normalized)) {
|
|
239
|
+
return { label: language?.trim(), support: null };
|
|
240
|
+
}
|
|
241
|
+
return { support: null };
|
|
242
|
+
}
|
|
243
|
+
function CodeBlock({
|
|
244
|
+
value,
|
|
245
|
+
language,
|
|
246
|
+
fileName,
|
|
247
|
+
label,
|
|
248
|
+
editable = false,
|
|
249
|
+
onChange,
|
|
250
|
+
lineNumbers = true,
|
|
251
|
+
wrap = true,
|
|
252
|
+
copyable = true,
|
|
253
|
+
ariaLabel,
|
|
254
|
+
height,
|
|
255
|
+
minHeight,
|
|
256
|
+
maxHeight = "28rem",
|
|
257
|
+
placeholder,
|
|
258
|
+
autoFocus,
|
|
259
|
+
className,
|
|
260
|
+
...props
|
|
261
|
+
}) {
|
|
262
|
+
const resolvedLanguage = useMemo(() => resolveLanguage(language, fileName), [fileName, language]);
|
|
263
|
+
const [copyStatus, setCopyStatus] = useState2("idle");
|
|
264
|
+
const copyResetTimer = useRef(null);
|
|
265
|
+
useEffect(() => () => {
|
|
266
|
+
if (copyResetTimer.current) clearTimeout(copyResetTimer.current);
|
|
267
|
+
}, []);
|
|
268
|
+
const extensions = useMemo(() => [
|
|
269
|
+
codeTheme,
|
|
270
|
+
syntaxHighlighting(fractalHighlightStyle),
|
|
271
|
+
...resolvedLanguage.support ? [resolvedLanguage.support] : [],
|
|
272
|
+
...lineNumbers ? [foldGutter(), lineNumberGutter()] : [],
|
|
273
|
+
...wrap ? [EditorView.lineWrapping] : []
|
|
274
|
+
], [lineNumbers, resolvedLanguage.support, wrap]);
|
|
275
|
+
const languageLabel = resolvedLanguage.label;
|
|
276
|
+
const toolbarLabel = label ?? fileName ?? languageLabel;
|
|
277
|
+
const surfaceLabel = ariaLabel ?? (fileName ? `${fileName} ${editable ? "editor" : "viewer"}` : `Code ${editable ? "editor" : "viewer"}`);
|
|
278
|
+
const copyCode = async () => {
|
|
279
|
+
try {
|
|
280
|
+
await navigator.clipboard.writeText(value);
|
|
281
|
+
setCopyStatus("copied");
|
|
282
|
+
} catch {
|
|
283
|
+
setCopyStatus("error");
|
|
284
|
+
}
|
|
285
|
+
if (copyResetTimer.current) clearTimeout(copyResetTimer.current);
|
|
286
|
+
copyResetTimer.current = setTimeout(() => setCopyStatus("idle"), 1800);
|
|
287
|
+
};
|
|
288
|
+
const showToolbar = toolbarLabel !== void 0 || copyable || editable;
|
|
289
|
+
return /* @__PURE__ */ jsxs2(
|
|
290
|
+
"div",
|
|
291
|
+
{
|
|
292
|
+
className: cn(
|
|
293
|
+
"fractal-code-block",
|
|
294
|
+
editable && "fractal-code-block--editable",
|
|
295
|
+
!lineNumbers && "fractal-code-block--no-line-numbers",
|
|
296
|
+
className
|
|
297
|
+
),
|
|
298
|
+
...props,
|
|
299
|
+
children: [
|
|
300
|
+
showToolbar && /* @__PURE__ */ jsxs2("div", { className: "fractal-code-block__toolbar", children: [
|
|
301
|
+
/* @__PURE__ */ jsxs2("div", { className: "fractal-code-block__identity", children: [
|
|
302
|
+
toolbarLabel !== void 0 && /* @__PURE__ */ jsx("span", { className: "fractal-code-block__label", title: typeof toolbarLabel === "string" ? toolbarLabel : void 0, children: toolbarLabel }),
|
|
303
|
+
fileName && languageLabel && /* @__PURE__ */ jsx("span", { className: "fractal-code-block__language", children: languageLabel }),
|
|
304
|
+
editable && /* @__PURE__ */ jsx("span", { className: "fractal-code-block__mode", children: "Editing" })
|
|
305
|
+
] }),
|
|
306
|
+
copyable && /* @__PURE__ */ jsxs2(
|
|
307
|
+
"button",
|
|
308
|
+
{
|
|
309
|
+
type: "button",
|
|
310
|
+
className: "fractal-code-block__copy",
|
|
311
|
+
"aria-label": copyStatus === "copied" ? "Code copied" : "Copy code",
|
|
312
|
+
onClick: () => void copyCode(),
|
|
313
|
+
children: [
|
|
314
|
+
copyStatus === "copied" ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 }),
|
|
315
|
+
/* @__PURE__ */ jsx("span", { children: copyStatus === "copied" ? "Copied" : copyStatus === "error" ? "Copy failed" : "Copy" })
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
] }),
|
|
320
|
+
/* @__PURE__ */ jsx("div", { className: "fractal-code-block__surface", children: /* @__PURE__ */ jsx(
|
|
321
|
+
CodeMirror,
|
|
322
|
+
{
|
|
323
|
+
"aria-label": surfaceLabel,
|
|
324
|
+
value,
|
|
325
|
+
editable,
|
|
326
|
+
readOnly: !editable,
|
|
327
|
+
onChange,
|
|
328
|
+
extensions,
|
|
329
|
+
theme: "none",
|
|
330
|
+
basicSetup: {
|
|
331
|
+
lineNumbers: false,
|
|
332
|
+
foldGutter: false,
|
|
333
|
+
drawSelection: editable,
|
|
334
|
+
highlightActiveLine: editable,
|
|
335
|
+
highlightActiveLineGutter: editable,
|
|
336
|
+
highlightSelectionMatches: editable,
|
|
337
|
+
autocompletion: editable,
|
|
338
|
+
history: editable
|
|
339
|
+
},
|
|
340
|
+
indentWithTab: editable,
|
|
341
|
+
height,
|
|
342
|
+
minHeight,
|
|
343
|
+
maxHeight,
|
|
344
|
+
placeholder,
|
|
345
|
+
autoFocus
|
|
346
|
+
}
|
|
347
|
+
) }),
|
|
348
|
+
/* @__PURE__ */ jsx("span", { className: "fractal-code-block__status", "aria-live": "polite", children: copyStatus === "copied" ? "Code copied to clipboard." : copyStatus === "error" ? "Code could not be copied." : "" })
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// src/components/Breadcrumbs/Breadcrumbs.tsx
|
|
355
|
+
import { ChevronRight } from "@mirror-physics/fractal-icons";
|
|
356
|
+
import { jsx as jsx2, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
357
|
+
function Breadcrumbs({
|
|
358
|
+
items,
|
|
359
|
+
ariaLabel = "Breadcrumbs",
|
|
360
|
+
separator = /* @__PURE__ */ jsx2(ChevronRight, { "aria-hidden": "true", size: 14 }),
|
|
361
|
+
className,
|
|
362
|
+
...props
|
|
363
|
+
}) {
|
|
364
|
+
if (items.length === 0) return null;
|
|
365
|
+
return /* @__PURE__ */ jsx2("nav", { "aria-label": ariaLabel, className: cn("fractal-breadcrumbs", className), ...props, children: /* @__PURE__ */ jsx2("ol", { className: "fractal-breadcrumbs__list", children: items.map((item, index) => {
|
|
366
|
+
const isCurrent = index === items.length - 1;
|
|
367
|
+
const content = isCurrent ? /* @__PURE__ */ jsx2("span", { "aria-current": "page", className: "fractal-breadcrumbs__current", children: item.label }) : /* @__PURE__ */ jsx2("a", { className: "fractal-breadcrumbs__link", href: item.href ?? "#", onClick: item.onClick, children: item.label });
|
|
368
|
+
return /* @__PURE__ */ jsxs3("li", { className: "fractal-breadcrumbs__item", children: [
|
|
369
|
+
index > 0 && /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", className: "fractal-breadcrumbs__separator", children: separator }),
|
|
370
|
+
content
|
|
371
|
+
] }, index);
|
|
372
|
+
}) }) });
|
|
373
|
+
}
|
|
374
|
+
|
|
168
375
|
// src/components/Card/Card.tsx
|
|
169
376
|
import * as React2 from "react";
|
|
170
377
|
import { Folder as FolderIcon } from "@mirror-physics/fractal-icons";
|
|
171
|
-
import { jsx, jsxs as
|
|
378
|
+
import { jsx as jsx3, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
172
379
|
var Card = React2.forwardRef(
|
|
173
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
380
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3("div", { ref, className: cn("fractal-card", className), ...props })
|
|
174
381
|
);
|
|
175
382
|
Card.displayName = "Card";
|
|
176
383
|
var CardHeader = React2.forwardRef(
|
|
177
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
384
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3("div", { ref, className: cn("fractal-card-header", className), ...props })
|
|
178
385
|
);
|
|
179
386
|
CardHeader.displayName = "CardHeader";
|
|
180
387
|
var CardTitle = React2.forwardRef(
|
|
181
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
388
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3("h3", { ref, className: cn("fractal-card-title", className), ...props })
|
|
182
389
|
);
|
|
183
390
|
CardTitle.displayName = "CardTitle";
|
|
184
391
|
var CardDescription = React2.forwardRef(
|
|
185
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
392
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3("p", { ref, className: cn("fractal-card-description", className), ...props })
|
|
186
393
|
);
|
|
187
394
|
CardDescription.displayName = "CardDescription";
|
|
188
395
|
var CardContent = React2.forwardRef(
|
|
189
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
396
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3("div", { ref, className: cn("fractal-card-content", className), ...props })
|
|
190
397
|
);
|
|
191
398
|
CardContent.displayName = "CardContent";
|
|
192
399
|
var CardFooter = React2.forwardRef(
|
|
193
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
400
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3("div", { ref, className: cn("fractal-card-footer", className), ...props })
|
|
194
401
|
);
|
|
195
402
|
CardFooter.displayName = "CardFooter";
|
|
196
403
|
var FeatureCard = React2.forwardRef(
|
|
197
|
-
({ icon, title, description, className, ...props }, ref) => /* @__PURE__ */
|
|
198
|
-
icon && /* @__PURE__ */
|
|
199
|
-
/* @__PURE__ */
|
|
200
|
-
/* @__PURE__ */
|
|
404
|
+
({ icon, title, description, className, ...props }, ref) => /* @__PURE__ */ jsxs4("div", { ref, className: cn("fractal-feature-card", className), ...props, children: [
|
|
405
|
+
icon && /* @__PURE__ */ jsx3("div", { className: "fractal-feature-card__icon", children: icon }),
|
|
406
|
+
/* @__PURE__ */ jsx3("h3", { className: "fractal-feature-card__title", children: title }),
|
|
407
|
+
/* @__PURE__ */ jsx3("p", { className: "fractal-feature-card__description", children: description })
|
|
201
408
|
] })
|
|
202
409
|
);
|
|
203
410
|
FeatureCard.displayName = "FeatureCard";
|
|
204
411
|
var FolderCard = React2.forwardRef(
|
|
205
|
-
({ name, sessionCount, selected, className, onClick, ...props }, ref) => /* @__PURE__ */
|
|
412
|
+
({ name, sessionCount, selected, className, onClick, ...props }, ref) => /* @__PURE__ */ jsxs4(
|
|
206
413
|
"div",
|
|
207
414
|
{
|
|
208
415
|
ref,
|
|
@@ -218,11 +425,11 @@ var FolderCard = React2.forwardRef(
|
|
|
218
425
|
className: cn("fractal-folder-card", selected && "fractal-folder-card--selected", className),
|
|
219
426
|
...props,
|
|
220
427
|
children: [
|
|
221
|
-
/* @__PURE__ */
|
|
222
|
-
/* @__PURE__ */
|
|
223
|
-
/* @__PURE__ */
|
|
428
|
+
/* @__PURE__ */ jsxs4("div", { className: "fractal-folder-card__header", children: [
|
|
429
|
+
/* @__PURE__ */ jsx3(FolderIcon, { size: 16, className: "fractal-folder-card__icon", "aria-hidden": true }),
|
|
430
|
+
/* @__PURE__ */ jsx3("span", { className: "fractal-folder-card__name", children: name })
|
|
224
431
|
] }),
|
|
225
|
-
sessionCount !== void 0 && /* @__PURE__ */
|
|
432
|
+
sessionCount !== void 0 && /* @__PURE__ */ jsx3("div", { className: "fractal-folder-card__footer", children: /* @__PURE__ */ jsxs4("span", { className: "fractal-folder-card__sessions", children: [
|
|
226
433
|
sessionCount,
|
|
227
434
|
" ",
|
|
228
435
|
sessionCount === 1 ? "session" : "sessions"
|
|
@@ -235,7 +442,7 @@ FolderCard.displayName = "FolderCard";
|
|
|
235
442
|
|
|
236
443
|
// src/components/PromptCard/PromptCard.tsx
|
|
237
444
|
import * as React3 from "react";
|
|
238
|
-
import { jsx as
|
|
445
|
+
import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
239
446
|
var titleToPrompt = (title) => typeof title === "string" || typeof title === "number" ? String(title) : "";
|
|
240
447
|
var PromptCard = React3.forwardRef(
|
|
241
448
|
({
|
|
@@ -256,7 +463,7 @@ var PromptCard = React3.forwardRef(
|
|
|
256
463
|
onPromptSelect?.(prompt ?? titleToPrompt(title));
|
|
257
464
|
}
|
|
258
465
|
};
|
|
259
|
-
return /* @__PURE__ */
|
|
466
|
+
return /* @__PURE__ */ jsxs5(
|
|
260
467
|
"button",
|
|
261
468
|
{
|
|
262
469
|
ref,
|
|
@@ -271,8 +478,8 @@ var PromptCard = React3.forwardRef(
|
|
|
271
478
|
onClick: handleClick,
|
|
272
479
|
...props,
|
|
273
480
|
children: [
|
|
274
|
-
icon && /* @__PURE__ */
|
|
275
|
-
/* @__PURE__ */
|
|
481
|
+
icon && /* @__PURE__ */ jsx4("span", { className: "fractal-prompt-card__icon", "aria-hidden": "true", children: icon }),
|
|
482
|
+
/* @__PURE__ */ jsx4("span", { className: "fractal-prompt-card__title", children: title })
|
|
276
483
|
]
|
|
277
484
|
}
|
|
278
485
|
);
|
|
@@ -280,7 +487,7 @@ var PromptCard = React3.forwardRef(
|
|
|
280
487
|
);
|
|
281
488
|
PromptCard.displayName = "PromptCard";
|
|
282
489
|
var PromptGrid = React3.forwardRef(
|
|
283
|
-
({ compact, padded, className, ...props }, ref) => /* @__PURE__ */
|
|
490
|
+
({ compact, padded, className, ...props }, ref) => /* @__PURE__ */ jsx4(
|
|
284
491
|
"div",
|
|
285
492
|
{
|
|
286
493
|
ref,
|
|
@@ -298,9 +505,9 @@ PromptGrid.displayName = "PromptGrid";
|
|
|
298
505
|
|
|
299
506
|
// src/components/Input/Input.tsx
|
|
300
507
|
import * as React4 from "react";
|
|
301
|
-
import { jsx as
|
|
508
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
302
509
|
var Input = React4.forwardRef(
|
|
303
|
-
({ className, type, ...props }, ref) => /* @__PURE__ */
|
|
510
|
+
({ className, type, ...props }, ref) => /* @__PURE__ */ jsx5(
|
|
304
511
|
"input",
|
|
305
512
|
{
|
|
306
513
|
type,
|
|
@@ -312,11 +519,141 @@ var Input = React4.forwardRef(
|
|
|
312
519
|
);
|
|
313
520
|
Input.displayName = "Input";
|
|
314
521
|
|
|
315
|
-
// src/components/
|
|
522
|
+
// src/components/NumberInput/NumberInput.tsx
|
|
316
523
|
import * as React5 from "react";
|
|
317
|
-
import {
|
|
318
|
-
|
|
319
|
-
|
|
524
|
+
import { Minus, Plus } from "@mirror-physics/fractal-icons";
|
|
525
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
526
|
+
function NumberInput({
|
|
527
|
+
unit,
|
|
528
|
+
className,
|
|
529
|
+
value,
|
|
530
|
+
defaultValue,
|
|
531
|
+
disabled,
|
|
532
|
+
readOnly,
|
|
533
|
+
min,
|
|
534
|
+
max,
|
|
535
|
+
...props
|
|
536
|
+
}) {
|
|
537
|
+
const inputRef = React5.useRef(null);
|
|
538
|
+
const numericValue = Number(value ?? defaultValue);
|
|
539
|
+
const characterCount = Math.max(String(value ?? defaultValue ?? "").length, 1);
|
|
540
|
+
const controlLabel = typeof props["aria-label"] === "string" ? props["aria-label"] : "value";
|
|
541
|
+
const decrementDisabled = disabled || readOnly || Number.isFinite(numericValue) && min !== void 0 && numericValue <= Number(min);
|
|
542
|
+
const incrementDisabled = disabled || readOnly || Number.isFinite(numericValue) && max !== void 0 && numericValue >= Number(max);
|
|
543
|
+
const changeByStep = (direction) => {
|
|
544
|
+
const input = inputRef.current;
|
|
545
|
+
if (!input) return;
|
|
546
|
+
if (direction === -1) input.stepDown();
|
|
547
|
+
else input.stepUp();
|
|
548
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
549
|
+
input.focus();
|
|
550
|
+
};
|
|
551
|
+
return /* @__PURE__ */ jsxs6("div", { className: cn("fractal-number-input", unit && "fractal-number-input--with-unit", className), children: [
|
|
552
|
+
/* @__PURE__ */ jsx6(
|
|
553
|
+
Input,
|
|
554
|
+
{
|
|
555
|
+
ref: inputRef,
|
|
556
|
+
type: "number",
|
|
557
|
+
value,
|
|
558
|
+
defaultValue,
|
|
559
|
+
disabled,
|
|
560
|
+
readOnly,
|
|
561
|
+
min,
|
|
562
|
+
max,
|
|
563
|
+
...props
|
|
564
|
+
}
|
|
565
|
+
),
|
|
566
|
+
unit && /* @__PURE__ */ jsx6(
|
|
567
|
+
"span",
|
|
568
|
+
{
|
|
569
|
+
className: "fractal-number-input-unit",
|
|
570
|
+
style: { left: `calc(var(--space-3, 12px) + ${characterCount}ch)` },
|
|
571
|
+
"aria-hidden": "true",
|
|
572
|
+
children: unit
|
|
573
|
+
}
|
|
574
|
+
),
|
|
575
|
+
/* @__PURE__ */ jsxs6("div", { className: "fractal-number-input-controls", children: [
|
|
576
|
+
/* @__PURE__ */ jsx6(
|
|
577
|
+
"button",
|
|
578
|
+
{
|
|
579
|
+
type: "button",
|
|
580
|
+
className: "fractal-number-input-step",
|
|
581
|
+
"aria-label": `Decrease ${controlLabel}`,
|
|
582
|
+
disabled: decrementDisabled,
|
|
583
|
+
onClick: () => changeByStep(-1),
|
|
584
|
+
children: /* @__PURE__ */ jsx6(Minus, { "aria-hidden": "true", size: 16 })
|
|
585
|
+
}
|
|
586
|
+
),
|
|
587
|
+
/* @__PURE__ */ jsx6(
|
|
588
|
+
"button",
|
|
589
|
+
{
|
|
590
|
+
type: "button",
|
|
591
|
+
className: "fractal-number-input-step",
|
|
592
|
+
"aria-label": `Increase ${controlLabel}`,
|
|
593
|
+
disabled: incrementDisabled,
|
|
594
|
+
onClick: () => changeByStep(1),
|
|
595
|
+
children: /* @__PURE__ */ jsx6(Plus, { "aria-hidden": "true", size: 16 })
|
|
596
|
+
}
|
|
597
|
+
)
|
|
598
|
+
] })
|
|
599
|
+
] });
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/components/PasswordInput/PasswordInput.tsx
|
|
603
|
+
import * as React6 from "react";
|
|
604
|
+
import { Eye, EyeSlash } from "@mirror-physics/fractal-icons";
|
|
605
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
606
|
+
var PasswordInput = React6.forwardRef(
|
|
607
|
+
({
|
|
608
|
+
className,
|
|
609
|
+
disabled,
|
|
610
|
+
showPasswordLabel = "Show password",
|
|
611
|
+
hidePasswordLabel = "Hide password",
|
|
612
|
+
...props
|
|
613
|
+
}, ref) => {
|
|
614
|
+
const [passwordVisible, setPasswordVisible] = React6.useState(false);
|
|
615
|
+
const toggleLabel = passwordVisible ? hidePasswordLabel : showPasswordLabel;
|
|
616
|
+
return /* @__PURE__ */ jsxs7(
|
|
617
|
+
"div",
|
|
618
|
+
{
|
|
619
|
+
className: cn("fractal-password-input", className),
|
|
620
|
+
"data-password-visible": passwordVisible ? "" : void 0,
|
|
621
|
+
children: [
|
|
622
|
+
/* @__PURE__ */ jsx7(
|
|
623
|
+
Input,
|
|
624
|
+
{
|
|
625
|
+
...props,
|
|
626
|
+
ref,
|
|
627
|
+
className: "fractal-password-input-field",
|
|
628
|
+
disabled,
|
|
629
|
+
type: passwordVisible ? "text" : "password"
|
|
630
|
+
}
|
|
631
|
+
),
|
|
632
|
+
/* @__PURE__ */ jsx7(
|
|
633
|
+
"button",
|
|
634
|
+
{
|
|
635
|
+
type: "button",
|
|
636
|
+
className: "fractal-password-input-toggle",
|
|
637
|
+
"aria-label": toggleLabel,
|
|
638
|
+
"aria-pressed": passwordVisible,
|
|
639
|
+
disabled,
|
|
640
|
+
title: toggleLabel,
|
|
641
|
+
onClick: () => setPasswordVisible((visible) => !visible),
|
|
642
|
+
children: passwordVisible ? /* @__PURE__ */ jsx7(EyeSlash, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ jsx7(Eye, { "aria-hidden": "true", size: 18 })
|
|
643
|
+
}
|
|
644
|
+
)
|
|
645
|
+
]
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
);
|
|
650
|
+
PasswordInput.displayName = "PasswordInput";
|
|
651
|
+
|
|
652
|
+
// src/components/Label/Label.tsx
|
|
653
|
+
import * as React7 from "react";
|
|
654
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
655
|
+
var Label = React7.forwardRef(
|
|
656
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
|
|
320
657
|
"label",
|
|
321
658
|
{
|
|
322
659
|
ref,
|
|
@@ -328,44 +665,48 @@ var Label = React5.forwardRef(
|
|
|
328
665
|
Label.displayName = "Label";
|
|
329
666
|
|
|
330
667
|
// src/components/Alert/Alert.tsx
|
|
331
|
-
import * as
|
|
332
|
-
import {
|
|
668
|
+
import * as React8 from "react";
|
|
669
|
+
import { CircleCheck, CircleClose, CircleInfo, Warning } from "@mirror-physics/fractal-icons";
|
|
670
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
333
671
|
var defaultIcons = {
|
|
334
|
-
default:
|
|
335
|
-
info:
|
|
336
|
-
success:
|
|
337
|
-
warning:
|
|
338
|
-
error:
|
|
672
|
+
default: CircleInfo,
|
|
673
|
+
info: CircleInfo,
|
|
674
|
+
success: CircleCheck,
|
|
675
|
+
warning: Warning,
|
|
676
|
+
error: CircleClose
|
|
339
677
|
};
|
|
340
|
-
var Alert =
|
|
341
|
-
({ className, variant = "default", icon, children, ...props }, ref) =>
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
678
|
+
var Alert = React8.forwardRef(
|
|
679
|
+
({ className, variant = "default", icon, children, ...props }, ref) => {
|
|
680
|
+
const DefaultIcon = defaultIcons[variant];
|
|
681
|
+
return /* @__PURE__ */ jsxs8(
|
|
682
|
+
"div",
|
|
683
|
+
{
|
|
684
|
+
ref,
|
|
685
|
+
role: "alert",
|
|
686
|
+
className: cn("fractal-alert", `fractal-alert--${variant}`, className),
|
|
687
|
+
...props,
|
|
688
|
+
children: [
|
|
689
|
+
/* @__PURE__ */ jsx9("span", { className: "fractal-alert-icon", "aria-hidden": true, children: icon ?? /* @__PURE__ */ jsx9(DefaultIcon, { size: 18 }) }),
|
|
690
|
+
/* @__PURE__ */ jsx9("div", { className: "fractal-alert-content", children })
|
|
691
|
+
]
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
}
|
|
354
695
|
);
|
|
355
696
|
Alert.displayName = "Alert";
|
|
356
|
-
var AlertTitle =
|
|
357
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
697
|
+
var AlertTitle = React8.forwardRef(
|
|
698
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx9("h5", { ref, className: cn("fractal-alert-title", className), ...props })
|
|
358
699
|
);
|
|
359
700
|
AlertTitle.displayName = "AlertTitle";
|
|
360
|
-
var AlertDescription =
|
|
361
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
701
|
+
var AlertDescription = React8.forwardRef(
|
|
702
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx9("div", { ref, className: cn("fractal-alert-description", className), ...props })
|
|
362
703
|
);
|
|
363
704
|
AlertDescription.displayName = "AlertDescription";
|
|
364
705
|
|
|
365
706
|
// src/components/Toggle/Toggle.tsx
|
|
366
|
-
import { jsx as
|
|
707
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
367
708
|
function Toggle({ checked, onChange, label, className }) {
|
|
368
|
-
return /* @__PURE__ */
|
|
709
|
+
return /* @__PURE__ */ jsxs9(
|
|
369
710
|
"button",
|
|
370
711
|
{
|
|
371
712
|
type: "button",
|
|
@@ -374,8 +715,8 @@ function Toggle({ checked, onChange, label, className }) {
|
|
|
374
715
|
className: cn("fractal-toggle", className),
|
|
375
716
|
onClick: () => onChange(!checked),
|
|
376
717
|
children: [
|
|
377
|
-
/* @__PURE__ */
|
|
378
|
-
label && /* @__PURE__ */
|
|
718
|
+
/* @__PURE__ */ jsx10("span", { className: cn("fractal-toggle-track", checked && "fractal-toggle-track--checked"), children: /* @__PURE__ */ jsx10("span", { className: cn("fractal-toggle-thumb", checked && "fractal-toggle-thumb--checked") }) }),
|
|
719
|
+
label && /* @__PURE__ */ jsx10("span", { className: "fractal-toggle-label", children: label })
|
|
379
720
|
]
|
|
380
721
|
}
|
|
381
722
|
);
|
|
@@ -385,7 +726,7 @@ function Toggle({ checked, onChange, label, className }) {
|
|
|
385
726
|
import { createPortal } from "react-dom";
|
|
386
727
|
|
|
387
728
|
// src/hooks/useEscapeDismiss.ts
|
|
388
|
-
import { useEffect, useRef } from "react";
|
|
729
|
+
import { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
389
730
|
var nextId = 0;
|
|
390
731
|
var stack = [];
|
|
391
732
|
function insertSorted(entry) {
|
|
@@ -418,9 +759,9 @@ function ensureGlobalListener() {
|
|
|
418
759
|
);
|
|
419
760
|
}
|
|
420
761
|
function useEscapeDismiss(priority, handler, enabled = true) {
|
|
421
|
-
const handlerRef =
|
|
762
|
+
const handlerRef = useRef3(handler);
|
|
422
763
|
handlerRef.current = handler;
|
|
423
|
-
|
|
764
|
+
useEffect2(() => {
|
|
424
765
|
if (!enabled) return;
|
|
425
766
|
ensureGlobalListener();
|
|
426
767
|
const id = nextId++;
|
|
@@ -434,27 +775,84 @@ function useEscapeDismiss(priority, handler, enabled = true) {
|
|
|
434
775
|
}, [priority, enabled]);
|
|
435
776
|
}
|
|
436
777
|
|
|
778
|
+
// src/components/UILoader/UILoader.tsx
|
|
779
|
+
import { useId } from "react";
|
|
780
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
781
|
+
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";
|
|
782
|
+
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";
|
|
783
|
+
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";
|
|
784
|
+
function UILoader({ size = 48, tone = "neutral", className, style, label = "Loading", ariaHidden = false }) {
|
|
785
|
+
const rawId = useId().replace(/[^a-zA-Z0-9_-]/g, "");
|
|
786
|
+
const clipId = `fractal-ui-loader-clip-${rawId}`;
|
|
787
|
+
const gradientId = `fractal-ui-loader-gradient-${rawId}`;
|
|
788
|
+
const height = typeof size === "number" ? `${size}px` : size;
|
|
789
|
+
return /* @__PURE__ */ jsx11(
|
|
790
|
+
"span",
|
|
791
|
+
{
|
|
792
|
+
"aria-hidden": ariaHidden || void 0,
|
|
793
|
+
"aria-label": ariaHidden ? void 0 : label,
|
|
794
|
+
className: cn("fractal-ui-loader", `fractal-ui-loader--${tone}`, className),
|
|
795
|
+
role: ariaHidden ? void 0 : "status",
|
|
796
|
+
style,
|
|
797
|
+
children: /* @__PURE__ */ jsxs10("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 144 92", style: { height, width: "auto" }, children: [
|
|
798
|
+
/* @__PURE__ */ jsxs10("defs", { children: [
|
|
799
|
+
/* @__PURE__ */ jsxs10("linearGradient", { id: gradientId, x1: "59", x2: "94.3", y1: "0", y2: "89.1", gradientUnits: "userSpaceOnUse", children: [
|
|
800
|
+
/* @__PURE__ */ jsx11("stop", { className: "fractal-ui-loader__stop-start", offset: "0" }),
|
|
801
|
+
/* @__PURE__ */ jsx11("stop", { className: "fractal-ui-loader__stop-end", offset: "1" })
|
|
802
|
+
] }),
|
|
803
|
+
/* @__PURE__ */ jsxs10("linearGradient", { id: `${gradientId}-shine`, x1: "0", x2: "1", y1: "0", y2: "0", children: [
|
|
804
|
+
/* @__PURE__ */ jsx11("stop", { offset: "0.4", stopColor: "white", stopOpacity: "0" }),
|
|
805
|
+
/* @__PURE__ */ jsx11("stop", { offset: "0.5", stopColor: "white", stopOpacity: "0.62" }),
|
|
806
|
+
/* @__PURE__ */ jsx11("stop", { offset: "0.6", stopColor: "white", stopOpacity: "0" })
|
|
807
|
+
] }),
|
|
808
|
+
/* @__PURE__ */ jsxs10("clipPath", { id: clipId, children: [
|
|
809
|
+
/* @__PURE__ */ jsx11("path", { d: LEFT }),
|
|
810
|
+
/* @__PURE__ */ jsx11("path", { d: CENTER }),
|
|
811
|
+
/* @__PURE__ */ jsx11("path", { d: RIGHT })
|
|
812
|
+
] })
|
|
813
|
+
] }),
|
|
814
|
+
/* @__PURE__ */ jsx11("path", { d: CENTER, fill: `url(#${gradientId})` }),
|
|
815
|
+
/* @__PURE__ */ jsx11("path", { d: RIGHT, fill: `url(#${gradientId})` }),
|
|
816
|
+
/* @__PURE__ */ jsx11("path", { d: LEFT, fill: `url(#${gradientId})` }),
|
|
817
|
+
/* @__PURE__ */ jsx11("g", { clipPath: `url(#${clipId})`, children: /* @__PURE__ */ jsx11("g", { className: "fractal-ui-loader__shine-axis", transform: "translate(72 46) rotate(68.4)", children: /* @__PURE__ */ jsx11("rect", { className: "fractal-ui-loader__shine", x: "-160", y: "-100", width: "320", height: "200", fill: `url(#${gradientId}-shine)` }) }) })
|
|
818
|
+
] })
|
|
819
|
+
}
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
|
|
437
823
|
// 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);
|
|
824
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
825
|
+
var CloseIcon = () => /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M12 4L4 12M4 4L12 12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
826
|
+
function Modal({ open, onClose, title, children, danger, warn, footer, noClose, closeDisabled = false, size = "sm", loading = false, loadingLabel = "Loading", scrollable = false, className }) {
|
|
827
|
+
useEscapeDismiss(80, onClose, open && !noClose && !closeDisabled);
|
|
442
828
|
if (!open) return null;
|
|
443
829
|
const sizeClass = `fractal-modal-panel--${size}`;
|
|
444
830
|
const accentClass = danger ? "fractal-modal-panel--danger" : warn ? "fractal-modal-panel--warn" : "";
|
|
445
831
|
return createPortal(
|
|
446
|
-
/* @__PURE__ */
|
|
832
|
+
/* @__PURE__ */ jsx12("div", { className: "fractal-modal-overlay", onClick: noClose || closeDisabled ? void 0 : onClose, children: /* @__PURE__ */ jsxs11(
|
|
447
833
|
"div",
|
|
448
834
|
{
|
|
449
|
-
className: cn("fractal-modal-panel", sizeClass, accentClass, className),
|
|
835
|
+
className: cn("fractal-modal-panel", sizeClass, accentClass, scrollable && "fractal-modal-panel--scrollable", className),
|
|
450
836
|
onClick: (e) => e.stopPropagation(),
|
|
451
837
|
children: [
|
|
452
|
-
/* @__PURE__ */
|
|
453
|
-
/* @__PURE__ */
|
|
454
|
-
!noClose && /* @__PURE__ */
|
|
838
|
+
/* @__PURE__ */ jsxs11("div", { className: "fractal-modal-title-row", children: [
|
|
839
|
+
/* @__PURE__ */ jsx12("h3", { className: cn("fractal-modal-title", danger && "fractal-modal-title--danger", warn && "fractal-modal-title--warn"), children: title }),
|
|
840
|
+
!noClose && /* @__PURE__ */ jsx12("button", { type: "button", onClick: onClose, title: "Close", disabled: closeDisabled, className: "fractal-modal-close", children: /* @__PURE__ */ jsx12(CloseIcon, {}) })
|
|
455
841
|
] }),
|
|
456
|
-
/* @__PURE__ */
|
|
457
|
-
|
|
842
|
+
/* @__PURE__ */ jsx12(
|
|
843
|
+
"div",
|
|
844
|
+
{
|
|
845
|
+
"aria-busy": loading || void 0,
|
|
846
|
+
className: cn(
|
|
847
|
+
"fractal-modal-body",
|
|
848
|
+
size === "lg" && "fractal-modal-body--lg",
|
|
849
|
+
loading && "fractal-modal-body--loading",
|
|
850
|
+
scrollable && "fractal-modal-body--scrollable"
|
|
851
|
+
),
|
|
852
|
+
children: loading ? /* @__PURE__ */ jsx12(UILoader, { label: loadingLabel }) : children
|
|
853
|
+
}
|
|
854
|
+
),
|
|
855
|
+
footer && /* @__PURE__ */ jsx12("div", { className: cn("fractal-modal-footer", scrollable && "fractal-modal-footer--divided"), children: footer })
|
|
458
856
|
]
|
|
459
857
|
}
|
|
460
858
|
) }),
|
|
@@ -463,17 +861,17 @@ function Modal({ open, onClose, title, children, danger, warn, footer, noClose,
|
|
|
463
861
|
}
|
|
464
862
|
|
|
465
863
|
// src/components/DataTable/DataTable.tsx
|
|
466
|
-
import { jsx as
|
|
864
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
467
865
|
function DataTable({ columns, data, emptyMessage, header, size = "md", className }) {
|
|
468
|
-
return /* @__PURE__ */
|
|
469
|
-
header && /* @__PURE__ */
|
|
470
|
-
data.length === 0 ? /* @__PURE__ */
|
|
471
|
-
/* @__PURE__ */
|
|
472
|
-
/* @__PURE__ */
|
|
866
|
+
return /* @__PURE__ */ jsx13("div", { className: cn("fractal-datatable", `fractal-datatable--${size}`, className), children: /* @__PURE__ */ jsxs12("div", { className: "fractal-datatable-surface", children: [
|
|
867
|
+
header && /* @__PURE__ */ jsx13("div", { className: "fractal-datatable-header", children: header }),
|
|
868
|
+
data.length === 0 ? /* @__PURE__ */ jsx13("div", { className: "fractal-datatable-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsxs12("table", { className: "fractal-datatable-table", children: [
|
|
869
|
+
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsx13("tr", { className: "fractal-datatable-thead-row", children: columns.map((col) => /* @__PURE__ */ jsx13("th", { className: "fractal-datatable-th", style: { width: col.width }, children: col.header }, col.key)) }) }),
|
|
870
|
+
/* @__PURE__ */ jsx13("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsx13(
|
|
473
871
|
"tr",
|
|
474
872
|
{
|
|
475
873
|
className: "fractal-datatable-row",
|
|
476
|
-
children: columns.map((col) => /* @__PURE__ */
|
|
874
|
+
children: columns.map((col) => /* @__PURE__ */ jsx13("td", { className: "fractal-datatable-td", style: { width: col.width }, children: col.render(row, rowIndex) }, col.key))
|
|
477
875
|
},
|
|
478
876
|
rowIndex
|
|
479
877
|
)) })
|
|
@@ -482,9 +880,9 @@ function DataTable({ columns, data, emptyMessage, header, size = "md", className
|
|
|
482
880
|
}
|
|
483
881
|
|
|
484
882
|
// src/components/Dropdown/Dropdown.tsx
|
|
485
|
-
import * as
|
|
883
|
+
import * as React9 from "react";
|
|
486
884
|
import { ChevronDown, ChevronUp } from "@mirror-physics/fractal-icons";
|
|
487
|
-
import { Fragment as Fragment2, jsx as
|
|
885
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
488
886
|
var MARGIN = 4;
|
|
489
887
|
function Dropdown({
|
|
490
888
|
items,
|
|
@@ -495,18 +893,20 @@ function Dropdown({
|
|
|
495
893
|
align = "left",
|
|
496
894
|
triggerContent,
|
|
497
895
|
label,
|
|
896
|
+
iconOnly = false,
|
|
498
897
|
noChevron = false,
|
|
499
898
|
size = "md",
|
|
500
899
|
triggerVariant = "outline",
|
|
501
900
|
className,
|
|
502
901
|
triggerClassName,
|
|
503
902
|
panelClassName,
|
|
504
|
-
closeOnSelect = true
|
|
903
|
+
closeOnSelect = true,
|
|
904
|
+
disabled = false
|
|
505
905
|
}) {
|
|
506
|
-
const [open, setOpen] =
|
|
507
|
-
const triggerRef =
|
|
508
|
-
const panelRef =
|
|
509
|
-
const [panelStyle, setPanelStyle] =
|
|
906
|
+
const [open, setOpen] = React9.useState(false);
|
|
907
|
+
const triggerRef = React9.useRef(null);
|
|
908
|
+
const panelRef = React9.useRef(null);
|
|
909
|
+
const [panelStyle, setPanelStyle] = React9.useState({});
|
|
510
910
|
const visibleItems = items.filter(
|
|
511
911
|
(item) => item.icon != null || item.description != null && (typeof item.description === "string" ? item.description !== "" : true)
|
|
512
912
|
);
|
|
@@ -515,7 +915,7 @@ function Dropdown({
|
|
|
515
915
|
const selected = items.find((i) => i.value === selectedValue && i.kind !== "header") ?? selectableItems[0] ?? visibleItems[0];
|
|
516
916
|
const isUp = direction === "up";
|
|
517
917
|
const ChevronIcon = isUp ? ChevronUp : ChevronDown;
|
|
518
|
-
|
|
918
|
+
React9.useLayoutEffect(() => {
|
|
519
919
|
if (!open || !triggerRef.current || !panelRef.current) return;
|
|
520
920
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
521
921
|
const panelRect = panelRef.current.getBoundingClientRect();
|
|
@@ -549,7 +949,7 @@ function Dropdown({
|
|
|
549
949
|
}
|
|
550
950
|
setPanelStyle({ top, left, right });
|
|
551
951
|
}, [open, isUp, align]);
|
|
552
|
-
|
|
952
|
+
React9.useEffect(() => {
|
|
553
953
|
if (!open) return;
|
|
554
954
|
const handleClickOutside = (e) => {
|
|
555
955
|
const target = e.target;
|
|
@@ -559,12 +959,13 @@ function Dropdown({
|
|
|
559
959
|
document.addEventListener("mousedown", handleClickOutside);
|
|
560
960
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
561
961
|
}, [open]);
|
|
562
|
-
return /* @__PURE__ */
|
|
563
|
-
/* @__PURE__ */
|
|
962
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("fractal-dropdown", className), children: [
|
|
963
|
+
/* @__PURE__ */ jsxs13(
|
|
564
964
|
"button",
|
|
565
965
|
{
|
|
566
966
|
ref: triggerRef,
|
|
567
967
|
type: "button",
|
|
968
|
+
disabled,
|
|
568
969
|
"aria-haspopup": "listbox",
|
|
569
970
|
"aria-expanded": open,
|
|
570
971
|
"aria-label": triggerLabel,
|
|
@@ -573,18 +974,19 @@ function Dropdown({
|
|
|
573
974
|
"fractal-dropdown-trigger",
|
|
574
975
|
`fractal-dropdown-trigger--${size}`,
|
|
575
976
|
`fractal-dropdown-trigger--${triggerVariant}`,
|
|
977
|
+
iconOnly && "fractal-dropdown-trigger--icon-only",
|
|
576
978
|
triggerClassName
|
|
577
979
|
),
|
|
578
980
|
children: [
|
|
579
|
-
triggerContent != null ? triggerContent : /* @__PURE__ */
|
|
580
|
-
selected.icon != null && /* @__PURE__ */
|
|
581
|
-
selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */
|
|
981
|
+
triggerContent != null ? triggerContent : /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
982
|
+
selected.icon != null && /* @__PURE__ */ jsx14("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected.icon }),
|
|
983
|
+
selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ jsx14("span", { className: "fractal-dropdown-selected-text", children: selected.description })
|
|
582
984
|
] }),
|
|
583
|
-
!noChevron && /* @__PURE__ */
|
|
985
|
+
!noChevron && !iconOnly && /* @__PURE__ */ jsx14("span", { className: "fractal-dropdown-chevron", "aria-hidden": true, children: /* @__PURE__ */ jsx14(ChevronIcon, { size: size === "sm" ? 14 : 16 }) })
|
|
584
986
|
]
|
|
585
987
|
}
|
|
586
988
|
),
|
|
587
|
-
open && /* @__PURE__ */
|
|
989
|
+
open && /* @__PURE__ */ jsxs13(
|
|
588
990
|
"div",
|
|
589
991
|
{
|
|
590
992
|
ref: panelRef,
|
|
@@ -593,21 +995,21 @@ function Dropdown({
|
|
|
593
995
|
className: cn("fractal-dropdown-panel", `fractal-dropdown-panel--${size}`, panelClassName),
|
|
594
996
|
style: panelStyle,
|
|
595
997
|
children: [
|
|
596
|
-
label != null && /* @__PURE__ */
|
|
998
|
+
label != null && /* @__PURE__ */ jsx14("div", { className: "fractal-dropdown-label", children: label }),
|
|
597
999
|
visibleItems.map((item, index) => {
|
|
598
|
-
const topDivider = item.border === "top" ? /* @__PURE__ */
|
|
599
|
-
const bottomDivider = item.border === "bottom" ? /* @__PURE__ */
|
|
1000
|
+
const topDivider = item.border === "top" ? /* @__PURE__ */ jsx14("div", { className: "fractal-dropdown-separator" }) : null;
|
|
1001
|
+
const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ jsx14("div", { className: "fractal-dropdown-separator" }) : null;
|
|
600
1002
|
if (item.kind === "header") {
|
|
601
|
-
return /* @__PURE__ */
|
|
1003
|
+
return /* @__PURE__ */ jsxs13(React9.Fragment, { children: [
|
|
602
1004
|
topDivider,
|
|
603
|
-
/* @__PURE__ */
|
|
1005
|
+
/* @__PURE__ */ jsx14("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
|
|
604
1006
|
bottomDivider
|
|
605
1007
|
] }, `header-${index}`);
|
|
606
1008
|
}
|
|
607
1009
|
const isSelected = item.value === selectedValue;
|
|
608
|
-
return /* @__PURE__ */
|
|
1010
|
+
return /* @__PURE__ */ jsxs13(React9.Fragment, { children: [
|
|
609
1011
|
topDivider,
|
|
610
|
-
/* @__PURE__ */
|
|
1012
|
+
/* @__PURE__ */ jsxs13(
|
|
611
1013
|
"button",
|
|
612
1014
|
{
|
|
613
1015
|
type: "button",
|
|
@@ -619,9 +1021,9 @@ function Dropdown({
|
|
|
619
1021
|
},
|
|
620
1022
|
className: "fractal-dropdown-option",
|
|
621
1023
|
children: [
|
|
622
|
-
item.icon != null && /* @__PURE__ */
|
|
623
|
-
item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */
|
|
624
|
-
item.trailing != null && /* @__PURE__ */
|
|
1024
|
+
item.icon != null && /* @__PURE__ */ jsx14("span", { className: "fractal-dropdown-icon", children: item.icon }),
|
|
1025
|
+
item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ jsx14("span", { className: "fractal-dropdown-option-text", children: item.description }),
|
|
1026
|
+
item.trailing != null && /* @__PURE__ */ jsx14("span", { className: "fractal-dropdown-trailing", children: item.trailing })
|
|
625
1027
|
]
|
|
626
1028
|
}
|
|
627
1029
|
),
|
|
@@ -635,10 +1037,10 @@ function Dropdown({
|
|
|
635
1037
|
}
|
|
636
1038
|
|
|
637
1039
|
// src/components/Link/Link.tsx
|
|
638
|
-
import * as
|
|
639
|
-
import { jsx as
|
|
640
|
-
var Link =
|
|
641
|
-
({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */
|
|
1040
|
+
import * as React10 from "react";
|
|
1041
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1042
|
+
var Link = React10.forwardRef(
|
|
1043
|
+
({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */ jsx15(
|
|
642
1044
|
"a",
|
|
643
1045
|
{
|
|
644
1046
|
ref,
|
|
@@ -650,10 +1052,10 @@ var Link = React8.forwardRef(
|
|
|
650
1052
|
Link.displayName = "Link";
|
|
651
1053
|
|
|
652
1054
|
// src/components/Chip/Chip.tsx
|
|
653
|
-
import * as
|
|
654
|
-
import { jsx as
|
|
655
|
-
var Chip =
|
|
656
|
-
({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */
|
|
1055
|
+
import * as React11 from "react";
|
|
1056
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1057
|
+
var Chip = React11.forwardRef(
|
|
1058
|
+
({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */ jsx16(
|
|
657
1059
|
"span",
|
|
658
1060
|
{
|
|
659
1061
|
ref,
|
|
@@ -664,36 +1066,86 @@ var Chip = React9.forwardRef(
|
|
|
664
1066
|
);
|
|
665
1067
|
Chip.displayName = "Chip";
|
|
666
1068
|
|
|
1069
|
+
// src/components/Checkbox/Checkbox.tsx
|
|
1070
|
+
import { Checkbox as CheckboxIcon, CheckboxChecked, Minus as Minus2 } from "@mirror-physics/fractal-icons";
|
|
1071
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1072
|
+
function Checkbox({
|
|
1073
|
+
checked,
|
|
1074
|
+
indeterminate = false,
|
|
1075
|
+
onCheckedChange,
|
|
1076
|
+
className,
|
|
1077
|
+
disabled,
|
|
1078
|
+
onClick,
|
|
1079
|
+
onKeyDown,
|
|
1080
|
+
...props
|
|
1081
|
+
}) {
|
|
1082
|
+
return /* @__PURE__ */ jsx17(
|
|
1083
|
+
"button",
|
|
1084
|
+
{
|
|
1085
|
+
...props,
|
|
1086
|
+
className: cn(
|
|
1087
|
+
"fractal-checkbox",
|
|
1088
|
+
(checked || indeterminate) && "fractal-checkbox--checked",
|
|
1089
|
+
indeterminate && "fractal-checkbox--indeterminate",
|
|
1090
|
+
className
|
|
1091
|
+
),
|
|
1092
|
+
type: "button",
|
|
1093
|
+
role: "checkbox",
|
|
1094
|
+
"aria-checked": indeterminate ? "mixed" : checked,
|
|
1095
|
+
disabled,
|
|
1096
|
+
onClick: (event) => {
|
|
1097
|
+
onClick?.(event);
|
|
1098
|
+
if (!event.defaultPrevented) onCheckedChange(indeterminate || !checked);
|
|
1099
|
+
},
|
|
1100
|
+
onKeyDown: (event) => {
|
|
1101
|
+
onKeyDown?.(event);
|
|
1102
|
+
if (event.key === " " || event.key === "Enter") event.stopPropagation();
|
|
1103
|
+
},
|
|
1104
|
+
children: indeterminate ? /* @__PURE__ */ jsxs14("span", { className: "fractal-checkbox__indeterminate-icon", "aria-hidden": "true", children: [
|
|
1105
|
+
/* @__PURE__ */ jsx17(CheckboxIcon, { size: 18 }),
|
|
1106
|
+
/* @__PURE__ */ jsx17(Minus2, { className: "fractal-checkbox__indeterminate-mark", size: 12 })
|
|
1107
|
+
] }) : checked ? /* @__PURE__ */ jsx17(CheckboxChecked, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ jsx17(CheckboxIcon, { "aria-hidden": "true", size: 18 })
|
|
1108
|
+
}
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
667
1112
|
// src/components/SortableTable/SortableTable.tsx
|
|
668
|
-
import { useMemo, useState as
|
|
1113
|
+
import { useMemo as useMemo2, useState as useState5 } from "react";
|
|
669
1114
|
import { ArrowUp, ArrowDown, ArrowsUpDown } from "@mirror-physics/fractal-icons";
|
|
670
|
-
import { jsx as
|
|
1115
|
+
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
671
1116
|
function SortableTable({
|
|
672
1117
|
columns,
|
|
673
1118
|
data,
|
|
674
1119
|
emptyMessage,
|
|
675
1120
|
header,
|
|
676
1121
|
size = "md",
|
|
1122
|
+
embedded = false,
|
|
677
1123
|
className,
|
|
1124
|
+
defaultSort,
|
|
678
1125
|
defaultSortKey = void 0,
|
|
679
1126
|
defaultSortDirection = null,
|
|
680
1127
|
sortKey: controlledKey,
|
|
681
1128
|
sortDirection: controlledDirection,
|
|
682
1129
|
onSortChange,
|
|
683
1130
|
highlightRow,
|
|
684
|
-
onRowClick
|
|
1131
|
+
onRowClick,
|
|
1132
|
+
rowAction
|
|
685
1133
|
}) {
|
|
686
|
-
const [internalKey, setInternalKey] =
|
|
687
|
-
const [internalDirection, setInternalDirection] =
|
|
1134
|
+
const [internalKey, setInternalKey] = useState5(defaultSortKey ?? null);
|
|
1135
|
+
const [internalDirection, setInternalDirection] = useState5(defaultSortDirection);
|
|
688
1136
|
const isControlled = controlledKey !== void 0 && controlledDirection !== void 0;
|
|
689
1137
|
const activeKey = isControlled ? controlledKey : internalKey;
|
|
690
1138
|
const activeDirection = isControlled ? controlledDirection : internalDirection;
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
1139
|
+
const baselineKey = defaultSort?.key ?? null;
|
|
1140
|
+
const baselineDirection = defaultSort?.direction ?? null;
|
|
1141
|
+
const effectiveKey = activeKey && activeDirection ? activeKey : baselineKey;
|
|
1142
|
+
const effectiveDirection = activeKey && activeDirection ? activeDirection : baselineDirection;
|
|
1143
|
+
const sorted = useMemo2(() => {
|
|
1144
|
+
if (!effectiveKey || !effectiveDirection) return data;
|
|
1145
|
+
const col = columns.find((c) => c.key === effectiveKey);
|
|
694
1146
|
if (!col) return data;
|
|
695
1147
|
const accessor = col.sortAccessor ?? ((row) => {
|
|
696
|
-
const value = row[
|
|
1148
|
+
const value = row[effectiveKey];
|
|
697
1149
|
return typeof value === "string" || typeof value === "number" ? value : null;
|
|
698
1150
|
});
|
|
699
1151
|
const copy = [...data];
|
|
@@ -704,26 +1156,28 @@ function SortableTable({
|
|
|
704
1156
|
if (av == null) return 1;
|
|
705
1157
|
if (bv == null) return -1;
|
|
706
1158
|
if (typeof av === "number" && typeof bv === "number") {
|
|
707
|
-
return
|
|
1159
|
+
return effectiveDirection === "asc" ? av - bv : bv - av;
|
|
708
1160
|
}
|
|
709
1161
|
const as = String(av).toLowerCase();
|
|
710
1162
|
const bs = String(bv).toLowerCase();
|
|
711
|
-
if (as < bs) return
|
|
712
|
-
if (as > bs) return
|
|
1163
|
+
if (as < bs) return effectiveDirection === "asc" ? -1 : 1;
|
|
1164
|
+
if (as > bs) return effectiveDirection === "asc" ? 1 : -1;
|
|
713
1165
|
return 0;
|
|
714
1166
|
});
|
|
715
1167
|
return copy;
|
|
716
|
-
}, [data, columns,
|
|
1168
|
+
}, [data, columns, effectiveKey, effectiveDirection]);
|
|
717
1169
|
const handleSortClick = (key) => {
|
|
718
1170
|
let nextDirection;
|
|
719
|
-
if (activeKey
|
|
1171
|
+
if (!activeKey || !activeDirection) {
|
|
1172
|
+
nextDirection = baselineKey === key && baselineDirection ? baselineDirection : "asc";
|
|
1173
|
+
} else if (activeKey !== key) {
|
|
720
1174
|
nextDirection = "asc";
|
|
1175
|
+
} else if (baselineKey === key && baselineDirection) {
|
|
1176
|
+
nextDirection = activeDirection === baselineDirection ? baselineDirection === "asc" ? "desc" : "asc" : null;
|
|
721
1177
|
} else if (activeDirection === "asc") {
|
|
722
1178
|
nextDirection = "desc";
|
|
723
|
-
} else if (activeDirection === "desc") {
|
|
724
|
-
nextDirection = null;
|
|
725
1179
|
} else {
|
|
726
|
-
nextDirection =
|
|
1180
|
+
nextDirection = null;
|
|
727
1181
|
}
|
|
728
1182
|
const nextKey = nextDirection === null ? null : key;
|
|
729
1183
|
if (isControlled) {
|
|
@@ -734,13 +1188,13 @@ function SortableTable({
|
|
|
734
1188
|
onSortChange?.(nextKey, nextDirection);
|
|
735
1189
|
}
|
|
736
1190
|
};
|
|
737
|
-
return /* @__PURE__ */
|
|
738
|
-
header && /* @__PURE__ */
|
|
739
|
-
sorted.length === 0 ? /* @__PURE__ */
|
|
740
|
-
/* @__PURE__ */
|
|
1191
|
+
return /* @__PURE__ */ jsx18("div", { className: cn("fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), children: /* @__PURE__ */ jsxs15("div", { className: "fractal-sortable-table-surface", children: [
|
|
1192
|
+
header && /* @__PURE__ */ jsx18("div", { className: "fractal-sortable-table-header", children: header }),
|
|
1193
|
+
sorted.length === 0 ? /* @__PURE__ */ jsx18("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ jsxs15("table", { className: "fractal-sortable-table-table", children: [
|
|
1194
|
+
/* @__PURE__ */ jsx18("thead", { children: /* @__PURE__ */ jsx18("tr", { className: "fractal-sortable-table-thead-row", children: columns.map((col) => {
|
|
741
1195
|
const isActive = activeKey === col.key && activeDirection !== null;
|
|
742
1196
|
if (!col.sortable) {
|
|
743
|
-
return /* @__PURE__ */
|
|
1197
|
+
return /* @__PURE__ */ jsx18(
|
|
744
1198
|
"th",
|
|
745
1199
|
{
|
|
746
1200
|
className: "fractal-sortable-table-th",
|
|
@@ -750,12 +1204,12 @@ function SortableTable({
|
|
|
750
1204
|
col.key
|
|
751
1205
|
);
|
|
752
1206
|
}
|
|
753
|
-
return /* @__PURE__ */
|
|
1207
|
+
return /* @__PURE__ */ jsx18(
|
|
754
1208
|
"th",
|
|
755
1209
|
{
|
|
756
1210
|
className: "fractal-sortable-table-th fractal-sortable-table-th--sortable",
|
|
757
1211
|
style: { width: col.width },
|
|
758
|
-
children: /* @__PURE__ */
|
|
1212
|
+
children: /* @__PURE__ */ jsxs15(
|
|
759
1213
|
"button",
|
|
760
1214
|
{
|
|
761
1215
|
type: "button",
|
|
@@ -766,8 +1220,8 @@ function SortableTable({
|
|
|
766
1220
|
onClick: () => handleSortClick(col.key),
|
|
767
1221
|
"aria-sort": isActive ? activeDirection === "asc" ? "ascending" : "descending" : "none",
|
|
768
1222
|
children: [
|
|
769
|
-
/* @__PURE__ */
|
|
770
|
-
/* @__PURE__ */
|
|
1223
|
+
/* @__PURE__ */ jsx18("span", { children: col.header }),
|
|
1224
|
+
/* @__PURE__ */ jsx18("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ jsx18(ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ jsx18(ArrowDown, { size: 14 }) : /* @__PURE__ */ jsx18(ArrowsUpDown, { size: 14 }) })
|
|
771
1225
|
]
|
|
772
1226
|
}
|
|
773
1227
|
)
|
|
@@ -775,9 +1229,13 @@ function SortableTable({
|
|
|
775
1229
|
col.key
|
|
776
1230
|
);
|
|
777
1231
|
}) }) }),
|
|
778
|
-
/* @__PURE__ */
|
|
1232
|
+
/* @__PURE__ */ jsx18("tbody", { children: sorted.map((row, rowIndex) => {
|
|
779
1233
|
const highlighted = highlightRow?.(row, rowIndex) ?? false;
|
|
780
|
-
|
|
1234
|
+
const action = rowAction ? {
|
|
1235
|
+
label: rowAction.label(row, rowIndex),
|
|
1236
|
+
icon: rowAction.icon(row, rowIndex)
|
|
1237
|
+
} : null;
|
|
1238
|
+
return /* @__PURE__ */ jsx18(
|
|
781
1239
|
"tr",
|
|
782
1240
|
{
|
|
783
1241
|
className: cn(
|
|
@@ -792,14 +1250,21 @@ function SortableTable({
|
|
|
792
1250
|
onRowClick(row, rowIndex);
|
|
793
1251
|
}
|
|
794
1252
|
} : void 0,
|
|
1253
|
+
"aria-label": action?.label,
|
|
795
1254
|
role: onRowClick ? "button" : void 0,
|
|
796
1255
|
tabIndex: onRowClick ? 0 : void 0,
|
|
797
|
-
children: columns.map((col) => /* @__PURE__ */
|
|
1256
|
+
children: columns.map((col, columnIndex) => /* @__PURE__ */ jsxs15(
|
|
798
1257
|
"td",
|
|
799
1258
|
{
|
|
800
|
-
className:
|
|
1259
|
+
className: cn(
|
|
1260
|
+
"fractal-sortable-table-td",
|
|
1261
|
+
action && columnIndex === columns.length - 1 && "fractal-sortable-table-td--row-action"
|
|
1262
|
+
),
|
|
801
1263
|
style: { width: col.width, textAlign: col.align ?? "left" },
|
|
802
|
-
children:
|
|
1264
|
+
children: [
|
|
1265
|
+
col.render(row, rowIndex),
|
|
1266
|
+
action && columnIndex === columns.length - 1 && /* @__PURE__ */ jsx18("span", { className: "fractal-sortable-table-row-action", "aria-hidden": "true", children: /* @__PURE__ */ jsx18("span", { className: "fractal-sortable-table-row-action__icon", children: action.icon }) })
|
|
1267
|
+
]
|
|
803
1268
|
},
|
|
804
1269
|
col.key
|
|
805
1270
|
))
|
|
@@ -812,23 +1277,40 @@ function SortableTable({
|
|
|
812
1277
|
}
|
|
813
1278
|
|
|
814
1279
|
// src/components/Tabs/Tabs.tsx
|
|
815
|
-
import { useId, useRef as
|
|
816
|
-
import { jsx as
|
|
1280
|
+
import { useId as useId2, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState6 } from "react";
|
|
1281
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
817
1282
|
function Tabs({
|
|
818
1283
|
items,
|
|
819
1284
|
defaultValue,
|
|
820
1285
|
value: controlledValue,
|
|
821
1286
|
onValueChange,
|
|
822
1287
|
className,
|
|
823
|
-
ariaLabel
|
|
1288
|
+
ariaLabel,
|
|
1289
|
+
divider = false,
|
|
1290
|
+
variant = "line"
|
|
824
1291
|
}) {
|
|
825
|
-
const reactId =
|
|
826
|
-
const [internalValue, setInternalValue] =
|
|
1292
|
+
const reactId = useId2();
|
|
1293
|
+
const [internalValue, setInternalValue] = useState6(
|
|
827
1294
|
defaultValue ?? items.find((i) => !i.disabled)?.id ?? items[0]?.id ?? ""
|
|
828
1295
|
);
|
|
829
1296
|
const isControlled = controlledValue !== void 0;
|
|
830
1297
|
const activeId = isControlled ? controlledValue : internalValue;
|
|
831
|
-
const
|
|
1298
|
+
const tabListRef = useRef5(null);
|
|
1299
|
+
const tabRefs = useRef5({});
|
|
1300
|
+
const [indicator, setIndicator] = useState6(null);
|
|
1301
|
+
useLayoutEffect2(() => {
|
|
1302
|
+
const updateIndicator = () => {
|
|
1303
|
+
const activeTab = tabRefs.current[activeId];
|
|
1304
|
+
if (!activeTab) return;
|
|
1305
|
+
setIndicator({ offset: activeTab.offsetLeft, width: activeTab.offsetWidth });
|
|
1306
|
+
};
|
|
1307
|
+
updateIndicator();
|
|
1308
|
+
const list = tabListRef.current;
|
|
1309
|
+
if (!list || typeof ResizeObserver === "undefined") return;
|
|
1310
|
+
const observer = new ResizeObserver(updateIndicator);
|
|
1311
|
+
observer.observe(list);
|
|
1312
|
+
return () => observer.disconnect();
|
|
1313
|
+
}, [activeId, items.length]);
|
|
832
1314
|
const selectTab = (id) => {
|
|
833
1315
|
if (isControlled) {
|
|
834
1316
|
onValueChange?.(id);
|
|
@@ -838,6 +1320,10 @@ function Tabs({
|
|
|
838
1320
|
}
|
|
839
1321
|
};
|
|
840
1322
|
const focusable = items.filter((i) => !i.disabled);
|
|
1323
|
+
const indicatorStyle = indicator ? {
|
|
1324
|
+
"--fractal-tabs-indicator-offset": `${indicator.offset}px`,
|
|
1325
|
+
"--fractal-tabs-indicator-width": `${indicator.width}px`
|
|
1326
|
+
} : void 0;
|
|
841
1327
|
const onKeyDown = (event) => {
|
|
842
1328
|
const currentIndex = focusable.findIndex((i) => i.id === activeId);
|
|
843
1329
|
if (currentIndex === -1) return;
|
|
@@ -863,41 +1349,52 @@ function Tabs({
|
|
|
863
1349
|
selectTab(nextId2);
|
|
864
1350
|
requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
|
|
865
1351
|
};
|
|
866
|
-
return /* @__PURE__ */
|
|
867
|
-
/* @__PURE__ */
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
"
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
id
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
1352
|
+
return /* @__PURE__ */ jsxs16("div", { className: cn("fractal-tabs", `fractal-tabs--${variant}`, divider && "fractal-tabs--divider", className), children: [
|
|
1353
|
+
/* @__PURE__ */ jsx19(
|
|
1354
|
+
"div",
|
|
1355
|
+
{
|
|
1356
|
+
ref: tabListRef,
|
|
1357
|
+
role: "tablist",
|
|
1358
|
+
"aria-label": ariaLabel,
|
|
1359
|
+
className: "fractal-tabs-list",
|
|
1360
|
+
"data-indicator-ready": indicator ? "true" : void 0,
|
|
1361
|
+
style: indicatorStyle,
|
|
1362
|
+
children: items.map((item) => {
|
|
1363
|
+
const isActive = item.id === activeId;
|
|
1364
|
+
const tabId = `${reactId}-tab-${item.id}`;
|
|
1365
|
+
const panelId = `${reactId}-panel-${item.id}`;
|
|
1366
|
+
return /* @__PURE__ */ jsx19(
|
|
1367
|
+
"button",
|
|
1368
|
+
{
|
|
1369
|
+
ref: (el) => {
|
|
1370
|
+
tabRefs.current[item.id] = el;
|
|
1371
|
+
},
|
|
1372
|
+
id: tabId,
|
|
1373
|
+
role: "tab",
|
|
1374
|
+
type: "button",
|
|
1375
|
+
"aria-selected": isActive,
|
|
1376
|
+
"aria-controls": panelId,
|
|
1377
|
+
tabIndex: isActive ? 0 : -1,
|
|
1378
|
+
disabled: item.disabled,
|
|
1379
|
+
className: cn(
|
|
1380
|
+
"fractal-tabs-trigger",
|
|
1381
|
+
isActive && "fractal-tabs-trigger--active",
|
|
1382
|
+
item.disabled && "fractal-tabs-trigger--disabled"
|
|
1383
|
+
),
|
|
1384
|
+
onClick: () => !item.disabled && selectTab(item.id),
|
|
1385
|
+
onKeyDown,
|
|
1386
|
+
children: item.label
|
|
1387
|
+
},
|
|
1388
|
+
item.id
|
|
1389
|
+
);
|
|
1390
|
+
})
|
|
1391
|
+
}
|
|
1392
|
+
),
|
|
896
1393
|
items.map((item) => {
|
|
897
1394
|
const tabId = `${reactId}-tab-${item.id}`;
|
|
898
1395
|
const panelId = `${reactId}-panel-${item.id}`;
|
|
899
1396
|
const isActive = item.id === activeId;
|
|
900
|
-
return /* @__PURE__ */
|
|
1397
|
+
return /* @__PURE__ */ jsx19(
|
|
901
1398
|
"div",
|
|
902
1399
|
{
|
|
903
1400
|
id: panelId,
|
|
@@ -913,10 +1410,112 @@ function Tabs({
|
|
|
913
1410
|
] });
|
|
914
1411
|
}
|
|
915
1412
|
|
|
1413
|
+
// src/components/ContentSwitcher/ContentSwitcher.tsx
|
|
1414
|
+
import * as React12 from "react";
|
|
1415
|
+
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1416
|
+
function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = false, className }) {
|
|
1417
|
+
const switcherRef = React12.useRef(null);
|
|
1418
|
+
const buttonRefs = React12.useRef([]);
|
|
1419
|
+
const indicatorMotionReadyRef = React12.useRef(false);
|
|
1420
|
+
const activeIndex = items.findIndex((item) => item.value === value);
|
|
1421
|
+
React12.useLayoutEffect(() => {
|
|
1422
|
+
const switcher = switcherRef.current;
|
|
1423
|
+
const activeButton = buttonRefs.current[activeIndex];
|
|
1424
|
+
let motionFrame = 0;
|
|
1425
|
+
if (!switcher || !activeButton) {
|
|
1426
|
+
switcher?.removeAttribute("data-indicator-ready");
|
|
1427
|
+
switcher?.removeAttribute("data-indicator-animate");
|
|
1428
|
+
indicatorMotionReadyRef.current = false;
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
const updateIndicator = () => {
|
|
1432
|
+
const switcherRect = switcher.getBoundingClientRect();
|
|
1433
|
+
const activeButtonRect = activeButton.getBoundingClientRect();
|
|
1434
|
+
switcher.style.setProperty("--fractal-content-switcher-indicator-x", `${activeButtonRect.left - switcherRect.left - switcher.clientLeft}px`);
|
|
1435
|
+
switcher.style.setProperty("--fractal-content-switcher-indicator-y", `${activeButtonRect.top - switcherRect.top - switcher.clientTop}px`);
|
|
1436
|
+
switcher.style.setProperty("--fractal-content-switcher-indicator-width", `${activeButtonRect.width}px`);
|
|
1437
|
+
switcher.style.setProperty("--fractal-content-switcher-indicator-height", `${activeButtonRect.height}px`);
|
|
1438
|
+
switcher.setAttribute("data-indicator-ready", "true");
|
|
1439
|
+
if (!indicatorMotionReadyRef.current && motionFrame === 0) {
|
|
1440
|
+
motionFrame = window.requestAnimationFrame(() => {
|
|
1441
|
+
indicatorMotionReadyRef.current = true;
|
|
1442
|
+
switcher.setAttribute("data-indicator-animate", "true");
|
|
1443
|
+
motionFrame = 0;
|
|
1444
|
+
});
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
updateIndicator();
|
|
1448
|
+
if (typeof ResizeObserver === "undefined") {
|
|
1449
|
+
return () => {
|
|
1450
|
+
if (motionFrame !== 0) window.cancelAnimationFrame(motionFrame);
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
const resizeObserver = new ResizeObserver(updateIndicator);
|
|
1454
|
+
resizeObserver.observe(switcher);
|
|
1455
|
+
buttonRefs.current.forEach((button) => {
|
|
1456
|
+
if (button) resizeObserver.observe(button);
|
|
1457
|
+
});
|
|
1458
|
+
return () => {
|
|
1459
|
+
resizeObserver.disconnect();
|
|
1460
|
+
if (motionFrame !== 0) window.cancelAnimationFrame(motionFrame);
|
|
1461
|
+
};
|
|
1462
|
+
}, [activeIndex, items.length]);
|
|
1463
|
+
const moveFocus = (index, direction) => {
|
|
1464
|
+
let nextIndex = index;
|
|
1465
|
+
do {
|
|
1466
|
+
nextIndex = (nextIndex + direction + items.length) % items.length;
|
|
1467
|
+
} while (items[nextIndex]?.disabled && nextIndex !== index);
|
|
1468
|
+
if (!items[nextIndex]?.disabled) {
|
|
1469
|
+
buttonRefs.current[nextIndex]?.focus();
|
|
1470
|
+
onValueChange(items[nextIndex].value);
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
return /* @__PURE__ */ jsxs17(
|
|
1474
|
+
"div",
|
|
1475
|
+
{
|
|
1476
|
+
className: cn("fractal-content-switcher", fullWidth && "fractal-content-switcher--full-width", className),
|
|
1477
|
+
role: "group",
|
|
1478
|
+
"aria-label": ariaLabel,
|
|
1479
|
+
ref: switcherRef,
|
|
1480
|
+
children: [
|
|
1481
|
+
/* @__PURE__ */ jsx20("span", { className: "fractal-content-switcher__indicator", "aria-hidden": true }),
|
|
1482
|
+
items.map((item, index) => {
|
|
1483
|
+
const active = item.value === value;
|
|
1484
|
+
return /* @__PURE__ */ jsx20(
|
|
1485
|
+
"button",
|
|
1486
|
+
{
|
|
1487
|
+
className: cn("fractal-content-switcher__item", active && "fractal-content-switcher__item--active"),
|
|
1488
|
+
type: "button",
|
|
1489
|
+
"aria-pressed": active,
|
|
1490
|
+
disabled: item.disabled,
|
|
1491
|
+
onClick: () => onValueChange(item.value),
|
|
1492
|
+
onKeyDown: (event) => {
|
|
1493
|
+
if (event.key === "ArrowRight") {
|
|
1494
|
+
event.preventDefault();
|
|
1495
|
+
moveFocus(index, 1);
|
|
1496
|
+
}
|
|
1497
|
+
if (event.key === "ArrowLeft") {
|
|
1498
|
+
event.preventDefault();
|
|
1499
|
+
moveFocus(index, -1);
|
|
1500
|
+
}
|
|
1501
|
+
},
|
|
1502
|
+
ref: (element) => {
|
|
1503
|
+
buttonRefs.current[index] = element;
|
|
1504
|
+
},
|
|
1505
|
+
children: item.label
|
|
1506
|
+
},
|
|
1507
|
+
item.value
|
|
1508
|
+
);
|
|
1509
|
+
})
|
|
1510
|
+
]
|
|
1511
|
+
}
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
916
1515
|
// src/components/Disclosure/Disclosure.tsx
|
|
917
|
-
import { useId as
|
|
918
|
-
import { ChevronRight, ChevronDown as ChevronDown2 } from "@mirror-physics/fractal-icons";
|
|
919
|
-
import { jsx as
|
|
1516
|
+
import { useId as useId3, useState as useState7 } from "react";
|
|
1517
|
+
import { ChevronRight as ChevronRight2, ChevronDown as ChevronDown2 } from "@mirror-physics/fractal-icons";
|
|
1518
|
+
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
920
1519
|
function Disclosure({
|
|
921
1520
|
title,
|
|
922
1521
|
meta,
|
|
@@ -924,16 +1523,18 @@ function Disclosure({
|
|
|
924
1523
|
defaultOpen = false,
|
|
925
1524
|
open: controlledOpen,
|
|
926
1525
|
onOpenChange,
|
|
1526
|
+
disabled = false,
|
|
927
1527
|
className,
|
|
928
1528
|
variant = "card"
|
|
929
1529
|
}) {
|
|
930
|
-
const reactId =
|
|
1530
|
+
const reactId = useId3();
|
|
931
1531
|
const headerId = `${reactId}-header`;
|
|
932
1532
|
const panelId = `${reactId}-panel`;
|
|
933
|
-
const [internalOpen, setInternalOpen] =
|
|
1533
|
+
const [internalOpen, setInternalOpen] = useState7(defaultOpen);
|
|
934
1534
|
const isControlled = controlledOpen !== void 0;
|
|
935
1535
|
const isOpen = isControlled ? controlledOpen : internalOpen;
|
|
936
1536
|
const toggle = () => {
|
|
1537
|
+
if (disabled) return;
|
|
937
1538
|
const next = !isOpen;
|
|
938
1539
|
if (isControlled) {
|
|
939
1540
|
onOpenChange?.(next);
|
|
@@ -942,17 +1543,18 @@ function Disclosure({
|
|
|
942
1543
|
onOpenChange?.(next);
|
|
943
1544
|
}
|
|
944
1545
|
};
|
|
945
|
-
return /* @__PURE__ */
|
|
1546
|
+
return /* @__PURE__ */ jsxs18(
|
|
946
1547
|
"div",
|
|
947
1548
|
{
|
|
948
1549
|
className: cn(
|
|
949
1550
|
"fractal-disclosure",
|
|
950
1551
|
variant === "card" && "fractal-disclosure--card",
|
|
951
1552
|
isOpen && "fractal-disclosure--open",
|
|
1553
|
+
disabled && "fractal-disclosure--disabled",
|
|
952
1554
|
className
|
|
953
1555
|
),
|
|
954
1556
|
children: [
|
|
955
|
-
/* @__PURE__ */
|
|
1557
|
+
/* @__PURE__ */ jsxs18(
|
|
956
1558
|
"button",
|
|
957
1559
|
{
|
|
958
1560
|
type: "button",
|
|
@@ -960,15 +1562,16 @@ function Disclosure({
|
|
|
960
1562
|
className: "fractal-disclosure-trigger",
|
|
961
1563
|
"aria-expanded": isOpen,
|
|
962
1564
|
"aria-controls": panelId,
|
|
1565
|
+
disabled,
|
|
963
1566
|
onClick: toggle,
|
|
964
1567
|
children: [
|
|
965
|
-
/* @__PURE__ */
|
|
966
|
-
/* @__PURE__ */
|
|
967
|
-
meta && /* @__PURE__ */
|
|
1568
|
+
/* @__PURE__ */ jsx21("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ jsx21(ChevronDown2, { size: 16 }) : /* @__PURE__ */ jsx21(ChevronRight2, { size: 16 }) }),
|
|
1569
|
+
/* @__PURE__ */ jsx21("span", { className: "fractal-disclosure-title", children: title }),
|
|
1570
|
+
meta && /* @__PURE__ */ jsx21("span", { className: "fractal-disclosure-meta", children: meta })
|
|
968
1571
|
]
|
|
969
1572
|
}
|
|
970
1573
|
),
|
|
971
|
-
/* @__PURE__ */
|
|
1574
|
+
/* @__PURE__ */ jsx21(
|
|
972
1575
|
"div",
|
|
973
1576
|
{
|
|
974
1577
|
id: panelId,
|
|
@@ -976,7 +1579,7 @@ function Disclosure({
|
|
|
976
1579
|
"aria-labelledby": headerId,
|
|
977
1580
|
className: "fractal-disclosure-panel",
|
|
978
1581
|
hidden: !isOpen,
|
|
979
|
-
children: /* @__PURE__ */
|
|
1582
|
+
children: /* @__PURE__ */ jsx21("div", { className: "fractal-disclosure-panel-inner", children })
|
|
980
1583
|
}
|
|
981
1584
|
)
|
|
982
1585
|
]
|
|
@@ -984,39 +1587,260 @@ function Disclosure({
|
|
|
984
1587
|
);
|
|
985
1588
|
}
|
|
986
1589
|
|
|
1590
|
+
// src/components/LatticeLoader/LatticeLoader.tsx
|
|
1591
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1592
|
+
var LATTICE_COUNT = 160;
|
|
1593
|
+
var WAVE_PERIOD = 80;
|
|
1594
|
+
function LatticeLoader({ className, label = "Loading", ...props }) {
|
|
1595
|
+
return /* @__PURE__ */ jsx22(
|
|
1596
|
+
"span",
|
|
1597
|
+
{
|
|
1598
|
+
"aria-label": label,
|
|
1599
|
+
className: cn("fractal-lattice-loader", className),
|
|
1600
|
+
role: "progressbar",
|
|
1601
|
+
...props,
|
|
1602
|
+
children: Array.from({ length: LATTICE_COUNT }, (_, index) => /* @__PURE__ */ jsx22(
|
|
1603
|
+
"span",
|
|
1604
|
+
{
|
|
1605
|
+
"aria-hidden": "true",
|
|
1606
|
+
className: "fractal-lattice-loader__cell",
|
|
1607
|
+
style: { "--fractal-lattice-index": index % WAVE_PERIOD }
|
|
1608
|
+
},
|
|
1609
|
+
index
|
|
1610
|
+
))
|
|
1611
|
+
}
|
|
1612
|
+
);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
// src/components/Ghost/Ghost.tsx
|
|
1616
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1617
|
+
var toCssLength = (value) => typeof value === "number" ? `${value}px` : value;
|
|
1618
|
+
function Ghost({ className, width, height, radius, style, ...props }) {
|
|
1619
|
+
return /* @__PURE__ */ jsx23(
|
|
1620
|
+
"div",
|
|
1621
|
+
{
|
|
1622
|
+
"aria-hidden": "true",
|
|
1623
|
+
className: cn("fractal-ghost", className),
|
|
1624
|
+
style: {
|
|
1625
|
+
width: toCssLength(width),
|
|
1626
|
+
height: toCssLength(height),
|
|
1627
|
+
borderRadius: toCssLength(radius),
|
|
1628
|
+
...style
|
|
1629
|
+
},
|
|
1630
|
+
...props
|
|
1631
|
+
}
|
|
1632
|
+
);
|
|
1633
|
+
}
|
|
1634
|
+
function GhostLine({ className, size = "md", width = "100%", ...props }) {
|
|
1635
|
+
return /* @__PURE__ */ jsx23(Ghost, { className: cn("fractal-ghost-line", `fractal-ghost-line--${size}`, className), width, ...props });
|
|
1636
|
+
}
|
|
1637
|
+
function ButtonGhost({ className, size = "md", iconOnly = false, width, ...props }) {
|
|
1638
|
+
return /* @__PURE__ */ jsx23(Ghost, { className: cn("fractal-ghost-button", `fractal-ghost-button--${size}`, iconOnly && "fractal-ghost-button--icon-only", className), width, ...props });
|
|
1639
|
+
}
|
|
1640
|
+
function CardGhost({ className, lines = 3, showHeader = true, ...props }) {
|
|
1641
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-card", className), ...props, children: [
|
|
1642
|
+
showHeader && /* @__PURE__ */ jsx23(GhostLine, { width: "38%" }),
|
|
1643
|
+
/* @__PURE__ */ jsx23("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx23(GhostLine, { width: index === lines - 1 ? "62%" : "100%" }, index)) })
|
|
1644
|
+
] });
|
|
1645
|
+
}
|
|
1646
|
+
function DataTableGhost({
|
|
1647
|
+
className,
|
|
1648
|
+
showHeader = true,
|
|
1649
|
+
headers,
|
|
1650
|
+
columns = 4,
|
|
1651
|
+
rows = 5,
|
|
1652
|
+
columnWidths,
|
|
1653
|
+
size = "md",
|
|
1654
|
+
...props
|
|
1655
|
+
}) {
|
|
1656
|
+
const cells = Array.from({ length: columns }, (_, index) => index);
|
|
1657
|
+
return /* @__PURE__ */ jsx23("div", { "aria-busy": "true", "aria-label": "Loading table", className: cn("fractal-ghost-table", `fractal-ghost-table--${size}`, className), role: "status", ...props, children: /* @__PURE__ */ jsxs19("table", { className: "fractal-ghost-table__table", children: [
|
|
1658
|
+
(showHeader || headers) && /* @__PURE__ */ jsx23("thead", { children: /* @__PURE__ */ jsx23("tr", { className: "fractal-ghost-table__head-row", children: cells.map((index) => /* @__PURE__ */ jsx23("th", { style: { width: columnWidths?.[index] }, children: headers?.[index] ?? /* @__PURE__ */ jsx23(GhostLine, { size: "sm", width: index === columns - 1 ? "62%" : "76%" }) }, index)) }) }),
|
|
1659
|
+
/* @__PURE__ */ jsx23("tbody", { children: Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ jsx23("tr", { className: "fractal-ghost-table__row", children: cells.map((columnIndex) => /* @__PURE__ */ jsx23("td", { style: { width: columnWidths?.[columnIndex] }, children: /* @__PURE__ */ jsx23(GhostLine, { width: `${[72, 54, 82, 63, 46][(rowIndex + columnIndex) % 5]}%` }) }, columnIndex)) }, rowIndex)) })
|
|
1660
|
+
] }) });
|
|
1661
|
+
}
|
|
1662
|
+
function InputGhost({ className, labelWidth = "26%", ...props }) {
|
|
1663
|
+
return /* @__PURE__ */ jsx23(FormFieldGhost, { className, labelWidth, ...props });
|
|
1664
|
+
}
|
|
1665
|
+
function TextareaGhost({ className, labelWidth = "26%", ...props }) {
|
|
1666
|
+
return /* @__PURE__ */ jsx23(FormFieldGhost, { className, labelWidth, multiline: true, ...props });
|
|
1667
|
+
}
|
|
1668
|
+
function LabelGhost({ className, width = "26%", ...props }) {
|
|
1669
|
+
return /* @__PURE__ */ jsx23(GhostLine, { className: cn("fractal-ghost-label", className), size: "sm", width, ...props });
|
|
1670
|
+
}
|
|
1671
|
+
function FormFieldGhost({ className, labelWidth = "26%", multiline = false, ...props }) {
|
|
1672
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-field", className), ...props, children: [
|
|
1673
|
+
/* @__PURE__ */ jsx23(LabelGhost, { width: labelWidth }),
|
|
1674
|
+
/* @__PURE__ */ jsx23(Ghost, { className: cn("fractal-ghost-field__control", multiline && "fractal-ghost-field__control--multiline") })
|
|
1675
|
+
] });
|
|
1676
|
+
}
|
|
1677
|
+
function AlertGhost({ className, ...props }) {
|
|
1678
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-alert", className), ...props, children: [
|
|
1679
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "30%" }),
|
|
1680
|
+
/* @__PURE__ */ jsx23(GhostLine, { size: "sm", width: "78%" })
|
|
1681
|
+
] });
|
|
1682
|
+
}
|
|
1683
|
+
function CheckboxGhost({ className, ...props }) {
|
|
1684
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-choice", className), ...props, children: [
|
|
1685
|
+
/* @__PURE__ */ jsx23(Ghost, { className: "fractal-ghost-choice__control" }),
|
|
1686
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "42%" })
|
|
1687
|
+
] });
|
|
1688
|
+
}
|
|
1689
|
+
var ToggleGhost = CheckboxGhost;
|
|
1690
|
+
function ChipGhost({ className, width = 74, ...props }) {
|
|
1691
|
+
return /* @__PURE__ */ jsx23(Ghost, { className: cn("fractal-ghost-chip", className), height: 24, width, ...props });
|
|
1692
|
+
}
|
|
1693
|
+
function LinkGhost({ className, width = 96, ...props }) {
|
|
1694
|
+
return /* @__PURE__ */ jsx23(GhostLine, { className: cn("fractal-ghost-link", className), size: "sm", width, ...props });
|
|
1695
|
+
}
|
|
1696
|
+
var TextButtonGhost = LinkGhost;
|
|
1697
|
+
function DropdownGhost({ className, ...props }) {
|
|
1698
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropdown", className), ...props, children: [
|
|
1699
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "38%" }),
|
|
1700
|
+
/* @__PURE__ */ jsx23(Ghost, { className: "fractal-ghost-dropdown__chevron" })
|
|
1701
|
+
] });
|
|
1702
|
+
}
|
|
1703
|
+
function ContentSwitcherGhost({ className, options = 3, ...props }) {
|
|
1704
|
+
return /* @__PURE__ */ jsx23("div", { "aria-hidden": "true", className: cn("fractal-ghost-switcher", className), ...props, children: Array.from({ length: options }, (_, index) => /* @__PURE__ */ jsx23(Ghost, {}, index)) });
|
|
1705
|
+
}
|
|
1706
|
+
var TabsGhost = ContentSwitcherGhost;
|
|
1707
|
+
function DisclosureGhost({ className, ...props }) {
|
|
1708
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-disclosure", className), ...props, children: [
|
|
1709
|
+
/* @__PURE__ */ jsx23(Ghost, { className: "fractal-ghost-disclosure__icon" }),
|
|
1710
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "42%" })
|
|
1711
|
+
] });
|
|
1712
|
+
}
|
|
1713
|
+
function PaginationGhost({ className, pages = 5, ...props }) {
|
|
1714
|
+
return /* @__PURE__ */ jsx23("div", { "aria-hidden": "true", className: cn("fractal-ghost-pagination", className), ...props, children: Array.from({ length: pages }, (_, index) => /* @__PURE__ */ jsx23(Ghost, {}, index)) });
|
|
1715
|
+
}
|
|
1716
|
+
function FileDropzoneGhost({ className, ...props }) {
|
|
1717
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropzone", className), ...props, children: [
|
|
1718
|
+
/* @__PURE__ */ jsx23(Ghost, { className: "fractal-ghost-dropzone__icon" }),
|
|
1719
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "26%" }),
|
|
1720
|
+
/* @__PURE__ */ jsx23(GhostLine, { size: "sm", width: "46%" })
|
|
1721
|
+
] });
|
|
1722
|
+
}
|
|
1723
|
+
function PromptCardGhost({ className, ...props }) {
|
|
1724
|
+
return /* @__PURE__ */ jsx23(CardGhost, { className: cn("fractal-ghost-prompt-card", className), lines: 4, ...props });
|
|
1725
|
+
}
|
|
1726
|
+
function ConversationGhost({
|
|
1727
|
+
className,
|
|
1728
|
+
"aria-label": ariaLabel = "Loading conversation",
|
|
1729
|
+
...props
|
|
1730
|
+
}) {
|
|
1731
|
+
return /* @__PURE__ */ jsxs19(
|
|
1732
|
+
"div",
|
|
1733
|
+
{
|
|
1734
|
+
"aria-busy": "true",
|
|
1735
|
+
"aria-label": ariaLabel,
|
|
1736
|
+
className: cn("fractal-ghost-conversation", className),
|
|
1737
|
+
role: "status",
|
|
1738
|
+
...props,
|
|
1739
|
+
children: [
|
|
1740
|
+
/* @__PURE__ */ jsx23("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--user", children: /* @__PURE__ */ jsxs19("div", { className: "fractal-ghost-conversation__bubble", children: [
|
|
1741
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "100%" }),
|
|
1742
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "86%" }),
|
|
1743
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "64%" })
|
|
1744
|
+
] }) }),
|
|
1745
|
+
/* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--assistant", children: [
|
|
1746
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "92%" }),
|
|
1747
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "78%" }),
|
|
1748
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "58%" })
|
|
1749
|
+
] })
|
|
1750
|
+
]
|
|
1751
|
+
}
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1754
|
+
function SortableTableGhost(props) {
|
|
1755
|
+
return /* @__PURE__ */ jsx23(DataTableGhost, { ...props });
|
|
1756
|
+
}
|
|
1757
|
+
function SidebarGhost({ className, items = 6, ...props }) {
|
|
1758
|
+
return /* @__PURE__ */ jsxs19("aside", { "aria-hidden": "true", className: cn("fractal-ghost-sidebar", className), ...props, children: [
|
|
1759
|
+
/* @__PURE__ */ jsx23(Ghost, { className: "fractal-ghost-sidebar__brand" }),
|
|
1760
|
+
/* @__PURE__ */ jsx23("div", { className: "fractal-ghost-sidebar__items", children: Array.from({ length: items }, (_, index) => /* @__PURE__ */ jsxs19("div", { className: "fractal-ghost-sidebar__item", children: [
|
|
1761
|
+
/* @__PURE__ */ jsx23(Ghost, {}),
|
|
1762
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: `${[54, 68, 44, 61][index % 4]}%` })
|
|
1763
|
+
] }, index)) })
|
|
1764
|
+
] });
|
|
1765
|
+
}
|
|
1766
|
+
function ModalGhost({ className, title, lines = 3, ...props }) {
|
|
1767
|
+
return /* @__PURE__ */ jsx23(SurfaceGhost, { className: cn("fractal-ghost-modal", className), title, lines, ...props });
|
|
1768
|
+
}
|
|
1769
|
+
function SidePanelGhost({ className, title, lines = 5, ...props }) {
|
|
1770
|
+
return /* @__PURE__ */ jsx23(SurfaceGhost, { className: cn("fractal-ghost-side-panel", className), title, lines, ...props });
|
|
1771
|
+
}
|
|
1772
|
+
function SurfaceGhost({ className, title, lines = 3, ...props }) {
|
|
1773
|
+
return /* @__PURE__ */ jsxs19("div", { "aria-hidden": "true", className: cn("fractal-ghost-surface", className), ...props, children: [
|
|
1774
|
+
/* @__PURE__ */ jsxs19("div", { className: "fractal-ghost-surface__header", children: [
|
|
1775
|
+
/* @__PURE__ */ jsx23(GhostLine, { width: "42%" }),
|
|
1776
|
+
/* @__PURE__ */ jsx23(Ghost, { className: "fractal-ghost-surface__close" })
|
|
1777
|
+
] }),
|
|
1778
|
+
title && /* @__PURE__ */ jsx23("div", { className: "fractal-ghost-surface__title", children: title }),
|
|
1779
|
+
/* @__PURE__ */ jsx23("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx23(GhostLine, { width: index === lines - 1 ? "64%" : "100%" }, index)) })
|
|
1780
|
+
] });
|
|
1781
|
+
}
|
|
1782
|
+
|
|
987
1783
|
// src/components/Sidebar/Sidebar.tsx
|
|
988
|
-
import * as
|
|
989
|
-
import { jsx as
|
|
990
|
-
var Sidebar =
|
|
991
|
-
({ className, width, style, ...props }, ref) => /* @__PURE__ */
|
|
1784
|
+
import * as React13 from "react";
|
|
1785
|
+
import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1786
|
+
var Sidebar = React13.forwardRef(
|
|
1787
|
+
({ className, width, compact = false, style, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
992
1788
|
"aside",
|
|
993
1789
|
{
|
|
994
1790
|
ref,
|
|
995
1791
|
className: cn("fractal-sidebar", className),
|
|
1792
|
+
"data-compact": compact || void 0,
|
|
996
1793
|
style: { ...style, ...width ? { "--fractal-sidebar-width": width } : {} },
|
|
997
1794
|
...props
|
|
998
1795
|
}
|
|
999
1796
|
)
|
|
1000
1797
|
);
|
|
1001
1798
|
Sidebar.displayName = "Sidebar";
|
|
1002
|
-
var SidebarHeader =
|
|
1003
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1799
|
+
var SidebarHeader = React13.forwardRef(
|
|
1800
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx24("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
|
|
1004
1801
|
);
|
|
1005
1802
|
SidebarHeader.displayName = "SidebarHeader";
|
|
1006
|
-
var SidebarBrand =
|
|
1007
|
-
({ className, type = "button", ...props }, ref) => /* @__PURE__ */
|
|
1803
|
+
var SidebarBrand = React13.forwardRef(
|
|
1804
|
+
({ className, type = "button", ...props }, ref) => /* @__PURE__ */ jsx24("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
|
|
1008
1805
|
);
|
|
1009
1806
|
SidebarBrand.displayName = "SidebarBrand";
|
|
1010
|
-
|
|
1011
|
-
|
|
1807
|
+
function SidebarAccountMenu({
|
|
1808
|
+
name,
|
|
1809
|
+
items,
|
|
1810
|
+
onSelect,
|
|
1811
|
+
triggerLabel = "Account menu",
|
|
1812
|
+
icon,
|
|
1813
|
+
className
|
|
1814
|
+
}) {
|
|
1815
|
+
return /* @__PURE__ */ jsx24(
|
|
1816
|
+
Dropdown,
|
|
1817
|
+
{
|
|
1818
|
+
align: "left",
|
|
1819
|
+
className: cn("fractal-sidebar__account", className),
|
|
1820
|
+
items,
|
|
1821
|
+
onSelect,
|
|
1822
|
+
panelClassName: "fractal-sidebar__account-panel",
|
|
1823
|
+
selectedValue: "",
|
|
1824
|
+
triggerClassName: "fractal-sidebar__account-trigger",
|
|
1825
|
+
triggerContent: /* @__PURE__ */ jsxs20(Fragment3, { children: [
|
|
1826
|
+
icon && /* @__PURE__ */ jsx24("span", { className: "fractal-sidebar__account-icon", "aria-hidden": "true", children: icon }),
|
|
1827
|
+
/* @__PURE__ */ jsx24("span", { className: "fractal-sidebar__account-name", children: name })
|
|
1828
|
+
] }),
|
|
1829
|
+
triggerLabel,
|
|
1830
|
+
triggerVariant: "tertiary"
|
|
1831
|
+
}
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
var SidebarNav = React13.forwardRef(
|
|
1835
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx24("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
|
|
1012
1836
|
);
|
|
1013
1837
|
SidebarNav.displayName = "SidebarNav";
|
|
1014
|
-
var SidebarSection =
|
|
1015
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1838
|
+
var SidebarSection = React13.forwardRef(
|
|
1839
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx24("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
|
|
1016
1840
|
);
|
|
1017
1841
|
SidebarSection.displayName = "SidebarSection";
|
|
1018
|
-
var SidebarNavItem =
|
|
1019
|
-
({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */
|
|
1842
|
+
var SidebarNavItem = React13.forwardRef(
|
|
1843
|
+
({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ jsxs20(
|
|
1020
1844
|
"button",
|
|
1021
1845
|
{
|
|
1022
1846
|
ref,
|
|
@@ -1026,42 +1850,28 @@ var SidebarNavItem = React10.forwardRef(
|
|
|
1026
1850
|
"aria-current": active ? "page" : void 0,
|
|
1027
1851
|
...props,
|
|
1028
1852
|
children: [
|
|
1029
|
-
icon && /* @__PURE__ */
|
|
1030
|
-
/* @__PURE__ */
|
|
1031
|
-
endAdornment && /* @__PURE__ */
|
|
1853
|
+
icon && /* @__PURE__ */ jsx24("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
|
|
1854
|
+
/* @__PURE__ */ jsx24("span", { className: "fractal-sidebar__nav-item-label", children }),
|
|
1855
|
+
endAdornment && /* @__PURE__ */ jsx24("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
|
|
1032
1856
|
]
|
|
1033
1857
|
}
|
|
1034
1858
|
)
|
|
1035
1859
|
);
|
|
1036
1860
|
SidebarNavItem.displayName = "SidebarNavItem";
|
|
1037
|
-
var SidebarFooter =
|
|
1038
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1861
|
+
var SidebarFooter = React13.forwardRef(
|
|
1862
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx24("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
|
|
1039
1863
|
);
|
|
1040
1864
|
SidebarFooter.displayName = "SidebarFooter";
|
|
1041
1865
|
|
|
1042
|
-
// src/components/PageHeader/PageHeader.tsx
|
|
1043
|
-
import * as React11 from "react";
|
|
1044
|
-
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1045
|
-
var PageHeader = React11.forwardRef(
|
|
1046
|
-
({ title, description, actions, className, ...props }, ref) => /* @__PURE__ */ jsxs13("div", { ref, className: cn("fractal-page-header", className), ...props, children: [
|
|
1047
|
-
/* @__PURE__ */ jsxs13("div", { className: "fractal-page-header__content", children: [
|
|
1048
|
-
/* @__PURE__ */ jsx16("h1", { className: "fractal-page-header__title", children: title }),
|
|
1049
|
-
description && /* @__PURE__ */ jsx16("p", { className: "fractal-page-header__description", children: description })
|
|
1050
|
-
] }),
|
|
1051
|
-
actions && /* @__PURE__ */ jsx16("div", { className: "fractal-page-header__actions", children: actions })
|
|
1052
|
-
] })
|
|
1053
|
-
);
|
|
1054
|
-
PageHeader.displayName = "PageHeader";
|
|
1055
|
-
|
|
1056
1866
|
// src/components/SidePanel/SidePanel.tsx
|
|
1057
1867
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1058
1868
|
import { Close } from "@mirror-physics/fractal-icons";
|
|
1059
|
-
import { jsx as
|
|
1060
|
-
function SidePanel({ open, onClose, title, description, children, footer, size = "md", className }) {
|
|
1869
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1870
|
+
function SidePanel({ open, onClose, title, description, children, footer, size = "md", loading = false, loadingLabel = "Loading", className }) {
|
|
1061
1871
|
useEscapeDismiss(80, onClose, open);
|
|
1062
1872
|
if (!open) return null;
|
|
1063
1873
|
return createPortal2(
|
|
1064
|
-
/* @__PURE__ */
|
|
1874
|
+
/* @__PURE__ */ jsx25("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ jsxs21(
|
|
1065
1875
|
"aside",
|
|
1066
1876
|
{
|
|
1067
1877
|
className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
|
|
@@ -1070,15 +1880,15 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
|
|
|
1070
1880
|
role: "dialog",
|
|
1071
1881
|
onMouseDown: (event) => event.stopPropagation(),
|
|
1072
1882
|
children: [
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
description && /* @__PURE__ */
|
|
1883
|
+
/* @__PURE__ */ jsxs21("header", { className: "fractal-side-panel__header", children: [
|
|
1884
|
+
/* @__PURE__ */ jsxs21("div", { className: "fractal-side-panel__heading", children: [
|
|
1885
|
+
typeof title === "string" ? /* @__PURE__ */ jsx25("h2", { className: "fractal-side-panel__title", children: title }) : /* @__PURE__ */ jsx25("div", { className: "fractal-side-panel__title", children: title }),
|
|
1886
|
+
description && /* @__PURE__ */ jsx25("p", { className: "fractal-side-panel__description", children: description })
|
|
1077
1887
|
] }),
|
|
1078
|
-
/* @__PURE__ */
|
|
1888
|
+
/* @__PURE__ */ jsx25("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ jsx25(Close, { size: 18 }) })
|
|
1079
1889
|
] }),
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
footer && /* @__PURE__ */
|
|
1890
|
+
/* @__PURE__ */ jsx25("div", { "aria-busy": loading || void 0, className: cn("fractal-side-panel__body", loading && "fractal-side-panel__body--loading"), children: loading ? /* @__PURE__ */ jsx25(UILoader, { label: loadingLabel }) : children }),
|
|
1891
|
+
footer && /* @__PURE__ */ jsx25("footer", { className: "fractal-side-panel__footer", children: footer })
|
|
1082
1892
|
]
|
|
1083
1893
|
}
|
|
1084
1894
|
) }),
|
|
@@ -1087,48 +1897,271 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
|
|
|
1087
1897
|
}
|
|
1088
1898
|
|
|
1089
1899
|
// src/components/Textarea/Textarea.tsx
|
|
1090
|
-
import * as
|
|
1091
|
-
import { jsx as
|
|
1092
|
-
var Textarea =
|
|
1093
|
-
({ className, ...props }, ref) => /* @__PURE__ */
|
|
1900
|
+
import * as React14 from "react";
|
|
1901
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
1902
|
+
var Textarea = React14.forwardRef(
|
|
1903
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx26("textarea", { ref, className: cn("fractal-textarea", className), ...props })
|
|
1094
1904
|
);
|
|
1095
1905
|
Textarea.displayName = "Textarea";
|
|
1906
|
+
|
|
1907
|
+
// src/components/TextButton/TextButton.tsx
|
|
1908
|
+
import * as React15 from "react";
|
|
1909
|
+
import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1910
|
+
var TextButton = React15.forwardRef(
|
|
1911
|
+
({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ jsxs22(
|
|
1912
|
+
"button",
|
|
1913
|
+
{
|
|
1914
|
+
ref,
|
|
1915
|
+
className: cn("fractal-text-button", `fractal-text-button--${size}`, `fractal-text-button--${tone}`, className),
|
|
1916
|
+
type: "button",
|
|
1917
|
+
...props,
|
|
1918
|
+
children: [
|
|
1919
|
+
icon && iconPosition === "start" && /* @__PURE__ */ jsx27("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon }),
|
|
1920
|
+
/* @__PURE__ */ jsx27("span", { children }),
|
|
1921
|
+
icon && iconPosition === "end" && /* @__PURE__ */ jsx27("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon })
|
|
1922
|
+
]
|
|
1923
|
+
}
|
|
1924
|
+
)
|
|
1925
|
+
);
|
|
1926
|
+
TextButton.displayName = "TextButton";
|
|
1927
|
+
|
|
1928
|
+
// src/components/FileDropzone/FileDropzone.tsx
|
|
1929
|
+
import * as React16 from "react";
|
|
1930
|
+
import { Close as Close2, FileArrowUp } from "@mirror-physics/fractal-icons";
|
|
1931
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1932
|
+
function FileDropzone({
|
|
1933
|
+
files,
|
|
1934
|
+
onFilesChange,
|
|
1935
|
+
accept,
|
|
1936
|
+
multiple = true,
|
|
1937
|
+
disabled = false,
|
|
1938
|
+
title = "Drop files here or click to browse",
|
|
1939
|
+
description = "Files stay attached to this record.",
|
|
1940
|
+
className
|
|
1941
|
+
}) {
|
|
1942
|
+
const inputId = React16.useId();
|
|
1943
|
+
const inputRef = React16.useRef(null);
|
|
1944
|
+
const [isDragging, setIsDragging] = React16.useState(false);
|
|
1945
|
+
const addFiles = (nextFiles) => {
|
|
1946
|
+
if (disabled) return;
|
|
1947
|
+
const additions = Array.from(nextFiles);
|
|
1948
|
+
if (additions.length === 0) return;
|
|
1949
|
+
onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
|
|
1950
|
+
};
|
|
1951
|
+
return /* @__PURE__ */ jsxs23("div", { className: cn("fractal-file-dropzone", className), children: [
|
|
1952
|
+
/* @__PURE__ */ jsx28(
|
|
1953
|
+
"input",
|
|
1954
|
+
{
|
|
1955
|
+
ref: inputRef,
|
|
1956
|
+
id: inputId,
|
|
1957
|
+
className: "fractal-file-dropzone__input",
|
|
1958
|
+
type: "file",
|
|
1959
|
+
accept,
|
|
1960
|
+
multiple,
|
|
1961
|
+
disabled,
|
|
1962
|
+
onChange: (event) => {
|
|
1963
|
+
if (event.target.files) addFiles(event.target.files);
|
|
1964
|
+
event.target.value = "";
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
),
|
|
1968
|
+
/* @__PURE__ */ jsxs23(
|
|
1969
|
+
"button",
|
|
1970
|
+
{
|
|
1971
|
+
className: "fractal-file-dropzone__target",
|
|
1972
|
+
"data-dragging": isDragging || void 0,
|
|
1973
|
+
type: "button",
|
|
1974
|
+
disabled,
|
|
1975
|
+
onClick: () => inputRef.current?.click(),
|
|
1976
|
+
onDragEnter: (event) => {
|
|
1977
|
+
event.preventDefault();
|
|
1978
|
+
if (!disabled) setIsDragging(true);
|
|
1979
|
+
},
|
|
1980
|
+
onDragOver: (event) => event.preventDefault(),
|
|
1981
|
+
onDragLeave: (event) => {
|
|
1982
|
+
event.preventDefault();
|
|
1983
|
+
setIsDragging(false);
|
|
1984
|
+
},
|
|
1985
|
+
onDrop: (event) => {
|
|
1986
|
+
event.preventDefault();
|
|
1987
|
+
setIsDragging(false);
|
|
1988
|
+
addFiles(event.dataTransfer.files);
|
|
1989
|
+
},
|
|
1990
|
+
children: [
|
|
1991
|
+
/* @__PURE__ */ jsx28(FileArrowUp, { "aria-hidden": "true", size: 20 }),
|
|
1992
|
+
/* @__PURE__ */ jsxs23("span", { className: "fractal-file-dropzone__copy", children: [
|
|
1993
|
+
/* @__PURE__ */ jsx28("span", { className: "fractal-file-dropzone__title", children: title }),
|
|
1994
|
+
description && /* @__PURE__ */ jsx28("span", { className: "fractal-file-dropzone__description", children: description })
|
|
1995
|
+
] })
|
|
1996
|
+
]
|
|
1997
|
+
}
|
|
1998
|
+
),
|
|
1999
|
+
files.length > 0 && /* @__PURE__ */ jsx28("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ jsxs23("li", { className: "fractal-file-dropzone__file", children: [
|
|
2000
|
+
/* @__PURE__ */ jsx28("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
|
|
2001
|
+
/* @__PURE__ */ jsx28("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
|
|
2002
|
+
/* @__PURE__ */ jsx28(
|
|
2003
|
+
"button",
|
|
2004
|
+
{
|
|
2005
|
+
className: "fractal-file-dropzone__remove",
|
|
2006
|
+
type: "button",
|
|
2007
|
+
"aria-label": `Remove ${file.name}`,
|
|
2008
|
+
disabled,
|
|
2009
|
+
onClick: () => onFilesChange(files.filter((_, fileIndex) => fileIndex !== index)),
|
|
2010
|
+
children: /* @__PURE__ */ jsx28(Close2, { "aria-hidden": "true", size: 14 })
|
|
2011
|
+
}
|
|
2012
|
+
)
|
|
2013
|
+
] }, `${file.name}-${file.size}-${index}`)) })
|
|
2014
|
+
] });
|
|
2015
|
+
}
|
|
2016
|
+
function formatFileSize(bytes) {
|
|
2017
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
2018
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
2019
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
// src/components/Pagination/Pagination.tsx
|
|
2023
|
+
import { ArrowLeft, ArrowRight } from "@mirror-physics/fractal-icons";
|
|
2024
|
+
import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2025
|
+
function Pagination({
|
|
2026
|
+
page,
|
|
2027
|
+
pageSize,
|
|
2028
|
+
totalItems,
|
|
2029
|
+
onPageChange,
|
|
2030
|
+
pageSizeOptions,
|
|
2031
|
+
onPageSizeChange,
|
|
2032
|
+
ariaLabel = "Pagination",
|
|
2033
|
+
className
|
|
2034
|
+
}) {
|
|
2035
|
+
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
|
|
2036
|
+
const currentPage = Math.min(Math.max(page, 1), totalPages);
|
|
2037
|
+
const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
|
|
2038
|
+
const end = Math.min(currentPage * pageSize, totalItems);
|
|
2039
|
+
const canChangePageSize = pageSizeOptions != null && pageSizeOptions.length > 0 && onPageSizeChange != null;
|
|
2040
|
+
return /* @__PURE__ */ jsxs24("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
|
|
2041
|
+
/* @__PURE__ */ jsx29("span", { className: "fractal-pagination__summary", children: totalItems === 0 ? "No results" : `${start}-${end} of ${totalItems}` }),
|
|
2042
|
+
/* @__PURE__ */ jsxs24("div", { className: "fractal-pagination__controls", children: [
|
|
2043
|
+
canChangePageSize && /* @__PURE__ */ jsx29(
|
|
2044
|
+
Dropdown,
|
|
2045
|
+
{
|
|
2046
|
+
align: "right",
|
|
2047
|
+
className: "fractal-pagination__page-size",
|
|
2048
|
+
direction: "up",
|
|
2049
|
+
items: pageSizeOptions.map((option) => ({
|
|
2050
|
+
value: String(option),
|
|
2051
|
+
description: `${option} per page`
|
|
2052
|
+
})),
|
|
2053
|
+
onSelect: (value) => onPageSizeChange(Number(value)),
|
|
2054
|
+
selectedValue: String(pageSize),
|
|
2055
|
+
size: "sm",
|
|
2056
|
+
triggerLabel: "Results per page",
|
|
2057
|
+
triggerVariant: "tertiary"
|
|
2058
|
+
}
|
|
2059
|
+
),
|
|
2060
|
+
/* @__PURE__ */ jsx29(
|
|
2061
|
+
"button",
|
|
2062
|
+
{
|
|
2063
|
+
className: "fractal-pagination__button",
|
|
2064
|
+
type: "button",
|
|
2065
|
+
"aria-label": "Previous page",
|
|
2066
|
+
title: "Previous page",
|
|
2067
|
+
disabled: currentPage === 1 || totalItems === 0,
|
|
2068
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
2069
|
+
children: /* @__PURE__ */ jsx29(ArrowLeft, { "aria-hidden": "true", size: 16 })
|
|
2070
|
+
}
|
|
2071
|
+
),
|
|
2072
|
+
/* @__PURE__ */ jsxs24("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
|
|
2073
|
+
currentPage,
|
|
2074
|
+
" of ",
|
|
2075
|
+
totalPages
|
|
2076
|
+
] }),
|
|
2077
|
+
/* @__PURE__ */ jsx29(
|
|
2078
|
+
"button",
|
|
2079
|
+
{
|
|
2080
|
+
className: "fractal-pagination__button",
|
|
2081
|
+
type: "button",
|
|
2082
|
+
"aria-label": "Next page",
|
|
2083
|
+
title: "Next page",
|
|
2084
|
+
disabled: currentPage === totalPages || totalItems === 0,
|
|
2085
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
2086
|
+
children: /* @__PURE__ */ jsx29(ArrowRight, { "aria-hidden": "true", size: 16 })
|
|
2087
|
+
}
|
|
2088
|
+
)
|
|
2089
|
+
] })
|
|
2090
|
+
] });
|
|
2091
|
+
}
|
|
1096
2092
|
export {
|
|
1097
2093
|
Alert,
|
|
1098
2094
|
AlertDescription,
|
|
2095
|
+
AlertGhost,
|
|
1099
2096
|
AlertTitle,
|
|
2097
|
+
Breadcrumbs,
|
|
1100
2098
|
Button,
|
|
2099
|
+
ButtonGhost,
|
|
1101
2100
|
Card,
|
|
1102
2101
|
CardContent,
|
|
1103
2102
|
CardDescription,
|
|
1104
2103
|
CardFooter,
|
|
2104
|
+
CardGhost,
|
|
1105
2105
|
CardHeader,
|
|
1106
2106
|
CardTitle,
|
|
2107
|
+
Checkbox,
|
|
2108
|
+
CheckboxGhost,
|
|
1107
2109
|
Chip,
|
|
2110
|
+
ChipGhost,
|
|
2111
|
+
CodeBlock,
|
|
2112
|
+
ContentSwitcher,
|
|
2113
|
+
ContentSwitcherGhost,
|
|
2114
|
+
ConversationGhost,
|
|
1108
2115
|
DataTable,
|
|
2116
|
+
DataTableGhost,
|
|
1109
2117
|
Disclosure,
|
|
2118
|
+
DisclosureGhost,
|
|
1110
2119
|
Dropdown,
|
|
2120
|
+
DropdownGhost,
|
|
1111
2121
|
FeatureCard,
|
|
2122
|
+
FileDropzone,
|
|
2123
|
+
FileDropzoneGhost,
|
|
1112
2124
|
FolderCard,
|
|
2125
|
+
Ghost,
|
|
2126
|
+
GhostLine,
|
|
1113
2127
|
Input,
|
|
2128
|
+
InputGhost,
|
|
1114
2129
|
Label,
|
|
2130
|
+
LabelGhost,
|
|
2131
|
+
LatticeLoader,
|
|
1115
2132
|
Link,
|
|
2133
|
+
LinkGhost,
|
|
1116
2134
|
Modal,
|
|
1117
|
-
|
|
2135
|
+
ModalGhost,
|
|
2136
|
+
NumberInput,
|
|
2137
|
+
Pagination,
|
|
2138
|
+
PaginationGhost,
|
|
2139
|
+
PasswordInput,
|
|
1118
2140
|
PromptCard,
|
|
2141
|
+
PromptCardGhost,
|
|
1119
2142
|
PromptGrid,
|
|
1120
2143
|
SidePanel,
|
|
2144
|
+
SidePanelGhost,
|
|
1121
2145
|
Sidebar,
|
|
2146
|
+
SidebarAccountMenu,
|
|
1122
2147
|
SidebarBrand,
|
|
1123
2148
|
SidebarFooter,
|
|
2149
|
+
SidebarGhost,
|
|
1124
2150
|
SidebarHeader,
|
|
1125
2151
|
SidebarNav,
|
|
1126
2152
|
SidebarNavItem,
|
|
1127
2153
|
SidebarSection,
|
|
1128
2154
|
SortableTable,
|
|
2155
|
+
SortableTableGhost,
|
|
1129
2156
|
Tabs,
|
|
2157
|
+
TabsGhost,
|
|
2158
|
+
TextButton,
|
|
2159
|
+
TextButtonGhost,
|
|
1130
2160
|
Textarea,
|
|
2161
|
+
TextareaGhost,
|
|
1131
2162
|
Toggle,
|
|
2163
|
+
ToggleGhost,
|
|
2164
|
+
UILoader,
|
|
1132
2165
|
cn,
|
|
1133
2166
|
useEscapeDismiss
|
|
1134
2167
|
};
|