@mirror-physics/fractal-ui 0.2.0-next.76 → 0.2.0-next.78
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/README.md +31 -0
- package/dist/chunk-QZX655IA.js +344 -0
- package/dist/chunk-QZX655IA.js.map +1 -0
- package/dist/column-editor.cjs +382 -0
- package/dist/column-editor.cjs.map +1 -0
- package/dist/column-editor.css +36 -0
- package/dist/column-editor.css.map +1 -0
- package/dist/column-editor.d.cts +20 -0
- package/dist/column-editor.d.ts +20 -0
- package/dist/column-editor.js +7 -0
- package/dist/column-editor.js.map +1 -0
- package/dist/index.cjs +854 -293
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +461 -39
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +51 -8
- package/dist/index.d.ts +51 -8
- package/dist/index.js +722 -496
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +34 -0
- package/package.json +10 -3
package/dist/index.cjs
CHANGED
|
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
33
|
Alert: () => Alert,
|
|
34
34
|
AlertDescription: () => AlertDescription,
|
|
35
35
|
AlertGhost: () => AlertGhost,
|
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
Chip: () => Chip,
|
|
50
50
|
ChipGhost: () => ChipGhost,
|
|
51
51
|
CodeBlock: () => CodeBlock,
|
|
52
|
+
ColumnEditor: () => ColumnEditor,
|
|
52
53
|
ContentSwitcher: () => ContentSwitcher,
|
|
53
54
|
ContentSwitcherGhost: () => ContentSwitcherGhost,
|
|
54
55
|
ConversationGhost: () => ConversationGhost,
|
|
@@ -110,7 +111,7 @@ __export(index_exports, {
|
|
|
110
111
|
cn: () => cn,
|
|
111
112
|
useEscapeDismiss: () => useEscapeDismiss
|
|
112
113
|
});
|
|
113
|
-
module.exports = __toCommonJS(
|
|
114
|
+
module.exports = __toCommonJS(src_exports);
|
|
114
115
|
|
|
115
116
|
// src/components/Button/Button.tsx
|
|
116
117
|
var React = __toESM(require("react"), 1);
|
|
@@ -1413,30 +1414,294 @@ function Modal({ open, onClose, title, children, danger, warn, footer, noClose,
|
|
|
1413
1414
|
);
|
|
1414
1415
|
}
|
|
1415
1416
|
|
|
1416
|
-
// src/components/
|
|
1417
|
+
// src/components/TableLayout/TableOverflowMenu.tsx
|
|
1418
|
+
var import_react4 = require("react");
|
|
1419
|
+
var import_react_dom3 = require("react-dom");
|
|
1420
|
+
var import_fractal_icons9 = require("@mirror-physics/fractal-icons");
|
|
1417
1421
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1418
|
-
function
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1422
|
+
function TableOverflowMenu({ items, label, disabled, onSelect }) {
|
|
1423
|
+
const id = (0, import_react4.useId)();
|
|
1424
|
+
const trigger = (0, import_react4.useRef)(null);
|
|
1425
|
+
const panel = (0, import_react4.useRef)(null);
|
|
1426
|
+
const initialLast = (0, import_react4.useRef)(false);
|
|
1427
|
+
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
1428
|
+
const [position, setPosition] = (0, import_react4.useState)({ top: 0, left: 0 });
|
|
1429
|
+
const buttons = () => [...panel.current?.querySelectorAll("button:not(:disabled)") ?? []];
|
|
1430
|
+
const close = (restore = true) => {
|
|
1431
|
+
setOpen(false);
|
|
1432
|
+
if (restore) trigger.current?.focus({ preventScroll: true });
|
|
1433
|
+
};
|
|
1434
|
+
useEscapeDismiss(100, () => close(), open);
|
|
1435
|
+
(0, import_react4.useLayoutEffect)(() => {
|
|
1436
|
+
if (!open || !trigger.current || !panel.current) return;
|
|
1437
|
+
const place = () => {
|
|
1438
|
+
const anchor = trigger.current.getBoundingClientRect();
|
|
1439
|
+
const menu = panel.current.getBoundingClientRect();
|
|
1440
|
+
const above = window.innerHeight - anchor.bottom < menu.height + 8 && anchor.top > window.innerHeight - anchor.bottom;
|
|
1441
|
+
setPosition({
|
|
1442
|
+
top: Math.max(8, Math.min(above ? anchor.top - menu.height - 4 : anchor.bottom + 4, window.innerHeight - menu.height - 8)),
|
|
1443
|
+
left: Math.max(8, Math.min(anchor.right - menu.width, window.innerWidth - menu.width - 8))
|
|
1444
|
+
});
|
|
1445
|
+
};
|
|
1446
|
+
place();
|
|
1447
|
+
const enabled = buttons();
|
|
1448
|
+
(initialLast.current ? enabled[enabled.length - 1] : enabled[0])?.focus({ preventScroll: true });
|
|
1449
|
+
if (enabled.length === 0) panel.current.focus({ preventScroll: true });
|
|
1450
|
+
const outside = (event) => {
|
|
1451
|
+
if (!panel.current?.contains(event.target) && !trigger.current?.contains(event.target)) setOpen(false);
|
|
1452
|
+
};
|
|
1453
|
+
const scroll = (event) => {
|
|
1454
|
+
if (!panel.current?.contains(event.target)) setOpen(false);
|
|
1455
|
+
};
|
|
1456
|
+
const observer = new ResizeObserver(place);
|
|
1457
|
+
observer.observe(panel.current);
|
|
1458
|
+
document.addEventListener("pointerdown", outside);
|
|
1459
|
+
window.addEventListener("scroll", scroll, true);
|
|
1460
|
+
window.addEventListener("resize", place);
|
|
1461
|
+
return () => {
|
|
1462
|
+
observer.disconnect();
|
|
1463
|
+
document.removeEventListener("pointerdown", outside);
|
|
1464
|
+
window.removeEventListener("scroll", scroll, true);
|
|
1465
|
+
window.removeEventListener("resize", place);
|
|
1466
|
+
};
|
|
1467
|
+
}, [open]);
|
|
1468
|
+
(0, import_react4.useLayoutEffect)(() => {
|
|
1469
|
+
if (disabled || items.length === 0) setOpen(false);
|
|
1470
|
+
}, [disabled, items.length]);
|
|
1471
|
+
if (items.length === 0) return null;
|
|
1472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "fractal-table-overflow-trigger", children: [
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1474
|
+
Button,
|
|
1475
|
+
{
|
|
1476
|
+
ref: trigger,
|
|
1477
|
+
buttonType: "ghost",
|
|
1478
|
+
controlSize: "sm",
|
|
1479
|
+
hasIconOnly: true,
|
|
1480
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_fractal_icons9.Ellipsis, { "aria-hidden": true }),
|
|
1481
|
+
"aria-label": label,
|
|
1482
|
+
"aria-haspopup": "menu",
|
|
1483
|
+
"aria-expanded": open,
|
|
1484
|
+
"aria-controls": open ? id : void 0,
|
|
1485
|
+
disabled,
|
|
1486
|
+
onClick: () => {
|
|
1487
|
+
initialLast.current = false;
|
|
1488
|
+
setOpen(!open);
|
|
1489
|
+
},
|
|
1490
|
+
onKeyDown: (event) => {
|
|
1491
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
1492
|
+
event.preventDefault();
|
|
1493
|
+
initialLast.current = event.key === "ArrowUp";
|
|
1494
|
+
setOpen(true);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
),
|
|
1499
|
+
open && (0, import_react_dom3.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1500
|
+
"div",
|
|
1501
|
+
{
|
|
1502
|
+
ref: panel,
|
|
1503
|
+
id,
|
|
1504
|
+
role: "menu",
|
|
1505
|
+
tabIndex: -1,
|
|
1506
|
+
"aria-label": label,
|
|
1507
|
+
className: "fractal-table-overflow-menu",
|
|
1508
|
+
style: position,
|
|
1509
|
+
onClick: (event) => event.stopPropagation(),
|
|
1510
|
+
onKeyDown: (event) => {
|
|
1511
|
+
event.stopPropagation();
|
|
1512
|
+
const enabled = buttons(), index = enabled.indexOf(document.activeElement);
|
|
1513
|
+
if (event.key === "Escape") {
|
|
1514
|
+
event.preventDefault();
|
|
1515
|
+
close();
|
|
1516
|
+
} else if (event.key === "Tab") {
|
|
1517
|
+
close();
|
|
1518
|
+
} else if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
|
|
1519
|
+
event.preventDefault();
|
|
1520
|
+
const next = event.key === "Home" ? 0 : event.key === "End" ? enabled.length - 1 : (index + (event.key === "ArrowDown" ? 1 : -1) + enabled.length) % enabled.length;
|
|
1521
|
+
enabled[next]?.focus();
|
|
1522
|
+
} else if (event.key.length === 1 && /\S/.test(event.key)) {
|
|
1523
|
+
const ordered = [...enabled.slice(index + 1), ...enabled.slice(0, index + 1)];
|
|
1524
|
+
ordered.find((button) => button.textContent?.trim().toLocaleLowerCase().startsWith(event.key.toLocaleLowerCase()))?.focus();
|
|
1525
|
+
}
|
|
1526
|
+
},
|
|
1527
|
+
children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1528
|
+
"button",
|
|
1529
|
+
{
|
|
1530
|
+
type: "button",
|
|
1531
|
+
role: "menuitem",
|
|
1532
|
+
tabIndex: -1,
|
|
1533
|
+
disabled: item.disabled,
|
|
1534
|
+
onClick: () => {
|
|
1535
|
+
onSelect(item.value);
|
|
1536
|
+
close();
|
|
1537
|
+
},
|
|
1538
|
+
children: [
|
|
1539
|
+
item.icon && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { "aria-hidden": "true", children: item.icon }),
|
|
1540
|
+
item.label
|
|
1541
|
+
]
|
|
1542
|
+
},
|
|
1543
|
+
item.value
|
|
1544
|
+
))
|
|
1545
|
+
}
|
|
1546
|
+
), document.body)
|
|
1547
|
+
] });
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
// src/components/TableLayout/TableLayout.tsx
|
|
1551
|
+
var import_react5 = require("react");
|
|
1552
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1553
|
+
var length = (value) => typeof value === "number" ? `${value}px` : value;
|
|
1554
|
+
function columnStyle(column) {
|
|
1555
|
+
return {
|
|
1556
|
+
width: column.width,
|
|
1557
|
+
"--table-column-width": !column.width || column.width.includes("%") ? void 0 : `calc(${column.width} - 1px)`,
|
|
1558
|
+
"--table-column-min": length(column.minWidth),
|
|
1559
|
+
"--table-column-max": length(column.maxWidth)
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
function useOverflow() {
|
|
1563
|
+
const ref = (0, import_react5.useRef)(null);
|
|
1564
|
+
const [overflow, setOverflow] = (0, import_react5.useState)(false);
|
|
1565
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
1566
|
+
const el = ref.current;
|
|
1567
|
+
if (!el) return;
|
|
1568
|
+
const measure = () => setOverflow(el.scrollWidth > el.clientWidth + 1 || el.scrollHeight > el.clientHeight + 1);
|
|
1569
|
+
const resize = new ResizeObserver(measure);
|
|
1570
|
+
const observe = () => {
|
|
1571
|
+
resize.disconnect();
|
|
1572
|
+
resize.observe(el);
|
|
1573
|
+
for (const child of el.children) resize.observe(child);
|
|
1574
|
+
measure();
|
|
1575
|
+
};
|
|
1576
|
+
const mutation = new MutationObserver(observe);
|
|
1577
|
+
mutation.observe(el, { childList: true, subtree: true, characterData: true });
|
|
1578
|
+
observe();
|
|
1579
|
+
return () => {
|
|
1580
|
+
resize.disconnect();
|
|
1581
|
+
mutation.disconnect();
|
|
1582
|
+
};
|
|
1583
|
+
}, []);
|
|
1584
|
+
return { ref, overflow };
|
|
1585
|
+
}
|
|
1586
|
+
function TableViewport({ children, maxHeight, label }) {
|
|
1587
|
+
const { ref, overflow } = useOverflow();
|
|
1588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { ref, className: "fractal-table-viewport", style: { maxHeight }, tabIndex: overflow ? 0 : void 0, role: overflow ? "region" : void 0, "aria-label": overflow ? `${label}, scrollable table` : void 0, children });
|
|
1589
|
+
}
|
|
1590
|
+
function TableCellContent({ children, label }) {
|
|
1591
|
+
const { ref, overflow } = useOverflow();
|
|
1592
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
1593
|
+
const cell = ref.current;
|
|
1594
|
+
if (!cell) return;
|
|
1595
|
+
const wheel = (event) => {
|
|
1596
|
+
if (event.defaultPrevented || event.ctrlKey || !event.cancelable || Math.abs(event.deltaX) <= Math.abs(event.deltaY)) return;
|
|
1597
|
+
const range = cell.scrollWidth - cell.clientWidth;
|
|
1598
|
+
if (range <= 1) return;
|
|
1599
|
+
const rtl = getComputedStyle(cell).direction === "rtl";
|
|
1600
|
+
const left = rtl ? -range : 0, right = rtl ? 0 : range;
|
|
1601
|
+
if (event.deltaX > 0 ? cell.scrollLeft < right - 1 : cell.scrollLeft > left + 1) return;
|
|
1602
|
+
const table = cell.closest(".fractal-table-viewport");
|
|
1603
|
+
if (!table) return;
|
|
1604
|
+
const tableRange = table.scrollWidth - table.clientWidth;
|
|
1605
|
+
const tableRtl = getComputedStyle(table).direction === "rtl";
|
|
1606
|
+
const tableLeft = tableRtl ? -tableRange : 0, tableRight = tableRtl ? 0 : tableRange;
|
|
1607
|
+
if (event.deltaX > 0 ? table.scrollLeft >= tableRight - 1 : table.scrollLeft <= tableLeft + 1) return;
|
|
1608
|
+
const unit = event.deltaMode === 1 ? parseFloat(getComputedStyle(cell).lineHeight) || 16 : event.deltaMode === 2 ? table.clientWidth : 1;
|
|
1609
|
+
event.preventDefault();
|
|
1610
|
+
table.scrollLeft += event.deltaX * unit;
|
|
1611
|
+
};
|
|
1612
|
+
cell.addEventListener("wheel", wheel, { passive: false });
|
|
1613
|
+
return () => cell.removeEventListener("wheel", wheel);
|
|
1614
|
+
}, [ref]);
|
|
1615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1616
|
+
"div",
|
|
1617
|
+
{
|
|
1618
|
+
ref,
|
|
1619
|
+
className: "fractal-table-cell-scroll",
|
|
1620
|
+
"data-overflow": overflow || void 0,
|
|
1621
|
+
tabIndex: overflow ? 0 : void 0,
|
|
1622
|
+
role: overflow ? "region" : void 0,
|
|
1623
|
+
"aria-label": overflow ? `${label}, scroll horizontally for full content` : void 0,
|
|
1624
|
+
onKeyDown: (event) => {
|
|
1625
|
+
if (!overflow || event.target !== event.currentTarget) return;
|
|
1626
|
+
if (["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) {
|
|
1627
|
+
event.preventDefault();
|
|
1628
|
+
event.stopPropagation();
|
|
1629
|
+
const el = event.currentTarget;
|
|
1630
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight") el.scrollBy({ left: event.key === "ArrowLeft" ? -40 : 40 });
|
|
1631
|
+
else el.scrollLeft = event.key === "Home" ? 0 : el.scrollWidth * (getComputedStyle(el).direction === "rtl" ? -1 : 1);
|
|
1632
|
+
} else if (event.key === " " || event.key === "Enter") event.stopPropagation();
|
|
1633
|
+
},
|
|
1634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "fractal-table-cell-content", children })
|
|
1635
|
+
}
|
|
1636
|
+
);
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// src/components/DataTable/DataTable.tsx
|
|
1640
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1641
|
+
function DataTable({ columns, data, emptyMessage, header, size = "md", className, overflowMenu, layout = "fill", stickyHeader = false, stickyFirstColumn = false, maxHeight, "aria-label": ariaLabel = "Data table" }) {
|
|
1642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("fractal-table-layout", "fractal-datatable", `fractal-datatable--${size}`, className), "data-overflow-menu": Boolean(overflowMenu), "data-table-layout": layout, "data-sticky-first": stickyFirstColumn, "data-sticky-header": stickyHeader, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "fractal-datatable-surface", children: [
|
|
1643
|
+
header && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "fractal-datatable-header", children: header }),
|
|
1644
|
+
data.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "fractal-datatable-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TableViewport, { maxHeight, label: ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("table", { "aria-label": ariaLabel, className: "fractal-datatable-table", children: [
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("tr", { className: "fractal-datatable-thead-row", children: [
|
|
1646
|
+
columns.map((col, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("th", { scope: "col", className: "fractal-datatable-th", style: columnStyle(col), "data-pinned-column": columnIndex === 0 ? "data" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TableCellContent, { label: `${col.header} column`, children: col.header }) }, col.key)),
|
|
1647
|
+
overflowMenu && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("th", { scope: "col", "aria-label": "Row actions", className: "fractal-datatable-th fractal-table-overflow-cell", "data-pinned-column": "overflow" })
|
|
1648
|
+
] }) }),
|
|
1649
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
1424
1650
|
"tr",
|
|
1425
1651
|
{
|
|
1426
1652
|
className: "fractal-datatable-row",
|
|
1427
|
-
children:
|
|
1653
|
+
children: [
|
|
1654
|
+
columns.map((col, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { className: "fractal-datatable-td", style: columnStyle(col), "data-pinned-column": columnIndex === 0 ? "data" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TableCellContent, { label: `${col.header || "Value"}, row ${rowIndex + 1}`, children: col.render(row, rowIndex) }) }, col.key)),
|
|
1655
|
+
overflowMenu && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { className: "fractal-datatable-td fractal-table-overflow-cell", "data-pinned-column": "overflow", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TableOverflowMenu, { items: overflowMenu.items(row, rowIndex), label: overflowMenu.getLabel?.(row, rowIndex) ?? `Actions for row ${rowIndex + 1}`, disabled: overflowMenu.isDisabled?.(row, rowIndex), onSelect: (value) => overflowMenu.onSelect(value, row, rowIndex) }) })
|
|
1656
|
+
]
|
|
1428
1657
|
},
|
|
1429
1658
|
rowIndex
|
|
1430
1659
|
)) })
|
|
1431
|
-
] })
|
|
1660
|
+
] }) })
|
|
1432
1661
|
] }) });
|
|
1433
1662
|
}
|
|
1434
1663
|
|
|
1435
1664
|
// src/components/Dropdown/Dropdown.tsx
|
|
1436
1665
|
var React12 = __toESM(require("react"), 1);
|
|
1437
|
-
var
|
|
1438
|
-
|
|
1439
|
-
|
|
1666
|
+
var import_fractal_icons10 = require("@mirror-physics/fractal-icons");
|
|
1667
|
+
|
|
1668
|
+
// src/components/Dropdown/position.ts
|
|
1669
|
+
function positionDropdown(trigger, panel, bounds, direction, align) {
|
|
1670
|
+
const gap = 4;
|
|
1671
|
+
const width = Math.min(panel.width, Math.max(0, bounds.right - bounds.left));
|
|
1672
|
+
let maxHeight = Math.max(0, bounds.bottom - bounds.top);
|
|
1673
|
+
let left;
|
|
1674
|
+
let top;
|
|
1675
|
+
if (direction === "left" || direction === "right") {
|
|
1676
|
+
const after = bounds.right - trigger.right - gap;
|
|
1677
|
+
const before = trigger.left - bounds.left - gap;
|
|
1678
|
+
let placeRight = direction === "right";
|
|
1679
|
+
if (width > (placeRight ? after : before) && (placeRight ? before > after : after > before)) {
|
|
1680
|
+
placeRight = !placeRight;
|
|
1681
|
+
}
|
|
1682
|
+
left = placeRight ? trigger.right + gap : trigger.left - width - gap;
|
|
1683
|
+
top = trigger.top;
|
|
1684
|
+
} else {
|
|
1685
|
+
const below = Math.max(0, bounds.bottom - trigger.bottom - gap);
|
|
1686
|
+
const above = Math.max(0, trigger.top - bounds.top - gap);
|
|
1687
|
+
let placeAbove = direction === "up";
|
|
1688
|
+
if (panel.height > (placeAbove ? above : below) && (placeAbove ? below > above : above > below)) {
|
|
1689
|
+
placeAbove = !placeAbove;
|
|
1690
|
+
}
|
|
1691
|
+
maxHeight = Math.min(maxHeight, placeAbove ? above : below);
|
|
1692
|
+
top = placeAbove ? trigger.top - Math.min(panel.height, maxHeight) - gap : trigger.bottom + gap;
|
|
1693
|
+
left = align === "right" ? trigger.right - width : trigger.left;
|
|
1694
|
+
}
|
|
1695
|
+
const height = Math.min(panel.height, maxHeight);
|
|
1696
|
+
return {
|
|
1697
|
+
left: Math.max(bounds.left, Math.min(left, bounds.right - width)),
|
|
1698
|
+
top: Math.max(bounds.top, Math.min(top, bounds.bottom - height)),
|
|
1699
|
+
maxHeight
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
// src/components/Dropdown/Dropdown.tsx
|
|
1704
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1440
1705
|
function Dropdown({
|
|
1441
1706
|
items,
|
|
1442
1707
|
selectedValue,
|
|
@@ -1444,6 +1709,8 @@ function Dropdown({
|
|
|
1444
1709
|
triggerLabel = "Options",
|
|
1445
1710
|
direction = "down",
|
|
1446
1711
|
align = "left",
|
|
1712
|
+
maxHeight = 320,
|
|
1713
|
+
collisionPadding = 8,
|
|
1447
1714
|
triggerOrientation = "horizontal",
|
|
1448
1715
|
triggerContent,
|
|
1449
1716
|
label,
|
|
@@ -1461,69 +1728,98 @@ function Dropdown({
|
|
|
1461
1728
|
}) {
|
|
1462
1729
|
const size = controlSize ?? sizeAlias;
|
|
1463
1730
|
const [open, setOpen] = React12.useState(false);
|
|
1731
|
+
const rootRef = React12.useRef(null);
|
|
1732
|
+
const menuId = React12.useId();
|
|
1733
|
+
const focusOnOpen = React12.useRef(false);
|
|
1464
1734
|
const triggerRef = React12.useRef(null);
|
|
1465
1735
|
const panelRef = React12.useRef(null);
|
|
1466
1736
|
const [panelStyle, setPanelStyle] = React12.useState({});
|
|
1467
1737
|
const visibleItems = items.filter(
|
|
1468
1738
|
(item) => item.icon != null || item.description != null && (typeof item.description === "string" ? item.description !== "" : true)
|
|
1469
1739
|
);
|
|
1470
|
-
if (visibleItems.length === 0) return null;
|
|
1471
1740
|
const selectableItems = visibleItems.filter((i) => i.kind !== "header");
|
|
1472
1741
|
const selected = items.find((i) => i.value === selectedValue && i.kind !== "header") ?? selectableItems[0] ?? visibleItems[0];
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1475
|
-
|
|
1742
|
+
const ChevronIcon = direction === "up" ? import_fractal_icons10.ChevronUp : direction === "left" ? import_fractal_icons10.ChevronLeft : direction === "right" ? import_fractal_icons10.ChevronRight : import_fractal_icons10.ChevronDown;
|
|
1743
|
+
useEscapeDismiss(100, () => {
|
|
1744
|
+
setOpen(false);
|
|
1745
|
+
triggerRef.current?.focus();
|
|
1746
|
+
}, open);
|
|
1476
1747
|
React12.useLayoutEffect(() => {
|
|
1477
|
-
|
|
1478
|
-
const
|
|
1479
|
-
const
|
|
1480
|
-
|
|
1481
|
-
const
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
top = 0;
|
|
1496
|
-
const panelBottom = triggerRect.top + panelRect.height;
|
|
1497
|
-
if (panelBottom > vh - MARGIN) top -= panelBottom - (vh - MARGIN);
|
|
1498
|
-
if (triggerRect.top + top < MARGIN) top += MARGIN - (triggerRect.top + top);
|
|
1499
|
-
} else {
|
|
1500
|
-
const spaceBelow = vh - triggerRect.bottom - MARGIN;
|
|
1501
|
-
const spaceAbove = triggerRect.top - MARGIN;
|
|
1502
|
-
let placeAbove = isUp;
|
|
1503
|
-
if (placeAbove && panelRect.height > spaceAbove && spaceBelow > spaceAbove) {
|
|
1504
|
-
placeAbove = false;
|
|
1505
|
-
} else if (!placeAbove && panelRect.height > spaceBelow && spaceAbove > spaceBelow) {
|
|
1506
|
-
placeAbove = true;
|
|
1507
|
-
}
|
|
1508
|
-
top = placeAbove ? -(panelRect.height + MARGIN) : triggerRect.height + MARGIN;
|
|
1509
|
-
if (align === "right") {
|
|
1510
|
-
right = 0;
|
|
1511
|
-
const panelLeft = triggerRect.right - panelRect.width;
|
|
1512
|
-
if (panelLeft < 0) {
|
|
1513
|
-
right = void 0;
|
|
1514
|
-
left = 0;
|
|
1748
|
+
const root = rootRef.current;
|
|
1749
|
+
const trigger = triggerRef.current;
|
|
1750
|
+
const panel = panelRef.current;
|
|
1751
|
+
if (!open || !root || !trigger || !panel) return;
|
|
1752
|
+
const updatePosition = () => {
|
|
1753
|
+
const viewport = window.visualViewport;
|
|
1754
|
+
const bounds = {
|
|
1755
|
+
left: viewport?.offsetLeft ?? 0,
|
|
1756
|
+
top: viewport?.offsetTop ?? 0,
|
|
1757
|
+
right: (viewport?.offsetLeft ?? 0) + (viewport?.width ?? document.documentElement.clientWidth),
|
|
1758
|
+
bottom: (viewport?.offsetTop ?? 0) + (viewport?.height ?? document.documentElement.clientHeight)
|
|
1759
|
+
};
|
|
1760
|
+
for (let ancestor = root.parentElement; ancestor; ancestor = ancestor.parentElement) {
|
|
1761
|
+
const style = getComputedStyle(ancestor);
|
|
1762
|
+
const rect = ancestor.getBoundingClientRect();
|
|
1763
|
+
if (/(auto|scroll|hidden|clip)/.test(style.overflowX)) {
|
|
1764
|
+
bounds.left = Math.max(bounds.left, rect.left + ancestor.clientLeft);
|
|
1765
|
+
bounds.right = Math.min(bounds.right, rect.left + ancestor.clientLeft + ancestor.clientWidth);
|
|
1515
1766
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
if (panelRight > vw) {
|
|
1520
|
-
left = void 0;
|
|
1521
|
-
right = 0;
|
|
1767
|
+
if (/(auto|scroll|hidden|clip)/.test(style.overflowY)) {
|
|
1768
|
+
bounds.top = Math.max(bounds.top, rect.top + ancestor.clientTop);
|
|
1769
|
+
bounds.bottom = Math.min(bounds.bottom, rect.top + ancestor.clientTop + ancestor.clientHeight);
|
|
1522
1770
|
}
|
|
1523
1771
|
}
|
|
1772
|
+
const padding = Math.max(0, collisionPadding);
|
|
1773
|
+
bounds.left += padding;
|
|
1774
|
+
bounds.right = Math.max(bounds.left, bounds.right - padding);
|
|
1775
|
+
bounds.top += padding;
|
|
1776
|
+
bounds.bottom = Math.max(bounds.top, bounds.bottom - padding);
|
|
1777
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
1778
|
+
const rootRect = root.getBoundingClientRect();
|
|
1779
|
+
const availableWidth = bounds.right - bounds.left;
|
|
1780
|
+
const heightLimit = Math.max(0, maxHeight);
|
|
1781
|
+
panel.style.maxWidth = `${availableWidth}px`;
|
|
1782
|
+
panel.style.minWidth = `${Math.min(triggerRect.width, availableWidth)}px`;
|
|
1783
|
+
const panelRect = panel.getBoundingClientRect();
|
|
1784
|
+
const desiredHeight = Math.min(heightLimit, panel.scrollHeight + panel.offsetHeight - panel.clientHeight);
|
|
1785
|
+
const position = positionDropdown(triggerRect, { width: panelRect.width, height: desiredHeight }, bounds, direction, align);
|
|
1786
|
+
const nextStyle = {
|
|
1787
|
+
left: position.left - rootRect.left - root.clientLeft + root.scrollLeft,
|
|
1788
|
+
top: position.top - rootRect.top - root.clientTop + root.scrollTop,
|
|
1789
|
+
minWidth: Math.min(triggerRect.width, availableWidth),
|
|
1790
|
+
maxWidth: availableWidth,
|
|
1791
|
+
maxHeight: Math.min(heightLimit, position.maxHeight)
|
|
1792
|
+
};
|
|
1793
|
+
for (const key of Object.keys(nextStyle)) {
|
|
1794
|
+
panel.style[key] = `${nextStyle[key]}px`;
|
|
1795
|
+
}
|
|
1796
|
+
setPanelStyle((previous) => Object.entries(nextStyle).every(([key, value]) => previous[key] === value) ? previous : nextStyle);
|
|
1797
|
+
};
|
|
1798
|
+
updatePosition();
|
|
1799
|
+
if (focusOnOpen.current) {
|
|
1800
|
+
focusOnOpen.current = false;
|
|
1801
|
+
const option = panel.querySelector('[aria-selected="true"]') ?? panel.querySelector('[role="option"]');
|
|
1802
|
+
option?.focus({ preventScroll: true });
|
|
1803
|
+
option?.scrollIntoView({ block: "nearest" });
|
|
1804
|
+
}
|
|
1805
|
+
const resize = new ResizeObserver(updatePosition);
|
|
1806
|
+
resize.observe(root);
|
|
1807
|
+
resize.observe(panel);
|
|
1808
|
+
for (let ancestor = root.parentElement; ancestor; ancestor = ancestor.parentElement) {
|
|
1809
|
+
resize.observe(ancestor);
|
|
1524
1810
|
}
|
|
1525
|
-
|
|
1526
|
-
|
|
1811
|
+
window.addEventListener("resize", updatePosition);
|
|
1812
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
1813
|
+
window.visualViewport?.addEventListener("resize", updatePosition);
|
|
1814
|
+
window.visualViewport?.addEventListener("scroll", updatePosition);
|
|
1815
|
+
return () => {
|
|
1816
|
+
resize.disconnect();
|
|
1817
|
+
window.removeEventListener("resize", updatePosition);
|
|
1818
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
1819
|
+
window.visualViewport?.removeEventListener("resize", updatePosition);
|
|
1820
|
+
window.visualViewport?.removeEventListener("scroll", updatePosition);
|
|
1821
|
+
};
|
|
1822
|
+
}, [open, direction, align, maxHeight, collisionPadding, items, label]);
|
|
1527
1823
|
React12.useEffect(() => {
|
|
1528
1824
|
if (!open) return;
|
|
1529
1825
|
const handleClickOutside = (e) => {
|
|
@@ -1534,8 +1830,9 @@ function Dropdown({
|
|
|
1534
1830
|
document.addEventListener("mousedown", handleClickOutside);
|
|
1535
1831
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1536
1832
|
}, [open]);
|
|
1537
|
-
|
|
1538
|
-
|
|
1833
|
+
if (visibleItems.length === 0) return null;
|
|
1834
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { ref: rootRef, "data-control-size": size, className: cn("fractal-dropdown", className), children: [
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1539
1836
|
"button",
|
|
1540
1837
|
{
|
|
1541
1838
|
ref: triggerRef,
|
|
@@ -1545,6 +1842,20 @@ function Dropdown({
|
|
|
1545
1842
|
disabled,
|
|
1546
1843
|
"aria-haspopup": "listbox",
|
|
1547
1844
|
"aria-expanded": open,
|
|
1845
|
+
"aria-controls": open ? menuId : void 0,
|
|
1846
|
+
onKeyDown: (event) => {
|
|
1847
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
1848
|
+
event.preventDefault();
|
|
1849
|
+
if (open) {
|
|
1850
|
+
const option = panelRef.current?.querySelector('[aria-selected="true"]') ?? panelRef.current?.querySelector('[role="option"]');
|
|
1851
|
+
option?.focus({ preventScroll: true });
|
|
1852
|
+
option?.scrollIntoView({ block: "nearest" });
|
|
1853
|
+
} else {
|
|
1854
|
+
focusOnOpen.current = true;
|
|
1855
|
+
setOpen(true);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
},
|
|
1548
1859
|
"aria-label": triggerLabel,
|
|
1549
1860
|
onClick: () => setOpen((o) => !o),
|
|
1550
1861
|
className: cn(
|
|
@@ -1557,38 +1868,48 @@ function Dropdown({
|
|
|
1557
1868
|
triggerClassName
|
|
1558
1869
|
),
|
|
1559
1870
|
children: [
|
|
1560
|
-
triggerContent != null ? triggerContent : /* @__PURE__ */ (0,
|
|
1561
|
-
selected.icon != null && /* @__PURE__ */ (0,
|
|
1562
|
-
selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ (0,
|
|
1871
|
+
triggerContent != null ? triggerContent : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
1872
|
+
selected.icon != null && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "fractal-dropdown-icon fractal-dropdown-icon--trigger", children: selected.icon }),
|
|
1873
|
+
selected.description != null && (typeof selected.description !== "string" || selected.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "fractal-dropdown-selected-text", children: selected.description })
|
|
1563
1874
|
] }),
|
|
1564
|
-
!noChevron && !iconOnly && /* @__PURE__ */ (0,
|
|
1875
|
+
!noChevron && !iconOnly && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "fractal-dropdown-chevron", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChevronIcon, { size: size === "sm" ? 14 : 16 }) })
|
|
1565
1876
|
]
|
|
1566
1877
|
}
|
|
1567
1878
|
),
|
|
1568
|
-
open && /* @__PURE__ */ (0,
|
|
1879
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1569
1880
|
"div",
|
|
1570
1881
|
{
|
|
1571
1882
|
ref: panelRef,
|
|
1883
|
+
id: menuId,
|
|
1884
|
+
onKeyDown: (event) => {
|
|
1885
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
1886
|
+
event.preventDefault();
|
|
1887
|
+
const options = Array.from(panelRef.current?.querySelectorAll('[role="option"]') ?? []);
|
|
1888
|
+
const current = options.indexOf(document.activeElement);
|
|
1889
|
+
const index = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : (current + (event.key === "ArrowDown" ? 1 : -1) + options.length) % options.length;
|
|
1890
|
+
options[index]?.focus({ preventScroll: true });
|
|
1891
|
+
options[index]?.scrollIntoView({ block: "nearest" });
|
|
1892
|
+
},
|
|
1572
1893
|
role: "listbox",
|
|
1573
1894
|
"aria-label": triggerLabel,
|
|
1574
1895
|
className: cn("fractal-dropdown-panel", `fractal-dropdown-panel--${size}`, panelClassName),
|
|
1575
1896
|
style: panelStyle,
|
|
1576
1897
|
children: [
|
|
1577
|
-
label != null && /* @__PURE__ */ (0,
|
|
1898
|
+
label != null && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "fractal-dropdown-label", children: label }),
|
|
1578
1899
|
visibleItems.map((item, index) => {
|
|
1579
|
-
const topDivider = item.border === "top" ? /* @__PURE__ */ (0,
|
|
1580
|
-
const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ (0,
|
|
1900
|
+
const topDivider = item.border === "top" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
|
|
1901
|
+
const bottomDivider = item.border === "bottom" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "fractal-dropdown-separator" }) : null;
|
|
1581
1902
|
if (item.kind === "header") {
|
|
1582
|
-
return /* @__PURE__ */ (0,
|
|
1903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(React12.Fragment, { children: [
|
|
1583
1904
|
topDivider,
|
|
1584
|
-
/* @__PURE__ */ (0,
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "presentation", className: "fractal-dropdown-label", children: item.description }),
|
|
1585
1906
|
bottomDivider
|
|
1586
1907
|
] }, `header-${index}`);
|
|
1587
1908
|
}
|
|
1588
1909
|
const isSelected = item.value === selectedValue;
|
|
1589
|
-
return /* @__PURE__ */ (0,
|
|
1910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(React12.Fragment, { children: [
|
|
1590
1911
|
topDivider,
|
|
1591
|
-
/* @__PURE__ */ (0,
|
|
1912
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1592
1913
|
"button",
|
|
1593
1914
|
{
|
|
1594
1915
|
type: "button",
|
|
@@ -1596,13 +1917,16 @@ function Dropdown({
|
|
|
1596
1917
|
"aria-selected": isSelected,
|
|
1597
1918
|
onClick: () => {
|
|
1598
1919
|
onSelect(item.value);
|
|
1599
|
-
if (closeOnSelect)
|
|
1920
|
+
if (closeOnSelect) {
|
|
1921
|
+
setOpen(false);
|
|
1922
|
+
triggerRef.current?.focus();
|
|
1923
|
+
}
|
|
1600
1924
|
},
|
|
1601
1925
|
className: "fractal-dropdown-option",
|
|
1602
1926
|
children: [
|
|
1603
|
-
item.icon != null && /* @__PURE__ */ (0,
|
|
1604
|
-
item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ (0,
|
|
1605
|
-
item.trailing != null && /* @__PURE__ */ (0,
|
|
1927
|
+
item.icon != null && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "fractal-dropdown-icon", children: item.icon }),
|
|
1928
|
+
item.description != null && (typeof item.description !== "string" || item.description !== "") && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "fractal-dropdown-option-text", children: item.description }),
|
|
1929
|
+
item.trailing != null && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "fractal-dropdown-trailing", children: item.trailing })
|
|
1606
1930
|
]
|
|
1607
1931
|
}
|
|
1608
1932
|
),
|
|
@@ -1617,9 +1941,9 @@ function Dropdown({
|
|
|
1617
1941
|
|
|
1618
1942
|
// src/components/Link/Link.tsx
|
|
1619
1943
|
var React13 = __toESM(require("react"), 1);
|
|
1620
|
-
var
|
|
1944
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1621
1945
|
var Link = React13.forwardRef(
|
|
1622
|
-
({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */ (0,
|
|
1946
|
+
({ className, theme = "default", size = "md", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1623
1947
|
"a",
|
|
1624
1948
|
{
|
|
1625
1949
|
ref,
|
|
@@ -1632,13 +1956,12 @@ Link.displayName = "Link";
|
|
|
1632
1956
|
|
|
1633
1957
|
// src/components/Chip/Chip.tsx
|
|
1634
1958
|
var React14 = __toESM(require("react"), 1);
|
|
1635
|
-
var
|
|
1959
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1636
1960
|
var Chip = React14.forwardRef(
|
|
1637
|
-
({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */ (0,
|
|
1961
|
+
({ className, tone = "neutral", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1638
1962
|
"span",
|
|
1639
1963
|
{
|
|
1640
1964
|
ref,
|
|
1641
|
-
"data-fractal-border-surface": tone === "neutral" ? "surface-2" : void 0,
|
|
1642
1965
|
className: cn("fractal-chip", `fractal-chip--${tone}`, className),
|
|
1643
1966
|
...props
|
|
1644
1967
|
}
|
|
@@ -1647,8 +1970,8 @@ var Chip = React14.forwardRef(
|
|
|
1647
1970
|
Chip.displayName = "Chip";
|
|
1648
1971
|
|
|
1649
1972
|
// src/components/Checkbox/Checkbox.tsx
|
|
1650
|
-
var
|
|
1651
|
-
var
|
|
1973
|
+
var import_fractal_icons11 = require("@mirror-physics/fractal-icons");
|
|
1974
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1652
1975
|
function Checkbox({
|
|
1653
1976
|
checked,
|
|
1654
1977
|
indeterminate = false,
|
|
@@ -1659,7 +1982,7 @@ function Checkbox({
|
|
|
1659
1982
|
onKeyDown,
|
|
1660
1983
|
...props
|
|
1661
1984
|
}) {
|
|
1662
|
-
return /* @__PURE__ */ (0,
|
|
1985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1663
1986
|
"button",
|
|
1664
1987
|
{
|
|
1665
1988
|
...props,
|
|
@@ -1681,16 +2004,16 @@ function Checkbox({
|
|
|
1681
2004
|
onKeyDown?.(event);
|
|
1682
2005
|
if (event.key === " " || event.key === "Enter") event.stopPropagation();
|
|
1683
2006
|
},
|
|
1684
|
-
children: indeterminate ? /* @__PURE__ */ (0,
|
|
1685
|
-
/* @__PURE__ */ (0,
|
|
1686
|
-
/* @__PURE__ */ (0,
|
|
1687
|
-
] }) : checked ? /* @__PURE__ */ (0,
|
|
2007
|
+
children: indeterminate ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "fractal-checkbox__indeterminate-icon", "aria-hidden": "true", children: [
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons11.Checkbox, { size: 18 }),
|
|
2009
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons11.Minus, { className: "fractal-checkbox__indeterminate-mark", size: 12 })
|
|
2010
|
+
] }) : checked ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons11.CheckboxChecked, { "aria-hidden": "true", size: 18 }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fractal_icons11.Checkbox, { "aria-hidden": "true", size: 18 })
|
|
1688
2011
|
}
|
|
1689
2012
|
);
|
|
1690
2013
|
}
|
|
1691
2014
|
|
|
1692
2015
|
// src/components/Radio/Radio.tsx
|
|
1693
|
-
var
|
|
2016
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1694
2017
|
function Radio({
|
|
1695
2018
|
checked,
|
|
1696
2019
|
className,
|
|
@@ -1700,8 +2023,8 @@ function Radio({
|
|
|
1700
2023
|
onCheckedChange,
|
|
1701
2024
|
...props
|
|
1702
2025
|
}) {
|
|
1703
|
-
return /* @__PURE__ */ (0,
|
|
1704
|
-
/* @__PURE__ */ (0,
|
|
2026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: cn("fractal-radio", disabled && "fractal-radio--disabled", className), children: [
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1705
2028
|
"input",
|
|
1706
2029
|
{
|
|
1707
2030
|
...props,
|
|
@@ -1712,18 +2035,18 @@ function Radio({
|
|
|
1712
2035
|
type: "radio"
|
|
1713
2036
|
}
|
|
1714
2037
|
),
|
|
1715
|
-
/* @__PURE__ */ (0,
|
|
1716
|
-
/* @__PURE__ */ (0,
|
|
1717
|
-
/* @__PURE__ */ (0,
|
|
1718
|
-
description && /* @__PURE__ */ (0,
|
|
2038
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": "true", className: "fractal-radio__control", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "fractal-radio__dot" }) }),
|
|
2039
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "fractal-radio__content", children: [
|
|
2040
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "fractal-radio__label", children: label }),
|
|
2041
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "fractal-radio__description", children: description })
|
|
1719
2042
|
] })
|
|
1720
2043
|
] });
|
|
1721
2044
|
}
|
|
1722
2045
|
|
|
1723
2046
|
// src/components/SortableTable/SortableTable.tsx
|
|
1724
|
-
var
|
|
1725
|
-
var
|
|
1726
|
-
var
|
|
2047
|
+
var import_react6 = require("react");
|
|
2048
|
+
var import_fractal_icons12 = require("@mirror-physics/fractal-icons");
|
|
2049
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1727
2050
|
function SortableTable({
|
|
1728
2051
|
columns,
|
|
1729
2052
|
data,
|
|
@@ -1732,6 +2055,11 @@ function SortableTable({
|
|
|
1732
2055
|
header,
|
|
1733
2056
|
size = "md",
|
|
1734
2057
|
embedded = false,
|
|
2058
|
+
layout = "fill",
|
|
2059
|
+
stickyHeader = false,
|
|
2060
|
+
stickyFirstColumn = false,
|
|
2061
|
+
maxHeight,
|
|
2062
|
+
overflowMenu,
|
|
1735
2063
|
className,
|
|
1736
2064
|
defaultSort,
|
|
1737
2065
|
defaultSortKey = void 0,
|
|
@@ -1748,8 +2076,8 @@ function SortableTable({
|
|
|
1748
2076
|
onRowDoubleClick,
|
|
1749
2077
|
rowAction
|
|
1750
2078
|
}) {
|
|
1751
|
-
const [internalKey, setInternalKey] = (0,
|
|
1752
|
-
const [internalDirection, setInternalDirection] = (0,
|
|
2079
|
+
const [internalKey, setInternalKey] = (0, import_react6.useState)(defaultSortKey ?? null);
|
|
2080
|
+
const [internalDirection, setInternalDirection] = (0, import_react6.useState)(defaultSortDirection);
|
|
1753
2081
|
const isControlled = controlledKey !== void 0 && controlledDirection !== void 0;
|
|
1754
2082
|
const activeKey = isControlled ? controlledKey : internalKey;
|
|
1755
2083
|
const activeDirection = isControlled ? controlledDirection : internalDirection;
|
|
@@ -1757,7 +2085,7 @@ function SortableTable({
|
|
|
1757
2085
|
const baselineDirection = defaultSort?.direction ?? null;
|
|
1758
2086
|
const effectiveKey = activeKey && activeDirection ? activeKey : baselineKey;
|
|
1759
2087
|
const effectiveDirection = activeKey && activeDirection ? activeDirection : baselineDirection;
|
|
1760
|
-
const sorted = (0,
|
|
2088
|
+
const sorted = (0, import_react6.useMemo)(() => {
|
|
1761
2089
|
if (!effectiveKey || !effectiveDirection) return data;
|
|
1762
2090
|
const col = columns.find((c) => c.key === effectiveKey);
|
|
1763
2091
|
if (!col) return data;
|
|
@@ -1783,7 +2111,7 @@ function SortableTable({
|
|
|
1783
2111
|
});
|
|
1784
2112
|
return copy;
|
|
1785
2113
|
}, [data, columns, effectiveKey, effectiveDirection]);
|
|
1786
|
-
const visibleRows = (0,
|
|
2114
|
+
const visibleRows = (0, import_react6.useMemo)(() => {
|
|
1787
2115
|
if (!pagination) return sorted;
|
|
1788
2116
|
const pageSize = Math.max(1, pagination.pageSize);
|
|
1789
2117
|
const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));
|
|
@@ -1818,16 +2146,17 @@ function SortableTable({
|
|
|
1818
2146
|
onSortChange?.(nextKey, nextDirection);
|
|
1819
2147
|
}
|
|
1820
2148
|
};
|
|
1821
|
-
return /* @__PURE__ */ (0,
|
|
1822
|
-
header && /* @__PURE__ */ (0,
|
|
1823
|
-
visibleRows.length === 0 ? /* @__PURE__ */ (0,
|
|
1824
|
-
/* @__PURE__ */ (0,
|
|
1825
|
-
selection && /* @__PURE__ */ (0,
|
|
2149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: cn("fractal-table-layout", "fractal-sortable-table", `fractal-sortable-table--${size}`, embedded && "fractal-sortable-table--embedded", className), "data-overflow-menu": Boolean(overflowMenu), "data-table-layout": layout, "data-sticky-first": stickyFirstColumn, "data-sticky-header": stickyHeader, "data-table-selection": Boolean(selection), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "fractal-sortable-table-surface", children: [
|
|
2150
|
+
header && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "fractal-sortable-table-header", children: header }),
|
|
2151
|
+
visibleRows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "fractal-sortable-table-empty", children: emptyMessage || "No data" }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TableViewport, { maxHeight, label: ariaLabel || "Data table", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("table", { "aria-label": ariaLabel, className: "fractal-sortable-table-table", children: [
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("tr", { className: "fractal-sortable-table-thead-row", children: [
|
|
2153
|
+
selection && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1826
2154
|
"th",
|
|
1827
2155
|
{
|
|
1828
2156
|
className: "fractal-sortable-table-th fractal-sortable-table-selection-cell",
|
|
2157
|
+
"data-pinned-column": "selection",
|
|
1829
2158
|
scope: "col",
|
|
1830
|
-
children: /* @__PURE__ */ (0,
|
|
2159
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1831
2160
|
Checkbox,
|
|
1832
2161
|
{
|
|
1833
2162
|
"aria-label": selection.selectAllLabel ?? "Select all rows",
|
|
@@ -1850,27 +2179,29 @@ function SortableTable({
|
|
|
1850
2179
|
)
|
|
1851
2180
|
}
|
|
1852
2181
|
),
|
|
1853
|
-
columns.map((col) => {
|
|
2182
|
+
columns.map((col, columnIndex) => {
|
|
1854
2183
|
const isActive = activeKey === col.key && activeDirection !== null;
|
|
1855
2184
|
if (!col.sortable) {
|
|
1856
|
-
return /* @__PURE__ */ (0,
|
|
2185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1857
2186
|
"th",
|
|
1858
2187
|
{
|
|
1859
2188
|
className: "fractal-sortable-table-th",
|
|
1860
2189
|
scope: "col",
|
|
1861
|
-
style:
|
|
1862
|
-
|
|
2190
|
+
style: columnStyle(col),
|
|
2191
|
+
"data-pinned-column": columnIndex === 0 ? "data" : void 0,
|
|
2192
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TableCellContent, { label: `${col.header} column`, children: col.header })
|
|
1863
2193
|
},
|
|
1864
2194
|
col.key
|
|
1865
2195
|
);
|
|
1866
2196
|
}
|
|
1867
|
-
return /* @__PURE__ */ (0,
|
|
2197
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1868
2198
|
"th",
|
|
1869
2199
|
{
|
|
1870
2200
|
className: "fractal-sortable-table-th fractal-sortable-table-th--sortable",
|
|
1871
2201
|
scope: "col",
|
|
1872
|
-
style:
|
|
1873
|
-
|
|
2202
|
+
style: columnStyle(col),
|
|
2203
|
+
"data-pinned-column": columnIndex === 0 ? "data" : void 0,
|
|
2204
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TableCellContent, { label: `${col.header} column`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1874
2205
|
"button",
|
|
1875
2206
|
{
|
|
1876
2207
|
type: "button",
|
|
@@ -1881,17 +2212,18 @@ function SortableTable({
|
|
|
1881
2212
|
onClick: () => handleSortClick(col.key),
|
|
1882
2213
|
"aria-sort": isActive ? activeDirection === "asc" ? "ascending" : "descending" : "none",
|
|
1883
2214
|
children: [
|
|
1884
|
-
/* @__PURE__ */ (0,
|
|
1885
|
-
/* @__PURE__ */ (0,
|
|
2215
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: col.header }),
|
|
2216
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "fractal-sortable-table-sort-icon", "aria-hidden": "true", children: isActive && activeDirection === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_fractal_icons12.ArrowUp, { size: 14 }) : isActive && activeDirection === "desc" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_fractal_icons12.ArrowDown, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_fractal_icons12.ArrowsUpDown, { size: 14 }) })
|
|
1886
2217
|
]
|
|
1887
2218
|
}
|
|
1888
|
-
)
|
|
2219
|
+
) })
|
|
1889
2220
|
},
|
|
1890
2221
|
col.key
|
|
1891
2222
|
);
|
|
1892
|
-
})
|
|
2223
|
+
}),
|
|
2224
|
+
overflowMenu && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("th", { scope: "col", "aria-label": "Row actions", className: "fractal-sortable-table-th fractal-table-overflow-cell", "data-pinned-column": "overflow" })
|
|
1893
2225
|
] }) }),
|
|
1894
|
-
/* @__PURE__ */ (0,
|
|
2226
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("tbody", { children: visibleRows.map((row, rowIndex) => {
|
|
1895
2227
|
const highlighted = highlightRow?.(row, rowIndex) ?? false;
|
|
1896
2228
|
const disabled = isRowDisabled?.(row) ?? false;
|
|
1897
2229
|
const selectionDisabled = disabled || (isRowSelectionDisabled?.(row) ?? false);
|
|
@@ -1900,7 +2232,7 @@ function SortableTable({
|
|
|
1900
2232
|
label: rowAction.label(row, rowIndex),
|
|
1901
2233
|
icon: rowAction.icon(row, rowIndex)
|
|
1902
2234
|
} : null;
|
|
1903
|
-
return /* @__PURE__ */ (0,
|
|
2235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1904
2236
|
"tr",
|
|
1905
2237
|
{
|
|
1906
2238
|
className: cn(
|
|
@@ -1924,7 +2256,7 @@ function SortableTable({
|
|
|
1924
2256
|
role: interactive ? "button" : void 0,
|
|
1925
2257
|
tabIndex: interactive ? 0 : void 0,
|
|
1926
2258
|
children: [
|
|
1927
|
-
selection && /* @__PURE__ */ (0,
|
|
2259
|
+
selection && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("td", { className: "fractal-sortable-table-td fractal-sortable-table-selection-cell", "data-pinned-column": "selection", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1928
2260
|
Checkbox,
|
|
1929
2261
|
{
|
|
1930
2262
|
"aria-label": selection.getRowLabel(row),
|
|
@@ -1936,33 +2268,46 @@ function SortableTable({
|
|
|
1936
2268
|
}
|
|
1937
2269
|
}
|
|
1938
2270
|
) }),
|
|
1939
|
-
columns.map((col, columnIndex) => /* @__PURE__ */ (0,
|
|
2271
|
+
columns.map((col, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1940
2272
|
"td",
|
|
1941
2273
|
{
|
|
1942
2274
|
className: cn(
|
|
1943
2275
|
"fractal-sortable-table-td",
|
|
1944
2276
|
action && columnIndex === columns.length - 1 && "fractal-sortable-table-td--row-action"
|
|
1945
2277
|
),
|
|
1946
|
-
style: {
|
|
2278
|
+
style: { ...columnStyle(col), textAlign: col.align ?? "left" },
|
|
2279
|
+
"data-column-align": col.align,
|
|
2280
|
+
"data-pinned-column": columnIndex === 0 ? "data" : void 0,
|
|
1947
2281
|
children: [
|
|
1948
|
-
col.render(row, rowIndex),
|
|
1949
|
-
action && columnIndex === columns.length - 1 && /* @__PURE__ */ (0,
|
|
2282
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TableCellContent, { label: `${col.header || "Value"}, row ${rowIndex + 1}`, children: col.render(row, rowIndex) }),
|
|
2283
|
+
action && columnIndex === columns.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "fractal-sortable-table-row-action", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "fractal-sortable-table-row-action__icon", children: action.icon }) })
|
|
1950
2284
|
]
|
|
1951
2285
|
},
|
|
1952
2286
|
col.key
|
|
1953
|
-
))
|
|
2287
|
+
)),
|
|
2288
|
+
overflowMenu && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2289
|
+
"td",
|
|
2290
|
+
{
|
|
2291
|
+
className: "fractal-sortable-table-td fractal-table-overflow-cell",
|
|
2292
|
+
"data-pinned-column": "overflow",
|
|
2293
|
+
onClick: (event) => event.stopPropagation(),
|
|
2294
|
+
onDoubleClick: (event) => event.stopPropagation(),
|
|
2295
|
+
onKeyDown: (event) => event.stopPropagation(),
|
|
2296
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TableOverflowMenu, { items: overflowMenu.items(row, rowIndex), label: overflowMenu.getLabel?.(row, rowIndex) ?? `Actions for row ${rowIndex + 1}`, disabled: disabled || overflowMenu.isDisabled?.(row, rowIndex), onSelect: (value) => overflowMenu.onSelect(value, row, rowIndex) })
|
|
2297
|
+
}
|
|
2298
|
+
)
|
|
1954
2299
|
]
|
|
1955
2300
|
},
|
|
1956
2301
|
rowIndex
|
|
1957
2302
|
);
|
|
1958
2303
|
}) })
|
|
1959
|
-
] })
|
|
2304
|
+
] }) })
|
|
1960
2305
|
] }) });
|
|
1961
2306
|
}
|
|
1962
2307
|
|
|
1963
2308
|
// src/components/Tabs/Tabs.tsx
|
|
1964
|
-
var
|
|
1965
|
-
var
|
|
2309
|
+
var import_react7 = require("react");
|
|
2310
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1966
2311
|
function Tabs({
|
|
1967
2312
|
items,
|
|
1968
2313
|
defaultValue,
|
|
@@ -1973,16 +2318,16 @@ function Tabs({
|
|
|
1973
2318
|
divider = false,
|
|
1974
2319
|
variant = "line"
|
|
1975
2320
|
}) {
|
|
1976
|
-
const reactId = (0,
|
|
1977
|
-
const [internalValue, setInternalValue] = (0,
|
|
2321
|
+
const reactId = (0, import_react7.useId)();
|
|
2322
|
+
const [internalValue, setInternalValue] = (0, import_react7.useState)(
|
|
1978
2323
|
defaultValue ?? items.find((i) => !i.disabled)?.id ?? items[0]?.id ?? ""
|
|
1979
2324
|
);
|
|
1980
2325
|
const isControlled = controlledValue !== void 0;
|
|
1981
2326
|
const activeId = isControlled ? controlledValue : internalValue;
|
|
1982
|
-
const tabListRef = (0,
|
|
1983
|
-
const tabRefs = (0,
|
|
1984
|
-
const [indicator, setIndicator] = (0,
|
|
1985
|
-
(0,
|
|
2327
|
+
const tabListRef = (0, import_react7.useRef)(null);
|
|
2328
|
+
const tabRefs = (0, import_react7.useRef)({});
|
|
2329
|
+
const [indicator, setIndicator] = (0, import_react7.useState)(null);
|
|
2330
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
1986
2331
|
const updateIndicator = () => {
|
|
1987
2332
|
const activeTab = tabRefs.current[activeId];
|
|
1988
2333
|
if (!activeTab) return;
|
|
@@ -2033,8 +2378,8 @@ function Tabs({
|
|
|
2033
2378
|
selectTab(nextId2);
|
|
2034
2379
|
requestAnimationFrame(() => tabRefs.current[nextId2]?.focus());
|
|
2035
2380
|
};
|
|
2036
|
-
return /* @__PURE__ */ (0,
|
|
2037
|
-
/* @__PURE__ */ (0,
|
|
2381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("fractal-tabs", `fractal-tabs--${variant}`, divider && "fractal-tabs--divider", className), children: [
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2038
2383
|
"div",
|
|
2039
2384
|
{
|
|
2040
2385
|
ref: tabListRef,
|
|
@@ -2047,7 +2392,7 @@ function Tabs({
|
|
|
2047
2392
|
const isActive = item.id === activeId;
|
|
2048
2393
|
const tabId = `${reactId}-tab-${item.id}`;
|
|
2049
2394
|
const panelId = `${reactId}-panel-${item.id}`;
|
|
2050
|
-
return /* @__PURE__ */ (0,
|
|
2395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2051
2396
|
"button",
|
|
2052
2397
|
{
|
|
2053
2398
|
ref: (el) => {
|
|
@@ -2078,7 +2423,7 @@ function Tabs({
|
|
|
2078
2423
|
const tabId = `${reactId}-tab-${item.id}`;
|
|
2079
2424
|
const panelId = `${reactId}-panel-${item.id}`;
|
|
2080
2425
|
const isActive = item.id === activeId;
|
|
2081
|
-
return /* @__PURE__ */ (0,
|
|
2426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2082
2427
|
"div",
|
|
2083
2428
|
{
|
|
2084
2429
|
id: panelId,
|
|
@@ -2096,7 +2441,7 @@ function Tabs({
|
|
|
2096
2441
|
|
|
2097
2442
|
// src/components/ContentSwitcher/ContentSwitcher.tsx
|
|
2098
2443
|
var React15 = __toESM(require("react"), 1);
|
|
2099
|
-
var
|
|
2444
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2100
2445
|
function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = false, className }) {
|
|
2101
2446
|
const switcherRef = React15.useRef(null);
|
|
2102
2447
|
const buttonRefs = React15.useRef([]);
|
|
@@ -2154,7 +2499,7 @@ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = f
|
|
|
2154
2499
|
onValueChange(items[nextIndex].value);
|
|
2155
2500
|
}
|
|
2156
2501
|
};
|
|
2157
|
-
return /* @__PURE__ */ (0,
|
|
2502
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
2158
2503
|
"div",
|
|
2159
2504
|
{
|
|
2160
2505
|
className: cn("fractal-content-switcher", fullWidth && "fractal-content-switcher--full-width", className),
|
|
@@ -2162,10 +2507,10 @@ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = f
|
|
|
2162
2507
|
"aria-label": ariaLabel,
|
|
2163
2508
|
ref: switcherRef,
|
|
2164
2509
|
children: [
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fractal-content-switcher__indicator", "aria-hidden": true }),
|
|
2166
2511
|
items.map((item, index) => {
|
|
2167
2512
|
const active = item.value === value;
|
|
2168
|
-
return /* @__PURE__ */ (0,
|
|
2513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
2169
2514
|
"button",
|
|
2170
2515
|
{
|
|
2171
2516
|
className: cn("fractal-content-switcher__item", active && "fractal-content-switcher__item--active"),
|
|
@@ -2197,9 +2542,9 @@ function ContentSwitcher({ items, value, onValueChange, ariaLabel, fullWidth = f
|
|
|
2197
2542
|
}
|
|
2198
2543
|
|
|
2199
2544
|
// src/components/Disclosure/Disclosure.tsx
|
|
2200
|
-
var
|
|
2201
|
-
var
|
|
2202
|
-
var
|
|
2545
|
+
var import_react8 = require("react");
|
|
2546
|
+
var import_fractal_icons13 = require("@mirror-physics/fractal-icons");
|
|
2547
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
2203
2548
|
function Disclosure({
|
|
2204
2549
|
title,
|
|
2205
2550
|
meta,
|
|
@@ -2211,10 +2556,10 @@ function Disclosure({
|
|
|
2211
2556
|
className,
|
|
2212
2557
|
variant = "card"
|
|
2213
2558
|
}) {
|
|
2214
|
-
const reactId = (0,
|
|
2559
|
+
const reactId = (0, import_react8.useId)();
|
|
2215
2560
|
const headerId = `${reactId}-header`;
|
|
2216
2561
|
const panelId = `${reactId}-panel`;
|
|
2217
|
-
const [internalOpen, setInternalOpen] = (0,
|
|
2562
|
+
const [internalOpen, setInternalOpen] = (0, import_react8.useState)(defaultOpen);
|
|
2218
2563
|
const isControlled = controlledOpen !== void 0;
|
|
2219
2564
|
const isOpen = isControlled ? controlledOpen : internalOpen;
|
|
2220
2565
|
const toggle = () => {
|
|
@@ -2227,7 +2572,7 @@ function Disclosure({
|
|
|
2227
2572
|
onOpenChange?.(next);
|
|
2228
2573
|
}
|
|
2229
2574
|
};
|
|
2230
|
-
return /* @__PURE__ */ (0,
|
|
2575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
2231
2576
|
"div",
|
|
2232
2577
|
{
|
|
2233
2578
|
className: cn(
|
|
@@ -2238,7 +2583,7 @@ function Disclosure({
|
|
|
2238
2583
|
className
|
|
2239
2584
|
),
|
|
2240
2585
|
children: [
|
|
2241
|
-
/* @__PURE__ */ (0,
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
2242
2587
|
"button",
|
|
2243
2588
|
{
|
|
2244
2589
|
type: "button",
|
|
@@ -2249,13 +2594,13 @@ function Disclosure({
|
|
|
2249
2594
|
disabled,
|
|
2250
2595
|
onClick: toggle,
|
|
2251
2596
|
children: [
|
|
2252
|
-
/* @__PURE__ */ (0,
|
|
2253
|
-
/* @__PURE__ */ (0,
|
|
2254
|
-
meta && /* @__PURE__ */ (0,
|
|
2597
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fractal-disclosure-icon", "aria-hidden": "true", children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_fractal_icons13.ChevronDown, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_fractal_icons13.ChevronRight, { size: 16 }) }),
|
|
2598
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fractal-disclosure-title", children: title }),
|
|
2599
|
+
meta && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fractal-disclosure-meta", children: meta })
|
|
2255
2600
|
]
|
|
2256
2601
|
}
|
|
2257
2602
|
),
|
|
2258
|
-
/* @__PURE__ */ (0,
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
2259
2604
|
"div",
|
|
2260
2605
|
{
|
|
2261
2606
|
id: panelId,
|
|
@@ -2263,7 +2608,7 @@ function Disclosure({
|
|
|
2263
2608
|
"aria-labelledby": headerId,
|
|
2264
2609
|
className: "fractal-disclosure-panel",
|
|
2265
2610
|
hidden: !isOpen,
|
|
2266
|
-
children: /* @__PURE__ */ (0,
|
|
2611
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "fractal-disclosure-panel-inner", children })
|
|
2267
2612
|
}
|
|
2268
2613
|
)
|
|
2269
2614
|
]
|
|
@@ -2272,18 +2617,18 @@ function Disclosure({
|
|
|
2272
2617
|
}
|
|
2273
2618
|
|
|
2274
2619
|
// src/components/LatticeLoader/LatticeLoader.tsx
|
|
2275
|
-
var
|
|
2620
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
2276
2621
|
var LATTICE_COUNT = 160;
|
|
2277
2622
|
var WAVE_PERIOD = 80;
|
|
2278
2623
|
function LatticeLoader({ className, label = "Loading", ...props }) {
|
|
2279
|
-
return /* @__PURE__ */ (0,
|
|
2624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2280
2625
|
"span",
|
|
2281
2626
|
{
|
|
2282
2627
|
"aria-label": label,
|
|
2283
2628
|
className: cn("fractal-lattice-loader", className),
|
|
2284
2629
|
role: "progressbar",
|
|
2285
2630
|
...props,
|
|
2286
|
-
children: Array.from({ length: LATTICE_COUNT }, (_, index) => /* @__PURE__ */ (0,
|
|
2631
|
+
children: Array.from({ length: LATTICE_COUNT }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2287
2632
|
"span",
|
|
2288
2633
|
{
|
|
2289
2634
|
"aria-hidden": "true",
|
|
@@ -2297,10 +2642,10 @@ function LatticeLoader({ className, label = "Loading", ...props }) {
|
|
|
2297
2642
|
}
|
|
2298
2643
|
|
|
2299
2644
|
// src/components/Ghost/Ghost.tsx
|
|
2300
|
-
var
|
|
2645
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
2301
2646
|
var toCssLength = (value) => typeof value === "number" ? `${value}px` : value;
|
|
2302
2647
|
function Ghost({ className, width, height, radius, style, ...props }) {
|
|
2303
|
-
return /* @__PURE__ */ (0,
|
|
2648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
2304
2649
|
"div",
|
|
2305
2650
|
{
|
|
2306
2651
|
"aria-hidden": "true",
|
|
@@ -2316,15 +2661,15 @@ function Ghost({ className, width, height, radius, style, ...props }) {
|
|
|
2316
2661
|
);
|
|
2317
2662
|
}
|
|
2318
2663
|
function GhostLine({ className, size = "md", width = "100%", ...props }) {
|
|
2319
|
-
return /* @__PURE__ */ (0,
|
|
2664
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: cn("fractal-ghost-line", `fractal-ghost-line--${size}`, className), width, ...props });
|
|
2320
2665
|
}
|
|
2321
2666
|
function ButtonGhost({ className, size = "md", controlSize, iconOnly = false, width, ...props }) {
|
|
2322
|
-
return /* @__PURE__ */ (0,
|
|
2667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { "data-control-size": controlSize ?? size, className: cn("fractal-ghost-button", `fractal-ghost-button--${size}`, iconOnly && "fractal-ghost-button--icon-only", className), width, ...props });
|
|
2323
2668
|
}
|
|
2324
2669
|
function CardGhost({ className, lines = 3, showHeader = true, ...props }) {
|
|
2325
|
-
return /* @__PURE__ */ (0,
|
|
2326
|
-
showHeader && /* @__PURE__ */ (0,
|
|
2327
|
-
/* @__PURE__ */ (0,
|
|
2670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-card", className), ...props, children: [
|
|
2671
|
+
showHeader && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "38%" }),
|
|
2672
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: index === lines - 1 ? "62%" : "100%" }, index)) })
|
|
2328
2673
|
] });
|
|
2329
2674
|
}
|
|
2330
2675
|
function DataTableGhost({
|
|
@@ -2338,81 +2683,81 @@ function DataTableGhost({
|
|
|
2338
2683
|
...props
|
|
2339
2684
|
}) {
|
|
2340
2685
|
const cells = Array.from({ length: columns }, (_, index) => index);
|
|
2341
|
-
return /* @__PURE__ */ (0,
|
|
2342
|
-
(showHeader || headers) && /* @__PURE__ */ (0,
|
|
2343
|
-
/* @__PURE__ */ (0,
|
|
2686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "aria-busy": "true", "aria-label": "Loading table", className: cn("fractal-ghost-table", `fractal-ghost-table--${size}`, className), role: "status", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("table", { className: "fractal-ghost-table__table", children: [
|
|
2687
|
+
(showHeader || headers) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tr", { className: "fractal-ghost-table__head-row", children: cells.map((index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("th", { style: { width: columnWidths?.[index] }, children: headers?.[index] ?? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { size: "sm", width: index === columns - 1 ? "62%" : "76%" }) }, index)) }) }),
|
|
2688
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tbody", { children: Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tr", { className: "fractal-ghost-table__row", children: cells.map((columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { style: { width: columnWidths?.[columnIndex] }, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: `${[72, 54, 82, 63, 46][(rowIndex + columnIndex) % 5]}%` }) }, columnIndex)) }, rowIndex)) })
|
|
2344
2689
|
] }) });
|
|
2345
2690
|
}
|
|
2346
2691
|
function InputGhost({ className, labelWidth = "26%", ...props }) {
|
|
2347
|
-
return /* @__PURE__ */ (0,
|
|
2692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(FormFieldGhost, { className, labelWidth, ...props });
|
|
2348
2693
|
}
|
|
2349
2694
|
function TextareaGhost({ className, labelWidth = "26%", ...props }) {
|
|
2350
|
-
return /* @__PURE__ */ (0,
|
|
2695
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(FormFieldGhost, { className, labelWidth, multiline: true, ...props });
|
|
2351
2696
|
}
|
|
2352
2697
|
function LabelGhost({ className, width = "26%", ...props }) {
|
|
2353
|
-
return /* @__PURE__ */ (0,
|
|
2698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { className: cn("fractal-ghost-label", className), size: "sm", width, ...props });
|
|
2354
2699
|
}
|
|
2355
2700
|
function FormFieldGhost({ className, labelWidth = "26%", multiline = false, controlSize = "md", ...props }) {
|
|
2356
|
-
return /* @__PURE__ */ (0,
|
|
2357
|
-
/* @__PURE__ */ (0,
|
|
2358
|
-
/* @__PURE__ */ (0,
|
|
2701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", "data-control-size": controlSize, className: cn("fractal-ghost-field", className), ...props, children: [
|
|
2702
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LabelGhost, { width: labelWidth }),
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: cn("fractal-ghost-field__control", multiline && "fractal-ghost-field__control--multiline") })
|
|
2359
2704
|
] });
|
|
2360
2705
|
}
|
|
2361
2706
|
function AlertGhost({ className, ...props }) {
|
|
2362
|
-
return /* @__PURE__ */ (0,
|
|
2363
|
-
/* @__PURE__ */ (0,
|
|
2364
|
-
/* @__PURE__ */ (0,
|
|
2707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-alert", className), ...props, children: [
|
|
2708
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "30%" }),
|
|
2709
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { size: "sm", width: "78%" })
|
|
2365
2710
|
] });
|
|
2366
2711
|
}
|
|
2367
2712
|
function CheckboxGhost({ className, ...props }) {
|
|
2368
|
-
return /* @__PURE__ */ (0,
|
|
2369
|
-
/* @__PURE__ */ (0,
|
|
2370
|
-
/* @__PURE__ */ (0,
|
|
2713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-choice", className), ...props, children: [
|
|
2714
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: "fractal-ghost-choice__control" }),
|
|
2715
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "42%" })
|
|
2371
2716
|
] });
|
|
2372
2717
|
}
|
|
2373
2718
|
var ToggleGhost = CheckboxGhost;
|
|
2374
2719
|
function ChipGhost({ className, width = 74, ...props }) {
|
|
2375
|
-
return /* @__PURE__ */ (0,
|
|
2720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: cn("fractal-ghost-chip", className), height: 24, width, ...props });
|
|
2376
2721
|
}
|
|
2377
2722
|
function LinkGhost({ className, width = 96, ...props }) {
|
|
2378
|
-
return /* @__PURE__ */ (0,
|
|
2723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { className: cn("fractal-ghost-link", className), size: "sm", width, ...props });
|
|
2379
2724
|
}
|
|
2380
2725
|
var TextButtonGhost = LinkGhost;
|
|
2381
2726
|
function DropdownGhost({ className, controlSize = "md", ...props }) {
|
|
2382
|
-
return /* @__PURE__ */ (0,
|
|
2383
|
-
/* @__PURE__ */ (0,
|
|
2384
|
-
/* @__PURE__ */ (0,
|
|
2727
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", "data-control-size": controlSize, className: cn("fractal-ghost-dropdown", className), ...props, children: [
|
|
2728
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "38%" }),
|
|
2729
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: "fractal-ghost-dropdown__chevron" })
|
|
2385
2730
|
] });
|
|
2386
2731
|
}
|
|
2387
2732
|
function ContentSwitcherGhost({ className, options = 3, ...props }) {
|
|
2388
|
-
return /* @__PURE__ */ (0,
|
|
2733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "aria-hidden": "true", className: cn("fractal-ghost-switcher", className), ...props, children: Array.from({ length: options }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, {}, index)) });
|
|
2389
2734
|
}
|
|
2390
2735
|
var TabsGhost = ContentSwitcherGhost;
|
|
2391
2736
|
function DisclosureGhost({ className, ...props }) {
|
|
2392
|
-
return /* @__PURE__ */ (0,
|
|
2393
|
-
/* @__PURE__ */ (0,
|
|
2394
|
-
/* @__PURE__ */ (0,
|
|
2737
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-disclosure", className), ...props, children: [
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: "fractal-ghost-disclosure__icon" }),
|
|
2739
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "42%" })
|
|
2395
2740
|
] });
|
|
2396
2741
|
}
|
|
2397
2742
|
function PaginationGhost({ className, pages = 5, ...props }) {
|
|
2398
|
-
return /* @__PURE__ */ (0,
|
|
2743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "aria-hidden": "true", className: cn("fractal-ghost-pagination", className), ...props, children: Array.from({ length: pages }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, {}, index)) });
|
|
2399
2744
|
}
|
|
2400
2745
|
function FileDropzoneGhost({ className, ...props }) {
|
|
2401
|
-
return /* @__PURE__ */ (0,
|
|
2402
|
-
/* @__PURE__ */ (0,
|
|
2403
|
-
/* @__PURE__ */ (0,
|
|
2404
|
-
/* @__PURE__ */ (0,
|
|
2746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-dropzone", className), ...props, children: [
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: "fractal-ghost-dropzone__icon" }),
|
|
2748
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "26%" }),
|
|
2749
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { size: "sm", width: "46%" })
|
|
2405
2750
|
] });
|
|
2406
2751
|
}
|
|
2407
2752
|
function PromptCardGhost({ className, ...props }) {
|
|
2408
|
-
return /* @__PURE__ */ (0,
|
|
2753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(CardGhost, { className: cn("fractal-ghost-prompt-card", className), lines: 4, ...props });
|
|
2409
2754
|
}
|
|
2410
2755
|
function ConversationGhost({
|
|
2411
2756
|
className,
|
|
2412
2757
|
"aria-label": ariaLabel = "Loading conversation",
|
|
2413
2758
|
...props
|
|
2414
2759
|
}) {
|
|
2415
|
-
return /* @__PURE__ */ (0,
|
|
2760
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
2416
2761
|
"div",
|
|
2417
2762
|
{
|
|
2418
2763
|
"aria-busy": "true",
|
|
@@ -2421,54 +2766,54 @@ function ConversationGhost({
|
|
|
2421
2766
|
role: "status",
|
|
2422
2767
|
...props,
|
|
2423
2768
|
children: [
|
|
2424
|
-
/* @__PURE__ */ (0,
|
|
2425
|
-
/* @__PURE__ */ (0,
|
|
2426
|
-
/* @__PURE__ */ (0,
|
|
2427
|
-
/* @__PURE__ */ (0,
|
|
2769
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--user", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "fractal-ghost-conversation__bubble", children: [
|
|
2770
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "100%" }),
|
|
2771
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "86%" }),
|
|
2772
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "64%" })
|
|
2428
2773
|
] }) }),
|
|
2429
|
-
/* @__PURE__ */ (0,
|
|
2430
|
-
/* @__PURE__ */ (0,
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2432
|
-
/* @__PURE__ */ (0,
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: "fractal-ghost-conversation__message fractal-ghost-conversation__message--assistant", children: [
|
|
2775
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "92%" }),
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "78%" }),
|
|
2777
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "58%" })
|
|
2433
2778
|
] })
|
|
2434
2779
|
]
|
|
2435
2780
|
}
|
|
2436
2781
|
);
|
|
2437
2782
|
}
|
|
2438
2783
|
function SortableTableGhost(props) {
|
|
2439
|
-
return /* @__PURE__ */ (0,
|
|
2784
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(DataTableGhost, { ...props });
|
|
2440
2785
|
}
|
|
2441
2786
|
function SidebarGhost({ className, items = 6, ...props }) {
|
|
2442
|
-
return /* @__PURE__ */ (0,
|
|
2443
|
-
/* @__PURE__ */ (0,
|
|
2444
|
-
/* @__PURE__ */ (0,
|
|
2445
|
-
/* @__PURE__ */ (0,
|
|
2446
|
-
/* @__PURE__ */ (0,
|
|
2787
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("aside", { "aria-hidden": "true", className: cn("fractal-ghost-sidebar", className), ...props, children: [
|
|
2788
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: "fractal-ghost-sidebar__brand" }),
|
|
2789
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "fractal-ghost-sidebar__items", children: Array.from({ length: items }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "fractal-ghost-sidebar__item", children: [
|
|
2790
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, {}),
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: `${[54, 68, 44, 61][index % 4]}%` })
|
|
2447
2792
|
] }, index)) })
|
|
2448
2793
|
] });
|
|
2449
2794
|
}
|
|
2450
2795
|
function ModalGhost({ className, title, lines = 3, ...props }) {
|
|
2451
|
-
return /* @__PURE__ */ (0,
|
|
2796
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SurfaceGhost, { className: cn("fractal-ghost-modal", className), title, lines, ...props });
|
|
2452
2797
|
}
|
|
2453
2798
|
function SidePanelGhost({ className, title, lines = 5, ...props }) {
|
|
2454
|
-
return /* @__PURE__ */ (0,
|
|
2799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SurfaceGhost, { className: cn("fractal-ghost-side-panel", className), title, lines, ...props });
|
|
2455
2800
|
}
|
|
2456
2801
|
function SurfaceGhost({ className, title, lines = 3, ...props }) {
|
|
2457
|
-
return /* @__PURE__ */ (0,
|
|
2458
|
-
/* @__PURE__ */ (0,
|
|
2459
|
-
/* @__PURE__ */ (0,
|
|
2460
|
-
/* @__PURE__ */ (0,
|
|
2802
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { "aria-hidden": "true", className: cn("fractal-ghost-surface", className), ...props, children: [
|
|
2803
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "fractal-ghost-surface__header", children: [
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: "42%" }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Ghost, { className: "fractal-ghost-surface__close" })
|
|
2461
2806
|
] }),
|
|
2462
|
-
title && /* @__PURE__ */ (0,
|
|
2463
|
-
/* @__PURE__ */ (0,
|
|
2807
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "fractal-ghost-surface__title", children: title }),
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "fractal-ghost-stack", children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GhostLine, { width: index === lines - 1 ? "64%" : "100%" }, index)) })
|
|
2464
2809
|
] });
|
|
2465
2810
|
}
|
|
2466
2811
|
|
|
2467
2812
|
// src/components/Sidebar/Sidebar.tsx
|
|
2468
2813
|
var React16 = __toESM(require("react"), 1);
|
|
2469
|
-
var
|
|
2814
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2470
2815
|
var Sidebar = React16.forwardRef(
|
|
2471
|
-
({ className, width, compact = false, style, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2816
|
+
({ className, width, compact = false, style, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2472
2817
|
"aside",
|
|
2473
2818
|
{
|
|
2474
2819
|
ref,
|
|
@@ -2481,11 +2826,11 @@ var Sidebar = React16.forwardRef(
|
|
|
2481
2826
|
);
|
|
2482
2827
|
Sidebar.displayName = "Sidebar";
|
|
2483
2828
|
var SidebarHeader = React16.forwardRef(
|
|
2484
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2829
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { ref, className: cn("fractal-sidebar__header", className), ...props })
|
|
2485
2830
|
);
|
|
2486
2831
|
SidebarHeader.displayName = "SidebarHeader";
|
|
2487
2832
|
var SidebarBrand = React16.forwardRef(
|
|
2488
|
-
({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0,
|
|
2833
|
+
({ className, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { ref, type, className: cn("fractal-sidebar__brand", className), ...props })
|
|
2489
2834
|
);
|
|
2490
2835
|
SidebarBrand.displayName = "SidebarBrand";
|
|
2491
2836
|
function SidebarAccountMenu({
|
|
@@ -2496,7 +2841,7 @@ function SidebarAccountMenu({
|
|
|
2496
2841
|
icon,
|
|
2497
2842
|
className
|
|
2498
2843
|
}) {
|
|
2499
|
-
return /* @__PURE__ */ (0,
|
|
2844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2500
2845
|
Dropdown,
|
|
2501
2846
|
{
|
|
2502
2847
|
align: "left",
|
|
@@ -2506,9 +2851,9 @@ function SidebarAccountMenu({
|
|
|
2506
2851
|
panelClassName: "fractal-sidebar__account-panel",
|
|
2507
2852
|
selectedValue: "",
|
|
2508
2853
|
triggerClassName: "fractal-sidebar__account-trigger",
|
|
2509
|
-
triggerContent: /* @__PURE__ */ (0,
|
|
2510
|
-
icon && /* @__PURE__ */ (0,
|
|
2511
|
-
/* @__PURE__ */ (0,
|
|
2854
|
+
triggerContent: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
2855
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fractal-sidebar__account-icon", "aria-hidden": "true", children: icon }),
|
|
2856
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fractal-sidebar__account-name", children: name })
|
|
2512
2857
|
] }),
|
|
2513
2858
|
triggerLabel,
|
|
2514
2859
|
triggerVariant: "tertiary"
|
|
@@ -2516,15 +2861,15 @@ function SidebarAccountMenu({
|
|
|
2516
2861
|
);
|
|
2517
2862
|
}
|
|
2518
2863
|
var SidebarNav = React16.forwardRef(
|
|
2519
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2864
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("nav", { ref, className: cn("fractal-sidebar__nav", className), ...props })
|
|
2520
2865
|
);
|
|
2521
2866
|
SidebarNav.displayName = "SidebarNav";
|
|
2522
2867
|
var SidebarSection = React16.forwardRef(
|
|
2523
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2868
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { ref, className: cn("fractal-sidebar__section", className), ...props })
|
|
2524
2869
|
);
|
|
2525
2870
|
SidebarSection.displayName = "SidebarSection";
|
|
2526
2871
|
var SidebarNavItem = React16.forwardRef(
|
|
2527
|
-
({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2872
|
+
({ active = false, icon, endAdornment, className, type = "button", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
2528
2873
|
"button",
|
|
2529
2874
|
{
|
|
2530
2875
|
ref,
|
|
@@ -2534,28 +2879,60 @@ var SidebarNavItem = React16.forwardRef(
|
|
|
2534
2879
|
"aria-current": active ? "page" : void 0,
|
|
2535
2880
|
...props,
|
|
2536
2881
|
children: [
|
|
2537
|
-
icon && /* @__PURE__ */ (0,
|
|
2538
|
-
/* @__PURE__ */ (0,
|
|
2539
|
-
endAdornment && /* @__PURE__ */ (0,
|
|
2882
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fractal-sidebar__nav-item-icon", "aria-hidden": "true", children: icon }),
|
|
2883
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fractal-sidebar__nav-item-label", children }),
|
|
2884
|
+
endAdornment && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fractal-sidebar__nav-item-end", children: endAdornment })
|
|
2540
2885
|
]
|
|
2541
2886
|
}
|
|
2542
2887
|
)
|
|
2543
2888
|
);
|
|
2544
2889
|
SidebarNavItem.displayName = "SidebarNavItem";
|
|
2545
2890
|
var SidebarFooter = React16.forwardRef(
|
|
2546
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2891
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { ref, className: cn("fractal-sidebar__footer", className), ...props })
|
|
2547
2892
|
);
|
|
2548
2893
|
SidebarFooter.displayName = "SidebarFooter";
|
|
2549
2894
|
|
|
2550
2895
|
// src/components/SidePanel/SidePanel.tsx
|
|
2551
|
-
var
|
|
2552
|
-
var
|
|
2553
|
-
var
|
|
2896
|
+
var React17 = __toESM(require("react"), 1);
|
|
2897
|
+
var import_react_dom4 = require("react-dom");
|
|
2898
|
+
var import_fractal_icons14 = require("@mirror-physics/fractal-icons");
|
|
2899
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2554
2900
|
function SidePanel({ open, onClose, title, description, children, footer, size = "md", loading = false, loadingLabel = "Loading", className }) {
|
|
2555
2901
|
useEscapeDismiss(80, onClose, open);
|
|
2902
|
+
const bodyRef = React17.useRef(null);
|
|
2903
|
+
const [scrollEdges, setScrollEdges] = React17.useState({ above: false, below: false });
|
|
2904
|
+
React17.useLayoutEffect(() => {
|
|
2905
|
+
const body = bodyRef.current;
|
|
2906
|
+
if (!open || !body) return;
|
|
2907
|
+
const measure = () => {
|
|
2908
|
+
const maxScroll = Math.max(0, body.scrollHeight - body.clientHeight);
|
|
2909
|
+
const top = Math.max(0, Math.min(body.scrollTop, maxScroll));
|
|
2910
|
+
const above = maxScroll > 1 && top > 0;
|
|
2911
|
+
const below = maxScroll - top > 1;
|
|
2912
|
+
setScrollEdges((previous) => previous.above === above && previous.below === below ? previous : { above, below });
|
|
2913
|
+
};
|
|
2914
|
+
const resize = new ResizeObserver(measure);
|
|
2915
|
+
const observeContent = () => {
|
|
2916
|
+
resize.disconnect();
|
|
2917
|
+
resize.observe(body);
|
|
2918
|
+
for (const child of body.children) resize.observe(child);
|
|
2919
|
+
measure();
|
|
2920
|
+
};
|
|
2921
|
+
const mutations = new MutationObserver(observeContent);
|
|
2922
|
+
mutations.observe(body, { childList: true, subtree: true, characterData: true, attributes: true });
|
|
2923
|
+
body.addEventListener("scroll", measure, { passive: true });
|
|
2924
|
+
body.addEventListener("load", measure, true);
|
|
2925
|
+
observeContent();
|
|
2926
|
+
return () => {
|
|
2927
|
+
resize.disconnect();
|
|
2928
|
+
mutations.disconnect();
|
|
2929
|
+
body.removeEventListener("scroll", measure);
|
|
2930
|
+
body.removeEventListener("load", measure, true);
|
|
2931
|
+
};
|
|
2932
|
+
}, [open, loading]);
|
|
2556
2933
|
if (!open) return null;
|
|
2557
|
-
return (0,
|
|
2558
|
-
/* @__PURE__ */ (0,
|
|
2934
|
+
return (0, import_react_dom4.createPortal)(
|
|
2935
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "fractal-side-panel-overlay", onMouseDown: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
2559
2936
|
"aside",
|
|
2560
2937
|
{
|
|
2561
2938
|
className: cn("fractal-side-panel", `fractal-side-panel--${size}`, className),
|
|
@@ -2564,15 +2941,15 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
|
|
|
2564
2941
|
role: "dialog",
|
|
2565
2942
|
onMouseDown: (event) => event.stopPropagation(),
|
|
2566
2943
|
children: [
|
|
2567
|
-
/* @__PURE__ */ (0,
|
|
2568
|
-
/* @__PURE__ */ (0,
|
|
2569
|
-
typeof title === "string" ? /* @__PURE__ */ (0,
|
|
2570
|
-
description && /* @__PURE__ */ (0,
|
|
2944
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("header", { className: "fractal-side-panel__header", "data-scroll-divider": scrollEdges.above, children: [
|
|
2945
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "fractal-side-panel__heading", children: [
|
|
2946
|
+
typeof title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("h2", { className: "fractal-side-panel__title", children: title }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "fractal-side-panel__title", children: title }),
|
|
2947
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "fractal-side-panel__description", children: description })
|
|
2571
2948
|
] }),
|
|
2572
|
-
/* @__PURE__ */ (0,
|
|
2949
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: "fractal-side-panel__close", "aria-label": "Close panel", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_fractal_icons14.Close, { size: 18 }) })
|
|
2573
2950
|
] }),
|
|
2574
|
-
/* @__PURE__ */ (0,
|
|
2575
|
-
footer && /* @__PURE__ */ (0,
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref: bodyRef, "aria-busy": loading || void 0, className: cn("fractal-side-panel__body", loading && "fractal-side-panel__body--loading"), children: loading ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(UILoader, { label: loadingLabel }) : children }),
|
|
2952
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("footer", { className: "fractal-side-panel__footer", "data-scroll-divider": scrollEdges.below, children: footer })
|
|
2576
2953
|
]
|
|
2577
2954
|
}
|
|
2578
2955
|
) }),
|
|
@@ -2581,18 +2958,18 @@ function SidePanel({ open, onClose, title, description, children, footer, size =
|
|
|
2581
2958
|
}
|
|
2582
2959
|
|
|
2583
2960
|
// src/components/Textarea/Textarea.tsx
|
|
2584
|
-
var
|
|
2585
|
-
var
|
|
2586
|
-
var Textarea =
|
|
2587
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2961
|
+
var React18 = __toESM(require("react"), 1);
|
|
2962
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
2963
|
+
var Textarea = React18.forwardRef(
|
|
2964
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("textarea", { ref, className: cn("fractal-textarea", className), ...props })
|
|
2588
2965
|
);
|
|
2589
2966
|
Textarea.displayName = "Textarea";
|
|
2590
2967
|
|
|
2591
2968
|
// src/components/TextButton/TextButton.tsx
|
|
2592
|
-
var
|
|
2593
|
-
var
|
|
2594
|
-
var TextButton =
|
|
2595
|
-
({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ (0,
|
|
2969
|
+
var React19 = __toESM(require("react"), 1);
|
|
2970
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2971
|
+
var TextButton = React19.forwardRef(
|
|
2972
|
+
({ className, icon, iconPosition = "start", size = "md", tone = "primary", children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
2596
2973
|
"button",
|
|
2597
2974
|
{
|
|
2598
2975
|
ref,
|
|
@@ -2600,9 +2977,9 @@ var TextButton = React18.forwardRef(
|
|
|
2600
2977
|
type: "button",
|
|
2601
2978
|
...props,
|
|
2602
2979
|
children: [
|
|
2603
|
-
icon && iconPosition === "start" && /* @__PURE__ */ (0,
|
|
2604
|
-
/* @__PURE__ */ (0,
|
|
2605
|
-
icon && iconPosition === "end" && /* @__PURE__ */ (0,
|
|
2980
|
+
icon && iconPosition === "start" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon }),
|
|
2981
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children }),
|
|
2982
|
+
icon && iconPosition === "end" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "fractal-text-button__icon", "aria-hidden": "true", children: icon })
|
|
2606
2983
|
]
|
|
2607
2984
|
}
|
|
2608
2985
|
)
|
|
@@ -2610,9 +2987,9 @@ var TextButton = React18.forwardRef(
|
|
|
2610
2987
|
TextButton.displayName = "TextButton";
|
|
2611
2988
|
|
|
2612
2989
|
// src/components/FileDropzone/FileDropzone.tsx
|
|
2613
|
-
var
|
|
2614
|
-
var
|
|
2615
|
-
var
|
|
2990
|
+
var React20 = __toESM(require("react"), 1);
|
|
2991
|
+
var import_fractal_icons15 = require("@mirror-physics/fractal-icons");
|
|
2992
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2616
2993
|
function FileDropzone({
|
|
2617
2994
|
files,
|
|
2618
2995
|
onFilesChange,
|
|
@@ -2623,17 +3000,17 @@ function FileDropzone({
|
|
|
2623
3000
|
description = "Files stay attached to this record.",
|
|
2624
3001
|
className
|
|
2625
3002
|
}) {
|
|
2626
|
-
const inputId =
|
|
2627
|
-
const inputRef =
|
|
2628
|
-
const [isDragging, setIsDragging] =
|
|
3003
|
+
const inputId = React20.useId();
|
|
3004
|
+
const inputRef = React20.useRef(null);
|
|
3005
|
+
const [isDragging, setIsDragging] = React20.useState(false);
|
|
2629
3006
|
const addFiles = (nextFiles) => {
|
|
2630
3007
|
if (disabled) return;
|
|
2631
3008
|
const additions = Array.from(nextFiles);
|
|
2632
3009
|
if (additions.length === 0) return;
|
|
2633
3010
|
onFilesChange(multiple ? [...files, ...additions] : additions.slice(0, 1));
|
|
2634
3011
|
};
|
|
2635
|
-
return /* @__PURE__ */ (0,
|
|
2636
|
-
/* @__PURE__ */ (0,
|
|
3012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: cn("fractal-file-dropzone", className), children: [
|
|
3013
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2637
3014
|
"input",
|
|
2638
3015
|
{
|
|
2639
3016
|
ref: inputRef,
|
|
@@ -2649,7 +3026,7 @@ function FileDropzone({
|
|
|
2649
3026
|
}
|
|
2650
3027
|
}
|
|
2651
3028
|
),
|
|
2652
|
-
/* @__PURE__ */ (0,
|
|
3029
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
2653
3030
|
"button",
|
|
2654
3031
|
{
|
|
2655
3032
|
className: "fractal-file-dropzone__target",
|
|
@@ -2672,18 +3049,18 @@ function FileDropzone({
|
|
|
2672
3049
|
addFiles(event.dataTransfer.files);
|
|
2673
3050
|
},
|
|
2674
3051
|
children: [
|
|
2675
|
-
/* @__PURE__ */ (0,
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
2677
|
-
/* @__PURE__ */ (0,
|
|
2678
|
-
description && /* @__PURE__ */ (0,
|
|
3052
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_fractal_icons15.FileArrowUp, { "aria-hidden": "true", size: 20 }),
|
|
3053
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "fractal-file-dropzone__copy", children: [
|
|
3054
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fractal-file-dropzone__title", children: title }),
|
|
3055
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fractal-file-dropzone__description", children: description })
|
|
2679
3056
|
] })
|
|
2680
3057
|
]
|
|
2681
3058
|
}
|
|
2682
3059
|
),
|
|
2683
|
-
files.length > 0 && /* @__PURE__ */ (0,
|
|
2684
|
-
/* @__PURE__ */ (0,
|
|
2685
|
-
/* @__PURE__ */ (0,
|
|
2686
|
-
/* @__PURE__ */ (0,
|
|
3060
|
+
files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "fractal-file-dropzone__files", "aria-label": "Attached files", children: files.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { className: "fractal-file-dropzone__file", children: [
|
|
3061
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fractal-file-dropzone__file-name", children: file.name }),
|
|
3062
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fractal-file-dropzone__file-meta", children: formatFileSize(file.size) }),
|
|
3063
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2687
3064
|
"button",
|
|
2688
3065
|
{
|
|
2689
3066
|
className: "fractal-file-dropzone__remove",
|
|
@@ -2691,7 +3068,7 @@ function FileDropzone({
|
|
|
2691
3068
|
"aria-label": `Remove ${file.name}`,
|
|
2692
3069
|
disabled,
|
|
2693
3070
|
onClick: () => onFilesChange(files.filter((_, fileIndex) => fileIndex !== index)),
|
|
2694
|
-
children: /* @__PURE__ */ (0,
|
|
3071
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_fractal_icons15.Close, { "aria-hidden": "true", size: 14 })
|
|
2695
3072
|
}
|
|
2696
3073
|
)
|
|
2697
3074
|
] }, `${file.name}-${file.size}-${index}`)) })
|
|
@@ -2704,8 +3081,8 @@ function formatFileSize(bytes) {
|
|
|
2704
3081
|
}
|
|
2705
3082
|
|
|
2706
3083
|
// src/components/Pagination/Pagination.tsx
|
|
2707
|
-
var
|
|
2708
|
-
var
|
|
3084
|
+
var import_fractal_icons16 = require("@mirror-physics/fractal-icons");
|
|
3085
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2709
3086
|
function Pagination({
|
|
2710
3087
|
page,
|
|
2711
3088
|
pageSize,
|
|
@@ -2721,10 +3098,10 @@ function Pagination({
|
|
|
2721
3098
|
const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
|
|
2722
3099
|
const end = Math.min(currentPage * pageSize, totalItems);
|
|
2723
3100
|
const canChangePageSize = pageSizeOptions != null && pageSizeOptions.length > 0 && onPageSizeChange != null;
|
|
2724
|
-
return /* @__PURE__ */ (0,
|
|
2725
|
-
/* @__PURE__ */ (0,
|
|
2726
|
-
/* @__PURE__ */ (0,
|
|
2727
|
-
canChangePageSize && /* @__PURE__ */ (0,
|
|
3101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("nav", { className: cn("fractal-pagination", className), "aria-label": ariaLabel, children: [
|
|
3102
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "fractal-pagination__summary", children: totalItems === 0 ? "No results" : `${start}-${end} of ${totalItems}` }),
|
|
3103
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "fractal-pagination__controls", children: [
|
|
3104
|
+
canChangePageSize && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2728
3105
|
Dropdown,
|
|
2729
3106
|
{
|
|
2730
3107
|
align: "right",
|
|
@@ -2741,7 +3118,7 @@ function Pagination({
|
|
|
2741
3118
|
triggerVariant: "tertiary"
|
|
2742
3119
|
}
|
|
2743
3120
|
),
|
|
2744
|
-
/* @__PURE__ */ (0,
|
|
3121
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2745
3122
|
"button",
|
|
2746
3123
|
{
|
|
2747
3124
|
className: "fractal-pagination__button",
|
|
@@ -2750,15 +3127,15 @@ function Pagination({
|
|
|
2750
3127
|
title: "Previous page",
|
|
2751
3128
|
disabled: currentPage === 1 || totalItems === 0,
|
|
2752
3129
|
onClick: () => onPageChange(currentPage - 1),
|
|
2753
|
-
children: /* @__PURE__ */ (0,
|
|
3130
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_fractal_icons16.ArrowLeft, { "aria-hidden": "true", size: 16 })
|
|
2754
3131
|
}
|
|
2755
3132
|
),
|
|
2756
|
-
/* @__PURE__ */ (0,
|
|
3133
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "fractal-pagination__page", "aria-current": "page", children: [
|
|
2757
3134
|
currentPage,
|
|
2758
3135
|
" of ",
|
|
2759
3136
|
totalPages
|
|
2760
3137
|
] }),
|
|
2761
|
-
/* @__PURE__ */ (0,
|
|
3138
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2762
3139
|
"button",
|
|
2763
3140
|
{
|
|
2764
3141
|
className: "fractal-pagination__button",
|
|
@@ -2767,12 +3144,195 @@ function Pagination({
|
|
|
2767
3144
|
title: "Next page",
|
|
2768
3145
|
disabled: currentPage === totalPages || totalItems === 0,
|
|
2769
3146
|
onClick: () => onPageChange(currentPage + 1),
|
|
2770
|
-
children: /* @__PURE__ */ (0,
|
|
3147
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_fractal_icons16.ArrowRight, { "aria-hidden": "true", size: 16 })
|
|
2771
3148
|
}
|
|
2772
3149
|
)
|
|
2773
3150
|
] })
|
|
2774
3151
|
] });
|
|
2775
3152
|
}
|
|
3153
|
+
|
|
3154
|
+
// src/components/ColumnEditor/ColumnEditor.tsx
|
|
3155
|
+
var React21 = __toESM(require("react"), 1);
|
|
3156
|
+
var import_fractal_icons17 = require("@mirror-physics/fractal-icons");
|
|
3157
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
3158
|
+
var equal = (a, b) => a.length === b.length && a.every((id, index) => id === b[index]);
|
|
3159
|
+
function ColumnEditor({ items, value, onChange, label = "Edit columns", hiddenLabel = "Hidden columns", className }) {
|
|
3160
|
+
const [open, setOpen] = React21.useState(false);
|
|
3161
|
+
const [preview, setPreview] = React21.useState(null);
|
|
3162
|
+
const [announcement, setAnnouncement] = React21.useState("");
|
|
3163
|
+
const root = React21.useRef(null);
|
|
3164
|
+
const trigger = React21.useRef(null);
|
|
3165
|
+
const panel = React21.useRef(null);
|
|
3166
|
+
const drag = React21.useRef(null);
|
|
3167
|
+
const positions = React21.useRef(null);
|
|
3168
|
+
const id = React21.useId();
|
|
3169
|
+
function capturePositions() {
|
|
3170
|
+
positions.current = new Map(Array.from(panel.current?.querySelectorAll("[data-column-editor-item]") ?? []).map((row2) => [row2.dataset.columnEditorItem, row2.getBoundingClientRect()]));
|
|
3171
|
+
}
|
|
3172
|
+
React21.useLayoutEffect(() => {
|
|
3173
|
+
const before = positions.current;
|
|
3174
|
+
positions.current = null;
|
|
3175
|
+
if (!before || !panel.current || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
3176
|
+
const styles = getComputedStyle(panel.current);
|
|
3177
|
+
const token = styles.getPropertyValue("--duration-normal").trim();
|
|
3178
|
+
const duration = parseFloat(token) * (token.endsWith("ms") ? 1 : 1e3);
|
|
3179
|
+
const easing = styles.getPropertyValue("--ease-out").trim();
|
|
3180
|
+
for (const row2 of panel.current.querySelectorAll("[data-column-editor-item]")) {
|
|
3181
|
+
const previous = before.get(row2.dataset.columnEditorItem);
|
|
3182
|
+
row2.getAnimations().filter((animation) => animation.id === "fractal-column-position").forEach((animation) => animation.cancel());
|
|
3183
|
+
if (!previous) continue;
|
|
3184
|
+
const next = row2.getBoundingClientRect();
|
|
3185
|
+
const x = previous.left - next.left, y = previous.top - next.top;
|
|
3186
|
+
if (Math.abs(x) < 1 && Math.abs(y) < 1) continue;
|
|
3187
|
+
row2.animate([{ transform: `translate(${x}px, ${y}px)` }, { transform: "translate(0, 0)" }], { duration, easing, id: "fractal-column-position" });
|
|
3188
|
+
}
|
|
3189
|
+
});
|
|
3190
|
+
const valid = [...new Set(value)].filter((key) => items.some((item) => item.id === key));
|
|
3191
|
+
const committed = [...valid, ...items.filter((item) => item.required && !valid.includes(item.id)).map((item) => item.id)];
|
|
3192
|
+
const visible = preview?.visible ?? committed;
|
|
3193
|
+
const hidden = preview?.hidden ?? items.filter((item) => !committed.includes(item.id)).map((item) => item.id);
|
|
3194
|
+
function cancel() {
|
|
3195
|
+
capturePositions();
|
|
3196
|
+
drag.current = null;
|
|
3197
|
+
setPreview(null);
|
|
3198
|
+
}
|
|
3199
|
+
React21.useEffect(() => {
|
|
3200
|
+
if (!open) return;
|
|
3201
|
+
panel.current?.focus();
|
|
3202
|
+
function outside(event) {
|
|
3203
|
+
if (!drag.current && !root.current?.contains(event.target)) setOpen(false);
|
|
3204
|
+
}
|
|
3205
|
+
function escape(event) {
|
|
3206
|
+
if (event.key !== "Escape") return;
|
|
3207
|
+
event.preventDefault();
|
|
3208
|
+
if (drag.current) {
|
|
3209
|
+
capturePositions();
|
|
3210
|
+
drag.current = null;
|
|
3211
|
+
setPreview(null);
|
|
3212
|
+
setAnnouncement("Reordering cancelled");
|
|
3213
|
+
} else {
|
|
3214
|
+
setOpen(false);
|
|
3215
|
+
trigger.current?.focus();
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
function blur(event) {
|
|
3219
|
+
if (event.relatedTarget instanceof Node && !root.current?.contains(event.relatedTarget)) setOpen(false);
|
|
3220
|
+
}
|
|
3221
|
+
const element = root.current;
|
|
3222
|
+
document.addEventListener("pointerdown", outside);
|
|
3223
|
+
document.addEventListener("keydown", escape);
|
|
3224
|
+
element?.addEventListener("focusout", blur);
|
|
3225
|
+
return () => {
|
|
3226
|
+
document.removeEventListener("pointerdown", outside);
|
|
3227
|
+
document.removeEventListener("keydown", escape);
|
|
3228
|
+
element?.removeEventListener("focusout", blur);
|
|
3229
|
+
};
|
|
3230
|
+
}, [open]);
|
|
3231
|
+
function commit(next, message) {
|
|
3232
|
+
capturePositions();
|
|
3233
|
+
onChange(next);
|
|
3234
|
+
setAnnouncement(message);
|
|
3235
|
+
}
|
|
3236
|
+
function move(key, offset) {
|
|
3237
|
+
const index = committed.indexOf(key);
|
|
3238
|
+
const next = committed.filter((item) => item !== key);
|
|
3239
|
+
if (offset > 0 && index === committed.length - 1 && !items.find((item) => item.id === key)?.required) {
|
|
3240
|
+
commit(next, `${items.find((item) => item.id === key)?.label} hidden`);
|
|
3241
|
+
return;
|
|
3242
|
+
}
|
|
3243
|
+
next.splice(Math.max(0, Math.min(next.length, index + offset)), 0, key);
|
|
3244
|
+
commit(next, `${items.find((item) => item.id === key)?.label} moved ${offset < 0 ? "up" : "down"}`);
|
|
3245
|
+
}
|
|
3246
|
+
function start(event, key) {
|
|
3247
|
+
if (event.button !== 0 || event.target.closest("button")) return;
|
|
3248
|
+
drag.current = { id: key, pointerId: event.pointerId, x: event.clientX, y: event.clientY, active: false, visible: [...committed], hidden: [...hidden] };
|
|
3249
|
+
panel.current?.setPointerCapture(event.pointerId);
|
|
3250
|
+
event.preventDefault();
|
|
3251
|
+
}
|
|
3252
|
+
function update(event) {
|
|
3253
|
+
const current = drag.current;
|
|
3254
|
+
if (!current || event.pointerId !== current.pointerId) return;
|
|
3255
|
+
if (!current.active && Math.hypot(event.clientX - current.x, event.clientY - current.y) < 4) return;
|
|
3256
|
+
current.active = true;
|
|
3257
|
+
const container = panel.current;
|
|
3258
|
+
if (!container) return;
|
|
3259
|
+
const bounds = container.getBoundingClientRect();
|
|
3260
|
+
const hiddenGroup = container.querySelector('[data-column-editor-group="hidden"]');
|
|
3261
|
+
const inside = event.clientX >= bounds.left && event.clientX <= bounds.right && event.clientY >= bounds.top && event.clientY <= bounds.bottom;
|
|
3262
|
+
if (!inside) return;
|
|
3263
|
+
const destination = event.clientY >= hiddenGroup.getBoundingClientRect().top ? "hidden" : "visible";
|
|
3264
|
+
if (destination === "hidden" && items.find((item) => item.id === current.id)?.required) return;
|
|
3265
|
+
const slots = Array.from(container.querySelectorAll(`[data-column-editor-group="${destination}"] [data-column-editor-item]`));
|
|
3266
|
+
const localY = event.clientY - bounds.top + container.scrollTop - container.clientTop;
|
|
3267
|
+
const ownSlot = slots.find((row2) => row2.dataset.columnEditorItem === current.id);
|
|
3268
|
+
if (ownSlot && localY >= ownSlot.offsetTop && localY <= ownSlot.offsetTop + ownSlot.offsetHeight) return;
|
|
3269
|
+
const nextVisible = current.visible.filter((key) => key !== current.id);
|
|
3270
|
+
let nextHidden = current.hidden.filter((key) => key !== current.id);
|
|
3271
|
+
if (destination === "visible") {
|
|
3272
|
+
const index = slots.filter((row2) => row2.dataset.columnEditorItem !== current.id && localY > row2.offsetTop + row2.offsetHeight / 2).length;
|
|
3273
|
+
nextVisible.splice(index, 0, current.id);
|
|
3274
|
+
} else {
|
|
3275
|
+
nextHidden.push(current.id);
|
|
3276
|
+
nextHidden = items.filter((item) => nextHidden.includes(item.id)).map((item) => item.id);
|
|
3277
|
+
}
|
|
3278
|
+
if (!equal(nextVisible, current.visible) || !equal(nextHidden, current.hidden)) {
|
|
3279
|
+
capturePositions();
|
|
3280
|
+
current.visible = nextVisible;
|
|
3281
|
+
current.hidden = nextHidden;
|
|
3282
|
+
}
|
|
3283
|
+
setPreview({ visible: current.visible, hidden: current.hidden, active: current.id });
|
|
3284
|
+
if (event.clientY < bounds.top + 32) container.scrollTop -= 12;
|
|
3285
|
+
else if (event.clientY > bounds.bottom - 32) container.scrollTop += 12;
|
|
3286
|
+
}
|
|
3287
|
+
function finish(event) {
|
|
3288
|
+
const current = drag.current;
|
|
3289
|
+
if (!current || current.pointerId !== event.pointerId) return;
|
|
3290
|
+
const hit = document.elementFromPoint(event.clientX, event.clientY);
|
|
3291
|
+
if (current.active && hit && panel.current?.contains(hit)) commit(current.visible, "Column order updated");
|
|
3292
|
+
cancel();
|
|
3293
|
+
if (panel.current?.hasPointerCapture(event.pointerId)) panel.current.releasePointerCapture(event.pointerId);
|
|
3294
|
+
}
|
|
3295
|
+
function row(key, isHidden, index) {
|
|
3296
|
+
const item = items.find((item2) => item2.id === key);
|
|
3297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
3298
|
+
"li",
|
|
3299
|
+
{
|
|
3300
|
+
className: "fractal-column-editor__row",
|
|
3301
|
+
"data-column-editor-item": key,
|
|
3302
|
+
"data-hidden": isHidden || void 0,
|
|
3303
|
+
"data-dragging": preview?.active === key || void 0,
|
|
3304
|
+
onPointerDown: (event) => start(event, key),
|
|
3305
|
+
children: [
|
|
3306
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.DotsSixVertical, { className: "fractal-column-editor__grip", "aria-hidden": "true" }),
|
|
3307
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "fractal-column-editor__name", children: item.label }),
|
|
3308
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "fractal-column-editor__actions", onPointerDown: (event) => event.stopPropagation(), children: isHidden ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Button, { buttonType: "ghost", controlSize: "sm", hasIconOnly: true, icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.Eye, { "aria-hidden": "true" }), "aria-label": `Show ${item.label} column`, onClick: () => commit([...committed, key], `${item.label} shown`) }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
3309
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Button, { buttonType: "ghost", controlSize: "sm", hasIconOnly: true, icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.ArrowUp, { "aria-hidden": "true" }), "aria-label": `Move ${item.label} up`, disabled: index === 0, onClick: () => move(key, -1) }),
|
|
3310
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Button, { buttonType: "ghost", controlSize: "sm", hasIconOnly: true, icon: index === visible.length - 1 && !item.required ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.EyeSlash, { "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.ArrowDown, { "aria-hidden": "true" }), "aria-label": index === visible.length - 1 && !item.required ? `Hide ${item.label} column` : `Move ${item.label} down`, disabled: index === visible.length - 1 && item.required, onClick: () => move(key, 1) })
|
|
3311
|
+
] }) })
|
|
3312
|
+
]
|
|
3313
|
+
},
|
|
3314
|
+
key
|
|
3315
|
+
);
|
|
3316
|
+
}
|
|
3317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn("fractal-column-editor", className), ref: root, children: [
|
|
3318
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Button, { ref: trigger, controlSize: "lg", buttonType: "secondary", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.Gear, { "aria-hidden": "true" }), iconPosition: "right", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": id, onClick: () => {
|
|
3319
|
+
cancel();
|
|
3320
|
+
setOpen((current) => !current);
|
|
3321
|
+
}, children: label }),
|
|
3322
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { id, className: "fractal-column-editor__panel", ref: panel, role: "dialog", "data-dragging": Boolean(preview) || void 0, "aria-label": label, tabIndex: -1, onPointerMove: update, onPointerUp: finish, onPointerCancel: cancel, onLostPointerCapture: cancel, children: [
|
|
3323
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ol", { className: "fractal-column-editor__list", "data-column-editor-group": "visible", "aria-label": "Visible columns", children: visible.map((key, index) => row(key, false, index)) }),
|
|
3324
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("section", { "data-column-editor-group": "hidden", className: "fractal-column-editor__hidden", "aria-label": hiddenLabel, children: [
|
|
3325
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "fractal-column-editor__divider", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
|
|
3326
|
+
hiddenLabel,
|
|
3327
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fractal_icons17.EyeSlash, { "aria-hidden": "true" })
|
|
3328
|
+
] }) }),
|
|
3329
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ol", { className: "fractal-column-editor__list", children: hidden.map((key, index) => row(key, true, index)) }),
|
|
3330
|
+
!hidden.length ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "fractal-column-editor__empty", children: "Drag columns here to hide them." }) : null
|
|
3331
|
+
] }),
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "fractal-column-editor__announcement", role: "status", "aria-live": "polite", children: announcement })
|
|
3333
|
+
] }) : null
|
|
3334
|
+
] });
|
|
3335
|
+
}
|
|
2776
3336
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2777
3337
|
0 && (module.exports = {
|
|
2778
3338
|
Alert,
|
|
@@ -2794,6 +3354,7 @@ function Pagination({
|
|
|
2794
3354
|
Chip,
|
|
2795
3355
|
ChipGhost,
|
|
2796
3356
|
CodeBlock,
|
|
3357
|
+
ColumnEditor,
|
|
2797
3358
|
ContentSwitcher,
|
|
2798
3359
|
ContentSwitcherGhost,
|
|
2799
3360
|
ConversationGhost,
|