@inshorts/glint-ui 0.5.4 → 0.6.1

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 (340) hide show
  1. package/README.md +3 -1
  2. package/dist/alert.cjs +96 -0
  3. package/dist/alert.cjs.map +1 -0
  4. package/dist/alert.d.cts +29 -0
  5. package/dist/alert.d.ts +29 -0
  6. package/dist/alert.js +10 -0
  7. package/dist/alert.js.map +1 -0
  8. package/dist/autocomplete.cjs +578 -0
  9. package/dist/autocomplete.cjs.map +1 -0
  10. package/dist/autocomplete.d.cts +56 -0
  11. package/dist/autocomplete.d.ts +56 -0
  12. package/dist/autocomplete.js +11 -0
  13. package/dist/autocomplete.js.map +1 -0
  14. package/dist/badge.cjs +89 -0
  15. package/dist/badge.cjs.map +1 -0
  16. package/dist/badge.d.cts +25 -0
  17. package/dist/badge.d.ts +25 -0
  18. package/dist/badge.js +10 -0
  19. package/dist/badge.js.map +1 -0
  20. package/dist/breadcrumb.cjs +88 -0
  21. package/dist/breadcrumb.cjs.map +1 -0
  22. package/dist/breadcrumb.d.cts +14 -0
  23. package/dist/breadcrumb.d.ts +14 -0
  24. package/dist/breadcrumb.js +8 -0
  25. package/dist/breadcrumb.js.map +1 -0
  26. package/dist/button.cjs +143 -0
  27. package/dist/button.cjs.map +1 -0
  28. package/dist/button.d.cts +34 -0
  29. package/dist/button.d.ts +34 -0
  30. package/dist/button.js +9 -0
  31. package/dist/button.js.map +1 -0
  32. package/dist/card.cjs +111 -0
  33. package/dist/card.cjs.map +1 -0
  34. package/dist/card.d.cts +15 -0
  35. package/dist/card.d.ts +15 -0
  36. package/dist/card.js +18 -0
  37. package/dist/card.js.map +1 -0
  38. package/dist/checkbox.cjs +66 -0
  39. package/dist/checkbox.cjs.map +1 -0
  40. package/{src/checkbox.tsx → dist/checkbox.d.cts} +5 -22
  41. package/dist/checkbox.d.ts +25 -0
  42. package/dist/checkbox.js +10 -0
  43. package/dist/checkbox.js.map +1 -0
  44. package/dist/chunk-5MEOZHJA.js +513 -0
  45. package/dist/chunk-5MEOZHJA.js.map +1 -0
  46. package/dist/chunk-67ACNS42.js +29 -0
  47. package/dist/chunk-67ACNS42.js.map +1 -0
  48. package/dist/chunk-A6GRLKOO.js +85 -0
  49. package/dist/chunk-A6GRLKOO.js.map +1 -0
  50. package/dist/chunk-DS3QYIKL.js +90 -0
  51. package/dist/chunk-DS3QYIKL.js.map +1 -0
  52. package/dist/chunk-EWSBFU54.js +53 -0
  53. package/dist/chunk-EWSBFU54.js.map +1 -0
  54. package/dist/chunk-G4ZQUSAJ.js +38 -0
  55. package/dist/chunk-G4ZQUSAJ.js.map +1 -0
  56. package/dist/chunk-GMCUXEFI.js +67 -0
  57. package/dist/chunk-GMCUXEFI.js.map +1 -0
  58. package/dist/chunk-HBBOR43A.js +85 -0
  59. package/dist/chunk-HBBOR43A.js.map +1 -0
  60. package/dist/chunk-HCA5ODCD.js +11 -0
  61. package/dist/chunk-HCA5ODCD.js.map +1 -0
  62. package/dist/chunk-HYRJYUPI.js +26 -0
  63. package/dist/chunk-HYRJYUPI.js.map +1 -0
  64. package/dist/chunk-IRCTGJQB.js +26 -0
  65. package/dist/chunk-IRCTGJQB.js.map +1 -0
  66. package/dist/chunk-ISPICB4W.js +70 -0
  67. package/dist/chunk-ISPICB4W.js.map +1 -0
  68. package/dist/chunk-JDE5XYPT.js +30 -0
  69. package/dist/chunk-JDE5XYPT.js.map +1 -0
  70. package/dist/chunk-JSJEEKR3.js +59 -0
  71. package/dist/chunk-JSJEEKR3.js.map +1 -0
  72. package/dist/chunk-KR3BCFP7.js +85 -0
  73. package/dist/chunk-KR3BCFP7.js.map +1 -0
  74. package/dist/chunk-MLRSOTFI.js +81 -0
  75. package/dist/chunk-MLRSOTFI.js.map +1 -0
  76. package/dist/chunk-MQT5RAQV.js +202 -0
  77. package/dist/chunk-MQT5RAQV.js.map +1 -0
  78. package/dist/chunk-MUPW2TFJ.js +102 -0
  79. package/dist/chunk-MUPW2TFJ.js.map +1 -0
  80. package/dist/chunk-OUYT6SPU.js +76 -0
  81. package/dist/chunk-OUYT6SPU.js.map +1 -0
  82. package/dist/chunk-PM2VE7DJ.js +100 -0
  83. package/dist/chunk-PM2VE7DJ.js.map +1 -0
  84. package/dist/chunk-PPYR3O3L.js +44 -0
  85. package/dist/chunk-PPYR3O3L.js.map +1 -0
  86. package/dist/chunk-PUTC52SI.js +98 -0
  87. package/dist/chunk-PUTC52SI.js.map +1 -0
  88. package/dist/chunk-PWAKTEXF.js +18 -0
  89. package/dist/chunk-PWAKTEXF.js.map +1 -0
  90. package/dist/chunk-QTFWORA7.js +26 -0
  91. package/dist/chunk-QTFWORA7.js.map +1 -0
  92. package/dist/chunk-RUPL2H6V.js +49 -0
  93. package/dist/chunk-RUPL2H6V.js.map +1 -0
  94. package/dist/chunk-S7PVZAPL.js +28 -0
  95. package/dist/chunk-S7PVZAPL.js.map +1 -0
  96. package/dist/chunk-SQDV2AKJ.js +49 -0
  97. package/dist/chunk-SQDV2AKJ.js.map +1 -0
  98. package/dist/chunk-T2KXVH3O.js +297 -0
  99. package/dist/chunk-T2KXVH3O.js.map +1 -0
  100. package/dist/chunk-T4WCCHJQ.js +29 -0
  101. package/dist/chunk-T4WCCHJQ.js.map +1 -0
  102. package/dist/chunk-UC3ZIQPE.js +93 -0
  103. package/dist/chunk-UC3ZIQPE.js.map +1 -0
  104. package/dist/chunk-UE7JY7VR.js +28 -0
  105. package/dist/chunk-UE7JY7VR.js.map +1 -0
  106. package/dist/chunk-Y5WCT6XN.js +93 -0
  107. package/dist/chunk-Y5WCT6XN.js.map +1 -0
  108. package/dist/chunk-YDICVETX.js +151 -0
  109. package/dist/chunk-YDICVETX.js.map +1 -0
  110. package/dist/chunk-ZFSQVMLJ.js +126 -0
  111. package/dist/chunk-ZFSQVMLJ.js.map +1 -0
  112. package/dist/chunk-ZHATD73Y.js +46 -0
  113. package/dist/chunk-ZHATD73Y.js.map +1 -0
  114. package/dist/chunk-ZLAA4DGG.js +111 -0
  115. package/dist/chunk-ZLAA4DGG.js.map +1 -0
  116. package/dist/chunk-ZP252OJZ.js +56 -0
  117. package/dist/chunk-ZP252OJZ.js.map +1 -0
  118. package/dist/clipboard.cjs +125 -0
  119. package/dist/clipboard.cjs.map +1 -0
  120. package/dist/clipboard.d.cts +52 -0
  121. package/dist/clipboard.d.ts +52 -0
  122. package/dist/clipboard.js +23 -0
  123. package/dist/clipboard.js.map +1 -0
  124. package/dist/collapsible.cjs +94 -0
  125. package/dist/collapsible.cjs.map +1 -0
  126. package/dist/collapsible.d.cts +21 -0
  127. package/dist/collapsible.d.ts +21 -0
  128. package/dist/collapsible.js +9 -0
  129. package/dist/collapsible.js.map +1 -0
  130. package/dist/confirm-dialog.cjs +369 -0
  131. package/dist/confirm-dialog.cjs.map +1 -0
  132. package/dist/confirm-dialog.d.cts +16 -0
  133. package/dist/confirm-dialog.d.ts +16 -0
  134. package/dist/confirm-dialog.js +13 -0
  135. package/dist/confirm-dialog.js.map +1 -0
  136. package/dist/copy-button.cjs +102 -0
  137. package/dist/copy-button.cjs.map +1 -0
  138. package/dist/copy-button.d.cts +18 -0
  139. package/dist/copy-button.d.ts +18 -0
  140. package/dist/copy-button.js +10 -0
  141. package/dist/copy-button.js.map +1 -0
  142. package/dist/data-table.cjs +140 -0
  143. package/dist/data-table.cjs.map +1 -0
  144. package/dist/data-table.d.cts +81 -0
  145. package/dist/data-table.d.ts +81 -0
  146. package/dist/data-table.js +8 -0
  147. package/dist/data-table.js.map +1 -0
  148. package/dist/date-range-picker/dateRange.cjs +138 -0
  149. package/dist/date-range-picker/dateRange.cjs.map +1 -0
  150. package/dist/date-range-picker/dateRange.d.cts +57 -0
  151. package/dist/date-range-picker/dateRange.d.ts +57 -0
  152. package/dist/date-range-picker/dateRange.js +31 -0
  153. package/dist/date-range-picker/dateRange.js.map +1 -0
  154. package/dist/date-range-picker/index.cjs +375 -0
  155. package/dist/date-range-picker/index.cjs.map +1 -0
  156. package/dist/date-range-picker/index.d.cts +18 -0
  157. package/dist/date-range-picker/index.d.ts +18 -0
  158. package/dist/date-range-picker/index.js +10 -0
  159. package/dist/date-range-picker/index.js.map +1 -0
  160. package/dist/dialogLayer.cjs +121 -0
  161. package/dist/dialogLayer.cjs.map +1 -0
  162. package/dist/dialogLayer.d.cts +11 -0
  163. package/dist/dialogLayer.d.ts +11 -0
  164. package/dist/dialogLayer.js +8 -0
  165. package/dist/dialogLayer.js.map +1 -0
  166. package/dist/feature-access-gate.cjs +160 -0
  167. package/dist/feature-access-gate.cjs.map +1 -0
  168. package/dist/feature-access-gate.d.cts +14 -0
  169. package/dist/feature-access-gate.d.ts +14 -0
  170. package/dist/feature-access-gate.js +11 -0
  171. package/dist/feature-access-gate.js.map +1 -0
  172. package/dist/field.cjs +58 -0
  173. package/dist/field.cjs.map +1 -0
  174. package/dist/field.d.cts +23 -0
  175. package/dist/field.d.ts +23 -0
  176. package/dist/field.js +8 -0
  177. package/dist/field.js.map +1 -0
  178. package/dist/image-uploader.cjs +293 -0
  179. package/dist/image-uploader.cjs.map +1 -0
  180. package/dist/image-uploader.d.cts +34 -0
  181. package/dist/image-uploader.d.ts +34 -0
  182. package/dist/image-uploader.js +12 -0
  183. package/dist/image-uploader.js.map +1 -0
  184. package/dist/index.cjs +3008 -0
  185. package/dist/index.cjs.map +1 -0
  186. package/dist/index.d.cts +41 -0
  187. package/dist/index.d.ts +41 -0
  188. package/dist/index.js +232 -0
  189. package/dist/index.js.map +1 -0
  190. package/dist/input.cjs +58 -0
  191. package/dist/input.cjs.map +1 -0
  192. package/dist/input.d.cts +7 -0
  193. package/dist/input.d.ts +7 -0
  194. package/dist/input.js +10 -0
  195. package/dist/input.js.map +1 -0
  196. package/dist/label.cjs +67 -0
  197. package/dist/label.cjs.map +1 -0
  198. package/dist/label.d.cts +7 -0
  199. package/dist/label.d.ts +7 -0
  200. package/dist/label.js +9 -0
  201. package/dist/label.js.map +1 -0
  202. package/dist/modal.cjs +212 -0
  203. package/dist/modal.cjs.map +1 -0
  204. package/dist/modal.d.cts +39 -0
  205. package/dist/modal.d.ts +39 -0
  206. package/dist/modal.js +12 -0
  207. package/dist/modal.js.map +1 -0
  208. package/dist/page-header.cjs +78 -0
  209. package/dist/page-header.cjs.map +1 -0
  210. package/dist/page-header.d.cts +35 -0
  211. package/dist/page-header.d.ts +35 -0
  212. package/dist/page-header.js +8 -0
  213. package/dist/page-header.js.map +1 -0
  214. package/dist/pagination.cjs +237 -0
  215. package/dist/pagination.cjs.map +1 -0
  216. package/dist/pagination.d.cts +15 -0
  217. package/dist/pagination.d.ts +15 -0
  218. package/dist/pagination.js +11 -0
  219. package/dist/pagination.js.map +1 -0
  220. package/dist/panel-brand-mark.cjs +59 -0
  221. package/dist/panel-brand-mark.cjs.map +1 -0
  222. package/dist/panel-brand-mark.d.cts +13 -0
  223. package/dist/panel-brand-mark.d.ts +13 -0
  224. package/dist/panel-brand-mark.js +8 -0
  225. package/dist/panel-brand-mark.js.map +1 -0
  226. package/dist/panel-sign-in.cjs +256 -0
  227. package/dist/panel-sign-in.cjs.map +1 -0
  228. package/dist/panel-sign-in.d.cts +31 -0
  229. package/dist/panel-sign-in.d.ts +31 -0
  230. package/dist/panel-sign-in.js +14 -0
  231. package/dist/panel-sign-in.js.map +1 -0
  232. package/dist/segmented-control.cjs +122 -0
  233. package/dist/segmented-control.cjs.map +1 -0
  234. package/dist/segmented-control.d.cts +58 -0
  235. package/dist/segmented-control.d.ts +58 -0
  236. package/dist/segmented-control.js +9 -0
  237. package/dist/segmented-control.js.map +1 -0
  238. package/dist/select.cjs +648 -0
  239. package/dist/select.cjs.map +1 -0
  240. package/dist/select.d.cts +30 -0
  241. package/dist/select.d.ts +30 -0
  242. package/dist/select.js +12 -0
  243. package/dist/select.js.map +1 -0
  244. package/dist/separator.cjs +70 -0
  245. package/dist/separator.cjs.map +1 -0
  246. package/dist/separator.d.cts +13 -0
  247. package/dist/separator.d.ts +13 -0
  248. package/dist/separator.js +9 -0
  249. package/dist/separator.js.map +1 -0
  250. package/dist/side-drawer.cjs +321 -0
  251. package/dist/side-drawer.cjs.map +1 -0
  252. package/dist/side-drawer.d.cts +21 -0
  253. package/dist/side-drawer.d.ts +21 -0
  254. package/dist/side-drawer.js +13 -0
  255. package/dist/side-drawer.js.map +1 -0
  256. package/dist/spinner.cjs +57 -0
  257. package/dist/spinner.cjs.map +1 -0
  258. package/{src/spinner.tsx → dist/spinner.d.cts} +11 -22
  259. package/dist/spinner.d.ts +27 -0
  260. package/dist/spinner.js +8 -0
  261. package/dist/spinner.js.map +1 -0
  262. package/dist/spreadsheet-grid.cjs +238 -0
  263. package/dist/spreadsheet-grid.cjs.map +1 -0
  264. package/dist/spreadsheet-grid.d.cts +48 -0
  265. package/dist/spreadsheet-grid.d.ts +48 -0
  266. package/dist/spreadsheet-grid.js +8 -0
  267. package/dist/spreadsheet-grid.js.map +1 -0
  268. package/dist/state-panel.cjs +86 -0
  269. package/dist/state-panel.cjs.map +1 -0
  270. package/dist/state-panel.d.cts +23 -0
  271. package/dist/state-panel.d.ts +23 -0
  272. package/dist/state-panel.js +9 -0
  273. package/dist/state-panel.js.map +1 -0
  274. package/dist/switch.cjs +87 -0
  275. package/dist/switch.cjs.map +1 -0
  276. package/dist/switch.d.cts +13 -0
  277. package/dist/switch.d.ts +13 -0
  278. package/dist/switch.js +9 -0
  279. package/dist/switch.js.map +1 -0
  280. package/dist/table.cjs +139 -0
  281. package/dist/table.cjs.map +1 -0
  282. package/dist/table.d.cts +16 -0
  283. package/dist/table.d.ts +16 -0
  284. package/dist/table.js +22 -0
  285. package/dist/table.js.map +1 -0
  286. package/dist/tabs.cjs +168 -0
  287. package/dist/tabs.cjs.map +1 -0
  288. package/dist/tabs.d.cts +59 -0
  289. package/dist/tabs.d.ts +59 -0
  290. package/dist/tabs.js +11 -0
  291. package/dist/tabs.js.map +1 -0
  292. package/dist/textarea.cjs +66 -0
  293. package/dist/textarea.cjs.map +1 -0
  294. package/dist/textarea.d.cts +18 -0
  295. package/dist/textarea.d.ts +18 -0
  296. package/dist/textarea.js +10 -0
  297. package/dist/textarea.js.map +1 -0
  298. package/dist/utils.cjs +35 -0
  299. package/dist/utils.cjs.map +1 -0
  300. package/dist/utils.d.cts +5 -0
  301. package/dist/utils.d.ts +5 -0
  302. package/dist/utils.js +7 -0
  303. package/dist/utils.js.map +1 -0
  304. package/package.json +391 -14
  305. package/src/alert.tsx +0 -74
  306. package/src/autocomplete.tsx +0 -666
  307. package/src/badge.tsx +0 -60
  308. package/src/breadcrumb.tsx +0 -71
  309. package/src/button.tsx +0 -113
  310. package/src/card.tsx +0 -79
  311. package/src/clipboard.ts +0 -144
  312. package/src/collapsible.tsx +0 -63
  313. package/src/confirm-dialog.tsx +0 -84
  314. package/src/copy-button.tsx +0 -58
  315. package/src/data-table.tsx +0 -190
  316. package/src/date-range-picker/dateRange.ts +0 -142
  317. package/src/date-range-picker/index.tsx +0 -366
  318. package/src/dialogLayer.ts +0 -142
  319. package/src/feature-access-gate.tsx +0 -38
  320. package/src/field.tsx +0 -56
  321. package/src/image-uploader.tsx +0 -181
  322. package/src/index.ts +0 -37
  323. package/src/input.tsx +0 -16
  324. package/src/label.tsx +0 -23
  325. package/src/modal.tsx +0 -117
  326. package/src/page-header.tsx +0 -75
  327. package/src/pagination.tsx +0 -116
  328. package/src/panel-brand-mark.tsx +0 -32
  329. package/src/panel-sign-in.tsx +0 -134
  330. package/src/segmented-control.tsx +0 -155
  331. package/src/select.tsx +0 -105
  332. package/src/separator.tsx +0 -32
  333. package/src/side-drawer.tsx +0 -87
  334. package/src/spreadsheet-grid.tsx +0 -264
  335. package/src/state-panel.tsx +0 -46
  336. package/src/switch.tsx +0 -47
  337. package/src/table.tsx +0 -110
  338. package/src/tabs.tsx +0 -201
  339. package/src/textarea.tsx +0 -32
  340. package/src/utils.ts +0 -6
package/dist/index.cjs ADDED
@@ -0,0 +1,3008 @@
1
+ "use client";
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ Alert: () => Alert,
35
+ Autocomplete: () => Autocomplete,
36
+ Badge: () => Badge,
37
+ Breadcrumb: () => Breadcrumb,
38
+ Button: () => Button,
39
+ CSV_DELIMITER: () => CSV_DELIMITER,
40
+ Card: () => Card,
41
+ CardContent: () => CardContent,
42
+ CardDescription: () => CardDescription,
43
+ CardFooter: () => CardFooter,
44
+ CardHeader: () => CardHeader,
45
+ CardTitle: () => CardTitle,
46
+ Checkbox: () => Checkbox,
47
+ CollapsibleSection: () => CollapsibleSection,
48
+ ConfirmDialog: () => ConfirmDialog,
49
+ CopyButton: () => CopyButton,
50
+ DataTable: () => DataTable,
51
+ DateRangePicker: () => DateRangePicker,
52
+ FeatureAccessGate: () => FeatureAccessGate,
53
+ Field: () => Field,
54
+ ImageUploader: () => ImageUploader,
55
+ Input: () => Input,
56
+ Label: () => Label,
57
+ Modal: () => Modal,
58
+ PageHeader: () => PageHeader,
59
+ Pagination: () => Pagination,
60
+ PanelBrandMark: () => PanelBrandMark,
61
+ PanelSignIn: () => PanelSignIn,
62
+ PanelSignInSkeleton: () => PanelSignInSkeleton,
63
+ SegmentedControl: () => SegmentedControl,
64
+ Select: () => Select,
65
+ Separator: () => Separator,
66
+ SideDrawer: () => SideDrawer,
67
+ Spinner: () => Spinner,
68
+ SpreadsheetGrid: () => SpreadsheetGrid,
69
+ StatePanel: () => StatePanel,
70
+ Switch: () => Switch,
71
+ TSV_DELIMITER: () => TSV_DELIMITER,
72
+ TabPanel: () => TabPanel,
73
+ Table: () => Table,
74
+ TableBody: () => TableBody,
75
+ TableCaption: () => TableCaption,
76
+ TableCell: () => TableCell,
77
+ TableFooter: () => TableFooter,
78
+ TableHead: () => TableHead,
79
+ TableHeader: () => TableHeader,
80
+ TableRow: () => TableRow,
81
+ Tabs: () => Tabs,
82
+ Textarea: () => Textarea,
83
+ addDays: () => addDays,
84
+ addMonths: () => addMonths,
85
+ alertVariants: () => alertVariants,
86
+ badgeVariants: () => badgeVariants,
87
+ buildRangeText: () => buildRangeText,
88
+ checkboxClass: () => checkboxClass,
89
+ cn: () => cn,
90
+ countCells: () => countCells,
91
+ createdRangeMs: () => createdRangeMs,
92
+ describeRange: () => describeRange,
93
+ endAt2359Ms: () => endAt2359Ms,
94
+ endOfDayMs: () => endOfDayMs,
95
+ escapeCell: () => escapeCell,
96
+ formatDisplay: () => formatDisplay,
97
+ fromIsoDate: () => fromIsoDate,
98
+ fullRange: () => fullRange,
99
+ inputClass: () => inputClass,
100
+ isSameDay: () => isSameDay,
101
+ monthGrid: () => monthGrid,
102
+ monthLabel: () => monthLabel,
103
+ normalizeRange: () => normalizeRange,
104
+ startOfDayMs: () => startOfDayMs,
105
+ startOfMonth: () => startOfMonth,
106
+ textareaClass: () => textareaClass,
107
+ toIsoDate: () => toIsoDate,
108
+ useDialogLayer: () => useDialogLayer,
109
+ useHasMounted: () => useHasMounted,
110
+ writeToClipboard: () => writeToClipboard
111
+ });
112
+ module.exports = __toCommonJS(index_exports);
113
+
114
+ // src/alert.tsx
115
+ var React = __toESM(require("react"), 1);
116
+ var import_class_variance_authority = require("class-variance-authority");
117
+
118
+ // src/utils.ts
119
+ var import_clsx = require("clsx");
120
+ var import_tailwind_merge = require("tailwind-merge");
121
+ function cn(...inputs) {
122
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
123
+ }
124
+
125
+ // src/alert.tsx
126
+ var import_jsx_runtime = require("react/jsx-runtime");
127
+ var alertVariants = (0, import_class_variance_authority.cva)("rounded-lg border px-3 py-2 text-sm", {
128
+ variants: {
129
+ variant: {
130
+ danger: "border-destructive/30 bg-destructive/5 text-destructive",
131
+ warning: "border-warning/30 bg-warning/5 text-warning",
132
+ success: "border-success/30 bg-success/5 text-success",
133
+ info: "border-info/30 bg-info/5 text-info",
134
+ /**
135
+ * The quiet state of a banner that also has loud ones — "no default
136
+ * campaign set" next to "this is the default". Without it those callers
137
+ * keep a ternary of raw class strings and the shared component only
138
+ * covers half of what they draw.
139
+ */
140
+ neutral: "border-border bg-muted/40 text-muted-foreground"
141
+ }
142
+ },
143
+ defaultVariants: {
144
+ // Failure is what a banner almost always reports here, and defaulting to
145
+ // it means the noisy case cannot be forgotten.
146
+ variant: "danger"
147
+ }
148
+ });
149
+ var Alert = React.forwardRef(
150
+ ({ className, variant, action, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
151
+ "div",
152
+ {
153
+ ref,
154
+ role: variant === "danger" || variant == null ? "alert" : "status",
155
+ className: cn(
156
+ alertVariants({ variant }),
157
+ action && "flex flex-wrap items-center justify-between gap-3",
158
+ className
159
+ ),
160
+ ...props,
161
+ children: [
162
+ action ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children }) : children,
163
+ action
164
+ ]
165
+ }
166
+ )
167
+ );
168
+ Alert.displayName = "Alert";
169
+
170
+ // src/autocomplete.tsx
171
+ var React4 = __toESM(require("react"), 1);
172
+ var import_react_dom2 = require("react-dom");
173
+ var import_lucide_react = require("lucide-react");
174
+
175
+ // src/modal.tsx
176
+ var React3 = __toESM(require("react"), 1);
177
+ var import_react_dom = require("react-dom");
178
+
179
+ // src/dialogLayer.ts
180
+ var React2 = __toESM(require("react"), 1);
181
+ var layers = [];
182
+ var FOCUSABLE = [
183
+ "a[href]",
184
+ "button:not([disabled])",
185
+ "input:not([disabled])",
186
+ "select:not([disabled])",
187
+ "textarea:not([disabled])",
188
+ '[tabindex]:not([tabindex="-1"])'
189
+ ].join(",");
190
+ function isVisible(element) {
191
+ if (element.closest("[hidden]")) return false;
192
+ if (element.getAttribute("aria-hidden") === "true") return false;
193
+ return typeof element.checkVisibility === "function" ? element.checkVisibility() : true;
194
+ }
195
+ function focusableWithin(container) {
196
+ return Array.from(container.querySelectorAll(FOCUSABLE)).filter(
197
+ isVisible
198
+ );
199
+ }
200
+ function useDialogLayer({
201
+ active,
202
+ containerRef,
203
+ onEscape
204
+ }) {
205
+ const escapeRef = React2.useRef(onEscape);
206
+ React2.useEffect(() => {
207
+ escapeRef.current = onEscape;
208
+ });
209
+ React2.useEffect(() => {
210
+ if (!active) return;
211
+ const layer = /* @__PURE__ */ Symbol("dialog-layer");
212
+ layers.push(layer);
213
+ const isTopLayer = () => layers[layers.length - 1] === layer;
214
+ const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
215
+ const container = containerRef.current;
216
+ if (container && !container.contains(document.activeElement)) {
217
+ const [first] = focusableWithin(container);
218
+ (container.hasAttribute("tabindex") ? container : first)?.focus();
219
+ }
220
+ function handleKeyDown(event) {
221
+ if (!isTopLayer()) return;
222
+ if (event.key === "Escape") {
223
+ escapeRef.current?.();
224
+ return;
225
+ }
226
+ if (event.key !== "Tab") return;
227
+ const panel = containerRef.current;
228
+ if (!panel) return;
229
+ const items = focusableWithin(panel);
230
+ if (items.length === 0) {
231
+ event.preventDefault();
232
+ panel.focus();
233
+ return;
234
+ }
235
+ const first = items[0];
236
+ const last = items[items.length - 1];
237
+ const active2 = document.activeElement;
238
+ const outside = !panel.contains(active2);
239
+ if (event.shiftKey && (active2 === first || outside)) {
240
+ event.preventDefault();
241
+ last.focus();
242
+ } else if (!event.shiftKey && (active2 === last || outside)) {
243
+ event.preventDefault();
244
+ first.focus();
245
+ }
246
+ }
247
+ document.addEventListener("keydown", handleKeyDown);
248
+ const previousOverflow = document.body.style.overflow;
249
+ document.body.style.overflow = "hidden";
250
+ return () => {
251
+ document.removeEventListener("keydown", handleKeyDown);
252
+ document.body.style.overflow = previousOverflow;
253
+ const index = layers.indexOf(layer);
254
+ if (index !== -1) layers.splice(index, 1);
255
+ if (previouslyFocused?.isConnected) previouslyFocused.focus();
256
+ };
257
+ }, [active, containerRef]);
258
+ }
259
+
260
+ // src/modal.tsx
261
+ var import_jsx_runtime2 = (
262
+ /*
263
+ `overflow-y-auto` on the overlay, `my-auto` on the panel — not
264
+ `items-center`. A flex item centred with `align-items` overflows equally
265
+ in both directions once it is taller than its container, and the half
266
+ above the top edge cannot be scrolled to: with the page behind it locked,
267
+ an over-tall dialog was simply unreachable at both ends. Auto margins
268
+ centre a short panel the same way and collapse to zero on a tall one,
269
+ which scrolls.
270
+ */
271
+ require("react/jsx-runtime")
272
+ );
273
+ var emptySubscribe = () => () => {
274
+ };
275
+ function useHasMounted() {
276
+ return React3.useSyncExternalStore(
277
+ emptySubscribe,
278
+ () => true,
279
+ () => false
280
+ );
281
+ }
282
+ function Modal({
283
+ isOpen,
284
+ labelledBy,
285
+ describedBy,
286
+ closeLabel,
287
+ onClose,
288
+ children,
289
+ dismissible = true,
290
+ role = "dialog",
291
+ panelClassName
292
+ }) {
293
+ const mounted = useHasMounted();
294
+ const panelRef = React3.useRef(null);
295
+ useDialogLayer({
296
+ // Gated on `mounted` too: before that the panel is not rendered, so there
297
+ // would be nothing to move focus into.
298
+ active: isOpen && mounted,
299
+ containerRef: panelRef,
300
+ onEscape: dismissible ? onClose : void 0
301
+ });
302
+ if (!mounted || !isOpen) return null;
303
+ return (0, import_react_dom.createPortal)(
304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fixed inset-0 z-[100] flex justify-center overflow-y-auto p-4", children: [
305
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
306
+ "button",
307
+ {
308
+ type: "button",
309
+ "aria-label": closeLabel,
310
+ tabIndex: -1,
311
+ className: "fixed inset-0 bg-overlay/50",
312
+ onClick: () => {
313
+ if (dismissible) onClose();
314
+ }
315
+ }
316
+ ),
317
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
318
+ "div",
319
+ {
320
+ ref: panelRef,
321
+ role,
322
+ "aria-modal": "true",
323
+ "aria-labelledby": labelledBy,
324
+ "aria-describedby": describedBy,
325
+ tabIndex: -1,
326
+ className: cn(
327
+ "border-border bg-background relative z-10 my-auto w-full rounded-lg border shadow-2xl outline-none",
328
+ panelClassName ?? "max-w-md p-6"
329
+ ),
330
+ children
331
+ }
332
+ )
333
+ ] }),
334
+ document.body
335
+ );
336
+ }
337
+
338
+ // src/autocomplete.tsx
339
+ var import_jsx_runtime3 = require("react/jsx-runtime");
340
+ var PREFERRED_LIST_HEIGHT = 224;
341
+ var MIN_LIST_HEIGHT = 120;
342
+ var VIEWPORT_MARGIN = 8;
343
+ var ANCHOR_GAP = 4;
344
+ function normalizeQuery(query) {
345
+ return query.trim().toLowerCase();
346
+ }
347
+ function filterOptions(options, query) {
348
+ const normalized = normalizeQuery(query);
349
+ if (!normalized) return options;
350
+ return options.filter(
351
+ (option) => option.label.toLowerCase().includes(normalized) || option.value.toLowerCase().includes(normalized)
352
+ );
353
+ }
354
+ function getOptionLabel(options, value) {
355
+ return options.find((option) => option.value === value)?.label ?? value;
356
+ }
357
+ function parseTagTokens(raw) {
358
+ const seen = /* @__PURE__ */ new Set();
359
+ const tokens = [];
360
+ for (const part of raw.split(/[\s,]+/)) {
361
+ const token = part.trim();
362
+ if (!token || seen.has(token)) continue;
363
+ seen.add(token);
364
+ tokens.push(token);
365
+ }
366
+ return tokens;
367
+ }
368
+ function Autocomplete(props) {
369
+ const {
370
+ options,
371
+ placeholder = "Search\u2026",
372
+ disabled = false,
373
+ className,
374
+ emptyMessage = "No results found",
375
+ id,
376
+ ariaLabel,
377
+ size = "default",
378
+ creatable = false,
379
+ clearable = true
380
+ } = props;
381
+ const multiple = props.multiple ?? false;
382
+ const singleValue = multiple ? void 0 : props.value;
383
+ const multipleValue = multiple ? props.value : void 0;
384
+ const selectedValues = React4.useMemo(() => {
385
+ if (multiple) return multipleValue ?? [];
386
+ return singleValue ? [singleValue] : [];
387
+ }, [multiple, multipleValue, singleValue]);
388
+ const onSingleChange = !multiple ? props.onChange : void 0;
389
+ const onMultipleChange = multiple ? props.onChange : void 0;
390
+ const containerRef = React4.useRef(null);
391
+ const dropdownRef = React4.useRef(null);
392
+ const inputRef = React4.useRef(null);
393
+ const listRef = React4.useRef(null);
394
+ const ignoreBlurRef = React4.useRef(false);
395
+ const mounted = useHasMounted();
396
+ const [open, setOpen] = React4.useState(false);
397
+ const [position, setPosition] = React4.useState(null);
398
+ const [query, setQuery] = React4.useState("");
399
+ const [highlightedIndex, setHighlightedIndex] = React4.useState(0);
400
+ const filteredOptions = React4.useMemo(
401
+ () => filterOptions(options, query),
402
+ [options, query]
403
+ );
404
+ const safeHighlightedIndex = highlightedIndex >= filteredOptions.length ? Math.max(filteredOptions.length - 1, 0) : highlightedIndex;
405
+ const close = React4.useCallback(() => {
406
+ setOpen(false);
407
+ setQuery("");
408
+ setHighlightedIndex(0);
409
+ }, []);
410
+ const openDropdown = React4.useCallback(() => {
411
+ if (disabled) return;
412
+ setOpen(true);
413
+ setHighlightedIndex(0);
414
+ }, [disabled]);
415
+ const commitSingleValue = React4.useCallback(
416
+ (value) => {
417
+ if (!multiple) {
418
+ onSingleChange?.(value);
419
+ close();
420
+ }
421
+ },
422
+ [close, multiple, onSingleChange]
423
+ );
424
+ const toggleMultipleValue = React4.useCallback(
425
+ (value) => {
426
+ if (!multiple || !onMultipleChange) return;
427
+ onMultipleChange(
428
+ selectedValues.includes(value) ? selectedValues.filter((item) => item !== value) : [...selectedValues, value]
429
+ );
430
+ setQuery("");
431
+ setHighlightedIndex(0);
432
+ },
433
+ [multiple, onMultipleChange, selectedValues]
434
+ );
435
+ const commitCustomValues = React4.useCallback(
436
+ (raw) => {
437
+ if (!creatable) return;
438
+ if (!multiple) {
439
+ const value = raw.trim();
440
+ if (!value) return;
441
+ commitSingleValue(value);
442
+ return;
443
+ }
444
+ if (!onMultipleChange) return;
445
+ const tokens = parseTagTokens(raw);
446
+ if (!tokens.length) return;
447
+ const next = [...selectedValues];
448
+ for (const token of tokens) {
449
+ if (!next.includes(token)) next.push(token);
450
+ }
451
+ onMultipleChange(next);
452
+ setQuery("");
453
+ setHighlightedIndex(0);
454
+ },
455
+ [commitSingleValue, creatable, multiple, onMultipleChange, selectedValues]
456
+ );
457
+ const removeValue = React4.useCallback(
458
+ (value) => {
459
+ if (!multiple || !onMultipleChange) return;
460
+ onMultipleChange(selectedValues.filter((item) => item !== value));
461
+ window.requestAnimationFrame(() => inputRef.current?.focus());
462
+ },
463
+ [multiple, onMultipleChange, selectedValues]
464
+ );
465
+ const selectOption = React4.useCallback(
466
+ (option) => {
467
+ if (option.disabled) return;
468
+ ignoreBlurRef.current = true;
469
+ window.setTimeout(() => {
470
+ ignoreBlurRef.current = false;
471
+ }, 0);
472
+ if (multiple) {
473
+ toggleMultipleValue(option.value);
474
+ window.requestAnimationFrame(() => inputRef.current?.focus());
475
+ return;
476
+ }
477
+ commitSingleValue(option.value);
478
+ },
479
+ [commitSingleValue, multiple, toggleMultipleValue]
480
+ );
481
+ const selectHighlighted = React4.useCallback(() => {
482
+ const option = filteredOptions[safeHighlightedIndex];
483
+ if (!option) return;
484
+ selectOption(option);
485
+ }, [filteredOptions, safeHighlightedIndex, selectOption]);
486
+ React4.useEffect(() => {
487
+ if (!open) return;
488
+ function handlePointerDown(event) {
489
+ const target = event.target;
490
+ if (containerRef.current?.contains(target) || dropdownRef.current?.contains(target)) {
491
+ return;
492
+ }
493
+ close();
494
+ }
495
+ document.addEventListener("pointerdown", handlePointerDown);
496
+ return () => document.removeEventListener("pointerdown", handlePointerDown);
497
+ }, [close, open]);
498
+ React4.useLayoutEffect(() => {
499
+ if (!open) return;
500
+ const update = () => {
501
+ const anchor = containerRef.current;
502
+ if (!anchor) return;
503
+ const rect = anchor.getBoundingClientRect();
504
+ const below = window.innerHeight - rect.bottom - ANCHOR_GAP - VIEWPORT_MARGIN;
505
+ const above = rect.top - ANCHOR_GAP - VIEWPORT_MARGIN;
506
+ const flip = below < Math.min(PREFERRED_LIST_HEIGHT, MIN_LIST_HEIGHT) && above > below;
507
+ const room = flip ? above : below;
508
+ const width = Math.max(rect.width, size === "compact" ? 220 : 0);
509
+ const left = Math.max(
510
+ VIEWPORT_MARGIN,
511
+ Math.min(rect.left, window.innerWidth - width - VIEWPORT_MARGIN)
512
+ );
513
+ setPosition({
514
+ left,
515
+ width,
516
+ maxHeight: Math.max(
517
+ MIN_LIST_HEIGHT,
518
+ Math.min(PREFERRED_LIST_HEIGHT, room)
519
+ ),
520
+ ...flip ? { bottom: window.innerHeight - rect.top + ANCHOR_GAP } : { top: rect.bottom + ANCHOR_GAP }
521
+ });
522
+ };
523
+ update();
524
+ window.addEventListener("scroll", update, true);
525
+ window.addEventListener("resize", update);
526
+ return () => {
527
+ window.removeEventListener("scroll", update, true);
528
+ window.removeEventListener("resize", update);
529
+ };
530
+ }, [open, size]);
531
+ React4.useEffect(() => {
532
+ if (!open || !listRef.current) return;
533
+ const highlighted = listRef.current.children[safeHighlightedIndex];
534
+ highlighted?.scrollIntoView({ block: "nearest" });
535
+ }, [safeHighlightedIndex, open]);
536
+ function handleInputKeyDown(event) {
537
+ if (disabled) return;
538
+ switch (event.key) {
539
+ case "ArrowDown":
540
+ event.preventDefault();
541
+ if (!open) {
542
+ openDropdown();
543
+ return;
544
+ }
545
+ setHighlightedIndex(
546
+ Math.min(safeHighlightedIndex + 1, filteredOptions.length - 1)
547
+ );
548
+ break;
549
+ case "ArrowUp":
550
+ event.preventDefault();
551
+ if (!open) {
552
+ openDropdown();
553
+ return;
554
+ }
555
+ setHighlightedIndex(Math.max(safeHighlightedIndex - 1, 0));
556
+ break;
557
+ case "Enter":
558
+ event.preventDefault();
559
+ if (creatable && query.trim()) {
560
+ if (multiple || filteredOptions.length === 0) {
561
+ commitCustomValues(query);
562
+ return;
563
+ }
564
+ }
565
+ if (!open) {
566
+ openDropdown();
567
+ return;
568
+ }
569
+ selectHighlighted();
570
+ break;
571
+ case ",":
572
+ if (creatable && multiple && query.trim()) {
573
+ event.preventDefault();
574
+ commitCustomValues(query);
575
+ }
576
+ break;
577
+ case "Escape":
578
+ event.preventDefault();
579
+ close();
580
+ break;
581
+ case "Backspace":
582
+ if (multiple && query.length === 0 && selectedValues.length > 0) {
583
+ event.preventDefault();
584
+ removeValue(selectedValues[selectedValues.length - 1]);
585
+ }
586
+ break;
587
+ case "Tab":
588
+ close();
589
+ break;
590
+ default:
591
+ break;
592
+ }
593
+ }
594
+ const displayValue = !multiple && !open && !query && selectedValues[0] ? getOptionLabel(options, selectedValues[0]) : query;
595
+ const inputPlaceholder = multiple && selectedValues.length > 0 ? "" : placeholder;
596
+ const createLabel = query.trim();
597
+ const canCreate = creatable && Boolean(createLabel) && !selectedValues.includes(createLabel);
598
+ const listboxId = id ? `${id}-listbox` : void 0;
599
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
600
+ "div",
601
+ {
602
+ ref: containerRef,
603
+ className: cn(
604
+ "relative",
605
+ size === "compact" ? "w-auto min-w-24" : "w-full",
606
+ className
607
+ ),
608
+ children: [
609
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
610
+ "div",
611
+ {
612
+ className: cn(
613
+ "border-border bg-background flex w-full cursor-pointer items-center rounded-md border transition-colors",
614
+ "focus-within:border-ring focus-within:ring-ring/30 focus-within:ring-2",
615
+ size === "compact" ? "min-h-0 gap-0.5 border-transparent bg-transparent px-1 py-0.5 text-xs shadow-none" : "min-h-9 gap-1.5 px-2 py-1.5 text-sm shadow-sm",
616
+ disabled && "cursor-not-allowed opacity-50",
617
+ open && "border-ring ring-ring/30 ring-2"
618
+ ),
619
+ onPointerDown: (event) => {
620
+ if (disabled) return;
621
+ if (event.target.closest("[data-option]")) return;
622
+ if (event.target.closest("[data-chip-remove]"))
623
+ return;
624
+ if (!event.target.closest("input")) {
625
+ event.preventDefault();
626
+ inputRef.current?.focus();
627
+ }
628
+ openDropdown();
629
+ },
630
+ children: [
631
+ size === "compact" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Search, { className: "text-muted-foreground size-4 shrink-0" }),
632
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1", children: [
633
+ multiple && selectedValues.map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
634
+ "span",
635
+ {
636
+ className: "bg-primary/10 text-primary inline-flex max-w-full items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium",
637
+ children: [
638
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate", children: getOptionLabel(options, value) }),
639
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
640
+ "button",
641
+ {
642
+ type: "button",
643
+ "data-chip-remove": true,
644
+ className: "text-primary/70 hover:bg-primary/15 hover:text-primary rounded-sm transition",
645
+ onPointerDown: (event) => {
646
+ event.preventDefault();
647
+ event.stopPropagation();
648
+ removeValue(value);
649
+ },
650
+ "aria-label": `Remove ${getOptionLabel(options, value)}`,
651
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.X, { className: "size-3" })
652
+ }
653
+ )
654
+ ]
655
+ },
656
+ value
657
+ )),
658
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
659
+ "input",
660
+ {
661
+ ref: inputRef,
662
+ id,
663
+ type: "text",
664
+ role: "combobox",
665
+ "aria-label": ariaLabel,
666
+ "aria-expanded": open,
667
+ "aria-controls": listboxId,
668
+ "aria-autocomplete": "list",
669
+ disabled,
670
+ value: displayValue,
671
+ placeholder: inputPlaceholder,
672
+ className: cn(
673
+ "placeholder:text-muted-foreground flex-1 bg-transparent outline-none",
674
+ size === "compact" ? "min-w-0" : "min-w-[6rem]"
675
+ ),
676
+ onFocus: openDropdown,
677
+ onBlur: () => {
678
+ if (ignoreBlurRef.current) return;
679
+ close();
680
+ },
681
+ onChange: (event) => {
682
+ setQuery(event.target.value);
683
+ setHighlightedIndex(0);
684
+ if (!open) setOpen(true);
685
+ },
686
+ onKeyDown: handleInputKeyDown,
687
+ onPaste: (event) => {
688
+ if (!creatable || !multiple) return;
689
+ const text = event.clipboardData.getData("text");
690
+ if (!/[\s,]/.test(text)) return;
691
+ event.preventDefault();
692
+ commitCustomValues(text);
693
+ }
694
+ }
695
+ )
696
+ ] }),
697
+ clearable && !multiple && selectedValues[0] && !disabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
698
+ "button",
699
+ {
700
+ type: "button",
701
+ className: "text-muted-foreground hover:bg-muted hover:text-foreground rounded-sm p-0.5 transition",
702
+ onPointerDown: (event) => {
703
+ event.preventDefault();
704
+ event.stopPropagation();
705
+ onSingleChange?.("");
706
+ setQuery("");
707
+ inputRef.current?.focus();
708
+ },
709
+ "aria-label": "Clear selection",
710
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.X, { className: "size-3.5" })
711
+ }
712
+ ),
713
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
714
+ import_lucide_react.ChevronDown,
715
+ {
716
+ className: cn(
717
+ "text-muted-foreground shrink-0 transition-transform",
718
+ size === "compact" ? "size-3" : "size-4",
719
+ open && "rotate-180"
720
+ )
721
+ }
722
+ )
723
+ ]
724
+ }
725
+ ),
726
+ open && mounted && position ? (0, import_react_dom2.createPortal)(
727
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
728
+ "div",
729
+ {
730
+ ref: dropdownRef,
731
+ "data-autocomplete-dropdown": true,
732
+ style: {
733
+ position: "fixed",
734
+ left: position.left,
735
+ width: position.width,
736
+ top: position.top,
737
+ bottom: position.bottom,
738
+ // Above the modal shell (z-100) it is usually opened inside.
739
+ zIndex: 200
740
+ },
741
+ className: "border-border bg-background overflow-hidden rounded-md border shadow-lg",
742
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
743
+ "ul",
744
+ {
745
+ ref: listRef,
746
+ id: listboxId,
747
+ role: "listbox",
748
+ "aria-multiselectable": multiple || void 0,
749
+ className: "overflow-y-auto p-1",
750
+ style: { maxHeight: position.maxHeight },
751
+ children: filteredOptions.length === 0 && !canCreate ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { className: "text-muted-foreground px-3 py-6 text-center text-sm", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
752
+ filteredOptions.map((option, index) => {
753
+ const isSelected = selectedValues.includes(option.value);
754
+ const isHighlighted = index === safeHighlightedIndex;
755
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
756
+ "li",
757
+ {
758
+ "data-option": true,
759
+ role: "option",
760
+ "aria-selected": isSelected,
761
+ "aria-disabled": option.disabled || void 0,
762
+ className: cn(
763
+ "flex cursor-pointer items-center gap-2 rounded-sm transition-colors",
764
+ size === "compact" ? "px-2 py-1 text-xs" : "px-2.5 py-2 text-sm",
765
+ isHighlighted && "bg-muted",
766
+ option.disabled && "cursor-not-allowed opacity-50"
767
+ ),
768
+ onMouseEnter: () => setHighlightedIndex(index),
769
+ onPointerDown: (event) => {
770
+ event.preventDefault();
771
+ event.stopPropagation();
772
+ selectOption(option);
773
+ },
774
+ children: [
775
+ multiple ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
776
+ "span",
777
+ {
778
+ className: cn(
779
+ "border-border flex size-4 shrink-0 items-center justify-center rounded border",
780
+ isSelected && "border-primary bg-primary text-primary-foreground"
781
+ ),
782
+ children: isSelected ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Check, { className: "size-3" }) : null
783
+ }
784
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
785
+ import_lucide_react.Check,
786
+ {
787
+ className: cn(
788
+ "text-primary size-4 shrink-0",
789
+ isSelected ? "opacity-100" : "opacity-0"
790
+ )
791
+ }
792
+ ),
793
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate", children: option.label })
794
+ ]
795
+ },
796
+ option.value
797
+ );
798
+ }),
799
+ canCreate ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
800
+ "li",
801
+ {
802
+ "data-option": true,
803
+ role: "option",
804
+ "aria-selected": false,
805
+ className: "hover:bg-muted flex cursor-pointer items-center gap-2 rounded-sm px-2.5 py-2 text-sm transition-colors",
806
+ onPointerDown: (event) => {
807
+ event.preventDefault();
808
+ event.stopPropagation();
809
+ ignoreBlurRef.current = true;
810
+ window.setTimeout(() => {
811
+ ignoreBlurRef.current = false;
812
+ }, 0);
813
+ commitCustomValues(query);
814
+ window.requestAnimationFrame(
815
+ () => inputRef.current?.focus()
816
+ );
817
+ },
818
+ children: [
819
+ "Add \u201C",
820
+ createLabel,
821
+ "\u201D"
822
+ ]
823
+ }
824
+ ) : null
825
+ ] })
826
+ }
827
+ )
828
+ }
829
+ ),
830
+ document.body
831
+ ) : null
832
+ ]
833
+ }
834
+ );
835
+ }
836
+
837
+ // src/badge.tsx
838
+ var React5 = __toESM(require("react"), 1);
839
+ var import_class_variance_authority2 = require("class-variance-authority");
840
+ var import_jsx_runtime4 = require("react/jsx-runtime");
841
+ var badgeVariants = (0, import_class_variance_authority2.cva)(
842
+ "inline-flex items-center gap-1 rounded font-medium whitespace-nowrap",
843
+ {
844
+ variants: {
845
+ variant: {
846
+ neutral: "bg-muted text-muted-foreground",
847
+ success: "bg-success/15 text-success",
848
+ warning: "bg-warning/15 text-warning",
849
+ danger: "bg-destructive/15 text-destructive",
850
+ info: "bg-info/15 text-info"
851
+ },
852
+ size: {
853
+ /** Inline chips — a category, a tenant, a permission. */
854
+ sm: "px-1.5 py-0.5 text-xs",
855
+ /** A row's status. */
856
+ md: "px-2 py-0.5 text-xs"
857
+ }
858
+ },
859
+ defaultVariants: {
860
+ variant: "neutral",
861
+ size: "md"
862
+ }
863
+ }
864
+ );
865
+ var Badge = React5.forwardRef(
866
+ ({ className, variant, size, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
867
+ "span",
868
+ {
869
+ ref,
870
+ className: cn(badgeVariants({ variant, size }), className),
871
+ ...props
872
+ }
873
+ )
874
+ );
875
+ Badge.displayName = "Badge";
876
+
877
+ // src/breadcrumb.tsx
878
+ var import_lucide_react2 = require("lucide-react");
879
+ var import_jsx_runtime5 = require("react/jsx-runtime");
880
+ function Breadcrumb({ items, className }) {
881
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { "aria-label": "Breadcrumb", className: cn("text-sm", className), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
882
+ const isLast = index === items.length - 1;
883
+ const isInteractive = !isLast && (item.href || item.onClick);
884
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
885
+ "li",
886
+ {
887
+ className: "flex items-center gap-1.5",
888
+ children: [
889
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
890
+ import_lucide_react2.ChevronRight,
891
+ {
892
+ className: "text-muted-foreground/70 size-3.5 shrink-0",
893
+ "aria-hidden": true
894
+ }
895
+ ),
896
+ isInteractive ? item.href ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
897
+ "a",
898
+ {
899
+ href: item.href,
900
+ className: "text-muted-foreground hover:text-foreground transition",
901
+ children: item.label
902
+ }
903
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
904
+ "button",
905
+ {
906
+ type: "button",
907
+ onClick: item.onClick,
908
+ className: "text-muted-foreground hover:text-foreground transition",
909
+ children: item.label
910
+ }
911
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
912
+ "span",
913
+ {
914
+ className: cn(
915
+ isLast ? "text-foreground font-medium" : "text-muted-foreground"
916
+ ),
917
+ "aria-current": isLast ? "page" : void 0,
918
+ children: item.label
919
+ }
920
+ )
921
+ ]
922
+ },
923
+ `${item.label}-${index}`
924
+ );
925
+ }) }) });
926
+ }
927
+
928
+ // src/button.tsx
929
+ var React6 = __toESM(require("react"), 1);
930
+ var import_class_variance_authority3 = require("class-variance-authority");
931
+ var import_react_slot = require("@radix-ui/react-slot");
932
+
933
+ // src/spinner.tsx
934
+ var import_lucide_react3 = require("lucide-react");
935
+ var import_jsx_runtime6 = require("react/jsx-runtime");
936
+ var SIZES = {
937
+ sm: "size-3.5",
938
+ md: "size-4",
939
+ lg: "size-5",
940
+ xl: "size-10 border-2"
941
+ };
942
+ function Spinner({ size = "md", className, ...props }) {
943
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
944
+ import_lucide_react3.Loader2,
945
+ {
946
+ "aria-hidden": true,
947
+ className: cn("animate-spin", SIZES[size], className),
948
+ ...props
949
+ }
950
+ );
951
+ }
952
+
953
+ // src/button.tsx
954
+ var import_jsx_runtime7 = require("react/jsx-runtime");
955
+ var buttonVariants = (0, import_class_variance_authority3.cva)(
956
+ "inline-flex h-9 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md px-3 text-sm font-medium transition duration-200 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
957
+ {
958
+ variants: {
959
+ variant: {
960
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
961
+ secondary: "bg-muted text-foreground hover:bg-muted/80",
962
+ ghost: "hover:bg-muted",
963
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
964
+ outline: "border border-border bg-background hover:bg-muted"
965
+ },
966
+ size: {
967
+ sm: "h-8 px-2.5",
968
+ md: "h-9 px-3",
969
+ lg: "h-10 px-4",
970
+ icon: "h-9 w-9 px-0",
971
+ // Square, matching `sm`'s height — for an icon-only control sitting in
972
+ // a table row or beside `sm` buttons, where `icon` is a row taller.
973
+ "icon-sm": "h-8 w-8 px-0"
974
+ }
975
+ },
976
+ defaultVariants: {
977
+ variant: "default",
978
+ size: "md"
979
+ }
980
+ }
981
+ );
982
+ var ICON_SIZES = /* @__PURE__ */ new Set(["icon", "icon-sm"]);
983
+ var Button = React6.forwardRef(
984
+ ({
985
+ className,
986
+ variant,
987
+ size,
988
+ asChild = false,
989
+ loading,
990
+ disabled,
991
+ children,
992
+ ...props
993
+ }, ref) => {
994
+ const Comp = asChild ? import_react_slot.Slot : "button";
995
+ if (asChild) {
996
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
997
+ Comp,
998
+ {
999
+ ref,
1000
+ className: cn(buttonVariants({ variant, size }), className),
1001
+ ...props,
1002
+ children
1003
+ }
1004
+ );
1005
+ }
1006
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1007
+ "button",
1008
+ {
1009
+ ref,
1010
+ disabled: disabled || loading,
1011
+ "aria-busy": loading || void 0,
1012
+ className: cn(buttonVariants({ variant, size }), className),
1013
+ ...props,
1014
+ children: [
1015
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Spinner, { size: "sm" }) : null,
1016
+ loading && size != null && ICON_SIZES.has(size) ? null : children
1017
+ ]
1018
+ }
1019
+ );
1020
+ }
1021
+ );
1022
+ Button.displayName = "Button";
1023
+
1024
+ // src/card.tsx
1025
+ var React7 = __toESM(require("react"), 1);
1026
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1027
+ var Card = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1028
+ "div",
1029
+ {
1030
+ ref,
1031
+ className: cn(
1032
+ "bg-card text-card-foreground rounded-xl border shadow",
1033
+ className
1034
+ ),
1035
+ ...props
1036
+ }
1037
+ ));
1038
+ Card.displayName = "Card";
1039
+ var CardHeader = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1040
+ "div",
1041
+ {
1042
+ ref,
1043
+ className: cn("flex flex-col space-y-1.5 p-6", className),
1044
+ ...props
1045
+ }
1046
+ ));
1047
+ CardHeader.displayName = "CardHeader";
1048
+ var CardTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1049
+ "div",
1050
+ {
1051
+ ref,
1052
+ className: cn("leading-none font-semibold tracking-tight", className),
1053
+ ...props
1054
+ }
1055
+ ));
1056
+ CardTitle.displayName = "CardTitle";
1057
+ var CardDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1058
+ "div",
1059
+ {
1060
+ ref,
1061
+ className: cn("text-muted-foreground text-sm", className),
1062
+ ...props
1063
+ }
1064
+ ));
1065
+ CardDescription.displayName = "CardDescription";
1066
+ var CardContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1067
+ CardContent.displayName = "CardContent";
1068
+ var CardFooter = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1069
+ "div",
1070
+ {
1071
+ ref,
1072
+ className: cn("flex items-center p-6 pt-0", className),
1073
+ ...props
1074
+ }
1075
+ ));
1076
+ CardFooter.displayName = "CardFooter";
1077
+
1078
+ // src/checkbox.tsx
1079
+ var React8 = __toESM(require("react"), 1);
1080
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1081
+ var checkboxClass = "accent-primary border-border focus-visible:ring-ring size-4 shrink-0 cursor-pointer rounded border focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50";
1082
+ var Checkbox = React8.forwardRef(
1083
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1084
+ "input",
1085
+ {
1086
+ ref,
1087
+ type: "checkbox",
1088
+ className: cn(checkboxClass, className),
1089
+ ...props
1090
+ }
1091
+ )
1092
+ );
1093
+ Checkbox.displayName = "Checkbox";
1094
+
1095
+ // src/clipboard.ts
1096
+ var TSV_DELIMITER = " ";
1097
+ var CSV_DELIMITER = ",";
1098
+ function normalizeRange(anchor, focus) {
1099
+ if (!anchor || !focus) return null;
1100
+ return {
1101
+ r1: Math.min(anchor.r, focus.r),
1102
+ r2: Math.max(anchor.r, focus.r),
1103
+ c1: Math.min(anchor.c, focus.c),
1104
+ c2: Math.max(anchor.c, focus.c)
1105
+ };
1106
+ }
1107
+ function escapeCell(raw, delimiter) {
1108
+ const value = raw == null ? "" : String(raw);
1109
+ if (value.includes(delimiter) || value.includes("\n") || value.includes("\r") || value.includes('"')) {
1110
+ return `"${value.replace(/"/g, '""')}"`;
1111
+ }
1112
+ return value;
1113
+ }
1114
+ function buildRangeText(range, columns, rows, delimiter, includeHeaders) {
1115
+ if (!range) return "";
1116
+ const lines = [];
1117
+ if (includeHeaders) {
1118
+ const header = [];
1119
+ for (let c = range.c1; c <= range.c2; c++) {
1120
+ header.push(escapeCell(columns[c]?.title, delimiter));
1121
+ }
1122
+ lines.push(header.join(delimiter));
1123
+ }
1124
+ for (let r = range.r1; r <= range.r2; r++) {
1125
+ const line = [];
1126
+ const row = rows[r];
1127
+ for (let c = range.c1; c <= range.c2; c++) {
1128
+ const column = columns[c];
1129
+ line.push(
1130
+ escapeCell(
1131
+ column && row !== void 0 ? column.value(row) : "",
1132
+ delimiter
1133
+ )
1134
+ );
1135
+ }
1136
+ lines.push(line.join(delimiter));
1137
+ }
1138
+ return lines.join("\n");
1139
+ }
1140
+ function fullRange(columns, rows) {
1141
+ if (!rows.length || !columns.length) return null;
1142
+ return { r1: 0, r2: rows.length - 1, c1: 0, c2: columns.length - 1 };
1143
+ }
1144
+ function describeRange(range) {
1145
+ if (!range) return "No selection";
1146
+ const rowCount = range.r2 - range.r1 + 1;
1147
+ const colCount = range.c2 - range.c1 + 1;
1148
+ if (rowCount === 1 && colCount === 1) return "1 cell selected";
1149
+ return `${rowCount} \xD7 ${colCount} selected`;
1150
+ }
1151
+ function countCells(range) {
1152
+ return {
1153
+ rows: range.r2 - range.r1 + 1,
1154
+ columns: range.c2 - range.c1 + 1
1155
+ };
1156
+ }
1157
+ async function writeToClipboard(text) {
1158
+ if (navigator.clipboard?.writeText) {
1159
+ return navigator.clipboard.writeText(text);
1160
+ }
1161
+ const textarea = document.createElement("textarea");
1162
+ textarea.value = text;
1163
+ textarea.style.position = "fixed";
1164
+ textarea.style.top = "-1000px";
1165
+ document.body.appendChild(textarea);
1166
+ textarea.select();
1167
+ try {
1168
+ if (!document.execCommand("copy")) {
1169
+ throw new Error("Could not write to the clipboard");
1170
+ }
1171
+ } finally {
1172
+ document.body.removeChild(textarea);
1173
+ }
1174
+ }
1175
+
1176
+ // src/collapsible.tsx
1177
+ var import_lucide_react4 = require("lucide-react");
1178
+ var React9 = __toESM(require("react"), 1);
1179
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1180
+ function CollapsibleSection({
1181
+ title,
1182
+ icon,
1183
+ defaultOpen = true,
1184
+ right,
1185
+ className,
1186
+ children
1187
+ }) {
1188
+ const [open, setOpen] = React9.useState(defaultOpen);
1189
+ const bodyId = React9.useId();
1190
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: cn("border-border rounded-lg border", className), children: [
1191
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1192
+ "button",
1193
+ {
1194
+ type: "button",
1195
+ "aria-expanded": open,
1196
+ "aria-controls": bodyId,
1197
+ onClick: () => setOpen((current) => !current),
1198
+ className: "hover:bg-muted/50 flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-semibold transition",
1199
+ children: [
1200
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1201
+ import_lucide_react4.ChevronDown,
1202
+ {
1203
+ size: 14,
1204
+ "aria-hidden": true,
1205
+ className: cn(
1206
+ "shrink-0 transition-transform",
1207
+ open ? "" : "-rotate-90"
1208
+ )
1209
+ }
1210
+ ),
1211
+ icon,
1212
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "flex-1", children: title }),
1213
+ right
1214
+ ]
1215
+ }
1216
+ ),
1217
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { id: bodyId, hidden: !open, className: "space-y-3 px-3 pt-1 pb-3", children })
1218
+ ] });
1219
+ }
1220
+
1221
+ // src/confirm-dialog.tsx
1222
+ var React10 = __toESM(require("react"), 1);
1223
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1224
+ function ConfirmDialog({
1225
+ isOpen,
1226
+ title,
1227
+ description,
1228
+ confirmLabel = "Delete",
1229
+ cancelLabel = "Cancel",
1230
+ isConfirming,
1231
+ error,
1232
+ onConfirm,
1233
+ onClose
1234
+ }) {
1235
+ const titleId = React10.useId();
1236
+ const descriptionId = React10.useId();
1237
+ const errorId = React10.useId();
1238
+ const describedBy = [
1239
+ description ? descriptionId : null,
1240
+ error ? errorId : null
1241
+ ].filter(Boolean).join(" ");
1242
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1243
+ Modal,
1244
+ {
1245
+ isOpen,
1246
+ role: "alertdialog",
1247
+ labelledBy: titleId,
1248
+ describedBy: describedBy || void 0,
1249
+ closeLabel: "Close dialog",
1250
+ onClose,
1251
+ children: [
1252
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { id: titleId, className: "text-lg font-semibold", children: title }),
1253
+ description ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { id: descriptionId, className: "text-muted-foreground mt-2 text-sm", children: description }) : null,
1254
+ error ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1255
+ "div",
1256
+ {
1257
+ id: errorId,
1258
+ role: "alert",
1259
+ className: "border-destructive/30 bg-destructive/5 text-destructive mt-4 rounded-lg border px-3 py-2 text-sm",
1260
+ children: error
1261
+ }
1262
+ ) : null,
1263
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-6 flex justify-end gap-2", children: [
1264
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Button, { variant: "outline", onClick: onClose, disabled: isConfirming, children: cancelLabel }),
1265
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1266
+ Button,
1267
+ {
1268
+ variant: "destructive",
1269
+ onClick: onConfirm,
1270
+ loading: isConfirming,
1271
+ children: confirmLabel
1272
+ }
1273
+ )
1274
+ ] })
1275
+ ]
1276
+ }
1277
+ );
1278
+ }
1279
+
1280
+ // src/copy-button.tsx
1281
+ var import_lucide_react5 = require("lucide-react");
1282
+ var React11 = __toESM(require("react"), 1);
1283
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1284
+ function CopyButton({
1285
+ value,
1286
+ label,
1287
+ className
1288
+ }) {
1289
+ const [copied, setCopied] = React11.useState(false);
1290
+ React11.useEffect(() => {
1291
+ if (!copied) return;
1292
+ const timer = window.setTimeout(() => setCopied(false), 1500);
1293
+ return () => window.clearTimeout(timer);
1294
+ }, [copied]);
1295
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1296
+ "button",
1297
+ {
1298
+ type: "button",
1299
+ "aria-label": copied ? `${label} copied` : `Copy ${label}`,
1300
+ title: copied ? "Copied" : `Copy ${label}`,
1301
+ className: cn(
1302
+ "text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring shrink-0 cursor-pointer rounded p-1 transition focus-visible:ring-2 focus-visible:outline-none",
1303
+ className
1304
+ ),
1305
+ onClick: () => {
1306
+ void writeToClipboard(value).then(() => setCopied(true)).catch(() => void 0);
1307
+ },
1308
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Check, { className: "size-3.5 text-success", "aria-hidden": true }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Copy, { className: "size-3.5", "aria-hidden": true })
1309
+ }
1310
+ );
1311
+ }
1312
+
1313
+ // src/data-table.tsx
1314
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1315
+ var HEADER_VARIANTS = {
1316
+ uppercase: "border-border bg-muted/40 text-muted-foreground border-b text-xs tracking-wide uppercase",
1317
+ plain: "text-muted-foreground border-border border-b text-left"
1318
+ };
1319
+ var DENSITY = {
1320
+ comfortable: "px-4 py-3",
1321
+ compact: "px-3 py-2"
1322
+ };
1323
+ var ALIGN = {
1324
+ left: "text-left",
1325
+ right: "text-right",
1326
+ center: "text-center"
1327
+ };
1328
+ function DataTable({
1329
+ columns,
1330
+ rows,
1331
+ rowKey,
1332
+ variant = "uppercase",
1333
+ density = "comfortable",
1334
+ stickyHeader = false,
1335
+ rowClassName,
1336
+ emptyMessage,
1337
+ footer,
1338
+ ariaLabel,
1339
+ className,
1340
+ tableClassName
1341
+ }) {
1342
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1343
+ "div",
1344
+ {
1345
+ className: cn(
1346
+ "border-border bg-background/80 overflow-x-auto rounded-lg border",
1347
+ className
1348
+ ),
1349
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1350
+ "table",
1351
+ {
1352
+ "aria-label": ariaLabel,
1353
+ className: cn("min-w-full text-left text-sm", tableClassName),
1354
+ children: [
1355
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1356
+ "thead",
1357
+ {
1358
+ className: cn(
1359
+ HEADER_VARIANTS[variant],
1360
+ stickyHeader && "bg-muted sticky top-0 z-10"
1361
+ ),
1362
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1363
+ "th",
1364
+ {
1365
+ scope: "col",
1366
+ "aria-sort": column.ariaSort,
1367
+ className: cn(
1368
+ DENSITY[density],
1369
+ "font-medium",
1370
+ ALIGN[column.align ?? "left"],
1371
+ column.headerClassName
1372
+ ),
1373
+ children: column.title
1374
+ },
1375
+ column.key
1376
+ )) })
1377
+ }
1378
+ ),
1379
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: rows.length === 0 && emptyMessage != null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1380
+ "td",
1381
+ {
1382
+ colSpan: columns.length,
1383
+ className: "text-muted-foreground px-4 py-6 text-center text-sm",
1384
+ children: emptyMessage
1385
+ }
1386
+ ) }) : rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1387
+ "tr",
1388
+ {
1389
+ className: cn(
1390
+ "border-border/70 border-b last:border-0",
1391
+ rowClassName?.(row, index)
1392
+ ),
1393
+ children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1394
+ "td",
1395
+ {
1396
+ className: cn(
1397
+ DENSITY[density],
1398
+ ALIGN[column.align ?? "left"],
1399
+ column.className
1400
+ ),
1401
+ children: column.cell(row, index)
1402
+ },
1403
+ column.key
1404
+ ))
1405
+ },
1406
+ rowKey(row, index)
1407
+ )) }),
1408
+ footer != null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tfoot", { children: footer }) : null
1409
+ ]
1410
+ }
1411
+ )
1412
+ }
1413
+ );
1414
+ }
1415
+
1416
+ // src/date-range-picker/index.tsx
1417
+ var import_lucide_react6 = require("lucide-react");
1418
+ var React12 = __toESM(require("react"), 1);
1419
+
1420
+ // src/date-range-picker/dateRange.ts
1421
+ var pad = (n) => String(n).padStart(2, "0");
1422
+ function toIsoDate(date) {
1423
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
1424
+ }
1425
+ function fromIsoDate(value) {
1426
+ if (!value) return null;
1427
+ const trimmed = value.trim();
1428
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(trimmed);
1429
+ if (!match) return null;
1430
+ const date = new Date(
1431
+ Number(match[1]),
1432
+ Number(match[2]) - 1,
1433
+ Number(match[3])
1434
+ );
1435
+ return toIsoDate(date) === trimmed ? date : null;
1436
+ }
1437
+ function startOfMonth(date) {
1438
+ return new Date(date.getFullYear(), date.getMonth(), 1);
1439
+ }
1440
+ function addMonths(date, count) {
1441
+ return new Date(date.getFullYear(), date.getMonth() + count, 1);
1442
+ }
1443
+ function addDays(date, count) {
1444
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + count);
1445
+ }
1446
+ function isSameDay(a, b) {
1447
+ if (!a || !b) return false;
1448
+ return toIsoDate(a) === toIsoDate(b);
1449
+ }
1450
+ function monthGrid(month) {
1451
+ const first = startOfMonth(month);
1452
+ const start = addDays(first, -first.getDay());
1453
+ return Array.from({ length: 42 }, (_, index) => addDays(start, index));
1454
+ }
1455
+ function monthLabel(month, locale = "en-IN") {
1456
+ return month.toLocaleDateString(locale, { month: "long", year: "numeric" });
1457
+ }
1458
+ function formatDisplay(value, locale = "en-IN") {
1459
+ const date = fromIsoDate(value);
1460
+ if (!date) return "";
1461
+ return date.toLocaleDateString(locale, {
1462
+ day: "numeric",
1463
+ month: "short",
1464
+ year: "numeric"
1465
+ });
1466
+ }
1467
+ function startOfDayMs(value) {
1468
+ const date = fromIsoDate(value);
1469
+ return date ? date.getTime() : 0;
1470
+ }
1471
+ function endOfDayMs(value) {
1472
+ const date = fromIsoDate(value);
1473
+ if (!date) return 0;
1474
+ return new Date(
1475
+ date.getFullYear(),
1476
+ date.getMonth(),
1477
+ date.getDate(),
1478
+ 23,
1479
+ 59,
1480
+ 59,
1481
+ 999
1482
+ ).getTime();
1483
+ }
1484
+ function endAt2359Ms(value) {
1485
+ const date = fromIsoDate(value);
1486
+ if (!date) return 0;
1487
+ return new Date(
1488
+ date.getFullYear(),
1489
+ date.getMonth(),
1490
+ date.getDate(),
1491
+ 23,
1492
+ 59,
1493
+ 59,
1494
+ 0
1495
+ ).getTime();
1496
+ }
1497
+ function createdRangeMs(from, to) {
1498
+ const startDate = from.trim() || to.trim();
1499
+ const endDate = to.trim() || from.trim();
1500
+ return {
1501
+ start_time: startOfDayMs(startDate),
1502
+ end_time: endAt2359Ms(endDate)
1503
+ };
1504
+ }
1505
+
1506
+ // src/date-range-picker/index.tsx
1507
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1508
+ var PRESETS = [
1509
+ {
1510
+ label: "Today",
1511
+ range: () => {
1512
+ const today = toIsoDate(/* @__PURE__ */ new Date());
1513
+ return { from: today, to: today };
1514
+ }
1515
+ },
1516
+ {
1517
+ label: "Yesterday",
1518
+ range: () => {
1519
+ const day = toIsoDate(addDays(/* @__PURE__ */ new Date(), -1));
1520
+ return { from: day, to: day };
1521
+ }
1522
+ },
1523
+ {
1524
+ label: "Last 7 days",
1525
+ range: () => ({
1526
+ from: toIsoDate(addDays(/* @__PURE__ */ new Date(), -6)),
1527
+ to: toIsoDate(/* @__PURE__ */ new Date())
1528
+ })
1529
+ },
1530
+ {
1531
+ label: "Last 30 days",
1532
+ range: () => ({
1533
+ from: toIsoDate(addDays(/* @__PURE__ */ new Date(), -29)),
1534
+ to: toIsoDate(/* @__PURE__ */ new Date())
1535
+ })
1536
+ },
1537
+ {
1538
+ label: "This month",
1539
+ range: () => ({
1540
+ from: toIsoDate(startOfMonth(/* @__PURE__ */ new Date())),
1541
+ to: toIsoDate(/* @__PURE__ */ new Date())
1542
+ })
1543
+ }
1544
+ ];
1545
+ var WEEKDAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
1546
+ function DateRangePicker({
1547
+ value,
1548
+ onChange,
1549
+ disabled,
1550
+ placeholder = "Any date",
1551
+ className,
1552
+ ariaLabel = "Date range"
1553
+ }) {
1554
+ const [open, setOpen] = React12.useState(false);
1555
+ const [hovered, setHovered] = React12.useState(null);
1556
+ const [pendingFrom, setPendingFrom] = React12.useState(null);
1557
+ const rootRef = React12.useRef(null);
1558
+ const from = fromIsoDate(value.from);
1559
+ const to = fromIsoDate(value.to);
1560
+ const [viewMonth, setViewMonth] = React12.useState(
1561
+ () => startOfMonth(from ?? /* @__PURE__ */ new Date())
1562
+ );
1563
+ React12.useEffect(() => {
1564
+ if (!open) return void 0;
1565
+ const onPointerDown = (event) => {
1566
+ if (!rootRef.current?.contains(event.target)) setOpen(false);
1567
+ };
1568
+ const onKeyDown = (event) => {
1569
+ if (event.key === "Escape") setOpen(false);
1570
+ };
1571
+ document.addEventListener("mousedown", onPointerDown);
1572
+ document.addEventListener("keydown", onKeyDown);
1573
+ return () => {
1574
+ document.removeEventListener("mousedown", onPointerDown);
1575
+ document.removeEventListener("keydown", onKeyDown);
1576
+ };
1577
+ }, [open]);
1578
+ function openPicker() {
1579
+ setViewMonth(startOfMonth(fromIsoDate(value.from) ?? /* @__PURE__ */ new Date()));
1580
+ setPendingFrom(null);
1581
+ setHovered(null);
1582
+ setOpen(true);
1583
+ }
1584
+ const anchor = pendingFrom ?? (to ? null : from);
1585
+ const previewEnd = pendingFrom ? hovered : null;
1586
+ function rangeBounds() {
1587
+ if (pendingFrom) {
1588
+ if (!previewEnd) return [pendingFrom, pendingFrom];
1589
+ return previewEnd.getTime() < pendingFrom.getTime() ? [previewEnd, pendingFrom] : [pendingFrom, previewEnd];
1590
+ }
1591
+ return [from, to];
1592
+ }
1593
+ const [rangeStart, rangeEnd] = rangeBounds();
1594
+ function selectDay(day) {
1595
+ if (!anchor) {
1596
+ setPendingFrom(day);
1597
+ onChange({ from: toIsoDate(day), to: "" });
1598
+ return;
1599
+ }
1600
+ const [start, end] = day.getTime() < anchor.getTime() ? [day, anchor] : [anchor, day];
1601
+ onChange({ from: toIsoDate(start), to: toIsoDate(end) });
1602
+ setPendingFrom(null);
1603
+ setHovered(null);
1604
+ setOpen(false);
1605
+ }
1606
+ function onGridKeyDown(event) {
1607
+ const offsets = {
1608
+ ArrowLeft: -1,
1609
+ ArrowRight: 1,
1610
+ ArrowUp: -7,
1611
+ ArrowDown: 7
1612
+ };
1613
+ const offset = offsets[event.key];
1614
+ if (offset === void 0) return;
1615
+ const focused = document.activeElement;
1616
+ const iso = focused?.dataset?.day;
1617
+ const current = fromIsoDate(iso);
1618
+ if (!current) return;
1619
+ event.preventDefault();
1620
+ const next = addDays(current, offset);
1621
+ const nextIso = toIsoDate(next);
1622
+ if (!rootRef.current?.querySelector(`[data-day="${nextIso}"]`)) {
1623
+ setViewMonth(startOfMonth(offset < 0 ? next : addMonths(next, -1)));
1624
+ }
1625
+ window.requestAnimationFrame(() => {
1626
+ rootRef.current?.querySelector(`[data-day="${nextIso}"]`)?.focus();
1627
+ });
1628
+ }
1629
+ const label = value.from || value.to ? `${formatDisplay(value.from) || "Any"} \u2192 ${formatDisplay(value.to) || "Any"}` : placeholder;
1630
+ const today = /* @__PURE__ */ new Date();
1631
+ function renderMonth(month) {
1632
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "w-[15.75rem] shrink-0", children: [
1633
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-foreground mb-2 text-center text-sm font-medium whitespace-nowrap", children: monthLabel(month) }),
1634
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-muted-foreground grid grid-cols-7 text-center text-[11px]", children: WEEKDAYS.map((day) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "grid size-9 place-items-center", children: day }, day)) }),
1635
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "grid grid-cols-7", children: monthGrid(month).map((day) => {
1636
+ const iso = toIsoDate(day);
1637
+ const outside = day.getMonth() !== month.getMonth();
1638
+ const isStart = isSameDay(day, rangeStart);
1639
+ const isEnd = isSameDay(day, rangeEnd);
1640
+ const inRange = rangeStart != null && rangeEnd != null && day.getTime() > rangeStart.getTime() && day.getTime() < rangeEnd.getTime();
1641
+ const isToday = isSameDay(day, today);
1642
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1643
+ "button",
1644
+ {
1645
+ type: "button",
1646
+ "data-day": iso,
1647
+ onClick: () => selectDay(day),
1648
+ onMouseEnter: () => setHovered(day),
1649
+ "aria-label": day.toDateString(),
1650
+ "aria-pressed": isStart || isEnd,
1651
+ className: cn(
1652
+ "focus-visible:ring-ring relative grid size-9 place-items-center rounded-md text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none",
1653
+ outside ? "text-muted-foreground/50" : "text-foreground",
1654
+ inRange && "bg-primary/10 rounded-none",
1655
+ (isStart || isEnd) && "bg-primary text-primary-foreground font-medium",
1656
+ // Square off the inner edge so a range reads as one bar
1657
+ // rather than two pills with a gap.
1658
+ isStart && rangeEnd && !isEnd && "rounded-r-none",
1659
+ isEnd && rangeStart && !isStart && "rounded-l-none",
1660
+ !isStart && !isEnd && "hover:bg-muted",
1661
+ isToday && !isStart && !isEnd && "ring-border font-semibold ring-1"
1662
+ ),
1663
+ children: day.getDate()
1664
+ },
1665
+ iso
1666
+ );
1667
+ }) })
1668
+ ] }, monthLabel(month));
1669
+ }
1670
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { ref: rootRef, className: cn("relative", className), children: [
1671
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1672
+ "div",
1673
+ {
1674
+ className: cn(
1675
+ "border-border bg-background flex items-center rounded-md border",
1676
+ "focus-within:ring-ring/50 focus-within:border-ring focus-within:ring-2",
1677
+ disabled && "opacity-50"
1678
+ ),
1679
+ children: [
1680
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1681
+ "button",
1682
+ {
1683
+ type: "button",
1684
+ disabled,
1685
+ "aria-haspopup": "dialog",
1686
+ "aria-expanded": open,
1687
+ "aria-label": ariaLabel,
1688
+ onClick: () => open ? setOpen(false) : openPicker(),
1689
+ className: "flex min-w-0 flex-1 items-center gap-2 px-2 py-1.5 text-left text-sm",
1690
+ children: [
1691
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1692
+ import_lucide_react6.CalendarDays,
1693
+ {
1694
+ className: "text-muted-foreground size-4 shrink-0",
1695
+ "aria-hidden": true
1696
+ }
1697
+ ),
1698
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1699
+ "span",
1700
+ {
1701
+ className: cn(
1702
+ "truncate",
1703
+ !value.from && !value.to && "text-muted-foreground"
1704
+ ),
1705
+ children: label
1706
+ }
1707
+ )
1708
+ ]
1709
+ }
1710
+ ),
1711
+ (value.from || value.to) && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1712
+ "button",
1713
+ {
1714
+ type: "button",
1715
+ "aria-label": "Clear date range",
1716
+ onClick: () => {
1717
+ onChange({ from: "", to: "" });
1718
+ setPendingFrom(null);
1719
+ },
1720
+ className: "text-muted-foreground hover:text-foreground shrink-0 px-2",
1721
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.X, { className: "size-3.5", "aria-hidden": true })
1722
+ }
1723
+ ) : null
1724
+ ]
1725
+ }
1726
+ ),
1727
+ open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1728
+ "div",
1729
+ {
1730
+ role: "dialog",
1731
+ "aria-label": ariaLabel,
1732
+ className: "border-border bg-background absolute top-full right-0 z-50 mt-1 flex w-max rounded-lg border p-3 shadow-lg",
1733
+ children: [
1734
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "border-border mr-3 flex w-32 shrink-0 flex-col gap-0.5 border-r pr-3", children: PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1735
+ "button",
1736
+ {
1737
+ type: "button",
1738
+ className: "hover:bg-muted text-foreground rounded-md px-2 py-1.5 text-left text-xs",
1739
+ onClick: () => {
1740
+ onChange(preset.range());
1741
+ setPendingFrom(null);
1742
+ setOpen(false);
1743
+ },
1744
+ children: preset.label
1745
+ },
1746
+ preset.label
1747
+ )) }),
1748
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { onKeyDown: onGridKeyDown, children: [
1749
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mb-2 flex items-center justify-between", children: [
1750
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1751
+ "button",
1752
+ {
1753
+ type: "button",
1754
+ "aria-label": "Previous month",
1755
+ className: "hover:bg-muted text-muted-foreground hover:text-foreground rounded-md p-1.5",
1756
+ onClick: () => setViewMonth(addMonths(viewMonth, -1)),
1757
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.ChevronLeft, { className: "size-4", "aria-hidden": true })
1758
+ }
1759
+ ),
1760
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1761
+ "button",
1762
+ {
1763
+ type: "button",
1764
+ "aria-label": "Next month",
1765
+ className: "hover:bg-muted text-muted-foreground hover:text-foreground rounded-md p-1.5",
1766
+ onClick: () => setViewMonth(addMonths(viewMonth, 1)),
1767
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.ChevronRight, { className: "size-4", "aria-hidden": true })
1768
+ }
1769
+ )
1770
+ ] }),
1771
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex gap-5", onMouseLeave: () => setHovered(null), children: [
1772
+ renderMonth(viewMonth),
1773
+ renderMonth(addMonths(viewMonth, 1))
1774
+ ] })
1775
+ ] })
1776
+ ]
1777
+ }
1778
+ ) : null
1779
+ ] });
1780
+ }
1781
+
1782
+ // src/state-panel.tsx
1783
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1784
+ function StatePanel({
1785
+ loading,
1786
+ className,
1787
+ children,
1788
+ ...props
1789
+ }) {
1790
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1791
+ "div",
1792
+ {
1793
+ role: loading ? "status" : void 0,
1794
+ "aria-live": loading ? "polite" : void 0,
1795
+ className: cn(
1796
+ "border-border bg-background/80 text-muted-foreground rounded-lg border px-4 py-6 text-center text-sm",
1797
+ loading && "flex items-center justify-center gap-2",
1798
+ className
1799
+ ),
1800
+ ...props,
1801
+ children: [
1802
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Spinner, { size: "md" }) : null,
1803
+ children
1804
+ ]
1805
+ }
1806
+ );
1807
+ }
1808
+
1809
+ // src/feature-access-gate.tsx
1810
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1811
+ function FeatureAccessGate({
1812
+ isLoading,
1813
+ allowed,
1814
+ deniedMessage,
1815
+ children
1816
+ }) {
1817
+ if (isLoading) {
1818
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatePanel, { loading: true, className: "p-6", children: "Checking permissions\u2026" });
1819
+ }
1820
+ if (!allowed) {
1821
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Alert, { children: deniedMessage });
1822
+ }
1823
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
1824
+ }
1825
+
1826
+ // src/field.tsx
1827
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1828
+ function Field({
1829
+ label,
1830
+ required,
1831
+ htmlFor,
1832
+ as = "div",
1833
+ className,
1834
+ children
1835
+ }) {
1836
+ const Wrapper = as;
1837
+ const labelNode = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
1838
+ label,
1839
+ required ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-destructive ml-0.5", "aria-hidden": "true", children: "*" }) : null
1840
+ ] });
1841
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Wrapper, { className: cn("space-y-1 text-sm", className), children: [
1842
+ htmlFor && as === "div" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { htmlFor, className: "text-muted-foreground", children: labelNode }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-muted-foreground", children: labelNode }),
1843
+ children
1844
+ ] });
1845
+ }
1846
+
1847
+ // src/image-uploader.tsx
1848
+ var import_lucide_react7 = require("lucide-react");
1849
+ var React14 = __toESM(require("react"), 1);
1850
+
1851
+ // src/input.tsx
1852
+ var React13 = __toESM(require("react"), 1);
1853
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1854
+ var inputClass = "h-9 w-full rounded-md border border-border bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
1855
+ var Input = React13.forwardRef(
1856
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("input", { ref, className: cn(inputClass, className), ...props })
1857
+ );
1858
+ Input.displayName = "Input";
1859
+
1860
+ // src/image-uploader.tsx
1861
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1862
+ function ImageUploader({
1863
+ value = "",
1864
+ onChange,
1865
+ disabled,
1866
+ label,
1867
+ className,
1868
+ allowUrlPaste = true,
1869
+ accept = "image/*,.gif",
1870
+ uploadFile,
1871
+ uploadFromUrl
1872
+ }) {
1873
+ const inputRef = React14.useRef(null);
1874
+ const [uploading, setUploading] = React14.useState(false);
1875
+ const [error, setError] = React14.useState(null);
1876
+ const busy = Boolean(disabled || uploading);
1877
+ const handleFile = async (file) => {
1878
+ if (!uploadFile) {
1879
+ setError("File upload is not configured for this panel.");
1880
+ return;
1881
+ }
1882
+ setUploading(true);
1883
+ setError(null);
1884
+ try {
1885
+ onChange(await uploadFile(file));
1886
+ } catch (err) {
1887
+ setError(err instanceof Error ? err.message : "Upload failed");
1888
+ } finally {
1889
+ setUploading(false);
1890
+ if (inputRef.current) inputRef.current.value = "";
1891
+ }
1892
+ };
1893
+ const handleUrl = async (imageUrl) => {
1894
+ const trimmed = imageUrl.trim();
1895
+ if (!trimmed) {
1896
+ onChange("");
1897
+ return;
1898
+ }
1899
+ if (trimmed === value) return;
1900
+ if (!uploadFromUrl || /^https?:\/\//i.test(trimmed)) {
1901
+ setError(null);
1902
+ onChange(trimmed);
1903
+ return;
1904
+ }
1905
+ setUploading(true);
1906
+ setError(null);
1907
+ try {
1908
+ onChange(await uploadFromUrl(trimmed));
1909
+ } catch (err) {
1910
+ setError(err instanceof Error ? err.message : "Upload failed");
1911
+ } finally {
1912
+ setUploading(false);
1913
+ }
1914
+ };
1915
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: cn("space-y-2", className), children: [
1916
+ label ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "text-muted-foreground text-xs font-medium", children: label }) : null,
1917
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
1918
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1919
+ "input",
1920
+ {
1921
+ ref: inputRef,
1922
+ type: "file",
1923
+ accept,
1924
+ className: "hidden",
1925
+ disabled: busy,
1926
+ onChange: (e) => {
1927
+ const file = e.target.files?.[0];
1928
+ if (file) void handleFile(file);
1929
+ }
1930
+ }
1931
+ ),
1932
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1933
+ Button,
1934
+ {
1935
+ type: "button",
1936
+ variant: "outline",
1937
+ size: "sm",
1938
+ disabled: busy,
1939
+ onClick: () => inputRef.current?.click(),
1940
+ children: [
1941
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react7.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react7.ImagePlus, { className: "h-4 w-4" }),
1942
+ uploading ? "Uploading\u2026" : "Upload"
1943
+ ]
1944
+ }
1945
+ ),
1946
+ value ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1947
+ Button,
1948
+ {
1949
+ type: "button",
1950
+ variant: "ghost",
1951
+ size: "sm",
1952
+ disabled: busy,
1953
+ onClick: () => onChange(""),
1954
+ "aria-label": "Clear image",
1955
+ children: [
1956
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react7.X, { className: "h-4 w-4" }),
1957
+ "Clear"
1958
+ ]
1959
+ }
1960
+ ) : null
1961
+ ] }),
1962
+ allowUrlPaste ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1963
+ Input,
1964
+ {
1965
+ defaultValue: value,
1966
+ disabled: busy,
1967
+ placeholder: "Or paste image URL\u2026",
1968
+ onBlur: (e) => {
1969
+ void handleUrl(e.target.value);
1970
+ },
1971
+ onKeyDown: (e) => {
1972
+ if (e.key === "Enter") {
1973
+ e.preventDefault();
1974
+ void handleUrl(e.target.value);
1975
+ }
1976
+ }
1977
+ },
1978
+ value || "empty"
1979
+ ) : null,
1980
+ value ? (
1981
+ // eslint-disable-next-line @next/next/no-img-element -- CDN URLs vary
1982
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1983
+ "img",
1984
+ {
1985
+ src: value,
1986
+ alt: "",
1987
+ className: "border-border max-h-24 rounded border bg-white object-contain p-1"
1988
+ }
1989
+ )
1990
+ ) : null,
1991
+ error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-destructive text-xs", role: "alert", children: error }) : null
1992
+ ] });
1993
+ }
1994
+
1995
+ // src/label.tsx
1996
+ var React15 = __toESM(require("react"), 1);
1997
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1998
+ var Label = React15.forwardRef(
1999
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2000
+ "label",
2001
+ {
2002
+ ref,
2003
+ className: cn(
2004
+ "text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
2005
+ className
2006
+ ),
2007
+ ...props
2008
+ }
2009
+ )
2010
+ );
2011
+ Label.displayName = "Label";
2012
+
2013
+ // src/page-header.tsx
2014
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2015
+ function PageHeader({
2016
+ title,
2017
+ description,
2018
+ eyebrow,
2019
+ actions,
2020
+ className
2021
+ }) {
2022
+ const heading = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
2023
+ eyebrow,
2024
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2025
+ "h1",
2026
+ {
2027
+ className: cn(
2028
+ "text-2xl font-semibold tracking-tight",
2029
+ eyebrow != null && "mt-1"
2030
+ ),
2031
+ children: title
2032
+ }
2033
+ ),
2034
+ description != null ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-muted-foreground mt-1 text-sm", children: description }) : null
2035
+ ] });
2036
+ if (!actions) {
2037
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className, children: heading });
2038
+ }
2039
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2040
+ "div",
2041
+ {
2042
+ className: cn(
2043
+ "flex flex-wrap items-center justify-between gap-3",
2044
+ className
2045
+ ),
2046
+ children: [
2047
+ heading,
2048
+ actions
2049
+ ]
2050
+ }
2051
+ );
2052
+ }
2053
+
2054
+ // src/panel-brand-mark.tsx
2055
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2056
+ function PanelBrandMark({
2057
+ children,
2058
+ size = "md",
2059
+ className,
2060
+ ...props
2061
+ }) {
2062
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2063
+ "div",
2064
+ {
2065
+ className: cn(
2066
+ "bg-primary text-primary-foreground grid shrink-0 place-items-center rounded-lg",
2067
+ size === "sm" ? "h-9 w-9" : "h-10 w-10",
2068
+ className
2069
+ ),
2070
+ ...props,
2071
+ children
2072
+ }
2073
+ );
2074
+ }
2075
+
2076
+ // src/panel-sign-in.tsx
2077
+ var import_lucide_react8 = require("lucide-react");
2078
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2079
+ function PanelSignIn({
2080
+ appName,
2081
+ eyebrow = "Secure Google sign-in",
2082
+ description = "Use your work Google account to continue.",
2083
+ features,
2084
+ brandIcon,
2085
+ error,
2086
+ refused = false,
2087
+ refusedTitle = "Access denied",
2088
+ refusedMessage = "This Google account is signed in, but it is not provisioned for this panel.",
2089
+ isSessionLoading = false,
2090
+ isSigningIn = false,
2091
+ onSignIn,
2092
+ signInLabel = "Continue with Google",
2093
+ className
2094
+ }) {
2095
+ const busy = isSessionLoading || isSigningIn;
2096
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2097
+ "main",
2098
+ {
2099
+ className: cn(
2100
+ "bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8",
2101
+ className
2102
+ ),
2103
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("section", { className: "border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm", children: [
2104
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3", children: [
2105
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PanelBrandMark, { children: brandIcon ?? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-sm font-semibold", "aria-hidden": true, children: appName.slice(0, 1).toUpperCase() }) }),
2106
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "min-w-0", children: [
2107
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-title truncate font-semibold", children: appName }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-muted-foreground text-meta", children: eyebrow })
2109
+ ] })
2110
+ ] }),
2111
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-2", children: [
2112
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-display font-semibold tracking-tight", children: refused ? refusedTitle : "Sign in" }),
2113
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-muted-foreground text-body", children: refused ? refusedMessage : description })
2114
+ ] }),
2115
+ features && features.length > 0 && !refused ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { className: "text-muted-foreground text-body space-y-1.5", children: features.slice(0, 3).map((feature) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("li", { className: "flex gap-2", children: [
2116
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current" }),
2117
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: feature })
2118
+ ] }, feature)) }) : null,
2119
+ error ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2120
+ "p",
2121
+ {
2122
+ role: "alert",
2123
+ className: "border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm",
2124
+ children: error
2125
+ }
2126
+ ) : null,
2127
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2128
+ Button,
2129
+ {
2130
+ className: "w-full",
2131
+ disabled: busy,
2132
+ onClick: onSignIn,
2133
+ "aria-busy": busy,
2134
+ children: [
2135
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react8.Loader2, { className: "mr-2 h-4 w-4 animate-spin", "aria-hidden": true }) : null,
2136
+ isSigningIn ? "Redirecting\u2026" : signInLabel
2137
+ ]
2138
+ }
2139
+ )
2140
+ ] })
2141
+ }
2142
+ );
2143
+ }
2144
+ function PanelSignInSkeleton({ className }) {
2145
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2146
+ "main",
2147
+ {
2148
+ className: cn(
2149
+ "bg-background grid min-h-screen place-items-center p-4 sm:p-8",
2150
+ className
2151
+ ),
2152
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm", children: [
2153
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "bg-muted h-3 w-24 animate-pulse rounded" }),
2154
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "bg-muted h-8 w-48 animate-pulse rounded" }),
2155
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "bg-muted mt-7 h-10 w-full animate-pulse rounded-md" })
2156
+ ] })
2157
+ }
2158
+ );
2159
+ }
2160
+
2161
+ // src/pagination.tsx
2162
+ var import_lucide_react9 = require("lucide-react");
2163
+ var React16 = __toESM(require("react"), 1);
2164
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2165
+ function Pagination({
2166
+ currentPage,
2167
+ totalPages,
2168
+ onPageChange,
2169
+ loading = false,
2170
+ showPageInfo = true
2171
+ }) {
2172
+ const visiblePages = React16.useMemo(() => {
2173
+ const delta = 2;
2174
+ const range = [];
2175
+ const rangeWithDots = [];
2176
+ for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) {
2177
+ range.push(i);
2178
+ }
2179
+ if (currentPage - delta > 2) {
2180
+ rangeWithDots.push(1, "...");
2181
+ } else {
2182
+ rangeWithDots.push(1);
2183
+ }
2184
+ rangeWithDots.push(...range);
2185
+ if (currentPage + delta < totalPages - 1) {
2186
+ rangeWithDots.push("...", totalPages);
2187
+ } else if (totalPages > 1) {
2188
+ rangeWithDots.push(totalPages);
2189
+ }
2190
+ return rangeWithDots;
2191
+ }, [currentPage, totalPages]);
2192
+ if (totalPages <= 1) return null;
2193
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center justify-between gap-4 sm:flex-row", children: [
2194
+ showPageInfo ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "text-muted-foreground order-2 text-sm sm:order-1", children: [
2195
+ "Page ",
2196
+ currentPage,
2197
+ " of ",
2198
+ totalPages
2199
+ ] }) : null,
2200
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "order-1 flex items-center space-x-1 sm:order-2 sm:space-x-2", children: [
2201
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2202
+ Button,
2203
+ {
2204
+ variant: "outline",
2205
+ size: "sm",
2206
+ onClick: () => onPageChange(currentPage - 1),
2207
+ disabled: currentPage <= 1 || loading,
2208
+ className: "h-8 min-w-8 px-2",
2209
+ "aria-label": "Previous page",
2210
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react9.ChevronLeft, { className: "h-4 w-4" })
2211
+ }
2212
+ ),
2213
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex max-w-[200px] items-center space-x-1 overflow-x-auto sm:max-w-none", children: visiblePages.map(
2214
+ (page, index) => page === "..." ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2215
+ "div",
2216
+ {
2217
+ className: "flex h-8 w-8 shrink-0 items-center justify-center",
2218
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react9.MoreHorizontal, { className: "h-4 w-4" })
2219
+ },
2220
+ `dots-${index}`
2221
+ ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2222
+ Button,
2223
+ {
2224
+ variant: page === currentPage ? "default" : "outline",
2225
+ size: "sm",
2226
+ onClick: () => onPageChange(page),
2227
+ disabled: loading,
2228
+ className: "h-8 min-w-8 shrink-0 px-2",
2229
+ "aria-current": page === currentPage ? "page" : void 0,
2230
+ children: page
2231
+ },
2232
+ page
2233
+ )
2234
+ ) }),
2235
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2236
+ Button,
2237
+ {
2238
+ variant: "outline",
2239
+ size: "sm",
2240
+ onClick: () => onPageChange(currentPage + 1),
2241
+ disabled: currentPage >= totalPages || loading,
2242
+ className: "h-8 min-w-8 px-2",
2243
+ "aria-label": "Next page",
2244
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react9.ChevronRight, { className: "h-4 w-4" })
2245
+ }
2246
+ )
2247
+ ] })
2248
+ ] });
2249
+ }
2250
+
2251
+ // src/segmented-control.tsx
2252
+ var React17 = __toESM(require("react"), 1);
2253
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2254
+ var TONE_ON = "bg-primary text-primary-foreground";
2255
+ var TONE_OFF = "text-muted-foreground hover:bg-muted";
2256
+ var TONES = {
2257
+ emphasis: { on: TONE_ON, off: TONE_OFF },
2258
+ primary: { on: TONE_ON, off: TONE_OFF }
2259
+ };
2260
+ var TRACKS = {
2261
+ contained: "border-border inline-flex rounded-md border p-0.5",
2262
+ loose: "flex flex-wrap gap-2"
2263
+ };
2264
+ function SegmentedControl({
2265
+ options,
2266
+ value,
2267
+ onChange,
2268
+ ariaLabel,
2269
+ variant = "contained",
2270
+ tone = "emphasis",
2271
+ fill = false,
2272
+ className
2273
+ }) {
2274
+ const refs = React17.useRef(/* @__PURE__ */ new Map());
2275
+ function onKeyDown(event) {
2276
+ const step = event.key === "ArrowRight" || event.key === "ArrowDown" ? 1 : event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 0;
2277
+ if (step === 0) return;
2278
+ const selectable = options.filter((option) => !option.disabled);
2279
+ if (selectable.length < 2) return;
2280
+ const current = selectable.findIndex((option) => option.value === value);
2281
+ const next = selectable[(current + step + selectable.length) % selectable.length];
2282
+ event.preventDefault();
2283
+ onChange(next.value);
2284
+ refs.current.get(next.value)?.focus();
2285
+ }
2286
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2287
+ "div",
2288
+ {
2289
+ role: "radiogroup",
2290
+ "aria-label": ariaLabel,
2291
+ onKeyDown,
2292
+ className: cn(TRACKS[variant], className),
2293
+ children: options.map((option) => {
2294
+ const checked = option.value === value;
2295
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2296
+ "button",
2297
+ {
2298
+ ref: (node) => {
2299
+ refs.current.set(option.value, node);
2300
+ },
2301
+ type: "button",
2302
+ role: "radio",
2303
+ "aria-checked": checked,
2304
+ disabled: option.disabled,
2305
+ title: option.title,
2306
+ tabIndex: checked ? 0 : -1,
2307
+ onClick: () => onChange(option.value),
2308
+ className: cn(
2309
+ "cursor-pointer rounded px-3 py-1 text-sm font-medium transition",
2310
+ "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
2311
+ "disabled:cursor-not-allowed disabled:opacity-50",
2312
+ fill && "flex-1",
2313
+ checked ? TONES[tone].on : TONES[tone].off
2314
+ ),
2315
+ children: option.label
2316
+ },
2317
+ option.value
2318
+ );
2319
+ })
2320
+ }
2321
+ );
2322
+ }
2323
+
2324
+ // src/select.tsx
2325
+ var React18 = __toESM(require("react"), 1);
2326
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2327
+ function optionText(node) {
2328
+ if (node == null || typeof node === "boolean") return "";
2329
+ if (typeof node === "string" || typeof node === "number") return String(node);
2330
+ if (Array.isArray(node)) return node.map(optionText).join("");
2331
+ if (React18.isValidElement(node)) {
2332
+ return optionText(node.props.children);
2333
+ }
2334
+ return "";
2335
+ }
2336
+ function optionsFromChildren(children) {
2337
+ const options = [];
2338
+ React18.Children.forEach(children, (child) => {
2339
+ if (!React18.isValidElement(child)) return;
2340
+ if (child.type === React18.Fragment) {
2341
+ options.push(
2342
+ ...optionsFromChildren(
2343
+ child.props.children
2344
+ )
2345
+ );
2346
+ return;
2347
+ }
2348
+ const props = child.props;
2349
+ const value = props.value == null ? "" : String(props.value);
2350
+ options.push({
2351
+ value,
2352
+ label: optionText(props.children).trim() || value,
2353
+ disabled: Boolean(props.disabled)
2354
+ });
2355
+ });
2356
+ return options;
2357
+ }
2358
+ function Select({
2359
+ id,
2360
+ className,
2361
+ disabled,
2362
+ value,
2363
+ placeholder,
2364
+ children,
2365
+ onChange,
2366
+ size = "default",
2367
+ "aria-label": ariaLabel
2368
+ }) {
2369
+ const options = optionsFromChildren(children);
2370
+ const current = Array.isArray(value) ? String(value[0] ?? "") : value == null ? "" : String(value);
2371
+ const blank = options.find((option) => option.value === "");
2372
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2373
+ Autocomplete,
2374
+ {
2375
+ id,
2376
+ className,
2377
+ disabled: Boolean(disabled),
2378
+ ariaLabel,
2379
+ size,
2380
+ options,
2381
+ value: current,
2382
+ clearable: false,
2383
+ placeholder: placeholder ?? blank?.label ?? "Search\u2026",
2384
+ onChange: (next) => onChange?.({
2385
+ target: { value: next },
2386
+ currentTarget: { value: next }
2387
+ })
2388
+ }
2389
+ );
2390
+ }
2391
+
2392
+ // src/separator.tsx
2393
+ var React19 = __toESM(require("react"), 1);
2394
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2395
+ var Separator = React19.forwardRef(
2396
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2397
+ "div",
2398
+ {
2399
+ ref,
2400
+ role: decorative ? "none" : "separator",
2401
+ "aria-orientation": orientation,
2402
+ className: cn(
2403
+ "bg-border shrink-0",
2404
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
2405
+ className
2406
+ ),
2407
+ ...props
2408
+ }
2409
+ )
2410
+ );
2411
+ Separator.displayName = "Separator";
2412
+
2413
+ // src/side-drawer.tsx
2414
+ var import_lucide_react10 = require("lucide-react");
2415
+ var React20 = __toESM(require("react"), 1);
2416
+ var import_react_dom3 = require("react-dom");
2417
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2418
+ function SideDrawer({
2419
+ isOpen,
2420
+ title,
2421
+ onClose,
2422
+ children,
2423
+ panelClassName
2424
+ }) {
2425
+ const mounted = useHasMounted();
2426
+ const headingId = React20.useId();
2427
+ const panelRef = React20.useRef(null);
2428
+ useDialogLayer({
2429
+ // Gated on `mounted` too: before that the panel is not rendered, so there
2430
+ // would be nothing to move focus into.
2431
+ active: isOpen && mounted,
2432
+ containerRef: panelRef,
2433
+ onEscape: onClose
2434
+ });
2435
+ if (!mounted || !isOpen) return null;
2436
+ return (0, import_react_dom3.createPortal)(
2437
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
2438
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2439
+ "div",
2440
+ {
2441
+ "aria-hidden": true,
2442
+ onClick: onClose,
2443
+ className: "fixed inset-0 z-[90] bg-overlay/30"
2444
+ }
2445
+ ),
2446
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
2447
+ "aside",
2448
+ {
2449
+ ref: panelRef,
2450
+ role: "dialog",
2451
+ "aria-modal": "true",
2452
+ "aria-labelledby": headingId,
2453
+ tabIndex: -1,
2454
+ className: cn(
2455
+ "border-border bg-background fixed inset-y-0 right-0 z-[95] flex flex-col border-l shadow-2xl outline-none",
2456
+ panelClassName ?? "w-full max-w-md"
2457
+ ),
2458
+ children: [
2459
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "border-border flex items-center justify-between gap-3 border-b px-4 py-3", children: [
2460
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { id: headingId, className: "truncate text-base font-semibold", children: title }),
2461
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2462
+ Button,
2463
+ {
2464
+ variant: "ghost",
2465
+ size: "icon",
2466
+ "aria-label": "Close panel",
2467
+ onClick: onClose,
2468
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react10.X, { className: "h-4 w-4", "aria-hidden": true })
2469
+ }
2470
+ )
2471
+ ] }),
2472
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children })
2473
+ ]
2474
+ }
2475
+ )
2476
+ ] }),
2477
+ document.body
2478
+ );
2479
+ }
2480
+
2481
+ // src/spreadsheet-grid.tsx
2482
+ var React21 = __toESM(require("react"), 1);
2483
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2484
+ function isInRange(range, r, c) {
2485
+ if (!range) return false;
2486
+ return r >= range.r1 && r <= range.r2 && c >= range.c1 && c <= range.c2;
2487
+ }
2488
+ function SpreadsheetGrid({
2489
+ columns,
2490
+ rows,
2491
+ rowKey,
2492
+ loading,
2493
+ emptyMessage = "Nothing to show.",
2494
+ loadingMessage = "Loading\u2026",
2495
+ ariaLabel = "Data grid",
2496
+ range,
2497
+ onRangeChange,
2498
+ onCopy
2499
+ }) {
2500
+ const gridRef = React21.useRef(null);
2501
+ const anchorRef = React21.useRef(null);
2502
+ const focusRef = React21.useRef(null);
2503
+ const [dragging, setDragging] = React21.useState(false);
2504
+ const setSelection = React21.useCallback(
2505
+ (anchor, focus) => {
2506
+ anchorRef.current = anchor;
2507
+ focusRef.current = focus;
2508
+ onRangeChange({ anchor, focus });
2509
+ },
2510
+ [onRangeChange]
2511
+ );
2512
+ const selectCell = React21.useCallback(
2513
+ (r, c, extend) => {
2514
+ if (extend && anchorRef.current)
2515
+ setSelection(anchorRef.current, { r, c });
2516
+ else setSelection({ r, c }, { r, c });
2517
+ },
2518
+ [setSelection]
2519
+ );
2520
+ const selectColumn = React21.useCallback(
2521
+ (c, extend) => {
2522
+ const lastRow = Math.max(rows.length - 1, 0);
2523
+ const anchorCol = extend && anchorRef.current ? anchorRef.current.c : c;
2524
+ setSelection({ r: 0, c: anchorCol }, { r: lastRow, c });
2525
+ },
2526
+ [rows.length, setSelection]
2527
+ );
2528
+ const selectRow = React21.useCallback(
2529
+ (r, extend) => {
2530
+ const lastCol = columns.length - 1;
2531
+ const anchorRow = extend && anchorRef.current ? anchorRef.current.r : r;
2532
+ setSelection({ r: anchorRow, c: 0 }, { r, c: lastCol });
2533
+ },
2534
+ [columns.length, setSelection]
2535
+ );
2536
+ const selectAll = React21.useCallback(() => {
2537
+ if (!rows.length || !columns.length) return;
2538
+ setSelection({ r: 0, c: 0 }, { r: rows.length - 1, c: columns.length - 1 });
2539
+ }, [rows.length, columns.length, setSelection]);
2540
+ const scrollCellIntoView = React21.useCallback((r, c) => {
2541
+ const cell = gridRef.current?.querySelector(`[data-cell="${r}-${c}"]`);
2542
+ cell?.scrollIntoView({ block: "nearest", inline: "nearest" });
2543
+ }, []);
2544
+ const moveFocus = React21.useCallback(
2545
+ (dr, dc, extend) => {
2546
+ if (!rows.length || !columns.length) return;
2547
+ const base = focusRef.current || { r: 0, c: 0 };
2548
+ const r = Math.min(Math.max(base.r + dr, 0), rows.length - 1);
2549
+ const c = Math.min(Math.max(base.c + dc, 0), columns.length - 1);
2550
+ selectCell(r, c, extend);
2551
+ scrollCellIntoView(r, c);
2552
+ },
2553
+ [rows.length, columns.length, selectCell, scrollCellIntoView]
2554
+ );
2555
+ React21.useEffect(() => {
2556
+ if (!dragging) return;
2557
+ const stop = () => setDragging(false);
2558
+ window.addEventListener("mouseup", stop);
2559
+ return () => window.removeEventListener("mouseup", stop);
2560
+ }, [dragging]);
2561
+ const handleKeyDown = (event) => {
2562
+ const meta = event.metaKey || event.ctrlKey;
2563
+ if (meta && event.key.toLowerCase() === "c") {
2564
+ event.preventDefault();
2565
+ onCopy();
2566
+ return;
2567
+ }
2568
+ if (meta && event.key.toLowerCase() === "a") {
2569
+ event.preventDefault();
2570
+ selectAll();
2571
+ return;
2572
+ }
2573
+ switch (event.key) {
2574
+ case "ArrowUp":
2575
+ event.preventDefault();
2576
+ moveFocus(-1, 0, event.shiftKey);
2577
+ break;
2578
+ case "ArrowDown":
2579
+ event.preventDefault();
2580
+ moveFocus(1, 0, event.shiftKey);
2581
+ break;
2582
+ case "ArrowLeft":
2583
+ event.preventDefault();
2584
+ moveFocus(0, -1, event.shiftKey);
2585
+ break;
2586
+ case "ArrowRight":
2587
+ case "Tab":
2588
+ event.preventDefault();
2589
+ moveFocus(0, 1, event.shiftKey && event.key !== "Tab");
2590
+ break;
2591
+ case "Escape":
2592
+ setSelection(null, null);
2593
+ break;
2594
+ default:
2595
+ break;
2596
+ }
2597
+ };
2598
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2599
+ "div",
2600
+ {
2601
+ ref: gridRef,
2602
+ tabIndex: 0,
2603
+ role: "grid",
2604
+ "aria-label": ariaLabel,
2605
+ onKeyDown: handleKeyDown,
2606
+ className: "border-border bg-background/80 overflow-x-auto rounded-lg border outline-none",
2607
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("table", { className: "w-full text-sm whitespace-nowrap select-none", children: [
2608
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("thead", { className: "text-muted-foreground border-border border-b text-left", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("tr", { children: [
2609
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2610
+ "th",
2611
+ {
2612
+ scope: "col",
2613
+ className: "w-10 cursor-pointer px-2 py-2 text-center font-medium",
2614
+ title: "Select everything",
2615
+ onMouseDown: () => selectAll(),
2616
+ children: "#"
2617
+ }
2618
+ ),
2619
+ columns.map((column, c) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2620
+ "th",
2621
+ {
2622
+ scope: "col",
2623
+ className: "cursor-pointer px-3 py-2 font-medium",
2624
+ title: `Select the ${column.title} column`,
2625
+ onMouseDown: (event) => selectColumn(c, event.shiftKey),
2626
+ children: column.title
2627
+ },
2628
+ column.key
2629
+ ))
2630
+ ] }) }),
2631
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("tbody", { children: rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2632
+ "td",
2633
+ {
2634
+ colSpan: columns.length + 1,
2635
+ className: "text-muted-foreground px-3 py-6 text-center",
2636
+ children: loading ? loadingMessage : emptyMessage
2637
+ }
2638
+ ) }) : rows.map((row, r) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
2639
+ "tr",
2640
+ {
2641
+ className: "border-border border-b",
2642
+ children: [
2643
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2644
+ "td",
2645
+ {
2646
+ className: "text-muted-foreground w-10 cursor-pointer px-2 py-2 text-center text-xs",
2647
+ title: "Select this row",
2648
+ onMouseDown: (event) => selectRow(r, event.shiftKey),
2649
+ children: r + 1
2650
+ }
2651
+ ),
2652
+ columns.map((column, c) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2653
+ "td",
2654
+ {
2655
+ "data-cell": `${r}-${c}`,
2656
+ onMouseDown: (event) => {
2657
+ selectCell(r, c, event.shiftKey);
2658
+ setDragging(true);
2659
+ gridRef.current?.focus();
2660
+ },
2661
+ onMouseEnter: () => {
2662
+ if (dragging) setSelection(anchorRef.current, { r, c });
2663
+ },
2664
+ className: `px-3 py-2 ${column.className || ""} ${isInRange(range, r, c) ? "bg-primary/15" : ""}`,
2665
+ title: column.className?.includes("truncate") ? column.value(row) : void 0,
2666
+ children: column.render ? column.render(row) : column.value(row)
2667
+ },
2668
+ column.key
2669
+ ))
2670
+ ]
2671
+ },
2672
+ rowKey ? rowKey(row, r) : String(r)
2673
+ )) })
2674
+ ] })
2675
+ }
2676
+ );
2677
+ }
2678
+
2679
+ // src/switch.tsx
2680
+ var React22 = __toESM(require("react"), 1);
2681
+ var import_jsx_runtime30 = require("react/jsx-runtime");
2682
+ var Switch = React22.forwardRef(
2683
+ ({ checked, onCheckedChange, className, disabled, id, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
2684
+ "button",
2685
+ {
2686
+ ref,
2687
+ id,
2688
+ type: "button",
2689
+ role: "switch",
2690
+ "aria-checked": checked,
2691
+ disabled,
2692
+ onClick: () => onCheckedChange(!checked),
2693
+ className: cn(
2694
+ // 24×44px track meets DESIGN.md 24px minimum target size.
2695
+ "relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border transition-colors",
2696
+ "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
2697
+ "disabled:cursor-not-allowed disabled:opacity-50",
2698
+ checked ? "border-primary bg-primary" : "border-border bg-muted",
2699
+ className
2700
+ ),
2701
+ ...props,
2702
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
2703
+ "span",
2704
+ {
2705
+ "aria-hidden": true,
2706
+ className: cn(
2707
+ "bg-background pointer-events-none block size-5 rounded-full shadow-sm transition-transform",
2708
+ checked ? "translate-x-5" : "translate-x-0.5"
2709
+ )
2710
+ }
2711
+ )
2712
+ }
2713
+ )
2714
+ );
2715
+ Switch.displayName = "Switch";
2716
+
2717
+ // src/table.tsx
2718
+ var React23 = __toESM(require("react"), 1);
2719
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2720
+ var Table = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2721
+ "table",
2722
+ {
2723
+ ref,
2724
+ className: cn("w-full caption-bottom text-sm", className),
2725
+ ...props
2726
+ }
2727
+ ) }));
2728
+ Table.displayName = "Table";
2729
+ var TableHeader = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
2730
+ TableHeader.displayName = "TableHeader";
2731
+ var TableBody = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2732
+ "tbody",
2733
+ {
2734
+ ref,
2735
+ className: cn("[&_tr:last-child]:border-0", className),
2736
+ ...props
2737
+ }
2738
+ ));
2739
+ TableBody.displayName = "TableBody";
2740
+ var TableFooter = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2741
+ "tfoot",
2742
+ {
2743
+ ref,
2744
+ className: cn(
2745
+ "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
2746
+ className
2747
+ ),
2748
+ ...props
2749
+ }
2750
+ ));
2751
+ TableFooter.displayName = "TableFooter";
2752
+ var TableRow = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2753
+ "tr",
2754
+ {
2755
+ ref,
2756
+ className: cn(
2757
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
2758
+ className
2759
+ ),
2760
+ ...props
2761
+ }
2762
+ ));
2763
+ TableRow.displayName = "TableRow";
2764
+ var TableHead = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2765
+ "th",
2766
+ {
2767
+ ref,
2768
+ className: cn(
2769
+ "text-muted-foreground h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0",
2770
+ className
2771
+ ),
2772
+ ...props
2773
+ }
2774
+ ));
2775
+ TableHead.displayName = "TableHead";
2776
+ var TableCell = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2777
+ "td",
2778
+ {
2779
+ ref,
2780
+ className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
2781
+ ...props
2782
+ }
2783
+ ));
2784
+ TableCell.displayName = "TableCell";
2785
+ var TableCaption = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2786
+ "caption",
2787
+ {
2788
+ ref,
2789
+ className: cn("text-muted-foreground mt-4 text-sm", className),
2790
+ ...props
2791
+ }
2792
+ ));
2793
+ TableCaption.displayName = "TableCaption";
2794
+
2795
+ // src/tabs.tsx
2796
+ var React24 = __toESM(require("react"), 1);
2797
+ var import_jsx_runtime32 = require("react/jsx-runtime");
2798
+ function TabPanel({
2799
+ id,
2800
+ labelledBy,
2801
+ active,
2802
+ children,
2803
+ className
2804
+ }) {
2805
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
2806
+ "div",
2807
+ {
2808
+ role: "tabpanel",
2809
+ id,
2810
+ "aria-labelledby": labelledBy,
2811
+ hidden: !active,
2812
+ className,
2813
+ children: active ? children : null
2814
+ }
2815
+ );
2816
+ }
2817
+ function Tabs({
2818
+ tabs,
2819
+ value,
2820
+ onChange,
2821
+ ariaLabel,
2822
+ className
2823
+ }) {
2824
+ const refs = React24.useRef(/* @__PURE__ */ new Map());
2825
+ const reactId = React24.useId();
2826
+ const hasInlinePanels = tabs.some((tab) => tab.panel != null);
2827
+ function tabDomId(key) {
2828
+ return `${reactId}-tab-${key}`;
2829
+ }
2830
+ function panelDomId(tab) {
2831
+ return tab.panelId ?? `${reactId}-panel-${tab.key}`;
2832
+ }
2833
+ function focusTab(key) {
2834
+ onChange(key);
2835
+ refs.current.get(key)?.focus();
2836
+ }
2837
+ function onKeyDown(event) {
2838
+ const step = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
2839
+ if (step === 0) return;
2840
+ const selectable = tabs.filter((tab) => !tab.disabled);
2841
+ if (selectable.length < 2) return;
2842
+ const current = selectable.findIndex((tab) => tab.key === value);
2843
+ const next = selectable[(current + step + selectable.length) % selectable.length];
2844
+ event.preventDefault();
2845
+ focusTab(next.key);
2846
+ }
2847
+ const tablist = /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
2848
+ "div",
2849
+ {
2850
+ role: "tablist",
2851
+ "aria-label": ariaLabel,
2852
+ onKeyDown,
2853
+ className: cn(
2854
+ "border-border flex flex-wrap gap-1 border-b",
2855
+ !hasInlinePanels ? className : void 0
2856
+ ),
2857
+ children: tabs.map((tab) => {
2858
+ const active = tab.key === value;
2859
+ const id = tabDomId(tab.key);
2860
+ const controls = tab.panel != null || tab.panelId ? panelDomId(tab) : void 0;
2861
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
2862
+ "button",
2863
+ {
2864
+ id,
2865
+ ref: (node) => {
2866
+ refs.current.set(tab.key, node);
2867
+ },
2868
+ type: "button",
2869
+ role: "tab",
2870
+ "aria-selected": active,
2871
+ "aria-controls": controls,
2872
+ disabled: tab.disabled,
2873
+ tabIndex: active ? 0 : -1,
2874
+ onClick: () => onChange(tab.key),
2875
+ className: cn(
2876
+ "cursor-pointer rounded-t-md px-3 py-1.5 text-sm font-medium transition",
2877
+ "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
2878
+ "disabled:cursor-not-allowed disabled:opacity-50",
2879
+ // The filled-pill active state the five hand-rolled strips
2880
+ // already used. Adopting it keeps this a deduplication rather
2881
+ // than a restyle of every panel that has tabs.
2882
+ active ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
2883
+ ),
2884
+ children: [
2885
+ tab.label,
2886
+ tab.badge != null ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-muted-foreground ml-1.5 text-xs", children: tab.badge }) : null
2887
+ ]
2888
+ },
2889
+ tab.key
2890
+ );
2891
+ })
2892
+ }
2893
+ );
2894
+ if (!hasInlinePanels) return tablist;
2895
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cn("space-y-3", className), children: [
2896
+ tablist,
2897
+ tabs.map(
2898
+ (tab) => tab.panel != null ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
2899
+ TabPanel,
2900
+ {
2901
+ id: panelDomId(tab),
2902
+ labelledBy: tabDomId(tab.key),
2903
+ active: tab.key === value,
2904
+ children: tab.panel
2905
+ },
2906
+ tab.key
2907
+ ) : null
2908
+ )
2909
+ ] });
2910
+ }
2911
+
2912
+ // src/textarea.tsx
2913
+ var React25 = __toESM(require("react"), 1);
2914
+ var import_jsx_runtime33 = require("react/jsx-runtime");
2915
+ var textareaClass = "border-border bg-background focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50";
2916
+ var Textarea = React25.forwardRef(
2917
+ ({ className, rows = 3, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
2918
+ "textarea",
2919
+ {
2920
+ ref,
2921
+ rows,
2922
+ className: cn(textareaClass, className),
2923
+ ...props
2924
+ }
2925
+ )
2926
+ );
2927
+ Textarea.displayName = "Textarea";
2928
+ // Annotate the CommonJS export names for ESM import in node:
2929
+ 0 && (module.exports = {
2930
+ Alert,
2931
+ Autocomplete,
2932
+ Badge,
2933
+ Breadcrumb,
2934
+ Button,
2935
+ CSV_DELIMITER,
2936
+ Card,
2937
+ CardContent,
2938
+ CardDescription,
2939
+ CardFooter,
2940
+ CardHeader,
2941
+ CardTitle,
2942
+ Checkbox,
2943
+ CollapsibleSection,
2944
+ ConfirmDialog,
2945
+ CopyButton,
2946
+ DataTable,
2947
+ DateRangePicker,
2948
+ FeatureAccessGate,
2949
+ Field,
2950
+ ImageUploader,
2951
+ Input,
2952
+ Label,
2953
+ Modal,
2954
+ PageHeader,
2955
+ Pagination,
2956
+ PanelBrandMark,
2957
+ PanelSignIn,
2958
+ PanelSignInSkeleton,
2959
+ SegmentedControl,
2960
+ Select,
2961
+ Separator,
2962
+ SideDrawer,
2963
+ Spinner,
2964
+ SpreadsheetGrid,
2965
+ StatePanel,
2966
+ Switch,
2967
+ TSV_DELIMITER,
2968
+ TabPanel,
2969
+ Table,
2970
+ TableBody,
2971
+ TableCaption,
2972
+ TableCell,
2973
+ TableFooter,
2974
+ TableHead,
2975
+ TableHeader,
2976
+ TableRow,
2977
+ Tabs,
2978
+ Textarea,
2979
+ addDays,
2980
+ addMonths,
2981
+ alertVariants,
2982
+ badgeVariants,
2983
+ buildRangeText,
2984
+ checkboxClass,
2985
+ cn,
2986
+ countCells,
2987
+ createdRangeMs,
2988
+ describeRange,
2989
+ endAt2359Ms,
2990
+ endOfDayMs,
2991
+ escapeCell,
2992
+ formatDisplay,
2993
+ fromIsoDate,
2994
+ fullRange,
2995
+ inputClass,
2996
+ isSameDay,
2997
+ monthGrid,
2998
+ monthLabel,
2999
+ normalizeRange,
3000
+ startOfDayMs,
3001
+ startOfMonth,
3002
+ textareaClass,
3003
+ toIsoDate,
3004
+ useDialogLayer,
3005
+ useHasMounted,
3006
+ writeToClipboard
3007
+ });
3008
+ //# sourceMappingURL=index.cjs.map