@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,127 @@
1
+ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
+ import { AlertTriangle } from "lucide-react";
3
+ import { CopyableText } from "../CopyableText.js";
4
+ const fmtIn = (v) => v.toLocaleString("en-US");
5
+ const fmtOut = (v) => v.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
6
+ function AmountCell({
7
+ inAmount,
8
+ inCurrency,
9
+ outAmount,
10
+ outCurrency,
11
+ inAmountConfirmed,
12
+ outAmountConfirmed,
13
+ mutedCurrency
14
+ }) {
15
+ const inMismatch = inAmountConfirmed !== void 0 && inAmountConfirmed > 0 && inAmountConfirmed !== inAmount;
16
+ const outMismatch = outAmountConfirmed !== void 0 && outAmountConfirmed > 0 && outAmountConfirmed !== outAmount;
17
+ const inCurrencyEl = mutedCurrency ? /* @__PURE__ */ jsx("span", { className: "text-[var(--text-secondary)] font-normal", children: inCurrency }) : inCurrency;
18
+ const outCurrencyEl = mutedCurrency ? /* @__PURE__ */ jsx("span", { className: "text-[var(--text-secondary)] font-normal", children: outCurrency }) : outCurrency;
19
+ return /* @__PURE__ */ jsxs("div", { children: [
20
+ inMismatch && inAmountConfirmed !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
21
+ /* @__PURE__ */ jsxs(
22
+ CopyableText,
23
+ {
24
+ value: String(inAmountConfirmed),
25
+ title: "Copy in amount confirmed",
26
+ className: "w-full",
27
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
28
+ children: [
29
+ /* @__PURE__ */ jsx(
30
+ AlertTriangle,
31
+ {
32
+ className: "inline h-3 w-3 mr-0.5 text-[var(--tag-orange-text)]",
33
+ "aria-hidden": true
34
+ }
35
+ ),
36
+ fmtIn(inAmountConfirmed),
37
+ " ",
38
+ inCurrencyEl
39
+ ]
40
+ }
41
+ ),
42
+ /* @__PURE__ */ jsxs(
43
+ CopyableText,
44
+ {
45
+ value: String(inAmount),
46
+ title: "Copy in amount",
47
+ className: "w-full",
48
+ textClassName: "text-[12px] font-mono text-[var(--text-secondary)] line-through",
49
+ children: [
50
+ fmtIn(inAmount),
51
+ " ",
52
+ inCurrencyEl
53
+ ]
54
+ }
55
+ )
56
+ ] }) : /* @__PURE__ */ jsxs(
57
+ CopyableText,
58
+ {
59
+ value: String(inAmount),
60
+ title: "Copy in amount",
61
+ className: "w-full",
62
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
63
+ children: [
64
+ fmtIn(inAmount),
65
+ " ",
66
+ inCurrencyEl
67
+ ]
68
+ }
69
+ ),
70
+ outMismatch && outAmountConfirmed !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
71
+ /* @__PURE__ */ jsxs(
72
+ CopyableText,
73
+ {
74
+ value: String(outAmountConfirmed),
75
+ title: "Copy out amount confirmed",
76
+ className: "w-full",
77
+ textClassName: "text-[12px] font-mono text-[var(--text-primary)]",
78
+ children: [
79
+ /* @__PURE__ */ jsx(
80
+ AlertTriangle,
81
+ {
82
+ className: "inline h-3 w-3 mr-0.5 text-[var(--tag-orange-text)]",
83
+ "aria-hidden": true
84
+ }
85
+ ),
86
+ "→ ",
87
+ fmtOut(outAmountConfirmed),
88
+ " ",
89
+ outCurrencyEl
90
+ ]
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsxs(
94
+ CopyableText,
95
+ {
96
+ value: String(outAmount),
97
+ title: "Copy out amount",
98
+ className: "w-full",
99
+ textClassName: "text-[12px] font-mono text-[var(--text-secondary)] line-through",
100
+ children: [
101
+ "→ ",
102
+ fmtOut(outAmount),
103
+ " ",
104
+ outCurrencyEl
105
+ ]
106
+ }
107
+ )
108
+ ] }) : /* @__PURE__ */ jsxs(
109
+ CopyableText,
110
+ {
111
+ value: String(outAmount),
112
+ title: "Copy out amount",
113
+ className: "w-full",
114
+ textClassName: "text-[12px] font-mono text-[var(--text-secondary)]",
115
+ children: [
116
+ "→ ",
117
+ fmtOut(outAmount),
118
+ " ",
119
+ outCurrencyEl
120
+ ]
121
+ }
122
+ )
123
+ ] });
124
+ }
125
+ export {
126
+ AmountCell
127
+ };
@@ -0,0 +1,115 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { CircleDashed, Check, AlertTriangle } from "lucide-react";
3
+ import { CopyableText } from "../CopyableText.js";
4
+ const fmt = (v) => v.toLocaleString("en-US");
5
+ function ConfirmedAmountCell({
6
+ value,
7
+ currency,
8
+ confirmedValue,
9
+ copyTitle = "Copy",
10
+ confirmedCopyTitle = "Copy confirmed",
11
+ mutedCurrency
12
+ }) {
13
+ const primaryCurrency = mutedCurrency ? /* @__PURE__ */ jsx("span", { className: "text-[var(--text-secondary)] font-normal", children: currency }) : currency;
14
+ const secondaryCurrency = mutedCurrency ? /* @__PURE__ */ jsx("span", { className: "text-[var(--text-secondary)] font-normal", children: currency }) : currency;
15
+ if (confirmedValue === void 0 || confirmedValue === null) {
16
+ return /* @__PURE__ */ jsxs(
17
+ CopyableText,
18
+ {
19
+ value: String(value),
20
+ title: copyTitle,
21
+ className: "w-full",
22
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
23
+ children: [
24
+ fmt(value),
25
+ " ",
26
+ primaryCurrency
27
+ ]
28
+ }
29
+ );
30
+ }
31
+ if (confirmedValue === 0 && value > 0) {
32
+ return /* @__PURE__ */ jsxs("div", { children: [
33
+ /* @__PURE__ */ jsxs(
34
+ CopyableText,
35
+ {
36
+ value: String(value),
37
+ title: copyTitle,
38
+ className: "w-full",
39
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
40
+ children: [
41
+ fmt(value),
42
+ " ",
43
+ primaryCurrency
44
+ ]
45
+ }
46
+ ),
47
+ /* @__PURE__ */ jsx(
48
+ "div",
49
+ {
50
+ className: "text-[11px] text-[var(--text-secondary)]",
51
+ title: "Not confirmed",
52
+ "aria-label": "Not confirmed",
53
+ children: /* @__PURE__ */ jsx(CircleDashed, { className: "inline h-3 w-3", "aria-hidden": true })
54
+ }
55
+ )
56
+ ] });
57
+ }
58
+ if (confirmedValue === value) {
59
+ return /* @__PURE__ */ jsxs(
60
+ CopyableText,
61
+ {
62
+ value: String(value),
63
+ title: copyTitle,
64
+ className: "w-full",
65
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
66
+ children: [
67
+ /* @__PURE__ */ jsx(Check, { className: "inline h-3 w-3 mr-0.5 text-[var(--text-tertiary)]", "aria-hidden": true }),
68
+ fmt(value),
69
+ " ",
70
+ primaryCurrency
71
+ ]
72
+ }
73
+ );
74
+ }
75
+ return /* @__PURE__ */ jsxs("div", { children: [
76
+ /* @__PURE__ */ jsxs(
77
+ CopyableText,
78
+ {
79
+ value: String(confirmedValue),
80
+ title: confirmedCopyTitle,
81
+ className: "w-full",
82
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
83
+ children: [
84
+ /* @__PURE__ */ jsx(
85
+ AlertTriangle,
86
+ {
87
+ className: "inline h-3 w-3 mr-0.5 text-[var(--tag-orange-text)]",
88
+ "aria-hidden": true
89
+ }
90
+ ),
91
+ fmt(confirmedValue),
92
+ " ",
93
+ primaryCurrency
94
+ ]
95
+ }
96
+ ),
97
+ /* @__PURE__ */ jsxs(
98
+ CopyableText,
99
+ {
100
+ value: String(value),
101
+ title: copyTitle,
102
+ className: "w-full",
103
+ textClassName: "text-[12px] font-mono text-[var(--text-secondary)] line-through",
104
+ children: [
105
+ fmt(value),
106
+ " ",
107
+ secondaryCurrency
108
+ ]
109
+ }
110
+ )
111
+ ] });
112
+ }
113
+ export {
114
+ ConfirmedAmountCell
115
+ };
@@ -0,0 +1,26 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { CopyableText } from "../CopyableText.js";
3
+ function CurrencyAmountCell({
4
+ value,
5
+ currency,
6
+ copyTitle = "Copy",
7
+ mutedCurrency
8
+ }) {
9
+ return /* @__PURE__ */ jsxs(
10
+ CopyableText,
11
+ {
12
+ value: String(value),
13
+ title: copyTitle,
14
+ className: "w-full",
15
+ textClassName: "text-[13px] font-semibold text-[var(--text-primary)]",
16
+ children: [
17
+ value.toLocaleString("en-US"),
18
+ " ",
19
+ mutedCurrency ? /* @__PURE__ */ jsx("span", { className: "text-[var(--text-secondary)] font-normal", children: currency }) : currency
20
+ ]
21
+ }
22
+ );
23
+ }
24
+ export {
25
+ CurrencyAmountCell
26
+ };
@@ -0,0 +1,59 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { CopyableText } from "../CopyableText.js";
3
+ import { truncateMiddle } from "./MonoIdCell.js";
4
+ function applyMiddleTruncate(value, config) {
5
+ if (!config) return value;
6
+ const head = typeof config === "object" ? config.head ?? 6 : 6;
7
+ const tail = typeof config === "object" ? config.tail ?? 6 : 6;
8
+ return truncateMiddle(value, head, tail, head + tail + 2);
9
+ }
10
+ function DualLineCell({
11
+ primary,
12
+ secondary,
13
+ primaryCopyTitle = "Copy",
14
+ secondaryCopyTitle = "Copy",
15
+ primaryVariant = "default",
16
+ primaryLabel,
17
+ secondaryLabel,
18
+ equalWeight = false,
19
+ primaryTruncateMiddle,
20
+ secondaryTruncateMiddle
21
+ }) {
22
+ const primaryTextClass = primaryVariant === "mono" ? "font-mono text-[11px]" : "font-semibold text-[var(--text-primary)]";
23
+ const secondaryColour = equalWeight ? "text-[var(--text-primary)]" : "text-[var(--text-secondary)]";
24
+ const primaryDisplay = primaryVariant === "mono" ? applyMiddleTruncate(primary, primaryTruncateMiddle) : primary;
25
+ const secondaryDisplay = applyMiddleTruncate(secondary, secondaryTruncateMiddle);
26
+ const primaryContent = primaryLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
27
+ /* @__PURE__ */ jsx("span", { className: "mr-1 text-[10px] text-[var(--text-secondary)]", children: primaryLabel }),
28
+ /* @__PURE__ */ jsx("span", { title: primary, children: primaryDisplay })
29
+ ] }) : /* @__PURE__ */ jsx("span", { title: primary, children: primaryDisplay });
30
+ const secondaryContent = secondaryLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
31
+ /* @__PURE__ */ jsx("span", { className: "mr-1 text-[10px] text-[var(--text-secondary)]", children: secondaryLabel }),
32
+ /* @__PURE__ */ jsx("span", { title: secondary, children: secondaryDisplay })
33
+ ] }) : /* @__PURE__ */ jsx("span", { title: secondary, children: secondaryDisplay });
34
+ return /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
35
+ /* @__PURE__ */ jsx(
36
+ CopyableText,
37
+ {
38
+ value: primary,
39
+ title: primaryCopyTitle,
40
+ className: "w-full",
41
+ textClassName: primaryTextClass,
42
+ children: primaryContent
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsx(
46
+ CopyableText,
47
+ {
48
+ value: secondary,
49
+ title: secondaryCopyTitle,
50
+ className: "w-full",
51
+ textClassName: `font-mono text-[11px] ${secondaryColour}`,
52
+ children: secondaryContent
53
+ }
54
+ )
55
+ ] });
56
+ }
57
+ export {
58
+ DualLineCell
59
+ };
@@ -0,0 +1,9 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Badge } from "../../ui/badge.js";
3
+ import { formatEnumLabel } from "../../../lib/format-enum.js";
4
+ function EnumBadgeCell({ value, variantMap, label, className }) {
5
+ return /* @__PURE__ */ jsx(Badge, { variant: variantMap[value], className, children: label ?? formatEnumLabel(value) });
6
+ }
7
+ export {
8
+ EnumBadgeCell
9
+ };
@@ -0,0 +1,31 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { CopyableText } from "../CopyableText.js";
3
+ function truncateMiddle(value, head, tail, threshold) {
4
+ if (value.length < threshold) return value;
5
+ return `${value.slice(0, head)}…${value.slice(-tail)}`;
6
+ }
7
+ function MonoIdCell({
8
+ value,
9
+ copyTitle = "Copy",
10
+ truncate = true,
11
+ truncateHead = 6,
12
+ truncateTail = 6,
13
+ truncateThreshold
14
+ }) {
15
+ const threshold = truncateThreshold ?? truncateHead + truncateTail + 2;
16
+ const display = truncate ? truncateMiddle(value, truncateHead, truncateTail, threshold) : value;
17
+ return /* @__PURE__ */ jsx(
18
+ CopyableText,
19
+ {
20
+ value,
21
+ title: copyTitle,
22
+ className: "w-full",
23
+ textClassName: "font-mono text-[11px]",
24
+ children: /* @__PURE__ */ jsx("span", { title: value, children: display })
25
+ }
26
+ );
27
+ }
28
+ export {
29
+ MonoIdCell,
30
+ truncateMiddle
31
+ };
@@ -0,0 +1,39 @@
1
+ import { useState, useRef, useCallback, useMemo } from "react";
2
+ function useColumnResize(defaults, initialWidths) {
3
+ const [widths, setWidths] = useState(() => {
4
+ const w = {};
5
+ for (const [id, m] of Object.entries(defaults)) w[id] = m.minW;
6
+ return initialWidths ? { ...w, ...initialWidths } : w;
7
+ });
8
+ const resizing = useRef(null);
9
+ const onPointerDown = useCallback(
10
+ (colId, e) => {
11
+ e.preventDefault();
12
+ e.stopPropagation();
13
+ resizing.current = { colId, startX: e.clientX, startW: widths[colId] ?? defaults[colId]?.minW ?? 100 };
14
+ const onMove = (ev) => {
15
+ if (!resizing.current) return;
16
+ const { colId: resizingColId, startX, startW } = resizing.current;
17
+ const diff = ev.clientX - startX;
18
+ const newW = Math.max(36, startW + diff);
19
+ setWidths((prev) => ({ ...prev, [resizingColId]: newW }));
20
+ };
21
+ const onUp = () => {
22
+ resizing.current = null;
23
+ document.removeEventListener("pointermove", onMove);
24
+ document.removeEventListener("pointerup", onUp);
25
+ };
26
+ document.addEventListener("pointermove", onMove);
27
+ document.addEventListener("pointerup", onUp);
28
+ },
29
+ [widths, defaults]
30
+ );
31
+ const totalWidth = useMemo(
32
+ () => Object.values(widths).reduce((s, w) => s + w, 0),
33
+ [widths]
34
+ );
35
+ return { widths, totalWidth, onPointerDown, setWidths };
36
+ }
37
+ export {
38
+ useColumnResize
39
+ };
@@ -0,0 +1,40 @@
1
+ import { useState } from "react";
2
+ function useRowDrag(source, onReorder) {
3
+ const [dragRowIdx, setDragRowIdx] = useState(null);
4
+ const [dropTargetIdx, setDropTargetIdx] = useState(null);
5
+ function getDragProps(rowIndex) {
6
+ return {
7
+ draggable: true,
8
+ onDragStart: (e) => {
9
+ setDragRowIdx(rowIndex);
10
+ e.dataTransfer.effectAllowed = "move";
11
+ e.dataTransfer.setData("text/plain", "");
12
+ },
13
+ onDragOver: (e) => {
14
+ e.preventDefault();
15
+ e.dataTransfer.dropEffect = "move";
16
+ setDropTargetIdx(rowIndex);
17
+ },
18
+ onDragLeave: () => setDropTargetIdx(null),
19
+ onDrop: (e) => {
20
+ e.preventDefault();
21
+ if (dragRowIdx !== null && dragRowIdx !== rowIndex) {
22
+ const items = [...source];
23
+ const [moved] = items.splice(dragRowIdx, 1);
24
+ items.splice(rowIndex, 0, moved);
25
+ onReorder(items);
26
+ }
27
+ setDragRowIdx(null);
28
+ setDropTargetIdx(null);
29
+ },
30
+ onDragEnd: () => {
31
+ setDragRowIdx(null);
32
+ setDropTargetIdx(null);
33
+ }
34
+ };
35
+ }
36
+ return { dragRowIdx, dropTargetIdx, getDragProps };
37
+ }
38
+ export {
39
+ useRowDrag
40
+ };
@@ -0,0 +1,14 @@
1
+ import "react";
2
+ function getVisiblePageNumbers(currentPage, totalPages, maxVisible = 5) {
3
+ const pages = [];
4
+ let start = Math.max(1, currentPage - Math.floor(maxVisible / 2));
5
+ const end = Math.min(totalPages, start + maxVisible - 1);
6
+ start = Math.max(1, end - maxVisible + 1);
7
+ for (let i = start; i <= end; i += 1) {
8
+ pages.push(i);
9
+ }
10
+ return pages;
11
+ }
12
+ export {
13
+ getVisiblePageNumbers
14
+ };
@@ -0,0 +1,35 @@
1
+ import { useState, useCallback } from "react";
2
+ function useTableSort(onSortChange) {
3
+ const [sortState, setSortState] = useState({});
4
+ const toggleSort = useCallback((columnId) => {
5
+ setSortState((prev) => {
6
+ const current = prev[columnId] ?? false;
7
+ const next = current === false ? "asc" : current === "asc" ? "desc" : false;
8
+ const reset = {};
9
+ for (const k of Object.keys(prev)) reset[k] = false;
10
+ reset[columnId] = next;
11
+ return reset;
12
+ });
13
+ onSortChange?.();
14
+ }, [onSortChange]);
15
+ const applySorting = useCallback(
16
+ (items, getSortValue) => {
17
+ const activeSortCol = Object.entries(sortState).find(([, dir2]) => dir2 !== false);
18
+ if (!activeSortCol) return items;
19
+ const [col, dir] = activeSortCol;
20
+ const sorted = [...items];
21
+ sorted.sort((a, b) => {
22
+ const va = getSortValue(a, col);
23
+ const vb = getSortValue(b, col);
24
+ const cmp = va < vb ? -1 : va > vb ? 1 : 0;
25
+ return dir === "asc" ? cmp : -cmp;
26
+ });
27
+ return sorted;
28
+ },
29
+ [sortState]
30
+ );
31
+ return { sortState, toggleSort, applySorting };
32
+ }
33
+ export {
34
+ useTableSort
35
+ };
@@ -0,0 +1,34 @@
1
+ function applyManagedChanges(orch, changes) {
2
+ const activeIds = new Set(orch.columnFilters.map((f) => f.columnId));
3
+ for (const change of changes) {
4
+ if (change.action === "remove") {
5
+ if (activeIds.has(change.columnId)) orch.handleRemoveColumnFilter(change.columnId);
6
+ continue;
7
+ }
8
+ orch.handleSetColumnFilter(change.columnId, change.value);
9
+ }
10
+ }
11
+ function clearManagedFilters(orch, managedColumnIds) {
12
+ const activeIds = new Set(orch.columnFilters.map((f) => f.columnId));
13
+ for (const id of managedColumnIds) {
14
+ if (activeIds.has(id)) orch.handleRemoveColumnFilter(id);
15
+ }
16
+ }
17
+ function isFilterValueEmpty(v) {
18
+ if (v === void 0) return true;
19
+ if (Array.isArray(v)) return v.length === 0 || v.every((x) => x === "" || x == null);
20
+ if (typeof v === "string") return v.length === 0;
21
+ if (typeof v === "object" && v !== null) {
22
+ return Object.values(v).every((x) => isFilterValueEmpty(x));
23
+ }
24
+ return false;
25
+ }
26
+ function hasActiveManagedFilters(filters, managedFieldIds) {
27
+ const managed = new Set(managedFieldIds);
28
+ return filters.some((f) => managed.has(f.columnId) && !isFilterValueEmpty(f.value));
29
+ }
30
+ export {
31
+ applyManagedChanges,
32
+ clearManagedFilters,
33
+ hasActiveManagedFilters
34
+ };
@@ -0,0 +1,25 @@
1
+ function stickyStyle(meta, isHeader) {
2
+ if (isHeader) {
3
+ return {
4
+ position: "sticky",
5
+ top: 0,
6
+ zIndex: meta?.sticky ? 30 : 10,
7
+ ...meta?.sticky ? { [meta.sticky]: meta.stickyOffset ?? 0 } : {}
8
+ };
9
+ }
10
+ if (!meta?.sticky) return void 0;
11
+ return {
12
+ position: "sticky",
13
+ [meta.sticky]: meta.stickyOffset ?? 0,
14
+ zIndex: 20
15
+ };
16
+ }
17
+ function stickyBorderClass(meta) {
18
+ const edge = meta?.borderEdge !== void 0 ? meta.borderEdge : meta?.sticky === "left" ? "right" : meta?.sticky === "right" ? "left" : null;
19
+ if (!edge) return "";
20
+ return edge === "right" ? "[box-shadow:1px_0_0_0_var(--border-subtle)]" : "[box-shadow:-1px_0_0_0_var(--border-subtle)]";
21
+ }
22
+ export {
23
+ stickyBorderClass,
24
+ stickyStyle
25
+ };
@@ -0,0 +1,113 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ import { AppShellContext } from "./app-shell-context.js";
5
+ import { Sidebar } from "./Sidebar.js";
6
+ import { TopBar } from "./TopBar.js";
7
+ const HOVER_DELAY = 200;
8
+ function AppShellRoot({
9
+ collapsed: controlledCollapsed,
10
+ defaultCollapsed = false,
11
+ onCollapsedChange: onCollapsedChangeProp,
12
+ children,
13
+ className
14
+ }) {
15
+ const isControlled = controlledCollapsed !== void 0;
16
+ const [internalCollapsed, setInternalCollapsed] = React.useState(defaultCollapsed);
17
+ const collapsed = isControlled ? controlledCollapsed : internalCollapsed;
18
+ const [hovering, setHovering] = React.useState(false);
19
+ const hoverTimerRef = React.useRef(
20
+ null
21
+ );
22
+ const onCollapsedChange = React.useCallback(
23
+ (next) => {
24
+ if (!isControlled) setInternalCollapsed(next);
25
+ onCollapsedChangeProp?.(next);
26
+ },
27
+ [isControlled, onCollapsedChangeProp]
28
+ );
29
+ React.useEffect(() => {
30
+ function handleKeyDown(e) {
31
+ if (e.key === "b" && (e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) {
32
+ const tag = e.target?.tagName;
33
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return;
34
+ if (e.target?.isContentEditable) return;
35
+ e.preventDefault();
36
+ onCollapsedChange(!collapsed);
37
+ }
38
+ }
39
+ document.addEventListener("keydown", handleKeyDown);
40
+ return () => document.removeEventListener("keydown", handleKeyDown);
41
+ }, [collapsed, onCollapsedChange]);
42
+ const handleMouseEnter = React.useCallback(() => {
43
+ if (!collapsed) return;
44
+ hoverTimerRef.current = setTimeout(() => setHovering(true), HOVER_DELAY);
45
+ }, [collapsed]);
46
+ const handleMouseLeave = React.useCallback(() => {
47
+ if (hoverTimerRef.current) {
48
+ clearTimeout(hoverTimerRef.current);
49
+ hoverTimerRef.current = null;
50
+ }
51
+ setHovering(false);
52
+ }, []);
53
+ React.useEffect(() => {
54
+ if (!collapsed) setHovering(false);
55
+ }, [collapsed]);
56
+ const ctx = React.useMemo(
57
+ () => ({
58
+ collapsed,
59
+ hovering,
60
+ effectiveCollapsed: collapsed && !hovering,
61
+ onCollapsedChange
62
+ }),
63
+ [collapsed, hovering, onCollapsedChange]
64
+ );
65
+ return /* @__PURE__ */ jsx(AppShellContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
66
+ "div",
67
+ {
68
+ className: cn("flex h-full overflow-hidden bg-[var(--bg-body)]", className),
69
+ onMouseLeave: handleMouseLeave,
70
+ children: React.Children.map(children, (child) => {
71
+ if (!React.isValidElement(child)) return child;
72
+ if (child.type === AppShellSidebar) {
73
+ return /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ onMouseEnter: handleMouseEnter,
77
+ onMouseLeave: handleMouseLeave,
78
+ className: "relative shrink-0",
79
+ style: {
80
+ width: collapsed ? "var(--size-sidebar-collapsed)" : "var(--size-sidebar-expanded)",
81
+ transitionProperty: "width",
82
+ transitionDuration: "var(--duration-sidebar)",
83
+ transitionTimingFunction: "ease-in-out"
84
+ },
85
+ children: child
86
+ }
87
+ );
88
+ }
89
+ return child;
90
+ })
91
+ }
92
+ ) });
93
+ }
94
+ function AppShellSidebar(props) {
95
+ return /* @__PURE__ */ jsx(Sidebar, { ...props });
96
+ }
97
+ function AppShellHeader(props) {
98
+ return /* @__PURE__ */ jsx(TopBar, { ...props });
99
+ }
100
+ function AppShellContent({
101
+ children,
102
+ className
103
+ }) {
104
+ return /* @__PURE__ */ jsx("div", { className: cn("min-h-0 flex-1 overflow-hidden", className), children });
105
+ }
106
+ const AppShell = Object.assign(AppShellRoot, {
107
+ Sidebar: AppShellSidebar,
108
+ Header: AppShellHeader,
109
+ Content: AppShellContent
110
+ });
111
+ export {
112
+ AppShell
113
+ };