@cytario/design 9.7.0 → 10.0.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,1135 +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
- )
2422
+ });
2423
+ },
2424
+ [store, columns, setColumnWidth]
2425
+ );
2426
+ const resetWidths = useCallback6(() => {
2427
+ reset();
2428
+ }, [reset]);
2429
+ return { columnSizing, setColumnSizing, resetWidths };
2430
+ }
2431
+
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]
2448
+ );
2449
+ return { sorting, setSorting };
2450
+ }
2451
+
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
2471
+ }) {
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",
2618
+ {
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
+ ] })
1929
2635
  }
1930
2636
  );
1931
2637
  }
1932
2638
 
1933
- // src/components/Form/Slider/Slider.tsx
2639
+ // src/components/Dialog/Dialog.tsx
1934
2640
  import {
1935
- Slider as AriaSlider,
1936
- SliderTrack,
1937
- SliderFill,
1938
- SliderThumb
2641
+ Modal,
2642
+ ModalOverlay,
2643
+ Dialog as AriaDialog,
2644
+ Heading as Heading3
1939
2645
  } from "react-aria-components";
1940
- import { twMerge as twMerge14 } from "tailwind-merge";
1941
- import { Fragment as Fragment6, jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
1942
- function Slider({
1943
- label,
1944
- output,
1945
- description,
1946
- errorMessage,
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,
1947
2660
  children,
1948
- className,
1949
- isDisabled,
1950
- ...props
2661
+ className
1951
2662
  }) {
1952
- return /* @__PURE__ */ jsx25(
1953
- AriaSlider,
2663
+ return /* @__PURE__ */ jsx37(
2664
+ ModalOverlay,
1954
2665
  {
1955
- ...props,
1956
- isDisabled,
1957
- className: twMerge14(
1958
- // data-disabled lands on the root (tailwindcss-react-aria-components
1959
- // maps the disabled: variant onto it).
1960
- "w-full flex flex-col gap-2 disabled:opacity-50 disabled:cursor-default",
1961
- className
1962
- ),
1963
- children: ({ state }) => /* @__PURE__ */ jsxs16(Fragment6, { children: [
1964
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
1965
- label && /* @__PURE__ */ jsx25(Label, { children: label }),
1966
- output && /* @__PURE__ */ jsx25("span", { className: "text-sm font-medium text-foreground tabular-nums", children: output(state.values[0]) })
1967
- ] }),
1968
- /* @__PURE__ */ jsxs16(SliderTrack, { className: "flex h-6 w-full cursor-pointer items-center", children: [
1969
- /* @__PURE__ */ jsx25("div", { className: "relative h-1.5 w-full overflow-hidden rounded-full bg-border", children: /* @__PURE__ */ jsx25(SliderFill, { className: "h-full rounded-full bg-primary" }) }),
1970
- /* @__PURE__ */ jsx25(
1971
- SliderThumb,
1972
- {
1973
- className: twMerge14(
1974
- "top-1/2 h-4 w-4 rounded-full bg-background",
1975
- "border-2 border-primary",
1976
- "shadow-sm",
1977
- "transition-[box-shadow,border-color]",
1978
- "hovered:border-primary-hover",
1979
- "dragging:cursor-grabbing",
1980
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
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,
2677
+ {
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
+ }
1981
2710
  )
1982
- }
1983
- )
1984
- ] }),
1985
- (description || errorMessage) && /* @__PURE__ */ jsx25(
1986
- "p",
1987
- {
1988
- className: twMerge14(
1989
- "text-xs text-muted-foreground",
1990
- errorMessage && "text-destructive"
1991
- ),
1992
- children: errorMessage ?? description
1993
- }
1994
- ),
1995
- children
1996
- ] })
2711
+ ] }),
2712
+ /* @__PURE__ */ jsx37("div", { className: "px-6 py-4 overflow-y-auto", children })
2713
+ ] }) })
2714
+ }
2715
+ )
1997
2716
  }
1998
2717
  );
1999
2718
  }
2000
2719
 
2001
- // src/components/Form/Fieldset/Fieldset.tsx
2002
- import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
2003
- function Fieldset({ legend, children, className }) {
2004
- return /* @__PURE__ */ jsxs17(
2005
- "fieldset",
2720
+ // src/components/Dialog/DialogFooter.tsx
2721
+ import { jsx as jsx38 } from "react/jsx-runtime";
2722
+
2723
+ // src/components/Toast/Toast.tsx
2724
+ import {
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
2741
+ };
2742
+ var variantConfig = {
2743
+ success: {
2744
+ icon: CheckCircle3,
2745
+ containerClass: "bg-success-surface border-success-border text-success",
2746
+ iconClass: "text-success"
2747
+ },
2748
+ error: {
2749
+ icon: XCircle2,
2750
+ containerClass: "bg-destructive-surface border-destructive-border text-destructive",
2751
+ iconClass: "text-destructive"
2752
+ },
2753
+ info: {
2754
+ icon: Info2,
2755
+ containerClass: "bg-info-surface border-info-border text-info",
2756
+ iconClass: "text-info"
2757
+ }
2758
+ };
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
2775
+ }) {
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",
2006
2794
  {
2795
+ role: "status",
2796
+ "aria-live": "polite",
2007
2797
  className: [
2008
- "flex flex-col gap-8",
2009
- "border-none p-0 m-0",
2010
- className
2011
- ].filter(Boolean).join(" "),
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(" "),
2012
2804
  children: [
2013
- legend && /* @__PURE__ */ jsx26(
2014
- "legend",
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",
2015
2809
  {
2016
- className: [
2017
- "text-lg",
2018
- "font-semibold",
2019
- "text-foreground",
2020
- "p-0"
2021
- ].join(" "),
2022
- children: legend
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" })
2023
2815
  }
2024
- ),
2025
- children
2816
+ )
2026
2817
  ]
2027
2818
  }
2028
2819
  );
2029
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
+ }
2030
2881
 
2031
- // src/components/Link/Link.tsx
2882
+ // src/components/Form/Switch/Switch.tsx
2032
2883
  import {
2033
- Link as AriaLink3
2884
+ SwitchField,
2885
+ SwitchButton
2034
2886
  } from "react-aria-components";
2035
- import { jsx as jsx27 } from "react/jsx-runtime";
2036
- var variantStyles2 = {
2037
- default: [
2038
- "text-teal-700 underline",
2039
- "hover:text-teal-800"
2040
- ].join(" "),
2041
- subtle: [
2042
- "text-muted-foreground no-underline",
2043
- "hover:underline hover:text-foreground"
2044
- ].join(" ")
2045
- };
2046
- function Link({
2047
- variant = "default",
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({
2890
+ children,
2891
+ color = "var(--color-primary)",
2048
2892
  className,
2049
2893
  ...props
2050
2894
  }) {
2051
- return /* @__PURE__ */ jsx27(
2052
- AriaLink3,
2053
- {
2054
- ...props,
2055
- className: [
2056
- "outline-none transition-colors",
2057
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
2058
- variantStyles2[variant],
2059
- className
2060
- ].filter(Boolean).join(" ")
2061
- }
2062
- );
2063
- }
2064
-
2065
- // src/components/Breadcrumbs/Breadcrumbs.tsx
2066
- import {
2067
- Breadcrumbs as AriaBreadcrumbs,
2068
- Breadcrumb as AriaBreadcrumb,
2069
- Link as Link2
2070
- } from "react-aria-components";
2071
- import { ChevronRight as ChevronRight2 } from "lucide-react";
2072
- import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
2073
- function Breadcrumbs({ items, className }) {
2074
- return /* @__PURE__ */ jsx28(
2075
- "nav",
2076
- {
2077
- "aria-label": "Breadcrumb",
2078
- className,
2079
- children: /* @__PURE__ */ jsx28(
2080
- AriaBreadcrumbs,
2081
- {
2082
- className: "flex items-center gap-1 text-sm min-w-0",
2083
- children: items.map((item, index) => {
2084
- const isLast = index === items.length - 1;
2085
- return /* @__PURE__ */ jsx28(
2086
- AriaBreadcrumb,
2087
- {
2088
- id: item.id,
2089
- className: [
2090
- "flex items-center gap-1",
2091
- isLast ? "min-w-0" : "shrink-0"
2092
- ].join(" "),
2093
- children: isLast ? /* @__PURE__ */ jsx28("span", { className: "font-medium text-foreground truncate", children: item.label }) : /* @__PURE__ */ jsxs18(Fragment7, { children: [
2094
- /* @__PURE__ */ jsx28(
2095
- Link2,
2096
- {
2097
- href: item.href,
2098
- 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",
2099
- children: item.label
2100
- }
2101
- ),
2102
- /* @__PURE__ */ jsx28(
2103
- ChevronRight2,
2104
- {
2105
- className: "shrink-0 text-slate-400",
2106
- size: 16,
2107
- "aria-hidden": "true"
2108
- }
2109
- )
2110
- ] })
2111
- },
2112
- item.id
2113
- );
2114
- })
2115
- }
2116
- )
2117
- }
2118
- );
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",
2898
+ {
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",
2911
+ {
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
+ )
2922
+ }
2923
+ )
2924
+ }
2925
+ ),
2926
+ children && /* @__PURE__ */ jsx40("span", { children })
2927
+ ] }) }) });
2119
2928
  }
2120
2929
 
2121
- // src/components/ToggleButton/ToggleButton.tsx
2930
+ // src/components/Form/Radio/Radio.tsx
2122
2931
  import {
2123
- ToggleButton as AriaToggleButton2
2932
+ RadioGroup as AriaRadioGroup,
2933
+ Radio as AriaRadio
2124
2934
  } from "react-aria-components";
2125
- import { twMerge as twMerge15 } from "tailwind-merge";
2126
- import { jsx as jsx29 } from "react/jsx-runtime";
2127
- var squareSizeStyles2 = {
2128
- xs: "h-6 w-6 text-xs",
2129
- sm: "h-7 w-7 text-sm",
2130
- md: "h-8 w-8 text-base",
2131
- lg: "h-10 w-10 text-lg"
2132
- };
2133
- var variantStyles3 = {
2134
- default: {
2135
- base: [
2136
- "bg-transparent text-foreground",
2137
- "hover:bg-accent",
2138
- "pressed:bg-accent"
2139
- ].join(" "),
2140
- selected: "bg-accent text-foreground"
2141
- },
2142
- primary: {
2143
- base: [
2144
- "bg-transparent text-foreground",
2145
- "hover:bg-accent",
2146
- "pressed:bg-accent"
2147
- ].join(" "),
2148
- selected: "bg-primary-pressed text-primary-foreground"
2149
- },
2150
- outlined: {
2151
- base: [
2152
- "bg-background text-foreground",
2153
- "border border-border",
2154
- "hover:bg-card",
2155
- "pressed:bg-muted"
2156
- ].join(" "),
2157
- selected: [
2158
- "bg-slate-800 text-primary-foreground",
2159
- "border border-slate-800"
2160
- ].join(" ")
2161
- }
2162
- };
2163
- function ToggleButton({
2164
- variant = "default",
2165
- size = "md",
2166
- isSquare = false,
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,
2167
2939
  className,
2940
+ orientation = "vertical",
2168
2941
  ...props
2169
2942
  }) {
2170
- const styles = variantStyles3[variant];
2171
- return /* @__PURE__ */ jsx29(
2172
- AriaToggleButton2,
2943
+ return /* @__PURE__ */ jsx41(
2944
+ AriaRadioGroup,
2173
2945
  {
2174
2946
  ...props,
2175
- className: ({ isSelected }) => twMerge15(
2176
- "inline-flex items-center justify-center gap-2 cursor-pointer",
2177
- isSquare ? "rounded-none" : "rounded-md",
2178
- "font-medium",
2179
- "leading-tight",
2180
- "outline-none transition-colors",
2181
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2182
- "disabled:opacity-50 disabled:pointer-events-none",
2183
- isSquare ? squareSizeStyles2[size] : sizeStyles[size],
2184
- isSelected ? styles.selected : styles.base,
2947
+ orientation,
2948
+ className: twMerge18(
2949
+ "flex gap-2 disabled:opacity-50",
2950
+ orientation === "horizontal" ? "flex-row" : "flex-col",
2185
2951
  className
2186
- )
2952
+ ),
2953
+ children
2187
2954
  }
2188
2955
  );
2189
2956
  }
2190
-
2191
- // src/components/Menu/Menu.tsx
2192
- import {
2193
- MenuTrigger,
2194
- Menu as AriaMenu,
2195
- MenuItem as AriaMenuItem,
2196
- Popover as Popover2
2197
- } from "react-aria-components";
2198
- import { twMerge as twMerge16 } from "tailwind-merge";
2199
-
2200
- // src/components/Menu/menuStyles.ts
2201
- var popoverStyles = `
2202
- bg-background rounded-md shadow-lg
2203
- border border-border
2204
- py-1 min-w-48
2205
- entering:animate-in entering:fade-in entering:zoom-in-95
2206
- exiting:animate-out exiting:fade-out exiting:zoom-out-95
2207
- `;
2208
-
2209
- // src/components/Menu/Menu.tsx
2210
- import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
2211
- function Menu2({
2212
- items,
2213
- content,
2214
- children,
2215
- onAction,
2216
- selectionMode,
2217
- selectedKeys,
2218
- defaultSelectedKeys,
2219
- onSelectionChange,
2220
- className
2221
- }) {
2222
- const selectionProps = selectionMode && selectionMode !== "none" ? { selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange } : {};
2223
- return /* @__PURE__ */ jsxs19(MenuTrigger, { children: [
2224
- children,
2225
- /* @__PURE__ */ jsx30(Popover2, { className: twMerge16(popoverStyles, className), children: items ? /* @__PURE__ */ jsx30(
2226
- AriaMenu,
2227
- {
2228
- items,
2229
- onAction: (key) => {
2230
- const item = items.find((i) => i.id === key);
2231
- item?.onAction?.();
2232
- onAction?.(key);
2233
- },
2234
- ...selectionProps,
2235
- className: "outline-none",
2236
- children: (item) => /* @__PURE__ */ jsxs19(
2237
- AriaMenuItem,
2238
- {
2239
- id: item.id,
2240
- href: item.href,
2241
- target: item.target,
2242
- isDisabled: item.isDisabled,
2243
- className: [
2244
- "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2245
- "transition-colors",
2246
- "focus:bg-muted",
2247
- "hover:bg-muted",
2248
- "disabled:opacity-50 disabled:pointer-events-none",
2249
- item.isDanger ? "text-destructive" : "text-foreground"
2250
- ].filter(Boolean).join(" "),
2251
- children: [
2252
- item.icon && /* @__PURE__ */ jsx30(Icon, { icon: item.icon, size: "sm" }),
2253
- /* @__PURE__ */ jsx30("span", { className: "flex-1", children: item.label }),
2254
- item.endContent && /* @__PURE__ */ jsx30("span", { className: "ml-auto flex items-center", children: item.endContent })
2255
- ]
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",
2970
+ {
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" })
2256
2978
  }
2257
- )
2258
- }
2259
- ) : /* @__PURE__ */ jsx30(
2260
- AriaMenu,
2261
- {
2262
- onAction: (key) => onAction?.(key),
2263
- ...selectionProps,
2264
- className: "outline-none",
2265
- children: content
2266
- }
2267
- ) })
2268
- ] });
2979
+ ),
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
+ )
3007
+ }
3008
+ );
2269
3009
  }
2270
3010
 
2271
- // src/components/Menu/useContextMenu.tsx
2272
- import {
2273
- useCallback as useCallback3,
2274
- useEffect as useEffect3,
2275
- useId as useId2,
2276
- useRef as useRef5,
2277
- useState as useState7
2278
- } from "react";
3011
+ // src/components/Form/Slider/Slider.tsx
2279
3012
  import {
2280
- Menu as AriaMenu2,
2281
- MenuTrigger as MenuTrigger2,
2282
- Popover as Popover3
3013
+ Slider as AriaSlider,
3014
+ SliderTrack,
3015
+ SliderFill,
3016
+ SliderThumb
2283
3017
  } from "react-aria-components";
2284
- import { twMerge as twMerge17 } from "tailwind-merge";
2285
- import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
2286
- function useContextMenu({
2287
- content,
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({
2288
3021
  label,
2289
- onAction,
2290
- className
3022
+ output,
3023
+ description,
3024
+ errorMessage,
3025
+ children,
3026
+ className,
3027
+ isDisabled,
3028
+ ...props
2291
3029
  }) {
2292
- const popoverId = useId2();
2293
- const [anchor, setAnchor] = useState7(null);
2294
- const anchorRef = useRef5(null);
2295
- const popoverRef = useRef5(null);
2296
- const isOpen = anchor !== null;
2297
- const close = useCallback3(() => setAnchor(null), []);
2298
- const onContextMenu = useCallback3((event) => {
2299
- event.preventDefault();
2300
- setAnchor({ x: event.clientX, y: event.clientY });
2301
- }, []);
2302
- const onPress = useCallback3((event) => {
2303
- const rect = event.target.getBoundingClientRect();
2304
- setAnchor({ x: rect.left, y: rect.bottom });
2305
- }, []);
2306
- useEffect3(() => {
2307
- if (!isOpen) return;
2308
- const isInside = (target) => popoverRef.current?.contains(target) ?? false;
2309
- const onPointerDown = (event) => {
2310
- if (!isInside(event.target)) close();
2311
- };
2312
- const onOutsideContextMenu = (event) => {
2313
- if (isInside(event.target)) return;
2314
- event.preventDefault();
2315
- close();
2316
- };
2317
- const onKeyDown = (event) => {
2318
- if (event.key === "Escape") close();
2319
- };
2320
- document.addEventListener("pointerdown", onPointerDown, true);
2321
- document.addEventListener("contextmenu", onOutsideContextMenu, true);
2322
- document.addEventListener("keydown", onKeyDown, true);
2323
- return () => {
2324
- document.removeEventListener("pointerdown", onPointerDown, true);
2325
- document.removeEventListener("contextmenu", onOutsideContextMenu, true);
2326
- document.removeEventListener("keydown", onKeyDown, true);
2327
- };
2328
- }, [isOpen, close]);
2329
- const menu = /* @__PURE__ */ jsxs20(
2330
- MenuTrigger2,
3030
+ return /* @__PURE__ */ jsx42(
3031
+ AriaSlider,
2331
3032
  {
2332
- isOpen,
2333
- onOpenChange: (open) => {
2334
- if (!open) close();
2335
- },
2336
- children: [
2337
- /* @__PURE__ */ jsx31(
2338
- "span",
3033
+ ...props,
3034
+ isDisabled,
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",
2339
3065
  {
2340
- ref: anchorRef,
2341
- "aria-hidden": true,
2342
- tabIndex: -1,
2343
- className: "pointer-events-none fixed h-0 w-0",
2344
- style: { left: anchor?.x ?? 0, top: anchor?.y ?? 0 }
3066
+ className: twMerge19(
3067
+ "text-xs text-muted-foreground",
3068
+ errorMessage && "text-destructive"
3069
+ ),
3070
+ children: errorMessage ?? description
2345
3071
  }
2346
3072
  ),
2347
- /* @__PURE__ */ jsx31(
2348
- Popover3,
2349
- {
2350
- isNonModal: true,
2351
- triggerRef: anchorRef,
2352
- placement: "bottom start",
2353
- ref: popoverRef,
2354
- className: twMerge17(popoverStyles, className),
2355
- children: /* @__PURE__ */ jsx31(
2356
- AriaMenu2,
2357
- {
2358
- id: popoverId,
2359
- "aria-label": label,
2360
- autoFocus: "first",
2361
- onAction: (key) => {
2362
- onAction?.(String(key));
2363
- close();
2364
- },
2365
- className: "outline-none",
2366
- children: content
2367
- }
2368
- )
2369
- }
2370
- )
2371
- ]
3073
+ children
3074
+ ] })
2372
3075
  }
2373
3076
  );
2374
- return {
2375
- targetProps: { onContextMenu },
2376
- triggerProps: {
2377
- onPress,
2378
- onClick: (e) => {
2379
- e.preventDefault();
2380
- },
2381
- "aria-haspopup": "menu",
2382
- "aria-expanded": isOpen,
2383
- "aria-controls": isOpen ? popoverId : void 0
2384
- },
2385
- menu,
2386
- isOpen,
2387
- close
2388
- };
2389
3077
  }
2390
3078
 
2391
- // src/components/Menu/MenuItem.tsx
2392
- import { MenuItem as AriaMenuItem2 } from "react-aria-components";
2393
- import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
2394
- function MenuItem({
2395
- id,
2396
- children,
2397
- icon,
2398
- endContent,
2399
- onAction,
2400
- href,
2401
- target,
2402
- isDisabled,
2403
- isDanger,
2404
- textValue,
2405
- className
2406
- }) {
2407
- return /* @__PURE__ */ jsxs21(
2408
- AriaMenuItem2,
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",
2409
3084
  {
2410
- id,
2411
- href,
2412
- target,
2413
- isDisabled,
2414
- onAction,
2415
- textValue,
2416
3085
  className: [
2417
- "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2418
- "transition-colors",
2419
- "focus:bg-muted",
2420
- "hover:bg-muted",
2421
- "disabled:opacity-50 disabled:pointer-events-none",
2422
- isDanger ? "text-destructive" : "text-foreground",
3086
+ "flex flex-col gap-8",
3087
+ "border-none p-0 m-0",
2423
3088
  className
2424
3089
  ].filter(Boolean).join(" "),
2425
3090
  children: [
2426
- icon && /* @__PURE__ */ jsx32(Icon, { icon, size: "sm" }),
2427
- /* @__PURE__ */ jsx32("span", { className: "flex-1", children }),
2428
- endContent && /* @__PURE__ */ jsx32("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
2429
3104
  ]
2430
3105
  }
2431
3106
  );
2432
3107
  }
2433
3108
 
2434
- // src/components/Menu/MenuCheckboxItem.tsx
2435
- import { MenuItem as AriaMenuItem3 } from "react-aria-components";
2436
- import { Check as Check4 } from "lucide-react";
2437
- import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
2438
- function MenuCheckboxItem({
2439
- id,
2440
- children,
2441
- textValue,
2442
- isDisabled,
2443
- 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
2444
3128
  }) {
2445
- return /* @__PURE__ */ jsx33(
2446
- AriaMenuItem3,
3129
+ return /* @__PURE__ */ jsx44(
3130
+ AriaLink3,
2447
3131
  {
2448
- id,
2449
- textValue,
2450
- isDisabled,
2451
- className: ({ isSelected }) => [
2452
- "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
2453
- "transition-colors",
2454
- "focus:bg-muted",
2455
- "hover:bg-muted",
2456
- "disabled:opacity-50 disabled:pointer-events-none",
2457
- "text-foreground",
2458
- 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],
2459
3137
  className
2460
- ].filter(Boolean).join(" "),
2461
- children: ({ isSelected }) => /* @__PURE__ */ jsxs22(Fragment8, { children: [
2462
- /* @__PURE__ */ jsx33("span", { className: "flex items-center justify-center w-4 h-4 shrink-0", children: isSelected && /* @__PURE__ */ jsx33(Check4, { size: 14, className: "text-primary", "aria-hidden": "true" }) }),
2463
- /* @__PURE__ */ jsx33("span", { className: "flex-1", children })
2464
- ] })
3138
+ ].filter(Boolean).join(" ")
2465
3139
  }
2466
3140
  );
2467
3141
  }
2468
3142
 
2469
- // src/components/Menu/MenuSection.tsx
3143
+ // src/components/Breadcrumbs/Breadcrumbs.tsx
2470
3144
  import {
2471
- MenuSection as AriaMenuSection,
2472
- Header
3145
+ Breadcrumbs as AriaBreadcrumbs,
3146
+ Breadcrumb as AriaBreadcrumb,
3147
+ Link as Link2
2473
3148
  } from "react-aria-components";
2474
- import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
2475
- function MenuSection({
2476
- header,
2477
- children,
2478
- "aria-label": ariaLabel,
2479
- className
2480
- }) {
2481
- return /* @__PURE__ */ jsxs23(AriaMenuSection, { className, "aria-label": ariaLabel, children: [
2482
- header && /* @__PURE__ */ jsx34(
2483
- Header,
2484
- {
2485
- className: [
2486
- "px-3 py-1.5",
2487
- "text-xs font-semibold",
2488
- "text-muted-foreground",
2489
- "uppercase tracking-wider",
2490
- "select-none"
2491
- ].join(" "),
2492
- children: header
2493
- }
2494
- ),
2495
- children
2496
- ] });
2497
- }
2498
-
2499
- // src/components/Menu/MenuHeader.tsx
2500
- import { Header as Header2 } from "react-aria-components";
2501
- import { jsx as jsx35 } from "react/jsx-runtime";
2502
- function MenuHeader({ children, className }) {
2503
- return /* @__PURE__ */ jsx35(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
+ );
2504
3197
  }
2505
3198
 
2506
- // src/components/Menu/MenuSeparator.tsx
2507
- import { Separator } from "react-aria-components";
2508
- import { jsx as jsx36 } from "react/jsx-runtime";
2509
- function MenuSeparator({ className }) {
2510
- return /* @__PURE__ */ jsx36(
2511
- 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,
2512
3251
  {
2513
- className: [
2514
- "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,
2515
3263
  className
2516
- ].filter(Boolean).join(" ")
3264
+ )
2517
3265
  }
2518
3266
  );
2519
3267
  }
@@ -2524,17 +3272,17 @@ import {
2524
3272
  Popover as AriaPopover,
2525
3273
  Button as AriaButton3
2526
3274
  } from "react-aria-components";
2527
- import { twMerge as twMerge18 } from "tailwind-merge";
2528
- import { jsx as jsx37 } from "react/jsx-runtime";
3275
+ import { twMerge as twMerge21 } from "tailwind-merge";
3276
+ import { jsx as jsx47 } from "react/jsx-runtime";
2529
3277
  function Popover4({ children, isOpen, onOpenChange }) {
2530
- return /* @__PURE__ */ jsx37(DialogTrigger, { isOpen, onOpenChange, children });
3278
+ return /* @__PURE__ */ jsx47(DialogTrigger, { isOpen, onOpenChange, children });
2531
3279
  }
2532
3280
  function PopoverTrigger({ children, className }) {
2533
3281
  const cx = `
2534
3282
  inline-flex items-center bg-transparent border-none p-0 outline-none cursor-pointer
2535
3283
  focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-sm
2536
3284
  `;
2537
- return /* @__PURE__ */ jsx37(AriaButton3, { className: twMerge18(cx, className), children });
3285
+ return /* @__PURE__ */ jsx47(AriaButton3, { className: twMerge21(cx, className), children });
2538
3286
  }
2539
3287
  function PopoverContent({
2540
3288
  placement = "bottom",
@@ -2555,13 +3303,13 @@ function PopoverContent({
2555
3303
  entering:placement-left:slide-in-from-right-1
2556
3304
  entering:placement-right:slide-in-from-left-1
2557
3305
  `;
2558
- return /* @__PURE__ */ jsx37(
3306
+ return /* @__PURE__ */ jsx47(
2559
3307
  AriaPopover,
2560
3308
  {
2561
3309
  ...rest,
2562
3310
  placement,
2563
3311
  offset: offsetPx,
2564
- className: twMerge18(cx, className),
3312
+ className: twMerge21(cx, className),
2565
3313
  children
2566
3314
  }
2567
3315
  );
@@ -2569,19 +3317,19 @@ function PopoverContent({
2569
3317
 
2570
3318
  // src/components/Tabs/Tabs.tsx
2571
3319
  import { createContext as createContext2, useContext as useContext2 } from "react";
2572
- import { twMerge as twMerge19 } from "tailwind-merge";
3320
+ import { twMerge as twMerge22 } from "tailwind-merge";
2573
3321
  import {
2574
3322
  Tabs as AriaTabs,
2575
3323
  TabList as AriaTabList,
2576
3324
  Tab as AriaTab,
2577
3325
  TabPanel as AriaTabPanel
2578
3326
  } from "react-aria-components";
2579
- import { jsx as jsx38 } from "react/jsx-runtime";
3327
+ import { jsx as jsx48 } from "react/jsx-runtime";
2580
3328
  var TabsContext = createContext2({
2581
3329
  variant: "underline",
2582
3330
  size: "md"
2583
3331
  });
2584
- var sizeStyles4 = {
3332
+ var sizeStyles5 = {
2585
3333
  sm: "px-3 py-1.5 text-sm",
2586
3334
  md: "px-4 py-2 text-base",
2587
3335
  lg: "px-6 py-3 text-lg"
@@ -2594,12 +3342,12 @@ function Tabs({
2594
3342
  children,
2595
3343
  ...props
2596
3344
  }) {
2597
- return /* @__PURE__ */ jsx38(TabsContext.Provider, { value: { variant, size }, children: /* @__PURE__ */ jsx38(
3345
+ return /* @__PURE__ */ jsx48(TabsContext.Provider, { value: { variant, size }, children: /* @__PURE__ */ jsx48(
2598
3346
  AriaTabs,
2599
3347
  {
2600
3348
  ...props,
2601
3349
  orientation,
2602
- className: twMerge19(
3350
+ className: twMerge22(
2603
3351
  orientation === "vertical" ? "flex" : "",
2604
3352
  className
2605
3353
  ),
@@ -2614,11 +3362,11 @@ function TabList({
2614
3362
  const { variant } = useContext2(TabsContext);
2615
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";
2616
3364
  const verticalStyles = variant === "unstyled" ? "flex-col" : variant === "underline" ? "flex-col border-b-0 border-r border-border" : "flex-col";
2617
- return /* @__PURE__ */ jsx38(
3365
+ return /* @__PURE__ */ jsx48(
2618
3366
  AriaTabList,
2619
3367
  {
2620
3368
  ...props,
2621
- className: ({ orientation }) => twMerge19(
3369
+ className: ({ orientation }) => twMerge22(
2622
3370
  baseStyles,
2623
3371
  orientation === "vertical" ? verticalStyles : "",
2624
3372
  className
@@ -2628,20 +3376,20 @@ function TabList({
2628
3376
  }
2629
3377
  function Tab({ className, ...props }) {
2630
3378
  const { variant, size } = useContext2(TabsContext);
2631
- return /* @__PURE__ */ jsx38(
3379
+ return /* @__PURE__ */ jsx48(
2632
3380
  AriaTab,
2633
3381
  {
2634
3382
  ...props,
2635
3383
  className: ({ isSelected, isDisabled, isHovered, isPressed }) => {
2636
3384
  if (variant === "unstyled") {
2637
- return twMerge19(
3385
+ return twMerge22(
2638
3386
  "cursor-pointer outline-none",
2639
3387
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2640
3388
  isDisabled ? "opacity-50 pointer-events-none" : "",
2641
3389
  className
2642
3390
  );
2643
3391
  }
2644
- return twMerge19(
3392
+ return twMerge22(
2645
3393
  // Base
2646
3394
  "cursor-pointer outline-none transition-colors",
2647
3395
  "font-medium",
@@ -2650,7 +3398,7 @@ function Tab({ className, ...props }) {
2650
3398
  // Disabled
2651
3399
  isDisabled ? "opacity-50 pointer-events-none" : "",
2652
3400
  // Size
2653
- sizeStyles4[size],
3401
+ sizeStyles5[size],
2654
3402
  ...getTabVariantStyles(variant, {
2655
3403
  isSelected,
2656
3404
  isHovered,
@@ -2685,11 +3433,11 @@ function getTabVariantStyles(variant, state) {
2685
3433
  }
2686
3434
  function TabPanel({ className, ...props }) {
2687
3435
  const { variant } = useContext2(TabsContext);
2688
- return /* @__PURE__ */ jsx38(
3436
+ return /* @__PURE__ */ jsx48(
2689
3437
  AriaTabPanel,
2690
3438
  {
2691
3439
  ...props,
2692
- className: twMerge19(
3440
+ className: twMerge22(
2693
3441
  variant === "unstyled" ? "outline-none" : "mt-4 outline-none",
2694
3442
  className
2695
3443
  )
@@ -2707,16 +3455,16 @@ import {
2707
3455
 
2708
3456
  // src/components/SegmentedControl/SegmentedControl.tsx
2709
3457
  import { createContext as createContext3, useContext as useContext3 } from "react";
2710
- import { twMerge as twMerge20 } from "tailwind-merge";
3458
+ import { twMerge as twMerge23 } from "tailwind-merge";
2711
3459
  import {
2712
3460
  ToggleButtonGroup as AriaToggleButtonGroup,
2713
3461
  ToggleButton as AriaToggleButton3
2714
3462
  } from "react-aria-components";
2715
- import { jsx as jsx39 } from "react/jsx-runtime";
3463
+ import { jsx as jsx49 } from "react/jsx-runtime";
2716
3464
  var SegmentedControlContext = createContext3({
2717
3465
  size: "md"
2718
3466
  });
2719
- var sizeStyles5 = {
3467
+ var sizeStyles6 = {
2720
3468
  sm: "px-2.5 py-1 text-xs",
2721
3469
  md: "px-3 py-1.5 text-sm",
2722
3470
  lg: "px-4 py-2 text-base"
@@ -2732,7 +3480,7 @@ function SegmentedControl({
2732
3480
  ...props
2733
3481
  }) {
2734
3482
  const isNoneMode = selectionMode === "none";
2735
- return /* @__PURE__ */ jsx39(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx39(
3483
+ return /* @__PURE__ */ jsx49(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx49(
2736
3484
  AriaToggleButtonGroup,
2737
3485
  {
2738
3486
  ...props,
@@ -2740,7 +3488,7 @@ function SegmentedControl({
2740
3488
  selectedKeys: isNoneMode ? /* @__PURE__ */ new Set() : selectedKeys,
2741
3489
  defaultSelectedKeys: isNoneMode ? void 0 : defaultSelectedKeys,
2742
3490
  onSelectionChange: isNoneMode ? void 0 : onSelectionChange,
2743
- className: twMerge20(
3491
+ className: twMerge23(
2744
3492
  "inline-flex items-center rounded-lg border border-border bg-muted p-0.5 gap-0.5",
2745
3493
  className
2746
3494
  ),
@@ -2753,11 +3501,11 @@ function SegmentedControlItem({
2753
3501
  ...props
2754
3502
  }) {
2755
3503
  const { size } = useContext3(SegmentedControlContext);
2756
- return /* @__PURE__ */ jsx39(
3504
+ return /* @__PURE__ */ jsx49(
2757
3505
  AriaToggleButton3,
2758
3506
  {
2759
3507
  ...props,
2760
- className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge20(
3508
+ className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge23(
2761
3509
  // Base layout
2762
3510
  "inline-flex items-center justify-center",
2763
3511
  "rounded-md",
@@ -2768,7 +3516,7 @@ function SegmentedControlItem({
2768
3516
  // Disabled
2769
3517
  isDisabled && "opacity-50 pointer-events-none",
2770
3518
  // Size
2771
- sizeStyles5[size],
3519
+ sizeStyles6[size],
2772
3520
  // Selected state
2773
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",
2774
3522
  className
@@ -2777,67 +3525,11 @@ function SegmentedControlItem({
2777
3525
  );
2778
3526
  }
2779
3527
 
2780
- // src/components/Badge/Badge.tsx
2781
- import { twMerge as twMerge22 } from "tailwind-merge";
2782
-
2783
- // src/components/MetricText/MetricText.tsx
2784
- import { twMerge as twMerge21 } from "tailwind-merge";
2785
- import { jsx as jsx40 } from "react/jsx-runtime";
2786
- function MetricText({ className, ...rest }) {
2787
- const cx = twMerge21(
2788
- "text-xs font-medium leading-none tracking-wider tabular-nums",
2789
- className
2790
- );
2791
- return /* @__PURE__ */ jsx40("span", { className: cx, ...rest });
2792
- }
2793
-
2794
- // src/components/Badge/Badge.tsx
2795
- import { jsx as jsx41, jsxs as jsxs24 } from "react/jsx-runtime";
2796
- var colorStyles = {
2797
- purple: "bg-badge-purple-bg text-badge-purple-text border-badge-purple-text/20",
2798
- teal: "bg-badge-teal-bg text-badge-teal-text border-badge-teal-text/20",
2799
- rose: "bg-badge-rose-bg text-badge-rose-text border-badge-rose-text/20",
2800
- slate: "bg-badge-slate-bg text-badge-slate-text border-badge-slate-text/20",
2801
- green: "bg-badge-green-bg text-badge-green-text border-badge-green-text/20",
2802
- amber: "bg-badge-amber-bg text-badge-amber-text border-badge-amber-text/20"
2803
- };
2804
- var sizeStyles6 = {
2805
- xs: "px-1 py-0 text-[10px]",
2806
- sm: "px-1.5 py-0.5 text-xs",
2807
- md: "px-2 py-0.5 text-xs",
2808
- lg: "px-2.5 py-1 text-sm"
2809
- };
2810
- function Badge({
2811
- children,
2812
- color = "slate",
2813
- size = "sm",
2814
- icon,
2815
- className,
2816
- ...rest
2817
- }) {
2818
- return /* @__PURE__ */ jsxs24(
2819
- MetricText,
2820
- {
2821
- className: twMerge22(
2822
- "inline-flex items-center gap-1 rounded-full border",
2823
- colorStyles[color],
2824
- sizeStyles6[size],
2825
- className
2826
- ),
2827
- ...rest,
2828
- children: [
2829
- icon && /* @__PURE__ */ jsx41(Icon, { icon, size: "xs" }),
2830
- children
2831
- ]
2832
- }
2833
- );
2834
- }
2835
-
2836
3528
  // src/components/Card/Card.tsx
2837
- import { twMerge as twMerge23 } from "tailwind-merge";
2838
- import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
3529
+ import { twMerge as twMerge24 } from "tailwind-merge";
3530
+ import { jsx as jsx50, jsxs as jsxs30 } from "react/jsx-runtime";
2839
3531
  function Card({ children, header, footer, className }) {
2840
- const cx = twMerge23(
3532
+ const cx = twMerge24(
2841
3533
  `
2842
3534
  bg-card p-8
2843
3535
  border border-border
@@ -2846,17 +3538,17 @@ function Card({ children, header, footer, className }) {
2846
3538
  `,
2847
3539
  className
2848
3540
  );
2849
- return /* @__PURE__ */ jsxs25("div", { className: cx, children: [
2850
- header && /* @__PURE__ */ jsx42("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 }),
2851
3543
  children,
2852
- footer && /* @__PURE__ */ jsx42("div", { className: "border-t border-border", children: footer })
3544
+ footer && /* @__PURE__ */ jsx50("div", { className: "border-t border-border", children: footer })
2853
3545
  ] });
2854
3546
  }
2855
3547
 
2856
3548
  // src/components/DeltaIndicator/DeltaIndicator.tsx
2857
3549
  import { ArrowUp as ArrowUp2, ArrowDown as ArrowDown2, Minus as Minus2 } from "lucide-react";
2858
- import { twMerge as twMerge24 } from "tailwind-merge";
2859
- import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
3550
+ import { twMerge as twMerge25 } from "tailwind-merge";
3551
+ import { jsx as jsx51, jsxs as jsxs31 } from "react/jsx-runtime";
2860
3552
  function getDirection(current, previous) {
2861
3553
  const diff = current - previous;
2862
3554
  if (diff > 0) return "increase";
@@ -2909,16 +3601,16 @@ function DeltaIndicator({
2909
3601
  className
2910
3602
  }) {
2911
3603
  if (unavailable) {
2912
- return /* @__PURE__ */ jsxs26(
3604
+ return /* @__PURE__ */ jsxs31(
2913
3605
  "span",
2914
3606
  {
2915
- className: twMerge24(
3607
+ className: twMerge25(
2916
3608
  "inline-flex items-center gap-1 font-medium",
2917
3609
  "text-muted-foreground",
2918
3610
  className
2919
3611
  ),
2920
3612
  children: [
2921
- label && /* @__PURE__ */ jsx43("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 }),
2922
3614
  unavailableText
2923
3615
  ]
2924
3616
  }
@@ -2948,10 +3640,10 @@ function DeltaIndicator({
2948
3640
  }
2949
3641
  }
2950
3642
  const isPill = mode === "pill";
2951
- return /* @__PURE__ */ jsxs26(
3643
+ return /* @__PURE__ */ jsxs31(
2952
3644
  "span",
2953
3645
  {
2954
- className: twMerge24(
3646
+ className: twMerge25(
2955
3647
  "inline-flex items-center gap-1 font-medium",
2956
3648
  colorStyles2,
2957
3649
  isPill && [
@@ -2962,8 +3654,8 @@ function DeltaIndicator({
2962
3654
  className
2963
3655
  ),
2964
3656
  children: [
2965
- label && /* @__PURE__ */ jsx43("span", { className: "text-sm text-muted-foreground mr-1", children: label }),
2966
- /* @__PURE__ */ jsx43(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 }),
2967
3659
  valueText
2968
3660
  ]
2969
3661
  }
@@ -2971,8 +3663,8 @@ function DeltaIndicator({
2971
3663
  }
2972
3664
 
2973
3665
  // src/components/ProgressBar/ProgressBar.tsx
2974
- import { twMerge as twMerge25 } from "tailwind-merge";
2975
- import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
3666
+ import { twMerge as twMerge26 } from "tailwind-merge";
3667
+ import { jsx as jsx52, jsxs as jsxs32 } from "react/jsx-runtime";
2976
3668
  var fillStyles = {
2977
3669
  brand: "bg-progress-fill",
2978
3670
  success: "bg-progress-fill-success",
@@ -2995,12 +3687,12 @@ function ProgressBar({
2995
3687
  className
2996
3688
  }) {
2997
3689
  const clampedValue = Math.min(100, Math.max(0, value));
2998
- return /* @__PURE__ */ jsxs27("div", { className: twMerge25("w-full", className), children: [
2999
- (label || description || showValue) && /* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between mb-2", children: [
3000
- /* @__PURE__ */ jsx44("span", { className: "text-sm font-medium text-foreground", children: label }),
3001
- /* @__PURE__ */ jsx44("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) })
3002
3694
  ] }),
3003
- /* @__PURE__ */ jsx44(
3695
+ /* @__PURE__ */ jsx52(
3004
3696
  "div",
3005
3697
  {
3006
3698
  role: "progressbar",
@@ -3008,14 +3700,14 @@ function ProgressBar({
3008
3700
  "aria-valuemin": 0,
3009
3701
  "aria-valuemax": 100,
3010
3702
  "aria-label": label ?? "Progress",
3011
- className: twMerge25(
3703
+ className: twMerge26(
3012
3704
  "w-full rounded-full bg-progress-track",
3013
3705
  sizeStyles7[size]
3014
3706
  ),
3015
- children: /* @__PURE__ */ jsx44(
3707
+ children: /* @__PURE__ */ jsx52(
3016
3708
  "div",
3017
3709
  {
3018
- className: twMerge25(
3710
+ className: twMerge26(
3019
3711
  "h-full rounded-full transition-all duration-300",
3020
3712
  fillStyles[variant]
3021
3713
  ),
@@ -3035,8 +3727,8 @@ import {
3035
3727
  AlertCircle as AlertCircle2,
3036
3728
  CheckCircle2 as CheckCircle22
3037
3729
  } from "lucide-react";
3038
- import { twMerge as twMerge26 } from "tailwind-merge";
3039
- import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
3730
+ import { twMerge as twMerge27 } from "tailwind-merge";
3731
+ import { jsx as jsx53, jsxs as jsxs33 } from "react/jsx-runtime";
3040
3732
  var variantConfig2 = {
3041
3733
  info: {
3042
3734
  icon: Info3,
@@ -3080,40 +3772,40 @@ function Banner({
3080
3772
  setDismissed(true);
3081
3773
  onDismiss?.();
3082
3774
  };
3083
- return /* @__PURE__ */ jsxs28(
3775
+ return /* @__PURE__ */ jsxs33(
3084
3776
  "div",
3085
3777
  {
3086
3778
  role: config.role,
3087
- className: twMerge26(
3779
+ className: twMerge27(
3088
3780
  "flex items-start gap-3 rounded-lg border px-4 py-3",
3089
3781
  "text-sm",
3090
3782
  config.containerClass,
3091
3783
  className
3092
3784
  ),
3093
3785
  children: [
3094
- /* @__PURE__ */ jsx45(
3786
+ /* @__PURE__ */ jsx53(
3095
3787
  Icon,
3096
3788
  {
3097
3789
  icon: resolvedIcon,
3098
3790
  size: "md",
3099
- className: twMerge26("mt-0.5", config.iconClass)
3791
+ className: twMerge27("mt-0.5", config.iconClass)
3100
3792
  }
3101
3793
  ),
3102
- /* @__PURE__ */ jsxs28("div", { className: "flex-1", children: [
3103
- title && /* @__PURE__ */ jsxs28("span", { className: "font-medium", children: [
3794
+ /* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
3795
+ title && /* @__PURE__ */ jsxs33("span", { className: "font-medium", children: [
3104
3796
  title,
3105
3797
  " \u2014 "
3106
3798
  ] }),
3107
3799
  children
3108
3800
  ] }),
3109
- dismissible && /* @__PURE__ */ jsx45(
3801
+ dismissible && /* @__PURE__ */ jsx53(
3110
3802
  "button",
3111
3803
  {
3112
3804
  type: "button",
3113
3805
  onClick: handleDismiss,
3114
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",
3115
3807
  "aria-label": "Dismiss",
3116
- children: /* @__PURE__ */ jsx45(Icon, { icon: "X", size: "sm" })
3808
+ children: /* @__PURE__ */ jsx53(Icon, { icon: "X", size: "sm" })
3117
3809
  }
3118
3810
  )
3119
3811
  ]
@@ -3122,8 +3814,8 @@ function Banner({
3122
3814
  }
3123
3815
 
3124
3816
  // src/components/MetricCard/MetricCard.tsx
3125
- import { twMerge as twMerge27 } from "tailwind-merge";
3126
- import { Fragment as Fragment9, jsx as jsx46, jsxs as jsxs29 } 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";
3127
3819
  var sizeConfig = {
3128
3820
  sm: {
3129
3821
  padding: "p-3",
@@ -3145,50 +3837,50 @@ function MetricCard({
3145
3837
  className
3146
3838
  }) {
3147
3839
  const config = sizeConfig[size];
3148
- const containerClass = twMerge27(
3840
+ const containerClass = twMerge28(
3149
3841
  "bg-background border border-border rounded-lg shadow-sm",
3150
3842
  config.padding,
3151
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",
3152
3844
  className
3153
3845
  );
3154
- const content = /* @__PURE__ */ jsxs29(Fragment9, { children: [
3155
- /* @__PURE__ */ jsx46("div", { className: twMerge27(config.labelClass, "text-muted-foreground"), children: label }),
3156
- /* @__PURE__ */ jsx46(
3846
+ const content = /* @__PURE__ */ jsxs34(Fragment11, { children: [
3847
+ /* @__PURE__ */ jsx54("div", { className: twMerge28(config.labelClass, "text-muted-foreground"), children: label }),
3848
+ /* @__PURE__ */ jsx54(
3157
3849
  "div",
3158
3850
  {
3159
- className: twMerge27(
3851
+ className: twMerge28(
3160
3852
  config.valueClass,
3161
3853
  "font-semibold text-foreground mt-1 tabular-nums"
3162
3854
  ),
3163
3855
  children: value
3164
3856
  }
3165
3857
  ),
3166
- secondary && /* @__PURE__ */ jsx46("div", { className: "mt-1 text-sm", children: secondary })
3858
+ secondary && /* @__PURE__ */ jsx54("div", { className: "mt-1 text-sm", children: secondary })
3167
3859
  ] });
3168
3860
  if (href) {
3169
- return /* @__PURE__ */ jsx46("a", { href, className: containerClass, children: content });
3861
+ return /* @__PURE__ */ jsx54("a", { href, className: containerClass, children: content });
3170
3862
  }
3171
- return /* @__PURE__ */ jsx46("div", { className: containerClass, children: content });
3863
+ return /* @__PURE__ */ jsx54("div", { className: containerClass, children: content });
3172
3864
  }
3173
3865
 
3174
3866
  // src/components/SectionHeader/SectionHeader.tsx
3175
3867
  import { forwardRef as forwardRef7 } from "react";
3176
- import { twMerge as twMerge28 } from "tailwind-merge";
3177
- import { jsx as jsx47, jsxs as jsxs30 } from "react/jsx-runtime";
3868
+ import { twMerge as twMerge29 } from "tailwind-merge";
3869
+ import { jsx as jsx55, jsxs as jsxs35 } from "react/jsx-runtime";
3178
3870
  var SectionHeader = forwardRef7(
3179
3871
  function SectionHeader2({ title, as = "h2", children, className, ...rest }, ref) {
3180
- return /* @__PURE__ */ jsxs30(
3872
+ return /* @__PURE__ */ jsxs35(
3181
3873
  "div",
3182
3874
  {
3183
3875
  ref,
3184
- className: twMerge28(
3876
+ className: twMerge29(
3185
3877
  "flex flex-wrap items-center gap-3 pt-0 pb-4",
3186
3878
  className
3187
3879
  ),
3188
3880
  ...rest,
3189
3881
  children: [
3190
- /* @__PURE__ */ jsx47(Heading, { as, children: title }),
3191
- children && /* @__PURE__ */ jsx47("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 })
3192
3884
  ]
3193
3885
  }
3194
3886
  );
@@ -3198,7 +3890,7 @@ var SectionHeader = forwardRef7(
3198
3890
  // src/components/DescriptionList/DescriptionList.tsx
3199
3891
  import { createContext as createContext4, useContext as useContext4 } from "react";
3200
3892
  import { Button as AriaButton4 } from "react-aria-components";
3201
- import { jsx as jsx48, jsxs as jsxs31 } from "react/jsx-runtime";
3893
+ import { jsx as jsx56, jsxs as jsxs36 } from "react/jsx-runtime";
3202
3894
  var LayoutContext = createContext4("stacked");
3203
3895
  var listGapStyles = {
3204
3896
  stacked: "gap-4",
@@ -3209,7 +3901,7 @@ function DescriptionList({
3209
3901
  layout = "stacked",
3210
3902
  className
3211
3903
  }) {
3212
- return /* @__PURE__ */ jsx48(LayoutContext.Provider, { value: layout, children: /* @__PURE__ */ jsx48(
3904
+ return /* @__PURE__ */ jsx56(LayoutContext.Provider, { value: layout, children: /* @__PURE__ */ jsx56(
3213
3905
  "dl",
3214
3906
  {
3215
3907
  className: ["flex flex-col", listGapStyles[layout], className].filter(Boolean).join(" "),
@@ -3233,17 +3925,17 @@ function DescriptionListItem({
3233
3925
  "text-sm m-0",
3234
3926
  muted ? "text-muted-foreground" : "text-foreground"
3235
3927
  ].join(" ");
3236
- const valueContent = /* @__PURE__ */ jsx48("dd", { className: valueClasses, children });
3237
- return /* @__PURE__ */ jsxs31("div", { className: itemLayoutStyles[layout], children: [
3238
- /* @__PURE__ */ jsx48("dt", { className: labelClasses, children: label }),
3239
- fullValue ? /* @__PURE__ */ jsx48(Tooltip, { content: fullValue, children: /* @__PURE__ */ jsx48(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
3240
3932
  ] });
3241
3933
  }
3242
3934
  DescriptionList.Item = DescriptionListItem;
3243
3935
 
3244
3936
  // src/components/PathPill/PathPill.tsx
3245
- import { twMerge as twMerge29 } from "tailwind-merge";
3246
- import { jsx as jsx49 } from "react/jsx-runtime";
3937
+ import { twMerge as twMerge30 } from "tailwind-merge";
3938
+ import { jsx as jsx57 } from "react/jsx-runtime";
3247
3939
  var hashColors = [
3248
3940
  "purple",
3249
3941
  "teal",
@@ -3269,17 +3961,17 @@ function PathPill({
3269
3961
  const effectiveVisible = visibleCount ?? segments.length;
3270
3962
  const dotCount = Math.max(0, segments.length - effectiveVisible);
3271
3963
  const fullPath = segments.join(" / ");
3272
- return /* @__PURE__ */ jsx49(
3964
+ return /* @__PURE__ */ jsx57(
3273
3965
  "div",
3274
3966
  {
3275
- className: twMerge29("relative flex", className),
3967
+ className: twMerge30("relative flex", className),
3276
3968
  "aria-label": `Path: ${fullPath}`,
3277
3969
  children: segments.map((segment, i) => {
3278
3970
  const isCollapsed = i < dotCount;
3279
3971
  const isLast = i === segments.length - 1;
3280
- const cx = twMerge29(!isLast && "pr-5 -mr-4", isCollapsed && "pr-3");
3972
+ const cx = twMerge30(!isLast && "pr-5 -mr-4", isCollapsed && "pr-3");
3281
3973
  const color = colorFn ? colorFn(segment, i) : pillColorFromName(segment);
3282
- return /* @__PURE__ */ jsx49(
3974
+ return /* @__PURE__ */ jsx57(
3283
3975
  Badge,
3284
3976
  {
3285
3977
  className: cx,
@@ -3295,8 +3987,8 @@ function PathPill({
3295
3987
  }
3296
3988
 
3297
3989
  // src/components/FormWizard/FormWizard.tsx
3298
- import { createContext as createContext5, useContext as useContext5, useCallback as useCallback4, useMemo } from "react";
3299
- import { jsx as jsx50 } 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";
3300
3992
  var FormWizardContext = createContext5({
3301
3993
  currentStep: 0,
3302
3994
  totalSteps: 1,
@@ -3316,12 +4008,12 @@ function FormWizard({
3316
4008
  }) {
3317
4009
  const canGoBack = currentStep > 0;
3318
4010
  const isLastStep = currentStep >= totalSteps - 1;
3319
- const goBack = useCallback4(() => {
4011
+ const goBack = useCallback10(() => {
3320
4012
  if (currentStep > 0) {
3321
4013
  onStepChange(currentStep - 1);
3322
4014
  }
3323
4015
  }, [currentStep, onStepChange]);
3324
- const value = useMemo(
4016
+ const value = useMemo5(
3325
4017
  () => ({
3326
4018
  currentStep,
3327
4019
  totalSteps,
@@ -3331,13 +4023,13 @@ function FormWizard({
3331
4023
  }),
3332
4024
  [currentStep, totalSteps, canGoBack, goBack, isLastStep]
3333
4025
  );
3334
- return /* @__PURE__ */ jsx50(FormWizardContext.Provider, { value, children });
4026
+ return /* @__PURE__ */ jsx58(FormWizardContext.Provider, { value, children });
3335
4027
  }
3336
4028
 
3337
4029
  // src/components/FormWizard/FormWizardProgress.tsx
3338
- import { jsx as jsx51, jsxs as jsxs32 } from "react/jsx-runtime";
4030
+ import { jsx as jsx59, jsxs as jsxs37 } from "react/jsx-runtime";
3339
4031
  function CheckIcon() {
3340
- return /* @__PURE__ */ jsx51(
4032
+ return /* @__PURE__ */ jsx59(
3341
4033
  "svg",
3342
4034
  {
3343
4035
  "aria-hidden": "true",
@@ -3348,24 +4040,24 @@ function CheckIcon() {
3348
4040
  strokeWidth: "2",
3349
4041
  strokeLinecap: "round",
3350
4042
  strokeLinejoin: "round",
3351
- children: /* @__PURE__ */ jsx51("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" })
3352
4044
  }
3353
4045
  );
3354
4046
  }
3355
4047
  function FormWizardProgress({ labels }) {
3356
4048
  const { currentStep, totalSteps } = useFormWizard();
3357
- return /* @__PURE__ */ jsx51("nav", { "aria-label": "Form progress", children: /* @__PURE__ */ jsx51("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) => {
3358
4050
  const isCompleted = index < currentStep;
3359
4051
  const isCurrent = index === currentStep;
3360
4052
  const isFuture = index > currentStep;
3361
- return /* @__PURE__ */ jsxs32(
4053
+ return /* @__PURE__ */ jsxs37(
3362
4054
  "li",
3363
4055
  {
3364
4056
  className: "flex flex-1 flex-col items-center",
3365
4057
  "aria-current": isCurrent ? "step" : void 0,
3366
4058
  children: [
3367
- /* @__PURE__ */ jsxs32("div", { className: "flex w-full items-center", children: [
3368
- index > 0 ? /* @__PURE__ */ jsx51(
4059
+ /* @__PURE__ */ jsxs37("div", { className: "flex w-full items-center", children: [
4060
+ index > 0 ? /* @__PURE__ */ jsx59(
3369
4061
  "div",
3370
4062
  {
3371
4063
  "aria-hidden": "true",
@@ -3374,8 +4066,8 @@ function FormWizardProgress({ labels }) {
3374
4066
  index <= currentStep ? "bg-primary" : "bg-border"
3375
4067
  ].join(" ")
3376
4068
  }
3377
- ) : /* @__PURE__ */ jsx51("div", { className: "flex-1", "aria-hidden": "true" }),
3378
- /* @__PURE__ */ jsx51(
4069
+ ) : /* @__PURE__ */ jsx59("div", { className: "flex-1", "aria-hidden": "true" }),
4070
+ /* @__PURE__ */ jsx59(
3379
4071
  "div",
3380
4072
  {
3381
4073
  className: [
@@ -3387,10 +4079,10 @@ function FormWizardProgress({ labels }) {
3387
4079
  isFuture ? "border-2 border-border bg-background text-muted-foreground" : ""
3388
4080
  ].join(" "),
3389
4081
  "aria-hidden": "true",
3390
- children: isCompleted ? /* @__PURE__ */ jsx51(CheckIcon, {}) : index + 1
4082
+ children: isCompleted ? /* @__PURE__ */ jsx59(CheckIcon, {}) : index + 1
3391
4083
  }
3392
4084
  ),
3393
- index < totalSteps - 1 ? /* @__PURE__ */ jsx51(
4085
+ index < totalSteps - 1 ? /* @__PURE__ */ jsx59(
3394
4086
  "div",
3395
4087
  {
3396
4088
  "aria-hidden": "true",
@@ -3399,9 +4091,9 @@ function FormWizardProgress({ labels }) {
3399
4091
  index < currentStep ? "bg-primary" : "bg-border"
3400
4092
  ].join(" ")
3401
4093
  }
3402
- ) : /* @__PURE__ */ jsx51("div", { className: "flex-1", "aria-hidden": "true" })
4094
+ ) : /* @__PURE__ */ jsx59("div", { className: "flex-1", "aria-hidden": "true" })
3403
4095
  ] }),
3404
- /* @__PURE__ */ jsx51(
4096
+ /* @__PURE__ */ jsx59(
3405
4097
  "span",
3406
4098
  {
3407
4099
  className: [
@@ -3419,15 +4111,15 @@ function FormWizardProgress({ labels }) {
3419
4111
  }
3420
4112
 
3421
4113
  // src/components/FormWizard/FormWizardNav.tsx
3422
- import { jsx as jsx52, jsxs as jsxs33 } from "react/jsx-runtime";
4114
+ import { jsx as jsx60, jsxs as jsxs38 } from "react/jsx-runtime";
3423
4115
  function FormWizardNav({
3424
4116
  onNext,
3425
4117
  isSubmitting = false,
3426
4118
  submitLabel = "Submit"
3427
4119
  }) {
3428
4120
  const { canGoBack, goBack, isLastStep } = useFormWizard();
3429
- return /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-end gap-3", children: [
3430
- canGoBack && /* @__PURE__ */ jsx52(
4121
+ return /* @__PURE__ */ jsxs38("div", { className: "flex items-center justify-end gap-3", children: [
4122
+ canGoBack && /* @__PURE__ */ jsx60(
3431
4123
  Button,
3432
4124
  {
3433
4125
  variant: "secondary",
@@ -3437,7 +4129,7 @@ function FormWizardNav({
3437
4129
  children: "Back"
3438
4130
  }
3439
4131
  ),
3440
- /* @__PURE__ */ jsx52(
4132
+ /* @__PURE__ */ jsx60(
3441
4133
  Button,
3442
4134
  {
3443
4135
  variant: "primary",
@@ -3456,9 +4148,7 @@ export {
3456
4148
  Button,
3457
4149
  ButtonLink,
3458
4150
  Card,
3459
- Cell,
3460
4151
  Checkbox,
3461
- Column,
3462
4152
  DeltaIndicator,
3463
4153
  Description,
3464
4154
  DescriptionList,
@@ -3483,6 +4173,8 @@ export {
3483
4173
  InputPassword,
3484
4174
  Label,
3485
4175
  Link,
4176
+ ListBox2 as ListBox,
4177
+ ListBoxItem2 as ListBoxItem,
3486
4178
  Logo,
3487
4179
  Menu2 as Menu,
3488
4180
  MenuCheckboxItem,
@@ -3492,6 +4184,7 @@ export {
3492
4184
  MenuSeparator,
3493
4185
  MetricCard,
3494
4186
  MetricText,
4187
+ NoFilterResults,
3495
4188
  PathPill,
3496
4189
  Popover4 as Popover,
3497
4190
  PopoverContent,
@@ -3502,11 +4195,11 @@ export {
3502
4195
  RadioButton,
3503
4196
  RadioGroup,
3504
4197
  RouterProvider,
3505
- Row,
3506
4198
  SectionHeader,
3507
4199
  SegmentedControl,
3508
4200
  SegmentedControlItem,
3509
4201
  Select,
4202
+ SelectionFooter,
3510
4203
  Slider,
3511
4204
  Spinner,
3512
4205
  Switch,
@@ -3514,8 +4207,6 @@ export {
3514
4207
  TabList,
3515
4208
  TabPanel,
3516
4209
  Table2 as Table,
3517
- TableBody,
3518
- TableHeader,
3519
4210
  Tabs,
3520
4211
  ToastProvider,
3521
4212
  ToggleButton,
@@ -3527,11 +4218,17 @@ export {
3527
4218
  Tabs2 as UnstyledTabs,
3528
4219
  buttonBaseClass,
3529
4220
  createToastBridge,
4221
+ getTableStore,
3530
4222
  iconRegistry,
3531
4223
  pillColorFromName,
3532
4224
  selectedStyles,
4225
+ useColumnFilters,
4226
+ useColumnVisibility,
4227
+ useColumnWidths,
3533
4228
  useContextMenu,
3534
4229
  useFormWizard,
4230
+ useTableSorting,
4231
+ useTableStore,
3535
4232
  useToast,
3536
4233
  variantStyles
3537
4234
  };