@getgreenline/blaze-ui 1.0.2 → 1.0.3-3.0-beta

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 (240) hide show
  1. package/dist/components/accordion.d.ts +8 -0
  2. package/dist/components/accordion.d.ts.map +1 -0
  3. package/dist/components/accordion.js +19 -0
  4. package/dist/components/alert-dialog.d.ts +18 -0
  5. package/dist/components/alert-dialog.d.ts.map +1 -0
  6. package/dist/components/alert-dialog.js +41 -0
  7. package/dist/components/alert.d.ts +10 -0
  8. package/dist/components/alert.d.ts.map +1 -0
  9. package/dist/components/alert.js +26 -0
  10. package/dist/components/aspect-ratio.d.ts +4 -0
  11. package/dist/components/aspect-ratio.d.ts.map +1 -0
  12. package/dist/components/aspect-ratio.js +8 -0
  13. package/dist/components/avatar.d.ts +7 -0
  14. package/dist/components/avatar.d.ts.map +1 -0
  15. package/dist/components/avatar.js +15 -0
  16. package/dist/components/badge.d.ts +10 -0
  17. package/dist/components/badge.d.ts.map +1 -0
  18. package/dist/components/badge.js +24 -0
  19. package/dist/components/breadcrumb.d.ts +12 -0
  20. package/dist/components/breadcrumb.d.ts.map +1 -0
  21. package/dist/components/breadcrumb.js +29 -0
  22. package/dist/components/button-group.d.ts +12 -0
  23. package/dist/components/button-group.d.ts.map +1 -0
  24. package/dist/components/button-group.js +29 -0
  25. package/dist/components/button.d.ts +16 -0
  26. package/dist/components/button.d.ts.map +1 -0
  27. package/dist/components/button.js +37 -0
  28. package/dist/components/card.d.ts +10 -0
  29. package/dist/components/card.d.ts.map +1 -0
  30. package/dist/components/card.js +26 -0
  31. package/dist/components/carousel.d.ts +20 -0
  32. package/dist/components/carousel.d.ts.map +1 -0
  33. package/dist/components/carousel.js +92 -0
  34. package/dist/components/chart.d.ts +41 -0
  35. package/dist/components/chart.d.ts.map +1 -0
  36. package/dist/components/chart.js +133 -0
  37. package/dist/components/checkbox.d.ts +5 -0
  38. package/dist/components/checkbox.d.ts.map +1 -0
  39. package/dist/components/checkbox.js +10 -0
  40. package/dist/components/collapsible.d.ts +6 -0
  41. package/dist/components/collapsible.d.ts.map +1 -0
  42. package/dist/components/collapsible.js +14 -0
  43. package/dist/components/command.d.ts +19 -0
  44. package/dist/components/command.d.ts.map +1 -0
  45. package/dist/components/command.js +35 -0
  46. package/dist/components/context-menu.d.ts +26 -0
  47. package/dist/components/context-menu.d.ts.map +1 -0
  48. package/dist/components/context-menu.js +52 -0
  49. package/dist/components/data-table.d.ts +83 -0
  50. package/dist/components/data-table.d.ts.map +1 -0
  51. package/dist/components/data-table.js +357 -0
  52. package/dist/components/dialog.d.ts +16 -0
  53. package/dist/components/dialog.d.ts.map +1 -0
  54. package/dist/components/dialog.js +37 -0
  55. package/dist/components/drawer.d.ts +14 -0
  56. package/dist/components/drawer.d.ts.map +1 -0
  57. package/dist/components/drawer.js +36 -0
  58. package/dist/components/dropdown-menu.d.ts +26 -0
  59. package/dist/components/dropdown-menu.d.ts.map +1 -0
  60. package/dist/components/dropdown-menu.js +52 -0
  61. package/dist/components/empty.d.ts +12 -0
  62. package/dist/components/empty.d.ts.map +1 -0
  63. package/dist/components/empty.js +35 -0
  64. package/dist/components/field.d.ts +25 -0
  65. package/dist/components/field.d.ts.map +1 -0
  66. package/dist/components/field.js +74 -0
  67. package/dist/components/form.d.ts +25 -0
  68. package/dist/components/form.d.ts.map +1 -0
  69. package/dist/components/form.js +60 -0
  70. package/dist/components/header-app-switcher.d.ts +50 -0
  71. package/dist/components/header-app-switcher.d.ts.map +1 -0
  72. package/dist/components/header-app-switcher.js +154 -0
  73. package/dist/components/hierarchical-select.d.ts +21 -0
  74. package/dist/components/hierarchical-select.d.ts.map +1 -0
  75. package/dist/components/hierarchical-select.js +96 -0
  76. package/dist/components/hover-card.d.ts +7 -0
  77. package/dist/components/hover-card.d.ts.map +1 -0
  78. package/dist/components/hover-card.js +15 -0
  79. package/dist/components/input-group.d.ts +17 -0
  80. package/dist/components/input-group.d.ts.map +1 -0
  81. package/dist/components/input-group.js +64 -0
  82. package/dist/components/input-otp.d.ts +12 -0
  83. package/dist/components/input-otp.d.ts.map +1 -0
  84. package/dist/components/input-otp.js +22 -0
  85. package/dist/components/input.d.ts +4 -0
  86. package/dist/components/input.d.ts.map +1 -0
  87. package/dist/components/input.js +8 -0
  88. package/dist/components/item.d.ts +24 -0
  89. package/dist/components/item.d.ts.map +1 -0
  90. package/dist/components/item.js +68 -0
  91. package/dist/components/kbd.d.ts +4 -0
  92. package/dist/components/kbd.d.ts.map +1 -0
  93. package/dist/components/kbd.js +11 -0
  94. package/dist/components/label.d.ts +8 -0
  95. package/dist/components/label.d.ts.map +1 -0
  96. package/dist/components/label.js +9 -0
  97. package/dist/components/login-screen.d.ts +4 -0
  98. package/dist/components/login-screen.d.ts.map +1 -0
  99. package/dist/components/login-screen.js +300 -0
  100. package/dist/components/login-screen.types.d.ts +82 -0
  101. package/dist/components/login-screen.types.d.ts.map +1 -0
  102. package/dist/components/login-screen.views.d.ts +114 -0
  103. package/dist/components/login-screen.views.d.ts.map +1 -0
  104. package/dist/components/login-screen.views.js +53 -0
  105. package/dist/components/menubar.d.ts +27 -0
  106. package/dist/components/menubar.d.ts.map +1 -0
  107. package/dist/components/menubar.js +55 -0
  108. package/dist/components/navigation-menu.d.ts +15 -0
  109. package/dist/components/navigation-menu.d.ts.map +1 -0
  110. package/dist/components/navigation-menu.js +33 -0
  111. package/dist/components/pagination.d.ts +14 -0
  112. package/dist/components/pagination.d.ts.map +1 -0
  113. package/dist/components/pagination.js +31 -0
  114. package/dist/components/popover.d.ts +8 -0
  115. package/dist/components/popover.d.ts.map +1 -0
  116. package/dist/components/popover.js +18 -0
  117. package/dist/components/progress.d.ts +5 -0
  118. package/dist/components/progress.d.ts.map +1 -0
  119. package/dist/components/progress.js +9 -0
  120. package/dist/components/radio-group.d.ts +6 -0
  121. package/dist/components/radio-group.d.ts.map +1 -0
  122. package/dist/components/radio-group.js +13 -0
  123. package/dist/components/resizable.d.ts +9 -0
  124. package/dist/components/resizable.d.ts.map +1 -0
  125. package/dist/components/resizable.js +16 -0
  126. package/dist/components/scroll-area.d.ts +6 -0
  127. package/dist/components/scroll-area.d.ts.map +1 -0
  128. package/dist/components/scroll-area.js +14 -0
  129. package/dist/components/search-bar.d.ts +15 -0
  130. package/dist/components/search-bar.d.ts.map +1 -0
  131. package/dist/components/search-bar.js +25 -0
  132. package/dist/components/segmented-control.d.ts +24 -0
  133. package/dist/components/segmented-control.d.ts.map +1 -0
  134. package/dist/components/segmented-control.js +88 -0
  135. package/dist/components/select.d.ts +16 -0
  136. package/dist/components/select.d.ts.map +1 -0
  137. package/dist/components/select.js +39 -0
  138. package/dist/components/selection-panel.d.ts +29 -0
  139. package/dist/components/selection-panel.d.ts.map +1 -0
  140. package/dist/components/selection-panel.js +255 -0
  141. package/dist/components/separator.d.ts +5 -0
  142. package/dist/components/separator.d.ts.map +1 -0
  143. package/dist/components/separator.js +9 -0
  144. package/dist/components/sheet.d.ts +17 -0
  145. package/dist/components/sheet.d.ts.map +1 -0
  146. package/dist/components/sheet.js +42 -0
  147. package/dist/components/sidebar.d.ts +70 -0
  148. package/dist/components/sidebar.d.ts.map +1 -0
  149. package/dist/components/sidebar.js +213 -0
  150. package/dist/components/skeleton.d.ts +3 -0
  151. package/dist/components/skeleton.d.ts.map +1 -0
  152. package/dist/components/skeleton.js +8 -0
  153. package/dist/components/slider.d.ts +5 -0
  154. package/dist/components/slider.d.ts.map +1 -0
  155. package/dist/components/slider.js +15 -0
  156. package/dist/components/sonner.d.ts +4 -0
  157. package/dist/components/sonner.d.ts.map +1 -0
  158. package/dist/components/sonner.js +22 -0
  159. package/dist/components/spinner.d.ts +3 -0
  160. package/dist/components/spinner.d.ts.map +1 -0
  161. package/dist/components/spinner.js +9 -0
  162. package/dist/components/switch.d.ts +5 -0
  163. package/dist/components/switch.d.ts.map +1 -0
  164. package/dist/components/switch.js +9 -0
  165. package/dist/components/table.d.ts +11 -0
  166. package/dist/components/table.d.ts.map +1 -0
  167. package/dist/components/table.js +29 -0
  168. package/dist/components/tabs.d.ts +8 -0
  169. package/dist/components/tabs.d.ts.map +1 -0
  170. package/dist/components/tabs.js +18 -0
  171. package/dist/components/textarea.d.ts +4 -0
  172. package/dist/components/textarea.d.ts.map +1 -0
  173. package/dist/components/textarea.js +8 -0
  174. package/dist/components/toggle-group.d.ts +8 -0
  175. package/dist/components/toggle-group.d.ts.map +1 -0
  176. package/dist/components/toggle-group.js +22 -0
  177. package/dist/components/toggle.d.ts +10 -0
  178. package/dist/components/toggle.d.ts.map +1 -0
  179. package/dist/components/toggle.js +27 -0
  180. package/dist/components/tooltip.d.ts +8 -0
  181. package/dist/components/tooltip.d.ts.map +1 -0
  182. package/dist/components/tooltip.js +18 -0
  183. package/dist/components/visually-hidden.d.ts +16 -0
  184. package/dist/components/visually-hidden.d.ts.map +1 -0
  185. package/dist/components/visually-hidden.js +22 -0
  186. package/dist/globals.css +646 -0
  187. package/dist/hooks/use-mobile.d.ts +2 -0
  188. package/dist/hooks/use-mobile.d.ts.map +1 -0
  189. package/dist/hooks/use-mobile.js +18 -0
  190. package/dist/index.d.ts +64 -0
  191. package/dist/index.d.ts.map +1 -0
  192. package/dist/index.js +64 -0
  193. package/dist/lib/portal-wrapper.d.ts +32 -0
  194. package/dist/lib/portal-wrapper.d.ts.map +1 -0
  195. package/dist/lib/portal-wrapper.js +34 -0
  196. package/dist/lib/utils.js +8 -0
  197. package/dist/svgs/blaze-dispatch-logo.d.ts +5 -0
  198. package/dist/svgs/blaze-dispatch-logo.d.ts.map +1 -0
  199. package/dist/svgs/blaze-dispatch-logo.js +7 -0
  200. package/dist/svgs/blaze-ecom-logo.d.ts +7 -0
  201. package/dist/svgs/blaze-ecom-logo.d.ts.map +1 -0
  202. package/dist/svgs/blaze-ecom-logo.js +7 -0
  203. package/dist/svgs/blaze-insights-logo.d.ts +5 -0
  204. package/dist/svgs/blaze-insights-logo.d.ts.map +1 -0
  205. package/dist/svgs/blaze-insights-logo.js +7 -0
  206. package/dist/svgs/blaze-lighthouse-logo.d.ts +6 -0
  207. package/dist/svgs/blaze-lighthouse-logo.d.ts.map +1 -0
  208. package/dist/svgs/blaze-lighthouse-logo.js +7 -0
  209. package/dist/svgs/blaze-pay-logo.d.ts +5 -0
  210. package/dist/svgs/blaze-pay-logo.d.ts.map +1 -0
  211. package/dist/svgs/blaze-pay-logo.js +7 -0
  212. package/dist/svgs/blaze-pos-logo.d.ts +5 -0
  213. package/dist/svgs/blaze-pos-logo.d.ts.map +1 -0
  214. package/dist/svgs/blaze-pos-logo.js +7 -0
  215. package/dist/svgs/blaze-retail-logo.d.ts +7 -0
  216. package/dist/svgs/blaze-retail-logo.d.ts.map +1 -0
  217. package/dist/svgs/blaze-retail-logo.js +7 -0
  218. package/dist/svgs/blaze-sites-logo.d.ts +5 -0
  219. package/dist/svgs/blaze-sites-logo.d.ts.map +1 -0
  220. package/dist/svgs/blaze-sites-logo.js +7 -0
  221. package/package.json +86 -21
  222. package/build/components/button.d.ts +0 -12
  223. package/build/components/button.d.ts.map +0 -1
  224. package/build/components/button.js +0 -106
  225. package/build/components/button.js.map +0 -1
  226. package/build/index.d.ts +0 -4
  227. package/build/index.d.ts.map +0 -1
  228. package/build/index.js +0 -11
  229. package/build/index.js.map +0 -1
  230. package/build/lib/utils.js +0 -9
  231. package/build/lib/utils.js.map +0 -1
  232. package/build/styles/blaze-ui.css +0 -157
  233. package/build/styles/styles.d.ts +0 -3
  234. package/build/styles/styles.d.ts.map +0 -1
  235. package/build/styles/styles.js +0 -8
  236. package/build/styles/styles.js.map +0 -1
  237. package/src/styles/blaze-ui.css +0 -157
  238. package/src/styles/styles.ts +0 -5
  239. /package/{build → dist}/lib/utils.d.ts +0 -0
  240. /package/{build → dist}/lib/utils.d.ts.map +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../src/components/resizable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,kBAAkB,MAAM,wBAAwB,CAAA;AAI5D,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,UAAU,CAAC,2CAW5D;AAED,iBAAS,cAAc,CAAC,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,KAAK,CAAC,2CAEvD;AAED,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,iBAAiB,CAAC,GAAG;IACrE,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,2CAiBA;AAED,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { GripVerticalIcon } from 'lucide-react';
3
+ import * as ResizablePrimitive from 'react-resizable-panels';
4
+ import { cn } from '../lib/utils.js';
5
+
6
+ function ResizablePanelGroup({ className, ...props }) {
7
+ return (jsx(ResizablePrimitive.PanelGroup, { "data-slot": "resizable-panel-group", className: cn("tw:flex tw:h-full tw:w-full data-[panel-group-direction=vertical]:tw:flex-col", className), ...props }));
8
+ }
9
+ function ResizablePanel({ ...props }) {
10
+ return jsx(ResizablePrimitive.Panel, { "data-slot": "resizable-panel", ...props });
11
+ }
12
+ function ResizableHandle({ withHandle, className, ...props }) {
13
+ return (jsx(ResizablePrimitive.PanelResizeHandle, { "data-slot": "resizable-handle", className: cn("tw:bg-border focus-visible:tw:ring-ring tw:relative tw:flex tw:w-px tw:items-center tw:justify-center after:tw:absolute after:tw:inset-y-0 after:tw:left-1/2 after:tw:w-1 after:tw:-translate-x-1/2 focus-visible:tw:ring-1 focus-visible:tw:ring-offset-1 focus-visible:tw:outline-hidden data-[panel-group-direction=vertical]:tw:h-px data-[panel-group-direction=vertical]:tw:w-full data-[panel-group-direction=vertical]:after:tw:left-0 data-[panel-group-direction=vertical]:after:tw:h-1 data-[panel-group-direction=vertical]:after:tw:w-full data-[panel-group-direction=vertical]:after:tw:translate-x-0 data-[panel-group-direction=vertical]:after:tw:-translate-y-1/2 tw:[&[data-panel-group-direction=vertical]>div]:rotate-90", className), ...props, children: withHandle && (jsx("div", { className: "tw:bg-border tw:z-10 tw:flex tw:h-4 tw:w-3 tw:items-center tw:justify-center tw:rounded-xs tw:border", children: jsx(GripVerticalIcon, { className: "tw:size-2.5" }) })) }));
14
+ }
15
+
16
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -0,0 +1,6 @@
1
+ import * as React from "react";
2
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
3
+ declare function ScrollArea({ className, children, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ declare function ScrollBar({ className, orientation, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): import("react/jsx-runtime").JSX.Element;
5
+ export { ScrollArea, ScrollBar };
6
+ //# sourceMappingURL=scroll-area.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAA;AAIlE,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,2CAiBvD;AAED,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,WAAwB,EACxB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,2CAqBtE;AAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
3
+ import { cn } from '../lib/utils.js';
4
+
5
+ function ScrollArea({ className, children, ...props }) {
6
+ return (jsxs(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", className: cn("tw:relative", className), ...props, children: [jsx(ScrollAreaPrimitive.Viewport, { "data-slot": "scroll-area-viewport", className: "tw:focus-visible:ring-ring/50 tw:size-full tw:rounded-[inherit] tw:transition-[color,box-shadow] tw:outline-none tw:focus-visible:ring-[3px] tw:focus-visible:outline-1", children: children }), jsx(ScrollBar, {}), jsx(ScrollAreaPrimitive.Corner, {})] }));
7
+ }
8
+ function ScrollBar({ className, orientation = "vertical", ...props }) {
9
+ return (jsx(ScrollAreaPrimitive.ScrollAreaScrollbar, { "data-slot": "scroll-area-scrollbar", orientation: orientation, className: cn("tw:flex tw:touch-none tw:p-px tw:transition-colors tw:select-none", orientation === "vertical" &&
10
+ "tw:h-full tw:w-2.5 tw:border-l tw:border-l-transparent", orientation === "horizontal" &&
11
+ "tw:h-2.5 tw:flex-col tw:border-t tw:border-t-transparent", className), ...props, children: jsx(ScrollAreaPrimitive.ScrollAreaThumb, { "data-slot": "scroll-area-thumb", className: "tw:bg-border tw:relative tw:flex-1 tw:rounded-full" }) }));
12
+ }
13
+
14
+ export { ScrollArea, ScrollBar };
@@ -0,0 +1,15 @@
1
+ export interface SearchBarProps {
2
+ value: string;
3
+ onChange: (value: string) => void;
4
+ onSearch: (value: string) => void;
5
+ onClear: () => void;
6
+ placeholder?: string;
7
+ disabled?: boolean;
8
+ loading?: boolean;
9
+ applyLabel?: string;
10
+ clearLabel?: string;
11
+ className?: string;
12
+ inputAriaLabel?: string;
13
+ }
14
+ export declare function SearchBar({ value, onChange, onSearch, onClear, placeholder, disabled, loading, applyLabel, clearLabel, className, inputAriaLabel, }: SearchBarProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=search-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-bar.d.ts","sourceRoot":"","sources":["../../src/components/search-bar.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,WAAyB,EACzB,QAAgB,EAChB,OAAe,EACf,UAAoB,EACpB,UAAoB,EACpB,SAAS,EACT,cAA+B,GAChC,EAAE,cAAc,2CA4EhB"}
@@ -0,0 +1,25 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { SearchIcon, XIcon } from 'lucide-react';
3
+ import { cn } from '../lib/utils.js';
4
+ import { Input } from './input.js';
5
+ import { Button } from './button.js';
6
+
7
+ function SearchBar({ value, onChange, onSearch, onClear, placeholder = "Search...", disabled = false, loading = false, applyLabel = "Apply", clearLabel = "Clear", className, inputAriaLabel = "Search input", }) {
8
+ const handleKeyDown = (e) => {
9
+ if (e.key === "Enter") {
10
+ e.preventDefault();
11
+ onSearch(value);
12
+ }
13
+ else if (e.key === "Escape") {
14
+ e.preventDefault();
15
+ onClear();
16
+ }
17
+ };
18
+ const handleClearClick = () => {
19
+ onChange("");
20
+ onClear();
21
+ };
22
+ return (jsxs("div", { "data-slot": "search-bar", className: cn("tw:!flex tw:!w-full tw:!gap-2", className), children: [jsxs("div", { className: "tw:!relative tw:!flex-1", children: [jsx(SearchIcon, { className: "tw:!absolute tw:!left-3 tw:!top-1/2 tw:!-translate-y-1/2 tw:!h-4 tw:!w-4 tw:text-muted-foreground tw:!pointer-events-none", "aria-hidden": "true" }), jsx(Input, { type: "text", value: value, onChange: (e) => onChange(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, className: "tw:!pl-9", "aria-label": inputAriaLabel }), value && !disabled && (jsx("button", { type: "button", onClick: handleClearClick, className: "tw:!absolute tw:!right-3 tw:!top-1/2 tw:!-translate-y-1/2 tw:!h-4 tw:!w-4 tw:text-muted-foreground hover:tw:text-foreground tw:transition-colors tw:!cursor-pointer", "aria-label": "Clear search", children: jsx(XIcon, { className: "tw:!h-4 tw:!w-4" }) }))] }), jsx(Button, { variant: "default", size: "sm", onClick: () => onSearch(value), disabled: disabled || !value, loading: loading, className: cn("tw:!min-w-[80px]", (disabled || !value) && "tw:!opacity-50 tw:!cursor-not-allowed"), "aria-label": "Apply search", children: applyLabel }), jsx(Button, { variant: "outline", size: "sm", onClick: handleClearClick, disabled: disabled || !value, className: cn("tw:!min-w-[80px]", (disabled || !value) && "tw:!opacity-50 tw:!cursor-not-allowed"), "aria-label": "Clear search", children: clearLabel })] }));
23
+ }
24
+
25
+ export { SearchBar };
@@ -0,0 +1,24 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ declare const segmentedControlVariants: (props?: ({
3
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
4
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ declare const segmentedControlItemVariants: (props?: ({
7
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
8
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
+ interface SegmentedControlOption {
11
+ value: string;
12
+ label: string;
13
+ }
14
+ interface SegmentedControlProps extends VariantProps<typeof segmentedControlVariants> {
15
+ options: SegmentedControlOption[];
16
+ value: string;
17
+ onValueChange: (value: string) => void;
18
+ className?: string;
19
+ ariaLabel?: string;
20
+ ariaLabelledBy?: string;
21
+ }
22
+ export declare function SegmentedControl({ options, value, onValueChange, className, ariaLabel, ariaLabelledBy, variant, size, }: SegmentedControlProps): import("react/jsx-runtime").JSX.Element;
23
+ export { segmentedControlItemVariants, segmentedControlVariants };
24
+ //# sourceMappingURL=segmented-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../src/components/segmented-control.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAOjE,QAAA,MAAM,wBAAwB;;;8EAwB7B,CAAA;AAED,QAAA,MAAM,4BAA4B;;;8EA6BjC,CAAA;AAED,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,qBACR,SAAQ,YAAY,CAAC,OAAO,wBAAwB,CAAC;IACrD,OAAO,EAAE,sBAAsB,EAAE,CAAA;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,KAAK,EACL,aAAa,EACb,SAAS,EACT,SAAS,EACT,cAAc,EACd,OAAO,EACP,IAAI,GACL,EAAE,qBAAqB,2CAgFvB;AAED,OAAO,EAAE,4BAA4B,EAAE,wBAAwB,EAAE,CAAA"}
@@ -0,0 +1,88 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { cva } from 'class-variance-authority';
3
+ import { useRef } from 'react';
4
+ import { cn } from '../lib/utils.js';
5
+
6
+ const segmentedControlVariants = cva("tw:inline-flex tw:items-center tw:gap-1 tw:rounded-md tw:border tw:p-1", {
7
+ variants: {
8
+ variant: {
9
+ default: "tw:border-transparent tw:bg-muted",
10
+ destructive: "tw:border-destructive/20 tw:bg-destructive/10",
11
+ outline: "tw:border-input tw:bg-background",
12
+ secondary: "tw:border-transparent tw:bg-secondary/60",
13
+ ghost: "tw:border-transparent tw:bg-transparent",
14
+ link: "tw:border-transparent tw:bg-transparent",
15
+ },
16
+ size: {
17
+ default: "tw:p-1",
18
+ sm: "tw:p-0.5",
19
+ lg: "tw:p-1.5",
20
+ icon: "tw:p-1",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ size: "default",
26
+ },
27
+ });
28
+ const segmentedControlItemVariants = cva("tw:inline-flex tw:items-center tw:justify-center tw:gap-2 tw:rounded-md tw:text-sm tw:font-medium tw:transition-all tw:duration-200 tw:outline-none tw:focus-visible:border-ring tw:focus-visible:ring-ring/50 tw:focus-visible:ring-[3px] tw:focus-visible:ring-offset-2 tw:focus-visible:ring-offset-background tw:focus:z-10 tw:cursor-pointer tw:disabled:cursor-not-allowed tw:disabled:pointer-events-none tw:disabled:opacity-50", {
29
+ variants: {
30
+ variant: {
31
+ default: "tw:text-foreground/70 tw:hover:text-primary tw:hover:bg-primary/10 tw:data-[state=active]:bg-primary tw:data-[state=active]:text-primary-foreground tw:data-[state=active]:shadow-xs",
32
+ destructive: "tw:text-destructive tw:hover:text-destructive tw:hover:bg-destructive/10 tw:data-[state=active]:bg-destructive tw:data-[state=active]:text-white tw:data-[state=active]:shadow-xs",
33
+ outline: "tw:text-foreground/70 tw:hover:text-foreground tw:hover:bg-muted/50 tw:data-[state=active]:border tw:data-[state=active]:border-input tw:data-[state=active]:bg-background tw:data-[state=active]:text-foreground tw:data-[state=active]:shadow-xs",
34
+ secondary: "tw:text-secondary-foreground/80 tw:hover:text-secondary-foreground tw:hover:bg-secondary/60 tw:data-[state=active]:bg-secondary tw:data-[state=active]:text-secondary-foreground tw:data-[state=active]:shadow-xs",
35
+ ghost: "tw:text-foreground/80 tw:hover:text-foreground tw:hover:bg-accent/50 tw:data-[state=active]:bg-accent tw:data-[state=active]:text-accent-foreground tw:data-[state=active]:shadow-xs",
36
+ link: "tw:text-primary tw:hover:underline tw:data-[state=active]:text-primary tw:data-[state=active]:underline tw:data-[state=active]:shadow-none",
37
+ },
38
+ size: {
39
+ default: "tw:px-4 tw:py-2 tw:text-sm",
40
+ sm: "tw:px-3 tw:py-1.5 tw:text-xs",
41
+ lg: "tw:px-5 tw:py-2.5 tw:text-base",
42
+ icon: "tw:px-2 tw:py-2 tw:text-sm",
43
+ },
44
+ },
45
+ defaultVariants: {
46
+ variant: "default",
47
+ size: "default",
48
+ },
49
+ });
50
+ function SegmentedControl({ options, value, onValueChange, className, ariaLabel, ariaLabelledBy, variant, size, }) {
51
+ const resolvedVariant = variant ?? "default";
52
+ const resolvedSize = size ?? "default";
53
+ const containerRef = useRef(null);
54
+ const handleKeyDown = (event, currentIndex) => {
55
+ let newIndex = currentIndex;
56
+ switch (event.key) {
57
+ case "ArrowLeft":
58
+ case "ArrowUp":
59
+ event.preventDefault();
60
+ newIndex = currentIndex > 0 ? currentIndex - 1 : options.length - 1;
61
+ break;
62
+ case "ArrowRight":
63
+ case "ArrowDown":
64
+ event.preventDefault();
65
+ newIndex = currentIndex < options.length - 1 ? currentIndex + 1 : 0;
66
+ break;
67
+ case "Home":
68
+ event.preventDefault();
69
+ newIndex = 0;
70
+ break;
71
+ case "End":
72
+ event.preventDefault();
73
+ newIndex = options.length - 1;
74
+ break;
75
+ default:
76
+ return;
77
+ }
78
+ onValueChange(options[newIndex]?.value ?? "");
79
+ const buttons = containerRef.current?.querySelectorAll("button");
80
+ buttons?.[newIndex]?.focus();
81
+ };
82
+ return (jsx("div", { ref: containerRef, className: cn(segmentedControlVariants({ variant, size }), className), role: "tablist", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-orientation": "horizontal", "data-slot": "segmented-control", "data-variant": resolvedVariant, "data-size": resolvedSize, children: options.map((option, index) => {
83
+ const isSelected = value === option.value;
84
+ return (jsxs("button", { type: "button", role: "tab", "aria-selected": isSelected, "aria-controls": `panel-${option.value}`, id: `tab-${option.value}`, tabIndex: isSelected ? 0 : -1, onClick: () => onValueChange(option.value), onKeyDown: (e) => handleKeyDown(e, index), className: segmentedControlItemVariants({ variant, size }), "aria-describedby": isSelected ? `${option.value}-description` : undefined, "data-state": isSelected ? "active" : "inactive", "data-variant": resolvedVariant, "data-slot": "segmented-control-item", children: [option.label, isSelected && (jsx("span", { className: "tw:sr-only", children: ", currently selected" }))] }, option.value));
85
+ }) }));
86
+ }
87
+
88
+ export { SegmentedControl, segmentedControlItemVariants, segmentedControlVariants };
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import * as SelectPrimitive from "@radix-ui/react-select";
3
+ declare function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ declare function SelectGroup({ ...props }: React.ComponentProps<typeof SelectPrimitive.Group>): import("react/jsx-runtime").JSX.Element;
5
+ declare function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>): import("react/jsx-runtime").JSX.Element;
6
+ declare function SelectTrigger({ className, size, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
7
+ size?: "sm" | "default";
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ declare function SelectContent({ className, children, position, ...props }: React.ComponentProps<typeof SelectPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
10
+ declare function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>): import("react/jsx-runtime").JSX.Element;
11
+ declare function SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>): import("react/jsx-runtime").JSX.Element;
12
+ declare function SelectSeparator({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Separator>): import("react/jsx-runtime").JSX.Element;
13
+ declare function SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>): import("react/jsx-runtime").JSX.Element;
14
+ declare function SelectScrollDownButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>): import("react/jsx-runtime").JSX.Element;
15
+ export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, };
16
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/components/select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AAKzD,iBAAS,MAAM,CAAC,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,2CAEnD;AAED,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAEpD;AAED,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAEpD;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,IAAgB,EAChB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,GAAG;IACxD,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAA;CACxB,2CAyBA;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,QAAmB,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,2CA8BtD;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAWpD;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,2CAsBnD;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,SAAS,CAAC,2CAWxD;AAED,iBAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,cAAc,CAAC,2CAa7D;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,gBAAgB,CAAC,2CAa/D;AAED,OAAO,EACL,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,WAAW,GACZ,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import * as SelectPrimitive from '@radix-ui/react-select';
3
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
4
+ import { cn } from '../lib/utils.js';
5
+
6
+ function Select({ ...props }) {
7
+ return jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
8
+ }
9
+ function SelectGroup({ ...props }) {
10
+ return jsx(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
11
+ }
12
+ function SelectValue({ ...props }) {
13
+ return jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
14
+ }
15
+ function SelectTrigger({ className, size = "default", children, ...props }) {
16
+ return (jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn("tw:!flex tw:!w-fit tw:!items-center tw:!justify-between tw:!gap-2 tw:!rounded-md tw:!border tw:!border-input tw:!bg-transparent tw:!px-3 tw:!py-2 tw:!text-[14px] tw:!whitespace-nowrap tw:!shadow-xs tw:!transition-[color,box-shadow] tw:!outline-none", "data-[placeholder]:tw:!text-muted-foreground [&_svg:not([class*='text-'])]:tw:!text-muted-foreground", "focus-visible:tw:!border-ring focus-visible:tw:!ring-ring/50 focus-visible:tw:!ring-[3px]", "aria-invalid:tw:!border-destructive aria-invalid:tw:!ring-destructive/20 dark:aria-invalid:tw:!ring-destructive/40", "dark:tw:!bg-input/30 dark:hover:tw:!bg-input/50", "disabled:tw:!cursor-not-allowed disabled:tw:!opacity-50", "data-[size=default]:tw:!h-9 data-[size=sm]:tw:!h-8", "*:data-[slot=select-value]:tw:!line-clamp-1 *:data-[slot=select-value]:tw:!flex *:data-[slot=select-value]:tw:!items-center *:data-[slot=select-value]:tw:!gap-2", "[&_svg]:tw:!pointer-events-none [&_svg]:tw:!shrink-0 [&_svg:not([class*='size-'])]:tw:!size-4", className), ...props, children: [children, jsx(SelectPrimitive.Icon, { asChild: true, children: jsx(ChevronDownIcon, { className: "tw:!size-4 tw:!opacity-50" }) })] }));
17
+ }
18
+ function SelectContent({ className, children, position = "popper", ...props }) {
19
+ return (jsx(SelectPrimitive.Portal, { children: jsxs(SelectPrimitive.Content, { "data-slot": "select-content", className: cn("tw:!relative tw:!z-50 tw:!min-w-[8rem] tw:!max-h-(--radix-select-content-available-height) tw:!origin-(--radix-select-content-transform-origin) tw:!overflow-x-hidden tw:!overflow-y-auto tw:!rounded-md tw:!border tw:!bg-popover tw:!text-popover-foreground tw:!shadow-md", "data-[state=open]:tw:!animate-in data-[state=closed]:tw:!animate-out data-[state=closed]:tw:!fade-out-0 data-[state=open]:tw:!fade-in-0 data-[state=closed]:tw:!zoom-out-95 data-[state=open]:tw:!zoom-in-95", "data-[side=bottom]:tw:!slide-in-from-top-2 data-[side=left]:tw:!slide-in-from-right-2 data-[side=right]:tw:!slide-in-from-left-2 data-[side=top]:tw:!slide-in-from-bottom-2", position === "popper" &&
20
+ "data-[side=bottom]:tw:!translate-y-1 data-[side=left]:tw:!-translate-x-1 data-[side=right]:tw:!translate-x-1 data-[side=top]:tw:!-translate-y-1", className), position: position, ...props, children: [jsx(SelectScrollUpButton, {}), jsx(SelectPrimitive.Viewport, { className: cn("tw:!p-1", position === "popper" &&
21
+ "tw:!h-[var(--radix-select-trigger-height)] tw:!w-full tw:!min-w-[var(--radix-select-trigger-width)] tw:!scroll-my-1"), children: children }), jsx(SelectScrollDownButton, {})] }) }));
22
+ }
23
+ function SelectLabel({ className, ...props }) {
24
+ return (jsx(SelectPrimitive.Label, { "data-slot": "select-label", className: cn("tw:!text-muted-foreground tw:!px-2 tw:!py-1.5 tw:!text-[12px]", className), ...props }));
25
+ }
26
+ function SelectItem({ className, children, ...props }) {
27
+ return (jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn("tw:!relative tw:!flex tw:!w-full tw:!cursor-default tw:!items-center tw:!gap-2 tw:!rounded-sm tw:!py-1.5 tw:!pl-2 tw:!pr-8 tw:!text-[14px] tw:!outline-hidden tw:!select-none tw:!transition-colors", "focus:tw:!bg-accent focus:tw:!text-accent-foreground", "data-[disabled]:tw:!pointer-events-none data-[disabled]:tw:!opacity-50", "[&>span]:tw:!line-clamp-1 [&>span]:tw:!flex [&>span]:tw:!items-center [&>span]:tw:!gap-2", "[&_svg]:tw:!pointer-events-none [&_svg]:tw:!shrink-0 [&_svg:not([class*='size-'])]:tw:!size-4 [&_svg:not([class*='text-'])]:tw:!text-muted-foreground", className), ...props, children: [jsx("span", { className: "tw:!absolute tw:!right-2 tw:!flex tw:!size-3.5 tw:!items-center tw:!justify-center", children: jsx(SelectPrimitive.ItemIndicator, { children: jsx(CheckIcon, { className: "tw:!size-4" }) }) }), jsx(SelectPrimitive.ItemText, { children: children })] }));
28
+ }
29
+ function SelectSeparator({ className, ...props }) {
30
+ return (jsx(SelectPrimitive.Separator, { "data-slot": "select-separator", className: cn("tw:!bg-border tw:!pointer-events-none tw:!-mx-1 tw:!my-1 tw:!h-px", className), ...props }));
31
+ }
32
+ function SelectScrollUpButton({ className, ...props }) {
33
+ return (jsx(SelectPrimitive.ScrollUpButton, { "data-slot": "select-scroll-up-button", className: cn("tw:!flex tw:!cursor-default tw:!items-center tw:!justify-center tw:!py-1", className), ...props, children: jsx(ChevronUpIcon, { className: "tw:!size-4" }) }));
34
+ }
35
+ function SelectScrollDownButton({ className, ...props }) {
36
+ return (jsx(SelectPrimitive.ScrollDownButton, { "data-slot": "select-scroll-down-button", className: cn("tw:!flex tw:!cursor-default tw:!items-center tw:!justify-center tw:!py-1", className), ...props, children: jsx(ChevronDownIcon, { className: "tw:!size-4" }) }));
37
+ }
38
+
39
+ export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
@@ -0,0 +1,29 @@
1
+ import { type DataTableColumn, type DataTableRow } from "./data-table";
2
+ export interface SelectionPanelProps<T extends DataTableRow> {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ onDone: (selectedIds: string[]) => void;
6
+ title?: string;
7
+ description?: string;
8
+ availableItems: T[];
9
+ columns: DataTableColumn<T>[];
10
+ selectedColumns?: DataTableColumn<T>[];
11
+ selectedIds: string[];
12
+ loading?: boolean;
13
+ treeMode?: boolean;
14
+ availableLabel?: string;
15
+ selectedLabel?: string;
16
+ addButtonLabel?: string;
17
+ removeButtonLabel?: string;
18
+ doneButtonLabel?: string;
19
+ cancelButtonLabel?: string;
20
+ availableEmptyMessage?: string;
21
+ selectedEmptyMessage?: string;
22
+ width?: string;
23
+ maxWidth?: string;
24
+ showConfirmOnClose?: boolean;
25
+ confirmCloseMessage?: string;
26
+ onBeforeSelectionChange?: (selectedIds: string[]) => string[];
27
+ }
28
+ export declare function SelectionPanel<T extends DataTableRow>({ open, onClose, onDone, title, description, availableItems, columns, selectedColumns, selectedIds: initialSelectedIds, loading, treeMode, availableLabel, selectedLabel, addButtonLabel, removeButtonLabel, doneButtonLabel, cancelButtonLabel, availableEmptyMessage, selectedEmptyMessage, width, maxWidth, showConfirmOnClose, confirmCloseMessage, onBeforeSelectionChange, }: SelectionPanelProps<T>): import("react/jsx-runtime").JSX.Element;
29
+ //# sourceMappingURL=selection-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-panel.d.ts","sourceRoot":"","sources":["../../src/components/selection-panel.tsx"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,cAAc,CAAA;AAuBrB,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,YAAY;IACzD,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,CAAC,EAAE,CAAA;IACnB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IACtC,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,uBAAuB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;CAC9D;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,YAAY,EAAE,EACrD,IAAI,EACJ,OAAO,EACP,MAAM,EACN,KAAsB,EACtB,WAAW,EACX,cAAc,EACd,OAAO,EACP,eAAe,EACf,WAAW,EAAE,kBAAkB,EAC/B,OAAe,EACf,QAAgB,EAChB,cAA4B,EAC5B,aAA0B,EAC1B,cAA+B,EAC/B,iBAAqC,EACrC,eAAwB,EACxB,iBAA4B,EAC5B,qBAAqB,EACrB,oBAA0C,EAC1C,KAAa,EACb,QAAmB,EACnB,kBAAyB,EACzB,mBAAkF,EAClF,uBAAuB,GACxB,EAAE,mBAAmB,CAAC,CAAC,CAAC,2CAwfxB"}
@@ -0,0 +1,255 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { cn } from '../lib/utils.js';
4
+ import { SearchBar } from './search-bar.js';
5
+ import { DataTable } from './data-table.js';
6
+ import { Button } from './button.js';
7
+ import { Sheet, SheetContent, SheetTitle, SheetFooter } from './sheet.js';
8
+ import { VisuallyHidden } from './visually-hidden.js';
9
+ import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from './alert-dialog.js';
10
+
11
+ function SelectionPanel({ open, onClose, onDone, title = "Select Items", description, availableItems, columns, selectedColumns, selectedIds: initialSelectedIds, loading = false, treeMode = false, availableLabel = "Available", selectedLabel = "Selected", addButtonLabel = "Add Selected", removeButtonLabel = "Remove Selected", doneButtonLabel = "Done", cancelButtonLabel = "Cancel", availableEmptyMessage, selectedEmptyMessage = "No items selected", width = "75%", maxWidth = "1400px", showConfirmOnClose = true, confirmCloseMessage = "Are you sure you want to exit without saving your changes?", onBeforeSelectionChange, }) {
12
+ const [selectedIds, setSelectedIds] = React.useState(new Set(initialSelectedIds));
13
+ const [availableChecked, setAvailableChecked] = React.useState(new Set());
14
+ const [selectedChecked, setSelectedChecked] = React.useState(new Set());
15
+ const [expandedAvailableRows, setExpandedAvailableRows] = React.useState(new Set());
16
+ const [availableSearch, setAvailableSearch] = React.useState("");
17
+ const [selectedSearch, setSelectedSearch] = React.useState("");
18
+ const [availableSearchApplied, setAvailableSearchApplied] = React.useState("");
19
+ const [selectedSearchApplied, setSelectedSearchApplied] = React.useState("");
20
+ // Pagination state for both panels
21
+ const [availablePage, setAvailablePage] = React.useState(1);
22
+ const [availablePageSize, setAvailablePageSize] = React.useState(20);
23
+ const [selectedPage, setSelectedPage] = React.useState(1);
24
+ const [selectedPageSize, setSelectedPageSize] = React.useState(20);
25
+ const [isDirty, setIsDirty] = React.useState(false);
26
+ const [showConfirmDialog, setShowConfirmDialog] = React.useState(false);
27
+ const availableHeadingId = React.useId();
28
+ const selectedHeadingId = React.useId();
29
+ React.useEffect(() => {
30
+ if (open) {
31
+ setSelectedIds(new Set(initialSelectedIds));
32
+ setAvailableChecked(new Set());
33
+ setSelectedChecked(new Set());
34
+ setExpandedAvailableRows(new Set());
35
+ setAvailableSearch("");
36
+ setSelectedSearch("");
37
+ setAvailableSearchApplied("");
38
+ setSelectedSearchApplied("");
39
+ setAvailablePage(1);
40
+ setSelectedPage(1);
41
+ setIsDirty(false);
42
+ }
43
+ }, [open, initialSelectedIds]);
44
+ const flattenTree = React.useCallback((items) => {
45
+ const map = {};
46
+ const traverse = (nodes, parentId) => {
47
+ nodes.forEach((node) => {
48
+ const entry = { ...node, parentId };
49
+ map[node.id] = entry;
50
+ if (node.children) {
51
+ traverse(node.children, node.id);
52
+ }
53
+ });
54
+ };
55
+ traverse(items);
56
+ return map;
57
+ }, []);
58
+ const availableItemsMap = React.useMemo(() => flattenTree(availableItems), [availableItems, flattenTree]);
59
+ const availableItemsFiltered = React.useMemo(() => {
60
+ const filterRecursive = (items) => {
61
+ return items
62
+ .filter((item) => !selectedIds.has(item.id))
63
+ .map((item) => {
64
+ if (treeMode && item.children) {
65
+ return {
66
+ ...item,
67
+ children: filterRecursive(item.children),
68
+ };
69
+ }
70
+ return item;
71
+ });
72
+ };
73
+ let filtered = filterRecursive(availableItems);
74
+ if (availableSearchApplied) {
75
+ const searchLower = availableSearchApplied.toLowerCase();
76
+ const searchRecursive = (items) => {
77
+ return items.filter((item) => {
78
+ const matches = columns.some((col) => {
79
+ const value = item[col.key];
80
+ return String(value).toLowerCase().includes(searchLower);
81
+ });
82
+ if (treeMode && item.children) {
83
+ const matchingChildren = searchRecursive(item.children);
84
+ if (matchingChildren.length > 0) {
85
+ return true;
86
+ }
87
+ }
88
+ return matches;
89
+ });
90
+ };
91
+ filtered = searchRecursive(filtered);
92
+ }
93
+ return filtered;
94
+ }, [availableItems, selectedIds, availableSearchApplied, columns, treeMode]);
95
+ const selectedItemsData = React.useMemo(() => {
96
+ const findItemsById = (items, ids) => {
97
+ const result = [];
98
+ for (const item of items) {
99
+ if (ids.has(item.id)) {
100
+ result.push(item);
101
+ }
102
+ if (treeMode && item.children) {
103
+ result.push(...findItemsById(item.children, ids));
104
+ }
105
+ }
106
+ return result;
107
+ };
108
+ let selected = findItemsById(availableItems, selectedIds);
109
+ if (selectedSearchApplied) {
110
+ const searchLower = selectedSearchApplied.toLowerCase();
111
+ selected = selected.filter((item) => {
112
+ return columns.some((col) => {
113
+ const value = item[col.key];
114
+ return String(value).toLowerCase().includes(searchLower);
115
+ });
116
+ });
117
+ }
118
+ return selected;
119
+ }, [availableItems, selectedIds, selectedSearchApplied, columns, treeMode]);
120
+ // Paginate available items (top-level only; children stay with parent)
121
+ const availableTotalPages = Math.ceil(availableItemsFiltered.length / availablePageSize);
122
+ const paginatedAvailableItems = React.useMemo(() => availableItemsFiltered.slice((availablePage - 1) * availablePageSize, availablePage * availablePageSize), [availableItemsFiltered, availablePage, availablePageSize]);
123
+ // Paginate selected items (flat list)
124
+ const selectedTotalPages = Math.ceil(selectedItemsData.length / selectedPageSize);
125
+ const paginatedSelectedItems = React.useMemo(() => selectedItemsData.slice((selectedPage - 1) * selectedPageSize, selectedPage * selectedPageSize), [selectedItemsData, selectedPage, selectedPageSize]);
126
+ // Reset to page 1 when filtered data changes (search, add/remove items)
127
+ React.useEffect(() => {
128
+ setAvailablePage(1);
129
+ }, [availableItemsFiltered.length]);
130
+ React.useEffect(() => {
131
+ setSelectedPage(1);
132
+ }, [selectedItemsData.length]);
133
+ const handleAvailableSelectionChange = React.useCallback((ids) => {
134
+ const transformedIds = onBeforeSelectionChange
135
+ ? onBeforeSelectionChange(ids)
136
+ : ids;
137
+ const newCheckedSet = new Set(transformedIds);
138
+ setAvailableChecked(newCheckedSet);
139
+ if (treeMode) {
140
+ // Only auto-expand ancestors of NEWLY checked IDs,
141
+ // don't touch expansion state for previously checked items
142
+ const newlyAdded = transformedIds.filter((id) => !availableChecked.has(id));
143
+ if (newlyAdded.length > 0) {
144
+ setExpandedAvailableRows((prev) => {
145
+ const nextExpanded = new Set(prev);
146
+ newlyAdded.forEach((id) => {
147
+ let currentNode = availableItemsMap[id];
148
+ if (!currentNode)
149
+ return;
150
+ let parentId = currentNode.parentId;
151
+ while (parentId) {
152
+ nextExpanded.add(parentId);
153
+ parentId = availableItemsMap[parentId]?.parentId;
154
+ }
155
+ });
156
+ return nextExpanded;
157
+ });
158
+ }
159
+ }
160
+ }, [onBeforeSelectionChange, treeMode, availableItemsMap, availableChecked]);
161
+ const handleSelectedSelectionChange = React.useCallback((ids) => {
162
+ setSelectedChecked(new Set(ids));
163
+ }, []);
164
+ const handleAddSelected = React.useCallback(() => {
165
+ if (availableChecked.size === 0)
166
+ return;
167
+ setSelectedIds((prev) => {
168
+ const next = new Set(prev);
169
+ availableChecked.forEach((id) => next.add(id));
170
+ return next;
171
+ });
172
+ setAvailableChecked(new Set());
173
+ setIsDirty(true);
174
+ }, [availableChecked]);
175
+ const handleRemoveSelected = React.useCallback(() => {
176
+ if (selectedChecked.size === 0)
177
+ return;
178
+ setSelectedIds((prev) => {
179
+ const next = new Set(prev);
180
+ selectedChecked.forEach((id) => next.delete(id));
181
+ return next;
182
+ });
183
+ setSelectedChecked(new Set());
184
+ setIsDirty(true);
185
+ }, [selectedChecked]);
186
+ const handleDone = React.useCallback(() => {
187
+ onDone(Array.from(selectedIds));
188
+ onClose();
189
+ }, [selectedIds, onDone, onClose]);
190
+ const handleClose = React.useCallback(() => {
191
+ if (isDirty && showConfirmOnClose) {
192
+ setShowConfirmDialog(true);
193
+ }
194
+ else {
195
+ onClose();
196
+ }
197
+ }, [isDirty, showConfirmOnClose, onClose]);
198
+ const handleConfirmClose = React.useCallback(() => {
199
+ setShowConfirmDialog(false);
200
+ onClose();
201
+ }, [onClose]);
202
+ return (jsxs(Fragment, { children: [jsx(Sheet, { open: open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: jsxs(SheetContent, { side: "right", className: cn("tw:!p-0 tw:!z-[1200]"), overlayClassName: "tw:!z-[1200]", style: { width, maxWidth }, children: [jsx(VisuallyHidden, { children: jsx(SheetTitle, { children: title }) }), jsxs("div", { className: "tw:!flex tw:!h-full tw:!flex-col", children: [jsxs("div", { className: "tw:!flex tw:!flex-1 tw:!overflow-hidden", children: [jsxs("div", { className: "tw:!flex tw:!w-1/2 tw:!flex-col tw:!border-r", role: "region", "aria-labelledby": availableHeadingId, children: [jsxs("div", { className: "tw:!border-b tw:!p-4", children: [jsx("h2", { id: availableHeadingId, className: "tw:text-lg tw:!font-semibold tw:!mb-3", children: availableLabel }), jsx(SearchBar, { value: availableSearch, onChange: setAvailableSearch, onSearch: (term) => setAvailableSearchApplied(term), onClear: () => {
203
+ setAvailableSearch("");
204
+ setAvailableSearchApplied("");
205
+ }, placeholder: `Search ${availableLabel.toLowerCase()}...`, inputAriaLabel: `Search within ${availableLabel}` }), jsx("div", { className: "tw:!flex tw:!justify-end tw:!mt-3", children: jsx(Button, { size: "sm", onClick: handleAddSelected, disabled: availableChecked.size === 0, className: availableChecked.size === 0
206
+ ? "tw:!opacity-50 tw:!cursor-not-allowed"
207
+ : undefined, "aria-label": availableChecked.size === 0
208
+ ? addButtonLabel
209
+ : `${addButtonLabel} (${availableChecked.size} selected)`, children: addButtonLabel }) })] }), jsx("div", { className: "tw:!flex-1 tw:!flex tw:!flex-col tw:!overflow-hidden", children: jsx(DataTable, { columns: columns, data: paginatedAvailableItems, onSelectionChange: handleAvailableSelectionChange, selectedRowIds: Array.from(availableChecked), treeData: treeMode, loading: loading, className: "tw:!flex-1", expandedRowIds: Array.from(expandedAvailableRows), onExpandedChange: (ids) => setExpandedAvailableRows(new Set(ids)), reservePaginationSpace: true, selectContentClassName: "tw:!z-[1300]", menuPopupClassName: "tw:!z-[1300]", pagination: {
210
+ currentPage: availablePage,
211
+ totalPages: availableTotalPages,
212
+ onPageChange: setAvailablePage,
213
+ pageSize: availablePageSize,
214
+ totalItems: availableItemsFiltered.length,
215
+ pageSizeOptions: [20, 40, 60, 80, 100],
216
+ onPageSizeChange: (size) => {
217
+ setAvailablePageSize(size);
218
+ setAvailablePage(1);
219
+ },
220
+ showTotalItems: true,
221
+ }, footerContent: jsxs("div", { className: "tw:text-sm tw:text-muted-foreground", "aria-live": "polite", role: "status", children: [availableChecked.size, " Selected"] }), emptyState: {
222
+ title: availableEmptyMessage || "No items available",
223
+ description: availableSearchApplied
224
+ ? "Try adjusting your search"
225
+ : undefined,
226
+ } }) })] }), jsxs("div", { className: "tw:!flex tw:!w-1/2 tw:!flex-col", role: "region", "aria-labelledby": selectedHeadingId, children: [jsxs("div", { className: "tw:!border-b tw:!p-4", children: [jsx("h2", { id: selectedHeadingId, className: "tw:text-lg tw:!font-semibold tw:!mb-3", children: selectedLabel }), jsx(SearchBar, { value: selectedSearch, onChange: setSelectedSearch, onSearch: (term) => setSelectedSearchApplied(term), onClear: () => {
227
+ setSelectedSearch("");
228
+ setSelectedSearchApplied("");
229
+ }, placeholder: `Search ${selectedLabel.toLowerCase()}...`, inputAriaLabel: `Search within ${selectedLabel}` }), jsx("div", { className: "tw:!flex tw:!justify-end tw:!mt-3", children: jsx(Button, { size: "sm", onClick: handleRemoveSelected, disabled: selectedChecked.size === 0, variant: "destructive", className: selectedChecked.size === 0
230
+ ? "tw:!opacity-50 tw:!cursor-not-allowed"
231
+ : undefined, "aria-label": selectedChecked.size === 0
232
+ ? removeButtonLabel
233
+ : `${removeButtonLabel} (${selectedChecked.size} selected)`, children: removeButtonLabel }) })] }), jsx("div", { className: "tw:!flex-1 tw:!flex tw:!flex-col tw:!overflow-hidden", children: jsx(DataTable, { columns: selectedColumns ?? columns, data: paginatedSelectedItems, onSelectionChange: handleSelectedSelectionChange, selectedRowIds: Array.from(selectedChecked), treeData: false, className: "tw:!flex-1", reservePaginationSpace: true, selectContentClassName: "tw:!z-[1300]", menuPopupClassName: "tw:!z-[1300]", pagination: {
234
+ currentPage: selectedPage,
235
+ totalPages: selectedTotalPages,
236
+ onPageChange: setSelectedPage,
237
+ pageSize: selectedPageSize,
238
+ totalItems: selectedItemsData.length,
239
+ pageSizeOptions: [20, 40, 60, 80, 100],
240
+ onPageSizeChange: (size) => {
241
+ setSelectedPageSize(size);
242
+ setSelectedPage(1);
243
+ },
244
+ showTotalItems: true,
245
+ }, footerContent: jsxs("div", { className: "tw:text-sm tw:text-muted-foreground", "aria-live": "polite", role: "status", children: [selectedIds.size, " Selected"] }), emptyState: {
246
+ title: selectedEmptyMessage,
247
+ description: selectedSearchApplied
248
+ ? "Try adjusting your search"
249
+ : undefined,
250
+ } }) })] })] }), jsxs(SheetFooter, { className: "tw:!border-t tw:!flex tw:!flex-row tw:!justify-between tw:!items-center", children: [jsx(Button, { variant: "link", className: "tw:!text-primary tw:!px-0", onClick: handleClose, children: cancelButtonLabel }), jsx(Button, { onClick: handleDone, disabled: selectedIds.size === 0, className: selectedIds.size === 0
251
+ ? "tw:!opacity-50 tw:!cursor-not-allowed"
252
+ : undefined, children: doneButtonLabel })] })] })] }) }), jsx(AlertDialog, { open: showConfirmDialog, onOpenChange: setShowConfirmDialog, children: jsxs(AlertDialogContent, { className: "tw:!z-[1300]", overlayClassName: "tw:!z-[1300]", children: [jsxs(AlertDialogHeader, { children: [jsx(AlertDialogTitle, { children: "Unsaved Changes" }), jsx(AlertDialogDescription, { children: confirmCloseMessage })] }), jsxs(AlertDialogFooter, { children: [jsx(AlertDialogCancel, { onClick: () => setShowConfirmDialog(false), children: "Go Back" }), jsx(AlertDialogAction, { onClick: handleConfirmClose, children: "Exit Without Saving" })] })] }) })] }));
253
+ }
254
+
255
+ export { SelectionPanel };
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
3
+ declare function Separator({ className, orientation, decorative, ...props }: React.ComponentProps<typeof SeparatorPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ export { Separator };
5
+ //# sourceMappingURL=separator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../src/components/separator.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAA;AAI/D,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,WAA0B,EAC1B,UAAiB,EACjB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,2CAatD;AAED,OAAO,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
3
+ import { cn } from '../lib/utils.js';
4
+
5
+ function Separator({ className, orientation = "horizontal", decorative = true, ...props }) {
6
+ return (jsx(SeparatorPrimitive.Root, { "data-slot": "separator", decorative: decorative, orientation: orientation, className: cn("tw:bg-border tw:shrink-0 data-[orientation=horizontal]:tw:h-px data-[orientation=horizontal]:tw:w-full data-[orientation=vertical]:tw:h-full data-[orientation=vertical]:tw:w-px", className), ...props }));
7
+ }
8
+
9
+ export { Separator };