@cytario/design 9.6.2 → 9.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1385,1067 +1385,1883 @@ function Select({
1385
1385
  );
1386
1386
  }
1387
1387
 
1388
+ // src/index.ts
1389
+ import { ListBox as ListBox2, ListBoxItem as ListBoxItem2 } from "react-aria-components";
1390
+
1388
1391
  // src/components/Table/Table.tsx
1389
1392
  import {
1390
- Cell as AriaCell,
1391
- Column as AriaColumn,
1392
- Row as AriaRow,
1393
- Table as AriaTable,
1394
- TableBody as AriaTableBody,
1395
- TableHeader as AriaTableHeader
1396
- } from "react-aria-components";
1397
- import { twMerge as twMerge11 } from "tailwind-merge";
1393
+ useReactTable,
1394
+ getCoreRowModel,
1395
+ getSortedRowModel,
1396
+ getFilteredRowModel,
1397
+ getFacetedUniqueValues
1398
+ } from "@tanstack/react-table";
1399
+ import { useCallback as useCallback8, useMemo as useMemo4, useRef as useRef5 } from "react";
1400
+
1401
+ // src/components/EmptyState/EmptyState.tsx
1398
1402
  import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
1399
- var tableSizeClass = {
1400
- compact: "[--table-row-py:theme(spacing.1)]",
1401
- comfortable: "[--table-row-py:theme(spacing.3)]"
1402
- };
1403
- function Table2({
1404
- size = "comfortable",
1405
- className,
1406
- ...props
1403
+ function EmptyState({
1404
+ icon,
1405
+ title,
1406
+ description,
1407
+ action,
1408
+ className
1407
1409
  }) {
1408
- return /* @__PURE__ */ jsx17(
1409
- AriaTable,
1410
+ return /* @__PURE__ */ jsxs9(
1411
+ "div",
1410
1412
  {
1411
- ...props,
1412
- className: twMerge11(
1413
- "w-full border-collapse text-sm text-foreground",
1414
- tableSizeClass[size],
1413
+ className: [
1414
+ "flex flex-col items-center text-center py-12 px-6",
1415
1415
  className
1416
- )
1416
+ ].filter(Boolean).join(" "),
1417
+ children: [
1418
+ icon && /* @__PURE__ */ jsx17(Icon, { icon, size: "xl", className: "text-muted-foreground" }),
1419
+ /* @__PURE__ */ jsx17("h3", { className: "text-lg font-semibold text-foreground mt-4", children: title }),
1420
+ description && /* @__PURE__ */ jsx17("p", { className: "text-sm text-muted-foreground mt-2 max-w-sm", children: description }),
1421
+ action && /* @__PURE__ */ jsx17("div", { className: "mt-6", children: action })
1422
+ ]
1417
1423
  }
1418
1424
  );
1419
1425
  }
1420
- function TableHeader(props) {
1421
- return /* @__PURE__ */ jsx17(AriaTableHeader, { ...props });
1426
+
1427
+ // src/components/Table/useColumnFilters.ts
1428
+ import { useCallback as useCallback2 } from "react";
1429
+ import { useStore } from "zustand";
1430
+
1431
+ // src/components/Table/state/createTableStore.ts
1432
+ import { createStore } from "zustand";
1433
+ import { devtools, persist } from "zustand/middleware";
1434
+
1435
+ // src/components/Table/persistMigration.ts
1436
+ function createMigrate(migrations, fallbackState) {
1437
+ return (persistedState, version) => {
1438
+ try {
1439
+ let state = persistedState;
1440
+ const targetVersion = Math.max(...Object.keys(migrations).map(Number)) + 1;
1441
+ for (let v = version; v < targetVersion; v++) {
1442
+ const migration = migrations[v];
1443
+ if (migration) {
1444
+ state = migration(state);
1445
+ }
1446
+ }
1447
+ return state;
1448
+ } catch (error) {
1449
+ console.warn("[persist] Migration failed, using fallback state:", error);
1450
+ return fallbackState;
1451
+ }
1452
+ };
1422
1453
  }
1423
- function Column({ className, ...props }) {
1424
- return /* @__PURE__ */ jsx17(
1425
- AriaColumn,
1454
+
1455
+ // src/components/Table/state/createTableStore.ts
1456
+ var createTableStore = (tableId) => createStore()(
1457
+ persist(
1458
+ devtools(
1459
+ (set) => ({
1460
+ tableId,
1461
+ columnWidths: {},
1462
+ sorting: [],
1463
+ columnVisibility: {},
1464
+ columnFilters: [],
1465
+ setColumnWidth: (columnId, width) => set(
1466
+ (state) => ({
1467
+ columnWidths: {
1468
+ ...state.columnWidths,
1469
+ [columnId]: width
1470
+ }
1471
+ }),
1472
+ false,
1473
+ "setColumnWidth"
1474
+ ),
1475
+ setSorting: (sorting) => set({ sorting }, false, "setSorting"),
1476
+ setColumnVisibility: (columnVisibility) => set({ columnVisibility }, false, "setColumnVisibility"),
1477
+ setColumnFilters: (columnFilters) => set({ columnFilters }, false, "setColumnFilters"),
1478
+ reset: () => set(
1479
+ {
1480
+ columnWidths: {},
1481
+ sorting: [],
1482
+ columnVisibility: {},
1483
+ columnFilters: []
1484
+ },
1485
+ false,
1486
+ "reset"
1487
+ )
1488
+ }),
1489
+ { name: `TableStore-${tableId}` }
1490
+ ),
1426
1491
  {
1427
- ...props,
1428
- className: twMerge11(
1429
- "px-3 py-2 text-left font-semibold text-muted-foreground",
1430
- "border-b-2 border-border",
1431
- "cursor-default select-none outline-none",
1432
- "focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-[-2px]",
1433
- className
1492
+ name: `TableStore-${tableId}`,
1493
+ version: 1,
1494
+ migrate: createMigrate(
1495
+ {
1496
+ 0: () => ({
1497
+ columnWidths: {},
1498
+ sorting: [],
1499
+ columnVisibility: {},
1500
+ columnFilters: []
1501
+ })
1502
+ },
1503
+ {
1504
+ columnWidths: {},
1505
+ sorting: [],
1506
+ columnVisibility: {},
1507
+ columnFilters: []
1508
+ }
1434
1509
  ),
1435
- children: ({ allowsSorting, sortDirection }) => /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-1", children: [
1436
- props.children,
1437
- allowsSorting && /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: "text-muted-foreground", children: sortDirection === "ascending" ? "\u25B2" : sortDirection === "descending" ? "\u25BC" : "\u25B4" })
1438
- ] })
1510
+ onRehydrateStorage: () => (_state, error) => {
1511
+ if (error) console.error(`[TableStore-${tableId}] Rehydration failed:`, error);
1512
+ }
1439
1513
  }
1514
+ )
1515
+ );
1516
+
1517
+ // src/components/Table/state/useTableStore.ts
1518
+ var tableStores = /* @__PURE__ */ new Map();
1519
+ function useTableStore(tableId) {
1520
+ let store = tableStores.get(tableId);
1521
+ if (!store) {
1522
+ store = createTableStore(tableId);
1523
+ tableStores.set(tableId, store);
1524
+ }
1525
+ return store;
1526
+ }
1527
+ function getTableStore(tableId) {
1528
+ return tableStores.get(tableId);
1529
+ }
1530
+
1531
+ // src/components/Table/useColumnFilters.ts
1532
+ function useColumnFilters({ tableId }) {
1533
+ const store = useTableStore(tableId);
1534
+ const columnFilters = useStore(store, (s) => s.columnFilters);
1535
+ const setFiltersStore = useStore(store, (s) => s.setColumnFilters);
1536
+ const setColumnFilters = useCallback2(
1537
+ (updaterOrValue) => {
1538
+ const current = store.getState().columnFilters;
1539
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(current) : updaterOrValue;
1540
+ setFiltersStore(next);
1541
+ },
1542
+ [store, setFiltersStore]
1440
1543
  );
1544
+ const resetFilters = useCallback2(() => {
1545
+ setFiltersStore([]);
1546
+ }, [setFiltersStore]);
1547
+ return { columnFilters, setColumnFilters, resetFilters };
1441
1548
  }
1442
- function TableBody(props) {
1443
- return /* @__PURE__ */ jsx17(AriaTableBody, { ...props });
1549
+
1550
+ // src/components/Table/NoFilterResults.tsx
1551
+ import { jsx as jsx18 } from "react/jsx-runtime";
1552
+ function NoFilterResults({ tableId }) {
1553
+ const { resetFilters } = useColumnFilters({ tableId });
1554
+ return /* @__PURE__ */ jsx18(
1555
+ EmptyState,
1556
+ {
1557
+ icon: "SearchX",
1558
+ title: "No results",
1559
+ description: "No results match your filters",
1560
+ action: /* @__PURE__ */ jsx18(Button, { variant: "secondary", iconLeft: "FilterX", onPress: resetFilters, children: "Clear all filters" })
1561
+ }
1562
+ );
1444
1563
  }
1445
- function Row({
1446
- className,
1447
- ...props
1448
- }) {
1449
- return /* @__PURE__ */ jsx17(
1450
- AriaRow,
1564
+
1565
+ // src/components/Form/Checkbox/Checkbox.tsx
1566
+ import {
1567
+ Checkbox as AriaCheckbox
1568
+ } from "react-aria-components";
1569
+ import { Check as Check3 } from "lucide-react";
1570
+ import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
1571
+ function stopToggleForInteractive(e) {
1572
+ if (e.target instanceof Element && e.target.closest("a, button, input, select, textarea")) {
1573
+ e.stopPropagation();
1574
+ }
1575
+ }
1576
+ function Checkbox({ children, className, ...props }) {
1577
+ return /* @__PURE__ */ jsx19(
1578
+ AriaCheckbox,
1451
1579
  {
1452
1580
  ...props,
1453
- className: twMerge11(
1454
- "border-b border-border",
1455
- "even:bg-card",
1456
- "hover:bg-muted",
1457
- "data-[selected]:bg-accent",
1458
- "data-[selected]:ring-2 data-[selected]:ring-ring data-[selected]:ring-inset",
1459
- "outline-none",
1460
- "focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-[-2px]",
1461
- "transition-colors",
1581
+ className: [
1582
+ "group flex items-center gap-2 text-sm text-foreground cursor-pointer",
1583
+ "disabled:opacity-50 disabled:cursor-default",
1462
1584
  className
1463
- )
1585
+ ].filter(Boolean).join(" "),
1586
+ children: ({ isSelected, isIndeterminate }) => /* @__PURE__ */ jsxs10(Fragment2, { children: [
1587
+ /* @__PURE__ */ jsxs10(
1588
+ "div",
1589
+ {
1590
+ className: [
1591
+ "flex items-center justify-center w-6 h-6 shrink-0",
1592
+ "rounded-sm border transition-colors",
1593
+ "group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2",
1594
+ isSelected || isIndeterminate ? "bg-primary border-primary" : "bg-background border-border group-hover:border-border"
1595
+ ].join(" "),
1596
+ children: [
1597
+ isSelected && /* @__PURE__ */ jsx19(Check3, { className: "w-4 h-4 text-primary-foreground", strokeWidth: 3 }),
1598
+ isIndeterminate && /* @__PURE__ */ jsx19("div", { className: "w-3 h-0.5 bg-primary-foreground rounded-full" })
1599
+ ]
1600
+ }
1601
+ ),
1602
+ children && /* @__PURE__ */ jsx19(
1603
+ "span",
1604
+ {
1605
+ onPointerDown: stopToggleForInteractive,
1606
+ onPointerUp: stopToggleForInteractive,
1607
+ onMouseDown: stopToggleForInteractive,
1608
+ onClick: stopToggleForInteractive,
1609
+ children
1610
+ }
1611
+ )
1612
+ ] })
1464
1613
  }
1465
1614
  );
1466
1615
  }
1467
- function Cell({ className, ...props }) {
1468
- return /* @__PURE__ */ jsx17(
1469
- AriaCell,
1616
+
1617
+ // src/components/Table/TableBodyRow.tsx
1618
+ import { flexRender } from "@tanstack/react-table";
1619
+ import { useCallback as useCallback3 } from "react";
1620
+ import { twMerge as twMerge11 } from "tailwind-merge";
1621
+ import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
1622
+ function TableBodyRow({
1623
+ row,
1624
+ rowIndex,
1625
+ columns,
1626
+ enableRowSelection,
1627
+ className
1628
+ }) {
1629
+ const handleKeyDown = useCallback3((event) => {
1630
+ const tr = event.currentTarget;
1631
+ if (event.key === "ArrowDown") {
1632
+ event.preventDefault();
1633
+ const next = tr.nextElementSibling;
1634
+ next?.focus();
1635
+ } else if (event.key === "ArrowUp") {
1636
+ event.preventDefault();
1637
+ const prev = tr.previousElementSibling;
1638
+ prev?.focus();
1639
+ } else if (event.key === "Enter") {
1640
+ const link = tr.querySelector("a");
1641
+ link?.click();
1642
+ }
1643
+ }, []);
1644
+ return /* @__PURE__ */ jsx20(
1645
+ "tr",
1470
1646
  {
1471
- ...props,
1647
+ tabIndex: 0,
1648
+ onKeyDown: handleKeyDown,
1472
1649
  className: twMerge11(
1473
- "px-3 py-(--table-row-py)",
1474
- "text-foreground",
1475
- "outline-none",
1476
- "focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-[-2px]",
1650
+ "w-full block border-b border-border",
1651
+ "hover:bg-card transition-colors",
1652
+ "focus-visible:outline-none focus-visible:bg-muted focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
1653
+ row.getIsSelected() && "bg-accent",
1477
1654
  className
1478
- )
1655
+ ),
1656
+ children: row.getVisibleCells().map((cell) => {
1657
+ const isIndexColumn = cell.column.id === "index";
1658
+ const columnConfig = columns.find((col) => col.id === cell.column.id);
1659
+ const isRight = columnConfig?.align === "right";
1660
+ const alignClass = isRight ? "text-right" : columnConfig?.align === "center" ? "text-center" : "text-left";
1661
+ const cxCell = twMerge11(
1662
+ "px-4 py-2",
1663
+ isIndexColumn ? "text-right" : alignClass,
1664
+ columnConfig?.monospace && "font-mono font-light",
1665
+ (isRight || isIndexColumn) && "tabular-nums",
1666
+ !columnConfig?.anchor && !isIndexColumn && "text-sm"
1667
+ );
1668
+ const style = {
1669
+ width: cell.column.getSize(),
1670
+ minWidth: cell.column.getSize(),
1671
+ maxWidth: cell.column.getSize()
1672
+ };
1673
+ const rawValue = cell.getValue();
1674
+ const useRawString = columnConfig?.ellipsis === "middle" && typeof rawValue === "string";
1675
+ const content = isIndexColumn ? rowIndex + 1 : useRawString ? rawValue : flexRender(cell.column.columnDef.cell, cell.getContext());
1676
+ const copyValue = columnConfig?.copyable && typeof rawValue === "string" ? rawValue : void 0;
1677
+ return isIndexColumn ? /* @__PURE__ */ jsx20("th", { className: "p-2", style, children: /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 text-sm text-muted-foreground tabular-nums justify-between", children: [
1678
+ enableRowSelection && /* @__PURE__ */ jsx20(Checkbox, { isSelected: row.getIsSelected(), onChange: () => row.toggleSelected() }),
1679
+ /* @__PURE__ */ jsx20("span", { children: rowIndex + 1 })
1680
+ ] }) }, cell.id) : /* @__PURE__ */ jsx20("td", { className: cxCell, style, children: /* @__PURE__ */ jsx20(TruncatedText, { ellipsis: columnConfig?.ellipsis, copyValue, children: content }) }, cell.id);
1681
+ })
1479
1682
  }
1480
1683
  );
1481
1684
  }
1482
1685
 
1483
- // src/components/Dialog/Dialog.tsx
1484
- import {
1485
- Modal,
1486
- ModalOverlay,
1487
- Dialog as AriaDialog,
1488
- Heading as Heading3
1489
- } from "react-aria-components";
1490
- import { X as X2 } from "lucide-react";
1491
- import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
1686
+ // src/components/Table/TableHeaderRow.tsx
1687
+ import { flexRender as flexRender2 } from "@tanstack/react-table";
1688
+ import { twMerge as twMerge16 } from "tailwind-merge";
1689
+
1690
+ // src/components/Badge/Badge.tsx
1691
+ import { twMerge as twMerge13 } from "tailwind-merge";
1692
+
1693
+ // src/components/MetricText/MetricText.tsx
1694
+ import { twMerge as twMerge12 } from "tailwind-merge";
1695
+ import { jsx as jsx21 } from "react/jsx-runtime";
1696
+ function MetricText({ className, ...rest }) {
1697
+ const cx = twMerge12(
1698
+ "text-xs font-medium leading-none tracking-wider tabular-nums",
1699
+ className
1700
+ );
1701
+ return /* @__PURE__ */ jsx21("span", { className: cx, ...rest });
1702
+ }
1703
+
1704
+ // src/components/Badge/Badge.tsx
1705
+ import { jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
1706
+ var colorStyles = {
1707
+ purple: "bg-badge-purple-bg text-badge-purple-text border-badge-purple-text/20",
1708
+ teal: "bg-badge-teal-bg text-badge-teal-text border-badge-teal-text/20",
1709
+ rose: "bg-badge-rose-bg text-badge-rose-text border-badge-rose-text/20",
1710
+ slate: "bg-badge-slate-bg text-badge-slate-text border-badge-slate-text/20",
1711
+ green: "bg-badge-green-bg text-badge-green-text border-badge-green-text/20",
1712
+ amber: "bg-badge-amber-bg text-badge-amber-text border-badge-amber-text/20"
1713
+ };
1492
1714
  var sizeStyles3 = {
1493
- sm: "max-w-md",
1494
- md: "max-w-lg",
1495
- lg: "max-w-2xl",
1496
- xl: "max-w-4xl"
1715
+ xs: "px-1 py-0 text-[10px]",
1716
+ sm: "px-1.5 py-0.5 text-xs",
1717
+ md: "px-2 py-0.5 text-xs",
1718
+ lg: "px-2.5 py-1 text-sm"
1497
1719
  };
1498
- function Dialog({
1499
- isOpen,
1500
- onOpenChange,
1501
- title,
1502
- size = "md",
1503
- isDismissable = true,
1720
+ function Badge({
1504
1721
  children,
1505
- className
1722
+ color = "slate",
1723
+ size = "sm",
1724
+ icon,
1725
+ className,
1726
+ ...rest
1506
1727
  }) {
1507
- return /* @__PURE__ */ jsx18(
1508
- ModalOverlay,
1728
+ return /* @__PURE__ */ jsxs12(
1729
+ MetricText,
1509
1730
  {
1510
- isOpen,
1511
- onOpenChange,
1512
- isDismissable,
1513
- className: [
1514
- "fixed inset-0 z-50 bg-backdrop backdrop-blur-sm",
1515
- "flex items-center justify-center",
1516
- "entering:animate-in entering:fade-in",
1517
- "exiting:animate-out exiting:fade-out"
1518
- ].join(" "),
1519
- children: /* @__PURE__ */ jsx18(
1520
- Modal,
1521
- {
1522
- className: [
1523
- "w-full mx-4",
1524
- sizeStyles3[size],
1525
- "bg-background rounded-lg shadow-xl max-h-[85vh] flex flex-col",
1526
- "entering:animate-in entering:zoom-in-95 entering:fade-in",
1527
- "exiting:animate-out exiting:zoom-out-95 exiting:fade-out",
1528
- className
1529
- ].filter(Boolean).join(" "),
1530
- children: /* @__PURE__ */ jsx18(AriaDialog, { className: "outline-none flex flex-col max-h-[85vh]", children: ({ close }) => /* @__PURE__ */ jsxs10(Fragment2, { children: [
1531
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border", children: [
1532
- /* @__PURE__ */ jsx18(
1533
- Heading3,
1534
- {
1535
- slot: "title",
1536
- className: "text-lg font-semibold text-foreground",
1537
- children: title
1538
- }
1539
- ),
1540
- /* @__PURE__ */ jsx18(
1541
- "button",
1542
- {
1543
- type: "button",
1544
- onClick: close,
1545
- className: [
1546
- "inline-flex items-center justify-center rounded-sm p-1",
1547
- "text-muted-foreground hover:text-foreground hover:bg-muted",
1548
- "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
1549
- "transition-colors"
1550
- ].join(" "),
1551
- "aria-label": "Close",
1552
- children: /* @__PURE__ */ jsx18(X2, { size: 20, "aria-hidden": "true" })
1553
- }
1554
- )
1555
- ] }),
1556
- /* @__PURE__ */ jsx18("div", { className: "px-6 py-4 overflow-y-auto", children })
1557
- ] }) })
1558
- }
1559
- )
1731
+ className: twMerge13(
1732
+ "inline-flex items-center gap-1 rounded-full border",
1733
+ colorStyles[color],
1734
+ sizeStyles3[size],
1735
+ className
1736
+ ),
1737
+ ...rest,
1738
+ children: [
1739
+ icon && /* @__PURE__ */ jsx22(Icon, { icon, size: "xs" }),
1740
+ children
1741
+ ]
1560
1742
  }
1561
1743
  );
1562
1744
  }
1563
1745
 
1564
- // src/components/Dialog/DialogFooter.tsx
1565
- import { jsx as jsx19 } from "react/jsx-runtime";
1746
+ // src/components/Table/ColumnFilterInput.tsx
1747
+ import { useMemo } from "react";
1748
+ import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
1749
+ var ALL_KEY = "__all__";
1750
+ var ALL_OPTION = { id: ALL_KEY, name: "All" };
1751
+ var AllPill = () => /* @__PURE__ */ jsx23(Badge, { color: "slate", children: "All" });
1752
+ function ColumnFilterInput({
1753
+ column,
1754
+ filterType,
1755
+ filterPlaceholder,
1756
+ filterOptions,
1757
+ filterRender
1758
+ }) {
1759
+ const filterValue = column.getFilterValue() ?? "";
1760
+ const selectItems = useMemo(() => {
1761
+ if (filterType !== "select") return [];
1762
+ if (filterOptions) {
1763
+ return [
1764
+ ALL_OPTION,
1765
+ ...filterOptions.filter((o) => o.value !== "").map((o) => ({ id: o.value, name: o.label }))
1766
+ ];
1767
+ }
1768
+ const facetedValues = column.getFacetedUniqueValues();
1769
+ return [
1770
+ ALL_OPTION,
1771
+ ...Array.from(facetedValues.keys()).filter((v) => v != null && v !== "").map(String).sort().map((v) => ({ id: v, name: v }))
1772
+ ];
1773
+ }, [column, filterType, filterOptions]);
1774
+ const selectedKey = filterValue || ALL_KEY;
1775
+ const setFilter = (key) => column.setFilterValue(key === ALL_KEY ? void 0 : key);
1776
+ const clearFilter = () => column.setFilterValue(void 0);
1777
+ const renderItem = useMemo(() => {
1778
+ if (!filterRender) return void 0;
1779
+ const render = filterRender;
1780
+ function FilterOption(item) {
1781
+ return item.id === ALL_KEY ? /* @__PURE__ */ jsx23(AllPill, {}) : render({ label: item.name, value: item.id });
1782
+ }
1783
+ return FilterOption;
1784
+ }, [filterRender]);
1785
+ return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1 font-normal", children: [
1786
+ filterType === "select" ? /* @__PURE__ */ jsx23(
1787
+ Select,
1788
+ {
1789
+ size: "sm",
1790
+ className: "w-full",
1791
+ items: selectItems,
1792
+ value: selectedKey,
1793
+ onChange: (key) => setFilter(String(key)),
1794
+ "aria-label": `Filter by ${column.columnDef.header}`,
1795
+ renderItem
1796
+ }
1797
+ ) : /* @__PURE__ */ jsx23(
1798
+ Input,
1799
+ {
1800
+ value: filterValue,
1801
+ onChange: setFilter,
1802
+ placeholder: filterPlaceholder ?? `Filter ${column.columnDef.header}...`,
1803
+ "aria-label": `Filter by ${column.columnDef.header}`,
1804
+ size: "sm"
1805
+ }
1806
+ ),
1807
+ filterValue && /* @__PURE__ */ jsx23(IconButton, { icon: "X", size: "sm", variant: "ghost", onPress: clearFilter, label: "Clear filter" })
1808
+ ] });
1809
+ }
1566
1810
 
1567
- // src/components/Toast/Toast.tsx
1568
- import {
1569
- createContext,
1570
- useCallback as useCallback2,
1571
- useContext,
1572
- useEffect as useEffect2,
1573
- useRef as useRef4,
1574
- useState as useState6
1575
- } from "react";
1576
- import { createPortal as createPortal2 } from "react-dom";
1577
- import { CheckCircle as CheckCircle3, XCircle as XCircle2, Info as Info2, X as X3 } from "lucide-react";
1578
- import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
1579
- var ToastContext = createContext(null);
1580
- var toastCounter = 0;
1581
- var defaultDuration = {
1582
- success: 5e3,
1583
- info: 5e3,
1584
- error: 1e4
1811
+ // src/components/Table/ColumnResizeHandle.tsx
1812
+ import { jsx as jsx24 } from "react/jsx-runtime";
1813
+ var ColumnResizeHandle = ({ header }) => {
1814
+ return /* @__PURE__ */ jsx24(
1815
+ "button",
1816
+ {
1817
+ type: "button",
1818
+ onMouseDown: header.getResizeHandler(),
1819
+ onTouchStart: header.getResizeHandler(),
1820
+ "aria-label": `Resize ${header.column.columnDef.header} column`,
1821
+ className: `
1822
+ z-20 cursor-col-resize
1823
+ absolute top-0 right-0 h-full w-2
1824
+ flex justify-end
1825
+ transition-colors duration-200
1826
+ bg-transparent hover:bg-accent active:bg-secondary
1827
+ `,
1828
+ children: /* @__PURE__ */ jsx24("div", { className: "w-px h-full bg-border" })
1829
+ }
1830
+ );
1585
1831
  };
1586
- var variantConfig = {
1587
- success: {
1588
- icon: CheckCircle3,
1589
- containerClass: "bg-success-surface border-success-border text-success",
1590
- iconClass: "text-success"
1591
- },
1592
- error: {
1593
- icon: XCircle2,
1594
- containerClass: "bg-destructive-surface border-destructive-border text-destructive",
1595
- iconClass: "text-destructive"
1596
- },
1597
- info: {
1598
- icon: Info2,
1599
- containerClass: "bg-info-surface border-info-border text-info",
1600
- iconClass: "text-info"
1832
+
1833
+ // src/components/Table/ColumnSortButton.tsx
1834
+ import { jsx as jsx25 } from "react/jsx-runtime";
1835
+ function getStyle(sortDirection) {
1836
+ switch (sortDirection) {
1837
+ case "desc":
1838
+ case "asc":
1839
+ return "text-muted-foreground group-hover/header:text-foreground";
1840
+ default:
1841
+ return "text-muted-foreground opacity-0 group-hover/header:opacity-100";
1601
1842
  }
1843
+ }
1844
+ var ColumnSortButton = ({ header }) => {
1845
+ const sortDirection = header.column.getIsSorted();
1846
+ const cx = getStyle(sortDirection);
1847
+ return sortDirection === "desc" ? /* @__PURE__ */ jsx25(Icon, { icon: "ChevronUp", size: "xs", className: cx }) : /* @__PURE__ */ jsx25(Icon, { icon: "ChevronDown", size: "xs", className: cx });
1602
1848
  };
1603
- var PlacementContext = createContext("bottom-right");
1604
- var exitAnimationByPlacement = {
1605
- "top-center": "-translate-y-full opacity-0",
1606
- "top-right": "translate-x-full opacity-0",
1607
- "bottom-center": "translate-y-full opacity-0",
1608
- "bottom-right": "translate-x-full opacity-0"
1609
- };
1610
- var enterAnimationByPlacement = {
1611
- "top-center": "translate-y-0 opacity-100 animate-in slide-in-from-top",
1612
- "top-right": "translate-x-0 opacity-100 animate-in slide-in-from-right",
1613
- "bottom-center": "translate-y-0 opacity-100 animate-in slide-in-from-bottom",
1614
- "bottom-right": "translate-x-0 opacity-100 animate-in slide-in-from-right"
1615
- };
1616
- function ToastItem({
1617
- toast,
1618
- onRemove
1849
+
1850
+ // src/components/Menu/Menu.tsx
1851
+ import {
1852
+ MenuTrigger,
1853
+ Menu as AriaMenu,
1854
+ MenuItem as AriaMenuItem,
1855
+ Popover as Popover2
1856
+ } from "react-aria-components";
1857
+ import { twMerge as twMerge14 } from "tailwind-merge";
1858
+
1859
+ // src/components/Menu/menuStyles.ts
1860
+ var popoverStyles = `
1861
+ bg-background rounded-md shadow-lg
1862
+ border border-border
1863
+ py-1 min-w-48
1864
+ entering:animate-in entering:fade-in entering:zoom-in-95
1865
+ exiting:animate-out exiting:fade-out exiting:zoom-out-95
1866
+ `;
1867
+
1868
+ // src/components/Menu/Menu.tsx
1869
+ import { jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
1870
+ function Menu2({
1871
+ items,
1872
+ content,
1873
+ children,
1874
+ onAction,
1875
+ selectionMode,
1876
+ selectedKeys,
1877
+ defaultSelectedKeys,
1878
+ onSelectionChange,
1879
+ className
1619
1880
  }) {
1620
- const [isExiting, setIsExiting] = useState6(false);
1621
- const timerRef = useRef4(null);
1622
- const placement = useContext(PlacementContext);
1623
- const config = variantConfig[toast.variant];
1624
- const IconComponent = config.icon;
1625
- const dismiss = useCallback2(() => {
1626
- setIsExiting(true);
1627
- setTimeout(() => onRemove(toast.id), 200);
1628
- }, [onRemove, toast.id]);
1881
+ const selectionProps = selectionMode && selectionMode !== "none" ? { selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange } : {};
1882
+ return /* @__PURE__ */ jsxs14(MenuTrigger, { children: [
1883
+ children,
1884
+ /* @__PURE__ */ jsx26(Popover2, { className: twMerge14(popoverStyles, className), children: items ? /* @__PURE__ */ jsx26(
1885
+ AriaMenu,
1886
+ {
1887
+ items,
1888
+ onAction: (key) => {
1889
+ const item = items.find((i) => i.id === key);
1890
+ item?.onAction?.();
1891
+ onAction?.(key);
1892
+ },
1893
+ ...selectionProps,
1894
+ className: "outline-none",
1895
+ children: (item) => /* @__PURE__ */ jsxs14(
1896
+ AriaMenuItem,
1897
+ {
1898
+ id: item.id,
1899
+ href: item.href,
1900
+ target: item.target,
1901
+ isDisabled: item.isDisabled,
1902
+ className: [
1903
+ "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
1904
+ "transition-colors",
1905
+ "focus:bg-muted",
1906
+ "hover:bg-muted",
1907
+ "disabled:opacity-50 disabled:pointer-events-none",
1908
+ item.isDanger ? "text-destructive" : "text-foreground"
1909
+ ].filter(Boolean).join(" "),
1910
+ children: [
1911
+ item.icon && /* @__PURE__ */ jsx26(Icon, { icon: item.icon, size: "sm" }),
1912
+ /* @__PURE__ */ jsx26("span", { className: "flex-1", children: item.label }),
1913
+ item.endContent && /* @__PURE__ */ jsx26("span", { className: "ml-auto flex items-center", children: item.endContent })
1914
+ ]
1915
+ }
1916
+ )
1917
+ }
1918
+ ) : /* @__PURE__ */ jsx26(
1919
+ AriaMenu,
1920
+ {
1921
+ onAction: (key) => onAction?.(key),
1922
+ ...selectionProps,
1923
+ className: "outline-none",
1924
+ children: content
1925
+ }
1926
+ ) })
1927
+ ] });
1928
+ }
1929
+
1930
+ // src/components/Menu/useContextMenu.tsx
1931
+ import {
1932
+ useCallback as useCallback4,
1933
+ useEffect as useEffect2,
1934
+ useId as useId2,
1935
+ useRef as useRef4,
1936
+ useState as useState6
1937
+ } from "react";
1938
+ import {
1939
+ Menu as AriaMenu2,
1940
+ MenuTrigger as MenuTrigger2,
1941
+ Popover as Popover3
1942
+ } from "react-aria-components";
1943
+ import { twMerge as twMerge15 } from "tailwind-merge";
1944
+ import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
1945
+ function useContextMenu({
1946
+ content,
1947
+ label,
1948
+ onAction,
1949
+ className
1950
+ }) {
1951
+ const popoverId = useId2();
1952
+ const [anchor, setAnchor] = useState6(null);
1953
+ const anchorRef = useRef4(null);
1954
+ const popoverRef = useRef4(null);
1955
+ const isOpen = anchor !== null;
1956
+ const close = useCallback4(() => setAnchor(null), []);
1957
+ const onContextMenu = useCallback4((event) => {
1958
+ event.preventDefault();
1959
+ setAnchor({ x: event.clientX, y: event.clientY });
1960
+ }, []);
1961
+ const onPress = useCallback4((event) => {
1962
+ const rect = event.target.getBoundingClientRect();
1963
+ setAnchor({ x: rect.left, y: rect.bottom });
1964
+ }, []);
1629
1965
  useEffect2(() => {
1630
- const duration = toast.duration ?? defaultDuration[toast.variant];
1631
- timerRef.current = setTimeout(dismiss, duration);
1966
+ if (!isOpen) return;
1967
+ const isInside = (target) => popoverRef.current?.contains(target) ?? false;
1968
+ const onPointerDown = (event) => {
1969
+ if (!isInside(event.target)) close();
1970
+ };
1971
+ const onOutsideContextMenu = (event) => {
1972
+ if (isInside(event.target)) return;
1973
+ event.preventDefault();
1974
+ close();
1975
+ };
1976
+ const onKeyDown = (event) => {
1977
+ if (event.key === "Escape") close();
1978
+ };
1979
+ document.addEventListener("pointerdown", onPointerDown, true);
1980
+ document.addEventListener("contextmenu", onOutsideContextMenu, true);
1981
+ document.addEventListener("keydown", onKeyDown, true);
1632
1982
  return () => {
1633
- if (timerRef.current) clearTimeout(timerRef.current);
1983
+ document.removeEventListener("pointerdown", onPointerDown, true);
1984
+ document.removeEventListener("contextmenu", onOutsideContextMenu, true);
1985
+ document.removeEventListener("keydown", onKeyDown, true);
1634
1986
  };
1635
- }, [toast.duration, toast.variant, dismiss]);
1636
- return /* @__PURE__ */ jsxs11(
1637
- "div",
1987
+ }, [isOpen, close]);
1988
+ const menu = /* @__PURE__ */ jsxs15(
1989
+ MenuTrigger2,
1638
1990
  {
1639
- role: "status",
1640
- "aria-live": "polite",
1641
- className: [
1642
- "flex items-start gap-3 rounded-lg border px-4 py-3 shadow-md",
1643
- "min-w-[320px] max-w-[420px]",
1644
- "transition-all duration-200",
1645
- isExiting ? exitAnimationByPlacement[placement] : enterAnimationByPlacement[placement],
1646
- config.containerClass
1647
- ].join(" "),
1991
+ isOpen,
1992
+ onOpenChange: (open) => {
1993
+ if (!open) close();
1994
+ },
1648
1995
  children: [
1649
- /* @__PURE__ */ jsx20(IconComponent, { size: 20, className: ["shrink-0 mt-0.5", config.iconClass].join(" "), "aria-hidden": "true" }),
1650
- /* @__PURE__ */ jsx20("p", { className: "flex-1 text-sm font-medium", children: toast.message }),
1651
- /* @__PURE__ */ jsx20(
1652
- "button",
1996
+ /* @__PURE__ */ jsx27(
1997
+ "span",
1653
1998
  {
1654
- type: "button",
1655
- onClick: dismiss,
1656
- className: "shrink-0 rounded-sm p-0.5 opacity-70 hover:opacity-100 transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-current",
1657
- "aria-label": "Dismiss",
1658
- children: /* @__PURE__ */ jsx20(X3, { size: 16, "aria-hidden": "true" })
1999
+ ref: anchorRef,
2000
+ "aria-hidden": true,
2001
+ tabIndex: -1,
2002
+ className: "pointer-events-none fixed h-0 w-0",
2003
+ style: { left: anchor?.x ?? 0, top: anchor?.y ?? 0 }
2004
+ }
2005
+ ),
2006
+ /* @__PURE__ */ jsx27(
2007
+ Popover3,
2008
+ {
2009
+ isNonModal: true,
2010
+ triggerRef: anchorRef,
2011
+ placement: "bottom start",
2012
+ ref: popoverRef,
2013
+ className: twMerge15(popoverStyles, className),
2014
+ children: /* @__PURE__ */ jsx27(
2015
+ AriaMenu2,
2016
+ {
2017
+ id: popoverId,
2018
+ "aria-label": label,
2019
+ autoFocus: "first",
2020
+ onAction: (key) => {
2021
+ onAction?.(String(key));
2022
+ close();
2023
+ },
2024
+ className: "outline-none",
2025
+ children: content
2026
+ }
2027
+ )
1659
2028
  }
1660
2029
  )
1661
2030
  ]
1662
2031
  }
1663
2032
  );
1664
- }
1665
- var containerPositionStyles = {
1666
- "top-center": "fixed top-4 left-1/2 -translate-x-1/2 z-50 flex flex-col-reverse gap-2 items-center",
1667
- "top-right": "fixed top-4 right-4 z-50 flex flex-col-reverse gap-2",
1668
- "bottom-center": "fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex flex-col gap-2 items-center",
1669
- "bottom-right": "fixed bottom-4 right-4 z-50 flex flex-col gap-2"
1670
- };
1671
- function ToastContainer({
1672
- toasts,
1673
- removeToast,
1674
- placement = "bottom-right"
1675
- }) {
1676
- if (toasts.length === 0) return null;
1677
- return createPortal2(
1678
- /* @__PURE__ */ jsx20(PlacementContext.Provider, { value: placement, children: /* @__PURE__ */ jsx20("div", { className: containerPositionStyles[placement], children: toasts.map((toast) => /* @__PURE__ */ jsx20(ToastItem, { toast, onRemove: removeToast }, toast.id)) }) }),
1679
- document.body
1680
- );
1681
- }
1682
- function createToastBridge() {
1683
- const listeners = /* @__PURE__ */ new Set();
1684
2033
  return {
1685
- emit: (toast) => {
1686
- listeners.forEach((fn) => fn(toast));
2034
+ targetProps: { onContextMenu },
2035
+ triggerProps: {
2036
+ onPress,
2037
+ onClick: (e) => {
2038
+ e.preventDefault();
2039
+ },
2040
+ "aria-haspopup": "menu",
2041
+ "aria-expanded": isOpen,
2042
+ "aria-controls": isOpen ? popoverId : void 0
1687
2043
  },
1688
- subscribe: (fn) => {
1689
- listeners.add(fn);
1690
- return () => {
1691
- listeners.delete(fn);
1692
- };
1693
- }
1694
- };
1695
- }
1696
- function ToastProvider({ children, bridge, placement = "bottom-right" }) {
1697
- const [toasts, setToasts] = useState6([]);
1698
- const addToast = useCallback2((toast) => {
1699
- const id = `toast-${++toastCounter}`;
1700
- setToasts((prev) => [...prev, { ...toast, id }]);
1701
- }, []);
1702
- const removeToast = useCallback2((id) => {
1703
- setToasts((prev) => prev.filter((t) => t.id !== id));
1704
- }, []);
1705
- useEffect2(() => {
1706
- if (!bridge) return;
1707
- return bridge.subscribe(addToast);
1708
- }, [bridge, addToast]);
1709
- return /* @__PURE__ */ jsxs11(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
1710
- children,
1711
- /* @__PURE__ */ jsx20(ToastContainer, { toasts, removeToast, placement })
1712
- ] });
1713
- }
1714
- function useToast() {
1715
- const context = useContext(ToastContext);
1716
- if (!context) {
1717
- throw new Error("useToast must be used within a ToastProvider");
1718
- }
1719
- return {
1720
- toast: context.addToast,
1721
- toasts: context.toasts,
1722
- removeToast: context.removeToast
2044
+ menu,
2045
+ isOpen,
2046
+ close
1723
2047
  };
1724
2048
  }
1725
2049
 
1726
- // src/components/EmptyState/EmptyState.tsx
1727
- import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
1728
- function EmptyState({
2050
+ // src/components/Menu/MenuItem.tsx
2051
+ import { MenuItem as AriaMenuItem2 } from "react-aria-components";
2052
+ import { jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
2053
+ function MenuItem({
2054
+ id,
2055
+ children,
1729
2056
  icon,
1730
- title,
1731
- description,
1732
- action,
2057
+ endContent,
2058
+ onAction,
2059
+ href,
2060
+ target,
2061
+ isDisabled,
2062
+ isDanger,
2063
+ textValue,
1733
2064
  className
1734
2065
  }) {
1735
- return /* @__PURE__ */ jsxs12(
1736
- "div",
2066
+ return /* @__PURE__ */ jsxs16(
2067
+ AriaMenuItem2,
1737
2068
  {
2069
+ id,
2070
+ href,
2071
+ target,
2072
+ isDisabled,
2073
+ onAction,
2074
+ textValue,
1738
2075
  className: [
1739
- "flex flex-col items-center text-center py-12 px-6",
2076
+ "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2077
+ "transition-colors",
2078
+ "focus:bg-muted",
2079
+ "hover:bg-muted",
2080
+ "disabled:opacity-50 disabled:pointer-events-none",
2081
+ isDanger ? "text-destructive" : "text-foreground",
1740
2082
  className
1741
2083
  ].filter(Boolean).join(" "),
1742
2084
  children: [
1743
- icon && /* @__PURE__ */ jsx21(Icon, { icon, size: "xl", className: "text-muted-foreground" }),
1744
- /* @__PURE__ */ jsx21("h3", { className: "text-lg font-semibold text-foreground mt-4", children: title }),
1745
- description && /* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground mt-2 max-w-sm", children: description }),
1746
- action && /* @__PURE__ */ jsx21("div", { className: "mt-6", children: action })
2085
+ icon && /* @__PURE__ */ jsx28(Icon, { icon, size: "sm" }),
2086
+ /* @__PURE__ */ jsx28("span", { className: "flex-1", children }),
2087
+ endContent && /* @__PURE__ */ jsx28("span", { className: "ml-auto flex items-center", children: endContent })
1747
2088
  ]
1748
2089
  }
1749
2090
  );
1750
2091
  }
1751
2092
 
1752
- // src/components/Form/Checkbox/Checkbox.tsx
1753
- import {
1754
- Checkbox as AriaCheckbox
1755
- } from "react-aria-components";
1756
- import { Check as Check3 } from "lucide-react";
1757
- import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
1758
- function stopToggleForInteractive(e) {
1759
- if (e.target instanceof Element && e.target.closest("a, button, input, select, textarea")) {
1760
- e.stopPropagation();
1761
- }
1762
- }
1763
- function Checkbox({ children, className, ...props }) {
1764
- return /* @__PURE__ */ jsx22(
1765
- AriaCheckbox,
2093
+ // src/components/Menu/MenuCheckboxItem.tsx
2094
+ import { MenuItem as AriaMenuItem3 } from "react-aria-components";
2095
+ import { Check as Check4 } from "lucide-react";
2096
+ import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
2097
+ function MenuCheckboxItem({
2098
+ id,
2099
+ children,
2100
+ textValue,
2101
+ isDisabled,
2102
+ className
2103
+ }) {
2104
+ return /* @__PURE__ */ jsx29(
2105
+ AriaMenuItem3,
1766
2106
  {
1767
- ...props,
1768
- className: [
1769
- "group flex items-center gap-2 text-sm text-foreground cursor-pointer",
1770
- "disabled:opacity-50 disabled:cursor-default",
2107
+ id,
2108
+ textValue,
2109
+ isDisabled,
2110
+ className: ({ isSelected }) => [
2111
+ "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2112
+ "transition-colors",
2113
+ "focus:bg-muted",
2114
+ "hover:bg-muted",
2115
+ "disabled:opacity-50 disabled:pointer-events-none",
2116
+ "text-foreground",
2117
+ isSelected ? "font-medium" : "",
1771
2118
  className
1772
2119
  ].filter(Boolean).join(" "),
1773
- children: ({ isSelected, isIndeterminate }) => /* @__PURE__ */ jsxs13(Fragment3, { children: [
1774
- /* @__PURE__ */ jsxs13(
1775
- "div",
1776
- {
1777
- className: [
1778
- "flex items-center justify-center w-6 h-6 shrink-0",
1779
- "rounded-sm border transition-colors",
1780
- "group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2",
1781
- isSelected || isIndeterminate ? "bg-primary border-primary" : "bg-background border-border group-hover:border-border"
1782
- ].join(" "),
1783
- children: [
1784
- isSelected && /* @__PURE__ */ jsx22(Check3, { className: "w-4 h-4 text-primary-foreground", strokeWidth: 3 }),
1785
- isIndeterminate && /* @__PURE__ */ jsx22("div", { className: "w-3 h-0.5 bg-primary-foreground rounded-full" })
1786
- ]
1787
- }
1788
- ),
1789
- children && /* @__PURE__ */ jsx22(
1790
- "span",
1791
- {
1792
- onPointerDown: stopToggleForInteractive,
1793
- onPointerUp: stopToggleForInteractive,
1794
- onMouseDown: stopToggleForInteractive,
1795
- onClick: stopToggleForInteractive,
1796
- children
1797
- }
1798
- )
2120
+ children: ({ isSelected }) => /* @__PURE__ */ jsxs17(Fragment3, { children: [
2121
+ /* @__PURE__ */ jsx29("span", { className: "flex items-center justify-center w-4 h-4 shrink-0", children: isSelected && /* @__PURE__ */ jsx29(Check4, { size: 14, className: "text-primary", "aria-hidden": "true" }) }),
2122
+ /* @__PURE__ */ jsx29("span", { className: "flex-1", children })
1799
2123
  ] })
1800
2124
  }
1801
2125
  );
1802
2126
  }
1803
2127
 
1804
- // src/components/Form/Switch/Switch.tsx
2128
+ // src/components/Menu/MenuSection.tsx
1805
2129
  import {
1806
- SwitchField,
1807
- SwitchButton
2130
+ MenuSection as AriaMenuSection,
2131
+ Header
1808
2132
  } from "react-aria-components";
1809
- import { twMerge as twMerge12 } from "tailwind-merge";
1810
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
1811
- function Switch({
2133
+ import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
2134
+ function MenuSection({
2135
+ header,
1812
2136
  children,
1813
- color = "var(--color-primary)",
1814
- className,
1815
- ...props
2137
+ "aria-label": ariaLabel,
2138
+ className
1816
2139
  }) {
1817
- return /* @__PURE__ */ jsx23(SwitchField, { ...props, children: /* @__PURE__ */ jsx23(SwitchButton, { className: "relative cursor-pointer", children: ({ isSelected, isFocusVisible }) => /* @__PURE__ */ jsxs14(Fragment4, { children: [
1818
- /* @__PURE__ */ jsx23(
1819
- "div",
2140
+ return /* @__PURE__ */ jsxs18(AriaMenuSection, { className, "aria-label": ariaLabel, children: [
2141
+ header && /* @__PURE__ */ jsx30(
2142
+ Header,
1820
2143
  {
1821
- className: twMerge12(
1822
- `
1823
- flex items-center
1824
- border-2 border-border
1825
- w-9 h-5 rounded-full transition-colors shrink-0
1826
- `,
1827
- isFocusVisible && "ring-2 ring-ring ring-offset-2",
1828
- !isSelected && "bg-border"
1829
- ),
1830
- style: isSelected ? { backgroundColor: color } : void 0,
1831
- children: /* @__PURE__ */ jsx23(
1832
- "div",
1833
- {
1834
- className: twMerge12(
1835
- `
1836
- absolute top-0 left-0 w-5 h-5
1837
- rounded-full
1838
- transition-transform
1839
- border-2 border-border
1840
-
1841
- `,
1842
- isSelected ? "translate-x-4 bg-card" : "translate-x-0 bg-background"
1843
- )
1844
- }
1845
- )
2144
+ className: [
2145
+ "px-3 py-1.5",
2146
+ "text-xs font-semibold",
2147
+ "text-muted-foreground",
2148
+ "uppercase tracking-wider",
2149
+ "select-none"
2150
+ ].join(" "),
2151
+ children: header
1846
2152
  }
1847
2153
  ),
1848
- children && /* @__PURE__ */ jsx23("span", { children })
1849
- ] }) }) });
2154
+ children
2155
+ ] });
1850
2156
  }
1851
2157
 
1852
- // src/components/Form/Radio/Radio.tsx
1853
- import {
1854
- RadioGroup as AriaRadioGroup,
1855
- Radio as AriaRadio
1856
- } from "react-aria-components";
1857
- import { twMerge as twMerge13 } from "tailwind-merge";
1858
- import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
1859
- function RadioGroup({
1860
- children,
1861
- className,
1862
- orientation = "vertical",
1863
- ...props
1864
- }) {
1865
- return /* @__PURE__ */ jsx24(
1866
- AriaRadioGroup,
2158
+ // src/components/Menu/MenuHeader.tsx
2159
+ import { Header as Header2 } from "react-aria-components";
2160
+ import { jsx as jsx31 } from "react/jsx-runtime";
2161
+ function MenuHeader({ children, className }) {
2162
+ return /* @__PURE__ */ jsx31(Header2, { className, children });
2163
+ }
2164
+
2165
+ // src/components/Menu/MenuSeparator.tsx
2166
+ import { Separator } from "react-aria-components";
2167
+ import { jsx as jsx32 } from "react/jsx-runtime";
2168
+ function MenuSeparator({ className }) {
2169
+ return /* @__PURE__ */ jsx32(
2170
+ Separator,
1867
2171
  {
1868
- ...props,
1869
- orientation,
1870
- className: twMerge13(
1871
- "flex gap-2 disabled:opacity-50",
1872
- orientation === "horizontal" ? "flex-row" : "flex-col",
2172
+ className: [
2173
+ "border-t border-border my-1",
1873
2174
  className
1874
- ),
1875
- children
2175
+ ].filter(Boolean).join(" ")
1876
2176
  }
1877
2177
  );
1878
2178
  }
1879
- function Radio({ children, className, ...props }) {
1880
- return /* @__PURE__ */ jsx24(
1881
- AriaRadio,
2179
+
2180
+ // src/components/Table/TableMenu.tsx
2181
+ import { Fragment as Fragment4, jsx as jsx33, jsxs as jsxs19 } from "react/jsx-runtime";
2182
+ function TableMenu({
2183
+ toggleableColumns,
2184
+ columnVisibility,
2185
+ toggleColumn,
2186
+ tableId
2187
+ }) {
2188
+ const store = useTableStore(tableId);
2189
+ const selectedKeys = new Set(
2190
+ toggleableColumns.filter((col) => columnVisibility[col.id] !== false).map((col) => col.id)
2191
+ );
2192
+ function handleSelectionChange(keys) {
2193
+ const newKeys = keys === "all" ? new Set(toggleableColumns.map((c) => c.id)) : keys;
2194
+ for (const col of toggleableColumns) {
2195
+ const wasSelected = columnVisibility[col.id] !== false;
2196
+ const isNowSelected = newKeys.has(col.id);
2197
+ if (wasSelected !== isNowSelected) {
2198
+ toggleColumn(col.id);
2199
+ }
2200
+ }
2201
+ }
2202
+ return /* @__PURE__ */ jsx33(
2203
+ Menu2,
1882
2204
  {
1883
- ...props,
1884
- className: [
1885
- "group flex items-center gap-2 text-sm text-foreground cursor-pointer",
1886
- "disabled:opacity-50 disabled:cursor-default",
1887
- className
1888
- ].filter(Boolean).join(" "),
1889
- children: ({ isSelected }) => /* @__PURE__ */ jsxs15(Fragment5, { children: [
1890
- /* @__PURE__ */ jsx24(
1891
- "div",
1892
- {
1893
- className: [
1894
- "flex items-center justify-center w-5 h-5 shrink-0",
1895
- "rounded-full border-2 transition-colors",
1896
- "group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2",
1897
- isSelected ? "border-primary" : "border-border group-hover:border-border"
1898
- ].join(" "),
1899
- children: isSelected && /* @__PURE__ */ jsx24("div", { className: "w-2.5 h-2.5 rounded-full bg-primary" })
1900
- }
1901
- ),
1902
- children && /* @__PURE__ */ jsx24("span", { children })
1903
- ] })
2205
+ selectionMode: "multiple",
2206
+ selectedKeys,
2207
+ onSelectionChange: handleSelectionChange,
2208
+ content: /* @__PURE__ */ jsxs19(Fragment4, { children: [
2209
+ toggleableColumns.map((col) => /* @__PURE__ */ jsx33(MenuCheckboxItem, { id: col.id, children: col.header }, col.id)),
2210
+ /* @__PURE__ */ jsx33(MenuSeparator, {}),
2211
+ /* @__PURE__ */ jsx33(MenuItem, { id: "reset-all", onAction: () => store.getState().reset(), children: "Reset all" })
2212
+ ] }),
2213
+ children: /* @__PURE__ */ jsx33(IconButton, { icon: "Columns3", variant: "ghost", size: "sm", label: "Column settings" })
1904
2214
  }
1905
2215
  );
1906
2216
  }
1907
- function RadioButton({ children, className, ...props }) {
1908
- return /* @__PURE__ */ jsx24(
1909
- AriaRadio,
1910
- {
1911
- ...props,
1912
- className: [
1913
- "group cursor-pointer",
1914
- "disabled:opacity-50 disabled:cursor-default",
1915
- className
1916
- ].filter(Boolean).join(" "),
1917
- children: ({ isSelected }) => /* @__PURE__ */ jsx24(
1918
- "div",
1919
- {
1920
- className: [
1921
- "px-4 py-2 text-sm font-medium",
1922
- "rounded-md border transition-colors text-center",
1923
- "group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2",
1924
- isSelected ? "bg-primary border-primary text-primary-foreground" : "bg-background border-border text-foreground hover:border-border"
1925
- ].join(" "),
1926
- children
2217
+
2218
+ // src/components/Table/TableHeaderRow.tsx
2219
+ import { jsx as jsx34, jsxs as jsxs20 } from "react/jsx-runtime";
2220
+ function TableHeaderRow({
2221
+ headerGroup,
2222
+ columns,
2223
+ tableId,
2224
+ toggleableColumns,
2225
+ columnVisibility,
2226
+ toggleColumn,
2227
+ enableRowSelection,
2228
+ hasFilters,
2229
+ onClearAllFilters,
2230
+ showFilters
2231
+ }) {
2232
+ return /* @__PURE__ */ jsx34("tr", { className: "w-full block", children: headerGroup.headers.map((header) => {
2233
+ const columnConfig = columns.find((col) => col.id === header.id);
2234
+ const isIndexColumn = header.id === "index";
2235
+ const isSorted = header.column.getIsSorted();
2236
+ const baseClass = "relative pl-4 pr-4 group/header text-sm align-top";
2237
+ const indexClass = "text-right tabular-nums text-center p-1 px-2";
2238
+ const alignClasses2 = {
2239
+ left: "text-left",
2240
+ right: "text-right",
2241
+ center: "text-center"
2242
+ };
2243
+ const alignClass = alignClasses2[columnConfig?.align ?? "left"];
2244
+ const cxTh = twMerge16(baseClass, isIndexColumn ? indexClass : alignClass);
2245
+ const style = {
2246
+ width: header.getSize(),
2247
+ minWidth: header.getSize(),
2248
+ maxWidth: header.getSize()
2249
+ };
2250
+ const isRight = columnConfig?.align === "right";
2251
+ const tableHeadCx = `
2252
+ flex items-center justify-between gap-1 h-8 text-left
2253
+ text-sm font-medium text-foreground
2254
+ `;
2255
+ const tableHeadToggleCx = `
2256
+ cursor-pointer
2257
+ hover:text-muted-foreground
2258
+ focus-visible:outline-none
2259
+ focus-visible:ring-2
2260
+ focus-visible:ring-ring
2261
+ focus-visible:ring-offset-1
2262
+ rounded-sm
2263
+ `;
2264
+ return /* @__PURE__ */ jsxs20(
2265
+ "th",
2266
+ {
2267
+ className: cxTh,
2268
+ style,
2269
+ "aria-sort": isSorted === "asc" ? "ascending" : isSorted === "desc" ? "descending" : void 0,
2270
+ children: [
2271
+ isIndexColumn ? /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-2", children: [
2272
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-1", children: [
2273
+ enableRowSelection && /* @__PURE__ */ jsx34(
2274
+ Checkbox,
2275
+ {
2276
+ isSelected: header.getContext().table.getIsAllRowsSelected(),
2277
+ isIndeterminate: header.getContext().table.getIsSomeRowsSelected() && !header.getContext().table.getIsAllRowsSelected(),
2278
+ onChange: () => header.getContext().table.toggleAllRowsSelected()
2279
+ }
2280
+ ),
2281
+ /* @__PURE__ */ jsx34(
2282
+ TableMenu,
2283
+ {
2284
+ toggleableColumns,
2285
+ columnVisibility,
2286
+ toggleColumn,
2287
+ tableId
2288
+ }
2289
+ )
2290
+ ] }),
2291
+ hasFilters && /* @__PURE__ */ jsx34(
2292
+ IconButton,
2293
+ {
2294
+ icon: "FilterX",
2295
+ size: "sm",
2296
+ variant: "secondary",
2297
+ onPress: onClearAllFilters,
2298
+ label: "Clear all filters"
2299
+ }
2300
+ )
2301
+ ] }) : /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-2 pb-2", children: [
2302
+ header.column.getCanSort() ? (
2303
+ // Sortable Header
2304
+ /* @__PURE__ */ jsxs20(
2305
+ "button",
2306
+ {
2307
+ type: "button",
2308
+ className: twMerge16(
2309
+ tableHeadCx,
2310
+ tableHeadToggleCx,
2311
+ isRight && "flex-row-reverse",
2312
+ isSorted && "text-foreground"
2313
+ ),
2314
+ onClick: header.column.getToggleSortingHandler() ?? void 0,
2315
+ children: [
2316
+ /* @__PURE__ */ jsx34("div", { className: "min-w-0", children: /* @__PURE__ */ jsx34(TruncatedText, { children: flexRender2(header.column.columnDef.header, header.getContext()) }) }),
2317
+ /* @__PURE__ */ jsx34(ColumnSortButton, { header })
2318
+ ]
2319
+ }
2320
+ )
2321
+ ) : (
2322
+ // Non-Sortable Header
2323
+ /* @__PURE__ */ jsx34("div", { className: tableHeadCx, children: /* @__PURE__ */ jsx34("div", { className: "min-w-0", children: /* @__PURE__ */ jsx34(TruncatedText, { children: flexRender2(header.column.columnDef.header, header.getContext()) }) }) })
2324
+ ),
2325
+ showFilters && header.column.getCanFilter() && columnConfig?.enableColumnFilter && /* @__PURE__ */ jsx34(
2326
+ ColumnFilterInput,
2327
+ {
2328
+ column: header.column,
2329
+ filterType: columnConfig.filterType ?? "text",
2330
+ filterPlaceholder: columnConfig.filterPlaceholder,
2331
+ filterOptions: columnConfig.filterOptions,
2332
+ filterRender: columnConfig.filterRender
2333
+ }
2334
+ )
2335
+ ] }),
2336
+ !isIndexColumn && header.column.getCanResize() && /* @__PURE__ */ jsx34(ColumnResizeHandle, { header })
2337
+ ]
2338
+ },
2339
+ header.id
2340
+ );
2341
+ }) }, headerGroup.id);
2342
+ }
2343
+
2344
+ // src/components/Table/useColumnVisibility.ts
2345
+ import { useCallback as useCallback5, useMemo as useMemo2 } from "react";
2346
+ import { useStore as useStore2 } from "zustand";
2347
+ function useColumnVisibility(columns, tableId) {
2348
+ const store = useTableStore(tableId);
2349
+ const storedVisibility = useStore2(store, (s) => s.columnVisibility);
2350
+ const setVisibilityStore = useStore2(store, (s) => s.setColumnVisibility);
2351
+ const columnVisibility = useMemo2(() => {
2352
+ const vis = {};
2353
+ columns.forEach((col) => {
2354
+ if (col.anchor) {
2355
+ vis[col.id] = true;
2356
+ } else {
2357
+ vis[col.id] = storedVisibility[col.id] ?? col.defaultVisible !== false;
2358
+ }
2359
+ });
2360
+ return vis;
2361
+ }, [columns, storedVisibility]);
2362
+ const setColumnVisibility = useCallback5(
2363
+ (updaterOrValue) => {
2364
+ const current = store.getState().columnVisibility;
2365
+ const currentFull = {};
2366
+ columns.forEach((col) => {
2367
+ currentFull[col.id] = current[col.id] ?? col.defaultVisible !== false;
2368
+ });
2369
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(currentFull) : updaterOrValue;
2370
+ columns.forEach((col) => {
2371
+ if (col.anchor) next[col.id] = true;
2372
+ });
2373
+ setVisibilityStore(next);
2374
+ },
2375
+ [store, columns, setVisibilityStore]
2376
+ );
2377
+ const toggleableColumns = useMemo2(() => columns.filter((col) => !col.anchor), [columns]);
2378
+ const toggleColumn = useCallback5(
2379
+ (columnId) => {
2380
+ setColumnVisibility((prev) => ({
2381
+ ...prev,
2382
+ [columnId]: !prev[columnId]
2383
+ }));
2384
+ },
2385
+ [setColumnVisibility]
2386
+ );
2387
+ return {
2388
+ columnVisibility,
2389
+ setColumnVisibility,
2390
+ toggleableColumns,
2391
+ toggleColumn
2392
+ };
2393
+ }
2394
+
2395
+ // src/components/Table/useColumnWidths.ts
2396
+ import { useCallback as useCallback6, useMemo as useMemo3 } from "react";
2397
+ import { useStore as useStore3 } from "zustand";
2398
+ function useColumnWidths(columns, tableId) {
2399
+ const store = useTableStore(tableId);
2400
+ const columnWidths = useStore3(store, (state) => state.columnWidths);
2401
+ const setColumnWidth = useStore3(store, (state) => state.setColumnWidth);
2402
+ const reset = useStore3(store, (state) => state.reset);
2403
+ const columnSizing = useMemo3(() => {
2404
+ const sizing = { index: 48 };
2405
+ columns.forEach((col) => {
2406
+ sizing[col.id] = columnWidths[col.id] ?? col.size;
2407
+ });
2408
+ return sizing;
2409
+ }, [columns, columnWidths]);
2410
+ const setColumnSizing = useCallback6(
2411
+ (updaterOrValue) => {
2412
+ const currentWidths = store.getState().columnWidths;
2413
+ const currentSizing = { index: 48 };
2414
+ columns.forEach((col) => {
2415
+ currentSizing[col.id] = currentWidths[col.id] ?? col.size;
2416
+ });
2417
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(currentSizing) : updaterOrValue;
2418
+ Object.entries(next).forEach(([columnId, width]) => {
2419
+ if (columnId !== "index" && currentSizing[columnId] !== width) {
2420
+ setColumnWidth(columnId, width);
1927
2421
  }
1928
- )
1929
- }
2422
+ });
2423
+ },
2424
+ [store, columns, setColumnWidth]
1930
2425
  );
2426
+ const resetWidths = useCallback6(() => {
2427
+ reset();
2428
+ }, [reset]);
2429
+ return { columnSizing, setColumnSizing, resetWidths };
1931
2430
  }
1932
2431
 
1933
- // src/components/Form/Fieldset/Fieldset.tsx
1934
- import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
1935
- function Fieldset({ legend, children, className }) {
1936
- return /* @__PURE__ */ jsxs16(
1937
- "fieldset",
1938
- {
1939
- className: [
1940
- "flex flex-col gap-8",
1941
- "border-none p-0 m-0",
1942
- className
1943
- ].filter(Boolean).join(" "),
1944
- children: [
1945
- legend && /* @__PURE__ */ jsx25(
1946
- "legend",
1947
- {
1948
- className: [
1949
- "text-lg",
1950
- "font-semibold",
1951
- "text-foreground",
1952
- "p-0"
1953
- ].join(" "),
1954
- children: legend
1955
- }
1956
- ),
1957
- children
1958
- ]
1959
- }
2432
+ // src/components/Table/useTableSorting.ts
2433
+ import { useCallback as useCallback7 } from "react";
2434
+ import { useStore as useStore4 } from "zustand";
2435
+ function useTableSorting(tableId, defaultSorting = []) {
2436
+ const store = useTableStore(tableId);
2437
+ const storedSorting = useStore4(store, (state) => state.sorting);
2438
+ const setSortingStore = useStore4(store, (state) => state.setSorting);
2439
+ const sorting = storedSorting.length > 0 ? storedSorting : defaultSorting;
2440
+ const setSorting = useCallback7(
2441
+ (updaterOrValue) => {
2442
+ const currentSorting = store.getState().sorting;
2443
+ const current = currentSorting.length > 0 ? currentSorting : defaultSorting;
2444
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(current) : updaterOrValue;
2445
+ setSortingStore(next);
2446
+ },
2447
+ [store, setSortingStore, defaultSorting]
1960
2448
  );
2449
+ return { sorting, setSorting };
1961
2450
  }
1962
2451
 
1963
- // src/components/Link/Link.tsx
1964
- import {
1965
- Link as AriaLink3
1966
- } from "react-aria-components";
1967
- import { jsx as jsx26 } from "react/jsx-runtime";
1968
- var variantStyles2 = {
1969
- default: [
1970
- "text-teal-700 underline",
1971
- "hover:text-teal-800"
1972
- ].join(" "),
1973
- subtle: [
1974
- "text-muted-foreground no-underline",
1975
- "hover:underline hover:text-foreground"
1976
- ].join(" ")
1977
- };
1978
- function Link({
1979
- variant = "default",
1980
- className,
1981
- ...props
2452
+ // src/components/Table/Table.tsx
2453
+ import { Fragment as Fragment5, jsx as jsx35, jsxs as jsxs21 } from "react/jsx-runtime";
2454
+ function booleanSortingFn(rowA, rowB, columnId) {
2455
+ const a = rowA.getValue(columnId) ? 1 : 0;
2456
+ const b = rowB.getValue(columnId) ? 1 : 0;
2457
+ return a - b;
2458
+ }
2459
+ function Table2({
2460
+ columns,
2461
+ data,
2462
+ cellRenderers = {},
2463
+ tableId = "default",
2464
+ ariaLabel,
2465
+ enableRowSelection,
2466
+ rowSelection,
2467
+ onRowSelectionChange,
2468
+ getRowId,
2469
+ showFilters = true,
2470
+ defaultSorting
1982
2471
  }) {
1983
- return /* @__PURE__ */ jsx26(
1984
- AriaLink3,
2472
+ const { columnSizing, setColumnSizing } = useColumnWidths(columns, tableId);
2473
+ const anchorColumnId = columns.find((c) => c.anchor)?.id ?? columns[0]?.id;
2474
+ const effectiveDefaultSorting = useMemo4(
2475
+ () => defaultSorting ?? (anchorColumnId ? [{ id: anchorColumnId, desc: false }] : []),
2476
+ [defaultSorting, anchorColumnId]
2477
+ );
2478
+ const { sorting, setSorting } = useTableSorting(tableId, effectiveDefaultSorting);
2479
+ const { columnVisibility, setColumnVisibility, toggleableColumns, toggleColumn } = useColumnVisibility(columns, tableId);
2480
+ const { columnFilters, setColumnFilters, resetFilters } = useColumnFilters({
2481
+ tableId
2482
+ });
2483
+ const indexColumnSize = enableRowSelection ? 80 : 48;
2484
+ const columnDefs = useMemo4(() => {
2485
+ const indexColumn = {
2486
+ id: "index",
2487
+ header: "",
2488
+ cell: (info) => info.row.index + 1,
2489
+ enableResizing: false,
2490
+ enableSorting: false,
2491
+ enableColumnFilter: false,
2492
+ size: indexColumnSize,
2493
+ minSize: indexColumnSize,
2494
+ maxSize: indexColumnSize
2495
+ };
2496
+ const dataColumns = columns.map((colConfig) => {
2497
+ const renderer = cellRenderers[colConfig.id];
2498
+ return {
2499
+ id: colConfig.id,
2500
+ accessorKey: colConfig.id,
2501
+ header: colConfig.header,
2502
+ cell: renderer ? (info) => renderer(info.row.original) : (info) => info.getValue(),
2503
+ enableResizing: colConfig.enableResizing !== false,
2504
+ enableSorting: colConfig.enableSorting ?? false,
2505
+ enableColumnFilter: colConfig.enableColumnFilter ?? false,
2506
+ ...colConfig.filterFn && { filterFn: colConfig.filterFn },
2507
+ sortingFn: colConfig.sortingFn === "boolean" ? booleanSortingFn : colConfig.sortingFn ?? "alphanumeric",
2508
+ size: colConfig.size ?? 150,
2509
+ minSize: colConfig.minSize ?? 48,
2510
+ maxSize: colConfig.maxSize ?? Number.MAX_SAFE_INTEGER
2511
+ };
2512
+ });
2513
+ return [indexColumn, ...dataColumns];
2514
+ }, [columns, cellRenderers, indexColumnSize]);
2515
+ const table = useReactTable({
2516
+ data,
2517
+ columns: columnDefs,
2518
+ getCoreRowModel: getCoreRowModel(),
2519
+ getSortedRowModel: getSortedRowModel(),
2520
+ getFilteredRowModel: getFilteredRowModel(),
2521
+ getFacetedUniqueValues: getFacetedUniqueValues(),
2522
+ enableSortingRemoval: false,
2523
+ enableColumnResizing: true,
2524
+ columnResizeMode: "onChange",
2525
+ enableRowSelection: !!enableRowSelection,
2526
+ state: {
2527
+ columnSizing,
2528
+ sorting,
2529
+ columnVisibility,
2530
+ columnFilters,
2531
+ ...enableRowSelection && { rowSelection }
2532
+ },
2533
+ onColumnSizingChange: setColumnSizing,
2534
+ onSortingChange: setSorting,
2535
+ onColumnVisibilityChange: setColumnVisibility,
2536
+ onColumnFiltersChange: setColumnFilters,
2537
+ ...enableRowSelection && {
2538
+ onRowSelectionChange,
2539
+ getRowId
2540
+ }
2541
+ });
2542
+ const headerRef = useRef5(null);
2543
+ const bodyRef = useRef5(null);
2544
+ const isSyncing = useRef5(false);
2545
+ const handleHeaderScroll = useCallback8(() => {
2546
+ if (isSyncing.current) return;
2547
+ isSyncing.current = true;
2548
+ if (headerRef.current && bodyRef.current) {
2549
+ bodyRef.current.scrollLeft = headerRef.current.scrollLeft;
2550
+ }
2551
+ requestAnimationFrame(() => {
2552
+ isSyncing.current = false;
2553
+ });
2554
+ }, []);
2555
+ const handleBodyScroll = useCallback8(() => {
2556
+ if (isSyncing.current) return;
2557
+ isSyncing.current = true;
2558
+ if (bodyRef.current && headerRef.current) {
2559
+ headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
2560
+ }
2561
+ requestAnimationFrame(() => {
2562
+ isSyncing.current = false;
2563
+ });
2564
+ }, []);
2565
+ const filteredCount = table.getRowModel().rows.length;
2566
+ const totalCount = data.length;
2567
+ const isFiltered = filteredCount !== totalCount;
2568
+ return /* @__PURE__ */ jsxs21(Fragment5, { children: [
2569
+ /* @__PURE__ */ jsx35("div", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: isFiltered ? `Showing ${filteredCount} of ${totalCount} rows` : "" }),
2570
+ /* @__PURE__ */ jsx35(
2571
+ "div",
2572
+ {
2573
+ ref: headerRef,
2574
+ className: "sticky top-0 z-10 bg-white border-b border-border overflow-x-auto",
2575
+ style: { scrollbarWidth: "none" },
2576
+ onScroll: handleHeaderScroll,
2577
+ children: /* @__PURE__ */ jsx35("table", { className: "min-w-full", "aria-label": ariaLabel, children: /* @__PURE__ */ jsx35("thead", { className: "w-full", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx35(
2578
+ TableHeaderRow,
2579
+ {
2580
+ headerGroup,
2581
+ columns,
2582
+ tableId,
2583
+ toggleableColumns,
2584
+ columnVisibility,
2585
+ toggleColumn,
2586
+ enableRowSelection: !!enableRowSelection,
2587
+ hasFilters: columnFilters.length > 0,
2588
+ onClearAllFilters: resetFilters,
2589
+ showFilters
2590
+ },
2591
+ headerGroup.id
2592
+ )) }) })
2593
+ }
2594
+ ),
2595
+ /* @__PURE__ */ jsx35("div", { ref: bodyRef, className: "overflow-x-auto", onScroll: handleBodyScroll, children: /* @__PURE__ */ jsx35("table", { className: "min-w-full", "aria-hidden": "true", children: /* @__PURE__ */ jsx35("tbody", { children: data.length === 0 ? /* @__PURE__ */ jsx35("tr", { children: /* @__PURE__ */ jsx35("td", { colSpan: columns.length + 1, children: /* @__PURE__ */ jsx35(EmptyState, { icon: "Inbox", title: "No results" }) }) }) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx35("tr", { children: /* @__PURE__ */ jsx35("td", { colSpan: columns.length + 1, children: /* @__PURE__ */ jsx35(NoFilterResults, { tableId }) }) }) : table.getRowModel().rows.map((row, index) => /* @__PURE__ */ jsx35(
2596
+ TableBodyRow,
2597
+ {
2598
+ row,
2599
+ rowIndex: index,
2600
+ columns,
2601
+ enableRowSelection: !!enableRowSelection
2602
+ },
2603
+ row.id
2604
+ )) }) }) })
2605
+ ] });
2606
+ }
2607
+
2608
+ // src/components/Table/SelectionFooter.tsx
2609
+ import { jsx as jsx36, jsxs as jsxs22 } from "react/jsx-runtime";
2610
+ function SelectionFooter({
2611
+ selectedCount,
2612
+ totalCount,
2613
+ onReset,
2614
+ children
2615
+ }) {
2616
+ return /* @__PURE__ */ jsx36(
2617
+ "div",
1985
2618
  {
1986
- ...props,
1987
- className: [
1988
- "outline-none transition-colors",
1989
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
1990
- variantStyles2[variant],
1991
- className
1992
- ].filter(Boolean).join(" ")
2619
+ role: "toolbar",
2620
+ "aria-label": `Bulk actions for ${selectedCount} selected items`,
2621
+ className: "sticky bottom-0 z-20 border-t border-border bg-background/95 backdrop-blur px-6 py-3",
2622
+ children: /* @__PURE__ */ jsxs22("div", { className: "container mx-auto flex items-center justify-between", children: [
2623
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-3", children: [
2624
+ /* @__PURE__ */ jsxs22("span", { className: "text-sm text-muted-foreground", children: [
2625
+ /* @__PURE__ */ jsx36("span", { className: "font-medium text-foreground", children: selectedCount }),
2626
+ " of ",
2627
+ totalCount,
2628
+ " ",
2629
+ "selected"
2630
+ ] }),
2631
+ /* @__PURE__ */ jsx36(Button, { variant: "secondary", size: "sm", onPress: onReset, children: "Clear selection" })
2632
+ ] }),
2633
+ children && /* @__PURE__ */ jsx36("div", { className: "flex items-center gap-2", children })
2634
+ ] })
1993
2635
  }
1994
2636
  );
1995
2637
  }
1996
2638
 
1997
- // src/components/Breadcrumbs/Breadcrumbs.tsx
2639
+ // src/components/Dialog/Dialog.tsx
1998
2640
  import {
1999
- Breadcrumbs as AriaBreadcrumbs,
2000
- Breadcrumb as AriaBreadcrumb,
2001
- Link as Link2
2641
+ Modal,
2642
+ ModalOverlay,
2643
+ Dialog as AriaDialog,
2644
+ Heading as Heading3
2002
2645
  } from "react-aria-components";
2003
- import { ChevronRight as ChevronRight2 } from "lucide-react";
2004
- import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
2005
- function Breadcrumbs({ items, className }) {
2006
- return /* @__PURE__ */ jsx27(
2007
- "nav",
2646
+ import { X as X2 } from "lucide-react";
2647
+ import { Fragment as Fragment6, jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
2648
+ var sizeStyles4 = {
2649
+ sm: "max-w-md",
2650
+ md: "max-w-lg",
2651
+ lg: "max-w-2xl",
2652
+ xl: "max-w-4xl"
2653
+ };
2654
+ function Dialog({
2655
+ isOpen,
2656
+ onOpenChange,
2657
+ title,
2658
+ size = "md",
2659
+ isDismissable = true,
2660
+ children,
2661
+ className
2662
+ }) {
2663
+ return /* @__PURE__ */ jsx37(
2664
+ ModalOverlay,
2008
2665
  {
2009
- "aria-label": "Breadcrumb",
2010
- className,
2011
- children: /* @__PURE__ */ jsx27(
2012
- AriaBreadcrumbs,
2666
+ isOpen,
2667
+ onOpenChange,
2668
+ isDismissable,
2669
+ className: [
2670
+ "fixed inset-0 z-50 bg-backdrop backdrop-blur-sm",
2671
+ "flex items-center justify-center",
2672
+ "entering:animate-in entering:fade-in",
2673
+ "exiting:animate-out exiting:fade-out"
2674
+ ].join(" "),
2675
+ children: /* @__PURE__ */ jsx37(
2676
+ Modal,
2013
2677
  {
2014
- className: "flex items-center gap-1 text-sm min-w-0",
2015
- children: items.map((item, index) => {
2016
- const isLast = index === items.length - 1;
2017
- return /* @__PURE__ */ jsx27(
2018
- AriaBreadcrumb,
2019
- {
2020
- id: item.id,
2021
- className: [
2022
- "flex items-center gap-1",
2023
- isLast ? "min-w-0" : "shrink-0"
2024
- ].join(" "),
2025
- children: isLast ? /* @__PURE__ */ jsx27("span", { className: "font-medium text-foreground truncate", children: item.label }) : /* @__PURE__ */ jsxs17(Fragment6, { children: [
2026
- /* @__PURE__ */ jsx27(
2027
- Link2,
2028
- {
2029
- href: item.href,
2030
- className: "whitespace-nowrap text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
2031
- children: item.label
2032
- }
2033
- ),
2034
- /* @__PURE__ */ jsx27(
2035
- ChevronRight2,
2036
- {
2037
- className: "shrink-0 text-slate-400",
2038
- size: 16,
2039
- "aria-hidden": "true"
2040
- }
2041
- )
2042
- ] })
2043
- },
2044
- item.id
2045
- );
2046
- })
2678
+ className: [
2679
+ "w-full mx-4",
2680
+ sizeStyles4[size],
2681
+ "bg-background rounded-lg shadow-xl max-h-[85vh] flex flex-col",
2682
+ "entering:animate-in entering:zoom-in-95 entering:fade-in",
2683
+ "exiting:animate-out exiting:zoom-out-95 exiting:fade-out",
2684
+ className
2685
+ ].filter(Boolean).join(" "),
2686
+ children: /* @__PURE__ */ jsx37(AriaDialog, { className: "outline-none flex flex-col max-h-[85vh]", children: ({ close }) => /* @__PURE__ */ jsxs23(Fragment6, { children: [
2687
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border", children: [
2688
+ /* @__PURE__ */ jsx37(
2689
+ Heading3,
2690
+ {
2691
+ slot: "title",
2692
+ className: "text-lg font-semibold text-foreground",
2693
+ children: title
2694
+ }
2695
+ ),
2696
+ /* @__PURE__ */ jsx37(
2697
+ "button",
2698
+ {
2699
+ type: "button",
2700
+ onClick: close,
2701
+ className: [
2702
+ "inline-flex items-center justify-center rounded-sm p-1",
2703
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
2704
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2705
+ "transition-colors"
2706
+ ].join(" "),
2707
+ "aria-label": "Close",
2708
+ children: /* @__PURE__ */ jsx37(X2, { size: 20, "aria-hidden": "true" })
2709
+ }
2710
+ )
2711
+ ] }),
2712
+ /* @__PURE__ */ jsx37("div", { className: "px-6 py-4 overflow-y-auto", children })
2713
+ ] }) })
2047
2714
  }
2048
2715
  )
2049
2716
  }
2050
2717
  );
2051
2718
  }
2052
2719
 
2053
- // src/components/ToggleButton/ToggleButton.tsx
2720
+ // src/components/Dialog/DialogFooter.tsx
2721
+ import { jsx as jsx38 } from "react/jsx-runtime";
2722
+
2723
+ // src/components/Toast/Toast.tsx
2054
2724
  import {
2055
- ToggleButton as AriaToggleButton2
2056
- } from "react-aria-components";
2057
- import { twMerge as twMerge14 } from "tailwind-merge";
2058
- import { jsx as jsx28 } from "react/jsx-runtime";
2059
- var squareSizeStyles2 = {
2060
- xs: "h-6 w-6 text-xs",
2061
- sm: "h-7 w-7 text-sm",
2062
- md: "h-8 w-8 text-base",
2063
- lg: "h-10 w-10 text-lg"
2725
+ createContext,
2726
+ useCallback as useCallback9,
2727
+ useContext,
2728
+ useEffect as useEffect3,
2729
+ useRef as useRef6,
2730
+ useState as useState7
2731
+ } from "react";
2732
+ import { createPortal as createPortal2 } from "react-dom";
2733
+ import { CheckCircle as CheckCircle3, XCircle as XCircle2, Info as Info2, X as X3 } from "lucide-react";
2734
+ import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
2735
+ var ToastContext = createContext(null);
2736
+ var toastCounter = 0;
2737
+ var defaultDuration = {
2738
+ success: 5e3,
2739
+ info: 5e3,
2740
+ error: 1e4
2064
2741
  };
2065
- var variantStyles3 = {
2066
- default: {
2067
- base: [
2068
- "bg-transparent text-foreground",
2069
- "hover:bg-accent",
2070
- "pressed:bg-accent"
2071
- ].join(" "),
2072
- selected: "bg-accent text-foreground"
2742
+ var variantConfig = {
2743
+ success: {
2744
+ icon: CheckCircle3,
2745
+ containerClass: "bg-success-surface border-success-border text-success",
2746
+ iconClass: "text-success"
2073
2747
  },
2074
- primary: {
2075
- base: [
2076
- "bg-transparent text-foreground",
2077
- "hover:bg-accent",
2078
- "pressed:bg-accent"
2079
- ].join(" "),
2080
- selected: "bg-primary-pressed text-primary-foreground"
2748
+ error: {
2749
+ icon: XCircle2,
2750
+ containerClass: "bg-destructive-surface border-destructive-border text-destructive",
2751
+ iconClass: "text-destructive"
2081
2752
  },
2082
- outlined: {
2083
- base: [
2084
- "bg-background text-foreground",
2085
- "border border-border",
2086
- "hover:bg-card",
2087
- "pressed:bg-muted"
2088
- ].join(" "),
2089
- selected: [
2090
- "bg-slate-800 text-primary-foreground",
2091
- "border border-slate-800"
2092
- ].join(" ")
2753
+ info: {
2754
+ icon: Info2,
2755
+ containerClass: "bg-info-surface border-info-border text-info",
2756
+ iconClass: "text-info"
2093
2757
  }
2094
2758
  };
2095
- function ToggleButton({
2096
- variant = "default",
2097
- size = "md",
2098
- isSquare = false,
2099
- className,
2100
- ...props
2759
+ var PlacementContext = createContext("bottom-right");
2760
+ var exitAnimationByPlacement = {
2761
+ "top-center": "-translate-y-full opacity-0",
2762
+ "top-right": "translate-x-full opacity-0",
2763
+ "bottom-center": "translate-y-full opacity-0",
2764
+ "bottom-right": "translate-x-full opacity-0"
2765
+ };
2766
+ var enterAnimationByPlacement = {
2767
+ "top-center": "translate-y-0 opacity-100 animate-in slide-in-from-top",
2768
+ "top-right": "translate-x-0 opacity-100 animate-in slide-in-from-right",
2769
+ "bottom-center": "translate-y-0 opacity-100 animate-in slide-in-from-bottom",
2770
+ "bottom-right": "translate-x-0 opacity-100 animate-in slide-in-from-right"
2771
+ };
2772
+ function ToastItem({
2773
+ toast,
2774
+ onRemove
2101
2775
  }) {
2102
- const styles = variantStyles3[variant];
2103
- return /* @__PURE__ */ jsx28(
2104
- AriaToggleButton2,
2776
+ const [isExiting, setIsExiting] = useState7(false);
2777
+ const timerRef = useRef6(null);
2778
+ const placement = useContext(PlacementContext);
2779
+ const config = variantConfig[toast.variant];
2780
+ const IconComponent = config.icon;
2781
+ const dismiss = useCallback9(() => {
2782
+ setIsExiting(true);
2783
+ setTimeout(() => onRemove(toast.id), 200);
2784
+ }, [onRemove, toast.id]);
2785
+ useEffect3(() => {
2786
+ const duration = toast.duration ?? defaultDuration[toast.variant];
2787
+ timerRef.current = setTimeout(dismiss, duration);
2788
+ return () => {
2789
+ if (timerRef.current) clearTimeout(timerRef.current);
2790
+ };
2791
+ }, [toast.duration, toast.variant, dismiss]);
2792
+ return /* @__PURE__ */ jsxs24(
2793
+ "div",
2105
2794
  {
2106
- ...props,
2107
- className: ({ isSelected }) => twMerge14(
2108
- "inline-flex items-center justify-center gap-2 cursor-pointer",
2109
- isSquare ? "rounded-none" : "rounded-md",
2110
- "font-medium",
2111
- "leading-tight",
2112
- "outline-none transition-colors",
2113
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2114
- "disabled:opacity-50 disabled:pointer-events-none",
2115
- isSquare ? squareSizeStyles2[size] : sizeStyles[size],
2116
- isSelected ? styles.selected : styles.base,
2117
- className
2118
- )
2795
+ role: "status",
2796
+ "aria-live": "polite",
2797
+ className: [
2798
+ "flex items-start gap-3 rounded-lg border px-4 py-3 shadow-md",
2799
+ "min-w-[320px] max-w-[420px]",
2800
+ "transition-all duration-200",
2801
+ isExiting ? exitAnimationByPlacement[placement] : enterAnimationByPlacement[placement],
2802
+ config.containerClass
2803
+ ].join(" "),
2804
+ children: [
2805
+ /* @__PURE__ */ jsx39(IconComponent, { size: 20, className: ["shrink-0 mt-0.5", config.iconClass].join(" "), "aria-hidden": "true" }),
2806
+ /* @__PURE__ */ jsx39("p", { className: "flex-1 text-sm font-medium", children: toast.message }),
2807
+ /* @__PURE__ */ jsx39(
2808
+ "button",
2809
+ {
2810
+ type: "button",
2811
+ onClick: dismiss,
2812
+ className: "shrink-0 rounded-sm p-0.5 opacity-70 hover:opacity-100 transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-current",
2813
+ "aria-label": "Dismiss",
2814
+ children: /* @__PURE__ */ jsx39(X3, { size: 16, "aria-hidden": "true" })
2815
+ }
2816
+ )
2817
+ ]
2119
2818
  }
2120
2819
  );
2121
2820
  }
2821
+ var containerPositionStyles = {
2822
+ "top-center": "fixed top-4 left-1/2 -translate-x-1/2 z-50 flex flex-col-reverse gap-2 items-center",
2823
+ "top-right": "fixed top-4 right-4 z-50 flex flex-col-reverse gap-2",
2824
+ "bottom-center": "fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex flex-col gap-2 items-center",
2825
+ "bottom-right": "fixed bottom-4 right-4 z-50 flex flex-col gap-2"
2826
+ };
2827
+ function ToastContainer({
2828
+ toasts,
2829
+ removeToast,
2830
+ placement = "bottom-right"
2831
+ }) {
2832
+ if (toasts.length === 0) return null;
2833
+ return createPortal2(
2834
+ /* @__PURE__ */ jsx39(PlacementContext.Provider, { value: placement, children: /* @__PURE__ */ jsx39("div", { className: containerPositionStyles[placement], children: toasts.map((toast) => /* @__PURE__ */ jsx39(ToastItem, { toast, onRemove: removeToast }, toast.id)) }) }),
2835
+ document.body
2836
+ );
2837
+ }
2838
+ function createToastBridge() {
2839
+ const listeners = /* @__PURE__ */ new Set();
2840
+ return {
2841
+ emit: (toast) => {
2842
+ listeners.forEach((fn) => fn(toast));
2843
+ },
2844
+ subscribe: (fn) => {
2845
+ listeners.add(fn);
2846
+ return () => {
2847
+ listeners.delete(fn);
2848
+ };
2849
+ }
2850
+ };
2851
+ }
2852
+ function ToastProvider({ children, bridge, placement = "bottom-right" }) {
2853
+ const [toasts, setToasts] = useState7([]);
2854
+ const addToast = useCallback9((toast) => {
2855
+ const id = `toast-${++toastCounter}`;
2856
+ setToasts((prev) => [...prev, { ...toast, id }]);
2857
+ }, []);
2858
+ const removeToast = useCallback9((id) => {
2859
+ setToasts((prev) => prev.filter((t) => t.id !== id));
2860
+ }, []);
2861
+ useEffect3(() => {
2862
+ if (!bridge) return;
2863
+ return bridge.subscribe(addToast);
2864
+ }, [bridge, addToast]);
2865
+ return /* @__PURE__ */ jsxs24(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
2866
+ children,
2867
+ /* @__PURE__ */ jsx39(ToastContainer, { toasts, removeToast, placement })
2868
+ ] });
2869
+ }
2870
+ function useToast() {
2871
+ const context = useContext(ToastContext);
2872
+ if (!context) {
2873
+ throw new Error("useToast must be used within a ToastProvider");
2874
+ }
2875
+ return {
2876
+ toast: context.addToast,
2877
+ toasts: context.toasts,
2878
+ removeToast: context.removeToast
2879
+ };
2880
+ }
2122
2881
 
2123
- // src/components/Menu/Menu.tsx
2882
+ // src/components/Form/Switch/Switch.tsx
2124
2883
  import {
2125
- MenuTrigger,
2126
- Menu as AriaMenu,
2127
- MenuItem as AriaMenuItem,
2128
- Popover as Popover2
2884
+ SwitchField,
2885
+ SwitchButton
2129
2886
  } from "react-aria-components";
2130
- import { twMerge as twMerge15 } from "tailwind-merge";
2131
-
2132
- // src/components/Menu/menuStyles.ts
2133
- var popoverStyles = `
2134
- bg-background rounded-md shadow-lg
2135
- border border-border
2136
- py-1 min-w-48
2137
- entering:animate-in entering:fade-in entering:zoom-in-95
2138
- exiting:animate-out exiting:fade-out exiting:zoom-out-95
2139
- `;
2140
-
2141
- // src/components/Menu/Menu.tsx
2142
- import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
2143
- function Menu2({
2144
- items,
2145
- content,
2887
+ import { twMerge as twMerge17 } from "tailwind-merge";
2888
+ import { Fragment as Fragment7, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
2889
+ function Switch({
2146
2890
  children,
2147
- onAction,
2148
- selectionMode,
2149
- selectedKeys,
2150
- defaultSelectedKeys,
2151
- onSelectionChange,
2152
- className
2891
+ color = "var(--color-primary)",
2892
+ className,
2893
+ ...props
2153
2894
  }) {
2154
- const selectionProps = selectionMode && selectionMode !== "none" ? { selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange } : {};
2155
- return /* @__PURE__ */ jsxs18(MenuTrigger, { children: [
2156
- children,
2157
- /* @__PURE__ */ jsx29(Popover2, { className: twMerge15(popoverStyles, className), children: items ? /* @__PURE__ */ jsx29(
2158
- AriaMenu,
2895
+ return /* @__PURE__ */ jsx40(SwitchField, { ...props, children: /* @__PURE__ */ jsx40(SwitchButton, { className: "relative cursor-pointer", children: ({ isSelected, isFocusVisible }) => /* @__PURE__ */ jsxs25(Fragment7, { children: [
2896
+ /* @__PURE__ */ jsx40(
2897
+ "div",
2159
2898
  {
2160
- items,
2161
- onAction: (key) => {
2162
- const item = items.find((i) => i.id === key);
2163
- item?.onAction?.();
2164
- onAction?.(key);
2165
- },
2166
- ...selectionProps,
2167
- className: "outline-none",
2168
- children: (item) => /* @__PURE__ */ jsxs18(
2169
- AriaMenuItem,
2899
+ className: twMerge17(
2900
+ `
2901
+ flex items-center
2902
+ border-2 border-border
2903
+ w-9 h-5 rounded-full transition-colors shrink-0
2904
+ `,
2905
+ isFocusVisible && "ring-2 ring-ring ring-offset-2",
2906
+ !isSelected && "bg-border"
2907
+ ),
2908
+ style: isSelected ? { backgroundColor: color } : void 0,
2909
+ children: /* @__PURE__ */ jsx40(
2910
+ "div",
2170
2911
  {
2171
- id: item.id,
2172
- href: item.href,
2173
- target: item.target,
2174
- isDisabled: item.isDisabled,
2175
- className: [
2176
- "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2177
- "transition-colors",
2178
- "focus:bg-muted",
2179
- "hover:bg-muted",
2180
- "disabled:opacity-50 disabled:pointer-events-none",
2181
- item.isDanger ? "text-destructive" : "text-foreground"
2182
- ].filter(Boolean).join(" "),
2183
- children: [
2184
- item.icon && /* @__PURE__ */ jsx29(Icon, { icon: item.icon, size: "sm" }),
2185
- /* @__PURE__ */ jsx29("span", { className: "flex-1", children: item.label }),
2186
- item.endContent && /* @__PURE__ */ jsx29("span", { className: "ml-auto flex items-center", children: item.endContent })
2187
- ]
2912
+ className: twMerge17(
2913
+ `
2914
+ absolute top-0 left-0 w-5 h-5
2915
+ rounded-full
2916
+ transition-transform
2917
+ border-2 border-border
2918
+
2919
+ `,
2920
+ isSelected ? "translate-x-4 bg-card" : "translate-x-0 bg-background"
2921
+ )
2188
2922
  }
2189
2923
  )
2190
2924
  }
2191
- ) : /* @__PURE__ */ jsx29(
2192
- AriaMenu,
2193
- {
2194
- onAction: (key) => onAction?.(key),
2195
- ...selectionProps,
2196
- className: "outline-none",
2197
- children: content
2198
- }
2199
- ) })
2200
- ] });
2925
+ ),
2926
+ children && /* @__PURE__ */ jsx40("span", { children })
2927
+ ] }) }) });
2201
2928
  }
2202
2929
 
2203
- // src/components/Menu/useContextMenu.tsx
2204
- import {
2205
- useCallback as useCallback3,
2206
- useEffect as useEffect3,
2207
- useId as useId2,
2208
- useRef as useRef5,
2209
- useState as useState7
2210
- } from "react";
2930
+ // src/components/Form/Radio/Radio.tsx
2211
2931
  import {
2212
- Menu as AriaMenu2,
2213
- MenuTrigger as MenuTrigger2,
2214
- Popover as Popover3
2932
+ RadioGroup as AriaRadioGroup,
2933
+ Radio as AriaRadio
2215
2934
  } from "react-aria-components";
2216
- import { twMerge as twMerge16 } from "tailwind-merge";
2217
- import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
2218
- function useContextMenu({
2219
- content,
2220
- label,
2221
- onAction,
2222
- className
2935
+ import { twMerge as twMerge18 } from "tailwind-merge";
2936
+ import { Fragment as Fragment8, jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
2937
+ function RadioGroup({
2938
+ children,
2939
+ className,
2940
+ orientation = "vertical",
2941
+ ...props
2223
2942
  }) {
2224
- const popoverId = useId2();
2225
- const [anchor, setAnchor] = useState7(null);
2226
- const anchorRef = useRef5(null);
2227
- const popoverRef = useRef5(null);
2228
- const isOpen = anchor !== null;
2229
- const close = useCallback3(() => setAnchor(null), []);
2230
- const onContextMenu = useCallback3((event) => {
2231
- event.preventDefault();
2232
- setAnchor({ x: event.clientX, y: event.clientY });
2233
- }, []);
2234
- const onPress = useCallback3((event) => {
2235
- const rect = event.target.getBoundingClientRect();
2236
- setAnchor({ x: rect.left, y: rect.bottom });
2237
- }, []);
2238
- useEffect3(() => {
2239
- if (!isOpen) return;
2240
- const isInside = (target) => popoverRef.current?.contains(target) ?? false;
2241
- const onPointerDown = (event) => {
2242
- if (!isInside(event.target)) close();
2243
- };
2244
- const onOutsideContextMenu = (event) => {
2245
- if (isInside(event.target)) return;
2246
- event.preventDefault();
2247
- close();
2248
- };
2249
- const onKeyDown = (event) => {
2250
- if (event.key === "Escape") close();
2251
- };
2252
- document.addEventListener("pointerdown", onPointerDown, true);
2253
- document.addEventListener("contextmenu", onOutsideContextMenu, true);
2254
- document.addEventListener("keydown", onKeyDown, true);
2255
- return () => {
2256
- document.removeEventListener("pointerdown", onPointerDown, true);
2257
- document.removeEventListener("contextmenu", onOutsideContextMenu, true);
2258
- document.removeEventListener("keydown", onKeyDown, true);
2259
- };
2260
- }, [isOpen, close]);
2261
- const menu = /* @__PURE__ */ jsxs19(
2262
- MenuTrigger2,
2943
+ return /* @__PURE__ */ jsx41(
2944
+ AriaRadioGroup,
2263
2945
  {
2264
- isOpen,
2265
- onOpenChange: (open) => {
2266
- if (!open) close();
2267
- },
2268
- children: [
2269
- /* @__PURE__ */ jsx30(
2270
- "span",
2946
+ ...props,
2947
+ orientation,
2948
+ className: twMerge18(
2949
+ "flex gap-2 disabled:opacity-50",
2950
+ orientation === "horizontal" ? "flex-row" : "flex-col",
2951
+ className
2952
+ ),
2953
+ children
2954
+ }
2955
+ );
2956
+ }
2957
+ function Radio({ children, className, ...props }) {
2958
+ return /* @__PURE__ */ jsx41(
2959
+ AriaRadio,
2960
+ {
2961
+ ...props,
2962
+ className: [
2963
+ "group flex items-center gap-2 text-sm text-foreground cursor-pointer",
2964
+ "disabled:opacity-50 disabled:cursor-default",
2965
+ className
2966
+ ].filter(Boolean).join(" "),
2967
+ children: ({ isSelected }) => /* @__PURE__ */ jsxs26(Fragment8, { children: [
2968
+ /* @__PURE__ */ jsx41(
2969
+ "div",
2271
2970
  {
2272
- ref: anchorRef,
2273
- "aria-hidden": true,
2274
- tabIndex: -1,
2275
- className: "pointer-events-none fixed h-0 w-0",
2276
- style: { left: anchor?.x ?? 0, top: anchor?.y ?? 0 }
2971
+ className: [
2972
+ "flex items-center justify-center w-5 h-5 shrink-0",
2973
+ "rounded-full border-2 transition-colors",
2974
+ "group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2",
2975
+ isSelected ? "border-primary" : "border-border group-hover:border-border"
2976
+ ].join(" "),
2977
+ children: isSelected && /* @__PURE__ */ jsx41("div", { className: "w-2.5 h-2.5 rounded-full bg-primary" })
2277
2978
  }
2278
2979
  ),
2279
- /* @__PURE__ */ jsx30(
2280
- Popover3,
2281
- {
2282
- isNonModal: true,
2283
- triggerRef: anchorRef,
2284
- placement: "bottom start",
2285
- ref: popoverRef,
2286
- className: twMerge16(popoverStyles, className),
2287
- children: /* @__PURE__ */ jsx30(
2288
- AriaMenu2,
2289
- {
2290
- id: popoverId,
2291
- "aria-label": label,
2292
- autoFocus: "first",
2293
- onAction: (key) => {
2294
- onAction?.(String(key));
2295
- close();
2296
- },
2297
- className: "outline-none",
2298
- children: content
2299
- }
2300
- )
2301
- }
2302
- )
2303
- ]
2980
+ children && /* @__PURE__ */ jsx41("span", { children })
2981
+ ] })
2982
+ }
2983
+ );
2984
+ }
2985
+ function RadioButton({ children, className, ...props }) {
2986
+ return /* @__PURE__ */ jsx41(
2987
+ AriaRadio,
2988
+ {
2989
+ ...props,
2990
+ className: [
2991
+ "group cursor-pointer",
2992
+ "disabled:opacity-50 disabled:cursor-default",
2993
+ className
2994
+ ].filter(Boolean).join(" "),
2995
+ children: ({ isSelected }) => /* @__PURE__ */ jsx41(
2996
+ "div",
2997
+ {
2998
+ className: [
2999
+ "px-4 py-2 text-sm font-medium",
3000
+ "rounded-md border transition-colors text-center",
3001
+ "group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2",
3002
+ isSelected ? "bg-primary border-primary text-primary-foreground" : "bg-background border-border text-foreground hover:border-border"
3003
+ ].join(" "),
3004
+ children
3005
+ }
3006
+ )
2304
3007
  }
2305
3008
  );
2306
- return {
2307
- targetProps: { onContextMenu },
2308
- triggerProps: {
2309
- onPress,
2310
- onClick: (e) => {
2311
- e.preventDefault();
2312
- },
2313
- "aria-haspopup": "menu",
2314
- "aria-expanded": isOpen,
2315
- "aria-controls": isOpen ? popoverId : void 0
2316
- },
2317
- menu,
2318
- isOpen,
2319
- close
2320
- };
2321
3009
  }
2322
3010
 
2323
- // src/components/Menu/MenuItem.tsx
2324
- import { MenuItem as AriaMenuItem2 } from "react-aria-components";
2325
- import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
2326
- function MenuItem({
2327
- id,
3011
+ // src/components/Form/Slider/Slider.tsx
3012
+ import {
3013
+ Slider as AriaSlider,
3014
+ SliderTrack,
3015
+ SliderFill,
3016
+ SliderThumb
3017
+ } from "react-aria-components";
3018
+ import { twMerge as twMerge19 } from "tailwind-merge";
3019
+ import { Fragment as Fragment9, jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
3020
+ function Slider({
3021
+ label,
3022
+ output,
3023
+ description,
3024
+ errorMessage,
2328
3025
  children,
2329
- icon,
2330
- endContent,
2331
- onAction,
2332
- href,
2333
- target,
3026
+ className,
2334
3027
  isDisabled,
2335
- isDanger,
2336
- textValue,
2337
- className
3028
+ ...props
2338
3029
  }) {
2339
- return /* @__PURE__ */ jsxs20(
2340
- AriaMenuItem2,
3030
+ return /* @__PURE__ */ jsx42(
3031
+ AriaSlider,
2341
3032
  {
2342
- id,
2343
- href,
2344
- target,
3033
+ ...props,
2345
3034
  isDisabled,
2346
- onAction,
2347
- textValue,
3035
+ className: twMerge19(
3036
+ // data-disabled lands on the root (tailwindcss-react-aria-components
3037
+ // maps the disabled: variant onto it).
3038
+ "w-full flex flex-col gap-2 disabled:opacity-50 disabled:cursor-default",
3039
+ className
3040
+ ),
3041
+ children: ({ state }) => /* @__PURE__ */ jsxs27(Fragment9, { children: [
3042
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between", children: [
3043
+ label && /* @__PURE__ */ jsx42(Label, { children: label }),
3044
+ output && /* @__PURE__ */ jsx42("span", { className: "text-sm font-medium text-foreground tabular-nums", children: output(state.values[0]) })
3045
+ ] }),
3046
+ /* @__PURE__ */ jsxs27(SliderTrack, { className: "flex h-6 w-full cursor-pointer items-center", children: [
3047
+ /* @__PURE__ */ jsx42("div", { className: "relative h-1.5 w-full overflow-hidden rounded-full bg-border", children: /* @__PURE__ */ jsx42(SliderFill, { className: "h-full rounded-full bg-primary" }) }),
3048
+ /* @__PURE__ */ jsx42(
3049
+ SliderThumb,
3050
+ {
3051
+ className: twMerge19(
3052
+ "top-1/2 h-4 w-4 rounded-full bg-background",
3053
+ "border-2 border-primary",
3054
+ "shadow-sm",
3055
+ "transition-[box-shadow,border-color]",
3056
+ "hovered:border-primary-hover",
3057
+ "dragging:cursor-grabbing",
3058
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
3059
+ )
3060
+ }
3061
+ )
3062
+ ] }),
3063
+ (description || errorMessage) && /* @__PURE__ */ jsx42(
3064
+ "p",
3065
+ {
3066
+ className: twMerge19(
3067
+ "text-xs text-muted-foreground",
3068
+ errorMessage && "text-destructive"
3069
+ ),
3070
+ children: errorMessage ?? description
3071
+ }
3072
+ ),
3073
+ children
3074
+ ] })
3075
+ }
3076
+ );
3077
+ }
3078
+
3079
+ // src/components/Form/Fieldset/Fieldset.tsx
3080
+ import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
3081
+ function Fieldset({ legend, children, className }) {
3082
+ return /* @__PURE__ */ jsxs28(
3083
+ "fieldset",
3084
+ {
2348
3085
  className: [
2349
- "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2350
- "transition-colors",
2351
- "focus:bg-muted",
2352
- "hover:bg-muted",
2353
- "disabled:opacity-50 disabled:pointer-events-none",
2354
- isDanger ? "text-destructive" : "text-foreground",
3086
+ "flex flex-col gap-8",
3087
+ "border-none p-0 m-0",
2355
3088
  className
2356
3089
  ].filter(Boolean).join(" "),
2357
3090
  children: [
2358
- icon && /* @__PURE__ */ jsx31(Icon, { icon, size: "sm" }),
2359
- /* @__PURE__ */ jsx31("span", { className: "flex-1", children }),
2360
- endContent && /* @__PURE__ */ jsx31("span", { className: "ml-auto flex items-center", children: endContent })
3091
+ legend && /* @__PURE__ */ jsx43(
3092
+ "legend",
3093
+ {
3094
+ className: [
3095
+ "text-lg",
3096
+ "font-semibold",
3097
+ "text-foreground",
3098
+ "p-0"
3099
+ ].join(" "),
3100
+ children: legend
3101
+ }
3102
+ ),
3103
+ children
2361
3104
  ]
2362
3105
  }
2363
3106
  );
2364
3107
  }
2365
3108
 
2366
- // src/components/Menu/MenuCheckboxItem.tsx
2367
- import { MenuItem as AriaMenuItem3 } from "react-aria-components";
2368
- import { Check as Check4 } from "lucide-react";
2369
- import { Fragment as Fragment7, jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
2370
- function MenuCheckboxItem({
2371
- id,
2372
- children,
2373
- textValue,
2374
- isDisabled,
2375
- className
3109
+ // src/components/Link/Link.tsx
3110
+ import {
3111
+ Link as AriaLink3
3112
+ } from "react-aria-components";
3113
+ import { jsx as jsx44 } from "react/jsx-runtime";
3114
+ var variantStyles2 = {
3115
+ default: [
3116
+ "text-teal-700 underline",
3117
+ "hover:text-teal-800"
3118
+ ].join(" "),
3119
+ subtle: [
3120
+ "text-muted-foreground no-underline",
3121
+ "hover:underline hover:text-foreground"
3122
+ ].join(" ")
3123
+ };
3124
+ function Link({
3125
+ variant = "default",
3126
+ className,
3127
+ ...props
2376
3128
  }) {
2377
- return /* @__PURE__ */ jsx32(
2378
- AriaMenuItem3,
3129
+ return /* @__PURE__ */ jsx44(
3130
+ AriaLink3,
2379
3131
  {
2380
- id,
2381
- textValue,
2382
- isDisabled,
2383
- className: ({ isSelected }) => [
2384
- "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2385
- "transition-colors",
2386
- "focus:bg-muted",
2387
- "hover:bg-muted",
2388
- "disabled:opacity-50 disabled:pointer-events-none",
2389
- "text-foreground",
2390
- isSelected ? "font-medium" : "",
3132
+ ...props,
3133
+ className: [
3134
+ "outline-none transition-colors",
3135
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
3136
+ variantStyles2[variant],
2391
3137
  className
2392
- ].filter(Boolean).join(" "),
2393
- children: ({ isSelected }) => /* @__PURE__ */ jsxs21(Fragment7, { children: [
2394
- /* @__PURE__ */ jsx32("span", { className: "flex items-center justify-center w-4 h-4 shrink-0", children: isSelected && /* @__PURE__ */ jsx32(Check4, { size: 14, className: "text-primary", "aria-hidden": "true" }) }),
2395
- /* @__PURE__ */ jsx32("span", { className: "flex-1", children })
2396
- ] })
3138
+ ].filter(Boolean).join(" ")
2397
3139
  }
2398
3140
  );
2399
3141
  }
2400
3142
 
2401
- // src/components/Menu/MenuSection.tsx
3143
+ // src/components/Breadcrumbs/Breadcrumbs.tsx
2402
3144
  import {
2403
- MenuSection as AriaMenuSection,
2404
- Header
3145
+ Breadcrumbs as AriaBreadcrumbs,
3146
+ Breadcrumb as AriaBreadcrumb,
3147
+ Link as Link2
2405
3148
  } from "react-aria-components";
2406
- import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
2407
- function MenuSection({
2408
- header,
2409
- children,
2410
- "aria-label": ariaLabel,
2411
- className
2412
- }) {
2413
- return /* @__PURE__ */ jsxs22(AriaMenuSection, { className, "aria-label": ariaLabel, children: [
2414
- header && /* @__PURE__ */ jsx33(
2415
- Header,
2416
- {
2417
- className: [
2418
- "px-3 py-1.5",
2419
- "text-xs font-semibold",
2420
- "text-muted-foreground",
2421
- "uppercase tracking-wider",
2422
- "select-none"
2423
- ].join(" "),
2424
- children: header
2425
- }
2426
- ),
2427
- children
2428
- ] });
2429
- }
2430
-
2431
- // src/components/Menu/MenuHeader.tsx
2432
- import { Header as Header2 } from "react-aria-components";
2433
- import { jsx as jsx34 } from "react/jsx-runtime";
2434
- function MenuHeader({ children, className }) {
2435
- return /* @__PURE__ */ jsx34(Header2, { className, children });
3149
+ import { ChevronRight as ChevronRight2 } from "lucide-react";
3150
+ import { Fragment as Fragment10, jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
3151
+ function Breadcrumbs({ items, className }) {
3152
+ return /* @__PURE__ */ jsx45(
3153
+ "nav",
3154
+ {
3155
+ "aria-label": "Breadcrumb",
3156
+ className,
3157
+ children: /* @__PURE__ */ jsx45(
3158
+ AriaBreadcrumbs,
3159
+ {
3160
+ className: "flex items-center gap-1 text-sm min-w-0",
3161
+ children: items.map((item, index) => {
3162
+ const isLast = index === items.length - 1;
3163
+ return /* @__PURE__ */ jsx45(
3164
+ AriaBreadcrumb,
3165
+ {
3166
+ id: item.id,
3167
+ className: [
3168
+ "flex items-center gap-1",
3169
+ isLast ? "min-w-0" : "shrink-0"
3170
+ ].join(" "),
3171
+ children: isLast ? /* @__PURE__ */ jsx45("span", { className: "font-medium text-foreground truncate", children: item.label }) : /* @__PURE__ */ jsxs29(Fragment10, { children: [
3172
+ /* @__PURE__ */ jsx45(
3173
+ Link2,
3174
+ {
3175
+ href: item.href,
3176
+ className: "whitespace-nowrap text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
3177
+ children: item.label
3178
+ }
3179
+ ),
3180
+ /* @__PURE__ */ jsx45(
3181
+ ChevronRight2,
3182
+ {
3183
+ className: "shrink-0 text-slate-400",
3184
+ size: 16,
3185
+ "aria-hidden": "true"
3186
+ }
3187
+ )
3188
+ ] })
3189
+ },
3190
+ item.id
3191
+ );
3192
+ })
3193
+ }
3194
+ )
3195
+ }
3196
+ );
2436
3197
  }
2437
3198
 
2438
- // src/components/Menu/MenuSeparator.tsx
2439
- import { Separator } from "react-aria-components";
2440
- import { jsx as jsx35 } from "react/jsx-runtime";
2441
- function MenuSeparator({ className }) {
2442
- return /* @__PURE__ */ jsx35(
2443
- Separator,
3199
+ // src/components/ToggleButton/ToggleButton.tsx
3200
+ import {
3201
+ ToggleButton as AriaToggleButton2
3202
+ } from "react-aria-components";
3203
+ import { twMerge as twMerge20 } from "tailwind-merge";
3204
+ import { jsx as jsx46 } from "react/jsx-runtime";
3205
+ var squareSizeStyles2 = {
3206
+ xs: "h-6 w-6 text-xs",
3207
+ sm: "h-7 w-7 text-sm",
3208
+ md: "h-8 w-8 text-base",
3209
+ lg: "h-10 w-10 text-lg"
3210
+ };
3211
+ var variantStyles3 = {
3212
+ default: {
3213
+ base: [
3214
+ "bg-transparent text-foreground",
3215
+ "hover:bg-accent",
3216
+ "pressed:bg-accent"
3217
+ ].join(" "),
3218
+ selected: "bg-accent text-foreground"
3219
+ },
3220
+ primary: {
3221
+ base: [
3222
+ "bg-transparent text-foreground",
3223
+ "hover:bg-accent",
3224
+ "pressed:bg-accent"
3225
+ ].join(" "),
3226
+ selected: "bg-primary-pressed text-primary-foreground"
3227
+ },
3228
+ outlined: {
3229
+ base: [
3230
+ "bg-background text-foreground",
3231
+ "border border-border",
3232
+ "hover:bg-card",
3233
+ "pressed:bg-muted"
3234
+ ].join(" "),
3235
+ selected: [
3236
+ "bg-slate-800 text-primary-foreground",
3237
+ "border border-slate-800"
3238
+ ].join(" ")
3239
+ }
3240
+ };
3241
+ function ToggleButton({
3242
+ variant = "default",
3243
+ size = "md",
3244
+ isSquare = false,
3245
+ className,
3246
+ ...props
3247
+ }) {
3248
+ const styles = variantStyles3[variant];
3249
+ return /* @__PURE__ */ jsx46(
3250
+ AriaToggleButton2,
2444
3251
  {
2445
- className: [
2446
- "border-t border-border my-1",
3252
+ ...props,
3253
+ className: ({ isSelected }) => twMerge20(
3254
+ "inline-flex items-center justify-center gap-2 cursor-pointer",
3255
+ isSquare ? "rounded-none" : "rounded-md",
3256
+ "font-medium",
3257
+ "leading-tight",
3258
+ "outline-none transition-colors",
3259
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
3260
+ "disabled:opacity-50 disabled:pointer-events-none",
3261
+ isSquare ? squareSizeStyles2[size] : sizeStyles[size],
3262
+ isSelected ? styles.selected : styles.base,
2447
3263
  className
2448
- ].filter(Boolean).join(" ")
3264
+ )
2449
3265
  }
2450
3266
  );
2451
3267
  }
@@ -2456,17 +3272,17 @@ import {
2456
3272
  Popover as AriaPopover,
2457
3273
  Button as AriaButton3
2458
3274
  } from "react-aria-components";
2459
- import { twMerge as twMerge17 } from "tailwind-merge";
2460
- import { jsx as jsx36 } from "react/jsx-runtime";
3275
+ import { twMerge as twMerge21 } from "tailwind-merge";
3276
+ import { jsx as jsx47 } from "react/jsx-runtime";
2461
3277
  function Popover4({ children, isOpen, onOpenChange }) {
2462
- return /* @__PURE__ */ jsx36(DialogTrigger, { isOpen, onOpenChange, children });
3278
+ return /* @__PURE__ */ jsx47(DialogTrigger, { isOpen, onOpenChange, children });
2463
3279
  }
2464
3280
  function PopoverTrigger({ children, className }) {
2465
3281
  const cx = `
2466
3282
  inline-flex items-center bg-transparent border-none p-0 outline-none cursor-pointer
2467
3283
  focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-sm
2468
3284
  `;
2469
- return /* @__PURE__ */ jsx36(AriaButton3, { className: twMerge17(cx, className), children });
3285
+ return /* @__PURE__ */ jsx47(AriaButton3, { className: twMerge21(cx, className), children });
2470
3286
  }
2471
3287
  function PopoverContent({
2472
3288
  placement = "bottom",
@@ -2487,13 +3303,13 @@ function PopoverContent({
2487
3303
  entering:placement-left:slide-in-from-right-1
2488
3304
  entering:placement-right:slide-in-from-left-1
2489
3305
  `;
2490
- return /* @__PURE__ */ jsx36(
3306
+ return /* @__PURE__ */ jsx47(
2491
3307
  AriaPopover,
2492
3308
  {
2493
3309
  ...rest,
2494
3310
  placement,
2495
3311
  offset: offsetPx,
2496
- className: twMerge17(cx, className),
3312
+ className: twMerge21(cx, className),
2497
3313
  children
2498
3314
  }
2499
3315
  );
@@ -2501,19 +3317,19 @@ function PopoverContent({
2501
3317
 
2502
3318
  // src/components/Tabs/Tabs.tsx
2503
3319
  import { createContext as createContext2, useContext as useContext2 } from "react";
2504
- import { twMerge as twMerge18 } from "tailwind-merge";
3320
+ import { twMerge as twMerge22 } from "tailwind-merge";
2505
3321
  import {
2506
3322
  Tabs as AriaTabs,
2507
3323
  TabList as AriaTabList,
2508
3324
  Tab as AriaTab,
2509
3325
  TabPanel as AriaTabPanel
2510
3326
  } from "react-aria-components";
2511
- import { jsx as jsx37 } from "react/jsx-runtime";
3327
+ import { jsx as jsx48 } from "react/jsx-runtime";
2512
3328
  var TabsContext = createContext2({
2513
3329
  variant: "underline",
2514
3330
  size: "md"
2515
3331
  });
2516
- var sizeStyles4 = {
3332
+ var sizeStyles5 = {
2517
3333
  sm: "px-3 py-1.5 text-sm",
2518
3334
  md: "px-4 py-2 text-base",
2519
3335
  lg: "px-6 py-3 text-lg"
@@ -2526,12 +3342,12 @@ function Tabs({
2526
3342
  children,
2527
3343
  ...props
2528
3344
  }) {
2529
- return /* @__PURE__ */ jsx37(TabsContext.Provider, { value: { variant, size }, children: /* @__PURE__ */ jsx37(
3345
+ return /* @__PURE__ */ jsx48(TabsContext.Provider, { value: { variant, size }, children: /* @__PURE__ */ jsx48(
2530
3346
  AriaTabs,
2531
3347
  {
2532
3348
  ...props,
2533
3349
  orientation,
2534
- className: twMerge18(
3350
+ className: twMerge22(
2535
3351
  orientation === "vertical" ? "flex" : "",
2536
3352
  className
2537
3353
  ),
@@ -2546,11 +3362,11 @@ function TabList({
2546
3362
  const { variant } = useContext2(TabsContext);
2547
3363
  const baseStyles = variant === "unstyled" ? "flex items-center" : variant === "underline" ? "flex items-center border-b border-border" : "inline-flex items-center bg-muted rounded-lg p-1 gap-1";
2548
3364
  const verticalStyles = variant === "unstyled" ? "flex-col" : variant === "underline" ? "flex-col border-b-0 border-r border-border" : "flex-col";
2549
- return /* @__PURE__ */ jsx37(
3365
+ return /* @__PURE__ */ jsx48(
2550
3366
  AriaTabList,
2551
3367
  {
2552
3368
  ...props,
2553
- className: ({ orientation }) => twMerge18(
3369
+ className: ({ orientation }) => twMerge22(
2554
3370
  baseStyles,
2555
3371
  orientation === "vertical" ? verticalStyles : "",
2556
3372
  className
@@ -2560,20 +3376,20 @@ function TabList({
2560
3376
  }
2561
3377
  function Tab({ className, ...props }) {
2562
3378
  const { variant, size } = useContext2(TabsContext);
2563
- return /* @__PURE__ */ jsx37(
3379
+ return /* @__PURE__ */ jsx48(
2564
3380
  AriaTab,
2565
3381
  {
2566
3382
  ...props,
2567
3383
  className: ({ isSelected, isDisabled, isHovered, isPressed }) => {
2568
3384
  if (variant === "unstyled") {
2569
- return twMerge18(
3385
+ return twMerge22(
2570
3386
  "cursor-pointer outline-none",
2571
3387
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2572
3388
  isDisabled ? "opacity-50 pointer-events-none" : "",
2573
3389
  className
2574
3390
  );
2575
3391
  }
2576
- return twMerge18(
3392
+ return twMerge22(
2577
3393
  // Base
2578
3394
  "cursor-pointer outline-none transition-colors",
2579
3395
  "font-medium",
@@ -2582,7 +3398,7 @@ function Tab({ className, ...props }) {
2582
3398
  // Disabled
2583
3399
  isDisabled ? "opacity-50 pointer-events-none" : "",
2584
3400
  // Size
2585
- sizeStyles4[size],
3401
+ sizeStyles5[size],
2586
3402
  ...getTabVariantStyles(variant, {
2587
3403
  isSelected,
2588
3404
  isHovered,
@@ -2617,11 +3433,11 @@ function getTabVariantStyles(variant, state) {
2617
3433
  }
2618
3434
  function TabPanel({ className, ...props }) {
2619
3435
  const { variant } = useContext2(TabsContext);
2620
- return /* @__PURE__ */ jsx37(
3436
+ return /* @__PURE__ */ jsx48(
2621
3437
  AriaTabPanel,
2622
3438
  {
2623
3439
  ...props,
2624
- className: twMerge18(
3440
+ className: twMerge22(
2625
3441
  variant === "unstyled" ? "outline-none" : "mt-4 outline-none",
2626
3442
  className
2627
3443
  )
@@ -2639,16 +3455,16 @@ import {
2639
3455
 
2640
3456
  // src/components/SegmentedControl/SegmentedControl.tsx
2641
3457
  import { createContext as createContext3, useContext as useContext3 } from "react";
2642
- import { twMerge as twMerge19 } from "tailwind-merge";
3458
+ import { twMerge as twMerge23 } from "tailwind-merge";
2643
3459
  import {
2644
3460
  ToggleButtonGroup as AriaToggleButtonGroup,
2645
3461
  ToggleButton as AriaToggleButton3
2646
3462
  } from "react-aria-components";
2647
- import { jsx as jsx38 } from "react/jsx-runtime";
3463
+ import { jsx as jsx49 } from "react/jsx-runtime";
2648
3464
  var SegmentedControlContext = createContext3({
2649
3465
  size: "md"
2650
3466
  });
2651
- var sizeStyles5 = {
3467
+ var sizeStyles6 = {
2652
3468
  sm: "px-2.5 py-1 text-xs",
2653
3469
  md: "px-3 py-1.5 text-sm",
2654
3470
  lg: "px-4 py-2 text-base"
@@ -2664,7 +3480,7 @@ function SegmentedControl({
2664
3480
  ...props
2665
3481
  }) {
2666
3482
  const isNoneMode = selectionMode === "none";
2667
- return /* @__PURE__ */ jsx38(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx38(
3483
+ return /* @__PURE__ */ jsx49(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx49(
2668
3484
  AriaToggleButtonGroup,
2669
3485
  {
2670
3486
  ...props,
@@ -2672,7 +3488,7 @@ function SegmentedControl({
2672
3488
  selectedKeys: isNoneMode ? /* @__PURE__ */ new Set() : selectedKeys,
2673
3489
  defaultSelectedKeys: isNoneMode ? void 0 : defaultSelectedKeys,
2674
3490
  onSelectionChange: isNoneMode ? void 0 : onSelectionChange,
2675
- className: twMerge19(
3491
+ className: twMerge23(
2676
3492
  "inline-flex items-center rounded-lg border border-border bg-muted p-0.5 gap-0.5",
2677
3493
  className
2678
3494
  ),
@@ -2685,11 +3501,11 @@ function SegmentedControlItem({
2685
3501
  ...props
2686
3502
  }) {
2687
3503
  const { size } = useContext3(SegmentedControlContext);
2688
- return /* @__PURE__ */ jsx38(
3504
+ return /* @__PURE__ */ jsx49(
2689
3505
  AriaToggleButton3,
2690
3506
  {
2691
3507
  ...props,
2692
- className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge19(
3508
+ className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge23(
2693
3509
  // Base layout
2694
3510
  "inline-flex items-center justify-center",
2695
3511
  "rounded-md",
@@ -2700,7 +3516,7 @@ function SegmentedControlItem({
2700
3516
  // Disabled
2701
3517
  isDisabled && "opacity-50 pointer-events-none",
2702
3518
  // Size
2703
- sizeStyles5[size],
3519
+ sizeStyles6[size],
2704
3520
  // Selected state
2705
3521
  isSelected ? "bg-background text-foreground shadow-sm font-semibold" : isPressed ? "bg-card text-foreground" : isHovered ? "bg-card text-foreground" : "bg-transparent text-muted-foreground",
2706
3522
  className
@@ -2709,67 +3525,11 @@ function SegmentedControlItem({
2709
3525
  );
2710
3526
  }
2711
3527
 
2712
- // src/components/Badge/Badge.tsx
2713
- import { twMerge as twMerge21 } from "tailwind-merge";
2714
-
2715
- // src/components/MetricText/MetricText.tsx
2716
- import { twMerge as twMerge20 } from "tailwind-merge";
2717
- import { jsx as jsx39 } from "react/jsx-runtime";
2718
- function MetricText({ className, ...rest }) {
2719
- const cx = twMerge20(
2720
- "text-xs font-medium leading-none tracking-wider tabular-nums",
2721
- className
2722
- );
2723
- return /* @__PURE__ */ jsx39("span", { className: cx, ...rest });
2724
- }
2725
-
2726
- // src/components/Badge/Badge.tsx
2727
- import { jsx as jsx40, jsxs as jsxs23 } from "react/jsx-runtime";
2728
- var colorStyles = {
2729
- purple: "bg-badge-purple-bg text-badge-purple-text border-badge-purple-text/20",
2730
- teal: "bg-badge-teal-bg text-badge-teal-text border-badge-teal-text/20",
2731
- rose: "bg-badge-rose-bg text-badge-rose-text border-badge-rose-text/20",
2732
- slate: "bg-badge-slate-bg text-badge-slate-text border-badge-slate-text/20",
2733
- green: "bg-badge-green-bg text-badge-green-text border-badge-green-text/20",
2734
- amber: "bg-badge-amber-bg text-badge-amber-text border-badge-amber-text/20"
2735
- };
2736
- var sizeStyles6 = {
2737
- xs: "px-1 py-0 text-[10px]",
2738
- sm: "px-1.5 py-0.5 text-xs",
2739
- md: "px-2 py-0.5 text-xs",
2740
- lg: "px-2.5 py-1 text-sm"
2741
- };
2742
- function Badge({
2743
- children,
2744
- color = "slate",
2745
- size = "sm",
2746
- icon,
2747
- className,
2748
- ...rest
2749
- }) {
2750
- return /* @__PURE__ */ jsxs23(
2751
- MetricText,
2752
- {
2753
- className: twMerge21(
2754
- "inline-flex items-center gap-1 rounded-full border",
2755
- colorStyles[color],
2756
- sizeStyles6[size],
2757
- className
2758
- ),
2759
- ...rest,
2760
- children: [
2761
- icon && /* @__PURE__ */ jsx40(Icon, { icon, size: "xs" }),
2762
- children
2763
- ]
2764
- }
2765
- );
2766
- }
2767
-
2768
3528
  // src/components/Card/Card.tsx
2769
- import { twMerge as twMerge22 } from "tailwind-merge";
2770
- import { jsx as jsx41, jsxs as jsxs24 } from "react/jsx-runtime";
3529
+ import { twMerge as twMerge24 } from "tailwind-merge";
3530
+ import { jsx as jsx50, jsxs as jsxs30 } from "react/jsx-runtime";
2771
3531
  function Card({ children, header, footer, className }) {
2772
- const cx = twMerge22(
3532
+ const cx = twMerge24(
2773
3533
  `
2774
3534
  bg-card p-8
2775
3535
  border border-border
@@ -2778,17 +3538,17 @@ function Card({ children, header, footer, className }) {
2778
3538
  `,
2779
3539
  className
2780
3540
  );
2781
- return /* @__PURE__ */ jsxs24("div", { className: cx, children: [
2782
- header && /* @__PURE__ */ jsx41("div", { className: "border-b border-border", children: header }),
3541
+ return /* @__PURE__ */ jsxs30("div", { className: cx, children: [
3542
+ header && /* @__PURE__ */ jsx50("div", { className: "border-b border-border", children: header }),
2783
3543
  children,
2784
- footer && /* @__PURE__ */ jsx41("div", { className: "border-t border-border", children: footer })
3544
+ footer && /* @__PURE__ */ jsx50("div", { className: "border-t border-border", children: footer })
2785
3545
  ] });
2786
3546
  }
2787
3547
 
2788
3548
  // src/components/DeltaIndicator/DeltaIndicator.tsx
2789
3549
  import { ArrowUp as ArrowUp2, ArrowDown as ArrowDown2, Minus as Minus2 } from "lucide-react";
2790
- import { twMerge as twMerge23 } from "tailwind-merge";
2791
- import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
3550
+ import { twMerge as twMerge25 } from "tailwind-merge";
3551
+ import { jsx as jsx51, jsxs as jsxs31 } from "react/jsx-runtime";
2792
3552
  function getDirection(current, previous) {
2793
3553
  const diff = current - previous;
2794
3554
  if (diff > 0) return "increase";
@@ -2841,16 +3601,16 @@ function DeltaIndicator({
2841
3601
  className
2842
3602
  }) {
2843
3603
  if (unavailable) {
2844
- return /* @__PURE__ */ jsxs25(
3604
+ return /* @__PURE__ */ jsxs31(
2845
3605
  "span",
2846
3606
  {
2847
- className: twMerge23(
3607
+ className: twMerge25(
2848
3608
  "inline-flex items-center gap-1 font-medium",
2849
3609
  "text-muted-foreground",
2850
3610
  className
2851
3611
  ),
2852
3612
  children: [
2853
- label && /* @__PURE__ */ jsx42("span", { className: "text-sm text-muted-foreground mr-1", children: label }),
3613
+ label && /* @__PURE__ */ jsx51("span", { className: "text-sm text-muted-foreground mr-1", children: label }),
2854
3614
  unavailableText
2855
3615
  ]
2856
3616
  }
@@ -2880,10 +3640,10 @@ function DeltaIndicator({
2880
3640
  }
2881
3641
  }
2882
3642
  const isPill = mode === "pill";
2883
- return /* @__PURE__ */ jsxs25(
3643
+ return /* @__PURE__ */ jsxs31(
2884
3644
  "span",
2885
3645
  {
2886
- className: twMerge23(
3646
+ className: twMerge25(
2887
3647
  "inline-flex items-center gap-1 font-medium",
2888
3648
  colorStyles2,
2889
3649
  isPill && [
@@ -2894,8 +3654,8 @@ function DeltaIndicator({
2894
3654
  className
2895
3655
  ),
2896
3656
  children: [
2897
- label && /* @__PURE__ */ jsx42("span", { className: "text-sm text-muted-foreground mr-1", children: label }),
2898
- /* @__PURE__ */ jsx42(IconComponent, { size: 14, "aria-hidden": true }),
3657
+ label && /* @__PURE__ */ jsx51("span", { className: "text-sm text-muted-foreground mr-1", children: label }),
3658
+ /* @__PURE__ */ jsx51(IconComponent, { size: 14, "aria-hidden": true }),
2899
3659
  valueText
2900
3660
  ]
2901
3661
  }
@@ -2903,8 +3663,8 @@ function DeltaIndicator({
2903
3663
  }
2904
3664
 
2905
3665
  // src/components/ProgressBar/ProgressBar.tsx
2906
- import { twMerge as twMerge24 } from "tailwind-merge";
2907
- import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
3666
+ import { twMerge as twMerge26 } from "tailwind-merge";
3667
+ import { jsx as jsx52, jsxs as jsxs32 } from "react/jsx-runtime";
2908
3668
  var fillStyles = {
2909
3669
  brand: "bg-progress-fill",
2910
3670
  success: "bg-progress-fill-success",
@@ -2927,12 +3687,12 @@ function ProgressBar({
2927
3687
  className
2928
3688
  }) {
2929
3689
  const clampedValue = Math.min(100, Math.max(0, value));
2930
- return /* @__PURE__ */ jsxs26("div", { className: twMerge24("w-full", className), children: [
2931
- (label || description || showValue) && /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between mb-2", children: [
2932
- /* @__PURE__ */ jsx43("span", { className: "text-sm font-medium text-foreground", children: label }),
2933
- /* @__PURE__ */ jsx43("span", { className: "text-sm text-muted-foreground", children: description ?? (showValue ? `${clampedValue}%` : null) })
3690
+ return /* @__PURE__ */ jsxs32("div", { className: twMerge26("w-full", className), children: [
3691
+ (label || description || showValue) && /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between mb-2", children: [
3692
+ /* @__PURE__ */ jsx52("span", { className: "text-sm font-medium text-foreground", children: label }),
3693
+ /* @__PURE__ */ jsx52("span", { className: "text-sm text-muted-foreground", children: description ?? (showValue ? `${clampedValue}%` : null) })
2934
3694
  ] }),
2935
- /* @__PURE__ */ jsx43(
3695
+ /* @__PURE__ */ jsx52(
2936
3696
  "div",
2937
3697
  {
2938
3698
  role: "progressbar",
@@ -2940,14 +3700,14 @@ function ProgressBar({
2940
3700
  "aria-valuemin": 0,
2941
3701
  "aria-valuemax": 100,
2942
3702
  "aria-label": label ?? "Progress",
2943
- className: twMerge24(
3703
+ className: twMerge26(
2944
3704
  "w-full rounded-full bg-progress-track",
2945
3705
  sizeStyles7[size]
2946
3706
  ),
2947
- children: /* @__PURE__ */ jsx43(
3707
+ children: /* @__PURE__ */ jsx52(
2948
3708
  "div",
2949
3709
  {
2950
- className: twMerge24(
3710
+ className: twMerge26(
2951
3711
  "h-full rounded-full transition-all duration-300",
2952
3712
  fillStyles[variant]
2953
3713
  ),
@@ -2967,8 +3727,8 @@ import {
2967
3727
  AlertCircle as AlertCircle2,
2968
3728
  CheckCircle2 as CheckCircle22
2969
3729
  } from "lucide-react";
2970
- import { twMerge as twMerge25 } from "tailwind-merge";
2971
- import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
3730
+ import { twMerge as twMerge27 } from "tailwind-merge";
3731
+ import { jsx as jsx53, jsxs as jsxs33 } from "react/jsx-runtime";
2972
3732
  var variantConfig2 = {
2973
3733
  info: {
2974
3734
  icon: Info3,
@@ -3012,40 +3772,40 @@ function Banner({
3012
3772
  setDismissed(true);
3013
3773
  onDismiss?.();
3014
3774
  };
3015
- return /* @__PURE__ */ jsxs27(
3775
+ return /* @__PURE__ */ jsxs33(
3016
3776
  "div",
3017
3777
  {
3018
3778
  role: config.role,
3019
- className: twMerge25(
3779
+ className: twMerge27(
3020
3780
  "flex items-start gap-3 rounded-lg border px-4 py-3",
3021
3781
  "text-sm",
3022
3782
  config.containerClass,
3023
3783
  className
3024
3784
  ),
3025
3785
  children: [
3026
- /* @__PURE__ */ jsx44(
3786
+ /* @__PURE__ */ jsx53(
3027
3787
  Icon,
3028
3788
  {
3029
3789
  icon: resolvedIcon,
3030
3790
  size: "md",
3031
- className: twMerge25("mt-0.5", config.iconClass)
3791
+ className: twMerge27("mt-0.5", config.iconClass)
3032
3792
  }
3033
3793
  ),
3034
- /* @__PURE__ */ jsxs27("div", { className: "flex-1", children: [
3035
- title && /* @__PURE__ */ jsxs27("span", { className: "font-medium", children: [
3794
+ /* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
3795
+ title && /* @__PURE__ */ jsxs33("span", { className: "font-medium", children: [
3036
3796
  title,
3037
3797
  " \u2014 "
3038
3798
  ] }),
3039
3799
  children
3040
3800
  ] }),
3041
- dismissible && /* @__PURE__ */ jsx44(
3801
+ dismissible && /* @__PURE__ */ jsx53(
3042
3802
  "button",
3043
3803
  {
3044
3804
  type: "button",
3045
3805
  onClick: handleDismiss,
3046
3806
  className: "shrink-0 rounded-sm p-0.5 opacity-70 hover:opacity-100 transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-current",
3047
3807
  "aria-label": "Dismiss",
3048
- children: /* @__PURE__ */ jsx44(Icon, { icon: "X", size: "sm" })
3808
+ children: /* @__PURE__ */ jsx53(Icon, { icon: "X", size: "sm" })
3049
3809
  }
3050
3810
  )
3051
3811
  ]
@@ -3054,8 +3814,8 @@ function Banner({
3054
3814
  }
3055
3815
 
3056
3816
  // src/components/MetricCard/MetricCard.tsx
3057
- import { twMerge as twMerge26 } from "tailwind-merge";
3058
- import { Fragment as Fragment8, jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
3817
+ import { twMerge as twMerge28 } from "tailwind-merge";
3818
+ import { Fragment as Fragment11, jsx as jsx54, jsxs as jsxs34 } from "react/jsx-runtime";
3059
3819
  var sizeConfig = {
3060
3820
  sm: {
3061
3821
  padding: "p-3",
@@ -3077,50 +3837,50 @@ function MetricCard({
3077
3837
  className
3078
3838
  }) {
3079
3839
  const config = sizeConfig[size];
3080
- const containerClass = twMerge26(
3840
+ const containerClass = twMerge28(
3081
3841
  "bg-background border border-border rounded-lg shadow-sm",
3082
3842
  config.padding,
3083
3843
  href && "block transition-shadow hover:shadow-md hover:border-ring focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 outline-none",
3084
3844
  className
3085
3845
  );
3086
- const content = /* @__PURE__ */ jsxs28(Fragment8, { children: [
3087
- /* @__PURE__ */ jsx45("div", { className: twMerge26(config.labelClass, "text-muted-foreground"), children: label }),
3088
- /* @__PURE__ */ jsx45(
3846
+ const content = /* @__PURE__ */ jsxs34(Fragment11, { children: [
3847
+ /* @__PURE__ */ jsx54("div", { className: twMerge28(config.labelClass, "text-muted-foreground"), children: label }),
3848
+ /* @__PURE__ */ jsx54(
3089
3849
  "div",
3090
3850
  {
3091
- className: twMerge26(
3851
+ className: twMerge28(
3092
3852
  config.valueClass,
3093
3853
  "font-semibold text-foreground mt-1 tabular-nums"
3094
3854
  ),
3095
3855
  children: value
3096
3856
  }
3097
3857
  ),
3098
- secondary && /* @__PURE__ */ jsx45("div", { className: "mt-1 text-sm", children: secondary })
3858
+ secondary && /* @__PURE__ */ jsx54("div", { className: "mt-1 text-sm", children: secondary })
3099
3859
  ] });
3100
3860
  if (href) {
3101
- return /* @__PURE__ */ jsx45("a", { href, className: containerClass, children: content });
3861
+ return /* @__PURE__ */ jsx54("a", { href, className: containerClass, children: content });
3102
3862
  }
3103
- return /* @__PURE__ */ jsx45("div", { className: containerClass, children: content });
3863
+ return /* @__PURE__ */ jsx54("div", { className: containerClass, children: content });
3104
3864
  }
3105
3865
 
3106
3866
  // src/components/SectionHeader/SectionHeader.tsx
3107
3867
  import { forwardRef as forwardRef7 } from "react";
3108
- import { twMerge as twMerge27 } from "tailwind-merge";
3109
- import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
3868
+ import { twMerge as twMerge29 } from "tailwind-merge";
3869
+ import { jsx as jsx55, jsxs as jsxs35 } from "react/jsx-runtime";
3110
3870
  var SectionHeader = forwardRef7(
3111
3871
  function SectionHeader2({ title, as = "h2", children, className, ...rest }, ref) {
3112
- return /* @__PURE__ */ jsxs29(
3872
+ return /* @__PURE__ */ jsxs35(
3113
3873
  "div",
3114
3874
  {
3115
3875
  ref,
3116
- className: twMerge27(
3876
+ className: twMerge29(
3117
3877
  "flex flex-wrap items-center gap-3 pt-0 pb-4",
3118
3878
  className
3119
3879
  ),
3120
3880
  ...rest,
3121
3881
  children: [
3122
- /* @__PURE__ */ jsx46(Heading, { as, children: title }),
3123
- children && /* @__PURE__ */ jsx46("div", { className: "ml-auto flex flex-wrap items-center gap-2", children })
3882
+ /* @__PURE__ */ jsx55(Heading, { as, children: title }),
3883
+ children && /* @__PURE__ */ jsx55("div", { className: "ml-auto flex flex-wrap items-center gap-2", children })
3124
3884
  ]
3125
3885
  }
3126
3886
  );
@@ -3130,7 +3890,7 @@ var SectionHeader = forwardRef7(
3130
3890
  // src/components/DescriptionList/DescriptionList.tsx
3131
3891
  import { createContext as createContext4, useContext as useContext4 } from "react";
3132
3892
  import { Button as AriaButton4 } from "react-aria-components";
3133
- import { jsx as jsx47, jsxs as jsxs30 } from "react/jsx-runtime";
3893
+ import { jsx as jsx56, jsxs as jsxs36 } from "react/jsx-runtime";
3134
3894
  var LayoutContext = createContext4("stacked");
3135
3895
  var listGapStyles = {
3136
3896
  stacked: "gap-4",
@@ -3141,7 +3901,7 @@ function DescriptionList({
3141
3901
  layout = "stacked",
3142
3902
  className
3143
3903
  }) {
3144
- return /* @__PURE__ */ jsx47(LayoutContext.Provider, { value: layout, children: /* @__PURE__ */ jsx47(
3904
+ return /* @__PURE__ */ jsx56(LayoutContext.Provider, { value: layout, children: /* @__PURE__ */ jsx56(
3145
3905
  "dl",
3146
3906
  {
3147
3907
  className: ["flex flex-col", listGapStyles[layout], className].filter(Boolean).join(" "),
@@ -3165,17 +3925,17 @@ function DescriptionListItem({
3165
3925
  "text-sm m-0",
3166
3926
  muted ? "text-muted-foreground" : "text-foreground"
3167
3927
  ].join(" ");
3168
- const valueContent = /* @__PURE__ */ jsx47("dd", { className: valueClasses, children });
3169
- return /* @__PURE__ */ jsxs30("div", { className: itemLayoutStyles[layout], children: [
3170
- /* @__PURE__ */ jsx47("dt", { className: labelClasses, children: label }),
3171
- fullValue ? /* @__PURE__ */ jsx47(Tooltip, { content: fullValue, children: /* @__PURE__ */ jsx47(AriaButton4, { className: "text-left outline-none cursor-default", children: valueContent }) }) : valueContent
3928
+ const valueContent = /* @__PURE__ */ jsx56("dd", { className: valueClasses, children });
3929
+ return /* @__PURE__ */ jsxs36("div", { className: itemLayoutStyles[layout], children: [
3930
+ /* @__PURE__ */ jsx56("dt", { className: labelClasses, children: label }),
3931
+ fullValue ? /* @__PURE__ */ jsx56(Tooltip, { content: fullValue, children: /* @__PURE__ */ jsx56(AriaButton4, { className: "text-left outline-none cursor-default", children: valueContent }) }) : valueContent
3172
3932
  ] });
3173
3933
  }
3174
3934
  DescriptionList.Item = DescriptionListItem;
3175
3935
 
3176
3936
  // src/components/PathPill/PathPill.tsx
3177
- import { twMerge as twMerge28 } from "tailwind-merge";
3178
- import { jsx as jsx48 } from "react/jsx-runtime";
3937
+ import { twMerge as twMerge30 } from "tailwind-merge";
3938
+ import { jsx as jsx57 } from "react/jsx-runtime";
3179
3939
  var hashColors = [
3180
3940
  "purple",
3181
3941
  "teal",
@@ -3201,17 +3961,17 @@ function PathPill({
3201
3961
  const effectiveVisible = visibleCount ?? segments.length;
3202
3962
  const dotCount = Math.max(0, segments.length - effectiveVisible);
3203
3963
  const fullPath = segments.join(" / ");
3204
- return /* @__PURE__ */ jsx48(
3964
+ return /* @__PURE__ */ jsx57(
3205
3965
  "div",
3206
3966
  {
3207
- className: twMerge28("relative flex", className),
3967
+ className: twMerge30("relative flex", className),
3208
3968
  "aria-label": `Path: ${fullPath}`,
3209
3969
  children: segments.map((segment, i) => {
3210
3970
  const isCollapsed = i < dotCount;
3211
3971
  const isLast = i === segments.length - 1;
3212
- const cx = twMerge28(!isLast && "pr-5 -mr-4", isCollapsed && "pr-3");
3972
+ const cx = twMerge30(!isLast && "pr-5 -mr-4", isCollapsed && "pr-3");
3213
3973
  const color = colorFn ? colorFn(segment, i) : pillColorFromName(segment);
3214
- return /* @__PURE__ */ jsx48(
3974
+ return /* @__PURE__ */ jsx57(
3215
3975
  Badge,
3216
3976
  {
3217
3977
  className: cx,
@@ -3227,8 +3987,8 @@ function PathPill({
3227
3987
  }
3228
3988
 
3229
3989
  // src/components/FormWizard/FormWizard.tsx
3230
- import { createContext as createContext5, useContext as useContext5, useCallback as useCallback4, useMemo } from "react";
3231
- import { jsx as jsx49 } from "react/jsx-runtime";
3990
+ import { createContext as createContext5, useContext as useContext5, useCallback as useCallback10, useMemo as useMemo5 } from "react";
3991
+ import { jsx as jsx58 } from "react/jsx-runtime";
3232
3992
  var FormWizardContext = createContext5({
3233
3993
  currentStep: 0,
3234
3994
  totalSteps: 1,
@@ -3248,12 +4008,12 @@ function FormWizard({
3248
4008
  }) {
3249
4009
  const canGoBack = currentStep > 0;
3250
4010
  const isLastStep = currentStep >= totalSteps - 1;
3251
- const goBack = useCallback4(() => {
4011
+ const goBack = useCallback10(() => {
3252
4012
  if (currentStep > 0) {
3253
4013
  onStepChange(currentStep - 1);
3254
4014
  }
3255
4015
  }, [currentStep, onStepChange]);
3256
- const value = useMemo(
4016
+ const value = useMemo5(
3257
4017
  () => ({
3258
4018
  currentStep,
3259
4019
  totalSteps,
@@ -3263,13 +4023,13 @@ function FormWizard({
3263
4023
  }),
3264
4024
  [currentStep, totalSteps, canGoBack, goBack, isLastStep]
3265
4025
  );
3266
- return /* @__PURE__ */ jsx49(FormWizardContext.Provider, { value, children });
4026
+ return /* @__PURE__ */ jsx58(FormWizardContext.Provider, { value, children });
3267
4027
  }
3268
4028
 
3269
4029
  // src/components/FormWizard/FormWizardProgress.tsx
3270
- import { jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
4030
+ import { jsx as jsx59, jsxs as jsxs37 } from "react/jsx-runtime";
3271
4031
  function CheckIcon() {
3272
- return /* @__PURE__ */ jsx50(
4032
+ return /* @__PURE__ */ jsx59(
3273
4033
  "svg",
3274
4034
  {
3275
4035
  "aria-hidden": "true",
@@ -3280,24 +4040,24 @@ function CheckIcon() {
3280
4040
  strokeWidth: "2",
3281
4041
  strokeLinecap: "round",
3282
4042
  strokeLinejoin: "round",
3283
- children: /* @__PURE__ */ jsx50("path", { d: "M3 8.5l3.5 3.5 6.5-7" })
4043
+ children: /* @__PURE__ */ jsx59("path", { d: "M3 8.5l3.5 3.5 6.5-7" })
3284
4044
  }
3285
4045
  );
3286
4046
  }
3287
4047
  function FormWizardProgress({ labels }) {
3288
4048
  const { currentStep, totalSteps } = useFormWizard();
3289
- return /* @__PURE__ */ jsx50("nav", { "aria-label": "Form progress", children: /* @__PURE__ */ jsx50("ol", { className: "flex items-start", role: "list", children: labels.map((label, index) => {
4049
+ return /* @__PURE__ */ jsx59("nav", { "aria-label": "Form progress", children: /* @__PURE__ */ jsx59("ol", { className: "flex items-start", role: "list", children: labels.map((label, index) => {
3290
4050
  const isCompleted = index < currentStep;
3291
4051
  const isCurrent = index === currentStep;
3292
4052
  const isFuture = index > currentStep;
3293
- return /* @__PURE__ */ jsxs31(
4053
+ return /* @__PURE__ */ jsxs37(
3294
4054
  "li",
3295
4055
  {
3296
4056
  className: "flex flex-1 flex-col items-center",
3297
4057
  "aria-current": isCurrent ? "step" : void 0,
3298
4058
  children: [
3299
- /* @__PURE__ */ jsxs31("div", { className: "flex w-full items-center", children: [
3300
- index > 0 ? /* @__PURE__ */ jsx50(
4059
+ /* @__PURE__ */ jsxs37("div", { className: "flex w-full items-center", children: [
4060
+ index > 0 ? /* @__PURE__ */ jsx59(
3301
4061
  "div",
3302
4062
  {
3303
4063
  "aria-hidden": "true",
@@ -3306,8 +4066,8 @@ function FormWizardProgress({ labels }) {
3306
4066
  index <= currentStep ? "bg-primary" : "bg-border"
3307
4067
  ].join(" ")
3308
4068
  }
3309
- ) : /* @__PURE__ */ jsx50("div", { className: "flex-1", "aria-hidden": "true" }),
3310
- /* @__PURE__ */ jsx50(
4069
+ ) : /* @__PURE__ */ jsx59("div", { className: "flex-1", "aria-hidden": "true" }),
4070
+ /* @__PURE__ */ jsx59(
3311
4071
  "div",
3312
4072
  {
3313
4073
  className: [
@@ -3319,10 +4079,10 @@ function FormWizardProgress({ labels }) {
3319
4079
  isFuture ? "border-2 border-border bg-background text-muted-foreground" : ""
3320
4080
  ].join(" "),
3321
4081
  "aria-hidden": "true",
3322
- children: isCompleted ? /* @__PURE__ */ jsx50(CheckIcon, {}) : index + 1
4082
+ children: isCompleted ? /* @__PURE__ */ jsx59(CheckIcon, {}) : index + 1
3323
4083
  }
3324
4084
  ),
3325
- index < totalSteps - 1 ? /* @__PURE__ */ jsx50(
4085
+ index < totalSteps - 1 ? /* @__PURE__ */ jsx59(
3326
4086
  "div",
3327
4087
  {
3328
4088
  "aria-hidden": "true",
@@ -3331,9 +4091,9 @@ function FormWizardProgress({ labels }) {
3331
4091
  index < currentStep ? "bg-primary" : "bg-border"
3332
4092
  ].join(" ")
3333
4093
  }
3334
- ) : /* @__PURE__ */ jsx50("div", { className: "flex-1", "aria-hidden": "true" })
4094
+ ) : /* @__PURE__ */ jsx59("div", { className: "flex-1", "aria-hidden": "true" })
3335
4095
  ] }),
3336
- /* @__PURE__ */ jsx50(
4096
+ /* @__PURE__ */ jsx59(
3337
4097
  "span",
3338
4098
  {
3339
4099
  className: [
@@ -3351,15 +4111,15 @@ function FormWizardProgress({ labels }) {
3351
4111
  }
3352
4112
 
3353
4113
  // src/components/FormWizard/FormWizardNav.tsx
3354
- import { jsx as jsx51, jsxs as jsxs32 } from "react/jsx-runtime";
4114
+ import { jsx as jsx60, jsxs as jsxs38 } from "react/jsx-runtime";
3355
4115
  function FormWizardNav({
3356
4116
  onNext,
3357
4117
  isSubmitting = false,
3358
4118
  submitLabel = "Submit"
3359
4119
  }) {
3360
4120
  const { canGoBack, goBack, isLastStep } = useFormWizard();
3361
- return /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-end gap-3", children: [
3362
- canGoBack && /* @__PURE__ */ jsx51(
4121
+ return /* @__PURE__ */ jsxs38("div", { className: "flex items-center justify-end gap-3", children: [
4122
+ canGoBack && /* @__PURE__ */ jsx60(
3363
4123
  Button,
3364
4124
  {
3365
4125
  variant: "secondary",
@@ -3369,7 +4129,7 @@ function FormWizardNav({
3369
4129
  children: "Back"
3370
4130
  }
3371
4131
  ),
3372
- /* @__PURE__ */ jsx51(
4132
+ /* @__PURE__ */ jsx60(
3373
4133
  Button,
3374
4134
  {
3375
4135
  variant: "primary",
@@ -3388,9 +4148,7 @@ export {
3388
4148
  Button,
3389
4149
  ButtonLink,
3390
4150
  Card,
3391
- Cell,
3392
4151
  Checkbox,
3393
- Column,
3394
4152
  DeltaIndicator,
3395
4153
  Description,
3396
4154
  DescriptionList,
@@ -3415,6 +4173,8 @@ export {
3415
4173
  InputPassword,
3416
4174
  Label,
3417
4175
  Link,
4176
+ ListBox2 as ListBox,
4177
+ ListBoxItem2 as ListBoxItem,
3418
4178
  Logo,
3419
4179
  Menu2 as Menu,
3420
4180
  MenuCheckboxItem,
@@ -3424,6 +4184,7 @@ export {
3424
4184
  MenuSeparator,
3425
4185
  MetricCard,
3426
4186
  MetricText,
4187
+ NoFilterResults,
3427
4188
  PathPill,
3428
4189
  Popover4 as Popover,
3429
4190
  PopoverContent,
@@ -3434,19 +4195,18 @@ export {
3434
4195
  RadioButton,
3435
4196
  RadioGroup,
3436
4197
  RouterProvider,
3437
- Row,
3438
4198
  SectionHeader,
3439
4199
  SegmentedControl,
3440
4200
  SegmentedControlItem,
3441
4201
  Select,
4202
+ SelectionFooter,
4203
+ Slider,
3442
4204
  Spinner,
3443
4205
  Switch,
3444
4206
  Tab,
3445
4207
  TabList,
3446
4208
  TabPanel,
3447
4209
  Table2 as Table,
3448
- TableBody,
3449
- TableHeader,
3450
4210
  Tabs,
3451
4211
  ToastProvider,
3452
4212
  ToggleButton,
@@ -3458,11 +4218,17 @@ export {
3458
4218
  Tabs2 as UnstyledTabs,
3459
4219
  buttonBaseClass,
3460
4220
  createToastBridge,
4221
+ getTableStore,
3461
4222
  iconRegistry,
3462
4223
  pillColorFromName,
3463
4224
  selectedStyles,
4225
+ useColumnFilters,
4226
+ useColumnVisibility,
4227
+ useColumnWidths,
3464
4228
  useContextMenu,
3465
4229
  useFormWizard,
4230
+ useTableSorting,
4231
+ useTableStore,
3466
4232
  useToast,
3467
4233
  variantStyles
3468
4234
  };