@undevy-org/tablewright 0.1.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/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/es/components/dashboard/ReportSummaryCard.js +67 -0
- package/dist/es/components/data-table/AppliedStateChips.js +113 -0
- package/dist/es/components/data-table/ColumnFilterPopover.js +548 -0
- package/dist/es/components/data-table/ColumnHeaderMenu.js +144 -0
- package/dist/es/components/data-table/CompoundFilterPopover.js +508 -0
- package/dist/es/components/data-table/CopyButton.js +35 -0
- package/dist/es/components/data-table/CopyableText.js +26 -0
- package/dist/es/components/data-table/DataTableShell.js +145 -0
- package/dist/es/components/data-table/DrawerActionGroup.js +59 -0
- package/dist/es/components/data-table/DrawerEntityCard.js +21 -0
- package/dist/es/components/data-table/DrawerField.js +10 -0
- package/dist/es/components/data-table/DrawerFlagItem.js +20 -0
- package/dist/es/components/data-table/DrawerSection.js +26 -0
- package/dist/es/components/data-table/DrawerShell.js +141 -0
- package/dist/es/components/data-table/DrawerSummaryCard.js +11 -0
- package/dist/es/components/data-table/EmptyState.js +14 -0
- package/dist/es/components/data-table/ExpiryTimestampCell.js +43 -0
- package/dist/es/components/data-table/FilterChip.js +47 -0
- package/dist/es/components/data-table/FilterFormPanel.js +357 -0
- package/dist/es/components/data-table/FilterFormToggle.js +77 -0
- package/dist/es/components/data-table/FilterPopoverFooter.js +19 -0
- package/dist/es/components/data-table/FilterToolbar.js +131 -0
- package/dist/es/components/data-table/FlatColumnToggle.js +46 -0
- package/dist/es/components/data-table/GapIndicator.js +29 -0
- package/dist/es/components/data-table/GroupedColumnToggle.js +112 -0
- package/dist/es/components/data-table/RowActionsMenu.js +74 -0
- package/dist/es/components/data-table/RowControlCell.js +104 -0
- package/dist/es/components/data-table/SortableHeader.js +102 -0
- package/dist/es/components/data-table/TableFooter.js +132 -0
- package/dist/es/components/data-table/TableLayout.js +14 -0
- package/dist/es/components/data-table/TimestampCell.js +16 -0
- package/dist/es/components/data-table/TwoPanelMenu.js +64 -0
- package/dist/es/components/data-table/ViewChip.js +25 -0
- package/dist/es/components/data-table/cells/AmountCell.js +127 -0
- package/dist/es/components/data-table/cells/ConfirmedAmountCell.js +115 -0
- package/dist/es/components/data-table/cells/CurrencyAmountCell.js +26 -0
- package/dist/es/components/data-table/cells/DualLineCell.js +59 -0
- package/dist/es/components/data-table/cells/EnumBadgeCell.js +9 -0
- package/dist/es/components/data-table/cells/MonoIdCell.js +31 -0
- package/dist/es/components/data-table/hooks/use-column-resize.js +39 -0
- package/dist/es/components/data-table/hooks/use-row-drag.js +40 -0
- package/dist/es/components/data-table/hooks/use-table-pagination.js +14 -0
- package/dist/es/components/data-table/hooks/use-table-sort.js +35 -0
- package/dist/es/components/data-table/managed-filters.js +34 -0
- package/dist/es/components/data-table/sticky-utils.js +25 -0
- package/dist/es/components/layout/AppShell.js +113 -0
- package/dist/es/components/layout/Sidebar.js +128 -0
- package/dist/es/components/layout/SidebarAccountMenu.js +129 -0
- package/dist/es/components/layout/SidebarUser.js +38 -0
- package/dist/es/components/layout/TopBar.js +25 -0
- package/dist/es/components/layout/app-shell-context.js +9 -0
- package/dist/es/components/ui/badge.js +31 -0
- package/dist/es/components/ui/button-footer.js +25 -0
- package/dist/es/components/ui/button.js +44 -0
- package/dist/es/components/ui/checkbox.js +24 -0
- package/dist/es/components/ui/combobox.js +179 -0
- package/dist/es/components/ui/dialog.js +80 -0
- package/dist/es/components/ui/dropdown-menu.js +66 -0
- package/dist/es/components/ui/input.js +24 -0
- package/dist/es/components/ui/popover.js +33 -0
- package/dist/es/components/ui/segmented-control.js +60 -0
- package/dist/es/components/ui/select.js +66 -0
- package/dist/es/components/ui/tabs.js +41 -0
- package/dist/es/components/ui/theme-switch.js +47 -0
- package/dist/es/constants/drawer.js +4 -0
- package/dist/es/context/drawer-expand-context.js +10 -0
- package/dist/es/context/portal-container-context.js +10 -0
- package/dist/es/hooks/table-orchestration-store.js +165 -0
- package/dist/es/hooks/use-scroll-activity.js +33 -0
- package/dist/es/hooks/useRowDragOverride.js +18 -0
- package/dist/es/hooks/useTableOrchestration.js +452 -0
- package/dist/es/index.js +199 -0
- package/dist/es/lib/column-gaps.js +23 -0
- package/dist/es/lib/filter-stats.js +67 -0
- package/dist/es/lib/format-enum.js +6 -0
- package/dist/es/lib/format-timestamp.js +37 -0
- package/dist/es/lib/style-scope.js +4 -0
- package/dist/es/lib/utils.js +8 -0
- package/dist/fonts.css +5 -0
- package/dist/preflight.css +502 -0
- package/dist/styles.css +1731 -0
- package/dist/tablewright.cjs +5473 -0
- package/dist/tablewright.css +1579 -0
- package/dist/tokens.css +150 -0
- package/dist/types/components/dashboard/ReportSummaryCard.d.ts +15 -0
- package/dist/types/components/data-table/AppliedStateChips.d.ts +28 -0
- package/dist/types/components/data-table/ColumnFilterPopover.d.ts +14 -0
- package/dist/types/components/data-table/ColumnHeaderMenu.d.ts +27 -0
- package/dist/types/components/data-table/CompoundFilterPopover.d.ts +14 -0
- package/dist/types/components/data-table/CopyButton.d.ts +8 -0
- package/dist/types/components/data-table/CopyableText.d.ts +10 -0
- package/dist/types/components/data-table/DataTableShell.d.ts +30 -0
- package/dist/types/components/data-table/DrawerActionGroup.d.ts +8 -0
- package/dist/types/components/data-table/DrawerEntityCard.d.ts +13 -0
- package/dist/types/components/data-table/DrawerField.d.ts +7 -0
- package/dist/types/components/data-table/DrawerFlagItem.d.ts +10 -0
- package/dist/types/components/data-table/DrawerSection.d.ts +8 -0
- package/dist/types/components/data-table/DrawerShell.d.ts +33 -0
- package/dist/types/components/data-table/DrawerSummaryCard.d.ts +7 -0
- package/dist/types/components/data-table/EmptyState.d.ts +6 -0
- package/dist/types/components/data-table/ExpiryTimestampCell.d.ts +6 -0
- package/dist/types/components/data-table/FilterChip.d.ts +8 -0
- package/dist/types/components/data-table/FilterFormPanel.d.ts +34 -0
- package/dist/types/components/data-table/FilterFormToggle.d.ts +18 -0
- package/dist/types/components/data-table/FilterPopoverFooter.d.ts +9 -0
- package/dist/types/components/data-table/FilterToolbar.d.ts +29 -0
- package/dist/types/components/data-table/FlatColumnToggle.d.ts +10 -0
- package/dist/types/components/data-table/GapIndicator.d.ts +11 -0
- package/dist/types/components/data-table/GroupedColumnToggle.d.ts +12 -0
- package/dist/types/components/data-table/RowActionsMenu.d.ts +10 -0
- package/dist/types/components/data-table/RowControlCell.d.ts +16 -0
- package/dist/types/components/data-table/SortableHeader.d.ts +16 -0
- package/dist/types/components/data-table/TableFooter.d.ts +31 -0
- package/dist/types/components/data-table/TableLayout.d.ts +12 -0
- package/dist/types/components/data-table/TimestampCell.d.ts +3 -0
- package/dist/types/components/data-table/TwoPanelMenu.d.ts +22 -0
- package/dist/types/components/data-table/ViewChip.d.ts +6 -0
- package/dist/types/components/data-table/cells/AmountCell.d.ts +11 -0
- package/dist/types/components/data-table/cells/ConfirmedAmountCell.d.ts +10 -0
- package/dist/types/components/data-table/cells/CurrencyAmountCell.d.ts +8 -0
- package/dist/types/components/data-table/cells/DualLineCell.d.ts +44 -0
- package/dist/types/components/data-table/cells/EnumBadgeCell.d.ts +9 -0
- package/dist/types/components/data-table/cells/MonoIdCell.d.ts +19 -0
- package/dist/types/components/data-table/filter-types.d.ts +79 -0
- package/dist/types/components/data-table/hooks/use-column-resize.d.ts +7 -0
- package/dist/types/components/data-table/hooks/use-row-drag.d.ts +14 -0
- package/dist/types/components/data-table/hooks/use-table-pagination.d.ts +10 -0
- package/dist/types/components/data-table/hooks/use-table-sort.d.ts +6 -0
- package/dist/types/components/data-table/managed-filters.d.ts +18 -0
- package/dist/types/components/data-table/sticky-utils.d.ts +4 -0
- package/dist/types/components/data-table/types.d.ts +35 -0
- package/dist/types/components/layout/AppShell.d.ts +23 -0
- package/dist/types/components/layout/Sidebar.d.ts +16 -0
- package/dist/types/components/layout/SidebarAccountMenu.d.ts +20 -0
- package/dist/types/components/layout/SidebarUser.d.ts +8 -0
- package/dist/types/components/layout/TopBar.d.ts +7 -0
- package/dist/types/components/layout/app-shell-context.d.ts +8 -0
- package/dist/types/components/layout/index.d.ts +10 -0
- package/dist/types/components/layout/types.d.ts +11 -0
- package/dist/types/components/ui/badge.d.ts +9 -0
- package/dist/types/components/ui/button-footer.d.ts +7 -0
- package/dist/types/components/ui/button.d.ts +11 -0
- package/dist/types/components/ui/checkbox.d.ts +4 -0
- package/dist/types/components/ui/combobox.d.ts +92 -0
- package/dist/types/components/ui/dialog.d.ts +15 -0
- package/dist/types/components/ui/dropdown-menu.d.ts +10 -0
- package/dist/types/components/ui/input.d.ts +6 -0
- package/dist/types/components/ui/popover.d.ts +7 -0
- package/dist/types/components/ui/segmented-control.d.ts +17 -0
- package/dist/types/components/ui/select.d.ts +8 -0
- package/dist/types/components/ui/tabs.d.ts +10 -0
- package/dist/types/components/ui/theme-switch.d.ts +12 -0
- package/dist/types/constants/drawer.d.ts +1 -0
- package/dist/types/context/drawer-expand-context.d.ts +7 -0
- package/dist/types/context/portal-container-context.d.ts +14 -0
- package/dist/types/hooks/table-orchestration-store.d.ts +75 -0
- package/dist/types/hooks/use-scroll-activity.d.ts +1 -0
- package/dist/types/hooks/useDemoTheme.d.ts +8 -0
- package/dist/types/hooks/useRowDragOverride.d.ts +6 -0
- package/dist/types/hooks/useTableOrchestration.d.ts +115 -0
- package/dist/types/index.d.ts +107 -0
- package/dist/types/lib/column-gaps.d.ts +3 -0
- package/dist/types/lib/filter-stats.d.ts +2 -0
- package/dist/types/lib/format-enum.d.ts +1 -0
- package/dist/types/lib/format-timestamp.d.ts +4 -0
- package/dist/types/lib/style-scope.d.ts +19 -0
- package/dist/types/lib/utils.d.ts +2 -0
- package/package.json +114 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { TwoPanelMenuBase } from "./TwoPanelMenu.js";
|
|
3
|
+
import { Columns, ChevronDown } from "lucide-react";
|
|
4
|
+
import { Button } from "../ui/button.js";
|
|
5
|
+
import { Checkbox } from "../ui/checkbox.js";
|
|
6
|
+
function CheckboxRightPanel({
|
|
7
|
+
group,
|
|
8
|
+
columnVisibility,
|
|
9
|
+
onColumnToggle,
|
|
10
|
+
onGroupToggleAll
|
|
11
|
+
}) {
|
|
12
|
+
const allVisible = group.items.every((item) => columnVisibility[item.id] !== false);
|
|
13
|
+
const noneVisible = group.items.every((item) => columnVisibility[item.id] === false);
|
|
14
|
+
const isIndeterminate = !allVisible && !noneVisible;
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: 4 }, children: [
|
|
16
|
+
/* @__PURE__ */ jsxs(
|
|
17
|
+
"label",
|
|
18
|
+
{
|
|
19
|
+
className: "flex w-full items-center gap-2.5 rounded-md px-2 py-2 text-left hover:bg-[var(--bg-hover)] cursor-pointer",
|
|
20
|
+
style: { fontSize: 12, fontWeight: 500, color: "var(--text-secondary)" },
|
|
21
|
+
children: [
|
|
22
|
+
/* @__PURE__ */ jsx(
|
|
23
|
+
Checkbox,
|
|
24
|
+
{
|
|
25
|
+
checked: isIndeterminate ? "indeterminate" : allVisible,
|
|
26
|
+
onCheckedChange: () => onGroupToggleAll(group.key, !allVisible),
|
|
27
|
+
className: "h-3.5 w-3.5 rounded-[3px]"
|
|
28
|
+
}
|
|
29
|
+
),
|
|
30
|
+
/* @__PURE__ */ jsx("span", { children: "All" })
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-[var(--border-subtle)]", style: { margin: "0 8px 4px 8px" } }),
|
|
35
|
+
group.items.map((item) => {
|
|
36
|
+
const isChecked = columnVisibility[item.id] !== false;
|
|
37
|
+
return /* @__PURE__ */ jsxs(
|
|
38
|
+
"label",
|
|
39
|
+
{
|
|
40
|
+
className: `flex w-full items-center gap-2.5 rounded-md px-2 py-2 text-left hover:bg-[var(--bg-hover)] cursor-pointer ${item.disabled ? "pointer-events-none opacity-50" : ""}`,
|
|
41
|
+
style: { fontSize: 13 },
|
|
42
|
+
children: [
|
|
43
|
+
/* @__PURE__ */ jsx(
|
|
44
|
+
Checkbox,
|
|
45
|
+
{
|
|
46
|
+
checked: isChecked,
|
|
47
|
+
onCheckedChange: () => onColumnToggle(item.id),
|
|
48
|
+
disabled: item.disabled,
|
|
49
|
+
className: "h-3.5 w-3.5 rounded-[3px]"
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
/* @__PURE__ */ jsx("span", { children: item.label })
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
item.id
|
|
56
|
+
);
|
|
57
|
+
})
|
|
58
|
+
] });
|
|
59
|
+
}
|
|
60
|
+
function GroupedColumnToggle({
|
|
61
|
+
columnGroups,
|
|
62
|
+
columnLabels,
|
|
63
|
+
columnVisibility,
|
|
64
|
+
onColumnToggle,
|
|
65
|
+
onGroupToggleAll,
|
|
66
|
+
open,
|
|
67
|
+
onOpenChange
|
|
68
|
+
}) {
|
|
69
|
+
const groups = columnGroups.map((cg) => ({
|
|
70
|
+
key: cg.key,
|
|
71
|
+
label: cg.label,
|
|
72
|
+
items: cg.columnIds.map((columnId) => ({
|
|
73
|
+
id: columnId,
|
|
74
|
+
label: columnLabels[columnId] ?? columnId,
|
|
75
|
+
checked: columnVisibility[columnId] !== false,
|
|
76
|
+
disabled: false
|
|
77
|
+
}))
|
|
78
|
+
}));
|
|
79
|
+
const activeCountPerGroup = {};
|
|
80
|
+
for (const cg of columnGroups) {
|
|
81
|
+
const hiddenCount = cg.columnIds.filter((id) => columnVisibility[id] === false).length;
|
|
82
|
+
activeCountPerGroup[cg.key] = hiddenCount;
|
|
83
|
+
}
|
|
84
|
+
const trigger = /* @__PURE__ */ jsxs(Button, { variant: "secondary", children: [
|
|
85
|
+
/* @__PURE__ */ jsx(Columns, { size: 14 }),
|
|
86
|
+
"Columns",
|
|
87
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-[var(--text-tertiary)]" })
|
|
88
|
+
] });
|
|
89
|
+
return /* @__PURE__ */ jsx(
|
|
90
|
+
TwoPanelMenuBase,
|
|
91
|
+
{
|
|
92
|
+
groups,
|
|
93
|
+
activeCountPerGroup,
|
|
94
|
+
trigger,
|
|
95
|
+
width: 380,
|
|
96
|
+
open,
|
|
97
|
+
onOpenChange,
|
|
98
|
+
renderRightPanel: (group) => /* @__PURE__ */ jsx(
|
|
99
|
+
CheckboxRightPanel,
|
|
100
|
+
{
|
|
101
|
+
group,
|
|
102
|
+
columnVisibility,
|
|
103
|
+
onColumnToggle,
|
|
104
|
+
onGroupToggleAll
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
GroupedColumnToggle
|
|
112
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { MoreVertical } from "lucide-react";
|
|
3
|
+
import { Button } from "../ui/button.js";
|
|
4
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "../ui/dropdown-menu.js";
|
|
5
|
+
import { cn } from "../../lib/utils.js";
|
|
6
|
+
function RowActionsMenu({
|
|
7
|
+
actions = [],
|
|
8
|
+
sections,
|
|
9
|
+
align = "end",
|
|
10
|
+
triggerClassName,
|
|
11
|
+
contentClassName
|
|
12
|
+
}) {
|
|
13
|
+
const resolvedSections = sections && sections.length > 0 ? sections : actions.length > 0 ? [{ label: "", actions }] : [];
|
|
14
|
+
const isGrouped = resolvedSections.some((section) => section.label);
|
|
15
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
16
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
17
|
+
Button,
|
|
18
|
+
{
|
|
19
|
+
variant: "ghost",
|
|
20
|
+
size: "icon",
|
|
21
|
+
"aria-label": "Row actions",
|
|
22
|
+
className: cn(
|
|
23
|
+
"h-7 w-7 rounded-sm p-0 opacity-0 transition-opacity group-hover:opacity-100 data-[state=open]:opacity-100",
|
|
24
|
+
triggerClassName
|
|
25
|
+
),
|
|
26
|
+
onClick: (event) => event.stopPropagation(),
|
|
27
|
+
children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
|
|
28
|
+
}
|
|
29
|
+
) }),
|
|
30
|
+
/* @__PURE__ */ jsx(
|
|
31
|
+
DropdownMenuContent,
|
|
32
|
+
{
|
|
33
|
+
align,
|
|
34
|
+
className: cn(isGrouped ? "w-[320px] p-1.5" : "w-40", contentClassName),
|
|
35
|
+
children: resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsxs("div", { children: [
|
|
36
|
+
section.label ? /* @__PURE__ */ jsx("div", { className: "px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-[0.12em] text-[var(--text-tertiary)] first:pt-1", children: section.label }) : null,
|
|
37
|
+
section.actions.map((action) => /* @__PURE__ */ jsxs(
|
|
38
|
+
DropdownMenuItem,
|
|
39
|
+
{
|
|
40
|
+
disabled: action.disabled,
|
|
41
|
+
className: cn(
|
|
42
|
+
"gap-2.5 rounded-md px-2.5 py-2",
|
|
43
|
+
action.variant === "danger" && "text-[var(--tag-pink-text)]",
|
|
44
|
+
action.variant === "accent" && "text-[var(--text-primary)]"
|
|
45
|
+
),
|
|
46
|
+
onClick: (event) => {
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
action.onClick(event);
|
|
49
|
+
},
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsx(
|
|
52
|
+
action.icon,
|
|
53
|
+
{
|
|
54
|
+
className: cn(
|
|
55
|
+
"h-3.5 w-3.5 shrink-0 text-[var(--text-secondary)]",
|
|
56
|
+
action.variant === "danger" && "text-[var(--tag-pink-text)]",
|
|
57
|
+
action.variant === "accent" && "text-[var(--text-primary)]"
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: action.label })
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
`${section.label}-${action.label}`
|
|
65
|
+
)),
|
|
66
|
+
sectionIndex < resolvedSections.length - 1 ? /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-[var(--border-subtle)]" }) : null
|
|
67
|
+
] }, section.label || sectionIndex))
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
RowActionsMenu
|
|
74
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { GripVertical, Expand } from "lucide-react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { Checkbox } from "../ui/checkbox.js";
|
|
5
|
+
function RowControlCell({
|
|
6
|
+
rowNumber,
|
|
7
|
+
selected,
|
|
8
|
+
onSelectToggle,
|
|
9
|
+
onExpandToggle,
|
|
10
|
+
ariaLabelSelect = "Select row",
|
|
11
|
+
ariaLabelExpand = "Expand row",
|
|
12
|
+
forceControlsVisible = false
|
|
13
|
+
}) {
|
|
14
|
+
const showCheckbox = selected || forceControlsVisible;
|
|
15
|
+
const showHoverAffordances = forceControlsVisible;
|
|
16
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative flex h-full w-full items-center justify-center", children: [
|
|
17
|
+
/* @__PURE__ */ jsx(
|
|
18
|
+
"span",
|
|
19
|
+
{
|
|
20
|
+
className: cn(
|
|
21
|
+
"text-[11px] tabular-nums text-[var(--text-tertiary)] transition-opacity",
|
|
22
|
+
showCheckbox ? "opacity-0" : "opacity-100 group-hover:opacity-0"
|
|
23
|
+
),
|
|
24
|
+
children: rowNumber
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
className: cn(
|
|
31
|
+
"absolute inset-0 flex items-center justify-center transition-opacity",
|
|
32
|
+
showCheckbox ? "opacity-100" : "pointer-events-none opacity-0 group-hover:pointer-events-auto group-hover:opacity-100"
|
|
33
|
+
),
|
|
34
|
+
children: /* @__PURE__ */ jsx(
|
|
35
|
+
Checkbox,
|
|
36
|
+
{
|
|
37
|
+
checked: selected,
|
|
38
|
+
onCheckedChange: () => onSelectToggle(),
|
|
39
|
+
onClick: (e) => {
|
|
40
|
+
e.stopPropagation();
|
|
41
|
+
},
|
|
42
|
+
"aria-label": ariaLabelSelect
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
/* @__PURE__ */ jsx(
|
|
48
|
+
"div",
|
|
49
|
+
{
|
|
50
|
+
className: cn(
|
|
51
|
+
"pointer-events-none absolute inset-y-0 left-0 flex w-5 items-center justify-center transition-opacity",
|
|
52
|
+
showHoverAffordances ? "opacity-100" : "opacity-0 group-hover:opacity-100"
|
|
53
|
+
),
|
|
54
|
+
children: /* @__PURE__ */ jsx(
|
|
55
|
+
GripVertical,
|
|
56
|
+
{
|
|
57
|
+
className: "h-3.5 w-3.5 shrink-0 text-[var(--text-tertiary)]",
|
|
58
|
+
"aria-hidden": "true"
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
),
|
|
63
|
+
onExpandToggle ? /* @__PURE__ */ jsx(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
className: cn(
|
|
67
|
+
"absolute inset-y-0 right-0 flex w-5 items-center justify-center transition-opacity",
|
|
68
|
+
showHoverAffordances ? "opacity-100" : "pointer-events-none opacity-0 group-hover:pointer-events-auto group-hover:opacity-100"
|
|
69
|
+
),
|
|
70
|
+
children: /* @__PURE__ */ jsx(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
type: "button",
|
|
74
|
+
className: "inline-flex h-5 w-5 items-center justify-center rounded border border-[var(--border-subtle)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)]",
|
|
75
|
+
onClick: (e) => {
|
|
76
|
+
e.stopPropagation();
|
|
77
|
+
onExpandToggle(e);
|
|
78
|
+
},
|
|
79
|
+
"aria-label": ariaLabelExpand,
|
|
80
|
+
children: /* @__PURE__ */ jsx(Expand, { className: "h-3 w-3" })
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
) : null
|
|
85
|
+
] });
|
|
86
|
+
}
|
|
87
|
+
function RowControlHeader({
|
|
88
|
+
checked,
|
|
89
|
+
onToggle,
|
|
90
|
+
ariaLabel = "Select all rows on page"
|
|
91
|
+
}) {
|
|
92
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
93
|
+
Checkbox,
|
|
94
|
+
{
|
|
95
|
+
checked,
|
|
96
|
+
onCheckedChange: () => onToggle(),
|
|
97
|
+
"aria-label": ariaLabel
|
|
98
|
+
}
|
|
99
|
+
) });
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
RowControlCell,
|
|
103
|
+
RowControlHeader
|
|
104
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowUp, ArrowDown, ArrowUpDown } from "lucide-react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
function SortIcon({
|
|
5
|
+
sorted,
|
|
6
|
+
hoverClass
|
|
7
|
+
}) {
|
|
8
|
+
if (sorted === "asc") {
|
|
9
|
+
return /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3 shrink-0 text-[var(--text-primary)]" });
|
|
10
|
+
}
|
|
11
|
+
if (sorted === "desc") {
|
|
12
|
+
return /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3 shrink-0 text-[var(--text-primary)]" });
|
|
13
|
+
}
|
|
14
|
+
return /* @__PURE__ */ jsx(
|
|
15
|
+
ArrowUpDown,
|
|
16
|
+
{
|
|
17
|
+
className: cn(
|
|
18
|
+
"h-3 w-3 shrink-0 text-[var(--text-tertiary)] opacity-0 transition-opacity",
|
|
19
|
+
hoverClass
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function SortableHeader({
|
|
25
|
+
label,
|
|
26
|
+
primaryLabel,
|
|
27
|
+
secondaryLabel,
|
|
28
|
+
mode,
|
|
29
|
+
sorted,
|
|
30
|
+
onClick,
|
|
31
|
+
primarySorted,
|
|
32
|
+
onPrimaryClick,
|
|
33
|
+
secondarySorted,
|
|
34
|
+
onSecondaryClick,
|
|
35
|
+
className
|
|
36
|
+
}) {
|
|
37
|
+
const resolvedPrimaryLabel = primaryLabel ?? label ?? "";
|
|
38
|
+
const resolvedMode = mode ?? (secondaryLabel ? "stacked" : "single");
|
|
39
|
+
const isStacked = resolvedMode === "stacked";
|
|
40
|
+
const isDualSort = isStacked && primarySorted !== void 0;
|
|
41
|
+
if (isDualSort) {
|
|
42
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-0.5", className), children: [
|
|
43
|
+
/* @__PURE__ */ jsxs(
|
|
44
|
+
"button",
|
|
45
|
+
{
|
|
46
|
+
type: "button",
|
|
47
|
+
className: "group/primary inline-flex cursor-pointer select-none items-center gap-1 text-left",
|
|
48
|
+
onClick: onPrimaryClick,
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--text-primary)]", children: resolvedPrimaryLabel }),
|
|
51
|
+
/* @__PURE__ */ jsx(
|
|
52
|
+
SortIcon,
|
|
53
|
+
{
|
|
54
|
+
sorted: primarySorted,
|
|
55
|
+
hoverClass: "group-hover/primary:opacity-100"
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
/* @__PURE__ */ jsxs(
|
|
62
|
+
"button",
|
|
63
|
+
{
|
|
64
|
+
type: "button",
|
|
65
|
+
className: "group/secondary inline-flex cursor-pointer select-none items-center gap-1 text-left",
|
|
66
|
+
onClick: onSecondaryClick,
|
|
67
|
+
children: [
|
|
68
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-[0.06em] text-[var(--text-tertiary)]", children: secondaryLabel }),
|
|
69
|
+
/* @__PURE__ */ jsx(
|
|
70
|
+
SortIcon,
|
|
71
|
+
{
|
|
72
|
+
sorted: secondarySorted,
|
|
73
|
+
hoverClass: "group-hover/secondary:opacity-100"
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
] });
|
|
80
|
+
}
|
|
81
|
+
return /* @__PURE__ */ jsxs(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
className: cn(
|
|
86
|
+
"group/header inline-flex cursor-pointer select-none items-start gap-1.5 text-left",
|
|
87
|
+
className
|
|
88
|
+
),
|
|
89
|
+
onClick,
|
|
90
|
+
children: [
|
|
91
|
+
isStacked ? /* @__PURE__ */ jsxs("span", { className: "flex flex-col leading-none", children: [
|
|
92
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--text-primary)]", children: resolvedPrimaryLabel }),
|
|
93
|
+
/* @__PURE__ */ jsx("span", { className: "mt-1 text-[10px] font-medium uppercase tracking-[0.06em] text-[var(--text-tertiary)]", children: secondaryLabel })
|
|
94
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--text-primary)]", children: resolvedPrimaryLabel }),
|
|
95
|
+
/* @__PURE__ */ jsx(SortIcon, { sorted, hoverClass: "group-hover/header:opacity-100" })
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
SortableHeader
|
|
102
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
3
|
+
import { Button } from "../ui/button.js";
|
|
4
|
+
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "../ui/select.js";
|
|
5
|
+
const defaultRowsPerPageOptions = [15, 30, 60, 100];
|
|
6
|
+
function TableFooter(props) {
|
|
7
|
+
const {
|
|
8
|
+
selectedCount,
|
|
9
|
+
totalCount,
|
|
10
|
+
onSelectAll,
|
|
11
|
+
onClearSelection,
|
|
12
|
+
bulkActions
|
|
13
|
+
} = props;
|
|
14
|
+
const summaryLabel = selectedCount > 0 ? `Selected: ${selectedCount}` : `Total: ${totalCount}`;
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex min-h-[64px] shrink-0 flex-col gap-3 border-t border-[var(--border-subtle)] px-6 py-3 lg:flex-row lg:items-center lg:justify-between", children: [
|
|
16
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
17
|
+
/* @__PURE__ */ jsx(
|
|
18
|
+
"span",
|
|
19
|
+
{
|
|
20
|
+
className: selectedCount > 0 ? "text-[12px] font-semibold text-[var(--text-primary)]" : "text-[12px] font-medium text-[var(--text-secondary)]",
|
|
21
|
+
children: summaryLabel
|
|
22
|
+
}
|
|
23
|
+
),
|
|
24
|
+
selectedCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
25
|
+
/* @__PURE__ */ jsxs(
|
|
26
|
+
Button,
|
|
27
|
+
{
|
|
28
|
+
variant: "ghost",
|
|
29
|
+
size: "sm",
|
|
30
|
+
className: "h-7 text-[12px]",
|
|
31
|
+
onClick: onSelectAll,
|
|
32
|
+
children: [
|
|
33
|
+
"Select All (",
|
|
34
|
+
totalCount,
|
|
35
|
+
")"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
Button,
|
|
41
|
+
{
|
|
42
|
+
variant: "ghost",
|
|
43
|
+
size: "sm",
|
|
44
|
+
className: "h-7 text-[12px]",
|
|
45
|
+
onClick: onClearSelection,
|
|
46
|
+
children: "Clear"
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
bulkActions.map((action) => /* @__PURE__ */ jsx(
|
|
50
|
+
Button,
|
|
51
|
+
{
|
|
52
|
+
variant: "ghost",
|
|
53
|
+
size: "sm",
|
|
54
|
+
className: `h-7 text-[12px]${action.variant === "danger" ? " text-[var(--tag-pink-text)]" : ""}`,
|
|
55
|
+
onClick: action.onClick,
|
|
56
|
+
children: action.label
|
|
57
|
+
},
|
|
58
|
+
action.label
|
|
59
|
+
))
|
|
60
|
+
] }) : null
|
|
61
|
+
] }),
|
|
62
|
+
renderPagination(props)
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
function renderPagination(props) {
|
|
66
|
+
if (props.paginationVariant === "perPage") {
|
|
67
|
+
const rowsPerPageOptions = props.rowsPerPageOptions ?? defaultRowsPerPageOptions;
|
|
68
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 lg:justify-end", children: [
|
|
69
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
70
|
+
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-[var(--text-secondary)]", children: "Rows per page" }),
|
|
71
|
+
/* @__PURE__ */ jsxs(
|
|
72
|
+
Select,
|
|
73
|
+
{
|
|
74
|
+
value: String(props.rowsPerPage),
|
|
75
|
+
onValueChange: (value) => props.onRowsPerPageChange(Number(value)),
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-[var(--size-control-sm)] w-[var(--size-select-compact)]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
78
|
+
/* @__PURE__ */ jsx(SelectContent, { children: rowsPerPageOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: String(option), children: option }, option)) })
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
] }),
|
|
83
|
+
renderNumericPager(props)
|
|
84
|
+
] });
|
|
85
|
+
}
|
|
86
|
+
if (props.paginationVariant !== "pages") {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return renderNumericPager(props);
|
|
90
|
+
}
|
|
91
|
+
function renderNumericPager(props) {
|
|
92
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 lg:justify-end", children: [
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
Button,
|
|
95
|
+
{
|
|
96
|
+
variant: "ghost",
|
|
97
|
+
size: "icon",
|
|
98
|
+
"aria-label": "Previous page",
|
|
99
|
+
className: "h-7 w-7",
|
|
100
|
+
disabled: props.currentPage === 1,
|
|
101
|
+
onClick: () => props.onPageChange(props.currentPage - 1),
|
|
102
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
|
|
103
|
+
}
|
|
104
|
+
),
|
|
105
|
+
props.pageNumbers.map((pageNum) => /* @__PURE__ */ jsx(
|
|
106
|
+
Button,
|
|
107
|
+
{
|
|
108
|
+
variant: pageNum === props.currentPage ? "default" : "ghost",
|
|
109
|
+
size: "sm",
|
|
110
|
+
className: "h-7 w-7 p-0 text-[12px]",
|
|
111
|
+
onClick: () => props.onPageChange(pageNum),
|
|
112
|
+
children: pageNum
|
|
113
|
+
},
|
|
114
|
+
pageNum
|
|
115
|
+
)),
|
|
116
|
+
/* @__PURE__ */ jsx(
|
|
117
|
+
Button,
|
|
118
|
+
{
|
|
119
|
+
variant: "ghost",
|
|
120
|
+
size: "icon",
|
|
121
|
+
"aria-label": "Next page",
|
|
122
|
+
className: "h-7 w-7",
|
|
123
|
+
disabled: props.currentPage === props.totalPages,
|
|
124
|
+
onClick: () => props.onPageChange(props.currentPage + 1),
|
|
125
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
export {
|
|
131
|
+
TableFooter
|
|
132
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/utils.js";
|
|
3
|
+
import { useScrollActivity } from "../../hooks/use-scroll-activity.js";
|
|
4
|
+
function TableLayout({ children, className }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative flex flex-1 flex-col overflow-hidden", className), children });
|
|
6
|
+
}
|
|
7
|
+
function ScrollArea({ children, className }) {
|
|
8
|
+
const scrollRef = useScrollActivity();
|
|
9
|
+
return /* @__PURE__ */ jsx("div", { ref: scrollRef, className: cn("scrollbar-auto-hide flex-1 overflow-auto", className), children });
|
|
10
|
+
}
|
|
11
|
+
TableLayout.ScrollArea = ScrollArea;
|
|
12
|
+
export {
|
|
13
|
+
TableLayout
|
|
14
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function splitTimestamp(value) {
|
|
3
|
+
if (!value) return { date: "—", time: "" };
|
|
4
|
+
const [date, time] = value.split(" ");
|
|
5
|
+
return { date: date ?? "—", time: time ?? "" };
|
|
6
|
+
}
|
|
7
|
+
function TimestampCell({ value }) {
|
|
8
|
+
const { date, time } = splitTimestamp(value);
|
|
9
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-left font-mono", children: [
|
|
10
|
+
/* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium text-[var(--text-primary)]", children: date }),
|
|
11
|
+
time ? /* @__PURE__ */ jsx("div", { className: "text-[12px] text-[var(--text-secondary)]", children: time }) : null
|
|
12
|
+
] });
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
TimestampCell
|
|
16
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Popover, PopoverTrigger, PopoverContent } from "../ui/popover.js";
|
|
4
|
+
function CategoryRow({ group, activeCount, isSelected, onClick }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs(
|
|
6
|
+
"button",
|
|
7
|
+
{
|
|
8
|
+
type: "button",
|
|
9
|
+
onClick,
|
|
10
|
+
className: `flex w-full cursor-pointer items-center justify-between gap-1 rounded-md px-3 py-2 text-left text-[13px] transition-colors hover:bg-[var(--bg-hover)] ${isSelected ? "bg-[var(--bg-secondary)] font-medium" : "font-normal"}`,
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ jsx(
|
|
13
|
+
"span",
|
|
14
|
+
{
|
|
15
|
+
className: `truncate leading-[1.4] ${isSelected ? "text-[var(--text-primary)]" : "text-[var(--text-secondary)]"}`,
|
|
16
|
+
children: group.label
|
|
17
|
+
}
|
|
18
|
+
),
|
|
19
|
+
activeCount > 0 && /* @__PURE__ */ jsx("span", { className: "inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full bg-[var(--bg-tertiary)] px-1.5 text-[11px] font-semibold tabular-nums text-[var(--text-utility)]", children: activeCount })
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function TwoPanelMenuBase({
|
|
25
|
+
groups,
|
|
26
|
+
activeCountPerGroup = {},
|
|
27
|
+
trigger,
|
|
28
|
+
width = 380,
|
|
29
|
+
renderRightPanel,
|
|
30
|
+
open,
|
|
31
|
+
onOpenChange
|
|
32
|
+
}) {
|
|
33
|
+
const [selectedGroupKey, setSelectedGroupKey] = useState(groups[0]?.key ?? "");
|
|
34
|
+
const selectedGroup = groups.find((g) => g.key === selectedGroupKey) ?? groups[0];
|
|
35
|
+
const handleClose = () => onOpenChange?.(false);
|
|
36
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange, children: [
|
|
37
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
|
|
38
|
+
/* @__PURE__ */ jsxs(
|
|
39
|
+
PopoverContent,
|
|
40
|
+
{
|
|
41
|
+
align: "start",
|
|
42
|
+
sideOffset: 4,
|
|
43
|
+
className: "flex max-h-[60vh] overflow-hidden p-0",
|
|
44
|
+
style: { width: `${width}px` },
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsx("div", { className: "w-44 shrink-0 overflow-y-auto bg-[var(--bg-surface-muted)] p-1.5", children: groups.map((group) => /* @__PURE__ */ jsx(
|
|
47
|
+
CategoryRow,
|
|
48
|
+
{
|
|
49
|
+
group,
|
|
50
|
+
activeCount: activeCountPerGroup[group.key] ?? 0,
|
|
51
|
+
isSelected: group.key === selectedGroupKey,
|
|
52
|
+
onClick: () => setSelectedGroupKey(group.key)
|
|
53
|
+
},
|
|
54
|
+
group.key
|
|
55
|
+
)) }),
|
|
56
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto bg-[var(--bg-surface)]", children: selectedGroup ? renderRightPanel(selectedGroup, handleClose) : null })
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
TwoPanelMenuBase
|
|
64
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
const ViewChip = React.forwardRef(
|
|
5
|
+
({ label, active, className, ...rest }, ref) => {
|
|
6
|
+
return /* @__PURE__ */ jsx(
|
|
7
|
+
"button",
|
|
8
|
+
{
|
|
9
|
+
ref,
|
|
10
|
+
type: "button",
|
|
11
|
+
...rest,
|
|
12
|
+
className: cn(
|
|
13
|
+
"inline-flex items-center rounded-full border px-3 py-1 text-[13px] font-medium transition-colors focus:outline-none focus:ring-1 focus:ring-[var(--border-focus)]",
|
|
14
|
+
active ? "border-[var(--border-brand)] bg-[var(--bg-brand-subtle)] text-[var(--text-brand)]" : "border-[var(--border-subtle)] bg-transparent text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]",
|
|
15
|
+
className
|
|
16
|
+
),
|
|
17
|
+
children: label
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
ViewChip.displayName = "ViewChip";
|
|
23
|
+
export {
|
|
24
|
+
ViewChip
|
|
25
|
+
};
|