@thangnqdev/ui 0.1.1 → 0.2.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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -65
  3. package/dist/bento/index.cjs.map +1 -1
  4. package/dist/bento/index.js +2 -2
  5. package/dist/bento/styles.css +2 -46
  6. package/dist/buttons/index.cjs +111 -18
  7. package/dist/buttons/index.cjs.map +1 -1
  8. package/dist/buttons/index.d.cts +1 -1
  9. package/dist/buttons/index.d.ts +1 -1
  10. package/dist/buttons/index.js +3 -3
  11. package/dist/buttons/styles.css +2 -6
  12. package/dist/{chunk-4S6L5V7X.js → chunk-2YJBW4E2.js} +2 -2
  13. package/dist/chunk-2YJBW4E2.js.map +1 -0
  14. package/dist/{chunk-F5Q7BTMH.js → chunk-4CRFNALF.js} +1011 -556
  15. package/dist/chunk-4CRFNALF.js.map +1 -0
  16. package/dist/{chunk-LWFRUJRU.js → chunk-4MS6ZHFQ.js} +225 -41
  17. package/dist/chunk-4MS6ZHFQ.js.map +1 -0
  18. package/dist/{chunk-2OXZK6IP.js → chunk-77KTYOMQ.js} +3 -3
  19. package/dist/chunk-77KTYOMQ.js.map +1 -0
  20. package/dist/{chunk-IABPUCAQ.js → chunk-ADO3SVUA.js} +2 -2
  21. package/dist/chunk-ADO3SVUA.js.map +1 -0
  22. package/dist/{chunk-GXI2H5XA.js → chunk-D7FB3TCA.js} +3 -3
  23. package/dist/chunk-D7FB3TCA.js.map +1 -0
  24. package/dist/chunk-DSEL7ELZ.js +314 -0
  25. package/dist/chunk-DSEL7ELZ.js.map +1 -0
  26. package/dist/{chunk-KJRBRTQE.js → chunk-EXFR2BFJ.js} +37 -28
  27. package/dist/chunk-EXFR2BFJ.js.map +1 -0
  28. package/dist/{chunk-PF4ZHGVW.js → chunk-GXWB6BSY.js} +116 -23
  29. package/dist/chunk-GXWB6BSY.js.map +1 -0
  30. package/dist/{chunk-66VWUJEI.js → chunk-I2FQBMVW.js} +3 -3
  31. package/dist/chunk-I2FQBMVW.js.map +1 -0
  32. package/dist/{chunk-EU2LPUYP.js → chunk-I5O2WCGF.js} +3 -3
  33. package/dist/chunk-I5O2WCGF.js.map +1 -0
  34. package/dist/{chunk-ATYGDTMK.js → chunk-ME4XILG5.js} +5 -5
  35. package/dist/chunk-ME4XILG5.js.map +1 -0
  36. package/dist/{chunk-5FZ6ZFII.js → chunk-PC5SZFZC.js} +373 -150
  37. package/dist/chunk-PC5SZFZC.js.map +1 -0
  38. package/dist/{chunk-C4SUXMI3.js → chunk-S6XJMYME.js} +3 -3
  39. package/dist/chunk-S6XJMYME.js.map +1 -0
  40. package/dist/{chunk-A7P3O5Z5.js → chunk-V52JOSDF.js} +3 -3
  41. package/dist/chunk-V52JOSDF.js.map +1 -0
  42. package/dist/{chunk-NFVONJUK.js → chunk-W5WNWTQC.js} +455 -211
  43. package/dist/chunk-W5WNWTQC.js.map +1 -0
  44. package/dist/{chunk-WAFHC4DQ.js → chunk-YJ64RI7J.js} +3 -3
  45. package/dist/chunk-YJ64RI7J.js.map +1 -0
  46. package/dist/chunk-YOCGBORV.js +155 -0
  47. package/dist/chunk-YOCGBORV.js.map +1 -0
  48. package/dist/chunk-ZEDXARXW.js +96 -0
  49. package/dist/chunk-ZEDXARXW.js.map +1 -0
  50. package/dist/components.css +2 -0
  51. package/dist/core/index.cjs +33 -24
  52. package/dist/core/index.cjs.map +1 -1
  53. package/dist/core/index.js +2 -2
  54. package/dist/core/styles.css +2 -130
  55. package/dist/data-display/index.cjs +770 -247
  56. package/dist/data-display/index.cjs.map +1 -1
  57. package/dist/data-display/index.d.cts +1 -1
  58. package/dist/data-display/index.d.ts +1 -1
  59. package/dist/data-display/index.js +5 -4
  60. package/dist/data-display/styles.css +2 -4
  61. package/dist/feedback/index.cjs.map +1 -1
  62. package/dist/feedback/index.js +2 -2
  63. package/dist/feedback/styles.css +2 -4
  64. package/dist/forms/index.cjs +1211 -459
  65. package/dist/forms/index.cjs.map +1 -1
  66. package/dist/forms/index.d.cts +1 -1
  67. package/dist/forms/index.d.ts +1 -1
  68. package/dist/forms/index.js +8 -8
  69. package/dist/forms/styles.css +2 -6
  70. package/dist/glass/index.cjs.map +1 -1
  71. package/dist/glass/index.js +2 -2
  72. package/dist/glass/styles.css +2 -81
  73. package/dist/{index-D6fE7w-b.d.cts → index-BGt_hecO.d.cts} +1 -0
  74. package/dist/{index-D6fE7w-b.d.ts → index-BGt_hecO.d.ts} +1 -0
  75. package/dist/{index-DzcWh1Hs.d.cts → index-BtDvpZCf.d.cts} +7 -0
  76. package/dist/{index-DzcWh1Hs.d.ts → index-BtDvpZCf.d.ts} +7 -0
  77. package/dist/{index-Cle6QzQl.d.ts → index-COX1sBUN.d.ts} +27 -3
  78. package/dist/{index-BkRqGNG1.d.ts → index-Cg8MuP7u.d.cts} +40 -13
  79. package/dist/{index-BkRqGNG1.d.cts → index-Cg8MuP7u.d.ts} +40 -13
  80. package/dist/{index-CenuF_P2.d.ts → index-DHkPRTvE.d.cts} +39 -8
  81. package/dist/{index-CenuF_P2.d.cts → index-DHkPRTvE.d.ts} +39 -8
  82. package/dist/{index-TyK-Ldpy.d.cts → index-Du_oht9k.d.cts} +27 -3
  83. package/dist/index.cjs +2481 -917
  84. package/dist/index.cjs.map +1 -1
  85. package/dist/index.d.cts +5 -5
  86. package/dist/index.d.ts +5 -5
  87. package/dist/index.js +19 -19
  88. package/dist/layout/index.cjs.map +1 -1
  89. package/dist/layout/index.js +2 -2
  90. package/dist/layout/styles.css +2 -8
  91. package/dist/navigation/index.cjs +288 -48
  92. package/dist/navigation/index.cjs.map +1 -1
  93. package/dist/navigation/index.d.cts +1 -1
  94. package/dist/navigation/index.d.ts +1 -1
  95. package/dist/navigation/index.js +6 -6
  96. package/dist/navigation/styles.css +2 -4
  97. package/dist/overlays/index.cjs +566 -229
  98. package/dist/overlays/index.cjs.map +1 -1
  99. package/dist/overlays/index.d.cts +1 -1
  100. package/dist/overlays/index.d.ts +1 -1
  101. package/dist/overlays/index.js +7 -7
  102. package/dist/overlays/styles.css +2 -8
  103. package/dist/reset.css +45 -0
  104. package/dist/styles.css +1 -1
  105. package/dist/tokens.css +11 -0
  106. package/dist/typography/index.cjs.map +1 -1
  107. package/dist/typography/index.js +4 -4
  108. package/dist/typography/styles.css +2 -5
  109. package/llms.txt +211 -113
  110. package/package.json +160 -116
  111. package/src/bento/BentoCard.tsx +140 -140
  112. package/src/bento/BentoGrid.tsx +50 -50
  113. package/src/bento/index.ts +2 -2
  114. package/src/bento/tokens.css +46 -46
  115. package/src/buttons/Button.tsx +104 -104
  116. package/src/buttons/ButtonGroup.tsx +43 -43
  117. package/src/buttons/IconButton.tsx +79 -79
  118. package/src/buttons/SplitButton.tsx +186 -86
  119. package/src/buttons/ToggleButton.tsx +157 -157
  120. package/src/buttons/index.ts +5 -5
  121. package/src/buttons/tokens.css +6 -6
  122. package/src/core/ThemeProvider.tsx +135 -123
  123. package/src/core/index.ts +2 -2
  124. package/src/core/tokens.css +134 -130
  125. package/src/data-display/Accordion.tsx +147 -147
  126. package/src/data-display/Avatar.tsx +134 -134
  127. package/src/data-display/Card.tsx +112 -112
  128. package/src/data-display/Chip.tsx +74 -74
  129. package/src/data-display/DataTablePro.tsx +299 -121
  130. package/src/data-display/StatCard.tsx +60 -60
  131. package/src/data-display/Table.tsx +74 -74
  132. package/src/data-display/Timeline.tsx +62 -62
  133. package/src/data-display/TreeView.tsx +243 -104
  134. package/src/data-display/tokens.css +4 -4
  135. package/src/feedback/Alert.tsx +80 -80
  136. package/src/feedback/EmptyState.tsx +45 -45
  137. package/src/feedback/Skeleton.tsx +66 -66
  138. package/src/feedback/Spinner.tsx +65 -65
  139. package/src/feedback/index.ts +5 -5
  140. package/src/feedback/tokens.css +4 -4
  141. package/src/forms/Checkbox.tsx +149 -69
  142. package/src/forms/CheckboxGroup.tsx +76 -29
  143. package/src/forms/Combobox.tsx +172 -28
  144. package/src/forms/DatePicker.tsx +385 -81
  145. package/src/forms/FileUpload.tsx +51 -7
  146. package/src/forms/FormField.tsx +115 -115
  147. package/src/forms/Input.tsx +151 -151
  148. package/src/forms/NumberInput.tsx +34 -20
  149. package/src/forms/PasswordInput.tsx +35 -35
  150. package/src/forms/PinInput.tsx +139 -125
  151. package/src/forms/Radio.tsx +142 -142
  152. package/src/forms/RangeSlider.tsx +237 -111
  153. package/src/forms/SearchInput.tsx +34 -34
  154. package/src/forms/Select.tsx +103 -103
  155. package/src/forms/Slider.tsx +85 -85
  156. package/src/forms/Textarea.tsx +114 -114
  157. package/src/forms/tokens.css +6 -6
  158. package/src/glass/GlassButton.tsx +59 -59
  159. package/src/glass/GlassCard.tsx +71 -71
  160. package/src/glass/index.ts +3 -3
  161. package/src/glass/tokens.css +81 -81
  162. package/src/index.ts +26 -26
  163. package/src/layout/AspectRatio.tsx +39 -39
  164. package/src/layout/Container.tsx +53 -53
  165. package/src/layout/Divider.tsx +61 -61
  166. package/src/layout/Flex.tsx +79 -79
  167. package/src/layout/Grid.tsx +124 -124
  168. package/src/layout/PageLayout.tsx +59 -59
  169. package/src/layout/Section.tsx +47 -47
  170. package/src/layout/Spacer.tsx +30 -30
  171. package/src/layout/Stack.tsx +88 -88
  172. package/src/layout/tokens.css +8 -8
  173. package/src/navigation/Breadcrumb.tsx +73 -73
  174. package/src/navigation/CommandPalette.tsx +142 -142
  175. package/src/navigation/DropdownMenu.tsx +244 -160
  176. package/src/navigation/Pagination.tsx +114 -114
  177. package/src/navigation/Stepper.tsx +93 -93
  178. package/src/navigation/Tabs.tsx +265 -133
  179. package/src/navigation/index.ts +6 -6
  180. package/src/navigation/tokens.css +4 -4
  181. package/src/overlays/AlertDialog.tsx +63 -54
  182. package/src/overlays/BottomSheet.tsx +30 -10
  183. package/src/overlays/ContextMenu.tsx +51 -9
  184. package/src/overlays/Drawer.tsx +160 -145
  185. package/src/overlays/FocusTrap.tsx +122 -49
  186. package/src/overlays/Modal.tsx +296 -219
  187. package/src/overlays/Popover.tsx +55 -25
  188. package/src/overlays/Portal.tsx +23 -23
  189. package/src/overlays/Toast.tsx +175 -137
  190. package/src/overlays/Tooltip.tsx +125 -100
  191. package/src/overlays/tokens.css +8 -8
  192. package/src/registry/components.ts +1368 -0
  193. package/src/styles/components.css +39 -0
  194. package/src/styles/index.css +2 -93
  195. package/src/styles/reset.css +45 -0
  196. package/src/styles/tokens.css +11 -2
  197. package/src/typography/Blockquote.tsx +32 -32
  198. package/src/typography/Code.tsx +89 -89
  199. package/src/typography/Heading.tsx +56 -56
  200. package/src/typography/Kbd.tsx +25 -25
  201. package/src/typography/Label.tsx +47 -47
  202. package/src/typography/Link.tsx +56 -56
  203. package/src/typography/Text.tsx +62 -62
  204. package/src/typography/index.ts +7 -7
  205. package/src/typography/tokens.css +5 -5
  206. package/src/utils/cn.ts +6 -6
  207. package/src/utils/scroll-lock.ts +19 -0
  208. package/src/utils/useControllableState.ts +54 -0
  209. package/ui-contract.json +192 -35
  210. package/dist/chunk-2OXZK6IP.js.map +0 -1
  211. package/dist/chunk-4S6L5V7X.js.map +0 -1
  212. package/dist/chunk-5FZ6ZFII.js.map +0 -1
  213. package/dist/chunk-66VWUJEI.js.map +0 -1
  214. package/dist/chunk-A7P3O5Z5.js.map +0 -1
  215. package/dist/chunk-ATYGDTMK.js.map +0 -1
  216. package/dist/chunk-C4SUXMI3.js.map +0 -1
  217. package/dist/chunk-EU2LPUYP.js.map +0 -1
  218. package/dist/chunk-F5Q7BTMH.js.map +0 -1
  219. package/dist/chunk-GXI2H5XA.js.map +0 -1
  220. package/dist/chunk-H3LCNPMC.js +0 -101
  221. package/dist/chunk-H3LCNPMC.js.map +0 -1
  222. package/dist/chunk-IABPUCAQ.js.map +0 -1
  223. package/dist/chunk-KJRBRTQE.js.map +0 -1
  224. package/dist/chunk-LBUBXUYQ.js +0 -40
  225. package/dist/chunk-LBUBXUYQ.js.map +0 -1
  226. package/dist/chunk-LWFRUJRU.js.map +0 -1
  227. package/dist/chunk-NFVONJUK.js.map +0 -1
  228. package/dist/chunk-PF4ZHGVW.js.map +0 -1
  229. package/dist/chunk-WAFHC4DQ.js.map +0 -1
  230. package/dist/chunk-X76KBH4Y.js +0 -71
  231. package/dist/chunk-X76KBH4Y.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React11 = require('react');
3
+ var React15 = require('react');
4
4
  var classVarianceAuthority = require('class-variance-authority');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
@@ -9,7 +9,7 @@ var lucideReact = require('lucide-react');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
- var React11__default = /*#__PURE__*/_interopDefault(React11);
12
+ var React15__default = /*#__PURE__*/_interopDefault(React15);
13
13
 
14
14
  // src/data-display/Card.tsx
15
15
  function cn(...inputs) {
@@ -44,7 +44,7 @@ var cardVariants = classVarianceAuthority.cva(
44
44
  }
45
45
  }
46
46
  );
47
- var Card = React11.forwardRef(
47
+ var Card = React15.forwardRef(
48
48
  ({ className, variant, padding, specular = true, children, ...props }, ref) => {
49
49
  return /* @__PURE__ */ jsxRuntime.jsx(
50
50
  "div",
@@ -58,53 +58,53 @@ var Card = React11.forwardRef(
58
58
  }
59
59
  );
60
60
  Card.displayName = "Card";
61
- var CardHeader = React11.forwardRef(
61
+ var CardHeader = React15.forwardRef(
62
62
  ({ className, children, ...props }, ref) => {
63
63
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col space-y-1.5 mb-5", className), ...props, children });
64
64
  }
65
65
  );
66
66
  CardHeader.displayName = "CardHeader";
67
- var CardTitle = React11.forwardRef(
67
+ var CardTitle = React15.forwardRef(
68
68
  ({ className, children, ...props }, ref) => {
69
69
  return /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-lg sm:text-xl font-bold tracking-tight text-[var(--ui-text-primary)]", className), ...props, children });
70
70
  }
71
71
  );
72
72
  CardTitle.displayName = "CardTitle";
73
- var CardDescription = React11.forwardRef(
73
+ var CardDescription = React15.forwardRef(
74
74
  ({ className, children, ...props }, ref) => {
75
75
  return /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-xs sm:text-sm text-[var(--ui-text-muted)] font-normal leading-relaxed", className), ...props, children });
76
76
  }
77
77
  );
78
78
  CardDescription.displayName = "CardDescription";
79
- var CardContent = React11.forwardRef(
79
+ var CardContent = React15.forwardRef(
80
80
  ({ className, children, ...props }, ref) => {
81
81
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("pt-0", className), ...props, children });
82
82
  }
83
83
  );
84
84
  CardContent.displayName = "CardContent";
85
- var CardFooter = React11.forwardRef(
85
+ var CardFooter = React15.forwardRef(
86
86
  ({ className, children, ...props }, ref) => {
87
87
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center pt-4 mt-5 border-t border-[var(--ui-border-subtle)]", className), ...props, children });
88
88
  }
89
89
  );
90
90
  CardFooter.displayName = "CardFooter";
91
- var Table = React11.forwardRef(
91
+ var Table = React15.forwardRef(
92
92
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-auto rounded-[var(--ui-radius-lg)] border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)]", children: /* @__PURE__ */ jsxRuntime.jsx("table", { ref, className: cn("w-full caption-bottom text-sm text-left", className), ...props }) })
93
93
  );
94
94
  Table.displayName = "Table";
95
- var TableHeader = React11.forwardRef(
95
+ var TableHeader = React15.forwardRef(
96
96
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("bg-[var(--ui-bg-secondary)] border-b border-[var(--ui-border-default)]", className), ...props })
97
97
  );
98
98
  TableHeader.displayName = "TableHeader";
99
- var TableBody = React11.forwardRef(
99
+ var TableBody = React15.forwardRef(
100
100
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props })
101
101
  );
102
102
  TableBody.displayName = "TableBody";
103
- var TableFooter = React11.forwardRef(
103
+ var TableFooter = React15.forwardRef(
104
104
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tfoot", { ref, className: cn("bg-[var(--ui-bg-secondary)] font-medium border-t border-[var(--ui-border-default)]", className), ...props })
105
105
  );
106
106
  TableFooter.displayName = "TableFooter";
107
- var TableRow = React11.forwardRef(
107
+ var TableRow = React15.forwardRef(
108
108
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
109
109
  "tr",
110
110
  {
@@ -118,7 +118,7 @@ var TableRow = React11.forwardRef(
118
118
  )
119
119
  );
120
120
  TableRow.displayName = "TableRow";
121
- var TableHead = React11.forwardRef(
121
+ var TableHead = React15.forwardRef(
122
122
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
123
123
  "th",
124
124
  {
@@ -132,11 +132,11 @@ var TableHead = React11.forwardRef(
132
132
  )
133
133
  );
134
134
  TableHead.displayName = "TableHead";
135
- var TableCell = React11.forwardRef(
135
+ var TableCell = React15.forwardRef(
136
136
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("td", { ref, className: cn("p-4 align-middle text-sm text-[var(--ui-text-primary)]", className), ...props })
137
137
  );
138
138
  TableCell.displayName = "TableCell";
139
- var TableCaption = React11.forwardRef(
139
+ var TableCaption = React15.forwardRef(
140
140
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("caption", { ref, className: cn("mt-4 text-xs text-[var(--ui-text-muted)]", className), ...props })
141
141
  );
142
142
  TableCaption.displayName = "TableCaption";
@@ -181,9 +181,9 @@ var statusVariants = classVarianceAuthority.cva(
181
181
  }
182
182
  }
183
183
  );
184
- var Avatar = React11.forwardRef(
184
+ var Avatar = React15.forwardRef(
185
185
  ({ className, size = "md", src, alt, name, status, children, ...props }, ref) => {
186
- const [hasError, setHasError] = React11.useState(false);
186
+ const [hasError, setHasError] = React15.useState(false);
187
187
  const getInitials = (n) => {
188
188
  if (!n) return "";
189
189
  const parts = n.trim().split(" ");
@@ -212,9 +212,9 @@ var Avatar = React11.forwardRef(
212
212
  }
213
213
  );
214
214
  Avatar.displayName = "Avatar";
215
- var AvatarGroup = React11.forwardRef(
215
+ var AvatarGroup = React15.forwardRef(
216
216
  ({ className, max = 4, spacing = "tight", children, ...props }, ref) => {
217
- const childArray = React11__default.default.Children.toArray(children);
217
+ const childArray = React15__default.default.Children.toArray(children);
218
218
  const visibleChildren = childArray.slice(0, max);
219
219
  const remainingCount = childArray.length - max;
220
220
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -240,13 +240,13 @@ var AvatarGroup = React11.forwardRef(
240
240
  }
241
241
  );
242
242
  AvatarGroup.displayName = "AvatarGroup";
243
- var AccordionContext = React11.createContext(null);
243
+ var AccordionContext = React15.createContext(null);
244
244
  function useAccordion() {
245
- const context = React11.useContext(AccordionContext);
245
+ const context = React15.useContext(AccordionContext);
246
246
  if (!context) throw new Error("AccordionItem components must be used within <Accordion />");
247
247
  return context;
248
248
  }
249
- var Accordion = React11.forwardRef(
249
+ var Accordion = React15.forwardRef(
250
250
  ({
251
251
  className,
252
252
  type = "single",
@@ -256,7 +256,7 @@ var Accordion = React11.forwardRef(
256
256
  children,
257
257
  ...props
258
258
  }, ref) => {
259
- const [internalOpen, setInternalOpen] = React11.useState(() => {
259
+ const [internalOpen, setInternalOpen] = React15.useState(() => {
260
260
  if (Array.isArray(defaultValue)) return defaultValue;
261
261
  if (typeof defaultValue === "string") return [defaultValue];
262
262
  return [];
@@ -276,17 +276,17 @@ var Accordion = React11.forwardRef(
276
276
  }
277
277
  );
278
278
  Accordion.displayName = "Accordion";
279
- var AccordionItemContext = React11.createContext(null);
280
- var AccordionItem = React11.forwardRef(
279
+ var AccordionItemContext = React15.createContext(null);
280
+ var AccordionItem = React15.forwardRef(
281
281
  ({ className, value, children, ...props }, ref) => {
282
282
  return /* @__PURE__ */ jsxRuntime.jsx(AccordionItemContext.Provider, { value: { id: value }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("w-full", className), ...props, children }) });
283
283
  }
284
284
  );
285
285
  AccordionItem.displayName = "AccordionItem";
286
- var AccordionTrigger = React11.forwardRef(
286
+ var AccordionTrigger = React15.forwardRef(
287
287
  ({ className, children, ...props }, ref) => {
288
288
  const { openItems, toggleItem } = useAccordion();
289
- const item = React11.useContext(AccordionItemContext);
289
+ const item = React15.useContext(AccordionItemContext);
290
290
  const isOpen = item ? openItems.includes(item.id) : false;
291
291
  return /* @__PURE__ */ jsxRuntime.jsxs(
292
292
  "button",
@@ -317,10 +317,10 @@ var AccordionTrigger = React11.forwardRef(
317
317
  }
318
318
  );
319
319
  AccordionTrigger.displayName = "AccordionTrigger";
320
- var AccordionContent = React11.forwardRef(
320
+ var AccordionContent = React15.forwardRef(
321
321
  ({ className, children, ...props }, ref) => {
322
322
  const { openItems } = useAccordion();
323
- const item = React11.useContext(AccordionItemContext);
323
+ const item = React15.useContext(AccordionItemContext);
324
324
  const isOpen = item ? openItems.includes(item.id) : false;
325
325
  if (!isOpen) return null;
326
326
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -364,7 +364,7 @@ var chipVariants = classVarianceAuthority.cva(
364
364
  }
365
365
  }
366
366
  );
367
- var Chip = React11.forwardRef(
367
+ var Chip = React15.forwardRef(
368
368
  ({ className, variant, size, clickable, onRemove, icon, children, onClick, ...props }, ref) => {
369
369
  const isClickable = Boolean(clickable || onClick);
370
370
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -396,7 +396,7 @@ var Chip = React11.forwardRef(
396
396
  }
397
397
  );
398
398
  Chip.displayName = "Chip";
399
- var StatCard = React11.forwardRef(
399
+ var StatCard = React15.forwardRef(
400
400
  ({ className, label, value, change, trend, trendLabel, icon, ...props }, ref) => {
401
401
  return /* @__PURE__ */ jsxRuntime.jsxs(Card, { ref, className: cn("p-6", className), ...props, children: [
402
402
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
@@ -428,7 +428,7 @@ var StatCard = React11.forwardRef(
428
428
  }
429
429
  );
430
430
  StatCard.displayName = "StatCard";
431
- var Timeline = React11.forwardRef(
431
+ var Timeline = React15.forwardRef(
432
432
  ({ className, items, ...props }, ref) => {
433
433
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("relative pl-6 space-y-6", className), ...props, children: [
434
434
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-[11px] top-2 bottom-2 w-0.5 bg-[var(--ui-border-subtle)]" }),
@@ -493,7 +493,7 @@ var buttonVariants = classVarianceAuthority.cva(
493
493
  }
494
494
  }
495
495
  );
496
- var Button = React11.forwardRef(
496
+ var Button = React15.forwardRef(
497
497
  ({
498
498
  className,
499
499
  variant,
@@ -537,6 +537,285 @@ var Button = React11.forwardRef(
537
537
  }
538
538
  );
539
539
  Button.displayName = "Button";
540
+ var labelVariants = classVarianceAuthority.cva(
541
+ "text-sm font-medium leading-none select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-[var(--ui-text-primary)] inline-flex items-center gap-1",
542
+ {
543
+ variants: {
544
+ size: {
545
+ sm: "text-xs",
546
+ md: "text-sm",
547
+ lg: "text-base"
548
+ },
549
+ error: {
550
+ true: "text-[var(--ui-error)]",
551
+ false: ""
552
+ }
553
+ },
554
+ defaultVariants: {
555
+ size: "md",
556
+ error: false
557
+ }
558
+ }
559
+ );
560
+ var Label = React15.forwardRef(
561
+ ({ className, size, error, required, children, ...props }, ref) => {
562
+ return /* @__PURE__ */ jsxRuntime.jsxs(
563
+ "label",
564
+ {
565
+ ref,
566
+ className: cn(labelVariants({ size, error }), className),
567
+ ...props,
568
+ children: [
569
+ children,
570
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--ui-error)] ml-0.5", "aria-hidden": "true", children: "*" })
571
+ ]
572
+ }
573
+ );
574
+ }
575
+ );
576
+ Label.displayName = "Label";
577
+ var FormFieldContext = React15.createContext(null);
578
+ function useFormField() {
579
+ const context = React15.useContext(FormFieldContext);
580
+ return context;
581
+ }
582
+ var FormField = React15.forwardRef(
583
+ ({ className, isRequired, isInvalid, isDisabled, children, ...props }, ref) => {
584
+ const generatedId = React15.useId();
585
+ const id = props.id || generatedId;
586
+ const labelId = `${id}-label`;
587
+ const descriptionId = `${id}-description`;
588
+ const errorId = `${id}-error`;
589
+ return /* @__PURE__ */ jsxRuntime.jsx(
590
+ FormFieldContext.Provider,
591
+ {
592
+ value: {
593
+ id,
594
+ labelId,
595
+ descriptionId,
596
+ errorId,
597
+ isRequired,
598
+ isInvalid,
599
+ isDisabled
600
+ },
601
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("space-y-1.5 w-full", className), ...props, children })
602
+ }
603
+ );
604
+ }
605
+ );
606
+ FormField.displayName = "FormField";
607
+ var FormLabel = React15.forwardRef(
608
+ ({ className, required, children, ...props }, ref) => {
609
+ const context = useFormField();
610
+ const isRequired = required ?? context?.isRequired;
611
+ const isError = context?.isInvalid;
612
+ return /* @__PURE__ */ jsxRuntime.jsx(
613
+ Label,
614
+ {
615
+ ref,
616
+ id: context?.labelId,
617
+ htmlFor: context?.id,
618
+ required: isRequired,
619
+ error: isError,
620
+ className,
621
+ ...props,
622
+ children
623
+ }
624
+ );
625
+ }
626
+ );
627
+ FormLabel.displayName = "FormLabel";
628
+ var FormHelperText = React15.forwardRef(
629
+ ({ className, children, ...props }, ref) => {
630
+ const context = useFormField();
631
+ return /* @__PURE__ */ jsxRuntime.jsx(
632
+ "p",
633
+ {
634
+ ref,
635
+ id: context?.descriptionId,
636
+ className: cn("text-xs text-[var(--ui-text-muted)]", className),
637
+ ...props,
638
+ children
639
+ }
640
+ );
641
+ }
642
+ );
643
+ FormHelperText.displayName = "FormHelperText";
644
+ var FormErrorMessage = React15.forwardRef(
645
+ ({ className, children, ...props }, ref) => {
646
+ const context = useFormField();
647
+ if (!context?.isInvalid && !children) return null;
648
+ return /* @__PURE__ */ jsxRuntime.jsx(
649
+ "p",
650
+ {
651
+ ref,
652
+ id: context?.errorId,
653
+ role: "alert",
654
+ className: cn("text-xs font-medium text-[var(--ui-error)]", className),
655
+ ...props,
656
+ children
657
+ }
658
+ );
659
+ }
660
+ );
661
+ FormErrorMessage.displayName = "FormErrorMessage";
662
+ var CheckboxGroupContext = React15.createContext(null);
663
+ var useCheckboxGroup = () => React15.useContext(CheckboxGroupContext);
664
+ var CheckboxGroup = React15.forwardRef(
665
+ ({
666
+ className,
667
+ orientation = "vertical",
668
+ children,
669
+ value: controlledValue,
670
+ defaultValue = [],
671
+ onChange,
672
+ disabled,
673
+ name,
674
+ ...props
675
+ }, ref) => {
676
+ const [internalValue, setInternalValue] = React15.useState(defaultValue);
677
+ const isControlled = controlledValue !== void 0;
678
+ const value = isControlled ? controlledValue : internalValue;
679
+ const handleValueChange = (nextValue) => {
680
+ if (!isControlled) {
681
+ setInternalValue(nextValue);
682
+ }
683
+ onChange?.(nextValue);
684
+ };
685
+ return /* @__PURE__ */ jsxRuntime.jsx(
686
+ CheckboxGroupContext.Provider,
687
+ {
688
+ value: {
689
+ value,
690
+ onChange: handleValueChange,
691
+ disabled,
692
+ name
693
+ },
694
+ children: /* @__PURE__ */ jsxRuntime.jsx(
695
+ "div",
696
+ {
697
+ ref,
698
+ role: "group",
699
+ className: cn(
700
+ "flex gap-2",
701
+ orientation === "vertical" ? "flex-col" : "flex-row flex-wrap items-center",
702
+ className
703
+ ),
704
+ ...props,
705
+ children
706
+ }
707
+ )
708
+ }
709
+ );
710
+ }
711
+ );
712
+ CheckboxGroup.displayName = "CheckboxGroup";
713
+ var checkboxVariants = classVarianceAuthority.cva(
714
+ "peer shrink-0 rounded-[var(--ui-radius-sm)] border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] transition-all flex items-center justify-center text-[var(--ui-primary-fg)] peer-focus-visible:ring-2 peer-focus-visible:ring-[var(--ui-primary)] peer-focus-visible:ring-offset-2",
715
+ {
716
+ variants: {
717
+ size: {
718
+ sm: "w-4 h-4 text-xs",
719
+ md: "w-5 h-5 text-sm",
720
+ lg: "w-6 h-6 text-base"
721
+ }
722
+ },
723
+ defaultVariants: {
724
+ size: "md"
725
+ }
726
+ }
727
+ );
728
+ var Checkbox = React15.forwardRef(
729
+ ({
730
+ className,
731
+ size,
732
+ indeterminate = false,
733
+ label,
734
+ checked,
735
+ defaultChecked = false,
736
+ disabled,
737
+ id,
738
+ name,
739
+ value: propValue,
740
+ onChange,
741
+ onCheckedChange,
742
+ ...props
743
+ }, ref) => {
744
+ const formField = useFormField();
745
+ const group = useCheckboxGroup();
746
+ const isGroupMember = group !== null && propValue !== void 0;
747
+ const isDisabled = disabled ?? group?.disabled ?? formField?.isDisabled ?? false;
748
+ const checkboxId = id || formField?.id;
749
+ const checkboxName = name || group?.name;
750
+ const isControlled = checked !== void 0;
751
+ const [internalChecked, setInternalChecked] = React15.useState(defaultChecked);
752
+ const isChecked = isGroupMember ? group.value.includes(String(propValue)) : isControlled ? Boolean(checked) : internalChecked;
753
+ const innerRef = React15.useRef(null);
754
+ React15.useImperativeHandle(ref, () => innerRef.current);
755
+ React15.useEffect(() => {
756
+ if (innerRef.current) {
757
+ innerRef.current.indeterminate = Boolean(indeterminate);
758
+ }
759
+ }, [indeterminate]);
760
+ const handleChange = (e) => {
761
+ if (isDisabled) return;
762
+ const newChecked = e.target.checked;
763
+ if (!isControlled && !isGroupMember) {
764
+ setInternalChecked(newChecked);
765
+ }
766
+ if (isGroupMember && group) {
767
+ const val = String(propValue);
768
+ const next = newChecked ? [...group.value, val] : group.value.filter((v) => v !== val);
769
+ group.onChange(next);
770
+ }
771
+ onChange?.(e);
772
+ onCheckedChange?.(newChecked);
773
+ };
774
+ const isVisualActive = isChecked || indeterminate;
775
+ return /* @__PURE__ */ jsxRuntime.jsxs(
776
+ "label",
777
+ {
778
+ className: cn(
779
+ "inline-flex items-center gap-2 select-none cursor-pointer group",
780
+ isDisabled && "cursor-not-allowed opacity-50"
781
+ ),
782
+ children: [
783
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
784
+ /* @__PURE__ */ jsxRuntime.jsx(
785
+ "input",
786
+ {
787
+ ref: innerRef,
788
+ type: "checkbox",
789
+ id: checkboxId,
790
+ name: checkboxName,
791
+ value: propValue,
792
+ disabled: isDisabled,
793
+ checked: isChecked,
794
+ onChange: handleChange,
795
+ "aria-checked": indeterminate ? "mixed" : isChecked,
796
+ className: "sr-only peer",
797
+ ...props
798
+ }
799
+ ),
800
+ /* @__PURE__ */ jsxRuntime.jsx(
801
+ "div",
802
+ {
803
+ className: cn(
804
+ checkboxVariants({ size }),
805
+ isVisualActive ? "bg-[var(--ui-primary)] border-[var(--ui-primary)] text-white" : "hover:border-[var(--ui-border-strong)]",
806
+ className
807
+ ),
808
+ children: indeterminate ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "w-3.5 h-3.5 stroke-[3]" }) : isChecked && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-3.5 h-3.5 stroke-[3]" })
809
+ }
810
+ )
811
+ ] }),
812
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-[var(--ui-text-primary)]", children: label })
813
+ ]
814
+ }
815
+ );
816
+ }
817
+ );
818
+ Checkbox.displayName = "Checkbox";
540
819
  function DataTablePro({
541
820
  data,
542
821
  columns,
@@ -544,79 +823,183 @@ function DataTablePro({
544
823
  searchable = true,
545
824
  searchPlaceholder = "Search all records...",
546
825
  selectable = true,
826
+ selectedKeys: controlledSelectedKeys,
827
+ defaultSelectedKeys = [],
547
828
  onSelectionChange,
548
829
  pageSize: initialPageSize = 10,
549
830
  pageSizeOptions = [5, 10, 25, 50],
550
831
  title,
551
832
  description,
552
833
  actions,
553
- className
834
+ className,
835
+ loading = false,
836
+ // Multi-column sorting
837
+ multiSort = true,
838
+ sorting: controlledSorting,
839
+ defaultSorting = [],
840
+ onSortingChange,
841
+ // Server-side / manual mode props
842
+ manualPagination = false,
843
+ manualSorting = false,
844
+ manualFiltering = false,
845
+ pageIndex: controlledPageIndex,
846
+ pageCount: controlledPageCount,
847
+ totalCount: controlledTotalCount,
848
+ onPaginationChange,
849
+ searchQuery: controlledSearchQuery,
850
+ onSearchChange,
851
+ onSelectAllDataset,
852
+ emptyText = "No matching records found."
554
853
  }) {
555
- const [search, setSearch] = React11.useState("");
556
- const [sortKey, setSortKey] = React11.useState(null);
557
- const [sortDirection, setSortDirection] = React11.useState("asc");
558
- const [currentPage, setCurrentPage] = React11.useState(1);
559
- const [pageSize, setPageSize] = React11.useState(initialPageSize);
560
- const [selectedKeys, setSelectedKeys] = React11.useState([]);
561
- const filteredData = React11.useMemo(() => {
562
- if (!search.trim()) return data;
854
+ const [internalSearch, setInternalSearch] = React15.useState("");
855
+ const search = controlledSearchQuery !== void 0 ? controlledSearchQuery : internalSearch;
856
+ const [internalSorting, setInternalSorting] = React15.useState(defaultSorting);
857
+ const currentSorting = controlledSorting !== void 0 ? controlledSorting ?? [] : internalSorting;
858
+ const [internalCurrentPage, setInternalCurrentPage] = React15.useState(1);
859
+ const currentPage = controlledPageIndex !== void 0 ? controlledPageIndex : internalCurrentPage;
860
+ const [internalPageSize, setInternalPageSize] = React15.useState(initialPageSize);
861
+ const pageSize = internalPageSize;
862
+ const [internalSelectedKeys, setInternalSelectedKeys] = React15.useState(defaultSelectedKeys);
863
+ const isSelectedControlled = controlledSelectedKeys !== void 0;
864
+ const selectedKeys = isSelectedControlled ? controlledSelectedKeys : internalSelectedKeys;
865
+ const handleSelectionUpdate = (nextKeys) => {
866
+ if (!isSelectedControlled) {
867
+ setInternalSelectedKeys(nextKeys);
868
+ }
869
+ onSelectionChange?.(nextKeys);
870
+ };
871
+ const filteredData = React15.useMemo(() => {
872
+ if (manualFiltering || !search.trim()) return data;
563
873
  const q = search.toLowerCase();
564
874
  return data.filter((row) => {
565
- return Object.values(row).some((val) => {
875
+ return columns.some((col) => {
876
+ const val = col.accessor ? col.accessor(row) : row[col.key];
566
877
  if (val === null || val === void 0) return false;
567
878
  return String(val).toLowerCase().includes(q);
568
879
  });
569
880
  });
570
- }, [data, search]);
571
- const sortedData = React11.useMemo(() => {
572
- if (!sortKey) return filteredData;
573
- const col = columns.find((c) => c.key === sortKey);
881
+ }, [data, search, columns, manualFiltering]);
882
+ const sortedData = React15.useMemo(() => {
883
+ if (manualSorting || currentSorting.length === 0) return filteredData;
574
884
  return [...filteredData].sort((a, b) => {
575
- const valA = col?.accessor ? col.accessor(a) : a[sortKey];
576
- const valB = col?.accessor ? col.accessor(b) : b[sortKey];
577
- if (valA === valB) return 0;
578
- if (valA === null || valA === void 0) return 1;
579
- if (valB === null || valB === void 0) return -1;
580
- const comp = valA < valB ? -1 : 1;
581
- return sortDirection === "asc" ? comp : -comp;
885
+ for (const { key, direction } of currentSorting) {
886
+ const col = columns.find((c) => c.key === key);
887
+ let comp = 0;
888
+ if (col?.sortComparator) {
889
+ comp = col.sortComparator(a, b);
890
+ } else {
891
+ const valA = col?.accessor ? col.accessor(a) : a[key];
892
+ const valB = col?.accessor ? col.accessor(b) : b[key];
893
+ if (valA === valB) continue;
894
+ if (valA === null || valA === void 0) return 1;
895
+ if (valB === null || valB === void 0) return -1;
896
+ comp = valA < valB ? -1 : 1;
897
+ }
898
+ if (comp !== 0) {
899
+ return direction === "asc" ? comp : -comp;
900
+ }
901
+ }
902
+ return 0;
582
903
  });
583
- }, [filteredData, sortKey, sortDirection, columns]);
584
- const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
585
- const paginatedData = React11.useMemo(() => {
904
+ }, [filteredData, currentSorting, columns, manualSorting]);
905
+ const totalItems = controlledTotalCount !== void 0 ? controlledTotalCount : sortedData.length;
906
+ const totalPages = controlledPageCount !== void 0 ? Math.max(1, controlledPageCount) : Math.max(1, Math.ceil(totalItems / pageSize));
907
+ React15.useEffect(() => {
908
+ if (!manualPagination && currentPage > totalPages && totalPages > 0) {
909
+ setInternalCurrentPage(totalPages);
910
+ onPaginationChange?.(totalPages, pageSize);
911
+ }
912
+ }, [totalPages, currentPage, manualPagination, pageSize, onPaginationChange]);
913
+ const paginatedData = React15.useMemo(() => {
914
+ if (manualPagination) return data;
586
915
  const start = (currentPage - 1) * pageSize;
587
916
  return sortedData.slice(start, start + pageSize);
588
- }, [sortedData, currentPage, pageSize]);
589
- const handleSort = (key) => {
590
- if (sortKey === key) {
591
- if (sortDirection === "asc") {
592
- setSortDirection("desc");
917
+ }, [data, sortedData, currentPage, pageSize, manualPagination]);
918
+ const handleSort = (key, e) => {
919
+ const isShift = e?.shiftKey || false;
920
+ let nextSorting = [...currentSorting];
921
+ const existingIdx = nextSorting.findIndex((s) => s.key === key);
922
+ if (isShift && multiSort) {
923
+ if (existingIdx >= 0) {
924
+ if (nextSorting[existingIdx].direction === "asc") {
925
+ nextSorting[existingIdx] = { key, direction: "desc" };
926
+ } else {
927
+ nextSorting.splice(existingIdx, 1);
928
+ }
593
929
  } else {
594
- setSortKey(null);
595
- setSortDirection("asc");
930
+ nextSorting.push({ key, direction: "asc" });
596
931
  }
597
932
  } else {
598
- setSortKey(key);
599
- setSortDirection("asc");
933
+ if (existingIdx >= 0 && nextSorting.length === 1) {
934
+ if (nextSorting[0].direction === "asc") {
935
+ nextSorting = [{ key, direction: "desc" }];
936
+ } else {
937
+ nextSorting = [];
938
+ }
939
+ } else {
940
+ nextSorting = [{ key, direction: "asc" }];
941
+ }
942
+ }
943
+ if (controlledSorting === void 0) {
944
+ setInternalSorting(nextSorting);
600
945
  }
946
+ onSortingChange?.(nextSorting);
601
947
  };
602
- const toggleSelectAll = () => {
603
- if (selectedKeys.length === paginatedData.length) {
604
- setSelectedKeys([]);
605
- onSelectionChange?.([]);
948
+ const handlePageChange = (newPage) => {
949
+ const clamped = Math.max(1, Math.min(totalPages, newPage));
950
+ if (controlledPageIndex === void 0) {
951
+ setInternalCurrentPage(clamped);
952
+ }
953
+ onPaginationChange?.(clamped, pageSize);
954
+ };
955
+ const handlePageSizeChange = (newSize) => {
956
+ setInternalPageSize(newSize);
957
+ if (controlledPageIndex === void 0) {
958
+ setInternalCurrentPage(1);
959
+ }
960
+ onPaginationChange?.(1, newSize);
961
+ };
962
+ const handleSearchChange = (query) => {
963
+ if (controlledSearchQuery === void 0) {
964
+ setInternalSearch(query);
965
+ if (controlledPageIndex === void 0) {
966
+ setInternalCurrentPage(1);
967
+ }
968
+ }
969
+ onSearchChange?.(query);
970
+ };
971
+ const currentPageKeys = React15.useMemo(() => paginatedData.map(keyExtractor), [paginatedData, keyExtractor]);
972
+ const isAllCurrentPageSelected = currentPageKeys.length > 0 && currentPageKeys.every((k) => selectedKeys.includes(k));
973
+ const isSomeCurrentPageSelected = currentPageKeys.some((k) => selectedKeys.includes(k)) && !isAllCurrentPageSelected;
974
+ const toggleSelectAllCurrentPage = () => {
975
+ if (isAllCurrentPageSelected) {
976
+ const next = selectedKeys.filter((k) => !currentPageKeys.includes(k));
977
+ handleSelectionUpdate(next);
606
978
  } else {
607
- const allKeys = paginatedData.map(keyExtractor);
608
- setSelectedKeys(allKeys);
609
- onSelectionChange?.(allKeys);
979
+ const combined = Array.from(/* @__PURE__ */ new Set([...selectedKeys, ...currentPageKeys]));
980
+ handleSelectionUpdate(combined);
610
981
  }
611
982
  };
612
983
  const toggleSelectRow = (key) => {
613
984
  const next = selectedKeys.includes(key) ? selectedKeys.filter((k) => k !== key) : [...selectedKeys, key];
614
- setSelectedKeys(next);
615
- onSelectionChange?.(next);
985
+ handleSelectionUpdate(next);
986
+ };
987
+ const canSelectAllDataset = !manualPagination || typeof onSelectAllDataset === "function";
988
+ const selectAllDataset = () => {
989
+ if (manualPagination) {
990
+ onSelectAllDataset?.();
991
+ return;
992
+ }
993
+ const allKeys = sortedData.map(keyExtractor);
994
+ handleSelectionUpdate(allKeys);
995
+ };
996
+ const clearSelection = () => {
997
+ handleSelectionUpdate([]);
616
998
  };
617
999
  const exportCSV = () => {
1000
+ const exportRows = manualPagination ? data : sortedData;
618
1001
  const headers = columns.map((c) => typeof c.header === "string" ? c.header : c.key);
619
- const rows = sortedData.map(
1002
+ const rows = exportRows.map(
620
1003
  (row) => columns.map((c) => {
621
1004
  const val = c.accessor ? c.accessor(row) : row[c.key];
622
1005
  return `"${String(val ?? "").replace(/"/g, '""')}"`;
@@ -631,7 +1014,6 @@ function DataTablePro({
631
1014
  link.click();
632
1015
  document.body.removeChild(link);
633
1016
  };
634
- const isAllSelected = paginatedData.length > 0 && selectedKeys.length === paginatedData.length;
635
1017
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full space-y-4", className), children: [
636
1018
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-4", children: [
637
1019
  (title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -647,10 +1029,7 @@ function DataTablePro({
647
1029
  type: "text",
648
1030
  placeholder: searchPlaceholder,
649
1031
  value: search,
650
- onChange: (e) => {
651
- setSearch(e.target.value);
652
- setCurrentPage(1);
653
- },
1032
+ onChange: (e) => handleSearchChange(e.target.value),
654
1033
  className: "w-full h-8 pl-8 pr-3 text-xs rounded-xl bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] focus:outline-none focus:ring-2 focus:ring-[var(--ui-primary)]/40 text-[var(--ui-text-primary)] placeholder:text-[var(--ui-text-muted)] transition-all shadow-inner"
655
1034
  }
656
1035
  )
@@ -659,83 +1038,110 @@ function DataTablePro({
659
1038
  actions
660
1039
  ] })
661
1040
  ] }),
662
- selectedKeys.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2 rounded-xl bg-[var(--ui-primary)]/15 border border-[var(--ui-primary)]/30 flex items-center justify-between animate-in fade-in duration-200", children: [
663
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 text-xs font-semibold text-[var(--ui-primary)]", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
664
- "Selected ",
665
- selectedKeys.length,
666
- " of ",
667
- sortedData.length,
668
- " records"
669
- ] }) }),
1041
+ selectedKeys.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2 rounded-xl bg-[var(--ui-primary)]/15 border border-[var(--ui-primary)]/30 flex flex-wrap items-center justify-between gap-2 animate-in fade-in duration-200", children: [
1042
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs font-semibold text-[var(--ui-primary)]", children: [
1043
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1044
+ "Selected ",
1045
+ selectedKeys.length,
1046
+ " records"
1047
+ ] }),
1048
+ canSelectAllDataset && selectedKeys.length < totalItems && /* @__PURE__ */ jsxRuntime.jsxs(
1049
+ "button",
1050
+ {
1051
+ type: "button",
1052
+ onClick: selectAllDataset,
1053
+ className: "underline hover:text-[var(--ui-primary)]/80 cursor-pointer font-bold ml-1",
1054
+ children: [
1055
+ "Select all ",
1056
+ totalItems,
1057
+ " records"
1058
+ ]
1059
+ }
1060
+ )
1061
+ ] }),
670
1062
  /* @__PURE__ */ jsxRuntime.jsx(
671
1063
  Button,
672
1064
  {
673
1065
  size: "xs",
674
1066
  variant: "ghost",
675
1067
  className: "text-xs text-rose-500 hover:text-rose-600 hover:bg-rose-500/10",
676
- onClick: () => {
677
- setSelectedKeys([]);
678
- onSelectionChange?.([]);
679
- },
1068
+ onClick: clearSelection,
680
1069
  children: "Clear Selection"
681
1070
  }
682
1071
  )
683
1072
  ] }),
684
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-x-auto rounded-2xl border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
685
- /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
686
- selectable && /* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "w-10 px-4", children: /* @__PURE__ */ jsxRuntime.jsx(
687
- "input",
1073
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full overflow-x-auto rounded-2xl border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] shadow-sm", children: [
1074
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-20 bg-[var(--ui-bg-surface)]/60 backdrop-blur-xs flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-6 h-6 animate-spin text-[var(--ui-primary)]" }) }),
1075
+ /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
1076
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
1077
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "w-10 px-4", children: /* @__PURE__ */ jsxRuntime.jsx(
1078
+ Checkbox,
1079
+ {
1080
+ checked: isAllCurrentPageSelected,
1081
+ indeterminate: isSomeCurrentPageSelected,
1082
+ onCheckedChange: toggleSelectAllCurrentPage,
1083
+ "aria-label": "Select all on page"
1084
+ }
1085
+ ) }),
1086
+ columns.map((col) => {
1087
+ const sortIndex = currentSorting.findIndex((s) => s.key === col.key);
1088
+ const sortRule = sortIndex >= 0 ? currentSorting[sortIndex] : null;
1089
+ return /* @__PURE__ */ jsxRuntime.jsx(
1090
+ TableHead,
1091
+ {
1092
+ style: { width: col.width },
1093
+ onClick: (e) => col.sortable !== false && handleSort(col.key, e),
1094
+ className: cn(
1095
+ col.sortable !== false && "cursor-pointer select-none hover:text-[var(--ui-text-primary)] transition-colors"
1096
+ ),
1097
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
1098
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: col.header }),
1099
+ col.sortable !== false && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 text-[var(--ui-text-muted)]", children: [
1100
+ sortRule ? sortRule.direction === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "w-3.5 h-3.5 text-[var(--ui-primary)] font-bold" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "w-3.5 h-3.5 text-[var(--ui-primary)] font-bold" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { className: "w-3 h-3 opacity-40" }),
1101
+ currentSorting.length > 1 && sortIndex >= 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-mono font-bold text-[var(--ui-primary)]", children: sortIndex + 1 })
1102
+ ] })
1103
+ ] })
1104
+ },
1105
+ col.key
1106
+ );
1107
+ })
1108
+ ] }) }),
1109
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: paginatedData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(
1110
+ TableCell,
688
1111
  {
689
- type: "checkbox",
690
- checked: isAllSelected,
691
- onChange: toggleSelectAll,
692
- className: "rounded border-[var(--ui-border-default)] text-[var(--ui-primary)] focus:ring-[var(--ui-primary)] cursor-pointer"
1112
+ colSpan: columns.length + (selectable ? 1 : 0),
1113
+ className: "h-32 text-center text-xs text-[var(--ui-text-muted)]",
1114
+ children: emptyText
693
1115
  }
694
- ) }),
695
- columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
696
- TableHead,
697
- {
698
- style: { width: col.width },
699
- onClick: () => col.sortable !== false && handleSort(col.key),
700
- className: cn(
701
- col.sortable !== false && "cursor-pointer select-none hover:text-[var(--ui-text-primary)] transition-colors"
702
- ),
703
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
704
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: col.header }),
705
- col.sortable !== false && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--ui-text-muted)]", children: sortKey === col.key ? sortDirection === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "w-3.5 h-3.5 text-[var(--ui-primary)] font-bold" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "w-3.5 h-3.5 text-[var(--ui-primary)] font-bold" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { className: "w-3 h-3 opacity-40" }) })
706
- ] })
707
- },
708
- col.key
709
- ))
710
- ] }) }),
711
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: paginatedData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length + (selectable ? 1 : 0), className: "h-32 text-center text-xs text-[var(--ui-text-muted)]", children: "No matching records found." }) }) : paginatedData.map((row, rowIdx) => {
712
- const key = keyExtractor(row);
713
- const isSelected = selectedKeys.includes(key);
714
- return /* @__PURE__ */ jsxRuntime.jsxs(
715
- TableRow,
716
- {
717
- "data-state": isSelected ? "selected" : void 0,
718
- className: cn(isSelected && "bg-[var(--ui-primary)]/10"),
719
- children: [
720
- selectable && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "w-10 px-4", children: /* @__PURE__ */ jsxRuntime.jsx(
721
- "input",
722
- {
723
- type: "checkbox",
724
- checked: isSelected,
725
- onChange: () => toggleSelectRow(key),
726
- className: "rounded border-[var(--ui-border-default)] text-[var(--ui-primary)] focus:ring-[var(--ui-primary)] cursor-pointer"
727
- }
728
- ) }),
729
- columns.map((col) => {
730
- const cellContent = col.render ? col.render(row, rowIdx) : col.accessor ? col.accessor(row) : row[col.key];
731
- return /* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: cellContent }, col.key);
732
- })
733
- ]
734
- },
735
- key
736
- );
737
- }) })
738
- ] }) }),
1116
+ ) }) : paginatedData.map((row, rowIdx) => {
1117
+ const key = keyExtractor(row);
1118
+ const isSelected = selectedKeys.includes(key);
1119
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1120
+ TableRow,
1121
+ {
1122
+ "data-state": isSelected ? "selected" : void 0,
1123
+ className: cn(isSelected && "bg-[var(--ui-primary)]/10"),
1124
+ children: [
1125
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "w-10 px-4", children: /* @__PURE__ */ jsxRuntime.jsx(
1126
+ Checkbox,
1127
+ {
1128
+ checked: isSelected,
1129
+ onCheckedChange: () => toggleSelectRow(key),
1130
+ "aria-label": `Select row ${key}`
1131
+ }
1132
+ ) }),
1133
+ columns.map((col) => {
1134
+ const val = col.accessor ? col.accessor(row) : row[col.key];
1135
+ const cellContent = col.render ? col.render(row, rowIdx, val) : val;
1136
+ return /* @__PURE__ */ jsxRuntime.jsx(TableCell, { children: cellContent }, col.key);
1137
+ })
1138
+ ]
1139
+ },
1140
+ key
1141
+ );
1142
+ }) })
1143
+ ] })
1144
+ ] }),
739
1145
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-3 px-1 text-xs text-[var(--ui-text-muted)] font-mono", children: [
740
1146
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
741
1147
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rows per page:" }),
@@ -743,21 +1149,18 @@ function DataTablePro({
743
1149
  "select",
744
1150
  {
745
1151
  value: pageSize,
746
- onChange: (e) => {
747
- setPageSize(Number(e.target.value));
748
- setCurrentPage(1);
749
- },
1152
+ onChange: (e) => handlePageSizeChange(Number(e.target.value)),
750
1153
  className: "px-2 py-1 rounded-lg bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] text-[var(--ui-text-primary)] font-mono text-xs focus:outline-none",
751
1154
  children: pageSizeOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: opt }, opt))
752
1155
  }
753
1156
  ),
754
1157
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[var(--ui-text-muted)]", children: [
755
1158
  "Showing ",
756
- Math.min((currentPage - 1) * pageSize + 1, sortedData.length),
1159
+ totalItems === 0 ? 0 : Math.min((currentPage - 1) * pageSize + 1, totalItems),
757
1160
  "\u2013",
758
- Math.min(currentPage * pageSize, sortedData.length),
1161
+ Math.min(currentPage * pageSize, totalItems),
759
1162
  " of ",
760
- sortedData.length
1163
+ totalItems
761
1164
  ] })
762
1165
  ] }),
763
1166
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
@@ -766,8 +1169,9 @@ function DataTablePro({
766
1169
  {
767
1170
  size: "xs",
768
1171
  variant: "outline",
769
- disabled: currentPage === 1,
770
- onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
1172
+ disabled: currentPage <= 1 || loading,
1173
+ onClick: () => handlePageChange(currentPage - 1),
1174
+ "aria-label": "Previous page",
771
1175
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "w-3.5 h-3.5" })
772
1176
  }
773
1177
  ),
@@ -781,8 +1185,9 @@ function DataTablePro({
781
1185
  {
782
1186
  size: "xs",
783
1187
  variant: "outline",
784
- disabled: currentPage === totalPages,
785
- onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
1188
+ disabled: currentPage >= totalPages || loading,
1189
+ onClick: () => handlePageChange(currentPage + 1),
1190
+ "aria-label": "Next page",
786
1191
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-3.5 h-3.5" })
787
1192
  }
788
1193
  )
@@ -790,106 +1195,224 @@ function DataTablePro({
790
1195
  ] })
791
1196
  ] });
792
1197
  }
793
- function TreeNode({ item, level, selectedId, onSelect }) {
794
- const [isExpanded, setIsExpanded] = React11.useState(Boolean(item.defaultExpanded));
795
- const hasChildren = Boolean(item.children && item.children.length > 0);
796
- const isSelected = selectedId === item.id;
797
- const handleClick = (e) => {
798
- e.stopPropagation();
799
- if (hasChildren) {
800
- setIsExpanded(!isExpanded);
801
- }
802
- onSelect?.(item);
803
- };
804
- const getIcon = () => {
805
- if (item.icon) return item.icon;
806
- if (hasChildren) {
807
- return isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderOpen, { className: "w-4 h-4 text-amber-500 shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Folder, { className: "w-4 h-4 text-amber-500 shrink-0" });
808
- }
809
- if (item.label.endsWith(".tsx") || item.label.endsWith(".ts") || item.label.endsWith(".js")) {
810
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { className: "w-4 h-4 text-blue-500 shrink-0" });
811
- }
812
- if (item.label.endsWith(".png") || item.label.endsWith(".jpg") || item.label.endsWith(".svg")) {
813
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "w-4 h-4 text-purple-500 shrink-0" });
814
- }
815
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "w-4 h-4 text-[var(--ui-text-muted)] shrink-0" });
816
- };
817
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "select-none text-xs", children: [
818
- /* @__PURE__ */ jsxRuntime.jsxs(
819
- "div",
820
- {
821
- onClick: handleClick,
822
- style: { paddingLeft: `${level * 16 + 8}px` },
823
- className: cn(
824
- "flex items-center justify-between py-1.5 pr-2.5 rounded-xl cursor-pointer transition-colors group",
825
- isSelected ? "bg-[var(--ui-primary)] text-white font-semibold shadow-xs" : "text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)]"
826
- ),
827
- children: [
828
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
829
- hasChildren ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("p-0.5 rounded transition-transform duration-200", isExpanded && "rotate-90"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: cn("w-3 h-3", isSelected ? "text-white" : "text-[var(--ui-text-muted)]") }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4" }),
830
- getIcon(),
831
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label })
832
- ] }),
833
- item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
834
- "span",
1198
+ var TreeView = React15.forwardRef(
1199
+ ({
1200
+ data,
1201
+ selectedId,
1202
+ defaultExpandedIds,
1203
+ onSelect,
1204
+ onExpandedChange,
1205
+ className,
1206
+ "aria-label": ariaLabel = "Tree View"
1207
+ }, ref) => {
1208
+ const initialExpanded = React15.useMemo(() => {
1209
+ if (defaultExpandedIds) return new Set(defaultExpandedIds);
1210
+ const set = /* @__PURE__ */ new Set();
1211
+ const collect = (items) => {
1212
+ for (const it of items) {
1213
+ if (it.defaultExpanded) set.add(it.id);
1214
+ if (it.children) collect(it.children);
1215
+ }
1216
+ };
1217
+ collect(data);
1218
+ return set;
1219
+ }, [data, defaultExpandedIds]);
1220
+ const [expandedSet, setExpandedSet] = React15.useState(initialExpanded);
1221
+ const [focusedId, setFocusedId] = React15.useState(null);
1222
+ const itemRefs = React15.useRef(/* @__PURE__ */ new Map());
1223
+ const focusNode = (id) => {
1224
+ setFocusedId(id);
1225
+ const el = itemRefs.current.get(id);
1226
+ if (el) {
1227
+ el.focus();
1228
+ }
1229
+ };
1230
+ const toggleExpand = (id) => {
1231
+ setExpandedSet((prev) => {
1232
+ const next = new Set(prev);
1233
+ if (next.has(id)) next.delete(id);
1234
+ else next.add(id);
1235
+ onExpandedChange?.(Array.from(next));
1236
+ return next;
1237
+ });
1238
+ };
1239
+ const expandNode = (id) => {
1240
+ if (!expandedSet.has(id)) {
1241
+ setExpandedSet((prev) => {
1242
+ const next = new Set(prev).add(id);
1243
+ onExpandedChange?.(Array.from(next));
1244
+ return next;
1245
+ });
1246
+ }
1247
+ };
1248
+ const collapseNode = (id) => {
1249
+ if (expandedSet.has(id)) {
1250
+ setExpandedSet((prev) => {
1251
+ const next = new Set(prev);
1252
+ next.delete(id);
1253
+ onExpandedChange?.(Array.from(next));
1254
+ return next;
1255
+ });
1256
+ }
1257
+ };
1258
+ const visibleList = React15.useMemo(() => {
1259
+ const list = [];
1260
+ const traverse = (items, level, parentId) => {
1261
+ for (const item of items) {
1262
+ const hasChildren = Boolean(item.children && item.children.length > 0);
1263
+ list.push({ item, level, parentId, hasChildren });
1264
+ if (hasChildren && expandedSet.has(item.id)) {
1265
+ traverse(item.children, level + 1, item.id);
1266
+ }
1267
+ }
1268
+ };
1269
+ traverse(data, 0, null);
1270
+ return list;
1271
+ }, [data, expandedSet]);
1272
+ const handleKeyDown = (e) => {
1273
+ if (visibleList.length === 0) return;
1274
+ const currentIdx = focusedId ? visibleList.findIndex((f) => f.item.id === focusedId) : 0;
1275
+ const currentFlat = visibleList[currentIdx] || visibleList[0];
1276
+ if (e.key === "ArrowDown") {
1277
+ e.preventDefault();
1278
+ const nextIdx = Math.min(visibleList.length - 1, currentIdx + 1);
1279
+ focusNode(visibleList[nextIdx].item.id);
1280
+ } else if (e.key === "ArrowUp") {
1281
+ e.preventDefault();
1282
+ const prevIdx = Math.max(0, currentIdx - 1);
1283
+ focusNode(visibleList[prevIdx].item.id);
1284
+ } else if (e.key === "ArrowRight") {
1285
+ e.preventDefault();
1286
+ if (currentFlat.hasChildren) {
1287
+ if (!expandedSet.has(currentFlat.item.id)) {
1288
+ expandNode(currentFlat.item.id);
1289
+ } else {
1290
+ const nextIdx = currentIdx + 1;
1291
+ if (nextIdx < visibleList.length) {
1292
+ focusNode(visibleList[nextIdx].item.id);
1293
+ }
1294
+ }
1295
+ }
1296
+ } else if (e.key === "ArrowLeft") {
1297
+ e.preventDefault();
1298
+ if (currentFlat.hasChildren && expandedSet.has(currentFlat.item.id)) {
1299
+ collapseNode(currentFlat.item.id);
1300
+ } else if (currentFlat.parentId) {
1301
+ focusNode(currentFlat.parentId);
1302
+ }
1303
+ } else if (e.key === "Home") {
1304
+ e.preventDefault();
1305
+ focusNode(visibleList[0].item.id);
1306
+ } else if (e.key === "End") {
1307
+ e.preventDefault();
1308
+ focusNode(visibleList[visibleList.length - 1].item.id);
1309
+ } else if (e.key === "Enter" || e.key === " ") {
1310
+ e.preventDefault();
1311
+ if (currentFlat) {
1312
+ if (currentFlat.hasChildren) {
1313
+ toggleExpand(currentFlat.item.id);
1314
+ }
1315
+ onSelect?.(currentFlat.item);
1316
+ }
1317
+ }
1318
+ };
1319
+ const getIcon = (item, hasChildren, isExpanded) => {
1320
+ if (item.icon) return item.icon;
1321
+ if (hasChildren) {
1322
+ return isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderOpen, { className: "w-4 h-4 text-amber-500 shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Folder, { className: "w-4 h-4 text-amber-500 shrink-0" });
1323
+ }
1324
+ if (item.label.endsWith(".tsx") || item.label.endsWith(".ts") || item.label.endsWith(".js")) {
1325
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { className: "w-4 h-4 text-blue-500 shrink-0" });
1326
+ }
1327
+ if (item.label.endsWith(".png") || item.label.endsWith(".jpg") || item.label.endsWith(".svg")) {
1328
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "w-4 h-4 text-purple-500 shrink-0" });
1329
+ }
1330
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "w-4 h-4 text-[var(--ui-text-muted)] shrink-0" });
1331
+ };
1332
+ const renderNodes = (items, level) => {
1333
+ return items.map((item, index) => {
1334
+ const hasChildren = Boolean(item.children && item.children.length > 0);
1335
+ const isExpanded = expandedSet.has(item.id);
1336
+ const isSelected = selectedId === item.id;
1337
+ const isFocused = focusedId === item.id || !focusedId && level === 0 && index === 0;
1338
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "none", className: "select-none text-xs", children: [
1339
+ /* @__PURE__ */ jsxRuntime.jsxs(
1340
+ "div",
835
1341
  {
1342
+ ref: (el) => {
1343
+ if (el) itemRefs.current.set(item.id, el);
1344
+ else itemRefs.current.delete(item.id);
1345
+ },
1346
+ role: "treeitem",
1347
+ tabIndex: isFocused ? 0 : -1,
1348
+ "aria-expanded": hasChildren ? isExpanded : void 0,
1349
+ "aria-selected": isSelected,
1350
+ "aria-level": level + 1,
1351
+ "aria-posinset": index + 1,
1352
+ "aria-setsize": items.length,
1353
+ onClick: (e) => {
1354
+ e.stopPropagation();
1355
+ focusNode(item.id);
1356
+ if (hasChildren) {
1357
+ toggleExpand(item.id);
1358
+ }
1359
+ onSelect?.(item);
1360
+ },
1361
+ style: { paddingLeft: `${level * 16 + 8}px` },
836
1362
  className: cn(
837
- "px-1.5 py-0.5 rounded-md text-[10px] font-mono",
838
- isSelected ? "bg-white/20 text-white" : "bg-[var(--ui-bg-secondary)] text-[var(--ui-text-muted)]"
1363
+ "flex items-center justify-between py-1.5 pr-2.5 rounded-xl cursor-pointer transition-colors group outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)]",
1364
+ isSelected ? "bg-[var(--ui-primary)] text-white font-semibold shadow-xs" : "text-[var(--ui-text-primary)] hover:bg-[var(--ui-bg-tertiary)]"
839
1365
  ),
840
- children: item.badge
1366
+ children: [
1367
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
1368
+ hasChildren ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("p-0.5 rounded transition-transform duration-200", isExpanded && "rotate-90"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: cn("w-3 h-3", isSelected ? "text-white" : "text-[var(--ui-text-muted)]") }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4" }),
1369
+ getIcon(item, hasChildren, isExpanded),
1370
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label })
1371
+ ] }),
1372
+ item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1373
+ "span",
1374
+ {
1375
+ className: cn(
1376
+ "px-1.5 py-0.5 rounded-md text-[10px] font-mono",
1377
+ isSelected ? "bg-white/20 text-white" : "bg-[var(--ui-bg-secondary)] text-[var(--ui-text-muted)]"
1378
+ ),
1379
+ children: item.badge
1380
+ }
1381
+ )
1382
+ ]
841
1383
  }
842
- )
843
- ]
844
- }
845
- ),
846
- hasChildren && isExpanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative space-y-0.5 animate-in fade-in duration-150", children: [
847
- /* @__PURE__ */ jsxRuntime.jsx(
848
- "div",
849
- {
850
- className: "absolute left-[15px] top-0 bottom-0 w-[1px] bg-[var(--ui-border-subtle)]",
851
- style: { left: `${level * 16 + 15}px` }
852
- }
853
- ),
854
- item.children.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
855
- TreeNode,
856
- {
857
- item: child,
858
- level: level + 1,
859
- selectedId,
860
- onSelect
861
- },
862
- child.id
863
- ))
864
- ] })
865
- ] });
866
- }
867
- var TreeView = React11.forwardRef(
868
- ({ data, selectedId, onSelect, className }, ref) => {
1384
+ ),
1385
+ hasChildren && isExpanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "group", className: "relative space-y-0.5 animate-in fade-in duration-150", children: [
1386
+ /* @__PURE__ */ jsxRuntime.jsx(
1387
+ "div",
1388
+ {
1389
+ className: "absolute left-[15px] top-0 bottom-0 w-[1px] bg-[var(--ui-border-subtle)]",
1390
+ style: { left: `${level * 16 + 15}px` }
1391
+ }
1392
+ ),
1393
+ renderNodes(item.children, level + 1)
1394
+ ] })
1395
+ ] }, item.id);
1396
+ });
1397
+ };
869
1398
  return /* @__PURE__ */ jsxRuntime.jsx(
870
1399
  "div",
871
1400
  {
872
1401
  ref,
1402
+ role: "tree",
1403
+ "aria-label": ariaLabel,
1404
+ onKeyDown: handleKeyDown,
873
1405
  className: cn(
874
- "w-full p-2 rounded-2xl bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] space-y-0.5 shadow-sm overflow-hidden",
1406
+ "w-full p-2 rounded-2xl bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] space-y-0.5 shadow-sm overflow-hidden outline-none",
875
1407
  className
876
1408
  ),
877
- children: data.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
878
- TreeNode,
879
- {
880
- item,
881
- level: 0,
882
- selectedId,
883
- onSelect
884
- },
885
- item.id
886
- ))
1409
+ children: renderNodes(data, 0)
887
1410
  }
888
1411
  );
889
1412
  }
890
1413
  );
891
1414
  TreeView.displayName = "TreeView";
892
- var Carousel = React11.forwardRef(
1415
+ var Carousel = React15.forwardRef(
893
1416
  ({
894
1417
  autoplay = false,
895
1418
  autoplayInterval = 4e3,
@@ -900,9 +1423,9 @@ var Carousel = React11.forwardRef(
900
1423
  className,
901
1424
  ...props
902
1425
  }, ref) => {
903
- const [currentIndex, setCurrentIndex] = React11.useState(0);
904
- const totalSlides = React11__default.default.Children.count(children);
905
- const timerRef = React11.useRef(null);
1426
+ const [currentIndex, setCurrentIndex] = React15.useState(0);
1427
+ const totalSlides = React15__default.default.Children.count(children);
1428
+ const timerRef = React15.useRef(null);
906
1429
  const nextSlide = () => {
907
1430
  setCurrentIndex((prev) => {
908
1431
  if (prev === totalSlides - 1) {
@@ -919,7 +1442,7 @@ var Carousel = React11.forwardRef(
919
1442
  return prev - 1;
920
1443
  });
921
1444
  };
922
- React11.useEffect(() => {
1445
+ React15.useEffect(() => {
923
1446
  if (autoplay && totalSlides > 1) {
924
1447
  timerRef.current = setInterval(nextSlide, autoplayInterval);
925
1448
  return () => clearInterval(timerRef.current);
@@ -943,7 +1466,7 @@ var Carousel = React11.forwardRef(
943
1466
  {
944
1467
  className: "flex transition-transform duration-500 ease-out",
945
1468
  style: { transform: `translateX(-${currentIndex * 100}%)` },
946
- children: React11__default.default.Children.map(children, (child, idx) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-shrink-0", children: child }, idx))
1469
+ children: React15__default.default.Children.map(children, (child, idx) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-shrink-0", children: child }, idx))
947
1470
  }
948
1471
  ),
949
1472
  showArrows && totalSlides > 1 && /* @__PURE__ */ jsxRuntime.jsx(