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