@kala-ui/react 0.0.1-beta.7 → 0.0.2

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 (291) hide show
  1. package/dist/components/accordion/accordion-skeleton.js +1 -1
  2. package/dist/components/accordion/accordion.js +2 -1
  3. package/dist/components/action-icon/action-icon.d.ts +12 -0
  4. package/dist/components/action-icon/action-icon.js +35 -0
  5. package/dist/components/action-icon/action-icon.stories.d.ts +9 -0
  6. package/dist/components/action-icon/action-icon.stories.js +42 -0
  7. package/dist/components/action-icon/index.d.ts +1 -0
  8. package/dist/components/action-icon/index.js +1 -0
  9. package/dist/components/alert/alert-skeleton.js +4 -3
  10. package/dist/components/alert/alert.d.ts +2 -2
  11. package/dist/components/alert/alert.js +8 -6
  12. package/dist/components/alert/alert.stories.js +13 -9
  13. package/dist/components/alert/index.d.ts +1 -1
  14. package/dist/components/alert-dialog/alert-dialog.js +8 -5
  15. package/dist/components/app-shell/app-shell.d.ts +58 -0
  16. package/dist/components/app-shell/app-shell.js +111 -0
  17. package/dist/components/app-shell/app-shell.stories.d.ts +8 -0
  18. package/dist/components/app-shell/app-shell.stories.js +35 -0
  19. package/dist/components/app-shell/index.d.ts +1 -0
  20. package/dist/components/app-shell/index.js +1 -0
  21. package/dist/components/avatar/avatar.d.ts +2 -2
  22. package/dist/components/avatar/avatar.stories.js +1 -1
  23. package/dist/components/badge/badge.d.ts +1 -1
  24. package/dist/components/badge/badge.js +1 -1
  25. package/dist/components/badge/badge.stories.js +1 -1
  26. package/dist/components/banner/banner-skeleton.js +1 -1
  27. package/dist/components/banner/banner.d.ts +1 -1
  28. package/dist/components/banner/banner.stories.js +1 -1
  29. package/dist/components/box/box.d.ts +8 -0
  30. package/dist/components/box/box.js +10 -0
  31. package/dist/components/box/box.stories.d.ts +8 -0
  32. package/dist/components/box/box.stories.js +32 -0
  33. package/dist/components/box/index.d.ts +1 -0
  34. package/dist/components/box/index.js +1 -0
  35. package/dist/components/breadcrumbs/breadcrumbs-skeleton.js +1 -1
  36. package/dist/components/breadcrumbs/breadcrumbs.stories.js +1 -1
  37. package/dist/components/burger/burger.d.ts +8 -0
  38. package/dist/components/burger/burger.js +21 -0
  39. package/dist/components/burger/burger.stories.d.ts +8 -0
  40. package/dist/components/burger/burger.stories.js +31 -0
  41. package/dist/components/burger/index.d.ts +1 -0
  42. package/dist/components/burger/index.js +1 -0
  43. package/dist/components/button/button.d.ts +2 -2
  44. package/dist/components/button/button.stories.js +10 -7
  45. package/dist/components/button-group/button-group.stories.js +1 -1
  46. package/dist/components/calendar/calendar-skeleton.js +1 -1
  47. package/dist/components/calendar/calendar.d.ts +1 -1
  48. package/dist/components/calendar/calendar.js +1 -1
  49. package/dist/components/calendar/calendar.types.d.ts +3 -3
  50. package/dist/components/card/card-skeleton.js +2 -2
  51. package/dist/components/card/card.js +17 -14
  52. package/dist/components/card/index.d.ts +1 -1
  53. package/dist/components/center/center.d.ts +7 -0
  54. package/dist/components/center/center.js +10 -0
  55. package/dist/components/center/center.stories.d.ts +7 -0
  56. package/dist/components/center/center.stories.js +25 -0
  57. package/dist/components/center/index.d.ts +1 -0
  58. package/dist/components/center/index.js +1 -0
  59. package/dist/components/charts/area-chart.js +1 -1
  60. package/dist/components/charts/bar-chart.js +1 -1
  61. package/dist/components/charts/donut-chart.js +1 -1
  62. package/dist/components/charts/index.d.ts +2 -2
  63. package/dist/components/charts/index.js +2 -2
  64. package/dist/components/charts/line-chart.js +1 -1
  65. package/dist/components/charts/radial-bar-chart.js +1 -1
  66. package/dist/components/charts/theme-utils.d.ts +1 -1
  67. package/dist/components/charts/use-theme-aware-chart.d.ts +1 -1
  68. package/dist/components/charts/use-theme-aware-chart.js +2 -1
  69. package/dist/components/checkbox/checkbox.js +1 -1
  70. package/dist/components/checkbox/checkbox.stories.js +12 -8
  71. package/dist/components/close-button/close-button.d.ts +7 -0
  72. package/dist/components/close-button/close-button.js +9 -0
  73. package/dist/components/close-button/close-button.stories.d.ts +7 -0
  74. package/dist/components/close-button/close-button.stories.js +18 -0
  75. package/dist/components/close-button/index.d.ts +1 -0
  76. package/dist/components/close-button/index.js +1 -0
  77. package/dist/components/code/code.d.ts +8 -0
  78. package/dist/components/code/code.js +14 -0
  79. package/dist/components/code/code.stories.d.ts +8 -0
  80. package/dist/components/code/code.stories.js +31 -0
  81. package/dist/components/code/index.d.ts +1 -0
  82. package/dist/components/code/index.js +1 -0
  83. package/dist/components/collapse/collapse.d.ts +17 -0
  84. package/dist/components/collapse/collapse.js +34 -0
  85. package/dist/components/collapse/index.d.ts +1 -0
  86. package/dist/components/collapse/index.js +1 -0
  87. package/dist/components/color-input/color-input.d.ts +28 -0
  88. package/dist/components/color-input/color-input.js +35 -0
  89. package/dist/components/color-input/color-input.stories.d.ts +10 -0
  90. package/dist/components/color-input/color-input.stories.js +41 -0
  91. package/dist/components/color-input/index.d.ts +1 -0
  92. package/dist/components/color-input/index.js +1 -0
  93. package/dist/components/combobox/combobox-skeleton.js +1 -1
  94. package/dist/components/combobox/combobox.d.ts +1 -1
  95. package/dist/components/combobox/combobox.js +17 -8
  96. package/dist/components/combobox/combobox.stories.js +1 -1
  97. package/dist/components/command/command.d.ts +2 -2
  98. package/dist/components/command/command.stories.js +14 -19
  99. package/dist/components/container/container.d.ts +1 -1
  100. package/dist/components/container/index.d.ts +1 -1
  101. package/dist/components/container/index.js +1 -1
  102. package/dist/components/data-table/column-header-filter.js +11 -6
  103. package/dist/components/data-table/data-table-skeleton.js +5 -15
  104. package/dist/components/data-table/data-table.js +18 -15
  105. package/dist/components/data-table/data-table.stories.js +3 -5
  106. package/dist/components/date-picker/date-picker.d.ts +1 -1
  107. package/dist/components/date-picker/date-picker.js +3 -3
  108. package/dist/components/date-picker/date-picker.types.d.ts +1 -1
  109. package/dist/components/dialog/dialog-skeleton.js +1 -1
  110. package/dist/components/dialog/dialog.js +6 -4
  111. package/dist/components/dialog/dialog.stories.js +2 -2
  112. package/dist/components/dnd/dnd.d.ts +4 -5
  113. package/dist/components/dnd/dnd.js +5 -5
  114. package/dist/components/dnd/dnd.stories.js +48 -40
  115. package/dist/components/drawer/drawer.stories.js +2 -2
  116. package/dist/components/empty-state/empty-state-skeleton.js +2 -3
  117. package/dist/components/empty-state/empty-state.d.ts +1 -1
  118. package/dist/components/field/field-skeleton.js +1 -1
  119. package/dist/components/field/field.stories.js +1 -1
  120. package/dist/components/file-upload/file-upload-skeleton.js +1 -1
  121. package/dist/components/flex/flex.d.ts +7 -5
  122. package/dist/components/flex/flex.js +2 -2
  123. package/dist/components/flex/index.d.ts +1 -1
  124. package/dist/components/flex/index.js +1 -1
  125. package/dist/components/grid/grid.d.ts +24 -0
  126. package/dist/components/grid/grid.js +136 -0
  127. package/dist/components/grid/grid.stories.d.ts +8 -0
  128. package/dist/components/grid/grid.stories.js +31 -0
  129. package/dist/components/grid/index.d.ts +1 -0
  130. package/dist/components/grid/index.js +1 -0
  131. package/dist/components/group/group.d.ts +2 -2
  132. package/dist/components/group/group.js +1 -1
  133. package/dist/components/group/index.d.ts +1 -1
  134. package/dist/components/group/index.js +1 -1
  135. package/dist/components/header/header-skeleton.js +1 -1
  136. package/dist/components/header/header.d.ts +3 -3
  137. package/dist/components/header/header.js +17 -31
  138. package/dist/components/header/index.d.ts +1 -1
  139. package/dist/components/heading/heading.d.ts +4 -2
  140. package/dist/components/heading/heading.js +3 -7
  141. package/dist/components/heading/index.d.ts +1 -1
  142. package/dist/components/heading/index.js +1 -1
  143. package/dist/components/indicator/index.d.ts +1 -0
  144. package/dist/components/indicator/index.js +1 -0
  145. package/dist/components/indicator/indicator.d.ts +30 -0
  146. package/dist/components/indicator/indicator.js +89 -0
  147. package/dist/components/indicator/indicator.stories.d.ts +10 -0
  148. package/dist/components/indicator/indicator.stories.js +75 -0
  149. package/dist/components/input/input.js +1 -1
  150. package/dist/components/input/input.stories.js +1 -1
  151. package/dist/components/input-group/input-group.stories.js +1 -1
  152. package/dist/components/kbd/index.d.ts +1 -0
  153. package/dist/components/kbd/index.js +1 -0
  154. package/dist/components/kbd/kbd.d.ts +6 -0
  155. package/dist/components/kbd/kbd.js +13 -0
  156. package/dist/components/kbd/kbd.stories.d.ts +9 -0
  157. package/dist/components/kbd/kbd.stories.js +28 -0
  158. package/dist/components/label/label.stories.js +1 -1
  159. package/dist/components/list/list-skeleton.js +2 -2
  160. package/dist/components/list/list.js +1 -1
  161. package/dist/components/list/list.stories.js +1 -1
  162. package/dist/components/list/list.types.d.ts +2 -2
  163. package/dist/components/loading-overlay/index.d.ts +1 -0
  164. package/dist/components/loading-overlay/index.js +1 -0
  165. package/dist/components/loading-overlay/loading-overlay.d.ts +19 -0
  166. package/dist/components/loading-overlay/loading-overlay.js +19 -0
  167. package/dist/components/loading-overlay/loading-overlay.stories.d.ts +8 -0
  168. package/dist/components/loading-overlay/loading-overlay.stories.js +46 -0
  169. package/dist/components/metric-card/metric-card-skeleton.js +2 -2
  170. package/dist/components/metric-card/metric-card.js +1 -1
  171. package/dist/components/multi-select/multi-select-skeleton.js +1 -1
  172. package/dist/components/multi-select/multi-select.stories.js +1 -1
  173. package/dist/components/nav-link/index.d.ts +1 -0
  174. package/dist/components/nav-link/index.js +1 -0
  175. package/dist/components/nav-link/nav-link.d.ts +26 -0
  176. package/dist/components/nav-link/nav-link.js +26 -0
  177. package/dist/components/nav-link/nav-link.stories.d.ts +9 -0
  178. package/dist/components/nav-link/nav-link.stories.js +37 -0
  179. package/dist/components/navigation/navigation-skeleton.js +1 -1
  180. package/dist/components/number-input/index.d.ts +1 -0
  181. package/dist/components/number-input/index.js +1 -0
  182. package/dist/components/number-input/number-input.d.ts +40 -0
  183. package/dist/components/number-input/number-input.js +69 -0
  184. package/dist/components/number-input/number-input.stories.d.ts +11 -0
  185. package/dist/components/number-input/number-input.stories.js +54 -0
  186. package/dist/components/overlay/index.d.ts +1 -0
  187. package/dist/components/overlay/index.js +1 -0
  188. package/dist/components/overlay/overlay.d.ts +22 -0
  189. package/dist/components/overlay/overlay.js +45 -0
  190. package/dist/components/overlay/overlay.stories.d.ts +9 -0
  191. package/dist/components/overlay/overlay.stories.js +47 -0
  192. package/dist/components/page-transition/page-transition.stories.js +1 -1
  193. package/dist/components/pagination/index.d.ts +1 -1
  194. package/dist/components/pagination/index.js +1 -1
  195. package/dist/components/pagination/pagination-skeleton.js +1 -1
  196. package/dist/components/pagination/pagination.d.ts +44 -28
  197. package/dist/components/pagination/pagination.js +53 -79
  198. package/dist/components/pagination/pagination.stories.d.ts +1 -0
  199. package/dist/components/pagination/pagination.stories.js +31 -5
  200. package/dist/components/paper/index.d.ts +1 -0
  201. package/dist/components/paper/index.js +1 -0
  202. package/dist/components/paper/paper.d.ts +12 -0
  203. package/dist/components/paper/paper.js +39 -0
  204. package/dist/components/paper/paper.stories.d.ts +7 -0
  205. package/dist/components/paper/paper.stories.js +30 -0
  206. package/dist/components/password-strength-indicator/password-strength-indicator.stories.js +1 -1
  207. package/dist/components/popover/popover-skeleton.js +1 -1
  208. package/dist/components/popover/popover.stories.js +2 -2
  209. package/dist/components/progress/index.d.ts +1 -1
  210. package/dist/components/progress/progress.d.ts +1 -1
  211. package/dist/components/progress/progress.stories.js +1 -1
  212. package/dist/components/radio-group/radio-group-skeleton.js +1 -1
  213. package/dist/components/radio-group/radio-group.stories.js +1 -1
  214. package/dist/components/resizable/resizable.stories.js +8 -8
  215. package/dist/components/ring-progress/index.d.ts +1 -0
  216. package/dist/components/ring-progress/index.js +1 -0
  217. package/dist/components/ring-progress/ring-progress.d.ts +24 -0
  218. package/dist/components/ring-progress/ring-progress.js +20 -0
  219. package/dist/components/ring-progress/ring-progress.stories.d.ts +9 -0
  220. package/dist/components/ring-progress/ring-progress.stories.js +46 -0
  221. package/dist/components/scroll-area/scroll-area.stories.js +26 -26
  222. package/dist/components/segmented-control/index.d.ts +1 -0
  223. package/dist/components/segmented-control/index.js +1 -0
  224. package/dist/components/segmented-control/segmented-control.d.ts +19 -0
  225. package/dist/components/segmented-control/segmented-control.js +46 -0
  226. package/dist/components/segmented-control/segmented-control.stories.d.ts +10 -0
  227. package/dist/components/segmented-control/segmented-control.stories.js +53 -0
  228. package/dist/components/select/select.js +1 -1
  229. package/dist/components/select/select.stories.js +1 -1
  230. package/dist/components/separator/separator.stories.js +1 -1
  231. package/dist/components/session-card/session-card-skeleton.js +2 -2
  232. package/dist/components/session-card/session-card.js +1 -1
  233. package/dist/components/sidebar/sidebar-skeleton.js +2 -2
  234. package/dist/components/skeleton/index.d.ts +3 -3
  235. package/dist/components/skeleton/index.js +1 -1
  236. package/dist/components/skeleton/skeleton.types.d.ts +0 -249
  237. package/dist/components/slider/index.d.ts +1 -1
  238. package/dist/components/slider/slider.js +1 -1
  239. package/dist/components/slider/slider.stories.js +1 -1
  240. package/dist/components/social-login-button/social-login-button.js +6 -6
  241. package/dist/components/sparkline-chart/sparkline-chart.js +6 -3
  242. package/dist/components/sparkline-chart/sparkline-chart.stories.js +1 -1
  243. package/dist/components/spinner/spinner.d.ts +1 -1
  244. package/dist/components/spoiler/index.d.ts +1 -0
  245. package/dist/components/spoiler/index.js +1 -0
  246. package/dist/components/spoiler/spoiler.d.ts +14 -0
  247. package/dist/components/spoiler/spoiler.js +20 -0
  248. package/dist/components/spoiler/spoiler.stories.d.ts +8 -0
  249. package/dist/components/spoiler/spoiler.stories.js +35 -0
  250. package/dist/components/stack/index.d.ts +1 -1
  251. package/dist/components/stack/index.js +1 -1
  252. package/dist/components/stack/stack.d.ts +2 -2
  253. package/dist/components/stack/stack.js +1 -1
  254. package/dist/components/steps/steps-skeleton.js +1 -1
  255. package/dist/components/steps/steps.js +7 -5
  256. package/dist/components/steps/steps.stories.js +6 -2
  257. package/dist/components/switch/index.d.ts +1 -1
  258. package/dist/components/switch/switch.js +1 -1
  259. package/dist/components/switch/switch.stories.js +1 -1
  260. package/dist/components/table/table-skeleton.js +2 -2
  261. package/dist/components/table/table.js +4 -3
  262. package/dist/components/table/table.stories.js +10 -7
  263. package/dist/components/tabs/tabs-skeleton.js +1 -1
  264. package/dist/components/tabs/tabs.d.ts +3 -3
  265. package/dist/components/tabs/tabs.js +1 -1
  266. package/dist/components/tabs/tabs.stories.js +5 -5
  267. package/dist/components/text/index.d.ts +1 -1
  268. package/dist/components/text/index.js +1 -1
  269. package/dist/components/text/text.d.ts +7 -5
  270. package/dist/components/text/text.js +2 -2
  271. package/dist/components/text/text.stories.js +34 -3
  272. package/dist/components/textarea/textarea.js +1 -1
  273. package/dist/components/textarea/textarea.stories.js +1 -1
  274. package/dist/components/timeline/index.d.ts +1 -0
  275. package/dist/components/timeline/index.js +1 -0
  276. package/dist/components/timeline/timeline.d.ts +35 -0
  277. package/dist/components/timeline/timeline.js +36 -0
  278. package/dist/components/timeline/timeline.stories.d.ts +7 -0
  279. package/dist/components/timeline/timeline.stories.js +21 -0
  280. package/dist/components/toast/toast.js +6 -6
  281. package/dist/components/toggle/toggle.stories.js +1 -1
  282. package/dist/components/tooltip/tooltip.stories.js +1 -1
  283. package/dist/components/user-menu-dropdown/user-menu-dropdown.js +1 -1
  284. package/dist/config/tailwind-base.d.ts +10 -0
  285. package/dist/config/tailwind-base.js +1 -0
  286. package/dist/index.d.ts +25 -0
  287. package/dist/index.js +25 -10
  288. package/dist/lib/animations.js +94 -94
  289. package/dist/primitives/command/Command.js +2 -1
  290. package/dist/styles/globals.css +415 -82
  291. package/package.json +101 -24
@@ -1,6 +1,10 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useDisclosure, useHotkeys } from "@kala-ui/react-hooks";
2
3
  import { Calculator, Calendar, CreditCard, Settings, Smile, User, } from "lucide-react";
3
- import { useEffect, useState } from "react";
4
+ import { useState } from "react";
5
+ import { Box } from "../box";
6
+ import { Stack } from "../stack";
7
+ import { Text } from "../text";
4
8
  import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "./command";
5
9
  const meta = {
6
10
  title: "Components/Command",
@@ -17,34 +21,25 @@ const meta = {
17
21
  };
18
22
  export default meta;
19
23
  export const Default = {
20
- render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Type a command or search..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Suggestions", children: [_jsxs(CommandItem, { children: [_jsx(Calendar, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Calendar" })] }), _jsxs(CommandItem, { children: [_jsx(Smile, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Search Emoji" })] }), _jsxs(CommandItem, { children: [_jsx(Calculator, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Calculator" })] })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Settings", children: [_jsxs(CommandItem, { children: [_jsx(User, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Profile" }), _jsx(CommandShortcut, { children: "\u2318P" })] }), _jsxs(CommandItem, { children: [_jsx(CreditCard, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Billing" }), _jsx(CommandShortcut, { children: "\u2318B" })] }), _jsxs(CommandItem, { children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Settings" }), _jsx(CommandShortcut, { children: "\u2318S" })] })] })] })] })),
24
+ render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Type a command or search..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Suggestions", children: [_jsxs(CommandItem, { children: [_jsx(Calendar, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Calendar" })] }), _jsxs(CommandItem, { children: [_jsx(Smile, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Search Emoji" })] }), _jsxs(CommandItem, { children: [_jsx(Calculator, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Calculator" })] })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Settings", children: [_jsxs(CommandItem, { children: [_jsx(User, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Profile" }), _jsx(CommandShortcut, { children: "\u2318P" })] }), _jsxs(CommandItem, { children: [_jsx(CreditCard, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Billing" }), _jsx(CommandShortcut, { children: "\u2318B" })] }), _jsxs(CommandItem, { children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Settings" }), _jsx(CommandShortcut, { children: "\u2318S" })] })] })] })] })),
21
25
  };
22
26
  export const WithDialog = {
23
27
  render: () => {
24
- const [open, setOpen] = useState(false);
25
- useEffect(() => {
26
- const down = (e) => {
27
- if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
28
- e.preventDefault();
29
- setOpen((open) => !open);
30
- }
31
- };
32
- document.addEventListener("keydown", down);
33
- return () => document.removeEventListener("keydown", down);
34
- }, []);
35
- return (_jsxs(_Fragment, { children: [_jsxs("p", { className: "text-sm text-muted-foreground mb-4", children: ["Press", " ", _jsxs("kbd", { className: "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100", children: [_jsx("span", { className: "text-xs", children: "\u2318" }), "K"] })] }), _jsx("button", { type: "button", onClick: () => setOpen(true), className: "rounded-md border px-4 py-2 text-sm hover:bg-accent", children: "Open Command Menu" }), _jsxs(CommandDialog, { open: open, onOpenChange: setOpen, children: [_jsx(CommandInput, { placeholder: "Type a command or search..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Suggestions", children: [_jsxs(CommandItem, { children: [_jsx(Calendar, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Calendar" })] }), _jsxs(CommandItem, { children: [_jsx(Smile, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Search Emoji" })] }), _jsxs(CommandItem, { children: [_jsx(Calculator, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Calculator" })] })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Settings", children: [_jsxs(CommandItem, { children: [_jsx(User, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Profile" }), _jsx(CommandShortcut, { children: "\u2318P" })] }), _jsxs(CommandItem, { children: [_jsx(CreditCard, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Billing" }), _jsx(CommandShortcut, { children: "\u2318B" })] }), _jsxs(CommandItem, { children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Settings" }), _jsx(CommandShortcut, { children: "\u2318S" })] })] })] })] })] }));
28
+ const [open, { toggle, set: setOpen }] = useDisclosure(false);
29
+ useHotkeys([["mod+K", toggle, { preventDefault: true }]]);
30
+ return (_jsxs(Stack, { gap: 2, children: [_jsxs(Text, { size: "sm", className: "text-muted-foreground", children: ["Press", " ", _jsxs("kbd", { className: "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100", children: [_jsx(Text, { as: "span", className: "text-xs", children: "\u2318" }), "K"] })] }), _jsxs(CommandDialog, { open: open, onOpenChange: setOpen, children: [_jsx(CommandInput, { placeholder: "Type a command or search..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Suggestions", children: [_jsxs(CommandItem, { children: [_jsx(Calendar, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Calendar" })] }), _jsxs(CommandItem, { children: [_jsx(Smile, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Search Emoji" })] }), _jsxs(CommandItem, { children: [_jsx(Calculator, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Calculator" })] })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Settings", children: [_jsxs(CommandItem, { children: [_jsx(User, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Profile" }), _jsx(CommandShortcut, { children: "\u2318P" })] }), _jsxs(CommandItem, { children: [_jsx(CreditCard, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Billing" }), _jsx(CommandShortcut, { children: "\u2318B" })] }), _jsxs(CommandItem, { children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Settings" }), _jsx(CommandShortcut, { children: "\u2318S" })] })] })] })] })] }));
36
31
  },
37
32
  };
38
33
  export const WithSearch = {
39
34
  render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search for fruits..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No fruits found." }), _jsxs(CommandGroup, { heading: "Fruits", children: [_jsx(CommandItem, { value: "apple", children: "\uD83C\uDF4E Apple" }), _jsx(CommandItem, { value: "banana", children: "\uD83C\uDF4C Banana" }), _jsx(CommandItem, { value: "cherry", children: "\uD83C\uDF52 Cherry" }), _jsx(CommandItem, { value: "grape", children: "\uD83C\uDF47 Grape" }), _jsx(CommandItem, { value: "orange", children: "\uD83C\uDF4A Orange" }), _jsx(CommandItem, { value: "strawberry", children: "\uD83C\uDF53 Strawberry" }), _jsx(CommandItem, { value: "watermelon", children: "\uD83C\uDF49 Watermelon" })] })] })] })),
40
35
  };
41
36
  export const MultipleGroups = {
42
- render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Files", children: [_jsx(CommandItem, { children: _jsx("span", { children: "Document.pdf" }) }), _jsx(CommandItem, { children: _jsx("span", { children: "Presentation.pptx" }) }), _jsx(CommandItem, { children: _jsx("span", { children: "Spreadsheet.xlsx" }) })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Folders", children: [_jsx(CommandItem, { children: _jsx("span", { children: "Downloads" }) }), _jsx(CommandItem, { children: _jsx("span", { children: "Documents" }) }), _jsx(CommandItem, { children: _jsx("span", { children: "Pictures" }) })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Actions", children: [_jsxs(CommandItem, { children: [_jsx("span", { children: "New File" }), _jsx(CommandShortcut, { children: "\u2318N" })] }), _jsxs(CommandItem, { children: [_jsx("span", { children: "New Folder" }), _jsx(CommandShortcut, { children: "\u21E7\u2318N" })] })] })] })] })),
37
+ render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Files", children: [_jsx(CommandItem, { children: _jsx(Text, { as: "span", children: "Document.pdf" }) }), _jsx(CommandItem, { children: _jsx(Text, { as: "span", children: "Presentation.pptx" }) }), _jsx(CommandItem, { children: _jsx(Text, { as: "span", children: "Spreadsheet.xlsx" }) })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Folders", children: [_jsx(CommandItem, { children: _jsx(Text, { as: "span", children: "Downloads" }) }), _jsx(CommandItem, { children: _jsx(Text, { as: "span", children: "Documents" }) }), _jsx(CommandItem, { children: _jsx(Text, { as: "span", children: "Pictures" }) })] }), _jsx(CommandSeparator, {}), _jsxs(CommandGroup, { heading: "Actions", children: [_jsxs(CommandItem, { children: [_jsx(Text, { as: "span", children: "New File" }), _jsx(CommandShortcut, { children: "\u2318N" })] }), _jsxs(CommandItem, { children: [_jsx(Text, { as: "span", children: "New Folder" }), _jsx(CommandShortcut, { children: "\u21E7\u2318N" })] })] })] })] })),
43
38
  };
44
39
  export const WithOnSelect = {
45
40
  render: () => {
46
41
  const [value, setValue] = useState("");
47
- return (_jsxs("div", { children: [_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Select an option..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Options", children: [_jsx(CommandItem, { value: "option1", onSelect: () => setValue("option1"), children: "Option 1" }), _jsx(CommandItem, { value: "option2", onSelect: () => setValue("option2"), children: "Option 2" }), _jsx(CommandItem, { value: "option3", onSelect: () => setValue("option3"), children: "Option 3" })] })] })] }), value && (_jsxs("p", { className: "mt-4 text-sm text-muted-foreground", children: ["Selected: ", value] }))] }));
42
+ return (_jsxs(Box, { children: [_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Select an option..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No results found." }), _jsxs(CommandGroup, { heading: "Options", children: [_jsx(CommandItem, { value: "option1", onSelect: () => setValue("option1"), children: "Option 1" }), _jsx(CommandItem, { value: "option2", onSelect: () => setValue("option2"), children: "Option 2" }), _jsx(CommandItem, { value: "option3", onSelect: () => setValue("option3"), children: "Option 3" })] })] })] }), value && (_jsxs(Text, { className: "mt-4 text-sm text-muted-foreground", children: ["Selected: ", value] }))] }));
48
43
  },
49
44
  };
50
45
  export const DisabledItems = {
@@ -54,10 +49,10 @@ export const Loading = {
54
49
  render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Searching..." }), _jsx(CommandList, { children: _jsx(CommandEmpty, { children: "Loading..." }) })] })),
55
50
  };
56
51
  export const EmptyState = {
57
- render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search..." }), _jsx(CommandList, { children: _jsx(CommandEmpty, { children: _jsxs("div", { className: "py-6 text-center", children: [_jsx("p", { className: "text-sm text-muted-foreground", children: "No results found." }), _jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: "Try searching for something else." })] }) }) })] })),
52
+ render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search..." }), _jsx(CommandList, { children: _jsx(CommandEmpty, { children: _jsxs(Box, { className: "py-6 text-center", children: [_jsx(Text, { className: "text-sm text-muted-foreground", children: "No results found." }), _jsx(Text, { className: "mt-2 text-xs text-muted-foreground", children: "Try searching for something else." })] }) }) })] })),
58
53
  };
59
54
  export const WithIcons = {
60
- render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search apps..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No apps found." }), _jsxs(CommandGroup, { heading: "Applications", children: [_jsxs(CommandItem, { children: [_jsx(Calendar, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Calendar" }), _jsx(CommandShortcut, { children: "\u23181" })] }), _jsxs(CommandItem, { children: [_jsx(Calculator, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Calculator" }), _jsx(CommandShortcut, { children: "\u23182" })] }), _jsxs(CommandItem, { children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Settings" }), _jsx(CommandShortcut, { children: "\u23183" })] }), _jsxs(CommandItem, { children: [_jsx(User, { className: "mr-2 h-4 w-4" }), _jsx("span", { children: "Profile" }), _jsx(CommandShortcut, { children: "\u23184" })] })] })] })] })),
55
+ render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search apps..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No apps found." }), _jsxs(CommandGroup, { heading: "Applications", children: [_jsxs(CommandItem, { children: [_jsx(Calendar, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Calendar" }), _jsx(CommandShortcut, { children: "\u23181" })] }), _jsxs(CommandItem, { children: [_jsx(Calculator, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Calculator" }), _jsx(CommandShortcut, { children: "\u23182" })] }), _jsxs(CommandItem, { children: [_jsx(Settings, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Settings" }), _jsx(CommandShortcut, { children: "\u23183" })] }), _jsxs(CommandItem, { children: [_jsx(User, { className: "mr-2 h-4 w-4" }), _jsx(Text, { as: "span", children: "Profile" }), _jsx(CommandShortcut, { children: "\u23184" })] })] })] })] })),
61
56
  };
62
57
  export const LongList = {
63
58
  render: () => (_jsxs(Command, { className: "rounded-lg border shadow-md", children: [_jsx(CommandInput, { placeholder: "Search countries..." }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No country found." }), _jsx(CommandGroup, { heading: "Countries", children: [
@@ -1,7 +1,7 @@
1
1
  import { type VariantProps } from "class-variance-authority";
2
2
  import * as React from "react";
3
3
  declare const containerVariants: (props?: ({
4
- size?: "sm" | "md" | "lg" | "xl" | "full" | "2xl" | null | undefined;
4
+ size?: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | null | undefined;
5
5
  centered?: boolean | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  export interface ContainerProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof containerVariants> {
@@ -1 +1 @@
1
- export * from './container';
1
+ export * from "./container";
@@ -1 +1 @@
1
- export * from './container';
1
+ export * from "./container";
@@ -5,16 +5,21 @@
5
5
  "use client";
6
6
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  import { Filter, X } from "lucide-react";
8
- import { useState } from "react";
8
+ import * as React from "react";
9
+ import { useDisclosure } from "@kala-ui/react-hooks";
9
10
  import { Badge } from "../badge";
10
11
  import { Button } from "../button";
11
12
  import { Checkbox } from "../checkbox";
13
+ import { Flex } from "../flex";
14
+ import { Heading } from "../heading";
12
15
  import { Input } from "../input";
13
16
  import { Label } from "../label";
14
17
  import { Popover, PopoverContent, PopoverTrigger } from "../popover";
18
+ import { Stack } from "../stack";
19
+ import { Text } from "../text";
15
20
  export function ColumnHeaderFilter({ column, activeFilters, onFilterChange, onFilterRemove, }) {
16
- const [open, setOpen] = useState(false);
17
- const [textValue, setTextValue] = useState("");
21
+ const [open, { set: setOpen }] = useDisclosure(false);
22
+ const [textValue, setTextValue] = React.useState("");
18
23
  const activeFilter = activeFilters.find((f) => f.key === column.key);
19
24
  const filterValue = activeFilter?.value;
20
25
  // For multi-select, track selected values
@@ -58,10 +63,10 @@ export function ColumnHeaderFilter({ column, activeFilters, onFilterChange, onFi
58
63
  onFilterRemove(column.key);
59
64
  setTextValue("");
60
65
  };
61
- return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0 hover:bg-muted relative", "aria-label": `Filter by ${column.label}`, children: [_jsx(Filter, { className: `h-4 w-4 ${hasActiveFilter ? "text-primary" : "text-muted-foreground"}` }), hasActiveFilter ? (_jsx(Badge, { variant: "default", className: "absolute -top-1 -right-1 h-4 w-4 p-0 flex items-center justify-center text-[10px] bg-primary", children: activeCount || 1 })) : null] }) }), _jsx(PopoverContent, { className: "w-64 p-3", align: "start", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("h4", { className: "font-medium text-sm text-foreground", children: ["Filter by ", column.label] }), hasActiveFilter ? (_jsxs(Button, { variant: "ghost", size: "sm", onClick: handleClear, className: "h-7 px-2 text-xs text-muted-foreground", children: [_jsx(X, { className: "h-3 w-3 mr-1" }), "Clear"] })) : null] }), column.type === "select" && column.options ? (_jsx("div", { className: "space-y-2 max-h-[300px] overflow-y-auto", children: column.options.map((option) => {
66
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0 hover:bg-muted relative", "aria-label": `Filter by ${column.label}`, children: [_jsx(Filter, { className: `h-4 w-4 ${hasActiveFilter ? "text-primary" : "text-muted-foreground"}` }), hasActiveFilter ? (_jsx(Badge, { variant: "default", className: "absolute -top-1 -right-1 h-4 w-4 p-0 flex items-center justify-center text-[10px]", children: _jsx(Text, { size: "xs", weight: "bold", className: "text-primary-foreground", children: column.type === "text" ? "1" : activeCount }) })) : null] }) }), _jsx(PopoverContent, { className: "w-64 p-3", align: "start", children: _jsxs(Stack, { gap: 3, children: [_jsxs(Flex, { align: "center", justify: "between", children: [_jsxs(Heading, { size: "h6", weight: "medium", className: "text-sm", children: ["Filter by ", column.label] }), hasActiveFilter ? (_jsxs(Button, { variant: "ghost", size: "sm", onClick: handleClear, className: "h-7 px-2 text-xs text-muted-foreground", children: [_jsx(X, { className: "h-3 w-3 mr-1" }), "Clear"] })) : null] }), column.type === "select" && column.options ? (_jsx(Stack, { gap: 2, className: "max-h-[300px] overflow-y-auto", children: column.options.map((option) => {
62
67
  const isChecked = selectedValues.includes(option.value);
63
- return (_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(Checkbox, { id: `${String(column.key)}-${option.value}`, checked: isChecked, onCheckedChange: (checked) => handleCheckboxChange(option.value, checked === true) }), _jsx(Label, { htmlFor: `${String(column.key)}-${option.value}`, className: "text-sm font-normal cursor-pointer flex-1 text-foreground", children: option.label })] }, option.value));
64
- }) })) : (_jsxs("div", { className: "space-y-2", children: [_jsx(Input, { type: "text", placeholder: column.placeholder || `Filter by ${column.label}`, value: textValue, onChange: (e) => setTextValue(e.target.value), onKeyDown: (e) => {
68
+ return (_jsxs(Flex, { align: "center", gap: 2, children: [_jsx(Checkbox, { id: `${String(column.key)}-${option.value}`, checked: isChecked, onCheckedChange: (checked) => handleCheckboxChange(option.value, checked === true) }), _jsx(Label, { htmlFor: `${String(column.key)}-${option.value}`, className: "text-sm font-normal cursor-pointer flex-1 text-foreground", children: option.label })] }, option.value));
69
+ }) })) : (_jsxs(Stack, { gap: 2, children: [_jsx(Input, { type: "text", placeholder: column.placeholder || `Filter by ${column.label}`, value: textValue, onChange: (e) => setTextValue(e.target.value), onKeyDown: (e) => {
65
70
  if (e.key === "Enter") {
66
71
  handleTextApply();
67
72
  }
@@ -10,32 +10,22 @@ import { Button } from "../button";
10
10
  import { Checkbox } from "../checkbox";
11
11
  import { FieldLabel } from "../field";
12
12
  import { Input } from "../input";
13
- import { Skeleton } from "../skeleton";
14
13
  import { Select, SelectTrigger, SelectValue } from "../select";
14
+ import { Skeleton } from "../skeleton";
15
15
  import { TableBody, TableCell, TableHead, TableHeader, TableRow, } from "../table";
16
16
  export function DataTableSkeleton({ rows = 5, columns, showSearch = false, showFilters = false, filterCount = 3, showPagination = false, showSelection = false, showBulkActions = false, stickyHeader = true, stickyFooter = false, }) {
17
- return (_jsxs("div", { className: "flex flex-col", children: [showSearch && (_jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-4 shrink-0", children: [_jsx("div", { className: "flex-1 max-w-sm", children: _jsx(Input, { type: "search", placeholder: "Search...", disabled: true, className: "opacity-50" }) }), showBulkActions && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap min-h-[36px]", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "0 selected" }), _jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: "Edit" }), _jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: "Delete" })] }))] })), showFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 mb-4 shrink-0", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "Active filters:" }), Array.from({ length: filterCount }).map((_, i) => (_jsxs(Badge, { variant: "secondary", className: "gap-1.5 pl-2 pr-1 py-1 bg-primary/10 text-primary border-primary/20", children: [_jsx("span", { className: "text-xs font-medium", children: "Filter: Value" }), _jsx(Button, { variant: "ghost", size: "sm", disabled: true, className: "h-4 w-4 p-0 hover:bg-primary/20 rounded-sm", children: _jsx(Skeleton, { className: "h-3 w-3" }) })] }, `filter-${i}`))), _jsx(Button, { variant: "ghost", size: "sm", disabled: true, className: "h-7 px-2 text-xs text-muted-foreground hover:text-foreground", children: "Clear all" })] })), _jsx("div", { className: cn("border relative overflow-hidden theme-card", showPagination ? "rounded-t-lg border-b-0" : "rounded-lg", stickyFooter ? "flex-1 min-h-0" : ""), children: _jsx("div", { className: cn("overflow-auto relative", showPagination ? "rounded-t-lg" : "rounded-lg", stickyFooter
18
- ? "flex-1 min-h-0 max-h-[70vh]"
19
- : "max-h-[600px]"), children: _jsxs("table", { className: "w-full border-separate border-spacing-0 caption-bottom text-sm", children: [_jsx(TableHeader, { className: cn(stickyHeader &&
20
- "sticky top-0 z-1 bg-muted/95 backdrop-blur-sm", "[&_tr]:border-0"), children: _jsxs(TableRow, { className: "border-0", children: [showSelection && (_jsx(TableHead, { className: cn("w-12 rounded-tl-lg", stickyHeader
17
+ return (_jsxs("div", { className: "flex flex-col", children: [showSearch && (_jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-4 shrink-0", children: [_jsx("div", { className: "flex-1 max-w-sm", children: _jsx(Input, { type: "search", placeholder: "Search...", disabled: true, className: "opacity-50" }) }), showBulkActions && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap min-h-[36px]", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "0 selected" }), _jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: "Edit" }), _jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: "Delete" })] }))] })), showFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 mb-4 shrink-0", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "Active filters:" }), Array.from({ length: filterCount }).map((_, i) => (_jsxs(Badge, { variant: "secondary", className: "gap-1.5 pl-2 pr-1 py-1 bg-primary/10 text-primary border-primary/20", children: [_jsx("span", { className: "text-xs font-medium", children: "Filter: Value" }), _jsx(Button, { variant: "ghost", size: "sm", disabled: true, className: "h-4 w-4 p-0 hover:bg-primary/20 rounded-sm", children: _jsx(Skeleton, { className: "h-3 w-3" }) })] }, `filter-${i}`))), _jsx(Button, { variant: "ghost", size: "sm", disabled: true, className: "h-7 px-2 text-xs text-muted-foreground hover:text-foreground", children: "Clear all" })] })), _jsx("div", { className: cn("border relative overflow-hidden theme-card", showPagination ? "rounded-t-lg border-b-0" : "rounded-lg", stickyFooter ? "flex-1 min-h-0" : ""), children: _jsx("div", { className: cn("overflow-auto relative", showPagination ? "rounded-t-lg" : "rounded-lg", stickyFooter ? "flex-1 min-h-0 max-h-[70vh]" : "max-h-[600px]"), children: _jsxs("table", { className: "w-full border-separate border-spacing-0 caption-bottom text-sm", children: [_jsx(TableHeader, { className: cn(stickyHeader && "sticky top-0 z-1 bg-muted/95 backdrop-blur-sm", "[&_tr]:border-0"), children: _jsxs(TableRow, { className: "border-0", children: [showSelection && (_jsx(TableHead, { className: cn("w-12 rounded-tl-lg", stickyHeader
21
18
  ? "border-b border-border-strong/50"
22
19
  : "border-b"), children: _jsx(Checkbox, { disabled: true }) })), columns.map((column, index) => {
23
20
  const isFirst = !showSelection && index === 0;
24
21
  const isLast = index === columns.length - 1;
25
22
  return (_jsx(TableHead, { style: { width: column.width }, className: cn(column.align === "center" && "text-center", column.align === "right" && "text-right", column.hideOnMobile && "hidden md:table-cell", stickyHeader
26
23
  ? "border-b border-border-strong/50"
27
- : "border-b", isFirst && "rounded-tl-lg", isLast && "rounded-tr-lg"), children: _jsx("div", { className: cn("flex items-center gap-1", column.align === "center" &&
28
- "justify-center", column.align === "right" &&
29
- "justify-end"), children: column.enableFiltering ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-4 flex-1" }), _jsx(Skeleton, { className: "h-4 w-4" })] })) : (_jsx(Skeleton, { className: "h-4 w-24" })) }) }, column.id));
24
+ : "border-b", isFirst && "rounded-tl-lg", isLast && "rounded-tr-lg"), children: _jsx("div", { className: cn("flex items-center gap-1", column.align === "center" && "justify-center", column.align === "right" && "justify-end"), children: column.enableFiltering ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-4 flex-1" }), _jsx(Skeleton, { className: "h-4 w-4" })] })) : (_jsx(Skeleton, { className: "h-4 w-24" })) }) }, column.id));
30
25
  })] }) }), _jsx(TableBody, { children: Array.from({ length: rows }).map((_, rowIndex) => {
31
26
  const isLastRow = rowIndex === rows - 1;
32
27
  return (_jsxs(TableRow, { className: cn("border-0"), children: [showSelection && (_jsx(TableCell, { children: _jsx(Checkbox, { disabled: true, "aria-label": `Select row ${rowIndex + 1}` }) })), columns.map((column) => {
33
- return (_jsx(TableCell, { className: cn(column.align ===
34
- "center" &&
35
- "text-center", column.align === "right" &&
36
- "text-right", column.hideOnMobile &&
37
- "hidden md:table-cell", !isLastRow && "border-b"), children: _jsx(Skeleton, { className: "h-4 w-32" }) }, column.id));
28
+ return (_jsx(TableCell, { className: cn(column.align === "center" && "text-center", column.align === "right" && "text-right", column.hideOnMobile && "hidden md:table-cell", !isLastRow && "border-b"), children: _jsx(Skeleton, { className: "h-4 w-32" }) }, column.id));
38
29
  })] }, rowIndex));
39
- }) })] }) }) }), showPagination && (_jsxs("div", { className: cn("flex flex-col sm:flex-row items-center justify-between gap-4 bg-background px-4 py-3 rounded-b-lg theme-card border-x border-b", stickyFooter &&
40
- "sticky bottom-0 z-1 shadow-xl bg-background"), children: [_jsx("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: _jsx(Skeleton, { className: "h-4 w-48" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FieldLabel, { htmlFor: "page-size", className: "text-sm text-muted-foreground mb-0", children: "Rows per page:" }), _jsx(Select, { disabled: true, children: _jsx(SelectTrigger, { className: "w-20 h-9 text-foreground opacity-50", children: _jsx(SelectValue, {}) }) })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: _jsx(Skeleton, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm text-muted-foreground px-2", children: _jsx(Skeleton, { className: "h-4 w-16 inline-block" }) }), _jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: _jsx(Skeleton, { className: "h-4 w-4" }) })] })] })] }))] }));
30
+ }) })] }) }) }), showPagination && (_jsxs("div", { className: cn("flex flex-col sm:flex-row items-center justify-between gap-4 bg-background px-4 py-3 rounded-b-lg theme-card border-x border-b", stickyFooter && "sticky bottom-0 z-1 shadow-xl bg-background"), children: [_jsx("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: _jsx(Skeleton, { className: "h-4 w-48" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FieldLabel, { htmlFor: "page-size", className: "text-sm text-muted-foreground mb-0", children: "Rows per page:" }), _jsx(Select, { disabled: true, children: _jsx(SelectTrigger, { className: "w-20 h-9 text-foreground opacity-50", children: _jsx(SelectValue, {}) }) })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: _jsx(Skeleton, { className: "h-4 w-4" }) }), _jsx("span", { className: "text-sm text-muted-foreground px-2", children: _jsx(Skeleton, { className: "h-4 w-16 inline-block" }) }), _jsx(Button, { variant: "outline", size: "sm", disabled: true, className: "opacity-50", children: _jsx(Skeleton, { className: "h-4 w-4" }) })] })] })] }))] }));
41
31
  }
@@ -17,17 +17,21 @@
17
17
  */
18
18
  "use client";
19
19
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
+ import { useDisclosure } from "@kala-ui/react-hooks";
20
21
  import { ArrowDown, ArrowUp, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Search, X, } from "lucide-react";
21
22
  import { useCallback, useMemo, useRef, useState } from "react";
22
23
  import { cn } from "../../lib/utils";
23
24
  import { Badge } from "../badge";
25
+ import { Box } from "../box";
24
26
  import { Button } from "../button";
25
27
  import { Checkbox } from "../checkbox";
26
28
  import { EmptyState } from "../empty-state";
27
- import { FieldLabel } from "../field";
29
+ import { Flex } from "../flex";
28
30
  import { Input } from "../input";
29
31
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../select";
32
+ import { Stack } from "../stack";
30
33
  import { TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from "../table";
34
+ import { Text } from "../text";
31
35
  import { ColumnHeaderFilter } from "./column-header-filter";
32
36
  import { DataTableSkeleton } from "./data-table-skeleton";
33
37
  import { useTableState } from "./useTableState";
@@ -80,14 +84,14 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
80
84
  const [selectedIds, setSelectedIds] = useState(selection?.selectedIds ?? new Set());
81
85
  // Scroll container ref for scroll-to-top/bottom buttons
82
86
  const scrollContainerRef = useRef(null);
83
- const [showScrollButtons, setShowScrollButtons] = useState(false);
87
+ const [showScrollButtons, { set: setShowScrollButtons }] = useDisclosure(false);
84
88
  // Handle scroll event to show/hide scroll buttons
85
89
  const handleScroll = useCallback(() => {
86
90
  if (scrollContainerRef.current) {
87
91
  const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
88
92
  setShowScrollButtons(scrollHeight > clientHeight && scrollTop > 100);
89
93
  }
90
- }, []);
94
+ }, [setShowScrollButtons]);
91
95
  // Scroll to top/bottom functions
92
96
  const scrollToTop = useCallback(() => {
93
97
  scrollContainerRef.current?.scrollTo({ top: 0, behavior: "smooth" });
@@ -197,13 +201,13 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
197
201
  // Hide search if no data and not searching (unless forceShow is true)
198
202
  if (data.length === 0 && !searchQuery && !forceShow)
199
203
  return null;
200
- return (_jsx("div", { className: "flex-1 max-w-sm", children: _jsx(Input, { type: "search", placeholder: searchConfig.placeholder, value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), prefixIcon: _jsx(Search, { className: "h-4 w-4" }), suffixIcon: searchQuery ? (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setSearchQuery(""), className: "p-1 text-muted-foreground hover:text-foreground h-auto", "aria-label": "Clear search", children: _jsx(X, { className: "h-4 w-4" }) })) : null, "aria-label": searchConfig.ariaLabel }) }));
204
+ return (_jsx(Box, { className: "flex-1 max-w-sm", children: _jsx(Input, { type: "search", placeholder: searchConfig.placeholder, value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), prefixIcon: _jsx(Search, { className: "h-4 w-4" }), suffixIcon: searchQuery ? (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setSearchQuery(""), className: "p-1 text-muted-foreground hover:text-foreground h-auto", "aria-label": "Clear search", children: _jsx(X, { className: "h-4 w-4" }) })) : null, "aria-label": searchConfig.ariaLabel }) }));
201
205
  };
202
206
  // Render loading state
203
207
  if (isLoading) {
204
208
  // Use custom skeleton if provided
205
209
  if (skeleton) {
206
- return _jsx("div", { className: cn("space-y-4", className), children: skeleton });
210
+ return _jsx(Stack, { gap: 4, className: className, children: skeleton });
207
211
  }
208
212
  // Use skeletonConfig if provided, otherwise fall back to legacy loadingConfig
209
213
  const showSearch = !!searchConfig;
@@ -212,7 +216,7 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
212
216
  const showSelection = !!selection?.enabled;
213
217
  const showBulkActions = !!bulkActions;
214
218
  const skeletonRows = skeletonConfig?.rows ?? loadingConfig?.rows ?? 5;
215
- return (_jsx("div", { className: cn("space-y-4", className), children: _jsx(DataTableSkeleton, { rows: skeletonRows, columns: columns, showSearch: showSearch, showFilters: showFilters, showPagination: showPagination, showSelection: showSelection, showBulkActions: showBulkActions, stickyHeader: stickyHeader, stickyFooter: stickyFooter }) }));
219
+ return (_jsx(Stack, { gap: 4, className: className, children: _jsx(DataTableSkeleton, { rows: skeletonRows, columns: columns, showSearch: showSearch, showFilters: showFilters, showPagination: showPagination, showSelection: showSelection, showBulkActions: showBulkActions, stickyHeader: stickyHeader, stickyFooter: stickyFooter }) }));
216
220
  }
217
221
  // Render empty state
218
222
  if (displayData.length === 0) {
@@ -223,16 +227,16 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
223
227
  : "There is no data to display at the moment.",
224
228
  };
225
229
  const emptyConfig = { ...defaultEmptyState, ...emptyState };
226
- return (_jsxs("div", { className: cn("space-y-4", className), children: [renderSearchInput(), _jsx(EmptyState, { title: emptyConfig.title, description: emptyConfig.description, ...(emptyConfig.icon && { icon: emptyConfig.icon }), ...(emptyConfig.action && { action: emptyConfig.action }) })] }));
230
+ return (_jsxs(Stack, { gap: 4, className: className, children: [renderSearchInput(), _jsx(EmptyState, { title: emptyConfig.title, description: emptyConfig.description, ...(emptyConfig.icon && { icon: emptyConfig.icon }), ...(emptyConfig.action && { action: emptyConfig.action }) })] }));
227
231
  }
228
- return (_jsxs("section", { className: cn("flex flex-col", stickyFooter ? "h-full min-h-0" : "", className), "aria-label": ariaLabel, children: [(searchConfig || bulkActions) && (_jsxs("div", { className: cn("flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-4", stickyFooter && "shrink-0"), children: [renderSearchInput(), bulkActions && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap min-h-[36px]", children: [_jsxs("span", { className: "text-sm text-muted-foreground", children: [selectedIds.size, " selected"] }), bulkActions.map((action) => (_jsxs(Button, { variant: action.variant ?? "outline", size: "sm", onClick: () => action.onClick(selectedRows), disabled: selectedIds.size === 0 || action.disabled, className: cn(selectedIds.size === 0 && "opacity-50 cursor-not-allowed"), children: [action.icon, action.label] }, action.id)))] }))] })), filterableColumns && filterConfigs.length > 0 && (_jsxs("div", { className: cn("flex flex-wrap items-center gap-2 mb-4", stickyFooter && "shrink-0"), children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "Active filters:" }), filterConfigs.map((filter) => {
232
+ return (_jsxs(Stack, { className: cn(stickyFooter ? "h-full min-h-0" : "", className), "aria-label": ariaLabel, role: ariaLabel ? "region" : undefined, children: [(searchConfig || bulkActions) && (_jsxs(Flex, { align: "center", justify: "between", gap: 4, className: cn("mb-4 flex-wrap", stickyFooter && "shrink-0"), children: [renderSearchInput(), bulkActions && (_jsxs(Flex, { align: "center", gap: 2, className: "flex-wrap min-h-[36px]", children: [_jsxs(Text, { size: "sm", className: "text-muted-foreground", children: [selectedIds.size, " selected"] }), bulkActions.map((action) => (_jsxs(Button, { variant: action.variant ?? "outline", size: "sm", onClick: () => action.onClick(selectedRows), disabled: selectedIds.size === 0 || action.disabled, className: cn(selectedIds.size === 0 && "opacity-50 cursor-not-allowed"), children: [action.icon, action.label] }, action.id)))] }))] })), filterableColumns && filterConfigs.length > 0 && (_jsxs(Flex, { align: "center", gap: 2, className: cn("mb-4 flex-wrap", stickyFooter && "shrink-0"), children: [_jsx(Text, { size: "sm", className: "text-muted-foreground", children: "Active filters:" }), filterConfigs.map((filter) => {
229
233
  const column = filterableColumns.find((fc) => fc.key === filter.key);
230
234
  if (!column)
231
235
  return null;
232
236
  const filterValueArray = Array.isArray(filter.value)
233
237
  ? filter.value
234
238
  : [filter.value];
235
- return filterValueArray.map((value, idx) => (_jsxs(Badge, { variant: "secondary", className: "gap-1.5 pl-2 pr-1 py-1 bg-primary/10 text-primary border-primary/20", children: [_jsxs("span", { className: "text-xs font-medium", children: [column.label, ": ", String(value)] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => {
239
+ return filterValueArray.map((value, idx) => (_jsxs(Badge, { variant: "secondary", className: "gap-1.5 pl-2 pr-1 py-1 bg-primary/10 text-primary border-primary/20", children: [_jsxs(Text, { size: "xs", weight: "medium", children: [column.label, ": ", String(value)] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => {
236
240
  if (filterValueArray.length === 1) {
237
241
  removeFilter(filter.key);
238
242
  }
@@ -245,7 +249,7 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
245
249
  });
246
250
  }
247
251
  }, className: "h-4 w-4 p-0 hover:bg-primary/20 rounded-sm", "aria-label": `Remove ${column.label} filter: ${String(value)}`, children: _jsx(X, { className: "h-3 w-3" }) })] }, `${String(filter.key)}-${value}-${idx}`)));
248
- }), _jsx(Button, { variant: "ghost", size: "sm", onClick: clearFilters, className: "h-7 px-2 text-xs text-muted-foreground hover:text-foreground", children: "Clear all" })] })), _jsxs("div", { className: cn("border relative overflow-hidden theme-card", stickyFooter && paginationConfig ? "flex-1 min-h-0" : "", bordered && "border-2", paginationConfig ? "rounded-t-lg border-b-0" : "rounded-lg"), children: [_jsx("div", { ref: scrollContainerRef, onScroll: handleScroll, className: cn("overflow-auto relative", paginationConfig ? "rounded-t-lg" : "rounded-lg", stickyFooter ? "flex-1 min-h-0 max-h-[70vh]" : "max-h-[600px]"), children: _jsxs("table", { className: "w-full border-separate border-spacing-0 caption-bottom text-sm", children: [caption && _jsx("caption", { className: "sr-only", children: caption }), _jsx(TableHeader, { className: cn(stickyHeader && "sticky top-0 z-1 bg-muted/95 backdrop-blur-sm", "[&_tr]:border-0"), children: _jsxs(TableRow, { className: "border-0", children: [selection?.enabled && (_jsx(TableHead, { className: cn("w-12 rounded-tl-lg", stickyHeader
252
+ }), _jsx(Button, { variant: "ghost", size: "sm", onClick: clearFilters, className: "h-7 px-2 text-xs text-muted-foreground hover:text-foreground", children: "Clear all" })] })), _jsxs(Box, { className: cn("border relative overflow-hidden theme-card", stickyFooter && paginationConfig ? "flex-1 min-h-0" : "", bordered && "border-2", paginationConfig ? "rounded-t-lg border-b-0" : "rounded-lg"), children: [_jsx(Box, { ref: scrollContainerRef, onScroll: handleScroll, className: cn("overflow-auto relative", paginationConfig ? "rounded-t-lg" : "rounded-lg", stickyFooter ? "flex-1 min-h-0 max-h-[70vh]" : "max-h-[600px]"), children: _jsxs("table", { className: "w-full border-separate border-spacing-0 caption-bottom text-sm", children: [caption && _jsx("caption", { className: "sr-only", children: caption }), _jsx(TableHeader, { className: cn(stickyHeader && "sticky top-0 z-1 bg-muted/95 backdrop-blur-sm", "[&_tr]:border-0"), children: _jsxs(TableRow, { className: "border-0", children: [selection?.enabled && (_jsx(TableHead, { className: cn("w-12 rounded-tl-lg", stickyHeader
249
253
  ? "border-b border-border-strong/50"
250
254
  : "border-b"), children: _jsx(Checkbox, { checked: isAllSelected
251
255
  ? true
@@ -266,9 +270,9 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
266
270
  ? sortDirection === "asc"
267
271
  ? "ascending"
268
272
  : "descending"
269
- : "none", children: _jsxs("div", { className: cn("flex items-center gap-1", column.align === "center" && "justify-center", column.align === "right" && "justify-end"), children: [canSort && column.accessorKey ? (_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => toggleSort(column.accessorKey), className: "-ml-3 h-8 data-[state=open]:bg-accent hover:bg-accent font-semibold text-foreground hover:text-accent-foreground", "aria-label": column.ariaLabel
273
+ : "none", children: _jsxs(Flex, { align: "center", gap: 1, className: cn(column.align === "center" && "justify-center", column.align === "right" && "justify-end"), children: [canSort && column.accessorKey ? (_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => toggleSort(column.accessorKey), className: "-ml-3 h-8 data-[state=open]:bg-accent hover:bg-accent font-semibold text-foreground hover:text-accent-foreground", "aria-label": column.ariaLabel
270
274
  ? `Sort by ${column.ariaLabel}`
271
- : `Sort by ${column.header}`, children: [column.header, isSorted ? (sortDirection === "asc" ? (_jsx(ChevronUp, { className: "ml-2 h-4 w-4", "aria-hidden": "true" })) : (_jsx(ChevronDown, { className: "ml-2 h-4 w-4", "aria-hidden": "true" }))) : (_jsx(ChevronDown, { className: "ml-2 h-4 w-4 opacity-0 group-hover:opacity-40", "aria-hidden": "true" }))] })) : (_jsx("span", { className: "font-semibold text-muted-foreground", children: column.header })), filterColumn && (_jsx(ColumnHeaderFilter, { column: filterColumn, activeFilters: filterConfigs, onFilterChange: setFilter, onFilterRemove: removeFilter }))] }) }, column.id));
275
+ : `Sort by ${column.header}`, children: [column.header, isSorted ? (sortDirection === "asc" ? (_jsx(ChevronUp, { className: "ml-2 h-4 w-4", "aria-hidden": "true" })) : (_jsx(ChevronDown, { className: "ml-2 h-4 w-4", "aria-hidden": "true" }))) : (_jsx(ChevronDown, { className: "ml-2 h-4 w-4 opacity-0 group-hover:opacity-40", "aria-hidden": "true" }))] })) : (_jsx(Text, { weight: "semibold", className: "text-muted-foreground", children: column.header })), filterColumn && (_jsx(ColumnHeaderFilter, { column: filterColumn, activeFilters: filterConfigs, onFilterChange: setFilter, onFilterRemove: removeFilter }))] }) }, column.id));
272
276
  })] }) }), _jsx(TableBody, { children: displayData.map((row, rowIndex) => {
273
277
  const isSelectable = !selection?.isRowSelectable || selection.isRowSelectable(row);
274
278
  const rowId = selection?.getRowId(row);
@@ -300,11 +304,10 @@ export function DataTable({ data, columns, searchable, pagination, defaultSort,
300
304
  ? true
301
305
  : isSomeSelected
302
306
  ? "indeterminate"
303
- : false, onCheckedChange: handleSelectAll, "aria-label": "Select all rows (bottom)" }) })), columns.map((column) => (_jsx(TableHead, { className: cn(column.className, column.align === "center" && "text-center", column.align === "right" && "text-right", stickyFooter && ""), children: _jsx("div", { className: cn("flex items-center gap-2", column.align === "center" && "justify-center", column.align === "right" && "justify-end"), children: column.enableSorting !== false ? (_jsxs(Button, { variant: "ghost", size: "sm", className: "h-auto p-0 -ml-2 justify-start font-medium hover:bg-transparent", onClick: () => toggleSort(column.accessorKey ||
307
+ : false, onCheckedChange: handleSelectAll, "aria-label": "Select all rows (bottom)" }) })), columns.map((column) => (_jsx(TableHead, { className: cn(column.className, column.align === "center" && "text-center", column.align === "right" && "text-right", stickyFooter && ""), children: _jsx(Flex, { align: "center", gap: 2, className: cn(column.align === "center" && "justify-center", column.align === "right" && "justify-end"), children: column.enableSorting !== false ? (_jsxs(Button, { variant: "ghost", size: "sm", className: "h-auto p-0 -ml-2 justify-start font-medium hover:bg-transparent", onClick: () => toggleSort(column.accessorKey ||
304
308
  column.id), "aria-label": `Sort by ${column.header}`, children: [column.header, sortConfig?.key ===
305
309
  (column.accessorKey || column.id) &&
306
- (sortConfig.direction === "asc" ? (_jsx(ArrowUp, { className: "ml-2 h-4 w-4 text-muted-foreground", "aria-hidden": "true" })) : (_jsx(ArrowDown, { className: "ml-2 h-4 w-4 text-muted-foreground", "aria-hidden": "true" })))] })) : (_jsx("span", { className: "font-medium", children: column.header })) }) }, column.id)))] }) })), footer && (_jsx(TableFooter, { className: cn("border-t", !!paginationConfig && "border-b"), children: _jsx(TableRow, { className: "border-0", children: _jsx(TableCell, { colSpan: columns.length + (selection?.enabled ? 1 : 0), className: "p-4", children: footer }) }) }))] }) }), showScrollButtons && (_jsxs("div", { className: "absolute right-4 bottom-4 flex flex-col gap-2 z-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: scrollToTop, className: "h-8 w-8 p-0 rounded-full shadow-lg bg-background theme-card", "aria-label": "Scroll to top", children: _jsx(ArrowUp, { className: "h-4 w-4", "aria-hidden": "true" }) }), _jsx(Button, { variant: "outline", size: "sm", onClick: scrollToBottom, className: "h-8 w-8 p-0 rounded-full shadow-lg bg-background theme-card", "aria-label": "Scroll to bottom", children: _jsx(ArrowDown, { className: "h-4 w-4", "aria-hidden": "true" }) })] }))] }), paginationConfig && (_jsxs("div", { className: cn("flex flex-col sm:flex-row items-center justify-between gap-4 bg-background px-4 py-3 rounded-b-lg theme-card", bordered ? "border-x-2 border-b-2" : "border-x border-b", stickyFooter &&
307
- "sticky bottom-0 z-1 shadow-xl bg-background"), children: [_jsx("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: _jsxs("span", { children: ["Showing ", (currentPage - 1) * currentPageSize + 1, " to", " ", Math.min(currentPage * currentPageSize, paginationConfig.total), " ", "of ", paginationConfig.total, " results"] }) }), _jsxs("div", { className: "flex items-center gap-2", children: [paginationConfig.pageSizeOptions && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FieldLabel, { htmlFor: "page-size", className: "text-sm text-muted-foreground mb-0", children: "Rows per page:" }), _jsxs(Select, { value: String(currentPageSize), onValueChange: (value) => setPageSize(Number(value)), children: [_jsx(SelectTrigger, { className: "w-20 h-9 text-foreground", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: paginationConfig.pageSizeOptions.map((size) => (_jsx(SelectItem, { value: String(size), children: size }, size))) })] })] })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: previousPage, disabled: !hasPreviousPage, "aria-label": "Go to previous page", children: _jsx(ChevronLeft, { className: "h-4 w-4", "aria-hidden": "true" }) }), _jsxs("span", { className: "text-sm text-muted-foreground px-2", children: ["Page ", currentPage, " of ", totalPages] }), _jsx(Button, { variant: "outline", size: "sm", onClick: nextPage, disabled: !hasNextPage, "aria-label": "Go to next page", children: _jsx(ChevronRight, { className: "h-4 w-4", "aria-hidden": "true" }) })] })] })] }))] }));
310
+ (sortConfig.direction === "asc" ? (_jsx(ArrowUp, { className: "ml-2 h-4 w-4 text-muted-foreground", "aria-hidden": "true" })) : (_jsx(ArrowDown, { className: "ml-2 h-4 w-4 text-muted-foreground", "aria-hidden": "true" })))] })) : (_jsx(Text, { weight: "medium", children: column.header })) }) }, column.id)))] }) })), footer && (_jsx(TableFooter, { className: cn("border-t", !!paginationConfig && "border-b"), children: _jsx(TableRow, { className: "border-0", children: _jsx(TableCell, { colSpan: columns.length + (selection?.enabled ? 1 : 0), className: "p-4", children: footer }) }) }))] }) }), showScrollButtons && (_jsxs(Flex, { gap: 2, className: "absolute bottom-4 right-4 z-10", children: [_jsx(Button, { variant: "secondary", size: "icon", onClick: scrollToTop, className: "rounded-full shadow-lg h-9 w-9 bg-background/80 backdrop-blur-sm border-border-strong/20", "aria-label": "Scroll to top", children: _jsx(ArrowUp, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "secondary", size: "icon", onClick: scrollToBottom, className: "rounded-full shadow-lg h-9 w-9 bg-background/80 backdrop-blur-sm border-border-strong/20", "aria-label": "Scroll to bottom", children: _jsx(ArrowDown, { className: "h-4 w-4" }) })] }))] }), paginationConfig && (_jsxs(Flex, { align: "center", justify: "between", className: cn("px-4 py-3 border rounded-b-lg bg-muted/30", stickyFooter && "shrink-0"), children: [_jsxs(Flex, { align: "center", gap: 4, children: [_jsxs(Text, { size: "sm", className: "text-muted-foreground whitespace-nowrap", children: ["Showing", " ", _jsx(Text, { as: "span", weight: "medium", className: "text-foreground inline", children: Math.min((paginationConfig.page - 1) * paginationConfig.pageSize + 1, paginationConfig.total) }), " ", "to", " ", _jsx(Text, { as: "span", weight: "medium", className: "text-foreground inline", children: Math.min(paginationConfig.page * paginationConfig.pageSize, paginationConfig.total) }), " ", "of", " ", _jsx(Text, { as: "span", weight: "medium", className: "text-foreground inline", children: paginationConfig.total }), " ", "results"] }), paginationConfig.pageSizeOptions && (_jsxs(Flex, { align: "center", gap: 2, children: [_jsx(Text, { size: "sm", className: "text-muted-foreground whitespace-nowrap", children: "Rows per page" }), _jsxs(Select, { value: String(paginationConfig.pageSize), onValueChange: (value) => setPageSize(Number(value)), children: [_jsx(SelectTrigger, { className: "h-8 w-[70px]", children: _jsx(SelectValue, { placeholder: String(paginationConfig.pageSize) }) }), _jsx(SelectContent, { side: "top", children: paginationConfig.pageSizeOptions.map((option) => (_jsx(SelectItem, { value: String(option), children: option }, option))) })] })] }))] }), _jsxs(Flex, { align: "center", gap: 2, children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: previousPage, disabled: !hasPreviousPage, className: "h-8 w-8 p-0", children: [_jsx(ChevronLeft, { className: "h-4 w-4" }), _jsx(Box, { as: "span", className: "sr-only", children: "Previous page" })] }), _jsx(Flex, { align: "center", gap: 1, children: _jsxs(Text, { size: "sm", weight: "medium", children: ["Page ", paginationConfig.page, " of ", totalPages] }) }), _jsxs(Button, { variant: "outline", size: "sm", onClick: nextPage, disabled: !hasNextPage, className: "h-8 w-8 p-0", children: [_jsx(ChevronRight, { className: "h-4 w-4" }), _jsx(Box, { as: "span", className: "sr-only", children: "Next page" })] })] })] }))] }));
308
311
  }
309
312
  // Export skeleton for direct use
310
313
  export { DataTableSkeleton } from "./data-table-skeleton";
@@ -1,8 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * DataTable Storybook Stories
4
- * Essential examples demonstrating DataTable features
5
- */
6
2
  import React from "react";
7
3
  import { Badge } from "../badge";
8
4
  import { Button } from "../button";
@@ -705,7 +701,9 @@ export const ServerSideDataFetching = {
705
701
  React.useEffect(() => {
706
702
  fetchData();
707
703
  }, [fetchData]);
708
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "p-4 bg-blue-50 dark:bg-blue-950 rounded-lg border border-blue-200 dark:border-blue-800", children: [_jsx("h3", { className: "font-semibold text-blue-900 dark:text-blue-100 mb-2", children: "Server-Side Mode" }), _jsx("p", { className: "text-sm text-blue-700 dark:text-blue-300 mb-2", children: "The table calls your callbacks when pagination, sorting, filtering, or search changes. You can then fetch fresh data from your API." }), _jsxs("div", { className: "text-xs text-blue-600 dark:text-blue-400 space-y-1", children: [_jsxs("div", { children: ["Current Page: ", currentPage] }), _jsxs("div", { children: ["Page Size: ", pageSize] }), _jsxs("div", { children: ["Total Records: ", totalRecords] }), _jsxs("div", { children: ["Sort: ", sortConfig ? `${String(sortConfig.key)} (${sortConfig.direction})` : "None"] }), _jsxs("div", { children: ["Search: ", searchQuery || "None"] })] })] }), _jsx(DataTable, { data: users, columns: userColumns, isLoading: isLoading, pagination: {
704
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "p-4 bg-blue-50 dark:bg-blue-950 rounded-lg border border-blue-200 dark:border-blue-800", children: [_jsx("h3", { className: "font-semibold text-blue-900 dark:text-blue-100 mb-2", children: "Server-Side Mode" }), _jsx("p", { className: "text-sm text-blue-700 dark:text-blue-300 mb-2", children: "The table calls your callbacks when pagination, sorting, filtering, or search changes. You can then fetch fresh data from your API." }), _jsxs("div", { className: "text-xs text-blue-600 dark:text-blue-400 space-y-1", children: [_jsxs("div", { children: ["Current Page: ", currentPage] }), _jsxs("div", { children: ["Page Size: ", pageSize] }), _jsxs("div", { children: ["Total Records: ", totalRecords] }), _jsxs("div", { children: ["Sort:", " ", sortConfig
705
+ ? `${String(sortConfig.key)} (${sortConfig.direction})`
706
+ : "None"] }), _jsxs("div", { children: ["Search: ", searchQuery || "None"] })] })] }), _jsx(DataTable, { data: users, columns: userColumns, isLoading: isLoading, pagination: {
709
707
  page: currentPage,
710
708
  pageSize: pageSize,
711
709
  total: totalRecords,
@@ -1,5 +1,5 @@
1
1
  import type { DateRange } from "react-day-picker";
2
- import { Calendar } from "../calendar/calendar";
2
+ import { Calendar } from "../calendar";
3
3
  export interface DatePickerProps extends Omit<React.ComponentProps<typeof Calendar>, "mode" | "selected" | "onSelect" | "className" | "required" | "disabled"> {
4
4
  date?: Date;
5
5
  onDateChange?: (date: Date | undefined) => void;
@@ -3,10 +3,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { format } from "date-fns";
4
4
  import { CalendarIcon } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button/button";
7
- import { Calendar } from "../calendar/calendar";
6
+ import { Button } from "../button";
7
+ import { Calendar } from "../calendar";
8
8
  import { Popover, PopoverContent, PopoverTrigger } from "../popover";
9
- import { Skeleton } from "../skeleton/skeleton";
9
+ import { Skeleton } from "../skeleton";
10
10
  export function DatePicker({ date, onDateChange, placeholder = "Pick a date", disabled, buttonDisabled = false, className, buttonClassName, formatStr = "PPP", isLoading = false, ...props }) {
11
11
  if (isLoading) {
12
12
  return (_jsx(Skeleton, { className: cn("h-10 w-[280px] rounded-md", buttonClassName) }));
@@ -1,5 +1,5 @@
1
1
  import type { DateRange } from "react-day-picker";
2
- import type { Calendar } from "../calendar/calendar";
2
+ import type { Calendar } from "../calendar";
3
3
  export interface DatePickerProps extends Omit<React.ComponentProps<typeof Calendar>, "mode" | "selected" | "onSelect" | "className" | "required" | "disabled"> {
4
4
  date?: Date;
5
5
  onDateChange?: (date: Date | undefined) => void;
@@ -6,7 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  * Supports header, body, and footer sections.
7
7
  */
8
8
  import { cn } from "../../lib/utils";
9
- import { Skeleton } from "../skeleton/skeleton";
9
+ import { Skeleton } from "../skeleton";
10
10
  /**
11
11
  * Dialog skeleton component
12
12
  *
@@ -3,6 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as DialogPrimitive from "@radix-ui/react-dialog";
4
4
  import { X } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
+ import { Box } from "../box";
7
+ import { Text } from "../text";
6
8
  function Dialog({ ...props }) {
7
9
  return _jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
8
10
  }
@@ -25,13 +27,13 @@ function DialogContent({ className, children, showCloseButton = true, size = "de
25
27
  lg: "w-[90vw] max-w-2xl",
26
28
  xl: "w-[90vw] max-w-4xl",
27
29
  };
28
- return (_jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { "data-slot": "dialog-content", className: cn("bg-card text-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-30 flex flex-col max-h-[90vh] translate-x-[-50%] translate-y-[-50%] rounded-lg border duration-200 theme-card", sizeClasses[size], className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", className: cn("absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 disabled:pointer-events-none p-1 hover:bg-accent", "focus-ring"), children: [_jsx(X, { className: "size-5", "aria-hidden": "true" }), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
30
+ return (_jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { "data-slot": "dialog-content", className: cn("bg-card text-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-30 flex flex-col max-h-[90vh] translate-x-[-50%] translate-y-[-50%] rounded-lg border duration-200 theme-card", sizeClasses[size], className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", className: cn("absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 disabled:pointer-events-none p-1 hover:bg-accent", "focus-ring"), children: [_jsx(X, { className: "size-5", "aria-hidden": "true" }), _jsx(Text, { as: "span", className: "sr-only", children: "Close" })] }))] })] }));
29
31
  }
30
32
  function DialogHeader({ className, ...props }) {
31
- return (_jsx("div", { "data-slot": "dialog-header", className: cn("flex flex-col gap-1.5 px-6 py-4 border-b", className), ...props }));
33
+ return (_jsx(Box, { "data-slot": "dialog-header", className: cn("flex flex-col gap-1.5 px-6 py-4 border-b", className), ...props }));
32
34
  }
33
35
  function DialogFooter({ className, ...props }) {
34
- return (_jsx("div", { "data-slot": "dialog-footer", className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end px-6 py-4 border-t bg-muted/50 rounded-b-lg", className), ...props }));
36
+ return (_jsx(Box, { "data-slot": "dialog-footer", className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end px-6 py-4 border-t bg-muted/50 rounded-b-lg", className), ...props }));
35
37
  }
36
38
  function DialogTitle({ className, translationKey, ...props }) {
37
39
  return (_jsx(DialogPrimitive.Title, { "data-slot": "dialog-title", className: cn("text-lg font-semibold leading-none tracking-tight text-foreground", className), ...props }));
@@ -40,6 +42,6 @@ function DialogDescription({ className, descriptionKey, ...props }) {
40
42
  return (_jsx(DialogPrimitive.Description, { "data-slot": "dialog-description", className: cn("text-sm leading-relaxed text-muted-foreground", className), ...props }));
41
43
  }
42
44
  function DialogBody({ className, ...props }) {
43
- return (_jsx("div", { "data-slot": "dialog-body", className: cn("flex-1 overflow-y-auto px-6 py-4 min-h-0", className), ...props }));
45
+ return (_jsx(Box, { "data-slot": "dialog-body", className: cn("flex-1 overflow-y-auto px-6 py-4 min-h-0", className), ...props }));
44
46
  }
45
47
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogBody, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "../button";
3
3
  import { Input } from "../input";
4
4
  import { Label } from "../label";
5
- import { Skeleton } from "../skeleton/skeleton";
5
+ import { Skeleton } from "../skeleton";
6
6
  import { Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "./dialog";
7
7
  const meta = {
8
8
  title: "Overlay/Dialog",
@@ -30,7 +30,7 @@ export const ScrollingContent = {
30
30
  render: () => (_jsxs(Dialog, { children: [_jsx(DialogTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Long Content" }) }), _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Terms of Service" }), _jsx(DialogDescription, { children: "Please read our terms of service carefully." })] }), _jsx(DialogBody, { children: Array.from({ length: 20 }).map(() => (_jsx("p", { className: "mb-4", children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris." }, crypto.randomUUID()))) }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", children: "Decline" }), _jsx(Button, { children: "Accept" })] })] })] })),
31
31
  };
32
32
  export const LoadingSkeleton = {
33
- render: () => (_jsx(Skeleton, { className: "h-10 w-32 rounded-md" })),
33
+ render: () => _jsx(Skeleton, { className: "h-10 w-32 rounded-md" }),
34
34
  parameters: {
35
35
  docs: {
36
36
  description: {
@@ -2,10 +2,9 @@
2
2
  * DnD Component - Drag and Drop primitives for @dnd-kit
3
3
  * Provides consistent wrappers with animations, sortable support, and drag overlays
4
4
  */
5
- import type { DragEndEvent, DraggableAttributes, DragOverEvent, DragStartEvent, UniqueIdentifier, DraggableSyntheticListeners, DndContextProps as DndKitContextProps, Active, Over, Collision, CollisionDetection, PointerActivationConstraint } from "@dnd-kit/core";
6
- import { useDraggable, useDroppable, KeyboardSensor, PointerSensor, TouchSensor, useSensor, useSensors } from "@dnd-kit/core";
7
- import { useSortable, sortableKeyboardCoordinates, type SortingStrategy } from "@dnd-kit/sortable";
8
- import type { Modifier } from "@dnd-kit/core";
5
+ import type { Active, Collision, CollisionDetection, DndContextProps as DndKitContextProps, DragEndEvent, DraggableAttributes, DraggableSyntheticListeners, DragOverEvent, DragStartEvent, Modifier, Over, PointerActivationConstraint, UniqueIdentifier } from "@dnd-kit/core";
6
+ import { KeyboardSensor, PointerSensor, TouchSensor, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
7
+ import { type SortingStrategy, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
9
8
  import type { Transform } from "@dnd-kit/utilities";
10
9
  import * as React from "react";
11
10
  type SyntheticListenerMap = DraggableSyntheticListeners;
@@ -37,7 +36,7 @@ export interface UseDragDropSensorsOptions {
37
36
  keyboardCoordinateGetter?: typeof sortableKeyboardCoordinates;
38
37
  }
39
38
  declare function createDragDropSensors(options?: UseDragDropSensorsOptions): import("@dnd-kit/core").SensorDescriptor<import("@dnd-kit/core").SensorOptions>[];
40
- export interface DragDropContextProps extends Omit<DndKitContextProps, 'sensors'> {
39
+ export interface DragDropContextProps extends Omit<DndKitContextProps, "sensors"> {
41
40
  children: React.ReactNode;
42
41
  sensors?: ReturnType<typeof createDragDropSensors>;
43
42
  useSensors?: UseDragDropSensorsOptions;
@@ -4,9 +4,9 @@
4
4
  */
5
5
  "use client";
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
- import { DndContext as DndKitContext, useDraggable, useDroppable, DragOverlay, closestCenter, closestCorners, rectIntersection, pointerWithin, KeyboardSensor, PointerSensor, TouchSensor, useSensor, useSensors, } from "@dnd-kit/core";
8
- import { SortableContext as SortableContextKit, useSortable, sortableKeyboardCoordinates, verticalListSortingStrategy, horizontalListSortingStrategy, rectSortingStrategy, rectSwappingStrategy, } from "@dnd-kit/sortable";
9
- import { restrictToHorizontalAxis, restrictToVerticalAxis, restrictToWindowEdges, restrictToParentElement, restrictToFirstScrollableAncestor, } from "@dnd-kit/modifiers";
7
+ import { closestCenter, closestCorners, DndContext as DndKitContext, DragOverlay, KeyboardSensor, PointerSensor, pointerWithin, rectIntersection, TouchSensor, useDraggable, useDroppable, useSensor, useSensors, } from "@dnd-kit/core";
8
+ import { restrictToFirstScrollableAncestor, restrictToHorizontalAxis, restrictToParentElement, restrictToVerticalAxis, restrictToWindowEdges, } from "@dnd-kit/modifiers";
9
+ import { horizontalListSortingStrategy, rectSortingStrategy, rectSwappingStrategy, SortableContext as SortableContextKit, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable";
10
10
  import { CSS } from "@dnd-kit/utilities";
11
11
  import * as React from "react";
12
12
  import { cn } from "../../lib/utils";
@@ -39,7 +39,7 @@ export const sortingStrategies = {
39
39
  rectSwapping: rectSwappingStrategy,
40
40
  };
41
41
  function createDragDropSensors(options = {}) {
42
- const { activationConstraint, keyboardCoordinateGetter = sortableKeyboardCoordinates } = options;
42
+ const { activationConstraint, keyboardCoordinateGetter = sortableKeyboardCoordinates, } = options;
43
43
  const sensors = useSensors(useSensor(PointerSensor, {
44
44
  activationConstraint,
45
45
  }), useSensor(TouchSensor, {
@@ -99,7 +99,7 @@ const Draggable = React.forwardRef(({ children, className, id, disabled = false,
99
99
  });
100
100
  Draggable.displayName = "Draggable";
101
101
  const SortableContext = React.forwardRef(({ children, items, strategy = verticalListSortingStrategy }, _ref) => {
102
- const itemIds = React.useMemo(() => items.map((item) => (typeof item === "object" && "id" in item ? item.id : item)), [items]);
102
+ const itemIds = React.useMemo(() => items.map((item) => typeof item === "object" && "id" in item ? item.id : item), [items]);
103
103
  return (_jsx(SortableContextKit, { items: itemIds, strategy: strategy, children: children }));
104
104
  });
105
105
  SortableContext.displayName = "SortableContext";