@exxatdesignux/ui 0.2.18 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (618) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/bin/sync-extras.mjs +116 -29
  3. package/consumer-extras/README.md +43 -4
  4. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
  5. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
  6. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
  7. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
  8. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
  9. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
  10. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
  11. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
  12. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +41 -0
  13. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
  14. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
  15. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
  16. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
  17. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
  18. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
  19. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
  20. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
  21. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
  22. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
  23. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
  24. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
  25. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
  26. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
  27. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
  28. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
  29. package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +28 -0
  30. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
  31. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
  32. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
  33. package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
  34. package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
  35. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
  36. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +9 -9
  37. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  38. package/consumer-extras/handbook/HANDBOOK.md +185 -0
  39. package/consumer-extras/handbook/glossary.md +57 -0
  40. package/consumer-extras/handbook/reference-implementations.md +126 -0
  41. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  42. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  43. package/consumer-extras/patterns/data-views-pattern.md +14 -14
  44. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  45. package/dist/components/data-table/filter-date-calendar.js +280 -0
  46. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  47. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  48. package/dist/components/data-table/filter-text-value-input.js +561 -0
  49. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  50. package/dist/components/data-table/index.d.ts +45 -0
  51. package/dist/components/data-table/index.js +3085 -0
  52. package/dist/components/data-table/index.js.map +1 -0
  53. package/dist/components/data-table/pagination.d.ts +28 -0
  54. package/dist/components/data-table/pagination.js +3264 -0
  55. package/dist/components/data-table/pagination.js.map +1 -0
  56. package/dist/components/data-table/types.d.ts +84 -0
  57. package/dist/components/data-table/types.js +3 -0
  58. package/dist/components/data-table/types.js.map +1 -0
  59. package/dist/components/data-table/use-table-state.d.ts +116 -0
  60. package/dist/components/data-table/use-table-state.js +670 -0
  61. package/dist/components/data-table/use-table-state.js.map +1 -0
  62. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  63. package/dist/components/data-views/board-card-primitives.js +84 -0
  64. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  65. package/dist/components/data-views/data-row-list.d.ts +33 -0
  66. package/dist/components/data-views/data-row-list.js +106 -0
  67. package/dist/components/data-views/data-row-list.js.map +1 -0
  68. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  69. package/dist/components/data-views/finder-panel-view.js +388 -0
  70. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  71. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  72. package/dist/components/data-views/folder-grid-view.js +58 -0
  73. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  74. package/dist/components/data-views/hub-table.d.ts +167 -0
  75. package/dist/components/data-views/hub-table.js +5561 -0
  76. package/dist/components/data-views/hub-table.js.map +1 -0
  77. package/dist/components/data-views/index.d.ts +27 -0
  78. package/dist/components/data-views/index.js +6575 -0
  79. package/dist/components/data-views/index.js.map +1 -0
  80. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  81. package/dist/components/data-views/list-page-board-card.js +264 -0
  82. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  83. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  84. package/dist/components/data-views/list-page-board-template.js +137 -0
  85. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  86. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  87. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  88. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  89. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  90. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  91. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  92. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  93. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  94. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  95. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  96. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  97. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  98. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  99. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  100. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  101. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  102. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  103. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  104. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  105. package/dist/components/data-views/os-folder-glyph.js +104 -0
  106. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  107. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  108. package/dist/components/data-views/outline-tree-menu.js +131 -0
  109. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  110. package/dist/components/table-properties/column-row.d.ts +22 -0
  111. package/dist/components/table-properties/column-row.js +153 -0
  112. package/dist/components/table-properties/column-row.js.map +1 -0
  113. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  114. package/dist/components/table-properties/draggable-list.js +53 -0
  115. package/dist/components/table-properties/draggable-list.js.map +1 -0
  116. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  117. package/dist/components/table-properties/drawer-button.js +2748 -0
  118. package/dist/components/table-properties/drawer-button.js.map +1 -0
  119. package/dist/components/table-properties/drawer.d.ts +100 -0
  120. package/dist/components/table-properties/drawer.js +2595 -0
  121. package/dist/components/table-properties/drawer.js.map +1 -0
  122. package/dist/components/table-properties/filter-card.d.ts +24 -0
  123. package/dist/components/table-properties/filter-card.js +854 -0
  124. package/dist/components/table-properties/filter-card.js.map +1 -0
  125. package/dist/components/table-properties/index.d.ts +14 -0
  126. package/dist/components/table-properties/index.js +2768 -0
  127. package/dist/components/table-properties/index.js.map +1 -0
  128. package/dist/components/table-properties/sort-card.d.ts +20 -0
  129. package/dist/components/table-properties/sort-card.js +102 -0
  130. package/dist/components/table-properties/sort-card.js.map +1 -0
  131. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  132. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  133. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  134. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  135. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  136. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  137. package/dist/components/templates/index.d.ts +9 -0
  138. package/dist/components/templates/index.js +2720 -0
  139. package/dist/components/templates/index.js.map +1 -0
  140. package/dist/components/templates/list-page.d.ts +83 -0
  141. package/dist/components/templates/list-page.js +2433 -0
  142. package/dist/components/templates/list-page.js.map +1 -0
  143. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  144. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  145. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  146. package/dist/components/ui/accordion.d.ts +10 -0
  147. package/dist/components/ui/accordion.js +74 -0
  148. package/dist/components/ui/accordion.js.map +1 -0
  149. package/dist/components/ui/alert-dialog.d.ts +37 -0
  150. package/dist/components/ui/alert-dialog.js +201 -0
  151. package/dist/components/ui/alert-dialog.js.map +1 -0
  152. package/dist/components/ui/avatar.d.ts +84 -0
  153. package/dist/components/ui/avatar.js +328 -0
  154. package/dist/components/ui/avatar.js.map +1 -0
  155. package/dist/components/ui/badge.d.ts +13 -0
  156. package/dist/components/ui/badge.js +49 -0
  157. package/dist/components/ui/badge.js.map +1 -0
  158. package/dist/components/ui/banner.d.ts +62 -0
  159. package/dist/components/ui/banner.js +364 -0
  160. package/dist/components/ui/banner.js.map +1 -0
  161. package/dist/components/ui/breadcrumb.d.ts +14 -0
  162. package/dist/components/ui/breadcrumb.js +114 -0
  163. package/dist/components/ui/breadcrumb.js.map +1 -0
  164. package/dist/components/ui/button.d.ts +16 -0
  165. package/dist/components/ui/button.js +59 -0
  166. package/dist/components/ui/button.js.map +1 -0
  167. package/dist/components/ui/calendar.d.ts +13 -0
  168. package/dist/components/ui/calendar.js +238 -0
  169. package/dist/components/ui/calendar.js.map +1 -0
  170. package/dist/components/ui/card.d.ts +14 -0
  171. package/dist/components/ui/card.js +102 -0
  172. package/dist/components/ui/card.js.map +1 -0
  173. package/dist/components/ui/chart.d.ts +58 -0
  174. package/dist/components/ui/chart.js +292 -0
  175. package/dist/components/ui/chart.js.map +1 -0
  176. package/dist/components/ui/checkbox.d.ts +23 -0
  177. package/dist/components/ui/checkbox.js +155 -0
  178. package/dist/components/ui/checkbox.js.map +1 -0
  179. package/dist/components/ui/coach-mark.d.ts +27 -0
  180. package/dist/components/ui/coach-mark.js +306 -0
  181. package/dist/components/ui/coach-mark.js.map +1 -0
  182. package/dist/components/ui/collapsible.d.ts +8 -0
  183. package/dist/components/ui/collapsible.js +35 -0
  184. package/dist/components/ui/collapsible.js.map +1 -0
  185. package/dist/components/ui/command.d.ts +36 -0
  186. package/dist/components/ui/command.js +274 -0
  187. package/dist/components/ui/command.js.map +1 -0
  188. package/dist/components/ui/context-menu.d.ts +32 -0
  189. package/dist/components/ui/context-menu.js +245 -0
  190. package/dist/components/ui/context-menu.js.map +1 -0
  191. package/dist/components/ui/date-picker-field.d.ts +38 -0
  192. package/dist/components/ui/date-picker-field.js +550 -0
  193. package/dist/components/ui/date-picker-field.js.map +1 -0
  194. package/dist/components/ui/dialog.d.ts +22 -0
  195. package/dist/components/ui/dialog.js +200 -0
  196. package/dist/components/ui/dialog.js.map +1 -0
  197. package/dist/components/ui/dot-pattern.d.ts +21 -0
  198. package/dist/components/ui/dot-pattern.js +139 -0
  199. package/dist/components/ui/dot-pattern.js.map +1 -0
  200. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  201. package/dist/components/ui/drag-handle-grip.js +15 -0
  202. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  203. package/dist/components/ui/drawer.d.ts +16 -0
  204. package/dist/components/ui/drawer.js +125 -0
  205. package/dist/components/ui/drawer.js.map +1 -0
  206. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  207. package/dist/components/ui/dropdown-menu.js +353 -0
  208. package/dist/components/ui/dropdown-menu.js.map +1 -0
  209. package/dist/components/ui/export-drawer.d.ts +11 -0
  210. package/dist/components/ui/export-drawer.js +1658 -0
  211. package/dist/components/ui/export-drawer.js.map +1 -0
  212. package/dist/components/ui/field.d.ts +30 -0
  213. package/dist/components/ui/field.js +249 -0
  214. package/dist/components/ui/field.js.map +1 -0
  215. package/dist/components/ui/form.d.ts +28 -0
  216. package/dist/components/ui/form.js +110 -0
  217. package/dist/components/ui/form.js.map +1 -0
  218. package/dist/components/ui/hover-card.d.ts +9 -0
  219. package/dist/components/ui/hover-card.js +43 -0
  220. package/dist/components/ui/hover-card.js.map +1 -0
  221. package/dist/components/ui/input-group.d.ts +20 -0
  222. package/dist/components/ui/input-group.js +219 -0
  223. package/dist/components/ui/input-group.js.map +1 -0
  224. package/dist/components/ui/input-mask.d.ts +39 -0
  225. package/dist/components/ui/input-mask.js +118 -0
  226. package/dist/components/ui/input-mask.js.map +1 -0
  227. package/dist/components/ui/input.d.ts +5 -0
  228. package/dist/components/ui/input.js +30 -0
  229. package/dist/components/ui/input.js.map +1 -0
  230. package/dist/components/ui/kbd.d.ts +20 -0
  231. package/dist/components/ui/kbd.js +45 -0
  232. package/dist/components/ui/kbd.js.map +1 -0
  233. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  234. package/dist/components/ui/key-metrics-context.js +26 -0
  235. package/dist/components/ui/key-metrics-context.js.map +1 -0
  236. package/dist/components/ui/key-metrics.d.ts +131 -0
  237. package/dist/components/ui/key-metrics.js +1015 -0
  238. package/dist/components/ui/key-metrics.js.map +1 -0
  239. package/dist/components/ui/label.d.ts +6 -0
  240. package/dist/components/ui/label.js +28 -0
  241. package/dist/components/ui/label.js.map +1 -0
  242. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  243. package/dist/components/ui/list-page-view-frame.js +24 -0
  244. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  245. package/dist/components/ui/page-header.d.ts +51 -0
  246. package/dist/components/ui/page-header.js +372 -0
  247. package/dist/components/ui/page-header.js.map +1 -0
  248. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  249. package/dist/components/ui/payment-card-fields.js +80 -0
  250. package/dist/components/ui/payment-card-fields.js.map +1 -0
  251. package/dist/components/ui/popover.d.ts +10 -0
  252. package/dist/components/ui/popover.js +47 -0
  253. package/dist/components/ui/popover.js.map +1 -0
  254. package/dist/components/ui/radio-group.d.ts +29 -0
  255. package/dist/components/ui/radio-group.js +190 -0
  256. package/dist/components/ui/radio-group.js.map +1 -0
  257. package/dist/components/ui/resizable.d.ts +16 -0
  258. package/dist/components/ui/resizable.js +51 -0
  259. package/dist/components/ui/resizable.js.map +1 -0
  260. package/dist/components/ui/scroll-area.d.ts +8 -0
  261. package/dist/components/ui/scroll-area.js +66 -0
  262. package/dist/components/ui/scroll-area.js.map +1 -0
  263. package/dist/components/ui/select.d.ts +18 -0
  264. package/dist/components/ui/select.js +186 -0
  265. package/dist/components/ui/select.js.map +1 -0
  266. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  267. package/dist/components/ui/selection-tile-grid.js +347 -0
  268. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  269. package/dist/components/ui/separator.d.ts +7 -0
  270. package/dist/components/ui/separator.js +33 -0
  271. package/dist/components/ui/separator.js.map +1 -0
  272. package/dist/components/ui/sheet.d.ts +18 -0
  273. package/dist/components/ui/sheet.js +181 -0
  274. package/dist/components/ui/sheet.js.map +1 -0
  275. package/dist/components/ui/sidebar.d.ts +94 -0
  276. package/dist/components/ui/sidebar.js +805 -0
  277. package/dist/components/ui/sidebar.js.map +1 -0
  278. package/dist/components/ui/skeleton.d.ts +5 -0
  279. package/dist/components/ui/skeleton.js +22 -0
  280. package/dist/components/ui/skeleton.js.map +1 -0
  281. package/dist/components/ui/slider.d.ts +7 -0
  282. package/dist/components/ui/slider.js +66 -0
  283. package/dist/components/ui/slider.js.map +1 -0
  284. package/dist/components/ui/sonner.d.ts +6 -0
  285. package/dist/components/ui/sonner.js +38 -0
  286. package/dist/components/ui/sonner.js.map +1 -0
  287. package/dist/components/ui/status-badge.d.ts +38 -0
  288. package/dist/components/ui/status-badge.js +77 -0
  289. package/dist/components/ui/status-badge.js.map +1 -0
  290. package/dist/components/ui/table.d.ts +13 -0
  291. package/dist/components/ui/table.js +115 -0
  292. package/dist/components/ui/table.js.map +1 -0
  293. package/dist/components/ui/tabs.d.ts +15 -0
  294. package/dist/components/ui/tabs.js +93 -0
  295. package/dist/components/ui/tabs.js.map +1 -0
  296. package/dist/components/ui/textarea.d.ts +6 -0
  297. package/dist/components/ui/textarea.js +25 -0
  298. package/dist/components/ui/textarea.js.map +1 -0
  299. package/dist/components/ui/tip.d.ts +12 -0
  300. package/dist/components/ui/tip.js +61 -0
  301. package/dist/components/ui/tip.js.map +1 -0
  302. package/dist/components/ui/toggle-group.d.ts +14 -0
  303. package/dist/components/ui/toggle-group.js +104 -0
  304. package/dist/components/ui/toggle-group.js.map +1 -0
  305. package/dist/components/ui/toggle-switch.d.ts +10 -0
  306. package/dist/components/ui/toggle-switch.js +33 -0
  307. package/dist/components/ui/toggle-switch.js.map +1 -0
  308. package/dist/components/ui/toggle.d.ts +13 -0
  309. package/dist/components/ui/toggle.js +51 -0
  310. package/dist/components/ui/toggle.js.map +1 -0
  311. package/dist/components/ui/tooltip.d.ts +10 -0
  312. package/dist/components/ui/tooltip.js +68 -0
  313. package/dist/components/ui/tooltip.js.map +1 -0
  314. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  315. package/dist/components/ui/view-segmented-control.js +167 -0
  316. package/dist/components/ui/view-segmented-control.js.map +1 -0
  317. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  318. package/dist/hooks/use-app-theme.d.ts +24 -0
  319. package/dist/hooks/use-app-theme.js +286 -0
  320. package/dist/hooks/use-app-theme.js.map +1 -0
  321. package/dist/hooks/use-coach-mark.d.ts +86 -0
  322. package/dist/hooks/use-coach-mark.js +218 -0
  323. package/dist/hooks/use-coach-mark.js.map +1 -0
  324. package/dist/hooks/use-mobile.d.ts +3 -0
  325. package/dist/hooks/use-mobile.js +29 -0
  326. package/dist/hooks/use-mobile.js.map +1 -0
  327. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  328. package/dist/hooks/use-mod-key-label.js +25 -0
  329. package/dist/hooks/use-mod-key-label.js.map +1 -0
  330. package/dist/index.d.ts +120 -0
  331. package/dist/index.js +13324 -0
  332. package/dist/index.js.map +1 -0
  333. package/dist/lib/compose-refs.d.ts +6 -0
  334. package/dist/lib/compose-refs.js +17 -0
  335. package/dist/lib/compose-refs.js.map +1 -0
  336. package/dist/lib/conditional-rule-match.d.ts +30 -0
  337. package/dist/lib/conditional-rule-match.js +66 -0
  338. package/dist/lib/conditional-rule-match.js.map +1 -0
  339. package/dist/lib/data-list-display-options.d.ts +26 -0
  340. package/dist/lib/data-list-display-options.js +14 -0
  341. package/dist/lib/data-list-display-options.js.map +1 -0
  342. package/dist/lib/data-list-view-registry.d.ts +2 -0
  343. package/dist/lib/data-list-view-registry.js +102 -0
  344. package/dist/lib/data-list-view-registry.js.map +1 -0
  345. package/dist/lib/data-list-view-surface.d.ts +2 -0
  346. package/dist/lib/data-list-view-surface.js +80 -0
  347. package/dist/lib/data-list-view-surface.js.map +1 -0
  348. package/dist/lib/data-list-view.d.ts +21 -0
  349. package/dist/lib/data-list-view.js +25 -0
  350. package/dist/lib/data-list-view.js.map +1 -0
  351. package/dist/lib/date-filter.d.ts +22 -0
  352. package/dist/lib/date-filter.js +61 -0
  353. package/dist/lib/date-filter.js.map +1 -0
  354. package/dist/lib/dev-log.d.ts +8 -0
  355. package/dist/lib/dev-log.js +10 -0
  356. package/dist/lib/dev-log.js.map +1 -0
  357. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  358. package/dist/lib/dropdown-menu-surface.js +6 -0
  359. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  360. package/dist/lib/editable-target.d.ts +12 -0
  361. package/dist/lib/editable-target.js +12 -0
  362. package/dist/lib/editable-target.js.map +1 -0
  363. package/dist/lib/list-page-table-properties.d.ts +35 -0
  364. package/dist/lib/list-page-table-properties.js +81 -0
  365. package/dist/lib/list-page-table-properties.js.map +1 -0
  366. package/dist/lib/raf-throttle.d.ts +23 -0
  367. package/dist/lib/raf-throttle.js +27 -0
  368. package/dist/lib/raf-throttle.js.map +1 -0
  369. package/dist/lib/row-height.d.ts +16 -0
  370. package/dist/lib/row-height.js +10 -0
  371. package/dist/lib/row-height.js.map +1 -0
  372. package/dist/lib/table-properties-types.d.ts +83 -0
  373. package/dist/lib/table-properties-types.js +19 -0
  374. package/dist/lib/table-properties-types.js.map +1 -0
  375. package/dist/lib/utils.d.ts +5 -0
  376. package/dist/lib/utils.js +11 -0
  377. package/dist/lib/utils.js.map +1 -0
  378. package/package.json +83 -18
  379. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  380. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  381. package/src/components/data-table/index.tsx +1678 -0
  382. package/src/components/data-table/pagination.tsx +255 -0
  383. package/src/components/data-table/types.ts +96 -0
  384. package/src/components/data-table/use-table-state.ts +767 -0
  385. package/src/components/data-views/board-card-primitives.tsx +93 -0
  386. package/src/components/data-views/data-row-list.tsx +183 -0
  387. package/src/components/data-views/finder-panel-view.tsx +405 -0
  388. package/src/components/data-views/folder-grid-view.tsx +86 -0
  389. package/src/components/data-views/hub-table.tsx +498 -0
  390. package/src/components/data-views/index.ts +28 -0
  391. package/src/components/data-views/list-page-board-card.tsx +192 -0
  392. package/src/components/data-views/list-page-board-template.tsx +122 -0
  393. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  394. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  395. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  396. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  397. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  398. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  399. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  400. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  401. package/src/components/table-properties/column-row.tsx +90 -0
  402. package/src/components/table-properties/draggable-list.ts +54 -0
  403. package/src/components/table-properties/drawer-button.tsx +300 -0
  404. package/src/components/table-properties/drawer.tsx +1148 -0
  405. package/src/components/table-properties/filter-card.tsx +251 -0
  406. package/src/components/table-properties/index.ts +36 -0
  407. package/src/components/table-properties/sort-card.tsx +63 -0
  408. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  409. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  410. package/src/components/templates/index.ts +33 -0
  411. package/src/components/templates/list-page.tsx +602 -0
  412. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  413. package/src/components/ui/accordion.tsx +92 -0
  414. package/src/components/ui/alert-dialog.tsx +221 -0
  415. package/src/components/ui/avatar.tsx +13 -2
  416. package/src/components/ui/banner.tsx +2 -2
  417. package/src/components/ui/calendar.tsx +1 -1
  418. package/src/components/ui/coach-mark.tsx +1 -1
  419. package/src/components/ui/context-menu.tsx +291 -0
  420. package/src/components/ui/date-picker-field.tsx +2 -2
  421. package/src/components/ui/dot-pattern.tsx +183 -0
  422. package/src/components/ui/export-drawer.tsx +375 -0
  423. package/src/components/ui/hover-card.tsx +66 -0
  424. package/src/components/ui/key-metrics-context.tsx +78 -0
  425. package/src/components/ui/key-metrics.tsx +1133 -0
  426. package/src/components/ui/list-page-view-frame.tsx +64 -0
  427. package/src/components/ui/page-header.tsx +244 -0
  428. package/src/components/ui/payment-card-fields.tsx +2 -2
  429. package/src/components/ui/resizable.tsx +68 -0
  430. package/src/components/ui/scroll-area.tsx +72 -0
  431. package/src/components/ui/selection-tile-grid.tsx +9 -2
  432. package/src/components/ui/sidebar.tsx +84 -12
  433. package/src/components/ui/slider.tsx +83 -0
  434. package/src/globals.css +494 -151
  435. package/src/globals.d.ts +20 -0
  436. package/src/index.ts +68 -1
  437. package/src/lib/conditional-rule-match.ts +119 -0
  438. package/src/lib/data-list-display-options.ts +35 -0
  439. package/src/lib/data-list-view-registry.ts +104 -0
  440. package/src/lib/data-list-view-surface.ts +83 -0
  441. package/src/lib/data-list-view.ts +47 -0
  442. package/src/lib/dev-log.ts +10 -0
  443. package/src/lib/editable-target.ts +20 -0
  444. package/src/lib/list-page-table-properties.ts +48 -0
  445. package/src/lib/raf-throttle.ts +45 -0
  446. package/src/lib/row-height.ts +19 -0
  447. package/src/lib/table-properties-types.ts +98 -0
  448. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  449. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
  450. package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
  451. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  452. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
  453. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  454. package/template/AGENTS.md +84 -20
  455. package/template/app/(app)/examples/page.tsx +0 -1
  456. package/template/app/(app)/layout.tsx +17 -4
  457. package/template/app/(app)/question-bank/layout.tsx +1 -1
  458. package/template/app/(app)/question-bank/new/page.tsx +11 -24
  459. package/template/app/globals.css +13 -1972
  460. package/template/components/ask-leo-sidebar.tsx +5 -1
  461. package/template/components/brand-color-picker.tsx +2 -2
  462. package/template/components/charts-overview.tsx +1 -1
  463. package/template/components/compliance-table.tsx +240 -384
  464. package/template/components/dashboard-report-charts.tsx +1 -1
  465. package/template/components/dashboard-tabs.tsx +1 -1
  466. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  467. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  468. package/template/components/data-table/index.tsx +1 -1634
  469. package/template/components/data-table/pagination.tsx +1 -255
  470. package/template/components/data-table/types.ts +1 -94
  471. package/template/components/data-table/use-table-state.test.ts +420 -0
  472. package/template/components/data-table/use-table-state.ts +1 -758
  473. package/template/components/data-view-dashboard-charts-compliance.tsx +2 -2
  474. package/template/components/data-view-dashboard-charts-team.tsx +2 -2
  475. package/template/components/data-view-dashboard-charts.tsx +2 -2
  476. package/template/components/data-views/board-card-primitives.tsx +1 -93
  477. package/template/components/data-views/data-row-list.tsx +1 -183
  478. package/template/components/data-views/finder-panel-view.tsx +1 -405
  479. package/template/components/data-views/folder-grid-view.tsx +1 -86
  480. package/template/components/data-views/hub-table.tsx +1 -0
  481. package/template/components/data-views/index.ts +42 -1
  482. package/template/components/data-views/list-page-board-card.tsx +1 -192
  483. package/template/components/data-views/list-page-board-template.tsx +1 -122
  484. package/template/components/data-views/list-page-connected-view-body.tsx +1 -0
  485. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  486. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -60
  487. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  488. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  489. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  490. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  491. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  492. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  493. package/template/components/export-drawer.test.tsx +71 -0
  494. package/template/components/export-drawer.tsx +1 -375
  495. package/template/components/exxat-product-logo.tsx +5 -5
  496. package/template/components/hub-tree-panel-view.tsx +2 -2
  497. package/template/components/invite-collaborators-drawer.tsx +3 -3
  498. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  499. package/template/components/key-metrics.tsx +1 -1063
  500. package/template/components/leo-insight-indicator.tsx +2 -2
  501. package/template/components/new-placement-back-btn.tsx +1 -1
  502. package/template/components/new-placement-form.tsx +63 -189
  503. package/template/components/new-question-composer.tsx +432 -402
  504. package/template/components/onboarding/index.ts +9 -0
  505. package/template/components/onboarding/onboarding-01.tsx +1 -1
  506. package/template/components/onboarding/onboarding-02.tsx +1 -1
  507. package/template/components/onboarding/onboarding-03.tsx +1 -1
  508. package/template/components/onboarding/onboarding-04.tsx +1 -1
  509. package/template/components/page-header.tsx +8 -226
  510. package/template/components/placement-board-card.tsx +71 -83
  511. package/template/components/placements-board-view.tsx +3 -10
  512. package/template/components/placements-client.tsx +10 -42
  513. package/template/components/placements-list-view.tsx +22 -69
  514. package/template/components/placements-table-columns.tsx +8 -438
  515. package/template/components/placements-table.tsx +588 -1296
  516. package/template/components/product-switcher.tsx +1 -1
  517. package/template/components/product-wordmark.tsx +2 -1
  518. package/template/components/question-bank-client.tsx +4 -1
  519. package/template/components/question-bank-hub-client.tsx +1 -1
  520. package/template/components/question-bank-new-folder-sheet.tsx +2 -2
  521. package/template/components/question-bank-secondary-nav.tsx +3 -3
  522. package/template/components/question-bank-table.tsx +294 -526
  523. package/template/components/rotations-empty-state.tsx +1 -1
  524. package/template/components/rotations-panel-activator.tsx +1 -1
  525. package/template/components/settings-appearance-card.tsx +1 -1
  526. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  527. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +4 -4
  528. package/template/components/sidebar/index.ts +16 -0
  529. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  530. package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +6 -3
  531. package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
  532. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  533. package/template/components/site-header.tsx +1 -1
  534. package/template/components/{sites-all-client.tsx → sites-client.tsx} +1 -1
  535. package/template/components/sites-table.tsx +124 -257
  536. package/template/components/table-properties/column-row.tsx +1 -90
  537. package/template/components/table-properties/draggable-list.ts +1 -49
  538. package/template/components/table-properties/drawer-button.tsx +1 -249
  539. package/template/components/table-properties/drawer.tsx +1 -1105
  540. package/template/components/table-properties/filter-card.tsx +1 -251
  541. package/template/components/table-properties/sort-card.tsx +1 -59
  542. package/template/components/table-properties/types.ts +28 -71
  543. package/template/components/team-table.tsx +242 -382
  544. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  545. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  546. package/template/components/templates/list-page.tsx +1 -584
  547. package/template/components/templates/nested-secondary-panel-shell.tsx +1 -62
  548. package/template/components/templates/new-focus-template.tsx +659 -0
  549. package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
  550. package/template/components/ui/accordion.tsx +1 -0
  551. package/template/components/ui/alert-dialog.tsx +1 -0
  552. package/template/components/ui/context-menu.tsx +1 -0
  553. package/template/components/ui/dot-pattern.tsx +1 -183
  554. package/template/components/ui/hover-card.tsx +1 -0
  555. package/template/components/ui/resizable.tsx +1 -68
  556. package/template/components/ui/scroll-area.tsx +1 -0
  557. package/template/components/ui/slider.tsx +1 -0
  558. package/template/docs/blueprints/README.md +86 -0
  559. package/template/docs/blueprints/_template.md +91 -0
  560. package/template/docs/blueprints/board-card.md +123 -0
  561. package/template/docs/blueprints/data-table.md +139 -0
  562. package/template/docs/blueprints/key-metrics.md +128 -0
  563. package/template/docs/blueprints/list-page-template.md +123 -0
  564. package/template/docs/blueprints/page-header.md +130 -0
  565. package/template/docs/command-menu-pattern.md +1 -1
  566. package/template/docs/component-selection-guide.md +224 -0
  567. package/template/docs/components-audit-2026-05.md +158 -0
  568. package/template/docs/data-views-pattern.md +14 -14
  569. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  570. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  571. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  572. package/template/docs/migrations/README.md +100 -0
  573. package/template/docs/migrations/_template.md +64 -0
  574. package/template/docs/token-taxonomy.md +416 -0
  575. package/template/eslint.config.mjs +27 -0
  576. package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
  577. package/template/lib/command-menu-config.ts +0 -1
  578. package/template/lib/compliance-supported-views.ts +10 -0
  579. package/template/lib/conditional-rule-match.ts +6 -97
  580. package/template/lib/data-list-display-options.ts +1 -35
  581. package/template/lib/data-list-view-registry.ts +1 -0
  582. package/template/lib/data-list-view-surface.ts +1 -69
  583. package/template/lib/data-list-view.ts +1 -38
  584. package/template/lib/dev-log.ts +1 -8
  585. package/template/lib/editable-target.ts +1 -10
  586. package/template/lib/hub-connected-view-renderers.ts +58 -0
  587. package/template/lib/list-hub-supported-views.ts +10 -0
  588. package/template/lib/list-page-table-properties.ts +1 -52
  589. package/template/lib/mock/navigation.tsx +0 -8
  590. package/template/lib/mock/placements.ts +0 -7
  591. package/template/lib/placement-board-card-layout.ts +41 -41
  592. package/template/lib/placements-supported-views.ts +12 -0
  593. package/template/lib/question-bank-supported-views.ts +12 -0
  594. package/template/lib/raf-throttle.ts +1 -45
  595. package/template/lib/row-height.ts +4 -10
  596. package/template/lib/sidebar-state-cookie.ts +11 -2
  597. package/template/lib/sites-supported-views.ts +10 -0
  598. package/template/lib/team-supported-views.ts +10 -0
  599. package/template/package.json +1 -0
  600. package/template/tests/setup.ts +25 -0
  601. package/src/theme.css +0 -1132
  602. package/template/app/(app)/data-list/[id]/page.tsx +0 -44
  603. package/template/app/(app)/data-list/new/page.tsx +0 -34
  604. package/template/app/(app)/data-list/page.tsx +0 -10
  605. package/template/components/compliance-list-view.tsx +0 -54
  606. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  607. package/template/components/dashboard-onboarding.tsx +0 -21
  608. package/template/components/question-bank-list-view.tsx +0 -53
  609. package/template/components/section-cards.tsx +0 -106
  610. package/template/components/sites-list-view.tsx +0 -42
  611. package/template/components/team-list-view.tsx +0 -59
  612. package/template/lib/placement-lifecycle.ts +0 -5
  613. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  614. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  615. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  616. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  617. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
  618. /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
@@ -0,0 +1,2433 @@
1
+ "use client";
2
+ import * as React12 from 'react';
3
+ import { clsx } from 'clsx';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { Slot, Label as Label$1, Checkbox as Checkbox$1, RadioGroup as RadioGroup$1, DropdownMenu as DropdownMenu$1, Dialog as Dialog$1, Tooltip as Tooltip$1, Popover as Popover$1 } from 'radix-ui';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+ import { useForm, FormProvider, Controller, useFormContext } from 'react-hook-form';
8
+ import { z } from 'zod';
9
+ import { zodResolver } from '@hookform/resolvers/zod';
10
+ import { cva } from 'class-variance-authority';
11
+ import { XIcon, ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from 'lucide-react';
12
+ import { getDefaultClassNames, DayPicker } from 'react-day-picker';
13
+ import { useMaskInput } from 'use-mask-input';
14
+
15
+ function cn(...inputs) {
16
+ return twMerge(clsx(inputs));
17
+ }
18
+ function Tooltip({
19
+ ...props
20
+ }) {
21
+ return /* @__PURE__ */ jsx(Tooltip$1.Root, { "data-slot": "tooltip", ...props });
22
+ }
23
+ function TooltipTrigger({
24
+ className,
25
+ ...props
26
+ }) {
27
+ return /* @__PURE__ */ jsx(
28
+ Tooltip$1.Trigger,
29
+ {
30
+ "data-slot": "tooltip-trigger",
31
+ suppressHydrationWarning: true,
32
+ className: cn("cursor-pointer", className),
33
+ ...props
34
+ }
35
+ );
36
+ }
37
+ function TooltipContent({
38
+ className,
39
+ sideOffset = 0,
40
+ children,
41
+ ...props
42
+ }) {
43
+ return /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsxs(
44
+ Tooltip$1.Content,
45
+ {
46
+ "data-slot": "tooltip-content",
47
+ sideOffset,
48
+ className: cn(
49
+ "z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pe-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
50
+ className
51
+ ),
52
+ ...props,
53
+ children: [
54
+ children,
55
+ /* @__PURE__ */ jsx(Tooltip$1.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
56
+ ]
57
+ }
58
+ ) });
59
+ }
60
+ function Tip({ label, children, side = "top" }) {
61
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
62
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
63
+ /* @__PURE__ */ jsx(TooltipContent, { side, className: "flex flex-wrap items-center gap-1.5", children: label })
64
+ ] });
65
+ }
66
+
67
+ // src/lib/dev-log.ts
68
+ function devLog(...args) {
69
+ if (process.env.NODE_ENV === "development") {
70
+ console.log(...args);
71
+ }
72
+ }
73
+ var buttonVariants = cva(
74
+ "group/button inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
75
+ {
76
+ variants: {
77
+ variant: {
78
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
79
+ outline: "border-input bg-background hover:bg-interactive-hover hover:text-interactive-hover-foreground aria-expanded:bg-interactive-hover aria-expanded:text-interactive-hover-foreground dark:bg-input/15 dark:hover:bg-input/25",
80
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
81
+ ghost: "hover:bg-interactive-hover hover:text-interactive-hover-foreground aria-expanded:bg-interactive-hover aria-expanded:text-interactive-hover-foreground dark:hover:bg-interactive-hover-subtle",
82
+ destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
83
+ link: "text-primary underline-offset-4 hover:underline"
84
+ },
85
+ size: {
86
+ default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pe-2.5 has-data-[icon=inline-start]:ps-2.5",
87
+ xs: "h-6 gap-1 px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&_svg:not([class*='size-'])]:size-3",
88
+ sm: "h-8 gap-1 px-3 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2 [&_svg:not([class*='size-'])]:size-3.5",
89
+ lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pe-3.5 has-data-[icon=inline-start]:ps-3.5",
90
+ icon: "size-9",
91
+ "icon-xs": "size-6 in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
92
+ "icon-sm": "size-8 in-data-[slot=button-group]:rounded-lg",
93
+ "icon-lg": "size-10"
94
+ }
95
+ },
96
+ defaultVariants: {
97
+ variant: "default",
98
+ size: "default"
99
+ }
100
+ }
101
+ );
102
+ var Button = React12.forwardRef(({ className, variant = "default", size = "default", asChild = false, ...props }, ref) => {
103
+ const Comp = asChild ? Slot.Root : "button";
104
+ return /* @__PURE__ */ jsx(
105
+ Comp,
106
+ {
107
+ ref,
108
+ "data-slot": "button",
109
+ "data-variant": variant,
110
+ "data-size": size,
111
+ className: cn(buttonVariants({ variant, size }), className),
112
+ ...props
113
+ }
114
+ );
115
+ });
116
+ Button.displayName = "Button";
117
+ var Label = React12.forwardRef(function Label2({ className, ...props }, ref) {
118
+ return /* @__PURE__ */ jsx(
119
+ Label$1.Root,
120
+ {
121
+ ref,
122
+ "data-slot": "label",
123
+ className: cn(
124
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
125
+ className
126
+ ),
127
+ ...props
128
+ }
129
+ );
130
+ });
131
+ var checkboxVariants = cva(
132
+ [
133
+ "peer relative box-border flex shrink-0 items-center justify-center self-center rounded-[4px] border border-input",
134
+ "outline-none transition-[color,box-shadow,transform,background-color,border-color] duration-150",
135
+ "motion-reduce:transition-none",
136
+ "group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2",
137
+ "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
138
+ "disabled:cursor-not-allowed disabled:opacity-50",
139
+ "aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary",
140
+ "dark:bg-input/15 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40"
141
+ ].join(" "),
142
+ {
143
+ variants: {
144
+ variant: {
145
+ default: [
146
+ "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary",
147
+ "data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground dark:data-[state=indeterminate]:bg-primary dark:data-[state=indeterminate]:text-primary-foreground"
148
+ ].join(" "),
149
+ outline: [
150
+ "bg-background",
151
+ "data-[state=checked]:border-primary data-[state=checked]:bg-background data-[state=checked]:text-primary data-[state=checked]:ring-2 data-[state=checked]:ring-primary/25",
152
+ "data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-background data-[state=indeterminate]:text-primary data-[state=indeterminate]:ring-2 data-[state=indeterminate]:ring-primary/25"
153
+ ].join(" "),
154
+ secondary: [
155
+ "data-[state=checked]:border-secondary data-[state=checked]:bg-secondary data-[state=checked]:text-secondary-foreground",
156
+ "data-[state=indeterminate]:border-secondary data-[state=indeterminate]:bg-secondary data-[state=indeterminate]:text-secondary-foreground"
157
+ ].join(" "),
158
+ success: [
159
+ "data-[state=checked]:border-chart-2 data-[state=checked]:bg-chart-2 data-[state=checked]:text-primary-foreground",
160
+ "data-[state=indeterminate]:border-chart-2 data-[state=indeterminate]:bg-chart-2 data-[state=indeterminate]:text-primary-foreground"
161
+ ].join(" "),
162
+ destructive: [
163
+ "data-[state=checked]:border-destructive data-[state=checked]:bg-destructive data-[state=checked]:text-destructive-foreground",
164
+ "data-[state=indeterminate]:border-destructive data-[state=indeterminate]:bg-destructive data-[state=indeterminate]:text-destructive-foreground"
165
+ ].join(" "),
166
+ warning: [
167
+ "data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500 data-[state=checked]:text-amber-950",
168
+ "data-[state=indeterminate]:border-amber-500 data-[state=indeterminate]:bg-amber-500 data-[state=indeterminate]:text-amber-950"
169
+ ].join(" "),
170
+ muted: [
171
+ "data-[state=checked]:border-muted-foreground/50 data-[state=checked]:bg-muted data-[state=checked]:text-foreground",
172
+ "data-[state=indeterminate]:border-muted-foreground/50 data-[state=indeterminate]:bg-muted data-[state=indeterminate]:text-foreground"
173
+ ].join(" ")
174
+ },
175
+ size: {
176
+ sm: "size-3.5 max-h-3.5 max-w-3.5 min-h-3.5 min-w-3.5 rounded-[3px] [&_[data-slot=checkbox-indicator]_i]:text-[10px]",
177
+ default: "size-4 max-h-4 max-w-4 min-h-4 min-w-4 [&_[data-slot=checkbox-indicator]_i]:text-xs",
178
+ lg: "size-5 max-h-5 max-w-5 min-h-5 min-w-5 rounded-[5px] [&_[data-slot=checkbox-indicator]_i]:text-sm"
179
+ },
180
+ motion: {
181
+ none: "",
182
+ pop: [
183
+ "motion-safe:active:scale-95",
184
+ "data-[state=checked]:motion-safe:scale-[1.04] data-[state=indeterminate]:motion-safe:scale-[1.04]"
185
+ ].join(" "),
186
+ glow: [
187
+ "data-[state=checked]:shadow-[0_0_0_3px] data-[state=checked]:shadow-primary/35",
188
+ "data-[state=indeterminate]:shadow-[0_0_0_3px] data-[state=indeterminate]:shadow-primary/35"
189
+ ].join(" "),
190
+ "pop-glow": [
191
+ "motion-safe:active:scale-95",
192
+ "data-[state=checked]:motion-safe:scale-[1.04] data-[state=indeterminate]:motion-safe:scale-[1.04]",
193
+ "data-[state=checked]:shadow-[0_0_0_3px] data-[state=checked]:shadow-primary/35",
194
+ "data-[state=indeterminate]:shadow-[0_0_0_3px] data-[state=indeterminate]:shadow-primary/35"
195
+ ].join(" ")
196
+ }
197
+ },
198
+ defaultVariants: {
199
+ variant: "default",
200
+ size: "default",
201
+ motion: "none"
202
+ }
203
+ }
204
+ );
205
+ var checkboxIndicatorVariants = cva("grid place-content-center text-current", {
206
+ variants: {
207
+ motion: {
208
+ none: "transition-none",
209
+ pop: "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:duration-150",
210
+ glow: "",
211
+ "pop-glow": "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:duration-150"
212
+ }
213
+ },
214
+ defaultVariants: {
215
+ motion: "none"
216
+ }
217
+ });
218
+ var Checkbox = React12.forwardRef(
219
+ function Checkbox2({ className, variant, size, motion, checked, ...props }, ref) {
220
+ const m = motion ?? "none";
221
+ return /* @__PURE__ */ jsx(
222
+ Checkbox$1.Root,
223
+ {
224
+ ref,
225
+ "data-slot": "checkbox",
226
+ "data-variant": variant ?? "default",
227
+ "data-motion": m,
228
+ checked,
229
+ className: cn(checkboxVariants({ variant, size, motion: m }), className),
230
+ ...props,
231
+ children: /* @__PURE__ */ jsx(
232
+ Checkbox$1.Indicator,
233
+ {
234
+ "data-slot": "checkbox-indicator",
235
+ className: checkboxIndicatorVariants({ motion: m }),
236
+ children: checked === "indeterminate" ? /* @__PURE__ */ jsx("i", { className: "fa-solid fa-minus text-current", "aria-hidden": "true" }) : /* @__PURE__ */ jsx("i", { className: "fa-solid fa-check text-current", "aria-hidden": "true" })
237
+ }
238
+ )
239
+ }
240
+ );
241
+ }
242
+ );
243
+ function Kbd({
244
+ className,
245
+ variant = "tile",
246
+ "aria-hidden": ariaHidden,
247
+ ...props
248
+ }) {
249
+ const hidden = ariaHidden ?? (variant === "bare" ? true : void 0);
250
+ return /* @__PURE__ */ jsx(
251
+ "kbd",
252
+ {
253
+ "data-slot": "kbd",
254
+ "data-variant": variant,
255
+ "aria-hidden": hidden,
256
+ className: cn(
257
+ "pointer-events-none inline-flex h-5 min-w-5 select-none items-center justify-center gap-1 px-1 font-sans text-xs font-medium",
258
+ variant === "tile" && "bg-muted text-muted-foreground rounded-sm border",
259
+ variant === "bare" && "text-current/70 px-0",
260
+ className
261
+ ),
262
+ ...props
263
+ }
264
+ );
265
+ }
266
+ function KbdGroup({ className, ...props }) {
267
+ return /* @__PURE__ */ jsx(
268
+ "div",
269
+ {
270
+ "data-slot": "kbd-group",
271
+ className: cn("inline-flex items-center gap-1", className),
272
+ ...props
273
+ }
274
+ );
275
+ }
276
+
277
+ // src/lib/dropdown-menu-surface.ts
278
+ var DROPDOWN_MENU_CONTENT_SURFACE_CLASS = "min-w-52 w-max max-w-[min(24rem,calc(100vw-2rem))]";
279
+ function DropdownMenu({
280
+ ...props
281
+ }) {
282
+ return /* @__PURE__ */ jsx(DropdownMenu$1.Root, { "data-slot": "dropdown-menu", ...props });
283
+ }
284
+ function DropdownMenuTrigger({
285
+ className,
286
+ ...props
287
+ }) {
288
+ return /* @__PURE__ */ jsx(
289
+ DropdownMenu$1.Trigger,
290
+ {
291
+ "data-slot": "dropdown-menu-trigger",
292
+ suppressHydrationWarning: true,
293
+ className: cn("cursor-pointer", className),
294
+ ...props
295
+ }
296
+ );
297
+ }
298
+ function DropdownMenuContent({
299
+ className,
300
+ align = "start",
301
+ sideOffset = 4,
302
+ ...props
303
+ }) {
304
+ return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(
305
+ DropdownMenu$1.Content,
306
+ {
307
+ "data-slot": "dropdown-menu-content",
308
+ sideOffset,
309
+ align,
310
+ className: cn(
311
+ "z-50 max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
312
+ DROPDOWN_MENU_CONTENT_SURFACE_CLASS,
313
+ className
314
+ ),
315
+ ...props
316
+ }
317
+ ) });
318
+ }
319
+ function DropdownMenuItem({
320
+ className,
321
+ inset,
322
+ variant = "default",
323
+ shortcut,
324
+ children,
325
+ asChild,
326
+ ...props
327
+ }) {
328
+ return /* @__PURE__ */ jsx(
329
+ DropdownMenu$1.Item,
330
+ {
331
+ "data-slot": "dropdown-menu-item",
332
+ "data-inset": inset,
333
+ "data-variant": variant,
334
+ asChild,
335
+ className: cn(
336
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:ps-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_i]:pointer-events-none [&_svg]:shrink-0 [&_i]:shrink-0 [&_svg:not([data-product-logo]):not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
337
+ className
338
+ ),
339
+ ...props,
340
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
341
+ children,
342
+ shortcut ? /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: shortcut }) : null
343
+ ] })
344
+ }
345
+ );
346
+ }
347
+ function Shortcut({
348
+ keys,
349
+ onInvoke,
350
+ disabled
351
+ }) {
352
+ useShortcut(keys, onInvoke, disabled);
353
+ return null;
354
+ }
355
+ function useShortcut(keys, onInvoke, disabled) {
356
+ const ref = React12.useRef(onInvoke);
357
+ React12.useEffect(() => {
358
+ ref.current = onInvoke;
359
+ }, [onInvoke]);
360
+ React12.useEffect(() => {
361
+ if (disabled) return;
362
+ const parsed = parseShortcut(keys);
363
+ if (!parsed) return;
364
+ function handler(e) {
365
+ if (!matchesShortcut(e, parsed)) return;
366
+ const t = e.target;
367
+ if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
368
+ if (t && (parsed.key === "enter" || parsed.key === " ")) {
369
+ const role = t.getAttribute("role");
370
+ if (t.tagName === "BUTTON" || t.tagName === "A" || t.tagName === "SELECT" || role === "button" || role === "link" || role === "menuitem" || role === "tab" || role === "option" || role === "checkbox" || role === "radio" || role === "switch" || t.closest('[role="button"], [role="link"], [role="menuitem"], [role="tab"], [role="option"]'))
371
+ return;
372
+ }
373
+ const openDialog = document.querySelector('[role="dialog"][data-state="open"], [role="alertdialog"][data-state="open"]');
374
+ if (openDialog && (!t || !openDialog.contains(t))) return;
375
+ e.preventDefault();
376
+ e.stopPropagation();
377
+ ref.current(e);
378
+ }
379
+ window.addEventListener("keydown", handler);
380
+ return () => window.removeEventListener("keydown", handler);
381
+ }, [keys, disabled]);
382
+ }
383
+ function mapKey(raw) {
384
+ const p = raw.toLowerCase();
385
+ if (raw === "\u232B") return "backspace";
386
+ if (raw === "\u2326") return "delete";
387
+ if (raw === "\u23CE" || p === "enter" || p === "return") return "enter";
388
+ if (raw === "\u2423" || p === "space") return " ";
389
+ if (p === "esc" || p === "escape") return "escape";
390
+ if (p === "tab") return "tab";
391
+ if (p === "up" || raw === "\u2191") return "arrowup";
392
+ if (p === "down" || raw === "\u2193") return "arrowdown";
393
+ if (p === "left" || raw === "\u2190") return "arrowleft";
394
+ if (p === "right" || raw === "\u2192") return "arrowright";
395
+ return p;
396
+ }
397
+ function parseShortcut(input) {
398
+ let s = input.trim();
399
+ if (!s) return null;
400
+ const out = { meta: false, ctrl: false, shift: false, alt: false, key: "" };
401
+ while (s.length) {
402
+ const c = s[0];
403
+ if (c === "\u2318") {
404
+ out.meta = true;
405
+ s = s.slice(1);
406
+ } else if (c === "\u2303") {
407
+ out.ctrl = true;
408
+ s = s.slice(1);
409
+ } else if (c === "\u21E7") {
410
+ out.shift = true;
411
+ s = s.slice(1);
412
+ } else if (c === "\u2325") {
413
+ out.alt = true;
414
+ s = s.slice(1);
415
+ } else break;
416
+ }
417
+ if (!s) return null;
418
+ if (/[+\s]/.test(s)) {
419
+ for (const raw of s.split(/[+\s]+/).filter(Boolean)) {
420
+ const p = raw.toLowerCase();
421
+ if (raw === "\u2318" || p === "cmd" || p === "meta" || p === "command") out.meta = true;
422
+ else if (raw === "\u2303" || p === "ctrl" || p === "control") out.ctrl = true;
423
+ else if (raw === "\u21E7" || p === "shift") out.shift = true;
424
+ else if (raw === "\u2325" || p === "alt" || p === "opt" || p === "option") out.alt = true;
425
+ else out.key = mapKey(raw);
426
+ }
427
+ } else {
428
+ out.key = mapKey(s);
429
+ }
430
+ return out.key ? out : null;
431
+ }
432
+ function matchesShortcut(e, s) {
433
+ if (e.metaKey !== s.meta) return false;
434
+ if (e.ctrlKey !== s.ctrl) return false;
435
+ if (e.altKey !== s.alt) return false;
436
+ if (e.shiftKey !== s.shift) return false;
437
+ return e.key.toLowerCase() === s.key;
438
+ }
439
+ function DropdownMenuLabel({
440
+ className,
441
+ inset,
442
+ ...props
443
+ }) {
444
+ return /* @__PURE__ */ jsx(
445
+ DropdownMenu$1.Label,
446
+ {
447
+ "data-slot": "dropdown-menu-label",
448
+ "data-inset": inset,
449
+ className: cn(
450
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:ps-7",
451
+ className
452
+ ),
453
+ ...props
454
+ }
455
+ );
456
+ }
457
+ function DropdownMenuSeparator({
458
+ className,
459
+ ...props
460
+ }) {
461
+ return /* @__PURE__ */ jsx(
462
+ DropdownMenu$1.Separator,
463
+ {
464
+ "data-slot": "dropdown-menu-separator",
465
+ className: cn("-mx-1 my-1 h-px bg-border", className),
466
+ ...props
467
+ }
468
+ );
469
+ }
470
+ function DropdownMenuShortcut({
471
+ className,
472
+ ...props
473
+ }) {
474
+ return /* @__PURE__ */ jsx(
475
+ "span",
476
+ {
477
+ "data-slot": "dropdown-menu-shortcut",
478
+ className: cn(
479
+ "ms-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
480
+ className
481
+ ),
482
+ ...props
483
+ }
484
+ );
485
+ }
486
+ var radioGroupItemVariants = cva(
487
+ [
488
+ "group/radio-group-item peer relative flex shrink-0 aspect-square rounded-full border border-input",
489
+ "outline-none transition-[color,box-shadow,transform,background-color,border-color] duration-150",
490
+ "motion-reduce:transition-none",
491
+ "group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2",
492
+ "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
493
+ "disabled:cursor-not-allowed disabled:opacity-50",
494
+ "aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:data-[state=checked]:border-primary",
495
+ "dark:bg-input/15 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40"
496
+ ].join(" "),
497
+ {
498
+ variants: {
499
+ variant: {
500
+ default: [
501
+ "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary"
502
+ ].join(" "),
503
+ outline: [
504
+ "bg-background",
505
+ "data-[state=checked]:border-primary data-[state=checked]:bg-background data-[state=checked]:text-primary data-[state=checked]:ring-2 data-[state=checked]:ring-primary/25"
506
+ ].join(" "),
507
+ secondary: [
508
+ "data-[state=checked]:border-secondary data-[state=checked]:bg-secondary data-[state=checked]:text-secondary-foreground"
509
+ ].join(" "),
510
+ success: [
511
+ "data-[state=checked]:border-chart-2 data-[state=checked]:bg-chart-2 data-[state=checked]:text-primary-foreground"
512
+ ].join(" "),
513
+ destructive: [
514
+ "data-[state=checked]:border-destructive data-[state=checked]:bg-destructive data-[state=checked]:text-destructive-foreground"
515
+ ].join(" "),
516
+ warning: [
517
+ "data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500 data-[state=checked]:text-amber-950"
518
+ ].join(" "),
519
+ muted: [
520
+ "data-[state=checked]:border-muted-foreground/50 data-[state=checked]:bg-muted data-[state=checked]:text-foreground"
521
+ ].join(" ")
522
+ },
523
+ size: {
524
+ sm: "size-3.5 min-h-3.5 min-w-3.5 max-h-3.5 max-w-3.5",
525
+ default: "size-4 min-h-4 min-w-4 max-h-4 max-w-4",
526
+ lg: "size-5 min-h-5 min-w-5 max-h-5 max-w-5"
527
+ },
528
+ motion: {
529
+ none: "",
530
+ pop: [
531
+ "motion-safe:active:scale-95",
532
+ "data-[state=checked]:motion-safe:scale-[1.04]"
533
+ ].join(" "),
534
+ glow: "data-[state=checked]:shadow-[0_0_0_3px] data-[state=checked]:shadow-primary/35",
535
+ "pop-glow": [
536
+ "motion-safe:active:scale-95",
537
+ "data-[state=checked]:motion-safe:scale-[1.04]",
538
+ "data-[state=checked]:shadow-[0_0_0_3px] data-[state=checked]:shadow-primary/35"
539
+ ].join(" ")
540
+ }
541
+ },
542
+ defaultVariants: {
543
+ variant: "default",
544
+ size: "default",
545
+ motion: "none"
546
+ }
547
+ }
548
+ );
549
+ var radioIndicatorDotVariants = cva(
550
+ "pointer-events-none absolute top-1/2 start-1/2 -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 rounded-full",
551
+ {
552
+ variants: {
553
+ variant: {
554
+ default: "bg-primary-foreground",
555
+ outline: "bg-primary",
556
+ secondary: "bg-secondary-foreground",
557
+ success: "bg-primary-foreground",
558
+ destructive: "bg-destructive-foreground",
559
+ warning: "bg-amber-950",
560
+ muted: "bg-foreground"
561
+ },
562
+ size: {
563
+ sm: "size-1.5",
564
+ default: "size-2",
565
+ lg: "size-2.5"
566
+ }
567
+ },
568
+ defaultVariants: {
569
+ variant: "default",
570
+ size: "default"
571
+ }
572
+ }
573
+ );
574
+ var radioIndicatorWrapperVariants = cva("relative flex size-full items-center justify-center", {
575
+ variants: {
576
+ motion: {
577
+ none: "",
578
+ pop: "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:duration-150",
579
+ glow: "",
580
+ "pop-glow": "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:duration-150"
581
+ }
582
+ },
583
+ defaultVariants: { motion: "none" }
584
+ });
585
+ var RadioGroupItemChromeContext = React12.createContext({});
586
+ function RadioGroup({
587
+ className,
588
+ itemVariant,
589
+ itemSize,
590
+ itemMotion,
591
+ ...props
592
+ }) {
593
+ const ctx = React12.useMemo(
594
+ () => ({ itemVariant, itemSize, itemMotion }),
595
+ [itemVariant, itemSize, itemMotion]
596
+ );
597
+ return /* @__PURE__ */ jsx(RadioGroupItemChromeContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
598
+ RadioGroup$1.Root,
599
+ {
600
+ "data-slot": "radio-group",
601
+ className: cn("grid w-full gap-2", className),
602
+ ...props
603
+ }
604
+ ) });
605
+ }
606
+ var RadioGroupItem = React12.forwardRef(function RadioGroupItem2({ className, variant: variantProp, size: sizeProp, motion: motionProp, ...props }, ref) {
607
+ const ctx = React12.useContext(RadioGroupItemChromeContext);
608
+ const variant = variantProp ?? ctx.itemVariant;
609
+ const size = sizeProp ?? ctx.itemSize;
610
+ const motion = motionProp ?? ctx.itemMotion ?? "none";
611
+ const vResolved = variant ?? "default";
612
+ const sResolved = size ?? "default";
613
+ return /* @__PURE__ */ jsx(
614
+ RadioGroup$1.Item,
615
+ {
616
+ ref,
617
+ "data-slot": "radio-group-item",
618
+ "data-variant": vResolved,
619
+ "data-motion": motion,
620
+ className: cn(radioGroupItemVariants({ variant, size, motion }), className),
621
+ ...props,
622
+ children: /* @__PURE__ */ jsx(
623
+ RadioGroup$1.Indicator,
624
+ {
625
+ "data-slot": "radio-group-indicator",
626
+ className: radioIndicatorWrapperVariants({ motion }),
627
+ children: /* @__PURE__ */ jsx("span", { className: radioIndicatorDotVariants({ variant: vResolved, size: sResolved }) })
628
+ }
629
+ )
630
+ }
631
+ );
632
+ });
633
+ function RadioGroupLabel({ className, ...props }) {
634
+ return /* @__PURE__ */ jsx(
635
+ Label,
636
+ {
637
+ "data-slot": "radio-group-label",
638
+ className: cn(
639
+ "inline-flex min-h-11 cursor-pointer select-none items-center gap-2 py-1 -my-1 text-sm font-medium leading-snug",
640
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-60",
641
+ className
642
+ ),
643
+ ...props
644
+ }
645
+ );
646
+ }
647
+ function selectionTileClassNames(selected) {
648
+ return cn(
649
+ "flex aspect-square flex-col items-center justify-center gap-1.5 rounded-lg border px-2 py-3 text-xs leading-tight transition-colors",
650
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
651
+ selected ? "border-brand bg-brand/5 text-foreground font-medium shadow-sm" : "border-border bg-background text-muted-foreground hover:border-border/80 hover:text-interactive-hover-foreground"
652
+ );
653
+ }
654
+ function selectionTilePreviewClassNames(selected) {
655
+ return cn(
656
+ "relative box-border flex aspect-square w-full max-w-full flex-col rounded-lg border p-1 transition-colors",
657
+ selected ? "border-brand bg-brand/5 shadow-sm" : "border-border bg-background hover:border-border/80"
658
+ );
659
+ }
660
+ function SelectionTileGraphic({
661
+ option,
662
+ selected
663
+ }) {
664
+ if (option.leading != null) {
665
+ return /* @__PURE__ */ jsx("span", { className: "flex h-full min-h-0 w-full min-w-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:block [&_svg]:h-full [&_svg]:w-auto [&_svg]:max-h-full [&_svg]:max-w-full [&_svg]:object-contain [&_svg]:object-center", children: option.leading });
666
+ }
667
+ if (option.icon) {
668
+ return /* @__PURE__ */ jsx(
669
+ "i",
670
+ {
671
+ className: cn(
672
+ "fa-light shrink-0 text-[18px] leading-none",
673
+ option.icon,
674
+ selected && "text-brand"
675
+ ),
676
+ "aria-hidden": "true"
677
+ }
678
+ );
679
+ }
680
+ return null;
681
+ }
682
+ function SelectionTileLabelText({
683
+ option
684
+ }) {
685
+ return /* @__PURE__ */ jsx("span", { className: "text-center leading-tight", children: option.label });
686
+ }
687
+ function SelectionTileCaptionBelow({
688
+ option,
689
+ selected,
690
+ ariaHidden = false
691
+ }) {
692
+ return /* @__PURE__ */ jsx(
693
+ "span",
694
+ {
695
+ className: cn(
696
+ "max-w-full px-0.5 text-center text-xs leading-tight",
697
+ selected ? "font-medium text-foreground" : "text-muted-foreground"
698
+ ),
699
+ ...ariaHidden ? { "aria-hidden": true } : {},
700
+ children: option.label
701
+ }
702
+ );
703
+ }
704
+ function SelectionTileGrid({
705
+ sectionLabel,
706
+ options,
707
+ columns = 4,
708
+ value,
709
+ onValueChange,
710
+ interaction,
711
+ idPrefix = "tile",
712
+ className,
713
+ labelPlacement = "inside",
714
+ itemVariant,
715
+ itemSize,
716
+ itemMotion
717
+ }) {
718
+ const gridClass = cn(
719
+ "gap-2",
720
+ columns === 2 && "grid grid-cols-2",
721
+ columns === 3 && "grid grid-cols-3",
722
+ columns === 4 && "grid grid-cols-4"
723
+ );
724
+ if (interaction === "radio") {
725
+ return /* @__PURE__ */ jsxs("div", { className, children: [
726
+ sectionLabel ? /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-medium text-muted-foreground", children: sectionLabel }) : null,
727
+ /* @__PURE__ */ jsx(
728
+ RadioGroup,
729
+ {
730
+ value,
731
+ onValueChange: (v) => onValueChange(v),
732
+ className: gridClass,
733
+ itemVariant,
734
+ itemSize,
735
+ itemMotion,
736
+ children: options.map((opt) => {
737
+ const selected = value === opt.value;
738
+ const id = `${idPrefix}-${opt.value}`;
739
+ if (labelPlacement === "below") {
740
+ return /* @__PURE__ */ jsxs(
741
+ Label,
742
+ {
743
+ htmlFor: id,
744
+ className: cn(
745
+ "flex min-w-0 cursor-pointer flex-col items-center gap-1.5 rounded-lg focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background"
746
+ ),
747
+ children: [
748
+ /* @__PURE__ */ jsxs("span", { className: cn("flex w-full justify-center", selectionTilePreviewClassNames(selected)), children: [
749
+ /* @__PURE__ */ jsx(RadioGroupItem, { value: opt.value, id, className: "sr-only" }),
750
+ /* @__PURE__ */ jsx("span", { className: "flex min-h-0 w-full min-w-0 flex-1 items-center justify-center", children: /* @__PURE__ */ jsx(SelectionTileGraphic, { option: opt, selected }) })
751
+ ] }),
752
+ /* @__PURE__ */ jsx(SelectionTileCaptionBelow, { option: opt, selected })
753
+ ]
754
+ },
755
+ opt.value
756
+ );
757
+ }
758
+ return /* @__PURE__ */ jsxs(
759
+ Label,
760
+ {
761
+ htmlFor: id,
762
+ className: cn(
763
+ "cursor-pointer rounded-lg focus-within:rounded-lg focus-within:ring-2 focus-within:ring-ring focus-within:outline-none",
764
+ selectionTileClassNames(selected)
765
+ ),
766
+ children: [
767
+ /* @__PURE__ */ jsx(RadioGroupItem, { value: opt.value, id, className: "sr-only" }),
768
+ /* @__PURE__ */ jsx(SelectionTileGraphic, { option: opt, selected }),
769
+ /* @__PURE__ */ jsx(SelectionTileLabelText, { option: opt })
770
+ ]
771
+ },
772
+ opt.value
773
+ );
774
+ })
775
+ }
776
+ )
777
+ ] });
778
+ }
779
+ return /* @__PURE__ */ jsxs("div", { className, children: [
780
+ sectionLabel ? /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-medium text-muted-foreground", children: sectionLabel }) : null,
781
+ /* @__PURE__ */ jsx("div", { className: gridClass, children: options.map((opt) => {
782
+ const selected = value === opt.value;
783
+ if (labelPlacement === "below") {
784
+ return /* @__PURE__ */ jsxs(
785
+ "button",
786
+ {
787
+ type: "button",
788
+ "aria-label": opt.label,
789
+ "aria-pressed": selected,
790
+ onClick: () => onValueChange(opt.value),
791
+ className: "flex min-w-0 flex-col items-center gap-1.5 rounded-lg border-0 bg-transparent p-0 text-inherit focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
792
+ children: [
793
+ /* @__PURE__ */ jsx("span", { className: cn("flex w-full justify-center", selectionTilePreviewClassNames(selected)), children: /* @__PURE__ */ jsx("span", { className: "flex min-h-0 w-full min-w-0 flex-1 items-center justify-center", children: /* @__PURE__ */ jsx(SelectionTileGraphic, { option: opt, selected }) }) }),
794
+ /* @__PURE__ */ jsx(SelectionTileCaptionBelow, { option: opt, selected, ariaHidden: true })
795
+ ]
796
+ },
797
+ opt.value
798
+ );
799
+ }
800
+ return /* @__PURE__ */ jsxs(
801
+ "button",
802
+ {
803
+ type: "button",
804
+ "aria-label": opt.label,
805
+ "aria-pressed": selected,
806
+ onClick: () => onValueChange(opt.value),
807
+ className: selectionTileClassNames(selected),
808
+ children: [
809
+ /* @__PURE__ */ jsx(SelectionTileGraphic, { option: opt, selected }),
810
+ /* @__PURE__ */ jsx(SelectionTileLabelText, { option: opt })
811
+ ]
812
+ },
813
+ opt.value
814
+ );
815
+ }) })
816
+ ] });
817
+ }
818
+ function Calendar({
819
+ className,
820
+ classNames,
821
+ showOutsideDays = true,
822
+ captionLayout = "label",
823
+ buttonVariant = "ghost",
824
+ formatters,
825
+ components,
826
+ ...props
827
+ }) {
828
+ const defaultClassNames = getDefaultClassNames();
829
+ return /* @__PURE__ */ jsx(
830
+ DayPicker,
831
+ {
832
+ showOutsideDays,
833
+ className: cn(
834
+ "group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
835
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
836
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
837
+ className
838
+ ),
839
+ captionLayout,
840
+ formatters: {
841
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
842
+ ...formatters
843
+ },
844
+ classNames: {
845
+ root: cn("w-fit", defaultClassNames.root),
846
+ months: cn(
847
+ "relative flex flex-col gap-4 md:flex-row",
848
+ defaultClassNames.months
849
+ ),
850
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
851
+ nav: cn(
852
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
853
+ defaultClassNames.nav
854
+ ),
855
+ button_previous: cn(
856
+ buttonVariants({ variant: buttonVariant }),
857
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
858
+ defaultClassNames.button_previous
859
+ ),
860
+ button_next: cn(
861
+ buttonVariants({ variant: buttonVariant }),
862
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
863
+ defaultClassNames.button_next
864
+ ),
865
+ month_caption: cn(
866
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
867
+ defaultClassNames.month_caption
868
+ ),
869
+ dropdowns: cn(
870
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
871
+ defaultClassNames.dropdowns
872
+ ),
873
+ dropdown_root: cn(
874
+ "relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
875
+ defaultClassNames.dropdown_root
876
+ ),
877
+ dropdown: cn(
878
+ "absolute inset-0 bg-popover opacity-0",
879
+ defaultClassNames.dropdown
880
+ ),
881
+ caption_label: cn(
882
+ "font-medium select-none",
883
+ captionLayout === "label" ? "text-sm" : "flex h-8 items-center gap-1 rounded-md pe-1 ps-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
884
+ defaultClassNames.caption_label
885
+ ),
886
+ table: "w-full border-collapse",
887
+ weekdays: cn("flex", defaultClassNames.weekdays),
888
+ weekday: cn(
889
+ "flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none",
890
+ defaultClassNames.weekday
891
+ ),
892
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
893
+ week_number_header: cn(
894
+ "w-(--cell-size) select-none",
895
+ defaultClassNames.week_number_header
896
+ ),
897
+ week_number: cn(
898
+ "text-[0.8rem] text-muted-foreground select-none",
899
+ defaultClassNames.week_number
900
+ ),
901
+ day: cn(
902
+ "group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md",
903
+ props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" : "[&:first-child[data-selected=true]_button]:rounded-l-md",
904
+ defaultClassNames.day
905
+ ),
906
+ range_start: cn(
907
+ "rounded-l-md bg-accent",
908
+ defaultClassNames.range_start
909
+ ),
910
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
911
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
912
+ today: cn(
913
+ "rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none",
914
+ defaultClassNames.today
915
+ ),
916
+ outside: cn(
917
+ "text-muted-foreground aria-selected:text-muted-foreground",
918
+ defaultClassNames.outside
919
+ ),
920
+ disabled: cn(
921
+ "text-muted-foreground opacity-50",
922
+ defaultClassNames.disabled
923
+ ),
924
+ hidden: cn("invisible", defaultClassNames.hidden),
925
+ ...classNames
926
+ },
927
+ components: {
928
+ Root: ({ className: className2, rootRef, ...props2 }) => {
929
+ return /* @__PURE__ */ jsx(
930
+ "div",
931
+ {
932
+ "data-slot": "calendar",
933
+ ref: rootRef,
934
+ className: cn(className2),
935
+ ...props2
936
+ }
937
+ );
938
+ },
939
+ Chevron: ({ className: className2, orientation, ...props2 }) => {
940
+ if (orientation === "left") {
941
+ return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
942
+ }
943
+ if (orientation === "right") {
944
+ return /* @__PURE__ */ jsx(
945
+ ChevronRightIcon,
946
+ {
947
+ className: cn("size-4", className2),
948
+ ...props2
949
+ }
950
+ );
951
+ }
952
+ return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
953
+ },
954
+ DayButton: CalendarDayButton,
955
+ WeekNumber: ({ children, ...props2 }) => {
956
+ return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
957
+ },
958
+ ...components
959
+ },
960
+ ...props
961
+ }
962
+ );
963
+ }
964
+ function CalendarDayButton({
965
+ className,
966
+ day,
967
+ modifiers,
968
+ ...props
969
+ }) {
970
+ const defaultClassNames = getDefaultClassNames();
971
+ const ref = React12.useRef(null);
972
+ React12.useEffect(() => {
973
+ if (modifiers.focused) ref.current?.focus();
974
+ }, [modifiers.focused]);
975
+ return /* @__PURE__ */ jsx(
976
+ Button,
977
+ {
978
+ ref,
979
+ variant: "ghost",
980
+ size: "icon",
981
+ "data-day": day.date.toLocaleDateString(),
982
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
983
+ "data-range-start": modifiers.range_start,
984
+ "data-range-end": modifiers.range_end,
985
+ "data-range-middle": modifiers.range_middle,
986
+ className: cn(
987
+ "flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70",
988
+ defaultClassNames.day,
989
+ className
990
+ ),
991
+ ...props
992
+ }
993
+ );
994
+ }
995
+ var Input = React12.forwardRef(
996
+ function Input2({ className, type, ...props }, ref) {
997
+ return /* @__PURE__ */ jsx(
998
+ "input",
999
+ {
1000
+ ref,
1001
+ type,
1002
+ "data-slot": "input",
1003
+ className: cn(
1004
+ "h-8 w-full min-w-0 rounded-md border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
1005
+ className
1006
+ ),
1007
+ ...props
1008
+ }
1009
+ );
1010
+ }
1011
+ );
1012
+ function InputGroup({ className, ...props }) {
1013
+ return /* @__PURE__ */ jsx(
1014
+ "div",
1015
+ {
1016
+ "data-slot": "input-group",
1017
+ role: "group",
1018
+ className: cn(
1019
+ "group/input-group relative flex h-8 w-full min-w-0 items-center rounded-md border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pe-1.5 has-[>[data-align=inline-start]]:[&>input]:ps-1.5",
1020
+ className
1021
+ ),
1022
+ ...props
1023
+ }
1024
+ );
1025
+ }
1026
+ var inputGroupAddonVariants = cva(
1027
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
1028
+ {
1029
+ variants: {
1030
+ align: {
1031
+ "inline-start": "order-first ps-2 has-[>button]:ms-[-0.3rem] has-[>kbd]:ms-[-0.15rem]",
1032
+ "inline-end": "order-last pe-2 has-[>button]:me-[-0.3rem] has-[>kbd]:me-[-0.15rem]",
1033
+ "block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
1034
+ "block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
1035
+ }
1036
+ },
1037
+ defaultVariants: {
1038
+ align: "inline-start"
1039
+ }
1040
+ }
1041
+ );
1042
+ function InputGroupAddon({
1043
+ className,
1044
+ align = "inline-start",
1045
+ ...props
1046
+ }) {
1047
+ return /* @__PURE__ */ jsx(
1048
+ "div",
1049
+ {
1050
+ role: "group",
1051
+ "data-slot": "input-group-addon",
1052
+ "data-align": align,
1053
+ className: cn(inputGroupAddonVariants({ align }), className),
1054
+ onClick: (e) => {
1055
+ if (e.target.closest("button")) {
1056
+ return;
1057
+ }
1058
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
1059
+ },
1060
+ ...props
1061
+ }
1062
+ );
1063
+ }
1064
+ var inputGroupButtonVariants = cva(
1065
+ "flex items-center gap-2 text-sm shadow-none",
1066
+ {
1067
+ variants: {
1068
+ size: {
1069
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
1070
+ sm: "",
1071
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
1072
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
1073
+ }
1074
+ },
1075
+ defaultVariants: {
1076
+ size: "xs"
1077
+ }
1078
+ }
1079
+ );
1080
+ function InputGroupButton({
1081
+ className,
1082
+ type = "button",
1083
+ variant = "ghost",
1084
+ size = "xs",
1085
+ ...props
1086
+ }) {
1087
+ return /* @__PURE__ */ jsx(
1088
+ Button,
1089
+ {
1090
+ type,
1091
+ "data-size": size,
1092
+ variant,
1093
+ className: cn(inputGroupButtonVariants({ size }), className),
1094
+ ...props
1095
+ }
1096
+ );
1097
+ }
1098
+
1099
+ // src/lib/compose-refs.ts
1100
+ function composeRefs(...refs) {
1101
+ return (node) => {
1102
+ for (const ref of refs) {
1103
+ if (ref == null) continue;
1104
+ if (typeof ref === "function") {
1105
+ ref(node);
1106
+ } else {
1107
+ ref.current = node;
1108
+ }
1109
+ }
1110
+ };
1111
+ }
1112
+ var exxatInputMaskDefaults = {
1113
+ placeholder: "_",
1114
+ showMaskOnHover: false
1115
+ };
1116
+ var exxatMaskPatterns = {
1117
+ /** US NANP 10-digit display */
1118
+ phoneUS: "(999) 999-9999",
1119
+ /** US ZIP or ZIP+4 */
1120
+ zipUS: "99999[-9999]",
1121
+ /** Calendar-style date (validate separately). */
1122
+ dateMDY: "99/99/9999"};
1123
+ var MaskedInput = React12.forwardRef(function MaskedInput2({ mask, maskOptions, className, type = "text", ...props }, ref) {
1124
+ const maskRef = useMaskInput({
1125
+ mask,
1126
+ options: { ...exxatInputMaskDefaults, ...maskOptions }
1127
+ });
1128
+ return /* @__PURE__ */ jsx(
1129
+ Input,
1130
+ {
1131
+ ref: composeRefs(ref, maskRef),
1132
+ type,
1133
+ className: cn(className),
1134
+ ...props
1135
+ }
1136
+ );
1137
+ });
1138
+ function Popover({ ...props }) {
1139
+ return /* @__PURE__ */ jsx(Popover$1.Root, { ...props });
1140
+ }
1141
+ function PopoverTrigger({ className, ...props }) {
1142
+ return /* @__PURE__ */ jsx(Popover$1.Trigger, { className: cn("cursor-pointer", className), ...props });
1143
+ }
1144
+ function PopoverContent({
1145
+ className,
1146
+ align = "start",
1147
+ sideOffset = 4,
1148
+ ...props
1149
+ }) {
1150
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
1151
+ Popover$1.Content,
1152
+ {
1153
+ "data-slot": "popover-content",
1154
+ align,
1155
+ sideOffset,
1156
+ className: cn(
1157
+ "z-50 rounded-lg border border-border bg-popover shadow-md outline-none",
1158
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
1159
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1160
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
1161
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
1162
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
1163
+ className
1164
+ ),
1165
+ ...props
1166
+ }
1167
+ ) });
1168
+ }
1169
+ var DATE_PICKER_ICON_CLASS = "fa-light fa-calendar";
1170
+ function parseMdyToLocalDate(raw) {
1171
+ const match = raw.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
1172
+ if (!match) return void 0;
1173
+ const month = Number(match[1]);
1174
+ const day = Number(match[2]);
1175
+ const year = Number(match[3]);
1176
+ if (month < 1 || month > 12 || day < 1 || day > 31) return void 0;
1177
+ const date = new Date(year, month - 1, day, 12, 0, 0, 0);
1178
+ if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) return void 0;
1179
+ return date;
1180
+ }
1181
+ function formatLocalDateToMdy(date) {
1182
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1183
+ const day = String(date.getDate()).padStart(2, "0");
1184
+ const year = String(date.getFullYear());
1185
+ return `${month}/${day}/${year}`;
1186
+ }
1187
+ function DateTextInputField({
1188
+ value,
1189
+ onValueChange,
1190
+ "aria-label": ariaLabel,
1191
+ id,
1192
+ placeholder = "MM/DD/YYYY",
1193
+ className,
1194
+ inputClassName,
1195
+ autoFocus,
1196
+ disabled,
1197
+ fromYear = 2020,
1198
+ toYear = 2032,
1199
+ iconButtonVariant = "ghost",
1200
+ popoverAlign = "end",
1201
+ popoverClassName
1202
+ }) {
1203
+ return /* @__PURE__ */ jsxs(InputGroup, { className, children: [
1204
+ /* @__PURE__ */ jsx(
1205
+ MaskedInput,
1206
+ {
1207
+ "data-slot": "input-group-control",
1208
+ id,
1209
+ mask: exxatMaskPatterns.dateMDY,
1210
+ "aria-label": ariaLabel,
1211
+ placeholder,
1212
+ value,
1213
+ onChange: (event) => onValueChange(event.target.value),
1214
+ className: cn(
1215
+ "flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent",
1216
+ inputClassName
1217
+ ),
1218
+ autoFocus,
1219
+ disabled
1220
+ }
1221
+ ),
1222
+ /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(Popover, { children: [
1223
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1224
+ InputGroupButton,
1225
+ {
1226
+ type: "button",
1227
+ variant: iconButtonVariant,
1228
+ size: "icon-xs",
1229
+ disabled,
1230
+ "aria-label": `${ariaLabel} pick date`,
1231
+ children: /* @__PURE__ */ jsx("i", { className: DATE_PICKER_ICON_CLASS, "aria-hidden": "true" })
1232
+ }
1233
+ ) }),
1234
+ /* @__PURE__ */ jsx(
1235
+ PopoverContent,
1236
+ {
1237
+ className: cn("z-[80] w-auto p-0", popoverClassName),
1238
+ align: popoverAlign,
1239
+ sideOffset: 6,
1240
+ children: /* @__PURE__ */ jsx(
1241
+ Calendar,
1242
+ {
1243
+ mode: "single",
1244
+ selected: parseMdyToLocalDate(value),
1245
+ onSelect: (next) => onValueChange(next ? formatLocalDateToMdy(next) : ""),
1246
+ initialFocus: true,
1247
+ fromYear,
1248
+ toYear,
1249
+ captionLayout: "dropdown"
1250
+ }
1251
+ )
1252
+ }
1253
+ )
1254
+ ] }) })
1255
+ ] });
1256
+ }
1257
+ var MASK_BY_KIND = {
1258
+ phone: exxatMaskPatterns.phoneUS,
1259
+ zip: exxatMaskPatterns.zipUS,
1260
+ dateMDY: exxatMaskPatterns.dateMDY
1261
+ };
1262
+ function FilterTextValueInput({
1263
+ id,
1264
+ mask,
1265
+ value,
1266
+ onValueChange,
1267
+ "aria-label": ariaLabel,
1268
+ placeholder,
1269
+ className,
1270
+ autoFocus
1271
+ }) {
1272
+ if (mask === "dateMDY") {
1273
+ return /* @__PURE__ */ jsx(
1274
+ DateTextInputField,
1275
+ {
1276
+ id,
1277
+ value,
1278
+ onValueChange,
1279
+ "aria-label": ariaLabel,
1280
+ placeholder,
1281
+ inputClassName: className,
1282
+ autoFocus,
1283
+ iconButtonVariant: "ghost",
1284
+ popoverAlign: "end"
1285
+ }
1286
+ );
1287
+ }
1288
+ if (mask) {
1289
+ return /* @__PURE__ */ jsx(
1290
+ MaskedInput,
1291
+ {
1292
+ id,
1293
+ mask: MASK_BY_KIND[mask],
1294
+ "aria-label": ariaLabel,
1295
+ placeholder,
1296
+ value,
1297
+ onChange: (e) => onValueChange(e.target.value),
1298
+ className,
1299
+ autoFocus
1300
+ }
1301
+ );
1302
+ }
1303
+ return /* @__PURE__ */ jsx(
1304
+ Input,
1305
+ {
1306
+ id,
1307
+ type: "text",
1308
+ "aria-label": ariaLabel,
1309
+ placeholder,
1310
+ value,
1311
+ onChange: (e) => onValueChange(e.target.value),
1312
+ className,
1313
+ autoFocus
1314
+ }
1315
+ );
1316
+ }
1317
+ function Sheet({ ...props }) {
1318
+ return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "sheet", ...props });
1319
+ }
1320
+ function SheetPortal({
1321
+ ...props
1322
+ }) {
1323
+ return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "sheet-portal", ...props });
1324
+ }
1325
+ function SheetOverlay({
1326
+ className,
1327
+ ...props
1328
+ }) {
1329
+ return /* @__PURE__ */ jsx(
1330
+ Dialog$1.Overlay,
1331
+ {
1332
+ "data-slot": "sheet-overlay",
1333
+ className: cn(
1334
+ "fixed inset-0 z-50 bg-overlay duration-300 ease-out supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
1335
+ className
1336
+ ),
1337
+ ...props
1338
+ }
1339
+ );
1340
+ }
1341
+ function SheetContent({
1342
+ className,
1343
+ children,
1344
+ side = "right",
1345
+ showCloseButton = true,
1346
+ showOverlay = true,
1347
+ ...props
1348
+ }) {
1349
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
1350
+ showOverlay && /* @__PURE__ */ jsx(SheetOverlay, {}),
1351
+ /* @__PURE__ */ jsxs(
1352
+ Dialog$1.Content,
1353
+ {
1354
+ "data-slot": "sheet-content",
1355
+ "data-side": side,
1356
+ className: cn(
1357
+ "fixed z-50 flex flex-col gap-4 bg-background bg-clip-padding text-sm shadow-lg outline-none duration-300 ease-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-e data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-s data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-6 data-[side=left]:data-open:slide-in-from-left-6 data-[side=right]:data-open:slide-in-from-right-6 data-[side=top]:data-open:slide-in-from-top-6 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-6 data-[side=left]:data-closed:slide-out-to-left-6 data-[side=right]:data-closed:slide-out-to-right-6 data-[side=top]:data-closed:slide-out-to-top-6",
1358
+ className
1359
+ ),
1360
+ ...props,
1361
+ children: [
1362
+ children,
1363
+ showCloseButton && /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "sheet-close", asChild: true, children: /* @__PURE__ */ jsxs(
1364
+ Button,
1365
+ {
1366
+ variant: "ghost",
1367
+ className: "absolute top-3 end-3",
1368
+ size: "icon-sm",
1369
+ children: [
1370
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark", "aria-hidden": "true" }),
1371
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
1372
+ ]
1373
+ }
1374
+ ) })
1375
+ ]
1376
+ }
1377
+ )
1378
+ ] });
1379
+ }
1380
+ function SheetTitle({
1381
+ className,
1382
+ ...props
1383
+ }) {
1384
+ return /* @__PURE__ */ jsx(
1385
+ Dialog$1.Title,
1386
+ {
1387
+ "data-slot": "sheet-title",
1388
+ className: cn(
1389
+ "text-base font-medium text-foreground",
1390
+ className
1391
+ ),
1392
+ ...props
1393
+ }
1394
+ );
1395
+ }
1396
+ var Form = FormProvider;
1397
+ var FormFieldContext = React12.createContext(
1398
+ {}
1399
+ );
1400
+ function FormField({ ...props }) {
1401
+ return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
1402
+ }
1403
+ function useFormField() {
1404
+ const fieldContext = React12.useContext(FormFieldContext);
1405
+ const itemContext = React12.useContext(FormItemContext);
1406
+ const { getFieldState, formState } = useFormContext();
1407
+ const fieldState = getFieldState(fieldContext.name, formState);
1408
+ if (!fieldContext) throw new Error("useFormField must be used inside <FormField>");
1409
+ const { id } = itemContext;
1410
+ return {
1411
+ id,
1412
+ name: fieldContext.name,
1413
+ formItemId: `${id}-form-item`,
1414
+ formDescriptionId: `${id}-form-item-description`,
1415
+ formMessageId: `${id}-form-item-message`,
1416
+ ...fieldState
1417
+ };
1418
+ }
1419
+ var FormItemContext = React12.createContext({});
1420
+ function FormItem({ className, ...props }) {
1421
+ const id = React12.useId();
1422
+ return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx("div", { "data-slot": "form-item", className: cn("flex flex-col gap-1.5", className), ...props }) });
1423
+ }
1424
+ function FormLabel({ className, ...props }) {
1425
+ const { error, formItemId } = useFormField();
1426
+ return /* @__PURE__ */ jsx(
1427
+ Label,
1428
+ {
1429
+ "data-slot": "form-label",
1430
+ "data-error": !!error,
1431
+ className: cn("data-[error=true]:text-destructive", className),
1432
+ htmlFor: formItemId,
1433
+ ...props
1434
+ }
1435
+ );
1436
+ }
1437
+ function FormControl({ ...props }) {
1438
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
1439
+ return /* @__PURE__ */ jsx(
1440
+ Slot.Root,
1441
+ {
1442
+ "data-slot": "form-control",
1443
+ id: formItemId,
1444
+ "aria-describedby": !error ? formDescriptionId : `${formDescriptionId} ${formMessageId}`,
1445
+ "aria-invalid": !!error,
1446
+ ...props
1447
+ }
1448
+ );
1449
+ }
1450
+ function FormDescription({ className, ...props }) {
1451
+ const { formDescriptionId } = useFormField();
1452
+ return /* @__PURE__ */ jsx(
1453
+ "p",
1454
+ {
1455
+ "data-slot": "form-description",
1456
+ id: formDescriptionId,
1457
+ className: cn("text-muted-foreground text-sm", className),
1458
+ ...props
1459
+ }
1460
+ );
1461
+ }
1462
+ function FormMessage({ className, children, ...props }) {
1463
+ const { error, formMessageId } = useFormField();
1464
+ const body = error ? String(error?.message ?? "") : children;
1465
+ if (!body) return null;
1466
+ return /* @__PURE__ */ jsx(
1467
+ "p",
1468
+ {
1469
+ "data-slot": "form-message",
1470
+ id: formMessageId,
1471
+ className: cn("text-destructive text-sm", className),
1472
+ ...props,
1473
+ children: body
1474
+ }
1475
+ );
1476
+ }
1477
+ function parseMdyToDate(raw) {
1478
+ if (!raw?.trim()) return void 0;
1479
+ const m = raw.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
1480
+ if (!m) return void 0;
1481
+ const month = Number(m[1]);
1482
+ const day = Number(m[2]);
1483
+ const year = Number(m[3]);
1484
+ if (month < 1 || month > 12 || day < 1 || day > 31) return void 0;
1485
+ const d = new Date(year, month - 1, day, 12, 0, 0, 0);
1486
+ if (d.getFullYear() !== year || d.getMonth() !== month - 1 || d.getDate() !== day) return void 0;
1487
+ return d;
1488
+ }
1489
+ var EXPORT_FORMAT_OPTIONS = [
1490
+ { value: "csv", label: "CSV", icon: "fa-file-csv" },
1491
+ { value: "excel", label: "Excel", icon: "fa-file-excel" },
1492
+ { value: "pdf", label: "PDF", icon: "fa-file-pdf" }
1493
+ ];
1494
+ var exportSchema = z.object({
1495
+ format: z.enum(["csv", "excel", "pdf"]),
1496
+ columns: z.enum(["all", "visible"]),
1497
+ dateFrom: z.string().optional(),
1498
+ dateTo: z.string().optional(),
1499
+ includeFilters: z.boolean()
1500
+ }).superRefine((data, ctx) => {
1501
+ const from = parseMdyToDate(data.dateFrom);
1502
+ const to = parseMdyToDate(data.dateTo);
1503
+ if (data.dateFrom?.trim() && !from) {
1504
+ ctx.addIssue({ code: "custom", message: "Enter a valid from date", path: ["dateFrom"] });
1505
+ }
1506
+ if (data.dateTo?.trim() && !to) {
1507
+ ctx.addIssue({ code: "custom", message: "Enter a valid to date", path: ["dateTo"] });
1508
+ }
1509
+ if (from && to && to < from) {
1510
+ ctx.addIssue({ code: "custom", message: "End date must be after start date", path: ["dateTo"] });
1511
+ }
1512
+ });
1513
+ function ExportDrawer({
1514
+ open,
1515
+ onOpenChange,
1516
+ totalRows = 0,
1517
+ visibleColumns
1518
+ }) {
1519
+ const form = useForm({
1520
+ resolver: zodResolver(exportSchema),
1521
+ defaultValues: {
1522
+ format: "csv",
1523
+ columns: "visible",
1524
+ dateFrom: "",
1525
+ dateTo: "",
1526
+ includeFilters: true
1527
+ }
1528
+ });
1529
+ const [isExporting, setIsExporting] = React12.useState(false);
1530
+ async function onSubmit(values) {
1531
+ setIsExporting(true);
1532
+ await new Promise((r) => setTimeout(r, 1200));
1533
+ devLog("Export:", {
1534
+ ...values,
1535
+ dateFrom: parseMdyToDate(values.dateFrom)?.toISOString(),
1536
+ dateTo: parseMdyToDate(values.dateTo)?.toISOString()
1537
+ });
1538
+ setIsExporting(false);
1539
+ onOpenChange(false);
1540
+ form.reset();
1541
+ }
1542
+ return /* @__PURE__ */ jsx(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
1543
+ SheetContent,
1544
+ {
1545
+ "data-slot": "export-drawer",
1546
+ side: "right",
1547
+ showCloseButton: false,
1548
+ showOverlay: false,
1549
+ className: "z-[80] w-80 sm:max-w-80 p-0 gap-0 flex flex-col border border-border shadow-xl rounded-xl overflow-hidden",
1550
+ style: { top: "0.5rem", bottom: "0.5rem", right: "0.5rem", height: "calc(100vh - 1rem)" },
1551
+ children: [
1552
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-4 pt-5 pb-3", children: [
1553
+ /* @__PURE__ */ jsx(SheetTitle, { className: "text-base font-semibold leading-tight", children: "Export data" }),
1554
+ /* @__PURE__ */ jsx(Tip, { label: "Close", side: "bottom", children: /* @__PURE__ */ jsx(
1555
+ Button,
1556
+ {
1557
+ type: "button",
1558
+ variant: "ghost",
1559
+ size: "icon-sm",
1560
+ "aria-label": "Close",
1561
+ onClick: () => onOpenChange(false),
1562
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark text-[13px]", "aria-hidden": "true" })
1563
+ }
1564
+ ) })
1565
+ ] }),
1566
+ /* @__PURE__ */ jsxs("p", { className: "px-4 pb-3 text-sm text-muted-foreground -mt-1", children: [
1567
+ totalRows,
1568
+ " record",
1569
+ totalRows !== 1 ? "s" : "",
1570
+ " available for export."
1571
+ ] }),
1572
+ /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsx(
1573
+ "form",
1574
+ {
1575
+ id: "export-form",
1576
+ onSubmit: form.handleSubmit(onSubmit),
1577
+ className: "flex-1 overflow-y-auto",
1578
+ children: /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 space-y-5", children: [
1579
+ /* @__PURE__ */ jsx(
1580
+ FormField,
1581
+ {
1582
+ control: form.control,
1583
+ name: "format",
1584
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1585
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1586
+ SelectionTileGrid,
1587
+ {
1588
+ sectionLabel: "File format",
1589
+ options: EXPORT_FORMAT_OPTIONS,
1590
+ columns: 3,
1591
+ value: field.value,
1592
+ onValueChange: field.onChange,
1593
+ interaction: "radio",
1594
+ idPrefix: "export-fmt",
1595
+ itemVariant: "outline",
1596
+ itemMotion: "pop"
1597
+ }
1598
+ ) }),
1599
+ /* @__PURE__ */ jsx(FormMessage, {})
1600
+ ] })
1601
+ }
1602
+ ),
1603
+ /* @__PURE__ */ jsxs("fieldset", { className: "space-y-2", children: [
1604
+ /* @__PURE__ */ jsxs("legend", { className: "text-sm font-medium leading-none mb-2", children: [
1605
+ "Date range",
1606
+ " ",
1607
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-normal", children: "(optional)" })
1608
+ ] }),
1609
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
1610
+ /* @__PURE__ */ jsx(
1611
+ FormField,
1612
+ {
1613
+ control: form.control,
1614
+ name: "dateFrom",
1615
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { className: "gap-1", children: [
1616
+ /* @__PURE__ */ jsx(FormLabel, { htmlFor: "export-date-from", className: "text-xs text-muted-foreground", children: "From" }),
1617
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1618
+ FilterTextValueInput,
1619
+ {
1620
+ id: "export-date-from",
1621
+ mask: "dateMDY",
1622
+ "aria-label": "Export from date (optional)",
1623
+ placeholder: "MM/DD/YYYY",
1624
+ value: field.value ?? "",
1625
+ onValueChange: field.onChange,
1626
+ className: "h-8 text-sm"
1627
+ }
1628
+ ) }),
1629
+ /* @__PURE__ */ jsx(FormDescription, { className: "text-[11px]", children: "MM/DD/YYYY" }),
1630
+ /* @__PURE__ */ jsx(FormMessage, {})
1631
+ ] })
1632
+ }
1633
+ ),
1634
+ /* @__PURE__ */ jsx(
1635
+ FormField,
1636
+ {
1637
+ control: form.control,
1638
+ name: "dateTo",
1639
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { className: "gap-1", children: [
1640
+ /* @__PURE__ */ jsx(FormLabel, { htmlFor: "export-date-to", className: "text-xs text-muted-foreground", children: "To" }),
1641
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1642
+ FilterTextValueInput,
1643
+ {
1644
+ id: "export-date-to",
1645
+ mask: "dateMDY",
1646
+ "aria-label": "Export to date (optional)",
1647
+ placeholder: "MM/DD/YYYY",
1648
+ value: field.value ?? "",
1649
+ onValueChange: field.onChange,
1650
+ className: "h-8 text-sm"
1651
+ }
1652
+ ) }),
1653
+ /* @__PURE__ */ jsx(FormDescription, { className: "text-[11px]", children: "MM/DD/YYYY" }),
1654
+ /* @__PURE__ */ jsx(FormMessage, {})
1655
+ ] })
1656
+ }
1657
+ )
1658
+ ] })
1659
+ ] }),
1660
+ /* @__PURE__ */ jsx(
1661
+ FormField,
1662
+ {
1663
+ control: form.control,
1664
+ name: "columns",
1665
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1666
+ /* @__PURE__ */ jsx(FormLabel, { className: "text-sm font-medium", children: "Columns" }),
1667
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1668
+ RadioGroup,
1669
+ {
1670
+ value: field.value,
1671
+ onValueChange: field.onChange,
1672
+ className: "space-y-1.5 mt-1",
1673
+ itemVariant: "outline",
1674
+ itemMotion: "pop",
1675
+ children: [
1676
+ { value: "all", label: "All columns", sub: null },
1677
+ { value: "visible", label: "Visible columns only", sub: visibleColumns !== void 0 ? `${visibleColumns} columns` : null }
1678
+ ].map((opt) => /* @__PURE__ */ jsxs(
1679
+ "div",
1680
+ {
1681
+ className: "flex items-center gap-2.5 rounded-lg border border-border px-3 py-2.5 transition-colors hover:bg-interactive-hover has-[[data-state=checked]]:border-brand has-[[data-state=checked]]:bg-brand/10 cursor-pointer",
1682
+ children: [
1683
+ /* @__PURE__ */ jsx(RadioGroupItem, { value: opt.value, id: `col-${opt.value}` }),
1684
+ /* @__PURE__ */ jsxs(
1685
+ RadioGroupLabel,
1686
+ {
1687
+ htmlFor: `col-${opt.value}`,
1688
+ className: "min-h-0 flex-1 cursor-pointer py-0 text-sm font-normal leading-none",
1689
+ children: [
1690
+ opt.label,
1691
+ opt.sub && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground ms-1.5 font-normal", children: [
1692
+ "(",
1693
+ opt.sub,
1694
+ ")"
1695
+ ] })
1696
+ ]
1697
+ }
1698
+ )
1699
+ ]
1700
+ },
1701
+ opt.value
1702
+ ))
1703
+ }
1704
+ ) }),
1705
+ /* @__PURE__ */ jsx(FormMessage, {})
1706
+ ] })
1707
+ }
1708
+ ),
1709
+ /* @__PURE__ */ jsx(
1710
+ FormField,
1711
+ {
1712
+ control: form.control,
1713
+ name: "includeFilters",
1714
+ render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
1715
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-border px-3 py-2.5 transition-colors hover:bg-interactive-hover has-[[data-state=checked]]:border-primary", children: [
1716
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
1717
+ Checkbox,
1718
+ {
1719
+ id: "include-filters",
1720
+ checked: field.value,
1721
+ onCheckedChange: field.onChange,
1722
+ className: "mt-0.5 shrink-0"
1723
+ }
1724
+ ) }),
1725
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1726
+ /* @__PURE__ */ jsx(Label, { htmlFor: "include-filters", className: "text-sm cursor-pointer font-medium leading-none", children: "Apply active filters" }),
1727
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Export only rows matching current filters" })
1728
+ ] })
1729
+ ] }),
1730
+ /* @__PURE__ */ jsx(FormMessage, {})
1731
+ ] })
1732
+ }
1733
+ )
1734
+ ] })
1735
+ }
1736
+ ) }),
1737
+ /* @__PURE__ */ jsx(Shortcut, { keys: "Enter", disabled: isExporting, onInvoke: () => form.handleSubmit(onSubmit)() }),
1738
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-3 border-t border-border", children: [
1739
+ /* @__PURE__ */ jsxs(
1740
+ Button,
1741
+ {
1742
+ type: "button",
1743
+ variant: "outline",
1744
+ className: "flex-1",
1745
+ onClick: () => onOpenChange(false),
1746
+ children: [
1747
+ "Cancel",
1748
+ /* @__PURE__ */ jsx(KbdGroup, { className: "ms-1.5", children: /* @__PURE__ */ jsx(Kbd, { variant: "bare", children: "Esc" }) })
1749
+ ]
1750
+ }
1751
+ ),
1752
+ /* @__PURE__ */ jsx(
1753
+ Button,
1754
+ {
1755
+ type: "submit",
1756
+ form: "export-form",
1757
+ className: "flex-1",
1758
+ disabled: isExporting,
1759
+ children: isExporting ? /* @__PURE__ */ jsxs(Fragment, { children: [
1760
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-spinner-third fa-spin text-[13px]", "aria-hidden": "true" }),
1761
+ "Exporting\u2026"
1762
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1763
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-arrow-down-to-line text-[13px]", "aria-hidden": "true" }),
1764
+ "Export",
1765
+ /* @__PURE__ */ jsx(KbdGroup, { className: "ms-1.5", children: /* @__PURE__ */ jsx(Kbd, { variant: "bare", children: "\u23CE" }) })
1766
+ ] })
1767
+ }
1768
+ )
1769
+ ] })
1770
+ ]
1771
+ }
1772
+ ) });
1773
+ }
1774
+ function Dialog({
1775
+ ...props
1776
+ }) {
1777
+ return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "dialog", ...props });
1778
+ }
1779
+ function DialogPortal({
1780
+ ...props
1781
+ }) {
1782
+ return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "dialog-portal", ...props });
1783
+ }
1784
+ function DialogOverlay({
1785
+ className,
1786
+ ...props
1787
+ }) {
1788
+ return /* @__PURE__ */ jsx(
1789
+ Dialog$1.Overlay,
1790
+ {
1791
+ "data-slot": "dialog-overlay",
1792
+ className: cn(
1793
+ "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
1794
+ className
1795
+ ),
1796
+ ...props
1797
+ }
1798
+ );
1799
+ }
1800
+ function DialogContent({
1801
+ className,
1802
+ children,
1803
+ showCloseButton = true,
1804
+ overlayClassName,
1805
+ ...props
1806
+ }) {
1807
+ return /* @__PURE__ */ jsxs(DialogPortal, { children: [
1808
+ /* @__PURE__ */ jsx(DialogOverlay, { className: overlayClassName ?? void 0 }),
1809
+ /* @__PURE__ */ jsxs(
1810
+ Dialog$1.Content,
1811
+ {
1812
+ "data-slot": "dialog-content",
1813
+ className: cn(
1814
+ "fixed top-1/2 start-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
1815
+ className
1816
+ ),
1817
+ ...props,
1818
+ children: [
1819
+ children,
1820
+ showCloseButton && /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "dialog-close", asChild: true, children: /* @__PURE__ */ jsxs(
1821
+ Button,
1822
+ {
1823
+ variant: "ghost",
1824
+ className: "absolute top-2 end-2",
1825
+ size: "icon-sm",
1826
+ children: [
1827
+ /* @__PURE__ */ jsx(
1828
+ XIcon,
1829
+ {}
1830
+ ),
1831
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
1832
+ ]
1833
+ }
1834
+ ) })
1835
+ ]
1836
+ }
1837
+ )
1838
+ ] });
1839
+ }
1840
+ function DialogHeader({ className, ...props }) {
1841
+ return /* @__PURE__ */ jsx(
1842
+ "div",
1843
+ {
1844
+ "data-slot": "dialog-header",
1845
+ className: cn("flex flex-col gap-2", className),
1846
+ ...props
1847
+ }
1848
+ );
1849
+ }
1850
+ function DialogFooter({
1851
+ className,
1852
+ showCloseButton = false,
1853
+ children,
1854
+ ...props
1855
+ }) {
1856
+ return /* @__PURE__ */ jsxs(
1857
+ "div",
1858
+ {
1859
+ "data-slot": "dialog-footer",
1860
+ className: cn(
1861
+ "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
1862
+ className
1863
+ ),
1864
+ ...props,
1865
+ children: [
1866
+ children,
1867
+ showCloseButton && /* @__PURE__ */ jsx(Dialog$1.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", children: "Close" }) })
1868
+ ]
1869
+ }
1870
+ );
1871
+ }
1872
+ function DialogTitle({
1873
+ className,
1874
+ ...props
1875
+ }) {
1876
+ return /* @__PURE__ */ jsx(
1877
+ Dialog$1.Title,
1878
+ {
1879
+ "data-slot": "dialog-title",
1880
+ className: cn(
1881
+ "font-heading text-base leading-none font-medium",
1882
+ className
1883
+ ),
1884
+ ...props
1885
+ }
1886
+ );
1887
+ }
1888
+ function DialogDescription({
1889
+ className,
1890
+ ...props
1891
+ }) {
1892
+ return /* @__PURE__ */ jsx(
1893
+ Dialog$1.Description,
1894
+ {
1895
+ "data-slot": "dialog-description",
1896
+ className: cn(
1897
+ "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
1898
+ className
1899
+ ),
1900
+ ...props
1901
+ }
1902
+ );
1903
+ }
1904
+
1905
+ // src/lib/data-list-view.ts
1906
+ var DATA_LIST_VIEW_TILES = [
1907
+ { value: "table", icon: "fa-table", label: "Table view" },
1908
+ { value: "list", icon: "fa-list", label: "List view" },
1909
+ { value: "board", icon: "fa-table-columns", label: "Board view" },
1910
+ { value: "dashboard", icon: "fa-chart-mixed", label: "Dashboard view" },
1911
+ { value: "calendar", icon: "fa-calendar-days", label: "Calendar view" },
1912
+ { value: "folder", icon: "fa-grid-2", label: "Folder view" },
1913
+ { value: "panel", icon: "fa-sidebar", label: "List & details" },
1914
+ { value: "tree-panel", icon: "fa-sitemap", label: "Tree & details" }
1915
+ ];
1916
+ function dataListViewIcon(view) {
1917
+ return DATA_LIST_VIEW_TILES.find((t) => t.value === view)?.icon ?? "fa-table";
1918
+ }
1919
+ function dataListViewAddShortcut(index) {
1920
+ if (index < 0 || index > 8) return void 0;
1921
+ return String(index + 1);
1922
+ }
1923
+
1924
+ // src/lib/data-list-view-surface.ts
1925
+ function getDataListViewRenderKind(view) {
1926
+ switch (view) {
1927
+ case "table":
1928
+ return "data-table";
1929
+ case "list":
1930
+ return "list-with-toolbar";
1931
+ case "board":
1932
+ return "board-with-toolbar";
1933
+ case "dashboard":
1934
+ return "dashboard-with-toolbar";
1935
+ case "calendar":
1936
+ return "calendar-with-toolbar";
1937
+ case "folder":
1938
+ return "folder-with-toolbar";
1939
+ case "panel":
1940
+ return "panel-with-toolbar";
1941
+ case "tree-panel":
1942
+ return "tree-panel-with-toolbar";
1943
+ default: {
1944
+ const _x = view;
1945
+ return _x;
1946
+ }
1947
+ }
1948
+ }
1949
+
1950
+ // src/lib/data-list-view-registry.ts
1951
+ var DEFINITIONS = DATA_LIST_VIEW_TILES.map((tile) => {
1952
+ const renderKind = getDataListViewRenderKind(tile.value);
1953
+ const hubMetricsStrip = renderKind !== "calendar-with-toolbar" && renderKind !== "dashboard-with-toolbar";
1954
+ return {
1955
+ value: tile.value,
1956
+ label: tile.label,
1957
+ icon: tile.icon,
1958
+ renderKind,
1959
+ hubMetricsStrip
1960
+ };
1961
+ });
1962
+ new Map(
1963
+ DEFINITIONS.map((d) => [d.value, d])
1964
+ );
1965
+ var DATA_LIST_VIEW_REGISTRY = DEFINITIONS;
1966
+ var DATA_LIST_SURFACE_VIEW_TYPES = new Set(
1967
+ DATA_LIST_VIEW_REGISTRY.map((d) => d.value)
1968
+ );
1969
+ function isDataListSurfaceViewType(viewType) {
1970
+ return DATA_LIST_SURFACE_VIEW_TYPES.has(viewType);
1971
+ }
1972
+
1973
+ // src/lib/list-page-table-properties.ts
1974
+ function createListPageEditViewHandler(tableRef, options) {
1975
+ const delay = 160;
1976
+ return (tab, { updateTab }) => {
1977
+ const mustSwitchToTableSurface = !isDataListSurfaceViewType(tab.viewType);
1978
+ if (mustSwitchToTableSurface) {
1979
+ updateTab({ viewType: "table", icon: dataListViewIcon("table") });
1980
+ }
1981
+ window.setTimeout(() => {
1982
+ tableRef.current?.openPropertiesDrawer();
1983
+ }, mustSwitchToTableSurface ? delay : 0);
1984
+ };
1985
+ }
1986
+ function viewSegmentedToolbarClass(className) {
1987
+ return cn(
1988
+ "inline-flex items-center gap-0.5 rounded-lg bg-muted/60 p-[3px]",
1989
+ className
1990
+ );
1991
+ }
1992
+ function viewSegmentedButtonClass(isActive, opts) {
1993
+ return cn(
1994
+ "inline-flex items-center rounded-md transition-all whitespace-nowrap",
1995
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
1996
+ "gap-1.5 px-2.5 py-1 text-xs min-h-8",
1997
+ isActive ? "bg-background text-foreground font-medium shadow-sm" : "text-muted-foreground hover:text-interactive-hover-foreground"
1998
+ );
1999
+ }
2000
+ var VIEW_TYPES = DATA_LIST_VIEW_TILES.map((t) => ({
2001
+ type: t.value,
2002
+ label: t.label,
2003
+ icon: t.icon
2004
+ }));
2005
+ function makeTabId(type) {
2006
+ const rand = Math.random().toString(36).slice(2, 8);
2007
+ return `${type}-${Date.now().toString(36)}-${rand}`;
2008
+ }
2009
+ function viewToolbarCountBadgeClass(filterId, isActive) {
2010
+ const palettes = {
2011
+ all: {
2012
+ active: "bg-slate-600 text-white dark:bg-slate-500",
2013
+ inactive: "bg-slate-100 text-slate-800 dark:bg-slate-800/70 dark:text-slate-100"
2014
+ },
2015
+ upcoming: {
2016
+ active: "bg-amber-600 text-white",
2017
+ inactive: "bg-amber-100 text-amber-950 dark:bg-amber-950/45 dark:text-amber-100"
2018
+ },
2019
+ ongoing: {
2020
+ active: "bg-blue-600 text-white",
2021
+ inactive: "bg-blue-100 text-blue-950 dark:bg-blue-950/45 dark:text-blue-100"
2022
+ },
2023
+ completed: {
2024
+ active: "bg-emerald-600 text-white",
2025
+ inactive: "bg-emerald-100 text-emerald-950 dark:bg-emerald-950/45 dark:text-emerald-100"
2026
+ }
2027
+ };
2028
+ const p = palettes[filterId] ?? palettes.all;
2029
+ return isActive ? p.active : p.inactive;
2030
+ }
2031
+ function ListPageTemplate({
2032
+ header,
2033
+ metrics,
2034
+ showMetrics = true,
2035
+ defaultTabs,
2036
+ tabs: tabsProp,
2037
+ onTabsChange,
2038
+ activeTabId: activeTabIdProp,
2039
+ onActiveTabChange,
2040
+ getTabCount,
2041
+ renderContent,
2042
+ exportOpen = false,
2043
+ onExportOpenChange,
2044
+ exportTotalRows = 0,
2045
+ onEditView,
2046
+ tablePropertiesRef,
2047
+ hideViewsToolbar = false,
2048
+ supportedViewTypes
2049
+ }) {
2050
+ const addableViewTypes = React12.useMemo(() => {
2051
+ if (!supportedViewTypes || supportedViewTypes.length === 0) return VIEW_TYPES;
2052
+ const allowed = new Set(supportedViewTypes);
2053
+ return VIEW_TYPES.filter((v) => allowed.has(v.type));
2054
+ }, [supportedViewTypes]);
2055
+ const controlled = tabsProp !== void 0 && onTabsChange !== void 0 && activeTabIdProp !== void 0 && onActiveTabChange !== void 0;
2056
+ const [internalTabs, setInternalTabs] = React12.useState(defaultTabs);
2057
+ const [internalActiveId, setInternalActiveId] = React12.useState(defaultTabs[0]?.id ?? "");
2058
+ const tabs = controlled ? tabsProp : internalTabs;
2059
+ const setTabsState = React12.useCallback(
2060
+ (action) => {
2061
+ if (controlled) {
2062
+ const next = typeof action === "function" ? action(tabsProp) : action;
2063
+ onTabsChange(next);
2064
+ } else {
2065
+ setInternalTabs(action);
2066
+ }
2067
+ },
2068
+ [controlled, onTabsChange, tabsProp, setInternalTabs]
2069
+ );
2070
+ const activeTabId = controlled ? activeTabIdProp : internalActiveId;
2071
+ const setActiveTabId = controlled ? onActiveTabChange : setInternalActiveId;
2072
+ const [renameOpen, setRenameOpen] = React12.useState(false);
2073
+ const [renameValue, setRenameValue] = React12.useState("");
2074
+ const [renameTabId, setRenameTabId] = React12.useState(null);
2075
+ const [reviewOpen, setReviewOpen] = React12.useState(false);
2076
+ const [reviewTab, setReviewTab] = React12.useState(null);
2077
+ const activeTab = tabs.find((t) => t.id === activeTabId) ?? tabs[0];
2078
+ const editViewFromRef = React12.useMemo(
2079
+ () => tablePropertiesRef ? createListPageEditViewHandler(tablePropertiesRef) : void 0,
2080
+ [tablePropertiesRef]
2081
+ );
2082
+ const resolvedOnEditView = onEditView ?? editViewFromRef;
2083
+ function addView(type) {
2084
+ const def = VIEW_TYPES.find((d) => d.type === type);
2085
+ const count = tabs.filter((t) => t.viewType === type).length;
2086
+ const id = makeTabId(type);
2087
+ const label = count === 0 ? def.label : `${def.label} ${count + 1}`;
2088
+ const newTab = { id, label, viewType: type, icon: def.icon, filterId: "all" };
2089
+ setTabsState((prev) => [...prev, newTab]);
2090
+ setActiveTabId(id);
2091
+ }
2092
+ function removeTab(id, e) {
2093
+ e.stopPropagation();
2094
+ setTabsState((prev) => {
2095
+ const next = prev.filter((t) => t.id !== id);
2096
+ if (activeTabId === id && next.length > 0) {
2097
+ const idx = Math.max(0, prev.findIndex((t) => t.id === id) - 1);
2098
+ setActiveTabId(next[Math.min(idx, next.length - 1)].id);
2099
+ }
2100
+ return next;
2101
+ });
2102
+ }
2103
+ function updateTab(id, patch) {
2104
+ setTabsState((prev) => prev.map((t) => t.id === id ? { ...t, ...patch } : t));
2105
+ }
2106
+ function duplicateTab(tab) {
2107
+ const id = makeTabId(tab.viewType);
2108
+ const newTab = {
2109
+ id,
2110
+ label: `Copy of ${tab.label}`,
2111
+ viewType: tab.viewType,
2112
+ icon: tab.icon,
2113
+ filterId: tab.filterId
2114
+ };
2115
+ setTabsState((prev) => [...prev, newTab]);
2116
+ setActiveTabId(id);
2117
+ }
2118
+ function openRename(tab) {
2119
+ setRenameTabId(tab.id);
2120
+ setRenameValue(tab.label);
2121
+ setRenameOpen(true);
2122
+ }
2123
+ function commitRename() {
2124
+ if (!renameTabId) return;
2125
+ const v = renameValue.trim();
2126
+ if (v) updateTab(renameTabId, { label: v });
2127
+ setRenameOpen(false);
2128
+ setRenameTabId(null);
2129
+ }
2130
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2131
+ !hideViewsToolbar && addableViewTypes.slice(0, 9).map((v, i) => {
2132
+ const keys = dataListViewAddShortcut(i);
2133
+ return keys ? /* @__PURE__ */ jsx(
2134
+ Shortcut,
2135
+ {
2136
+ keys,
2137
+ onInvoke: () => addView(v.type)
2138
+ },
2139
+ v.type
2140
+ ) : null;
2141
+ }),
2142
+ activeTab && !hideViewsToolbar && /* @__PURE__ */ jsxs(Fragment, { children: [
2143
+ /* @__PURE__ */ jsx(Shortcut, { keys: "F2", onInvoke: () => openRename(activeTab) }),
2144
+ /* @__PURE__ */ jsx(
2145
+ Shortcut,
2146
+ {
2147
+ keys: "\u2318E",
2148
+ disabled: !resolvedOnEditView,
2149
+ onInvoke: () => resolvedOnEditView?.(activeTab, { updateTab: (p) => updateTab(activeTab.id, p) })
2150
+ }
2151
+ ),
2152
+ /* @__PURE__ */ jsx(Shortcut, { keys: "\u2318D", onInvoke: () => duplicateTab(activeTab) }),
2153
+ /* @__PURE__ */ jsx(Shortcut, { keys: "\u2318I", onInvoke: () => {
2154
+ setReviewTab(activeTab);
2155
+ setReviewOpen(true);
2156
+ } }),
2157
+ /* @__PURE__ */ jsx(
2158
+ Shortcut,
2159
+ {
2160
+ keys: "\u2318\u232B",
2161
+ disabled: tabs.length <= 1,
2162
+ onInvoke: (e) => removeTab(activeTab.id, e)
2163
+ }
2164
+ )
2165
+ ] }),
2166
+ header,
2167
+ showMetrics && metrics,
2168
+ !hideViewsToolbar && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: "mt-3 shrink-0 overflow-x-auto px-4 lg:px-6", children: /* @__PURE__ */ jsxs("div", { className: "flex w-max items-center gap-1 py-1.5", children: [
2169
+ /* @__PURE__ */ jsx(
2170
+ "div",
2171
+ {
2172
+ role: "toolbar",
2173
+ "aria-label": "Views",
2174
+ "data-slot": "view-segmented-toolbar",
2175
+ className: viewSegmentedToolbarClass(),
2176
+ children: tabs.map((tab) => {
2177
+ const isActive = tab.id === activeTabId;
2178
+ const isOnly = tabs.length === 1;
2179
+ const count = getTabCount?.(tab.filterId);
2180
+ const tabInner = /* @__PURE__ */ jsxs(Fragment, { children: [
2181
+ /* @__PURE__ */ jsx("i", { className: cn("fa-light shrink-0 text-xs", tab.icon), "aria-hidden": "true" }),
2182
+ tab.label,
2183
+ count !== void 0 && /* @__PURE__ */ jsx(
2184
+ "span",
2185
+ {
2186
+ "data-slot": "view-toolbar-count",
2187
+ className: cn(
2188
+ "text-xs tabular-nums rounded-full px-1 py-px min-w-[1.125rem] text-center font-semibold",
2189
+ viewToolbarCountBadgeClass(tab.filterId, isActive)
2190
+ ),
2191
+ children: count
2192
+ }
2193
+ )
2194
+ ] });
2195
+ const viewSettingsMenu = /* @__PURE__ */ jsxs(DropdownMenu, { children: [
2196
+ /* @__PURE__ */ jsx(Tip, { label: "View settings", side: "bottom", children: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
2197
+ "button",
2198
+ {
2199
+ type: "button",
2200
+ className: cn(
2201
+ "inline-flex items-center justify-center min-h-8 min-w-6 shrink-0 rounded-e-md rounded-s-none px-0.5",
2202
+ "text-muted-foreground hover:text-interactive-hover-foreground hover:bg-foreground/[0.04]",
2203
+ "transition-colors",
2204
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:z-10"
2205
+ ),
2206
+ "aria-label": "View settings",
2207
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-down text-xs", "aria-hidden": "true" })
2208
+ }
2209
+ ) }) }),
2210
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", children: [
2211
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "text-xs text-muted-foreground", children: [
2212
+ "View: ",
2213
+ VIEW_TYPES.find((v) => v.type === tab.viewType)?.label
2214
+ ] }),
2215
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2216
+ /* @__PURE__ */ jsxs(
2217
+ DropdownMenuItem,
2218
+ {
2219
+ shortcut: "F2",
2220
+ onSelect: () => openRename(tab),
2221
+ children: [
2222
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-pen text-xs", "aria-hidden": "true" }),
2223
+ "Rename"
2224
+ ]
2225
+ }
2226
+ ),
2227
+ /* @__PURE__ */ jsxs(
2228
+ DropdownMenuItem,
2229
+ {
2230
+ disabled: !resolvedOnEditView,
2231
+ shortcut: "\u2318E",
2232
+ onSelect: () => resolvedOnEditView?.(tab, { updateTab: (patch) => updateTab(tab.id, patch) }),
2233
+ children: [
2234
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-sliders text-xs", "aria-hidden": "true" }),
2235
+ "Edit"
2236
+ ]
2237
+ }
2238
+ ),
2239
+ /* @__PURE__ */ jsxs(DropdownMenuItem, { shortcut: "\u2318D", onSelect: () => duplicateTab(tab), children: [
2240
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-copy text-xs", "aria-hidden": "true" }),
2241
+ "Duplicate"
2242
+ ] }),
2243
+ /* @__PURE__ */ jsxs(
2244
+ DropdownMenuItem,
2245
+ {
2246
+ shortcut: "\u2318I",
2247
+ onSelect: () => {
2248
+ setReviewTab(tab);
2249
+ setReviewOpen(true);
2250
+ },
2251
+ children: [
2252
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-clipboard-list text-xs", "aria-hidden": "true" }),
2253
+ "Review view"
2254
+ ]
2255
+ }
2256
+ ),
2257
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2258
+ !isOnly && /* @__PURE__ */ jsxs(
2259
+ DropdownMenuItem,
2260
+ {
2261
+ shortcut: "\u2318\u232B",
2262
+ onSelect: (e) => removeTab(tab.id, e),
2263
+ className: "text-destructive focus:text-destructive",
2264
+ children: [
2265
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-trash text-xs", "aria-hidden": "true" }),
2266
+ "Remove view"
2267
+ ]
2268
+ }
2269
+ )
2270
+ ] })
2271
+ ] });
2272
+ return /* @__PURE__ */ jsxs("div", { className: "group relative inline-flex items-center", children: [
2273
+ isActive ? /* @__PURE__ */ jsxs(
2274
+ "div",
2275
+ {
2276
+ className: cn(
2277
+ viewSegmentedButtonClass(true),
2278
+ "gap-0 p-0 inline-flex items-stretch"
2279
+ ),
2280
+ children: [
2281
+ /* @__PURE__ */ jsx(
2282
+ "button",
2283
+ {
2284
+ type: "button",
2285
+ "aria-pressed": true,
2286
+ "data-slot": "view-segmented-item",
2287
+ onClick: () => setActiveTabId(tab.id),
2288
+ className: cn(
2289
+ "inline-flex items-center gap-1.5 ps-2.5 pe-0.5 py-1 text-xs min-h-8",
2290
+ "rounded-s-md rounded-e-none",
2291
+ "bg-transparent text-foreground font-medium",
2292
+ "hover:bg-foreground/[0.04]",
2293
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:z-10"
2294
+ ),
2295
+ children: tabInner
2296
+ }
2297
+ ),
2298
+ viewSettingsMenu
2299
+ ]
2300
+ }
2301
+ ) : /* @__PURE__ */ jsx(
2302
+ "button",
2303
+ {
2304
+ type: "button",
2305
+ "aria-pressed": false,
2306
+ "data-slot": "view-segmented-item",
2307
+ onClick: () => setActiveTabId(tab.id),
2308
+ className: cn(
2309
+ viewSegmentedButtonClass(false),
2310
+ /* Tighter trailing edge when remove control follows */
2311
+ !isOnly && "pe-1.5"
2312
+ ),
2313
+ children: tabInner
2314
+ }
2315
+ ),
2316
+ !isActive && !isOnly && /* @__PURE__ */ jsx(Tip, { side: "bottom", label: `Remove ${tab.label} view`, children: /* @__PURE__ */ jsx(
2317
+ "button",
2318
+ {
2319
+ type: "button",
2320
+ "aria-label": `Remove ${tab.label} view`,
2321
+ onClick: (e) => removeTab(tab.id, e),
2322
+ className: "inline-flex items-center justify-center size-6 min-h-6 min-w-6 rounded transition-opacity opacity-0 group-hover:opacity-60 hover:!opacity-100 hover:text-destructive focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2323
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark text-xs", "aria-hidden": "true" })
2324
+ }
2325
+ ) })
2326
+ ] }, tab.id);
2327
+ })
2328
+ }
2329
+ ),
2330
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
2331
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2332
+ Button,
2333
+ {
2334
+ type: "button",
2335
+ variant: "ghost",
2336
+ className: "shrink-0 text-muted-foreground",
2337
+ children: [
2338
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-plus text-sm", "aria-hidden": "true" }),
2339
+ "Add view"
2340
+ ]
2341
+ }
2342
+ ) }),
2343
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", children: [
2344
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs", children: "Add a view" }),
2345
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2346
+ addableViewTypes.map((v, i) => /* @__PURE__ */ jsxs(
2347
+ DropdownMenuItem,
2348
+ {
2349
+ shortcut: dataListViewAddShortcut(i),
2350
+ onSelect: () => addView(v.type),
2351
+ children: [
2352
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${v.icon}`, "aria-hidden": "true" }),
2353
+ v.label
2354
+ ]
2355
+ },
2356
+ v.type
2357
+ ))
2358
+ ] })
2359
+ ] })
2360
+ ] }) }) }),
2361
+ activeTab ? /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: renderContent(activeTab, (patch) => updateTab(activeTab.id, patch)) }, activeTab.id) : null,
2362
+ onExportOpenChange && /* @__PURE__ */ jsx(
2363
+ ExportDrawer,
2364
+ {
2365
+ open: exportOpen,
2366
+ onOpenChange: onExportOpenChange,
2367
+ totalRows: exportTotalRows ?? getTabCount?.(activeTab.filterId) ?? 0
2368
+ }
2369
+ ),
2370
+ /* @__PURE__ */ jsx(Dialog, { open: renameOpen, onOpenChange: setRenameOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-sm", children: [
2371
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
2372
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Rename view" }),
2373
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Enter a new name for this view." })
2374
+ ] }),
2375
+ /* @__PURE__ */ jsx(
2376
+ Input,
2377
+ {
2378
+ className: "mt-3 h-9 text-sm",
2379
+ value: renameValue,
2380
+ onChange: (e) => setRenameValue(e.target.value),
2381
+ onKeyDown: (e) => {
2382
+ if (e.key === "Enter") commitRename();
2383
+ },
2384
+ autoFocus: true,
2385
+ "aria-label": "View name"
2386
+ }
2387
+ ),
2388
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
2389
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setRenameOpen(false), children: "Cancel" }),
2390
+ /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: commitRename, children: "Save" })
2391
+ ] })
2392
+ ] }) }),
2393
+ /* @__PURE__ */ jsx(
2394
+ Dialog,
2395
+ {
2396
+ open: reviewOpen && !!reviewTab,
2397
+ onOpenChange: (open) => {
2398
+ setReviewOpen(open);
2399
+ if (!open) setReviewTab(null);
2400
+ },
2401
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-md", children: [
2402
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
2403
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Review view" }),
2404
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Summary of this view\u2019s configuration." })
2405
+ ] }),
2406
+ reviewTab && /* @__PURE__ */ jsxs("dl", { className: "mt-2 space-y-3 text-sm", children: [
2407
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-4 border-b border-border pb-2", children: [
2408
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "Name" }),
2409
+ /* @__PURE__ */ jsx("dd", { className: "font-medium text-foreground text-end", children: reviewTab.label })
2410
+ ] }),
2411
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-4 border-b border-border pb-2", children: [
2412
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "View type" }),
2413
+ /* @__PURE__ */ jsx("dd", { className: "text-foreground text-end", children: VIEW_TYPES.find((v) => v.type === reviewTab.viewType)?.label })
2414
+ ] }),
2415
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-4 border-b border-border pb-2", children: [
2416
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "Lifecycle filter" }),
2417
+ /* @__PURE__ */ jsx("dd", { className: "text-foreground text-end capitalize", children: reviewTab.filterId })
2418
+ ] }),
2419
+ getTabCount && /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-4", children: [
2420
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "Row count" }),
2421
+ /* @__PURE__ */ jsx("dd", { className: "tabular-nums text-foreground text-end", children: getTabCount(reviewTab.filterId) })
2422
+ ] })
2423
+ ] }),
2424
+ /* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => setReviewOpen(false), children: "Close" }) })
2425
+ ] })
2426
+ }
2427
+ )
2428
+ ] });
2429
+ }
2430
+
2431
+ export { ListPageTemplate, VIEW_TYPES, viewToolbarCountBadgeClass };
2432
+ //# sourceMappingURL=list-page.js.map
2433
+ //# sourceMappingURL=list-page.js.map