@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.
Files changed (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +262 -0
  3. package/dist/es/components/dashboard/ReportSummaryCard.js +67 -0
  4. package/dist/es/components/data-table/AppliedStateChips.js +113 -0
  5. package/dist/es/components/data-table/ColumnFilterPopover.js +548 -0
  6. package/dist/es/components/data-table/ColumnHeaderMenu.js +144 -0
  7. package/dist/es/components/data-table/CompoundFilterPopover.js +508 -0
  8. package/dist/es/components/data-table/CopyButton.js +35 -0
  9. package/dist/es/components/data-table/CopyableText.js +26 -0
  10. package/dist/es/components/data-table/DataTableShell.js +145 -0
  11. package/dist/es/components/data-table/DrawerActionGroup.js +59 -0
  12. package/dist/es/components/data-table/DrawerEntityCard.js +21 -0
  13. package/dist/es/components/data-table/DrawerField.js +10 -0
  14. package/dist/es/components/data-table/DrawerFlagItem.js +20 -0
  15. package/dist/es/components/data-table/DrawerSection.js +26 -0
  16. package/dist/es/components/data-table/DrawerShell.js +141 -0
  17. package/dist/es/components/data-table/DrawerSummaryCard.js +11 -0
  18. package/dist/es/components/data-table/EmptyState.js +14 -0
  19. package/dist/es/components/data-table/ExpiryTimestampCell.js +43 -0
  20. package/dist/es/components/data-table/FilterChip.js +47 -0
  21. package/dist/es/components/data-table/FilterFormPanel.js +357 -0
  22. package/dist/es/components/data-table/FilterFormToggle.js +77 -0
  23. package/dist/es/components/data-table/FilterPopoverFooter.js +19 -0
  24. package/dist/es/components/data-table/FilterToolbar.js +131 -0
  25. package/dist/es/components/data-table/FlatColumnToggle.js +46 -0
  26. package/dist/es/components/data-table/GapIndicator.js +29 -0
  27. package/dist/es/components/data-table/GroupedColumnToggle.js +112 -0
  28. package/dist/es/components/data-table/RowActionsMenu.js +74 -0
  29. package/dist/es/components/data-table/RowControlCell.js +104 -0
  30. package/dist/es/components/data-table/SortableHeader.js +102 -0
  31. package/dist/es/components/data-table/TableFooter.js +132 -0
  32. package/dist/es/components/data-table/TableLayout.js +14 -0
  33. package/dist/es/components/data-table/TimestampCell.js +16 -0
  34. package/dist/es/components/data-table/TwoPanelMenu.js +64 -0
  35. package/dist/es/components/data-table/ViewChip.js +25 -0
  36. package/dist/es/components/data-table/cells/AmountCell.js +127 -0
  37. package/dist/es/components/data-table/cells/ConfirmedAmountCell.js +115 -0
  38. package/dist/es/components/data-table/cells/CurrencyAmountCell.js +26 -0
  39. package/dist/es/components/data-table/cells/DualLineCell.js +59 -0
  40. package/dist/es/components/data-table/cells/EnumBadgeCell.js +9 -0
  41. package/dist/es/components/data-table/cells/MonoIdCell.js +31 -0
  42. package/dist/es/components/data-table/hooks/use-column-resize.js +39 -0
  43. package/dist/es/components/data-table/hooks/use-row-drag.js +40 -0
  44. package/dist/es/components/data-table/hooks/use-table-pagination.js +14 -0
  45. package/dist/es/components/data-table/hooks/use-table-sort.js +35 -0
  46. package/dist/es/components/data-table/managed-filters.js +34 -0
  47. package/dist/es/components/data-table/sticky-utils.js +25 -0
  48. package/dist/es/components/layout/AppShell.js +113 -0
  49. package/dist/es/components/layout/Sidebar.js +128 -0
  50. package/dist/es/components/layout/SidebarAccountMenu.js +129 -0
  51. package/dist/es/components/layout/SidebarUser.js +38 -0
  52. package/dist/es/components/layout/TopBar.js +25 -0
  53. package/dist/es/components/layout/app-shell-context.js +9 -0
  54. package/dist/es/components/ui/badge.js +31 -0
  55. package/dist/es/components/ui/button-footer.js +25 -0
  56. package/dist/es/components/ui/button.js +44 -0
  57. package/dist/es/components/ui/checkbox.js +24 -0
  58. package/dist/es/components/ui/combobox.js +179 -0
  59. package/dist/es/components/ui/dialog.js +80 -0
  60. package/dist/es/components/ui/dropdown-menu.js +66 -0
  61. package/dist/es/components/ui/input.js +24 -0
  62. package/dist/es/components/ui/popover.js +33 -0
  63. package/dist/es/components/ui/segmented-control.js +60 -0
  64. package/dist/es/components/ui/select.js +66 -0
  65. package/dist/es/components/ui/tabs.js +41 -0
  66. package/dist/es/components/ui/theme-switch.js +47 -0
  67. package/dist/es/constants/drawer.js +4 -0
  68. package/dist/es/context/drawer-expand-context.js +10 -0
  69. package/dist/es/context/portal-container-context.js +10 -0
  70. package/dist/es/hooks/table-orchestration-store.js +165 -0
  71. package/dist/es/hooks/use-scroll-activity.js +33 -0
  72. package/dist/es/hooks/useRowDragOverride.js +18 -0
  73. package/dist/es/hooks/useTableOrchestration.js +452 -0
  74. package/dist/es/index.js +199 -0
  75. package/dist/es/lib/column-gaps.js +23 -0
  76. package/dist/es/lib/filter-stats.js +67 -0
  77. package/dist/es/lib/format-enum.js +6 -0
  78. package/dist/es/lib/format-timestamp.js +37 -0
  79. package/dist/es/lib/style-scope.js +4 -0
  80. package/dist/es/lib/utils.js +8 -0
  81. package/dist/fonts.css +5 -0
  82. package/dist/preflight.css +502 -0
  83. package/dist/styles.css +1731 -0
  84. package/dist/tablewright.cjs +5473 -0
  85. package/dist/tablewright.css +1579 -0
  86. package/dist/tokens.css +150 -0
  87. package/dist/types/components/dashboard/ReportSummaryCard.d.ts +15 -0
  88. package/dist/types/components/data-table/AppliedStateChips.d.ts +28 -0
  89. package/dist/types/components/data-table/ColumnFilterPopover.d.ts +14 -0
  90. package/dist/types/components/data-table/ColumnHeaderMenu.d.ts +27 -0
  91. package/dist/types/components/data-table/CompoundFilterPopover.d.ts +14 -0
  92. package/dist/types/components/data-table/CopyButton.d.ts +8 -0
  93. package/dist/types/components/data-table/CopyableText.d.ts +10 -0
  94. package/dist/types/components/data-table/DataTableShell.d.ts +30 -0
  95. package/dist/types/components/data-table/DrawerActionGroup.d.ts +8 -0
  96. package/dist/types/components/data-table/DrawerEntityCard.d.ts +13 -0
  97. package/dist/types/components/data-table/DrawerField.d.ts +7 -0
  98. package/dist/types/components/data-table/DrawerFlagItem.d.ts +10 -0
  99. package/dist/types/components/data-table/DrawerSection.d.ts +8 -0
  100. package/dist/types/components/data-table/DrawerShell.d.ts +33 -0
  101. package/dist/types/components/data-table/DrawerSummaryCard.d.ts +7 -0
  102. package/dist/types/components/data-table/EmptyState.d.ts +6 -0
  103. package/dist/types/components/data-table/ExpiryTimestampCell.d.ts +6 -0
  104. package/dist/types/components/data-table/FilterChip.d.ts +8 -0
  105. package/dist/types/components/data-table/FilterFormPanel.d.ts +34 -0
  106. package/dist/types/components/data-table/FilterFormToggle.d.ts +18 -0
  107. package/dist/types/components/data-table/FilterPopoverFooter.d.ts +9 -0
  108. package/dist/types/components/data-table/FilterToolbar.d.ts +29 -0
  109. package/dist/types/components/data-table/FlatColumnToggle.d.ts +10 -0
  110. package/dist/types/components/data-table/GapIndicator.d.ts +11 -0
  111. package/dist/types/components/data-table/GroupedColumnToggle.d.ts +12 -0
  112. package/dist/types/components/data-table/RowActionsMenu.d.ts +10 -0
  113. package/dist/types/components/data-table/RowControlCell.d.ts +16 -0
  114. package/dist/types/components/data-table/SortableHeader.d.ts +16 -0
  115. package/dist/types/components/data-table/TableFooter.d.ts +31 -0
  116. package/dist/types/components/data-table/TableLayout.d.ts +12 -0
  117. package/dist/types/components/data-table/TimestampCell.d.ts +3 -0
  118. package/dist/types/components/data-table/TwoPanelMenu.d.ts +22 -0
  119. package/dist/types/components/data-table/ViewChip.d.ts +6 -0
  120. package/dist/types/components/data-table/cells/AmountCell.d.ts +11 -0
  121. package/dist/types/components/data-table/cells/ConfirmedAmountCell.d.ts +10 -0
  122. package/dist/types/components/data-table/cells/CurrencyAmountCell.d.ts +8 -0
  123. package/dist/types/components/data-table/cells/DualLineCell.d.ts +44 -0
  124. package/dist/types/components/data-table/cells/EnumBadgeCell.d.ts +9 -0
  125. package/dist/types/components/data-table/cells/MonoIdCell.d.ts +19 -0
  126. package/dist/types/components/data-table/filter-types.d.ts +79 -0
  127. package/dist/types/components/data-table/hooks/use-column-resize.d.ts +7 -0
  128. package/dist/types/components/data-table/hooks/use-row-drag.d.ts +14 -0
  129. package/dist/types/components/data-table/hooks/use-table-pagination.d.ts +10 -0
  130. package/dist/types/components/data-table/hooks/use-table-sort.d.ts +6 -0
  131. package/dist/types/components/data-table/managed-filters.d.ts +18 -0
  132. package/dist/types/components/data-table/sticky-utils.d.ts +4 -0
  133. package/dist/types/components/data-table/types.d.ts +35 -0
  134. package/dist/types/components/layout/AppShell.d.ts +23 -0
  135. package/dist/types/components/layout/Sidebar.d.ts +16 -0
  136. package/dist/types/components/layout/SidebarAccountMenu.d.ts +20 -0
  137. package/dist/types/components/layout/SidebarUser.d.ts +8 -0
  138. package/dist/types/components/layout/TopBar.d.ts +7 -0
  139. package/dist/types/components/layout/app-shell-context.d.ts +8 -0
  140. package/dist/types/components/layout/index.d.ts +10 -0
  141. package/dist/types/components/layout/types.d.ts +11 -0
  142. package/dist/types/components/ui/badge.d.ts +9 -0
  143. package/dist/types/components/ui/button-footer.d.ts +7 -0
  144. package/dist/types/components/ui/button.d.ts +11 -0
  145. package/dist/types/components/ui/checkbox.d.ts +4 -0
  146. package/dist/types/components/ui/combobox.d.ts +92 -0
  147. package/dist/types/components/ui/dialog.d.ts +15 -0
  148. package/dist/types/components/ui/dropdown-menu.d.ts +10 -0
  149. package/dist/types/components/ui/input.d.ts +6 -0
  150. package/dist/types/components/ui/popover.d.ts +7 -0
  151. package/dist/types/components/ui/segmented-control.d.ts +17 -0
  152. package/dist/types/components/ui/select.d.ts +8 -0
  153. package/dist/types/components/ui/tabs.d.ts +10 -0
  154. package/dist/types/components/ui/theme-switch.d.ts +12 -0
  155. package/dist/types/constants/drawer.d.ts +1 -0
  156. package/dist/types/context/drawer-expand-context.d.ts +7 -0
  157. package/dist/types/context/portal-container-context.d.ts +14 -0
  158. package/dist/types/hooks/table-orchestration-store.d.ts +75 -0
  159. package/dist/types/hooks/use-scroll-activity.d.ts +1 -0
  160. package/dist/types/hooks/useDemoTheme.d.ts +8 -0
  161. package/dist/types/hooks/useRowDragOverride.d.ts +6 -0
  162. package/dist/types/hooks/useTableOrchestration.d.ts +115 -0
  163. package/dist/types/index.d.ts +107 -0
  164. package/dist/types/lib/column-gaps.d.ts +3 -0
  165. package/dist/types/lib/filter-stats.d.ts +2 -0
  166. package/dist/types/lib/format-enum.d.ts +1 -0
  167. package/dist/types/lib/format-timestamp.d.ts +4 -0
  168. package/dist/types/lib/style-scope.d.ts +19 -0
  169. package/dist/types/lib/utils.d.ts +2 -0
  170. package/package.json +114 -0
@@ -0,0 +1,128 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { ChevronRight, ChevronLeft } from "lucide-react";
4
+ import { cn } from "../../lib/utils.js";
5
+ import { useAppShell } from "./app-shell-context.js";
6
+ function isItemActive(href, activeKey) {
7
+ if (href === "" || href === "/") return activeKey === "" || activeKey === "/";
8
+ return activeKey === href || activeKey.startsWith(href + "/");
9
+ }
10
+ const Sidebar = React.forwardRef(
11
+ function Sidebar2({
12
+ groups,
13
+ activeKey = "",
14
+ collapsed: collapsedProp,
15
+ onCollapsedChange: onCollapsedChangeProp,
16
+ renderLink,
17
+ header,
18
+ footer,
19
+ className
20
+ }, ref) {
21
+ const shell = useAppShell();
22
+ const collapsed = collapsedProp ?? shell?.collapsed ?? false;
23
+ const hovering = shell?.hovering ?? false;
24
+ const effectiveCollapsed = shell ? shell.effectiveCollapsed : collapsed;
25
+ const onCollapsedChange = onCollapsedChangeProp ?? shell?.onCollapsedChange ?? (() => {
26
+ });
27
+ const showExpanded = !effectiveCollapsed;
28
+ const isOverlay = hovering && collapsed;
29
+ return /* @__PURE__ */ jsxs(
30
+ "aside",
31
+ {
32
+ ref,
33
+ "aria-label": "Primary navigation",
34
+ className: cn(
35
+ "flex h-full shrink-0 flex-col overflow-hidden border-r border-[var(--border-subtle)] bg-[var(--bg-surface)]",
36
+ "transition-[width] ease-in-out",
37
+ isOverlay ? "absolute left-0 top-0 z-40 h-full [box-shadow:var(--shadow-sidebar-overlay)]" : "relative",
38
+ className
39
+ ),
40
+ style: {
41
+ width: showExpanded ? "var(--size-sidebar-expanded)" : "var(--size-sidebar-collapsed)",
42
+ transitionDuration: "var(--duration-sidebar)"
43
+ },
44
+ children: [
45
+ header && /* @__PURE__ */ jsx(
46
+ "div",
47
+ {
48
+ className: cn(
49
+ "flex shrink-0 items-center border-b border-[var(--border-subtle)]",
50
+ showExpanded ? "h-[var(--size-topbar-height)] px-2" : "h-[var(--size-topbar-height)] justify-center px-0"
51
+ ),
52
+ children: header
53
+ }
54
+ ),
55
+ /* @__PURE__ */ jsx("nav", { className: "scrollbar-auto-hide min-h-0 flex-1 overflow-y-auto py-2", children: groups.map((group, groupIndex) => /* @__PURE__ */ jsxs("div", { children: [
56
+ groupIndex > 0 && /* @__PURE__ */ jsx("div", { className: "mx-3 my-1.5 border-t border-[var(--border-subtle)]" }),
57
+ showExpanded && /* @__PURE__ */ jsx("div", { className: "px-3 pb-1 pt-3 text-[10px] font-semibold uppercase tracking-[0.12em] text-[var(--text-tertiary)] first:pt-2", children: group.label }),
58
+ /* @__PURE__ */ jsx("div", { className: cn("px-2", !showExpanded && "py-1"), children: group.items.map((item) => {
59
+ const active = isItemActive(item.href, activeKey);
60
+ const Icon = item.icon;
61
+ const itemClassName = cn(
62
+ "flex w-full items-center rounded-[var(--radius-md)] transition-colors",
63
+ showExpanded ? "gap-2.5 px-3 py-2" : "justify-center p-2.5",
64
+ active ? "bg-[var(--bg-nav-item-active)] font-medium text-[var(--text-primary)]" : "text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)]"
65
+ );
66
+ const children = /* @__PURE__ */ jsxs(Fragment, { children: [
67
+ /* @__PURE__ */ jsx(
68
+ Icon,
69
+ {
70
+ className: cn(
71
+ "shrink-0",
72
+ showExpanded ? "h-4 w-4" : "h-[18px] w-[18px]"
73
+ )
74
+ }
75
+ ),
76
+ showExpanded && /* @__PURE__ */ jsx("span", { className: "truncate text-[13px]", children: item.label })
77
+ ] });
78
+ if (renderLink) {
79
+ return /* @__PURE__ */ jsx(React.Fragment, { children: renderLink(item.href, {
80
+ className: itemClassName,
81
+ children
82
+ }) }, item.key);
83
+ }
84
+ return /* @__PURE__ */ jsx(
85
+ "a",
86
+ {
87
+ href: item.href,
88
+ className: itemClassName,
89
+ children
90
+ },
91
+ item.key
92
+ );
93
+ }) })
94
+ ] }, group.label)) }),
95
+ footer,
96
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-[var(--border-subtle)] p-2", children: /* @__PURE__ */ jsx(
97
+ "button",
98
+ {
99
+ type: "button",
100
+ "aria-label": (
101
+ // Mirrors the visible-text branches below, isOverlay first: when the
102
+ // collapsed rail is hovered both isOverlay and showExpanded are true,
103
+ // and the button reads "Expand". Keying on showExpanded alone made the
104
+ // accessible name contradict the visible label (WCAG 2.5.3).
105
+ isOverlay ? "Expand sidebar" : showExpanded ? "Collapse sidebar" : "Expand sidebar"
106
+ ),
107
+ onClick: () => onCollapsedChange(!collapsed),
108
+ className: cn(
109
+ "flex w-full items-center rounded-[var(--radius-md)] p-2 text-[var(--text-tertiary)] transition-colors hover:bg-[var(--bg-hover)] hover:text-[var(--text-secondary)]",
110
+ !showExpanded ? "justify-center" : "gap-2"
111
+ ),
112
+ children: isOverlay ? /* @__PURE__ */ jsxs(Fragment, { children: [
113
+ /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }),
114
+ /* @__PURE__ */ jsx("span", { className: "text-[12px]", children: "Expand" })
115
+ ] }) : showExpanded ? /* @__PURE__ */ jsxs(Fragment, { children: [
116
+ /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }),
117
+ /* @__PURE__ */ jsx("span", { className: "text-[12px]", children: "Collapse" })
118
+ ] }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
119
+ }
120
+ ) })
121
+ ]
122
+ }
123
+ );
124
+ }
125
+ );
126
+ export {
127
+ Sidebar
128
+ };
@@ -0,0 +1,129 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { ChevronDown, SunMoon, LogOut } from "lucide-react";
3
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "../ui/dropdown-menu.js";
4
+ import { ThemeSwitch } from "../ui/theme-switch.js";
5
+ import { cn } from "../../lib/utils.js";
6
+ import { useAppShell } from "./app-shell-context.js";
7
+ function getInitials(name) {
8
+ return name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase();
9
+ }
10
+ function SidebarAccountMenu({
11
+ name,
12
+ role,
13
+ avatarUrl,
14
+ theme,
15
+ onThemeChange,
16
+ menuItems,
17
+ onSignOut,
18
+ collapsed: collapsedProp,
19
+ className
20
+ }) {
21
+ const shell = useAppShell();
22
+ const effectiveCollapsed = collapsedProp ?? shell?.effectiveCollapsed ?? false;
23
+ const showTheme = theme !== void 0 && onThemeChange !== void 0;
24
+ const hasItemsBelow = menuItems && menuItems.length > 0 || Boolean(onSignOut);
25
+ const avatar = avatarUrl ? /* @__PURE__ */ jsx(
26
+ "img",
27
+ {
28
+ src: avatarUrl,
29
+ alt: name,
30
+ className: "h-7 w-7 shrink-0 rounded-full object-cover"
31
+ }
32
+ ) : /* @__PURE__ */ jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-[var(--bg-tertiary)] text-[11px] font-semibold text-[var(--text-secondary)]", children: getInitials(name) });
33
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
34
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
35
+ "button",
36
+ {
37
+ type: "button",
38
+ className: cn(
39
+ "group flex w-full items-center rounded-[var(--radius-md)] transition-colors hover:bg-[var(--bg-hover)]",
40
+ effectiveCollapsed ? "justify-center p-1.5" : "gap-2.5 px-3 py-2",
41
+ className
42
+ ),
43
+ children: [
44
+ avatar,
45
+ !effectiveCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
46
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left text-[13px] font-medium text-[var(--text-primary)]", children: name }),
47
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-[var(--text-tertiary)] transition-transform group-data-[state=open]:rotate-180" })
48
+ ] })
49
+ ]
50
+ }
51
+ ) }),
52
+ /* @__PURE__ */ jsxs(
53
+ DropdownMenuContent,
54
+ {
55
+ side: "bottom",
56
+ align: "start",
57
+ sideOffset: 6,
58
+ className: "min-w-[220px]",
59
+ children: [
60
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-2 py-2", children: [
61
+ avatarUrl ? /* @__PURE__ */ jsx(
62
+ "img",
63
+ {
64
+ src: avatarUrl,
65
+ alt: name,
66
+ className: "h-8 w-8 shrink-0 rounded-full object-cover"
67
+ }
68
+ ) : /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--bg-tertiary)] text-[11px] font-semibold text-[var(--text-secondary)]", children: getInitials(name) }),
69
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
70
+ /* @__PURE__ */ jsx("div", { className: "truncate text-[13px] font-medium text-[var(--text-primary)]", children: name }),
71
+ role && /* @__PURE__ */ jsx("div", { className: "truncate text-[12px] text-[var(--text-secondary)]", children: role })
72
+ ] })
73
+ ] }),
74
+ /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-[var(--border-subtle)]" }),
75
+ showTheme && /* @__PURE__ */ jsxs(Fragment, { children: [
76
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-3 py-2", children: [
77
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
78
+ /* @__PURE__ */ jsx(SunMoon, { className: "h-4 w-4" }),
79
+ /* @__PURE__ */ jsx("span", { className: "text-[13px]", children: "Theme" })
80
+ ] }),
81
+ /* @__PURE__ */ jsx(
82
+ ThemeSwitch,
83
+ {
84
+ variant: "icon",
85
+ value: theme,
86
+ onValueChange: onThemeChange
87
+ }
88
+ )
89
+ ] }),
90
+ hasItemsBelow && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-[var(--border-subtle)]" })
91
+ ] }),
92
+ menuItems && menuItems.map((item) => {
93
+ const Icon = item.icon;
94
+ return /* @__PURE__ */ jsxs(
95
+ DropdownMenuItem,
96
+ {
97
+ onClick: item.onClick,
98
+ className: cn(
99
+ "gap-2 px-3 py-2",
100
+ item.variant === "destructive" && "text-red-600"
101
+ ),
102
+ children: [
103
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
104
+ item.label
105
+ ]
106
+ },
107
+ item.key
108
+ );
109
+ }),
110
+ menuItems && menuItems.length > 0 && onSignOut && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-[var(--border-subtle)]" }),
111
+ onSignOut && /* @__PURE__ */ jsxs(
112
+ DropdownMenuItem,
113
+ {
114
+ onClick: onSignOut,
115
+ className: "gap-2 px-3 py-2 text-red-600",
116
+ children: [
117
+ /* @__PURE__ */ jsx(LogOut, { className: "h-4 w-4" }),
118
+ "Sign Out"
119
+ ]
120
+ }
121
+ )
122
+ ]
123
+ }
124
+ )
125
+ ] });
126
+ }
127
+ export {
128
+ SidebarAccountMenu
129
+ };
@@ -0,0 +1,38 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ import { useAppShell } from "./app-shell-context.js";
5
+ function getInitials(name) {
6
+ return name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase();
7
+ }
8
+ const SidebarUser = React.forwardRef(
9
+ function SidebarUser2({ name, avatarUrl, collapsed: collapsedProp, className }, ref) {
10
+ const shell = useAppShell();
11
+ const effectiveCollapsed = collapsedProp ?? shell?.effectiveCollapsed ?? false;
12
+ return /* @__PURE__ */ jsxs(
13
+ "div",
14
+ {
15
+ ref,
16
+ className: cn(
17
+ "flex shrink-0 items-center border-t border-[var(--border-subtle)] p-2",
18
+ effectiveCollapsed ? "justify-center" : "gap-2.5 px-3",
19
+ className
20
+ ),
21
+ children: [
22
+ avatarUrl ? /* @__PURE__ */ jsx(
23
+ "img",
24
+ {
25
+ src: avatarUrl,
26
+ alt: name,
27
+ className: "h-8 w-8 shrink-0 rounded-full object-cover"
28
+ }
29
+ ) : /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--bg-tertiary)] text-[11px] font-semibold text-[var(--text-secondary)]", children: getInitials(name) }),
30
+ !effectiveCollapsed && /* @__PURE__ */ jsx("span", { className: "truncate text-[13px] font-medium text-[var(--text-primary)]", children: name })
31
+ ]
32
+ }
33
+ );
34
+ }
35
+ );
36
+ export {
37
+ SidebarUser
38
+ };
@@ -0,0 +1,25 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ const TopBar = React.forwardRef(
5
+ function TopBar2({ children, actions, className }, ref) {
6
+ return /* @__PURE__ */ jsxs(
7
+ "header",
8
+ {
9
+ ref,
10
+ className: cn(
11
+ "flex shrink-0 items-center justify-between border-b border-[var(--border-subtle)] bg-[var(--bg-body)] px-6",
12
+ className
13
+ ),
14
+ style: { height: "var(--size-topbar-height)" },
15
+ children: [
16
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children }),
17
+ actions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: actions })
18
+ ]
19
+ }
20
+ );
21
+ }
22
+ );
23
+ export {
24
+ TopBar
25
+ };
@@ -0,0 +1,9 @@
1
+ import { useContext, createContext } from "react";
2
+ const AppShellContext = createContext(null);
3
+ function useAppShell() {
4
+ return useContext(AppShellContext);
5
+ }
6
+ export {
7
+ AppShellContext,
8
+ useAppShell
9
+ };
@@ -0,0 +1,31 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ import { cva } from "class-variance-authority";
4
+ import { cn } from "../../lib/utils.js";
5
+ const badgeVariants = cva(
6
+ "inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-medium leading-[1.4]",
7
+ {
8
+ variants: {
9
+ variant: {
10
+ success: "bg-[var(--tag-green-bg)] text-[var(--tag-green-text)]",
11
+ warning: "bg-[var(--tag-orange-bg)] text-[var(--tag-orange-text)]",
12
+ danger: "bg-[var(--tag-pink-bg)] text-[var(--tag-pink-text)]",
13
+ info: "bg-[var(--tag-blue-bg)] text-[var(--tag-blue-text)]",
14
+ neutral: "bg-[var(--tag-gray-bg)] text-[var(--tag-gray-text)]",
15
+ purple: "bg-[var(--tag-purple-bg)] text-[var(--tag-purple-text)]",
16
+ sky: "bg-[var(--tag-sky-bg)] text-[var(--tag-sky-text)]",
17
+ indigo: "bg-[var(--tag-indigo-bg)] text-[var(--tag-indigo-text)]"
18
+ }
19
+ },
20
+ defaultVariants: {
21
+ variant: "neutral"
22
+ }
23
+ }
24
+ );
25
+ function Badge({ className, variant, ...props }) {
26
+ return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
27
+ }
28
+ export {
29
+ Badge,
30
+ badgeVariants
31
+ };
@@ -0,0 +1,25 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ function ButtonFooter({
5
+ children,
6
+ className,
7
+ align = "stretch",
8
+ ...props
9
+ }) {
10
+ return /* @__PURE__ */ jsx(
11
+ "div",
12
+ {
13
+ className: cn(
14
+ "flex gap-2 border-t border-[var(--border-subtle)] pt-4",
15
+ align === "stretch" ? "[&>*]:flex-1" : "justify-end",
16
+ className
17
+ ),
18
+ ...props,
19
+ children
20
+ }
21
+ );
22
+ }
23
+ export {
24
+ ButtonFooter
25
+ };
@@ -0,0 +1,44 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { Slot } from "@radix-ui/react-slot";
4
+ import { cva } from "class-variance-authority";
5
+ import { cn } from "../../lib/utils.js";
6
+ const buttonVariants = cva(
7
+ "inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-md text-[13px] font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-[var(--accent-primary)] text-[var(--text-on-accent)] hover:opacity-90",
12
+ secondary: "border border-[var(--border-subtle)] bg-[var(--bg-surface)] text-[var(--text-secondary)] hover:border-[var(--border-focus)] hover:text-[var(--text-primary)]",
13
+ ghost: "bg-transparent text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)]"
14
+ },
15
+ size: {
16
+ default: "h-[var(--size-control-md)] px-4",
17
+ sm: "h-[var(--size-control-sm)] rounded-md px-3 text-[12px]",
18
+ icon: "h-[var(--size-control-md)] w-[var(--size-control-md)]"
19
+ }
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ size: "default"
24
+ }
25
+ }
26
+ );
27
+ const Button = React.forwardRef(
28
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
29
+ const Comp = asChild ? Slot : "button";
30
+ return /* @__PURE__ */ jsx(
31
+ Comp,
32
+ {
33
+ className: cn(buttonVariants({ variant, size, className })),
34
+ ref,
35
+ ...props
36
+ }
37
+ );
38
+ }
39
+ );
40
+ Button.displayName = "Button";
41
+ export {
42
+ Button,
43
+ buttonVariants
44
+ };
@@ -0,0 +1,24 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
4
+ import { Minus, Check } from "lucide-react";
5
+ import { cn } from "../../lib/utils.js";
6
+ const Checkbox = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
7
+ CheckboxPrimitive.Root,
8
+ {
9
+ ref,
10
+ className: cn(
11
+ "peer h-4 w-4 shrink-0 rounded-sm border border-[var(--border-subtle)] bg-[var(--bg-surface)] text-[var(--text-primary)] outline-none focus-visible:ring-1 focus-visible:ring-[var(--border-focus)] data-[state=checked]:border-[var(--accent-primary)] data-[state=checked]:bg-[var(--accent-primary)] data-[state=indeterminate]:border-[var(--accent-primary)] data-[state=indeterminate]:bg-[var(--accent-primary)]",
12
+ className
13
+ ),
14
+ ...props,
15
+ children: /* @__PURE__ */ jsxs(CheckboxPrimitive.Indicator, { className: "group flex items-center justify-center text-[var(--text-on-accent)]", children: [
16
+ /* @__PURE__ */ jsx(Minus, { className: "hidden h-3 w-3 group-data-[state=indeterminate]:block" }),
17
+ /* @__PURE__ */ jsx(Check, { className: "h-3 w-3 group-data-[state=indeterminate]:hidden" })
18
+ ] })
19
+ }
20
+ ));
21
+ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
22
+ export {
23
+ Checkbox
24
+ };
@@ -0,0 +1,179 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { Command as Command$1 } from "cmdk";
4
+ import { ChevronsUpDown, Check, Search } from "lucide-react";
5
+ import { cn } from "../../lib/utils.js";
6
+ import { Popover, PopoverTrigger, PopoverContent } from "./popover.js";
7
+ const Command = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
8
+ Command$1,
9
+ {
10
+ ref,
11
+ className: cn(
12
+ "flex h-full w-full flex-col overflow-hidden rounded-md bg-[var(--bg-surface)] text-[var(--text-primary)]",
13
+ className
14
+ ),
15
+ ...props
16
+ }
17
+ ));
18
+ Command.displayName = "Command";
19
+ const CommandInput = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { className: "flex items-center border-b border-[var(--border-subtle)] px-2.5", children: [
20
+ /* @__PURE__ */ jsx(Search, { className: "mr-2 h-3.5 w-3.5 shrink-0 text-[var(--text-tertiary)]" }),
21
+ /* @__PURE__ */ jsx(
22
+ Command$1.Input,
23
+ {
24
+ ref,
25
+ className: cn(
26
+ "flex h-9 w-full bg-transparent py-2 text-[13px] text-[var(--text-primary)] outline-none placeholder:text-[var(--text-tertiary)]",
27
+ className
28
+ ),
29
+ ...props
30
+ }
31
+ )
32
+ ] }));
33
+ CommandInput.displayName = Command$1.Input.displayName;
34
+ const CommandList = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35
+ Command$1.List,
36
+ {
37
+ ref,
38
+ className: cn("max-h-[280px] overflow-y-auto overflow-x-hidden p-1", className),
39
+ ...props
40
+ }
41
+ ));
42
+ CommandList.displayName = Command$1.List.displayName;
43
+ const CommandEmpty = React.forwardRef((props, ref) => /* @__PURE__ */ jsx(
44
+ Command$1.Empty,
45
+ {
46
+ ref,
47
+ className: "py-6 text-center text-[12px] text-[var(--text-tertiary)]",
48
+ ...props
49
+ }
50
+ ));
51
+ CommandEmpty.displayName = Command$1.Empty.displayName;
52
+ const CommandGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
53
+ Command$1.Group,
54
+ {
55
+ ref,
56
+ className: cn(
57
+ "overflow-hidden p-1 text-[var(--text-primary)] [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-[10px] [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider [&_[cmdk-group-heading]]:text-[var(--text-tertiary)]",
58
+ className
59
+ ),
60
+ ...props
61
+ }
62
+ ));
63
+ CommandGroup.displayName = Command$1.Group.displayName;
64
+ const CommandItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
65
+ Command$1.Item,
66
+ {
67
+ ref,
68
+ className: cn(
69
+ "relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] outline-none",
70
+ "data-[selected=true]:bg-[var(--bg-hover)] data-[selected=true]:text-[var(--text-primary)]",
71
+ "data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
72
+ className
73
+ ),
74
+ ...props
75
+ }
76
+ ));
77
+ CommandItem.displayName = Command$1.Item.displayName;
78
+ function Combobox({
79
+ value,
80
+ onChange,
81
+ options,
82
+ placeholder = "Select...",
83
+ searchPlaceholder = "Search...",
84
+ emptyText = "No results.",
85
+ disabled,
86
+ clearable = true,
87
+ className,
88
+ triggerClassName,
89
+ contentClassName,
90
+ renderSelected,
91
+ triggerAriaLabel
92
+ }) {
93
+ const [open, setOpen] = React.useState(false);
94
+ const selected = React.useMemo(
95
+ () => options.find((o) => o.value === value) ?? null,
96
+ [options, value]
97
+ );
98
+ return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
99
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
100
+ "button",
101
+ {
102
+ type: "button",
103
+ disabled,
104
+ "aria-expanded": open,
105
+ "aria-haspopup": "listbox",
106
+ "aria-label": triggerAriaLabel,
107
+ className: cn(
108
+ "flex h-9 w-full items-center justify-between gap-2 rounded-md border border-[var(--border-subtle)] bg-[var(--bg-surface)] px-2.5 text-left text-[13px] text-[var(--text-primary)] outline-none transition-colors",
109
+ "hover:border-[var(--border-focus)] focus-visible:border-[var(--border-focus)] focus-visible:ring-2 focus-visible:ring-[var(--border-focus)]",
110
+ "disabled:cursor-not-allowed disabled:opacity-50",
111
+ triggerClassName
112
+ ),
113
+ children: [
114
+ /* @__PURE__ */ jsx("span", { className: cn("truncate", !selected && "text-[var(--text-tertiary)]"), children: selected ? renderSelected ? renderSelected(selected) : selected.label : placeholder }),
115
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-[var(--text-tertiary)]" })
116
+ ]
117
+ }
118
+ ) }),
119
+ /* @__PURE__ */ jsx(
120
+ PopoverContent,
121
+ {
122
+ align: "start",
123
+ className: cn("w-[var(--radix-popover-trigger-width)] p-0", contentClassName),
124
+ children: /* @__PURE__ */ jsxs(
125
+ Command,
126
+ {
127
+ filter: (itemValue, search) => itemValue.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
128
+ children: [
129
+ /* @__PURE__ */ jsx(CommandInput, { placeholder: searchPlaceholder }),
130
+ /* @__PURE__ */ jsxs(CommandList, { children: [
131
+ /* @__PURE__ */ jsx(CommandEmpty, { children: emptyText }),
132
+ /* @__PURE__ */ jsx(CommandGroup, { children: options.map((option) => {
133
+ const isSelected = option.value === value;
134
+ return /* @__PURE__ */ jsxs(
135
+ CommandItem,
136
+ {
137
+ value: `${option.label} ${option.value}`,
138
+ disabled: option.disabled,
139
+ onSelect: () => {
140
+ if (isSelected && clearable) onChange(null);
141
+ else onChange(option.value);
142
+ setOpen(false);
143
+ },
144
+ children: [
145
+ /* @__PURE__ */ jsx(
146
+ Check,
147
+ {
148
+ className: cn(
149
+ "h-3.5 w-3.5 shrink-0",
150
+ isSelected ? "text-[var(--accent-primary)]" : "text-transparent"
151
+ )
152
+ }
153
+ ),
154
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col", children: [
155
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: option.label }),
156
+ option.description && /* @__PURE__ */ jsx("span", { className: "truncate text-[11px] text-[var(--text-tertiary)]", children: option.description })
157
+ ] })
158
+ ]
159
+ },
160
+ option.value
161
+ );
162
+ }) })
163
+ ] })
164
+ ]
165
+ }
166
+ )
167
+ }
168
+ )
169
+ ] }) });
170
+ }
171
+ export {
172
+ Combobox,
173
+ Command,
174
+ CommandEmpty,
175
+ CommandGroup,
176
+ CommandInput,
177
+ CommandItem,
178
+ CommandList
179
+ };