@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,2768 @@
1
+ import * as React11 from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { Label as Label$1, RadioGroup as RadioGroup$1, Slot, Dialog, Select as Select$1, DropdownMenu as DropdownMenu$1, Tooltip as Tooltip$1, Popover as Popover$1 } from 'radix-ui';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import { cva } from 'class-variance-authority';
7
+ import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from 'lucide-react';
8
+ import { getDefaultClassNames, DayPicker } from 'react-day-picker';
9
+ import { useMaskInput } from 'use-mask-input';
10
+
11
+ // src/components/table-properties/drawer.tsx
12
+ function cn(...inputs) {
13
+ return twMerge(clsx(inputs));
14
+ }
15
+
16
+ // src/lib/data-list-view.ts
17
+ var DATA_LIST_VIEW_TILES = [
18
+ { value: "table", icon: "fa-table", label: "Table view" },
19
+ { value: "list", icon: "fa-list", label: "List view" },
20
+ { value: "board", icon: "fa-table-columns", label: "Board view" },
21
+ { value: "dashboard", icon: "fa-chart-mixed", label: "Dashboard view" },
22
+ { value: "calendar", icon: "fa-calendar-days", label: "Calendar view" },
23
+ { value: "folder", icon: "fa-grid-2", label: "Folder view" },
24
+ { value: "panel", icon: "fa-sidebar", label: "List & details" },
25
+ { value: "tree-panel", icon: "fa-sitemap", label: "Tree & details" }
26
+ ];
27
+ function dataListViewLabel(view) {
28
+ return DATA_LIST_VIEW_TILES.find((t) => t.value === view)?.label ?? view;
29
+ }
30
+ function dataListViewIcon(view) {
31
+ return DATA_LIST_VIEW_TILES.find((t) => t.value === view)?.icon ?? "fa-table";
32
+ }
33
+
34
+ // src/lib/data-list-view-surface.ts
35
+ function getDataListViewRenderKind(view) {
36
+ switch (view) {
37
+ case "table":
38
+ return "data-table";
39
+ case "list":
40
+ return "list-with-toolbar";
41
+ case "board":
42
+ return "board-with-toolbar";
43
+ case "dashboard":
44
+ return "dashboard-with-toolbar";
45
+ case "calendar":
46
+ return "calendar-with-toolbar";
47
+ case "folder":
48
+ return "folder-with-toolbar";
49
+ case "panel":
50
+ return "panel-with-toolbar";
51
+ case "tree-panel":
52
+ return "tree-panel-with-toolbar";
53
+ default: {
54
+ const _x = view;
55
+ return _x;
56
+ }
57
+ }
58
+ }
59
+
60
+ // src/lib/data-list-view-registry.ts
61
+ var DEFINITIONS = DATA_LIST_VIEW_TILES.map((tile) => {
62
+ const renderKind = getDataListViewRenderKind(tile.value);
63
+ const hubMetricsStrip = renderKind !== "calendar-with-toolbar" && renderKind !== "dashboard-with-toolbar";
64
+ return {
65
+ value: tile.value,
66
+ label: tile.label,
67
+ icon: tile.icon,
68
+ renderKind,
69
+ hubMetricsStrip
70
+ };
71
+ });
72
+ new Map(
73
+ DEFINITIONS.map((d) => [d.value, d])
74
+ );
75
+ var DATA_LIST_VIEW_REGISTRY = DEFINITIONS;
76
+ function dataListViewTilesForHub(supported) {
77
+ const allowed = new Set(supported);
78
+ return DATA_LIST_VIEW_REGISTRY.filter((d) => allowed.has(d.value)).map((d) => ({
79
+ type: d.value,
80
+ label: d.label,
81
+ icon: d.icon
82
+ }));
83
+ }
84
+ var DATA_LIST_SURFACE_VIEW_TYPES = new Set(
85
+ DATA_LIST_VIEW_REGISTRY.map((d) => d.value)
86
+ );
87
+ function isDataListSurfaceViewType(viewType) {
88
+ return DATA_LIST_SURFACE_VIEW_TYPES.has(viewType);
89
+ }
90
+
91
+ // src/lib/row-height.ts
92
+ var ROW_HEIGHT_TILES = [
93
+ { value: "compact", label: "Compact", icon: "fa-down-to-line" },
94
+ { value: "default", label: "Default", icon: "fa-arrows-up-down" },
95
+ { value: "comfortable", label: "Comfortable", icon: "fa-up-to-line" }
96
+ ];
97
+ var Label = React11.forwardRef(function Label2({ className, ...props }, ref) {
98
+ return /* @__PURE__ */ jsx(
99
+ Label$1.Root,
100
+ {
101
+ ref,
102
+ "data-slot": "label",
103
+ className: cn(
104
+ "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",
105
+ className
106
+ ),
107
+ ...props
108
+ }
109
+ );
110
+ });
111
+ var radioGroupItemVariants = cva(
112
+ [
113
+ "group/radio-group-item peer relative flex shrink-0 aspect-square rounded-full border border-input",
114
+ "outline-none transition-[color,box-shadow,transform,background-color,border-color] duration-150",
115
+ "motion-reduce:transition-none",
116
+ "group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2",
117
+ "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
118
+ "disabled:cursor-not-allowed disabled:opacity-50",
119
+ "aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:data-[state=checked]:border-primary",
120
+ "dark:bg-input/15 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40"
121
+ ].join(" "),
122
+ {
123
+ variants: {
124
+ variant: {
125
+ default: [
126
+ "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary"
127
+ ].join(" "),
128
+ outline: [
129
+ "bg-background",
130
+ "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"
131
+ ].join(" "),
132
+ secondary: [
133
+ "data-[state=checked]:border-secondary data-[state=checked]:bg-secondary data-[state=checked]:text-secondary-foreground"
134
+ ].join(" "),
135
+ success: [
136
+ "data-[state=checked]:border-chart-2 data-[state=checked]:bg-chart-2 data-[state=checked]:text-primary-foreground"
137
+ ].join(" "),
138
+ destructive: [
139
+ "data-[state=checked]:border-destructive data-[state=checked]:bg-destructive data-[state=checked]:text-destructive-foreground"
140
+ ].join(" "),
141
+ warning: [
142
+ "data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500 data-[state=checked]:text-amber-950"
143
+ ].join(" "),
144
+ muted: [
145
+ "data-[state=checked]:border-muted-foreground/50 data-[state=checked]:bg-muted data-[state=checked]:text-foreground"
146
+ ].join(" ")
147
+ },
148
+ size: {
149
+ sm: "size-3.5 min-h-3.5 min-w-3.5 max-h-3.5 max-w-3.5",
150
+ default: "size-4 min-h-4 min-w-4 max-h-4 max-w-4",
151
+ lg: "size-5 min-h-5 min-w-5 max-h-5 max-w-5"
152
+ },
153
+ motion: {
154
+ none: "",
155
+ pop: [
156
+ "motion-safe:active:scale-95",
157
+ "data-[state=checked]:motion-safe:scale-[1.04]"
158
+ ].join(" "),
159
+ glow: "data-[state=checked]:shadow-[0_0_0_3px] data-[state=checked]:shadow-primary/35",
160
+ "pop-glow": [
161
+ "motion-safe:active:scale-95",
162
+ "data-[state=checked]:motion-safe:scale-[1.04]",
163
+ "data-[state=checked]:shadow-[0_0_0_3px] data-[state=checked]:shadow-primary/35"
164
+ ].join(" ")
165
+ }
166
+ },
167
+ defaultVariants: {
168
+ variant: "default",
169
+ size: "default",
170
+ motion: "none"
171
+ }
172
+ }
173
+ );
174
+ var radioIndicatorDotVariants = cva(
175
+ "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",
176
+ {
177
+ variants: {
178
+ variant: {
179
+ default: "bg-primary-foreground",
180
+ outline: "bg-primary",
181
+ secondary: "bg-secondary-foreground",
182
+ success: "bg-primary-foreground",
183
+ destructive: "bg-destructive-foreground",
184
+ warning: "bg-amber-950",
185
+ muted: "bg-foreground"
186
+ },
187
+ size: {
188
+ sm: "size-1.5",
189
+ default: "size-2",
190
+ lg: "size-2.5"
191
+ }
192
+ },
193
+ defaultVariants: {
194
+ variant: "default",
195
+ size: "default"
196
+ }
197
+ }
198
+ );
199
+ var radioIndicatorWrapperVariants = cva("relative flex size-full items-center justify-center", {
200
+ variants: {
201
+ motion: {
202
+ none: "",
203
+ pop: "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:duration-150",
204
+ glow: "",
205
+ "pop-glow": "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:duration-150"
206
+ }
207
+ },
208
+ defaultVariants: { motion: "none" }
209
+ });
210
+ var RadioGroupItemChromeContext = React11.createContext({});
211
+ function RadioGroup({
212
+ className,
213
+ itemVariant,
214
+ itemSize,
215
+ itemMotion,
216
+ ...props
217
+ }) {
218
+ const ctx = React11.useMemo(
219
+ () => ({ itemVariant, itemSize, itemMotion }),
220
+ [itemVariant, itemSize, itemMotion]
221
+ );
222
+ return /* @__PURE__ */ jsx(RadioGroupItemChromeContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
223
+ RadioGroup$1.Root,
224
+ {
225
+ "data-slot": "radio-group",
226
+ className: cn("grid w-full gap-2", className),
227
+ ...props
228
+ }
229
+ ) });
230
+ }
231
+ var RadioGroupItem = React11.forwardRef(function RadioGroupItem2({ className, variant: variantProp, size: sizeProp, motion: motionProp, ...props }, ref) {
232
+ const ctx = React11.useContext(RadioGroupItemChromeContext);
233
+ const variant = variantProp ?? ctx.itemVariant;
234
+ const size = sizeProp ?? ctx.itemSize;
235
+ const motion = motionProp ?? ctx.itemMotion ?? "none";
236
+ const vResolved = variant ?? "default";
237
+ const sResolved = size ?? "default";
238
+ return /* @__PURE__ */ jsx(
239
+ RadioGroup$1.Item,
240
+ {
241
+ ref,
242
+ "data-slot": "radio-group-item",
243
+ "data-variant": vResolved,
244
+ "data-motion": motion,
245
+ className: cn(radioGroupItemVariants({ variant, size, motion }), className),
246
+ ...props,
247
+ children: /* @__PURE__ */ jsx(
248
+ RadioGroup$1.Indicator,
249
+ {
250
+ "data-slot": "radio-group-indicator",
251
+ className: radioIndicatorWrapperVariants({ motion }),
252
+ children: /* @__PURE__ */ jsx("span", { className: radioIndicatorDotVariants({ variant: vResolved, size: sResolved }) })
253
+ }
254
+ )
255
+ }
256
+ );
257
+ });
258
+ function selectionTileClassNames(selected) {
259
+ return cn(
260
+ "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",
261
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
262
+ 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"
263
+ );
264
+ }
265
+ function selectionTilePreviewClassNames(selected) {
266
+ return cn(
267
+ "relative box-border flex aspect-square w-full max-w-full flex-col rounded-lg border p-1 transition-colors",
268
+ selected ? "border-brand bg-brand/5 shadow-sm" : "border-border bg-background hover:border-border/80"
269
+ );
270
+ }
271
+ function SelectionTileGraphic({
272
+ option,
273
+ selected
274
+ }) {
275
+ if (option.leading != null) {
276
+ 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 });
277
+ }
278
+ if (option.icon) {
279
+ return /* @__PURE__ */ jsx(
280
+ "i",
281
+ {
282
+ className: cn(
283
+ "fa-light shrink-0 text-[18px] leading-none",
284
+ option.icon,
285
+ selected && "text-brand"
286
+ ),
287
+ "aria-hidden": "true"
288
+ }
289
+ );
290
+ }
291
+ return null;
292
+ }
293
+ function SelectionTileLabelText({
294
+ option
295
+ }) {
296
+ return /* @__PURE__ */ jsx("span", { className: "text-center leading-tight", children: option.label });
297
+ }
298
+ function SelectionTileCaptionBelow({
299
+ option,
300
+ selected,
301
+ ariaHidden = false
302
+ }) {
303
+ return /* @__PURE__ */ jsx(
304
+ "span",
305
+ {
306
+ className: cn(
307
+ "max-w-full px-0.5 text-center text-xs leading-tight",
308
+ selected ? "font-medium text-foreground" : "text-muted-foreground"
309
+ ),
310
+ ...ariaHidden ? { "aria-hidden": true } : {},
311
+ children: option.label
312
+ }
313
+ );
314
+ }
315
+ function SelectionTileGrid({
316
+ sectionLabel,
317
+ options,
318
+ columns = 4,
319
+ value,
320
+ onValueChange,
321
+ interaction,
322
+ idPrefix = "tile",
323
+ className,
324
+ labelPlacement = "inside",
325
+ itemVariant,
326
+ itemSize,
327
+ itemMotion
328
+ }) {
329
+ const gridClass = cn(
330
+ "gap-2",
331
+ columns === 2 && "grid grid-cols-2",
332
+ columns === 3 && "grid grid-cols-3",
333
+ columns === 4 && "grid grid-cols-4"
334
+ );
335
+ if (interaction === "radio") {
336
+ return /* @__PURE__ */ jsxs("div", { className, children: [
337
+ sectionLabel ? /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-medium text-muted-foreground", children: sectionLabel }) : null,
338
+ /* @__PURE__ */ jsx(
339
+ RadioGroup,
340
+ {
341
+ value,
342
+ onValueChange: (v) => onValueChange(v),
343
+ className: gridClass,
344
+ itemVariant,
345
+ itemSize,
346
+ itemMotion,
347
+ children: options.map((opt) => {
348
+ const selected = value === opt.value;
349
+ const id = `${idPrefix}-${opt.value}`;
350
+ if (labelPlacement === "below") {
351
+ return /* @__PURE__ */ jsxs(
352
+ Label,
353
+ {
354
+ htmlFor: id,
355
+ className: cn(
356
+ "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"
357
+ ),
358
+ children: [
359
+ /* @__PURE__ */ jsxs("span", { className: cn("flex w-full justify-center", selectionTilePreviewClassNames(selected)), children: [
360
+ /* @__PURE__ */ jsx(RadioGroupItem, { value: opt.value, id, className: "sr-only" }),
361
+ /* @__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 }) })
362
+ ] }),
363
+ /* @__PURE__ */ jsx(SelectionTileCaptionBelow, { option: opt, selected })
364
+ ]
365
+ },
366
+ opt.value
367
+ );
368
+ }
369
+ return /* @__PURE__ */ jsxs(
370
+ Label,
371
+ {
372
+ htmlFor: id,
373
+ className: cn(
374
+ "cursor-pointer rounded-lg focus-within:rounded-lg focus-within:ring-2 focus-within:ring-ring focus-within:outline-none",
375
+ selectionTileClassNames(selected)
376
+ ),
377
+ children: [
378
+ /* @__PURE__ */ jsx(RadioGroupItem, { value: opt.value, id, className: "sr-only" }),
379
+ /* @__PURE__ */ jsx(SelectionTileGraphic, { option: opt, selected }),
380
+ /* @__PURE__ */ jsx(SelectionTileLabelText, { option: opt })
381
+ ]
382
+ },
383
+ opt.value
384
+ );
385
+ })
386
+ }
387
+ )
388
+ ] });
389
+ }
390
+ return /* @__PURE__ */ jsxs("div", { className, children: [
391
+ sectionLabel ? /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-medium text-muted-foreground", children: sectionLabel }) : null,
392
+ /* @__PURE__ */ jsx("div", { className: gridClass, children: options.map((opt) => {
393
+ const selected = value === opt.value;
394
+ if (labelPlacement === "below") {
395
+ return /* @__PURE__ */ jsxs(
396
+ "button",
397
+ {
398
+ type: "button",
399
+ "aria-label": opt.label,
400
+ "aria-pressed": selected,
401
+ onClick: () => onValueChange(opt.value),
402
+ 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",
403
+ children: [
404
+ /* @__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 }) }) }),
405
+ /* @__PURE__ */ jsx(SelectionTileCaptionBelow, { option: opt, selected, ariaHidden: true })
406
+ ]
407
+ },
408
+ opt.value
409
+ );
410
+ }
411
+ return /* @__PURE__ */ jsxs(
412
+ "button",
413
+ {
414
+ type: "button",
415
+ "aria-label": opt.label,
416
+ "aria-pressed": selected,
417
+ onClick: () => onValueChange(opt.value),
418
+ className: selectionTileClassNames(selected),
419
+ children: [
420
+ /* @__PURE__ */ jsx(SelectionTileGraphic, { option: opt, selected }),
421
+ /* @__PURE__ */ jsx(SelectionTileLabelText, { option: opt })
422
+ ]
423
+ },
424
+ opt.value
425
+ );
426
+ }) })
427
+ ] });
428
+ }
429
+
430
+ // src/lib/dropdown-menu-surface.ts
431
+ var DROPDOWN_MENU_CONTENT_SURFACE_CLASS = "min-w-52 w-max max-w-[min(24rem,calc(100vw-2rem))]";
432
+ function DropdownMenu({
433
+ ...props
434
+ }) {
435
+ return /* @__PURE__ */ jsx(DropdownMenu$1.Root, { "data-slot": "dropdown-menu", ...props });
436
+ }
437
+ function DropdownMenuTrigger({
438
+ className,
439
+ ...props
440
+ }) {
441
+ return /* @__PURE__ */ jsx(
442
+ DropdownMenu$1.Trigger,
443
+ {
444
+ "data-slot": "dropdown-menu-trigger",
445
+ suppressHydrationWarning: true,
446
+ className: cn("cursor-pointer", className),
447
+ ...props
448
+ }
449
+ );
450
+ }
451
+ function DropdownMenuContent({
452
+ className,
453
+ align = "start",
454
+ sideOffset = 4,
455
+ ...props
456
+ }) {
457
+ return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(
458
+ DropdownMenu$1.Content,
459
+ {
460
+ "data-slot": "dropdown-menu-content",
461
+ sideOffset,
462
+ align,
463
+ className: cn(
464
+ "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",
465
+ DROPDOWN_MENU_CONTENT_SURFACE_CLASS,
466
+ className
467
+ ),
468
+ ...props
469
+ }
470
+ ) });
471
+ }
472
+ function DropdownMenuItem({
473
+ className,
474
+ inset,
475
+ variant = "default",
476
+ shortcut,
477
+ children,
478
+ asChild,
479
+ ...props
480
+ }) {
481
+ return /* @__PURE__ */ jsx(
482
+ DropdownMenu$1.Item,
483
+ {
484
+ "data-slot": "dropdown-menu-item",
485
+ "data-inset": inset,
486
+ "data-variant": variant,
487
+ asChild,
488
+ className: cn(
489
+ "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",
490
+ className
491
+ ),
492
+ ...props,
493
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
494
+ children,
495
+ shortcut ? /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: shortcut }) : null
496
+ ] })
497
+ }
498
+ );
499
+ }
500
+ function DropdownMenuLabel({
501
+ className,
502
+ inset,
503
+ ...props
504
+ }) {
505
+ return /* @__PURE__ */ jsx(
506
+ DropdownMenu$1.Label,
507
+ {
508
+ "data-slot": "dropdown-menu-label",
509
+ "data-inset": inset,
510
+ className: cn(
511
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:ps-7",
512
+ className
513
+ ),
514
+ ...props
515
+ }
516
+ );
517
+ }
518
+ function DropdownMenuSeparator({
519
+ className,
520
+ ...props
521
+ }) {
522
+ return /* @__PURE__ */ jsx(
523
+ DropdownMenu$1.Separator,
524
+ {
525
+ "data-slot": "dropdown-menu-separator",
526
+ className: cn("-mx-1 my-1 h-px bg-border", className),
527
+ ...props
528
+ }
529
+ );
530
+ }
531
+ function DropdownMenuShortcut({
532
+ className,
533
+ ...props
534
+ }) {
535
+ return /* @__PURE__ */ jsx(
536
+ "span",
537
+ {
538
+ "data-slot": "dropdown-menu-shortcut",
539
+ className: cn(
540
+ "ms-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
541
+ className
542
+ ),
543
+ ...props
544
+ }
545
+ );
546
+ }
547
+ var buttonVariants = cva(
548
+ "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",
549
+ {
550
+ variants: {
551
+ variant: {
552
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
553
+ 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",
554
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
555
+ 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",
556
+ 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",
557
+ link: "text-primary underline-offset-4 hover:underline"
558
+ },
559
+ size: {
560
+ default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pe-2.5 has-data-[icon=inline-start]:ps-2.5",
561
+ 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",
562
+ 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",
563
+ lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pe-3.5 has-data-[icon=inline-start]:ps-3.5",
564
+ icon: "size-9",
565
+ "icon-xs": "size-6 in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
566
+ "icon-sm": "size-8 in-data-[slot=button-group]:rounded-lg",
567
+ "icon-lg": "size-10"
568
+ }
569
+ },
570
+ defaultVariants: {
571
+ variant: "default",
572
+ size: "default"
573
+ }
574
+ }
575
+ );
576
+ var Button = React11.forwardRef(({ className, variant = "default", size = "default", asChild = false, ...props }, ref) => {
577
+ const Comp = asChild ? Slot.Root : "button";
578
+ return /* @__PURE__ */ jsx(
579
+ Comp,
580
+ {
581
+ ref,
582
+ "data-slot": "button",
583
+ "data-variant": variant,
584
+ "data-size": size,
585
+ className: cn(buttonVariants({ variant, size }), className),
586
+ ...props
587
+ }
588
+ );
589
+ });
590
+ Button.displayName = "Button";
591
+ function Sheet({ ...props }) {
592
+ return /* @__PURE__ */ jsx(Dialog.Root, { "data-slot": "sheet", ...props });
593
+ }
594
+ function SheetPortal({
595
+ ...props
596
+ }) {
597
+ return /* @__PURE__ */ jsx(Dialog.Portal, { "data-slot": "sheet-portal", ...props });
598
+ }
599
+ function SheetOverlay({
600
+ className,
601
+ ...props
602
+ }) {
603
+ return /* @__PURE__ */ jsx(
604
+ Dialog.Overlay,
605
+ {
606
+ "data-slot": "sheet-overlay",
607
+ className: cn(
608
+ "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",
609
+ className
610
+ ),
611
+ ...props
612
+ }
613
+ );
614
+ }
615
+ function SheetContent({
616
+ className,
617
+ children,
618
+ side = "right",
619
+ showCloseButton = true,
620
+ showOverlay = true,
621
+ ...props
622
+ }) {
623
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
624
+ showOverlay && /* @__PURE__ */ jsx(SheetOverlay, {}),
625
+ /* @__PURE__ */ jsxs(
626
+ Dialog.Content,
627
+ {
628
+ "data-slot": "sheet-content",
629
+ "data-side": side,
630
+ className: cn(
631
+ "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",
632
+ className
633
+ ),
634
+ ...props,
635
+ children: [
636
+ children,
637
+ showCloseButton && /* @__PURE__ */ jsx(Dialog.Close, { "data-slot": "sheet-close", asChild: true, children: /* @__PURE__ */ jsxs(
638
+ Button,
639
+ {
640
+ variant: "ghost",
641
+ className: "absolute top-3 end-3",
642
+ size: "icon-sm",
643
+ children: [
644
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark", "aria-hidden": "true" }),
645
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
646
+ ]
647
+ }
648
+ ) })
649
+ ]
650
+ }
651
+ )
652
+ ] });
653
+ }
654
+ function SheetTitle({
655
+ className,
656
+ ...props
657
+ }) {
658
+ return /* @__PURE__ */ jsx(
659
+ Dialog.Title,
660
+ {
661
+ "data-slot": "sheet-title",
662
+ className: cn(
663
+ "text-base font-medium text-foreground",
664
+ className
665
+ ),
666
+ ...props
667
+ }
668
+ );
669
+ }
670
+ function Select({
671
+ ...props
672
+ }) {
673
+ return /* @__PURE__ */ jsx(Select$1.Root, { "data-slot": "select", ...props });
674
+ }
675
+ function SelectValue({
676
+ ...props
677
+ }) {
678
+ return /* @__PURE__ */ jsx(Select$1.Value, { "data-slot": "select-value", ...props });
679
+ }
680
+ function SelectTrigger({
681
+ className,
682
+ size = "default",
683
+ children,
684
+ ...props
685
+ }) {
686
+ return /* @__PURE__ */ jsxs(
687
+ Select$1.Trigger,
688
+ {
689
+ "data-slot": "select-trigger",
690
+ "data-size": size,
691
+ className: cn(
692
+ "flex w-fit cursor-pointer items-center justify-between gap-1.5 rounded-md border border-input bg-transparent py-2 pe-2 ps-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/15 dark:hover:bg-input/50 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",
693
+ className
694
+ ),
695
+ ...props,
696
+ children: [
697
+ children,
698
+ /* @__PURE__ */ jsx(Select$1.Icon, { asChild: true, children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-down pointer-events-none size-4 text-muted-foreground", "aria-hidden": "true" }) })
699
+ ]
700
+ }
701
+ );
702
+ }
703
+ function SelectContent({
704
+ className,
705
+ children,
706
+ position = "item-aligned",
707
+ align = "center",
708
+ ...props
709
+ }) {
710
+ return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsxs(
711
+ Select$1.Content,
712
+ {
713
+ "data-slot": "select-content",
714
+ "data-align-trigger": position === "item-aligned",
715
+ className: cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none 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-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", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 rtl:data-[side=left]:translate-x-1 data-[side=right]:translate-x-1 rtl:data-[side=right]:-translate-x-1 data-[side=top]:-translate-y-1", className),
716
+ position,
717
+ align,
718
+ ...props,
719
+ children: [
720
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
721
+ /* @__PURE__ */ jsx(
722
+ Select$1.Viewport,
723
+ {
724
+ "data-position": position,
725
+ className: cn(
726
+ "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
727
+ position === "popper" && ""
728
+ ),
729
+ children
730
+ }
731
+ ),
732
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
733
+ ]
734
+ }
735
+ ) });
736
+ }
737
+ function SelectItem({
738
+ className,
739
+ children,
740
+ ...props
741
+ }) {
742
+ return /* @__PURE__ */ jsxs(
743
+ Select$1.Item,
744
+ {
745
+ "data-slot": "select-item",
746
+ className: cn(
747
+ "relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pe-8 ps-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground 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([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
748
+ className
749
+ ),
750
+ ...props,
751
+ children: [
752
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute end-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsx(Select$1.ItemIndicator, { children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-check pointer-events-none", "aria-hidden": "true" }) }) }),
753
+ /* @__PURE__ */ jsx(Select$1.ItemText, { children })
754
+ ]
755
+ }
756
+ );
757
+ }
758
+ function SelectScrollUpButton({
759
+ className,
760
+ ...props
761
+ }) {
762
+ return /* @__PURE__ */ jsx(
763
+ Select$1.ScrollUpButton,
764
+ {
765
+ "data-slot": "select-scroll-up-button",
766
+ className: cn(
767
+ "z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
768
+ className
769
+ ),
770
+ ...props,
771
+ children: /* @__PURE__ */ jsx(
772
+ "i",
773
+ {
774
+ className: "fa-light fa-chevron-up",
775
+ "aria-hidden": "true"
776
+ }
777
+ )
778
+ }
779
+ );
780
+ }
781
+ function SelectScrollDownButton({
782
+ className,
783
+ ...props
784
+ }) {
785
+ return /* @__PURE__ */ jsx(
786
+ Select$1.ScrollDownButton,
787
+ {
788
+ "data-slot": "select-scroll-down-button",
789
+ className: cn(
790
+ "z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
791
+ className
792
+ ),
793
+ ...props,
794
+ children: /* @__PURE__ */ jsx(
795
+ "i",
796
+ {
797
+ className: "fa-light fa-chevron-down",
798
+ "aria-hidden": "true"
799
+ }
800
+ )
801
+ }
802
+ );
803
+ }
804
+ function TooltipProvider({
805
+ delayDuration = 0,
806
+ ...props
807
+ }) {
808
+ return /* @__PURE__ */ jsx(
809
+ Tooltip$1.Provider,
810
+ {
811
+ "data-slot": "tooltip-provider",
812
+ delayDuration,
813
+ ...props
814
+ }
815
+ );
816
+ }
817
+ function Tooltip({
818
+ ...props
819
+ }) {
820
+ return /* @__PURE__ */ jsx(Tooltip$1.Root, { "data-slot": "tooltip", ...props });
821
+ }
822
+ function TooltipTrigger({
823
+ className,
824
+ ...props
825
+ }) {
826
+ return /* @__PURE__ */ jsx(
827
+ Tooltip$1.Trigger,
828
+ {
829
+ "data-slot": "tooltip-trigger",
830
+ suppressHydrationWarning: true,
831
+ className: cn("cursor-pointer", className),
832
+ ...props
833
+ }
834
+ );
835
+ }
836
+ function TooltipContent({
837
+ className,
838
+ sideOffset = 0,
839
+ children,
840
+ ...props
841
+ }) {
842
+ return /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsxs(
843
+ Tooltip$1.Content,
844
+ {
845
+ "data-slot": "tooltip-content",
846
+ sideOffset,
847
+ className: cn(
848
+ "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",
849
+ className
850
+ ),
851
+ ...props,
852
+ children: [
853
+ children,
854
+ /* @__PURE__ */ jsx(Tooltip$1.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
855
+ ]
856
+ }
857
+ ) });
858
+ }
859
+ function Tip({ label, children, side = "top" }) {
860
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
861
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
862
+ /* @__PURE__ */ jsx(TooltipContent, { side, className: "flex flex-wrap items-center gap-1.5", children: label })
863
+ ] });
864
+ }
865
+ function ToggleSwitch({ checked, onChange, id }) {
866
+ return /* @__PURE__ */ jsx(
867
+ "button",
868
+ {
869
+ id,
870
+ type: "button",
871
+ role: "switch",
872
+ "aria-checked": checked,
873
+ onClick: () => onChange(!checked),
874
+ className: cn(
875
+ "relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-input transition-colors",
876
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
877
+ checked ? "bg-primary" : "bg-input"
878
+ ),
879
+ children: /* @__PURE__ */ jsx("span", { className: cn(
880
+ "pointer-events-none inline-block size-4 rounded-full bg-primary-foreground shadow-sm transition-transform",
881
+ checked ? "translate-x-4" : "translate-x-0"
882
+ ) })
883
+ }
884
+ );
885
+ }
886
+ var Input = React11.forwardRef(
887
+ function Input2({ className, type, ...props }, ref) {
888
+ return /* @__PURE__ */ jsx(
889
+ "input",
890
+ {
891
+ ref,
892
+ type,
893
+ "data-slot": "input",
894
+ className: cn(
895
+ "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",
896
+ className
897
+ ),
898
+ ...props
899
+ }
900
+ );
901
+ }
902
+ );
903
+ function Calendar({
904
+ className,
905
+ classNames,
906
+ showOutsideDays = true,
907
+ captionLayout = "label",
908
+ buttonVariant = "ghost",
909
+ formatters,
910
+ components,
911
+ ...props
912
+ }) {
913
+ const defaultClassNames = getDefaultClassNames();
914
+ return /* @__PURE__ */ jsx(
915
+ DayPicker,
916
+ {
917
+ showOutsideDays,
918
+ className: cn(
919
+ "group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
920
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
921
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
922
+ className
923
+ ),
924
+ captionLayout,
925
+ formatters: {
926
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
927
+ ...formatters
928
+ },
929
+ classNames: {
930
+ root: cn("w-fit", defaultClassNames.root),
931
+ months: cn(
932
+ "relative flex flex-col gap-4 md:flex-row",
933
+ defaultClassNames.months
934
+ ),
935
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
936
+ nav: cn(
937
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
938
+ defaultClassNames.nav
939
+ ),
940
+ button_previous: cn(
941
+ buttonVariants({ variant: buttonVariant }),
942
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
943
+ defaultClassNames.button_previous
944
+ ),
945
+ button_next: cn(
946
+ buttonVariants({ variant: buttonVariant }),
947
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
948
+ defaultClassNames.button_next
949
+ ),
950
+ month_caption: cn(
951
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
952
+ defaultClassNames.month_caption
953
+ ),
954
+ dropdowns: cn(
955
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
956
+ defaultClassNames.dropdowns
957
+ ),
958
+ dropdown_root: cn(
959
+ "relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
960
+ defaultClassNames.dropdown_root
961
+ ),
962
+ dropdown: cn(
963
+ "absolute inset-0 bg-popover opacity-0",
964
+ defaultClassNames.dropdown
965
+ ),
966
+ caption_label: cn(
967
+ "font-medium select-none",
968
+ 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",
969
+ defaultClassNames.caption_label
970
+ ),
971
+ table: "w-full border-collapse",
972
+ weekdays: cn("flex", defaultClassNames.weekdays),
973
+ weekday: cn(
974
+ "flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none",
975
+ defaultClassNames.weekday
976
+ ),
977
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
978
+ week_number_header: cn(
979
+ "w-(--cell-size) select-none",
980
+ defaultClassNames.week_number_header
981
+ ),
982
+ week_number: cn(
983
+ "text-[0.8rem] text-muted-foreground select-none",
984
+ defaultClassNames.week_number
985
+ ),
986
+ day: cn(
987
+ "group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md",
988
+ props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" : "[&:first-child[data-selected=true]_button]:rounded-l-md",
989
+ defaultClassNames.day
990
+ ),
991
+ range_start: cn(
992
+ "rounded-l-md bg-accent",
993
+ defaultClassNames.range_start
994
+ ),
995
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
996
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
997
+ today: cn(
998
+ "rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none",
999
+ defaultClassNames.today
1000
+ ),
1001
+ outside: cn(
1002
+ "text-muted-foreground aria-selected:text-muted-foreground",
1003
+ defaultClassNames.outside
1004
+ ),
1005
+ disabled: cn(
1006
+ "text-muted-foreground opacity-50",
1007
+ defaultClassNames.disabled
1008
+ ),
1009
+ hidden: cn("invisible", defaultClassNames.hidden),
1010
+ ...classNames
1011
+ },
1012
+ components: {
1013
+ Root: ({ className: className2, rootRef, ...props2 }) => {
1014
+ return /* @__PURE__ */ jsx(
1015
+ "div",
1016
+ {
1017
+ "data-slot": "calendar",
1018
+ ref: rootRef,
1019
+ className: cn(className2),
1020
+ ...props2
1021
+ }
1022
+ );
1023
+ },
1024
+ Chevron: ({ className: className2, orientation, ...props2 }) => {
1025
+ if (orientation === "left") {
1026
+ return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
1027
+ }
1028
+ if (orientation === "right") {
1029
+ return /* @__PURE__ */ jsx(
1030
+ ChevronRightIcon,
1031
+ {
1032
+ className: cn("size-4", className2),
1033
+ ...props2
1034
+ }
1035
+ );
1036
+ }
1037
+ return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
1038
+ },
1039
+ DayButton: CalendarDayButton,
1040
+ WeekNumber: ({ children, ...props2 }) => {
1041
+ return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
1042
+ },
1043
+ ...components
1044
+ },
1045
+ ...props
1046
+ }
1047
+ );
1048
+ }
1049
+ function CalendarDayButton({
1050
+ className,
1051
+ day,
1052
+ modifiers,
1053
+ ...props
1054
+ }) {
1055
+ const defaultClassNames = getDefaultClassNames();
1056
+ const ref = React11.useRef(null);
1057
+ React11.useEffect(() => {
1058
+ if (modifiers.focused) ref.current?.focus();
1059
+ }, [modifiers.focused]);
1060
+ return /* @__PURE__ */ jsx(
1061
+ Button,
1062
+ {
1063
+ ref,
1064
+ variant: "ghost",
1065
+ size: "icon",
1066
+ "data-day": day.date.toLocaleDateString(),
1067
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
1068
+ "data-range-start": modifiers.range_start,
1069
+ "data-range-end": modifiers.range_end,
1070
+ "data-range-middle": modifiers.range_middle,
1071
+ className: cn(
1072
+ "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",
1073
+ defaultClassNames.day,
1074
+ className
1075
+ ),
1076
+ ...props
1077
+ }
1078
+ );
1079
+ }
1080
+
1081
+ // src/lib/date-filter.ts
1082
+ function ymdToLocalDate(ymd) {
1083
+ if (!ymd || !/^\d{4}-\d{2}-\d{2}$/.test(ymd)) return void 0;
1084
+ const [y, m, d] = ymd.split("-").map(Number);
1085
+ return new Date(y, m - 1, d, 12, 0, 0, 0);
1086
+ }
1087
+ function localDateToYmd(d) {
1088
+ const y = d.getFullYear();
1089
+ const m = String(d.getMonth() + 1).padStart(2, "0");
1090
+ const day = String(d.getDate()).padStart(2, "0");
1091
+ return `${y}-${m}-${day}`;
1092
+ }
1093
+ function FilterDateCalendar({
1094
+ valueYmd,
1095
+ onChangeYmd,
1096
+ label
1097
+ }) {
1098
+ const [timeZone, setTimeZone] = React11.useState();
1099
+ React11.useEffect(() => {
1100
+ setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone);
1101
+ }, []);
1102
+ return /* @__PURE__ */ jsx(
1103
+ "div",
1104
+ {
1105
+ className: "rounded-lg border border-border overflow-hidden",
1106
+ role: "group",
1107
+ "aria-label": label,
1108
+ children: /* @__PURE__ */ jsx(
1109
+ Calendar,
1110
+ {
1111
+ mode: "single",
1112
+ selected: ymdToLocalDate(valueYmd),
1113
+ onSelect: (d) => onChangeYmd(d ? localDateToYmd(d) : void 0),
1114
+ captionLayout: "dropdown",
1115
+ timeZone,
1116
+ className: "rounded-lg border-0"
1117
+ }
1118
+ )
1119
+ }
1120
+ );
1121
+ }
1122
+ function InputGroup({ className, ...props }) {
1123
+ return /* @__PURE__ */ jsx(
1124
+ "div",
1125
+ {
1126
+ "data-slot": "input-group",
1127
+ role: "group",
1128
+ className: cn(
1129
+ "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",
1130
+ className
1131
+ ),
1132
+ ...props
1133
+ }
1134
+ );
1135
+ }
1136
+ var inputGroupAddonVariants = cva(
1137
+ "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",
1138
+ {
1139
+ variants: {
1140
+ align: {
1141
+ "inline-start": "order-first ps-2 has-[>button]:ms-[-0.3rem] has-[>kbd]:ms-[-0.15rem]",
1142
+ "inline-end": "order-last pe-2 has-[>button]:me-[-0.3rem] has-[>kbd]:me-[-0.15rem]",
1143
+ "block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
1144
+ "block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
1145
+ }
1146
+ },
1147
+ defaultVariants: {
1148
+ align: "inline-start"
1149
+ }
1150
+ }
1151
+ );
1152
+ function InputGroupAddon({
1153
+ className,
1154
+ align = "inline-start",
1155
+ ...props
1156
+ }) {
1157
+ return /* @__PURE__ */ jsx(
1158
+ "div",
1159
+ {
1160
+ role: "group",
1161
+ "data-slot": "input-group-addon",
1162
+ "data-align": align,
1163
+ className: cn(inputGroupAddonVariants({ align }), className),
1164
+ onClick: (e) => {
1165
+ if (e.target.closest("button")) {
1166
+ return;
1167
+ }
1168
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
1169
+ },
1170
+ ...props
1171
+ }
1172
+ );
1173
+ }
1174
+ var inputGroupButtonVariants = cva(
1175
+ "flex items-center gap-2 text-sm shadow-none",
1176
+ {
1177
+ variants: {
1178
+ size: {
1179
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
1180
+ sm: "",
1181
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
1182
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
1183
+ }
1184
+ },
1185
+ defaultVariants: {
1186
+ size: "xs"
1187
+ }
1188
+ }
1189
+ );
1190
+ function InputGroupButton({
1191
+ className,
1192
+ type = "button",
1193
+ variant = "ghost",
1194
+ size = "xs",
1195
+ ...props
1196
+ }) {
1197
+ return /* @__PURE__ */ jsx(
1198
+ Button,
1199
+ {
1200
+ type,
1201
+ "data-size": size,
1202
+ variant,
1203
+ className: cn(inputGroupButtonVariants({ size }), className),
1204
+ ...props
1205
+ }
1206
+ );
1207
+ }
1208
+
1209
+ // src/lib/compose-refs.ts
1210
+ function composeRefs(...refs) {
1211
+ return (node) => {
1212
+ for (const ref of refs) {
1213
+ if (ref == null) continue;
1214
+ if (typeof ref === "function") {
1215
+ ref(node);
1216
+ } else {
1217
+ ref.current = node;
1218
+ }
1219
+ }
1220
+ };
1221
+ }
1222
+ var exxatInputMaskDefaults = {
1223
+ placeholder: "_",
1224
+ showMaskOnHover: false
1225
+ };
1226
+ var exxatMaskPatterns = {
1227
+ /** US NANP 10-digit display */
1228
+ phoneUS: "(999) 999-9999",
1229
+ /** US ZIP or ZIP+4 */
1230
+ zipUS: "99999[-9999]",
1231
+ /** Calendar-style date (validate separately). */
1232
+ dateMDY: "99/99/9999"};
1233
+ var MaskedInput = React11.forwardRef(function MaskedInput2({ mask, maskOptions, className, type = "text", ...props }, ref) {
1234
+ const maskRef = useMaskInput({
1235
+ mask,
1236
+ options: { ...exxatInputMaskDefaults, ...maskOptions }
1237
+ });
1238
+ return /* @__PURE__ */ jsx(
1239
+ Input,
1240
+ {
1241
+ ref: composeRefs(ref, maskRef),
1242
+ type,
1243
+ className: cn(className),
1244
+ ...props
1245
+ }
1246
+ );
1247
+ });
1248
+ function Popover({ ...props }) {
1249
+ return /* @__PURE__ */ jsx(Popover$1.Root, { ...props });
1250
+ }
1251
+ function PopoverTrigger({ className, ...props }) {
1252
+ return /* @__PURE__ */ jsx(Popover$1.Trigger, { className: cn("cursor-pointer", className), ...props });
1253
+ }
1254
+ function PopoverContent({
1255
+ className,
1256
+ align = "start",
1257
+ sideOffset = 4,
1258
+ ...props
1259
+ }) {
1260
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
1261
+ Popover$1.Content,
1262
+ {
1263
+ "data-slot": "popover-content",
1264
+ align,
1265
+ sideOffset,
1266
+ className: cn(
1267
+ "z-50 rounded-lg border border-border bg-popover shadow-md outline-none",
1268
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
1269
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1270
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
1271
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
1272
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
1273
+ className
1274
+ ),
1275
+ ...props
1276
+ }
1277
+ ) });
1278
+ }
1279
+ var DATE_PICKER_ICON_CLASS = "fa-light fa-calendar";
1280
+ function parseMdyToLocalDate(raw) {
1281
+ const match = raw.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
1282
+ if (!match) return void 0;
1283
+ const month = Number(match[1]);
1284
+ const day = Number(match[2]);
1285
+ const year = Number(match[3]);
1286
+ if (month < 1 || month > 12 || day < 1 || day > 31) return void 0;
1287
+ const date = new Date(year, month - 1, day, 12, 0, 0, 0);
1288
+ if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) return void 0;
1289
+ return date;
1290
+ }
1291
+ function formatLocalDateToMdy(date) {
1292
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1293
+ const day = String(date.getDate()).padStart(2, "0");
1294
+ const year = String(date.getFullYear());
1295
+ return `${month}/${day}/${year}`;
1296
+ }
1297
+ function DateTextInputField({
1298
+ value,
1299
+ onValueChange,
1300
+ "aria-label": ariaLabel,
1301
+ id,
1302
+ placeholder = "MM/DD/YYYY",
1303
+ className,
1304
+ inputClassName,
1305
+ autoFocus,
1306
+ disabled,
1307
+ fromYear = 2020,
1308
+ toYear = 2032,
1309
+ iconButtonVariant = "ghost",
1310
+ popoverAlign = "end",
1311
+ popoverClassName
1312
+ }) {
1313
+ return /* @__PURE__ */ jsxs(InputGroup, { className, children: [
1314
+ /* @__PURE__ */ jsx(
1315
+ MaskedInput,
1316
+ {
1317
+ "data-slot": "input-group-control",
1318
+ id,
1319
+ mask: exxatMaskPatterns.dateMDY,
1320
+ "aria-label": ariaLabel,
1321
+ placeholder,
1322
+ value,
1323
+ onChange: (event) => onValueChange(event.target.value),
1324
+ className: cn(
1325
+ "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",
1326
+ inputClassName
1327
+ ),
1328
+ autoFocus,
1329
+ disabled
1330
+ }
1331
+ ),
1332
+ /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(Popover, { children: [
1333
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1334
+ InputGroupButton,
1335
+ {
1336
+ type: "button",
1337
+ variant: iconButtonVariant,
1338
+ size: "icon-xs",
1339
+ disabled,
1340
+ "aria-label": `${ariaLabel} pick date`,
1341
+ children: /* @__PURE__ */ jsx("i", { className: DATE_PICKER_ICON_CLASS, "aria-hidden": "true" })
1342
+ }
1343
+ ) }),
1344
+ /* @__PURE__ */ jsx(
1345
+ PopoverContent,
1346
+ {
1347
+ className: cn("z-[80] w-auto p-0", popoverClassName),
1348
+ align: popoverAlign,
1349
+ sideOffset: 6,
1350
+ children: /* @__PURE__ */ jsx(
1351
+ Calendar,
1352
+ {
1353
+ mode: "single",
1354
+ selected: parseMdyToLocalDate(value),
1355
+ onSelect: (next) => onValueChange(next ? formatLocalDateToMdy(next) : ""),
1356
+ initialFocus: true,
1357
+ fromYear,
1358
+ toYear,
1359
+ captionLayout: "dropdown"
1360
+ }
1361
+ )
1362
+ }
1363
+ )
1364
+ ] }) })
1365
+ ] });
1366
+ }
1367
+ var MASK_BY_KIND = {
1368
+ phone: exxatMaskPatterns.phoneUS,
1369
+ zip: exxatMaskPatterns.zipUS,
1370
+ dateMDY: exxatMaskPatterns.dateMDY
1371
+ };
1372
+ function FilterTextValueInput({
1373
+ id,
1374
+ mask,
1375
+ value,
1376
+ onValueChange,
1377
+ "aria-label": ariaLabel,
1378
+ placeholder,
1379
+ className,
1380
+ autoFocus
1381
+ }) {
1382
+ if (mask === "dateMDY") {
1383
+ return /* @__PURE__ */ jsx(
1384
+ DateTextInputField,
1385
+ {
1386
+ id,
1387
+ value,
1388
+ onValueChange,
1389
+ "aria-label": ariaLabel,
1390
+ placeholder,
1391
+ inputClassName: className,
1392
+ autoFocus,
1393
+ iconButtonVariant: "ghost",
1394
+ popoverAlign: "end"
1395
+ }
1396
+ );
1397
+ }
1398
+ if (mask) {
1399
+ return /* @__PURE__ */ jsx(
1400
+ MaskedInput,
1401
+ {
1402
+ id,
1403
+ mask: MASK_BY_KIND[mask],
1404
+ "aria-label": ariaLabel,
1405
+ placeholder,
1406
+ value,
1407
+ onChange: (e) => onValueChange(e.target.value),
1408
+ className,
1409
+ autoFocus
1410
+ }
1411
+ );
1412
+ }
1413
+ return /* @__PURE__ */ jsx(
1414
+ Input,
1415
+ {
1416
+ id,
1417
+ type: "text",
1418
+ "aria-label": ariaLabel,
1419
+ placeholder,
1420
+ value,
1421
+ onChange: (e) => onValueChange(e.target.value),
1422
+ className,
1423
+ autoFocus
1424
+ }
1425
+ );
1426
+ }
1427
+
1428
+ // src/lib/table-properties-types.ts
1429
+ var OPERATOR_LABELS = {
1430
+ is: "is",
1431
+ is_not: "is not",
1432
+ contains: "contains",
1433
+ not_contains: "does not contain"
1434
+ };
1435
+ var RULE_COLORS = [
1436
+ { name: "Green", bg: "var(--conditional-rule-green)" },
1437
+ { name: "Yellow", bg: "var(--conditional-rule-yellow)" },
1438
+ { name: "Blue", bg: "var(--conditional-rule-blue)" },
1439
+ { name: "Red", bg: "var(--conditional-rule-red)" },
1440
+ { name: "Purple", bg: "var(--conditional-rule-purple)" },
1441
+ { name: "Orange", bg: "var(--conditional-rule-orange)" }
1442
+ ];
1443
+ function DrawerFilterCard(props) {
1444
+ const {
1445
+ fieldDef,
1446
+ expanded,
1447
+ onToggleExpand,
1448
+ onRemove,
1449
+ renderOptionLabel
1450
+ } = props;
1451
+ const isCond = props.variant === "conditional";
1452
+ const filter = props.filter;
1453
+ const filterId = filter.id;
1454
+ const onUpdate = props.onUpdate;
1455
+ const [optSearch, setOptSearch] = React11.useState("");
1456
+ const options = fieldDef.options ?? [];
1457
+ const showSearch = options.length > 8;
1458
+ const filteredOpts = optSearch ? options.filter((o) => o.label.toLowerCase().includes(optSearch.toLowerCase())) : options;
1459
+ const values = filter.values;
1460
+ React11.useEffect(() => {
1461
+ if (fieldDef.type !== "select" && fieldDef.type !== "date") return;
1462
+ if (filter.operator !== "is" && filter.operator !== "is_not") {
1463
+ onUpdate(filterId, { operator: "is" });
1464
+ }
1465
+ }, [filter.operator, filter.id, fieldDef.type, filterId, onUpdate]);
1466
+ function toggleValue(val) {
1467
+ const next = values.includes(val) ? values.filter((v) => v !== val) : [...values, val];
1468
+ onUpdate(filterId, { values: next });
1469
+ }
1470
+ function cycleOperator() {
1471
+ const ops = fieldDef.operators;
1472
+ const idx = ops.indexOf(filter.operator);
1473
+ const i = idx === -1 ? 0 : idx;
1474
+ onUpdate(filterId, { operator: ops[(i + 1) % ops.length] });
1475
+ }
1476
+ const removeLabel = isCond ? "rule" : "filter";
1477
+ const rule = isCond ? props.filter : null;
1478
+ return /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs("div", { children: [
1479
+ /* @__PURE__ */ jsxs(
1480
+ "div",
1481
+ {
1482
+ className: "flex items-start justify-between px-3 pt-2.5 pb-2 gap-2 cursor-pointer",
1483
+ role: "button",
1484
+ tabIndex: 0,
1485
+ "aria-label": expanded ? `Collapse ${fieldDef.label}` : `Expand ${fieldDef.label}`,
1486
+ onClick: onToggleExpand,
1487
+ onKeyDown: (e) => {
1488
+ if (e.key === "Enter" || e.key === " ") {
1489
+ e.preventDefault();
1490
+ onToggleExpand();
1491
+ }
1492
+ },
1493
+ children: [
1494
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1495
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: fieldDef.label }),
1496
+ /* @__PURE__ */ jsxs(
1497
+ Button,
1498
+ {
1499
+ type: "button",
1500
+ variant: "ghost",
1501
+ size: "xs",
1502
+ "aria-label": `Operator: ${OPERATOR_LABELS[filter.operator]} \u2014 click to cycle`,
1503
+ onClick: (e) => {
1504
+ e.stopPropagation();
1505
+ cycleOperator();
1506
+ },
1507
+ className: "h-auto py-0 px-1 -ms-1 text-xs text-muted-foreground font-normal",
1508
+ children: [
1509
+ OPERATOR_LABELS[filter.operator],
1510
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-down text-xs", "aria-hidden": "true" })
1511
+ ]
1512
+ }
1513
+ )
1514
+ ] }),
1515
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 shrink-0 self-start", children: [
1516
+ /* @__PURE__ */ jsx(Tip, { label: `Remove ${fieldDef.label} ${removeLabel}`, side: "top", children: /* @__PURE__ */ jsx(
1517
+ Button,
1518
+ {
1519
+ type: "button",
1520
+ variant: "ghost",
1521
+ size: "icon-sm",
1522
+ "aria-label": `Remove ${fieldDef.label} ${removeLabel}`,
1523
+ className: "text-muted-foreground hover:text-destructive",
1524
+ onClick: (e) => {
1525
+ e.stopPropagation();
1526
+ onRemove(filterId);
1527
+ },
1528
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-trash text-xs", "aria-hidden": "true" })
1529
+ }
1530
+ ) }),
1531
+ /* @__PURE__ */ jsx(
1532
+ "i",
1533
+ {
1534
+ className: `fa-light ${expanded ? "fa-chevron-up" : "fa-chevron-down"} text-xs text-muted-foreground mt-2`,
1535
+ "aria-hidden": "true"
1536
+ }
1537
+ )
1538
+ ] })
1539
+ ]
1540
+ }
1541
+ ),
1542
+ expanded && /* @__PURE__ */ jsxs("div", { className: "border-t border-border", children: [
1543
+ fieldDef.type === "select" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1544
+ showSearch && /* @__PURE__ */ jsx("div", { className: "px-3 pt-2 pb-1", children: /* @__PURE__ */ jsx(Input, { placeholder: "Search\u2026", value: optSearch, onChange: (e) => setOptSearch(e.target.value), className: "h-7 text-xs" }) }),
1545
+ /* @__PURE__ */ jsxs("div", { role: "listbox", "aria-multiselectable": "true", "aria-label": `${fieldDef.label} options`, className: "py-1 max-h-52 overflow-y-auto", children: [
1546
+ filteredOpts.map((opt) => {
1547
+ const checked = values.includes(opt.value);
1548
+ return /* @__PURE__ */ jsxs(
1549
+ "div",
1550
+ {
1551
+ role: "option",
1552
+ "aria-selected": checked,
1553
+ tabIndex: 0,
1554
+ onClick: () => toggleValue(opt.value),
1555
+ onKeyDown: (e) => {
1556
+ if (e.key === "Enter" || e.key === " ") {
1557
+ e.preventDefault();
1558
+ toggleValue(opt.value);
1559
+ }
1560
+ },
1561
+ className: "flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-interactive-hover cursor-pointer select-none focus-visible:outline-none focus-visible:bg-interactive-hover",
1562
+ children: [
1563
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-slot": "checkbox", "data-state": checked ? "checked" : "unchecked", className: cn(
1564
+ "inline-flex items-center justify-center size-3.5 shrink-0 rounded-[3px] border transition-colors",
1565
+ checked ? "bg-primary border-primary text-primary-foreground" : "border-input bg-background"
1566
+ ), children: checked && /* @__PURE__ */ jsx("i", { className: "fa-solid fa-check text-current", style: { fontSize: "7px" } }) }),
1567
+ renderOptionLabel ? renderOptionLabel(opt.value) : /* @__PURE__ */ jsx("span", { className: "text-foreground", children: opt.label })
1568
+ ]
1569
+ },
1570
+ opt.value
1571
+ );
1572
+ }),
1573
+ filteredOpts.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No options found" })
1574
+ ] })
1575
+ ] }) : fieldDef.type === "date" ? /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
1576
+ FilterDateCalendar,
1577
+ {
1578
+ label: `${fieldDef.label} \u2014 choose date`,
1579
+ valueYmd: filter.values[0],
1580
+ onChangeYmd: (ymd) => onUpdate(filterId, { values: ymd ? [ymd] : [] })
1581
+ }
1582
+ ) }) : fieldDef.type === "text" ? /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx(
1583
+ FilterTextValueInput,
1584
+ {
1585
+ mask: fieldDef.textMask,
1586
+ "aria-label": `${fieldDef.label} value`,
1587
+ placeholder: `Enter ${fieldDef.label.toLowerCase()}\u2026`,
1588
+ value: values[0] ?? "",
1589
+ onValueChange: (next) => onUpdate(filterId, { values: [next] }),
1590
+ className: "text-sm",
1591
+ autoFocus: true
1592
+ }
1593
+ ) }) : null,
1594
+ values.length > 0 ? /* @__PURE__ */ jsx("div", { className: "sticky bottom-0 border-t border-border bg-card p-2", children: /* @__PURE__ */ jsxs(
1595
+ Button,
1596
+ {
1597
+ type: "button",
1598
+ variant: "outline",
1599
+ size: "sm",
1600
+ onClick: () => onUpdate(filterId, { values: [] }),
1601
+ className: "w-full justify-center gap-1.5 text-xs text-muted-foreground",
1602
+ children: [
1603
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark text-xs", "aria-hidden": "true" }),
1604
+ "Clear selection"
1605
+ ]
1606
+ }
1607
+ ) }) : null
1608
+ ] }),
1609
+ isCond && rule && /* @__PURE__ */ jsxs("div", { className: "border-t border-border px-3 py-2.5", children: [
1610
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2", children: "Highlight color" }),
1611
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: RULE_COLORS.map((c) => /* @__PURE__ */ jsx(
1612
+ Button,
1613
+ {
1614
+ type: "button",
1615
+ size: "icon-xs",
1616
+ variant: "outline",
1617
+ "aria-label": c.name,
1618
+ className: cn(
1619
+ "rounded-md border-2 p-0 transition-all",
1620
+ rule.bgColor === c.bg ? "border-foreground scale-110" : "border-transparent hover:scale-105"
1621
+ ),
1622
+ style: { background: c.bg },
1623
+ onClick: () => onUpdate(filterId, { bgColor: c.bg })
1624
+ },
1625
+ c.name
1626
+ )) })
1627
+ ] })
1628
+ ] }) });
1629
+ }
1630
+ function DragHandleGripIcon({ className }) {
1631
+ return /* @__PURE__ */ jsx("i", { className: cn("fa-solid fa-grip-dots-vertical shrink-0", className), "aria-hidden": "true" });
1632
+ }
1633
+ function DrawerSortCard(props) {
1634
+ const { rule, fieldLabel, isPrimary, onRemove, onToggleDir } = props;
1635
+ const label = fieldLabel || rule.fieldKey;
1636
+ if (!label) return null;
1637
+ return /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-background overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5", children: [
1638
+ /* @__PURE__ */ jsx(DragHandleGripIcon, { className: "text-[13px] text-muted-foreground/40" }),
1639
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1640
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
1641
+ isPrimary && /* @__PURE__ */ jsx("span", { className: "text-xs font-bold text-accent-foreground bg-accent rounded px-1 py-0.5 leading-none uppercase tracking-wide shrink-0", children: "Primary" }),
1642
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground truncate", children: label })
1643
+ ] }),
1644
+ /* @__PURE__ */ jsxs(
1645
+ "button",
1646
+ {
1647
+ type: "button",
1648
+ "aria-label": `Direction: ${rule.direction === "asc" ? "Ascending" : "Descending"} \u2014 click to toggle`,
1649
+ onClick: onToggleDir,
1650
+ className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-interactive-hover-foreground transition-colors mt-0.5",
1651
+ children: [
1652
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${rule.direction === "asc" ? "fa-arrow-up-a-z" : "fa-arrow-down-a-z"} text-xs`, "aria-hidden": "true" }),
1653
+ rule.direction === "asc" ? "Ascending" : "Descending",
1654
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-down text-xs", "aria-hidden": "true" })
1655
+ ]
1656
+ }
1657
+ )
1658
+ ] }),
1659
+ /* @__PURE__ */ jsx(Tip, { label: `Remove ${label} sort`, side: "top", children: /* @__PURE__ */ jsx(
1660
+ "button",
1661
+ {
1662
+ type: "button",
1663
+ "aria-label": `Remove ${label} sort`,
1664
+ onClick: onRemove,
1665
+ className: "inline-flex items-center justify-center size-7 rounded text-muted-foreground hover:text-destructive hover:bg-interactive-hover transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring shrink-0",
1666
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-trash text-xs", "aria-hidden": "true" })
1667
+ }
1668
+ ) })
1669
+ ] }) });
1670
+ }
1671
+ function ColumnRow({
1672
+ label,
1673
+ isFirst,
1674
+ isLast,
1675
+ visible,
1676
+ onToggleVisible,
1677
+ onMoveUp,
1678
+ onMoveDown,
1679
+ draggable,
1680
+ onDragStart,
1681
+ onDragOver,
1682
+ onDrop,
1683
+ onDragEnd,
1684
+ isDragging,
1685
+ isOver
1686
+ }) {
1687
+ return /* @__PURE__ */ jsxs(
1688
+ "div",
1689
+ {
1690
+ role: "listitem",
1691
+ draggable,
1692
+ onDragStart,
1693
+ onDragOver,
1694
+ onDrop,
1695
+ onDragEnd,
1696
+ className: cn(
1697
+ "flex items-center gap-2 px-2 py-2 rounded-lg group hover:bg-interactive-hover-subtle transition-colors cursor-grab active:cursor-grabbing",
1698
+ isDragging && "opacity-40",
1699
+ isOver && "ring-2 ring-ring bg-accent/30"
1700
+ ),
1701
+ children: [
1702
+ /* @__PURE__ */ jsx(DragHandleGripIcon, { className: "text-[13px] text-muted-foreground/40 transition-colors group-hover:text-muted-foreground" }),
1703
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm text-foreground", children: label }),
1704
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity", children: [
1705
+ /* @__PURE__ */ jsx(Tip, { label: `Move ${label} up`, side: "top", children: /* @__PURE__ */ jsx(
1706
+ "button",
1707
+ {
1708
+ type: "button",
1709
+ "aria-label": `Move ${label} up`,
1710
+ disabled: isFirst,
1711
+ onClick: onMoveUp,
1712
+ className: "inline-flex items-center justify-center size-6 rounded text-muted-foreground hover:text-interactive-hover-foreground hover:bg-interactive-hover disabled:opacity-30 disabled:pointer-events-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1713
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-up text-xs", "aria-hidden": "true" })
1714
+ }
1715
+ ) }),
1716
+ /* @__PURE__ */ jsx(Tip, { label: `Move ${label} down`, side: "top", children: /* @__PURE__ */ jsx(
1717
+ "button",
1718
+ {
1719
+ type: "button",
1720
+ "aria-label": `Move ${label} down`,
1721
+ disabled: isLast,
1722
+ onClick: onMoveDown,
1723
+ className: "inline-flex items-center justify-center size-6 rounded text-muted-foreground hover:text-interactive-hover-foreground hover:bg-interactive-hover disabled:opacity-30 disabled:pointer-events-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1724
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-down text-xs", "aria-hidden": "true" })
1725
+ }
1726
+ ) })
1727
+ ] }),
1728
+ /* @__PURE__ */ jsx(
1729
+ ToggleSwitch,
1730
+ {
1731
+ checked: visible,
1732
+ onChange: onToggleVisible
1733
+ }
1734
+ )
1735
+ ]
1736
+ }
1737
+ );
1738
+ }
1739
+ function useDraggableList(items, getId, onReorder) {
1740
+ const [dragId, setDragId] = React11.useState(null);
1741
+ const [overId, setOverId] = React11.useState(null);
1742
+ function getItemProps(id) {
1743
+ return {
1744
+ draggable: true,
1745
+ onDragStart: (e) => {
1746
+ e.dataTransfer.effectAllowed = "move";
1747
+ setDragId(id);
1748
+ },
1749
+ onDragOver: (e) => {
1750
+ e.preventDefault();
1751
+ e.dataTransfer.dropEffect = "move";
1752
+ setOverId(id);
1753
+ },
1754
+ onDrop: (e) => {
1755
+ e.preventDefault();
1756
+ if (!dragId || dragId === id) {
1757
+ setDragId(null);
1758
+ setOverId(null);
1759
+ return;
1760
+ }
1761
+ const from = items.findIndex((i) => getId(i) === dragId);
1762
+ const to = items.findIndex((i) => getId(i) === id);
1763
+ if (from === -1 || to === -1) {
1764
+ setDragId(null);
1765
+ setOverId(null);
1766
+ return;
1767
+ }
1768
+ const next = [...items];
1769
+ const [moved] = next.splice(from, 1);
1770
+ next.splice(to, 0, moved);
1771
+ onReorder(next);
1772
+ setDragId(null);
1773
+ setOverId(null);
1774
+ },
1775
+ onDragEnd: () => {
1776
+ setDragId(null);
1777
+ setOverId(null);
1778
+ },
1779
+ "data-dragging": dragId === id,
1780
+ "data-over": overId === id && dragId !== id
1781
+ };
1782
+ }
1783
+ return { dragId, overId, getItemProps };
1784
+ }
1785
+ var PROPERTIES_SHEET_PORTAL_Z = "z-[90]";
1786
+ function TablePropertiesDrawer({
1787
+ open,
1788
+ onOpenChange,
1789
+ initialPanel,
1790
+ showGridlines,
1791
+ onShowGridlinesChange,
1792
+ rowHeight,
1793
+ onRowHeightChange,
1794
+ pagination,
1795
+ onPaginationChange,
1796
+ activeFilters,
1797
+ onAddFilter,
1798
+ onUpdateFilter,
1799
+ onRemoveFilter,
1800
+ getFilterConnector,
1801
+ onToggleFilterConnector,
1802
+ filterBarVisible,
1803
+ onFilterBarVisibleChange,
1804
+ drawerExpandedFilters,
1805
+ onDrawerExpandedFiltersChange,
1806
+ totalRows,
1807
+ filteredRows,
1808
+ sortRules,
1809
+ onSortRulesChange,
1810
+ onAddSortRule,
1811
+ onRemoveSortRule,
1812
+ onToggleSortDir,
1813
+ colOrder,
1814
+ onColOrderChange,
1815
+ hiddenCols,
1816
+ onToggleColVisibility,
1817
+ onMoveCol,
1818
+ groupBy,
1819
+ onGroupByChange,
1820
+ primarySortKey,
1821
+ conditionalRules,
1822
+ onAddConditionalRule,
1823
+ onRemoveConditionalRule,
1824
+ onUpdateConditionalRule,
1825
+ filterFields,
1826
+ currentView,
1827
+ onViewChange,
1828
+ supportedViewTypes,
1829
+ lifecycleTabLabel,
1830
+ fieldDefinitions,
1831
+ resolveColumnLabel: resolveColumnLabelProp,
1832
+ displayOptions,
1833
+ onDisplayOptionsChange,
1834
+ boardGroupByColumnOptions,
1835
+ renderFilterOptionValue
1836
+ }) {
1837
+ const [sheetPanel, setSheetPanel] = React11.useState("main");
1838
+ React11.useEffect(() => {
1839
+ if (open && initialPanel) {
1840
+ setSheetPanel(initialPanel);
1841
+ } else if (!open) {
1842
+ setSheetPanel("main");
1843
+ }
1844
+ }, [open, initialPanel]);
1845
+ const resolveColumnLabel = React11.useCallback(
1846
+ (key) => resolveColumnLabelProp?.(key) ?? fieldDefinitions.find((f) => f.key === key)?.label ?? key,
1847
+ [resolveColumnLabelProp, fieldDefinitions]
1848
+ );
1849
+ const sortFieldList = React11.useMemo(
1850
+ () => fieldDefinitions.filter(
1851
+ (f) => f.sortable !== false && f.key !== "select" && f.key !== "actions"
1852
+ ),
1853
+ [fieldDefinitions]
1854
+ );
1855
+ const groupFieldList = React11.useMemo(
1856
+ () => fieldDefinitions.filter((f) => f.key !== "select" && f.key !== "actions"),
1857
+ [fieldDefinitions]
1858
+ );
1859
+ const viewSurface = currentView ?? "table";
1860
+ const isBoardView = viewSurface === "board";
1861
+ const boardGroupByLabel = boardGroupByColumnOptions?.find((o) => o.key === displayOptions.boardGroupByColumnKey)?.label;
1862
+ const viewDisplayLabel = dataListViewLabel(viewSurface);
1863
+ const viewDisplayDesc = (() => {
1864
+ if (viewSurface === "board") {
1865
+ return [
1866
+ boardGroupByLabel ? `By ${boardGroupByLabel}` : null,
1867
+ `${displayOptions.boardLineCount}-line`,
1868
+ displayOptions.showColumnLabels ? "Column labels" : "No labels"
1869
+ ].filter(Boolean).join(" \xB7 ");
1870
+ }
1871
+ if (viewSurface === "list") {
1872
+ return [
1873
+ displayOptions.showColumnLabels ? "Column labels" : "No labels",
1874
+ displayOptions.showToolbarSearch ? "Toolbar search" : "No search"
1875
+ ].join(" \xB7 ");
1876
+ }
1877
+ if (viewSurface === "dashboard") {
1878
+ return "Charts \xB7 KPI metrics";
1879
+ }
1880
+ return [showGridlines ? "Gridlines" : null, pagination ? "Paginated" : null].filter(Boolean).join(" \xB7 ") || "Default";
1881
+ })();
1882
+ const viewDisplayIcon = DATA_LIST_VIEW_TILES.find((t) => t.value === viewSurface)?.icon ?? "fa-table";
1883
+ const sortDrag = useDraggableList(sortRules, (r) => r.id, onSortRulesChange);
1884
+ const orderable = colOrder.filter((k) => k !== "select" && k !== "actions");
1885
+ const colDrag = useDraggableList(
1886
+ orderable,
1887
+ (k) => k,
1888
+ (newOrder) => onColOrderChange(["select", ...newOrder, "actions"])
1889
+ );
1890
+ const primarySortLabel = primarySortKey ? resolveColumnLabel(primarySortKey) : sortRules[0]?.fieldKey ? resolveColumnLabel(sortRules[0].fieldKey) : "\u2014";
1891
+ return /* @__PURE__ */ jsx(Sheet, { open, onOpenChange, modal: false, children: /* @__PURE__ */ jsx(
1892
+ SheetContent,
1893
+ {
1894
+ side: "right",
1895
+ showCloseButton: false,
1896
+ showOverlay: false,
1897
+ className: "z-[80] w-[min(20rem,calc(100vw-1rem))] p-0 gap-0 flex flex-col border border-border shadow-xl rounded-xl overflow-hidden",
1898
+ style: { top: "0.5rem", bottom: "0.5rem", right: "0.5rem", height: "calc(100svh - 1rem)" },
1899
+ children: sheetPanel === "main" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1900
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-4 pt-5 pb-3", children: [
1901
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1902
+ /* @__PURE__ */ jsx(SheetTitle, { className: "text-base font-semibold leading-tight", children: "Properties" }),
1903
+ lifecycleTabLabel ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", title: lifecycleTabLabel, children: lifecycleTabLabel }) : null
1904
+ ] }),
1905
+ /* @__PURE__ */ jsx(Tip, { label: "Close", side: "bottom", children: /* @__PURE__ */ jsx(
1906
+ Button,
1907
+ {
1908
+ type: "button",
1909
+ variant: "ghost",
1910
+ size: "icon-sm",
1911
+ "aria-label": "Close",
1912
+ onClick: () => onOpenChange(false),
1913
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark text-[13px]", "aria-hidden": "true" })
1914
+ }
1915
+ ) })
1916
+ ] }),
1917
+ onViewChange && currentView && /* @__PURE__ */ jsx("div", { className: "px-4 pb-3", children: /* @__PURE__ */ jsx(
1918
+ SelectionTileGrid,
1919
+ {
1920
+ sectionLabel: "View type",
1921
+ options: supportedViewTypes && supportedViewTypes.length > 0 ? dataListViewTilesForHub(supportedViewTypes).map((t) => ({
1922
+ value: t.type,
1923
+ label: t.label,
1924
+ icon: t.icon
1925
+ })) : DATA_LIST_VIEW_TILES,
1926
+ columns: 4,
1927
+ value: currentView,
1928
+ onValueChange: onViewChange,
1929
+ interaction: "button",
1930
+ idPrefix: "props-view"
1931
+ }
1932
+ ) }),
1933
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto py-2 px-3 space-y-1", children: [
1934
+ {
1935
+ id: "table-display",
1936
+ icon: viewDisplayIcon,
1937
+ label: viewDisplayLabel,
1938
+ desc: viewDisplayDesc
1939
+ },
1940
+ {
1941
+ id: "filter",
1942
+ icon: "fa-filter",
1943
+ label: "Filter",
1944
+ desc: activeFilters.length === 0 ? `Showing all ${filteredRows} rows.` : `${activeFilters.length} filter${activeFilters.length !== 1 ? "s" : ""} active \xB7 ${filteredRows} rows.`
1945
+ },
1946
+ {
1947
+ id: "sort",
1948
+ icon: "fa-arrow-up-arrow-down",
1949
+ label: "Sort",
1950
+ desc: `Sorted by ${primarySortLabel}.`
1951
+ },
1952
+ {
1953
+ id: "group",
1954
+ icon: "fa-layer-group",
1955
+ label: "Group",
1956
+ desc: groupBy ? `Grouped by ${resolveColumnLabel(groupBy)}.` : "No grouping."
1957
+ },
1958
+ {
1959
+ id: "columns",
1960
+ icon: "fa-table-columns",
1961
+ label: "Columns",
1962
+ desc: hiddenCols.size === 0 ? "All columns visible." : `${hiddenCols.size} column${hiddenCols.size !== 1 ? "s" : ""} hidden.`
1963
+ },
1964
+ {
1965
+ id: "conditional-rules",
1966
+ icon: "fa-palette",
1967
+ label: "Conditional rules",
1968
+ desc: conditionalRules.length === 0 ? "No rules applied." : `${conditionalRules.length} rule${conditionalRules.length !== 1 ? "s" : ""} active.`
1969
+ }
1970
+ ].map((item) => /* @__PURE__ */ jsxs(
1971
+ Button,
1972
+ {
1973
+ type: "button",
1974
+ variant: "ghost",
1975
+ onClick: () => setSheetPanel(item.id),
1976
+ className: cn(
1977
+ "w-full h-auto justify-start gap-3 px-3 py-3 rounded-2xl font-normal border border-transparent",
1978
+ "hover:bg-muted/60 hover:text-foreground",
1979
+ "focus-visible:bg-muted/60 focus-visible:text-foreground"
1980
+ ),
1981
+ children: [
1982
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: `fa-light ${item.icon} text-[15px] text-secondary-foreground`, "aria-hidden": "true" }) }),
1983
+ /* @__PURE__ */ jsxs("span", { className: "flex-1 min-w-0 text-start", children: [
1984
+ /* @__PURE__ */ jsx("span", { className: "block text-sm font-medium text-foreground", children: item.label }),
1985
+ /* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground mt-0.5", children: item.desc })
1986
+ ] }),
1987
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-right text-xs text-muted-foreground shrink-0", "aria-hidden": "true" })
1988
+ ]
1989
+ },
1990
+ item.id
1991
+ )) })
1992
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1993
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-4 pt-4 pb-3", children: [
1994
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
1995
+ /* @__PURE__ */ jsx(Tip, { label: "Back to Properties", side: "bottom", children: /* @__PURE__ */ jsx(
1996
+ Button,
1997
+ {
1998
+ type: "button",
1999
+ variant: "ghost",
2000
+ size: "icon-sm",
2001
+ className: "shrink-0",
2002
+ "aria-label": "Back to Properties",
2003
+ onClick: () => setSheetPanel("main"),
2004
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-chevron-left text-[13px]", "aria-hidden": "true" })
2005
+ }
2006
+ ) }),
2007
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2008
+ /* @__PURE__ */ jsxs(SheetTitle, { className: "text-base font-semibold text-foreground leading-tight flex items-center gap-1.5", children: [
2009
+ {
2010
+ "table-display": viewDisplayLabel,
2011
+ filter: "Filter",
2012
+ sort: "Sort",
2013
+ group: "Group",
2014
+ columns: "Columns",
2015
+ "conditional-rules": "Conditional rules",
2016
+ main: ""
2017
+ }[sheetPanel],
2018
+ sheetPanel === "filter" && /* @__PURE__ */ jsx("i", { className: "fa-light fa-circle-question text-xs text-muted-foreground", "aria-hidden": "true" })
2019
+ ] }),
2020
+ sheetPanel === "filter" && /* @__PURE__ */ jsx(
2021
+ "p",
2022
+ {
2023
+ className: "text-xs text-muted-foreground mt-0.5",
2024
+ "aria-live": "polite",
2025
+ "aria-atomic": "true",
2026
+ children: activeFilters.length === 0 ? `Showing all ${filteredRows} rows` : `${filteredRows} of ${totalRows} rows match \xB7 ${activeFilters.length} filter${activeFilters.length !== 1 ? "s" : ""} active`
2027
+ }
2028
+ )
2029
+ ] })
2030
+ ] }),
2031
+ /* @__PURE__ */ jsx(Tip, { label: "Close", side: "bottom", children: /* @__PURE__ */ jsx(
2032
+ Button,
2033
+ {
2034
+ type: "button",
2035
+ variant: "ghost",
2036
+ size: "icon-sm",
2037
+ className: "shrink-0",
2038
+ "aria-label": "Close panel",
2039
+ onClick: () => onOpenChange(false),
2040
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-xmark text-[13px]", "aria-hidden": "true" })
2041
+ }
2042
+ ) })
2043
+ ] }),
2044
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
2045
+ sheetPanel === "table-display" && /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-5", children: [
2046
+ isBoardView ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground leading-relaxed", children: [
2047
+ dataListViewLabel("board"),
2048
+ " groups rows into columns. Sort, filter, and column settings apply to the same dataset as other views (e.g. Table view)."
2049
+ ] }) : null,
2050
+ isBoardView && boardGroupByColumnOptions && boardGroupByColumnOptions.length > 1 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 py-2", children: [
2051
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2052
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-table-columns text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2053
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2054
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Board columns" }),
2055
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Choose which field splits the board into swimlanes." })
2056
+ ] })
2057
+ ] }),
2058
+ /* @__PURE__ */ jsxs(
2059
+ Select,
2060
+ {
2061
+ value: boardGroupByColumnOptions.some((o) => o.key === displayOptions.boardGroupByColumnKey) ? displayOptions.boardGroupByColumnKey : boardGroupByColumnOptions[0].key,
2062
+ onValueChange: (v) => onDisplayOptionsChange({ boardGroupByColumnKey: v }),
2063
+ children: [
2064
+ /* @__PURE__ */ jsx(
2065
+ SelectTrigger,
2066
+ {
2067
+ size: "sm",
2068
+ className: "w-[9.5rem] shrink-0",
2069
+ id: "board-group-by-field",
2070
+ "aria-label": "Field for board columns",
2071
+ children: /* @__PURE__ */ jsx(SelectValue, {})
2072
+ }
2073
+ ),
2074
+ /* @__PURE__ */ jsx(SelectContent, { align: "end", className: PROPERTIES_SHEET_PORTAL_Z, children: boardGroupByColumnOptions.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.key, children: o.label }, o.key)) })
2075
+ ]
2076
+ }
2077
+ )
2078
+ ] }) : null,
2079
+ viewSurface === "table" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2080
+ /* @__PURE__ */ jsxs("div", { children: [
2081
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-3", children: "Appearance" }),
2082
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: [
2083
+ { id: "gridlines", icon: "fa-border-all", label: "Gridlines", checked: showGridlines, onChange: onShowGridlinesChange },
2084
+ { id: "pagination", icon: "fa-table-list", label: "Pagination", checked: pagination, onChange: onPaginationChange }
2085
+ ].map((row) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-2", children: [
2086
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 text-sm", children: [
2087
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${row.icon} text-muted-foreground w-4 text-center`, "aria-hidden": "true" }),
2088
+ /* @__PURE__ */ jsx("label", { htmlFor: `toggle-${row.id}`, className: "cursor-pointer select-none", children: row.label })
2089
+ ] }),
2090
+ /* @__PURE__ */ jsx(ToggleSwitch, { id: `toggle-${row.id}`, checked: row.checked, onChange: row.onChange })
2091
+ ] }, row.id)) })
2092
+ ] }),
2093
+ /* @__PURE__ */ jsx("div", { className: "border-t border-border pt-4", children: /* @__PURE__ */ jsx(
2094
+ SelectionTileGrid,
2095
+ {
2096
+ sectionLabel: "Row height",
2097
+ options: ROW_HEIGHT_TILES,
2098
+ columns: 3,
2099
+ value: rowHeight,
2100
+ onValueChange: onRowHeightChange,
2101
+ interaction: "button",
2102
+ idPrefix: "row-height"
2103
+ }
2104
+ ) })
2105
+ ] }) : null,
2106
+ /* @__PURE__ */ jsxs(
2107
+ "div",
2108
+ {
2109
+ className: cn(
2110
+ "space-y-3",
2111
+ (viewSurface === "board" || viewSurface === "table") && "border-t border-border pt-4"
2112
+ ),
2113
+ children: [
2114
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Display options" }),
2115
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2116
+ isBoardView && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-2", children: [
2117
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2118
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-file-lines text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2119
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Line count" }) })
2120
+ ] }),
2121
+ /* @__PURE__ */ jsxs(
2122
+ Select,
2123
+ {
2124
+ value: String(displayOptions.boardLineCount),
2125
+ onValueChange: (v) => onDisplayOptionsChange({ boardLineCount: Number(v) }),
2126
+ children: [
2127
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-[6.5rem] shrink-0", id: "board-line-count", "aria-label": "Line count", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
2128
+ /* @__PURE__ */ jsxs(SelectContent, { align: "end", className: PROPERTIES_SHEET_PORTAL_Z, children: [
2129
+ /* @__PURE__ */ jsx(SelectItem, { value: "1", children: "1 line" }),
2130
+ /* @__PURE__ */ jsx(SelectItem, { value: "2", children: "2 lines" }),
2131
+ /* @__PURE__ */ jsx(SelectItem, { value: "3", children: "3 lines" })
2132
+ ] })
2133
+ ]
2134
+ }
2135
+ )
2136
+ ] }),
2137
+ viewSurface === "table" && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-2", children: [
2138
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2139
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-font text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2140
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2141
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Table title" }),
2142
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Show the page heading and subtitle." })
2143
+ ] })
2144
+ ] }),
2145
+ /* @__PURE__ */ jsx(
2146
+ ToggleSwitch,
2147
+ {
2148
+ id: "toggle-view-title",
2149
+ checked: displayOptions.showViewTitle,
2150
+ onChange: (v) => onDisplayOptionsChange({ showViewTitle: v })
2151
+ }
2152
+ )
2153
+ ] }),
2154
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-2", children: [
2155
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2156
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-table-columns text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2157
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2158
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Column labels" }),
2159
+ viewSurface === "table" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Column headers in the table." }) : viewSurface === "list" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Column headers in the list." }) : null
2160
+ ] })
2161
+ ] }),
2162
+ /* @__PURE__ */ jsx(
2163
+ ToggleSwitch,
2164
+ {
2165
+ id: "toggle-column-labels",
2166
+ checked: displayOptions.showColumnLabels,
2167
+ onChange: (v) => onDisplayOptionsChange({ showColumnLabels: v })
2168
+ }
2169
+ )
2170
+ ] }),
2171
+ isBoardView && /* @__PURE__ */ jsxs(Fragment, { children: [
2172
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-2", children: [
2173
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2174
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-hashtag text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2175
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Column counts" }) })
2176
+ ] }),
2177
+ /* @__PURE__ */ jsx(
2178
+ ToggleSwitch,
2179
+ {
2180
+ id: "toggle-board-counts",
2181
+ checked: displayOptions.showBoardColumnCounts,
2182
+ onChange: (v) => onDisplayOptionsChange({ showBoardColumnCounts: v })
2183
+ }
2184
+ )
2185
+ ] }),
2186
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-2", children: [
2187
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2188
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-square-plus text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2189
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Above new card button" }) })
2190
+ ] }),
2191
+ /* @__PURE__ */ jsx(
2192
+ ToggleSwitch,
2193
+ {
2194
+ id: "toggle-new-card-above",
2195
+ checked: displayOptions.boardNewCardAbove,
2196
+ onChange: (v) => onDisplayOptionsChange({ boardNewCardAbove: v })
2197
+ }
2198
+ )
2199
+ ] })
2200
+ ] }),
2201
+ (viewSurface === "table" || viewSurface === "list") && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-2", children: [
2202
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [
2203
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-secondary border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-magnifying-glass text-[15px] text-secondary-foreground", "aria-hidden": "true" }) }),
2204
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2205
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground leading-tight", children: "Search" }),
2206
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Toolbar search for this view." })
2207
+ ] })
2208
+ ] }),
2209
+ /* @__PURE__ */ jsx(
2210
+ ToggleSwitch,
2211
+ {
2212
+ id: "toggle-toolbar-search",
2213
+ checked: displayOptions.showToolbarSearch,
2214
+ onChange: (v) => onDisplayOptionsChange({ showToolbarSearch: v })
2215
+ }
2216
+ )
2217
+ ] })
2218
+ ] })
2219
+ ]
2220
+ }
2221
+ )
2222
+ ] }),
2223
+ sheetPanel === "filter" && /* @__PURE__ */ jsxs("div", { className: "px-4 py-4 space-y-2", children: [
2224
+ activeFilters.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border bg-muted/40 p-4 space-y-3", children: [
2225
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2226
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center size-7 rounded-lg bg-background border border-border shrink-0", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-filter text-muted-foreground text-xs", "aria-hidden": "true" }) }),
2227
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "No filters yet" })
2228
+ ] }),
2229
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground leading-relaxed", children: [
2230
+ "Use filters to show only the rows you need. With multiple filters, use ",
2231
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground/80", children: "and" }),
2232
+ " or ",
2233
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground/80", children: "or" }),
2234
+ " between them to control how they combine."
2235
+ ] }),
2236
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: [
2237
+ { icon: "fa-circle-1", text: 'Click "Add filter" below' },
2238
+ { icon: "fa-circle-2", text: "Choose a field to filter by" },
2239
+ { icon: "fa-circle-3", text: "Pick at least one value \u2014 the grid updates immediately" }
2240
+ ].map((step) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2241
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${step.icon} text-muted-foreground text-xs shrink-0`, "aria-hidden": "true" }),
2242
+ step.text
2243
+ ] }, step.icon)) })
2244
+ ] }) : /* @__PURE__ */ jsx(Fragment, { children: activeFilters.map((f, idx) => {
2245
+ const fieldDef = filterFields.find((fd) => fd.key === f.fieldKey);
2246
+ if (!fieldDef) return null;
2247
+ const leftId = idx > 0 ? activeFilters[idx - 1].id : null;
2248
+ const connector = leftId ? getFilterConnector(leftId) : "and";
2249
+ return /* @__PURE__ */ jsxs(React11.Fragment, { children: [
2250
+ idx > 0 && leftId && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-1", children: [
2251
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border", "aria-hidden": "true" }),
2252
+ /* @__PURE__ */ jsx(Tip, { label: "Click to switch: AND \u2014 every filter must match; OR \u2014 any matching filter is enough.", side: "top", children: /* @__PURE__ */ jsx(
2253
+ "button",
2254
+ {
2255
+ type: "button",
2256
+ onClick: () => onToggleFilterConnector(leftId),
2257
+ className: cn(
2258
+ "shrink-0 rounded-md border px-2.5 py-0.5 text-xs font-semibold uppercase tracking-wide transition-colors",
2259
+ "border-border bg-muted/40 text-muted-foreground hover:bg-interactive-hover hover:text-interactive-hover-foreground",
2260
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
2261
+ ),
2262
+ "aria-label": connector === "and" ? "Filters are combined with AND. Click to use OR instead." : "Filters are combined with OR. Click to use AND instead.",
2263
+ children: connector
2264
+ }
2265
+ ) }),
2266
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border", "aria-hidden": "true" })
2267
+ ] }),
2268
+ /* @__PURE__ */ jsx(
2269
+ DrawerFilterCard,
2270
+ {
2271
+ filter: f,
2272
+ fieldDef,
2273
+ expanded: drawerExpandedFilters.has(f.id),
2274
+ onToggleExpand: () => onDrawerExpandedFiltersChange((prev) => {
2275
+ const next = new Set(prev);
2276
+ if (next.has(f.id)) next.delete(f.id);
2277
+ else next.add(f.id);
2278
+ return next;
2279
+ }),
2280
+ onUpdate: onUpdateFilter,
2281
+ onRemove: (id) => {
2282
+ onRemoveFilter(id);
2283
+ onDrawerExpandedFiltersChange((prev) => {
2284
+ const next = new Set(prev);
2285
+ next.delete(id);
2286
+ return next;
2287
+ });
2288
+ },
2289
+ renderOptionLabel: (value) => renderFilterOptionValue?.(f.fieldKey, value)
2290
+ }
2291
+ )
2292
+ ] }, f.id);
2293
+ }) }),
2294
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
2295
+ /* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
2296
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2297
+ Button,
2298
+ {
2299
+ type: "button",
2300
+ variant: "outline",
2301
+ className: "flex-1 gap-1.5 h-8 border-dashed text-muted-foreground",
2302
+ children: [
2303
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-plus text-xs", "aria-hidden": "true" }),
2304
+ "Add filter"
2305
+ ]
2306
+ }
2307
+ ) }),
2308
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", className: PROPERTIES_SHEET_PORTAL_Z, children: [
2309
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs", children: "Filter by field" }),
2310
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2311
+ filterFields.map((f) => /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: () => onAddFilter(f.key), children: [
2312
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${f.icon}`, "aria-hidden": "true" }),
2313
+ f.label
2314
+ ] }, f.key))
2315
+ ] })
2316
+ ] }),
2317
+ activeFilters.length > 0 && /* @__PURE__ */ jsx(
2318
+ Button,
2319
+ {
2320
+ type: "button",
2321
+ variant: "ghost",
2322
+ size: "sm",
2323
+ className: "shrink-0 text-destructive hover:text-destructive hover:bg-destructive/10",
2324
+ onClick: () => {
2325
+ activeFilters.forEach((f) => onRemoveFilter(f.id));
2326
+ onDrawerExpandedFiltersChange(/* @__PURE__ */ new Set());
2327
+ },
2328
+ children: "Remove all"
2329
+ }
2330
+ )
2331
+ ] }),
2332
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 pt-3 mt-1 border-t border-border", children: [
2333
+ /* @__PURE__ */ jsxs("div", { children: [
2334
+ /* @__PURE__ */ jsx("label", { htmlFor: "toggle-filter-bar", className: "text-sm font-medium text-foreground cursor-pointer", children: "Enable filter bar" }),
2335
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Show filters above the table." })
2336
+ ] }),
2337
+ /* @__PURE__ */ jsx(ToggleSwitch, { id: "toggle-filter-bar", checked: filterBarVisible, onChange: onFilterBarVisibleChange })
2338
+ ] })
2339
+ ] }),
2340
+ sheetPanel === "sort" && /* @__PURE__ */ jsxs("div", { className: "px-4 py-4 space-y-2", children: [
2341
+ sortRules.length === 0 ? (
2342
+ /* Empty state */
2343
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-dashed border-border bg-muted/30 px-4 py-6 text-center space-y-2", children: [
2344
+ /* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-muted mb-1", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-arrow-up-arrow-down text-muted-foreground text-[16px]", "aria-hidden": "true" }) }),
2345
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "No sorts applied" }),
2346
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: "Add a sort rule to order rows by any field. Multiple rules are applied in priority order." }),
2347
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5 text-start pt-1", children: [
2348
+ { icon: "fa-circle-1", text: 'Click "Add sort" below' },
2349
+ { icon: "fa-circle-2", text: "Choose a field to sort by" },
2350
+ { icon: "fa-circle-3", text: "Toggle ascending or descending" }
2351
+ ].map((step) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2352
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${step.icon} text-muted-foreground text-xs shrink-0`, "aria-hidden": "true" }),
2353
+ step.text
2354
+ ] }, step.icon)) })
2355
+ ] })
2356
+ ) : sortRules.map((rule, idx) => {
2357
+ const dragProps = sortDrag.getItemProps(rule.id);
2358
+ return /* @__PURE__ */ jsxs(React11.Fragment, { children: [
2359
+ idx > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-0.5", children: [
2360
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
2361
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground px-1", children: "then by" }),
2362
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" })
2363
+ ] }),
2364
+ /* @__PURE__ */ jsx(
2365
+ "div",
2366
+ {
2367
+ ...dragProps,
2368
+ className: cn(
2369
+ "transition-all",
2370
+ dragProps["data-dragging"] && "opacity-40",
2371
+ dragProps["data-over"] && "ring-2 ring-ring bg-accent/30 rounded-lg"
2372
+ ),
2373
+ children: /* @__PURE__ */ jsx(
2374
+ DrawerSortCard,
2375
+ {
2376
+ rule,
2377
+ fieldLabel: resolveColumnLabel(rule.fieldKey),
2378
+ isPrimary: idx === 0,
2379
+ onRemove: () => onRemoveSortRule(rule.id),
2380
+ onToggleDir: () => onToggleSortDir(rule.id)
2381
+ }
2382
+ )
2383
+ }
2384
+ )
2385
+ ] }, rule.id);
2386
+ }),
2387
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
2388
+ /* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
2389
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2390
+ Button,
2391
+ {
2392
+ type: "button",
2393
+ variant: "outline",
2394
+ className: "flex-1 gap-1.5 h-8 border-dashed text-muted-foreground",
2395
+ children: [
2396
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-plus text-xs", "aria-hidden": "true" }),
2397
+ "Add sort"
2398
+ ]
2399
+ }
2400
+ ) }),
2401
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", className: PROPERTIES_SHEET_PORTAL_Z, children: [
2402
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs", children: "Sort by field" }),
2403
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2404
+ sortFieldList.filter((f) => !sortRules.some((r) => r.fieldKey === f.key)).map((col) => /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: () => onAddSortRule(col.key), children: [
2405
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-arrow-up-arrow-down text-xs", "aria-hidden": "true" }),
2406
+ col.label
2407
+ ] }, col.key)),
2408
+ sortFieldList.filter((f) => !sortRules.some((r) => r.fieldKey === f.key)).length === 0 && /* @__PURE__ */ jsx("p", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: "All fields added" })
2409
+ ] })
2410
+ ] }),
2411
+ sortRules.length > 0 && /* @__PURE__ */ jsx(
2412
+ Button,
2413
+ {
2414
+ type: "button",
2415
+ variant: "ghost",
2416
+ size: "sm",
2417
+ className: "shrink-0 text-destructive hover:text-destructive hover:bg-destructive/10",
2418
+ onClick: () => onSortRulesChange([]),
2419
+ children: "Remove all"
2420
+ }
2421
+ )
2422
+ ] })
2423
+ ] }),
2424
+ sheetPanel === "group" && /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-2", children: [
2425
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-3", children: groupBy ? `Grouped by ${resolveColumnLabel(groupBy)}.` : "No grouping applied." }),
2426
+ /* @__PURE__ */ jsxs(
2427
+ Button,
2428
+ {
2429
+ type: "button",
2430
+ variant: "ghost",
2431
+ onClick: () => onGroupByChange(null),
2432
+ className: cn(
2433
+ "w-full justify-start gap-2 px-3 py-2 h-auto text-sm font-normal",
2434
+ !groupBy ? "bg-accent text-accent-foreground font-medium" : "text-muted-foreground"
2435
+ ),
2436
+ children: [
2437
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-ban text-xs", "aria-hidden": "true" }),
2438
+ "None"
2439
+ ]
2440
+ }
2441
+ ),
2442
+ groupFieldList.map((col) => /* @__PURE__ */ jsxs(
2443
+ Button,
2444
+ {
2445
+ type: "button",
2446
+ variant: "ghost",
2447
+ onClick: () => onGroupByChange(groupBy === col.key ? null : col.key),
2448
+ className: cn(
2449
+ "w-full justify-start gap-2 px-3 py-2 h-auto text-sm font-normal",
2450
+ groupBy === col.key ? "bg-accent text-accent-foreground font-medium" : ""
2451
+ ),
2452
+ children: [
2453
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-layer-group text-xs text-muted-foreground", "aria-hidden": "true" }),
2454
+ col.label,
2455
+ groupBy === col.key && /* @__PURE__ */ jsx("i", { className: "fa-solid fa-check text-accent-foreground text-xs ms-auto", "aria-hidden": "true" })
2456
+ ]
2457
+ },
2458
+ col.key
2459
+ ))
2460
+ ] }),
2461
+ sheetPanel === "columns" && /* @__PURE__ */ jsxs("div", { className: "px-4 py-4", children: [
2462
+ isBoardView ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-3", children: "Column visibility and order apply when you use Table view. They are saved with this tab." }) : null,
2463
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-3", children: hiddenCols.size === 0 ? "All columns visible. Drag to reorder." : `${hiddenCols.size} column${hiddenCols.size !== 1 ? "s" : ""} hidden. Drag handle to reorder.` }),
2464
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", role: "list", "aria-label": "Column order and visibility", children: orderable.map((key, idx, arr) => {
2465
+ const dragProps = colDrag.getItemProps(key);
2466
+ return /* @__PURE__ */ jsx(
2467
+ ColumnRow,
2468
+ {
2469
+ label: resolveColumnLabel(key),
2470
+ isFirst: idx === 0,
2471
+ isLast: idx === arr.length - 1,
2472
+ visible: !hiddenCols.has(key),
2473
+ onToggleVisible: () => onToggleColVisibility(key),
2474
+ onMoveUp: () => onMoveCol(key, "up"),
2475
+ onMoveDown: () => onMoveCol(key, "down"),
2476
+ draggable: dragProps.draggable,
2477
+ onDragStart: dragProps.onDragStart,
2478
+ onDragOver: dragProps.onDragOver,
2479
+ onDrop: dragProps.onDrop,
2480
+ onDragEnd: dragProps.onDragEnd,
2481
+ isDragging: dragProps["data-dragging"],
2482
+ isOver: dragProps["data-over"]
2483
+ },
2484
+ key
2485
+ );
2486
+ }) })
2487
+ ] }),
2488
+ sheetPanel === "conditional-rules" && /* @__PURE__ */ jsx(
2489
+ ConditionalRulesPanel,
2490
+ {
2491
+ filterFields,
2492
+ rules: conditionalRules,
2493
+ onAdd: onAddConditionalRule,
2494
+ onRemove: onRemoveConditionalRule,
2495
+ onUpdate: onUpdateConditionalRule,
2496
+ renderFilterOptionValue
2497
+ }
2498
+ )
2499
+ ] })
2500
+ ] })
2501
+ }
2502
+ ) });
2503
+ }
2504
+ function ConditionalRulesPanel({
2505
+ filterFields,
2506
+ rules,
2507
+ onAdd,
2508
+ onRemove,
2509
+ onUpdate,
2510
+ renderFilterOptionValue
2511
+ }) {
2512
+ const [expandedIds, setExpandedIds] = React11.useState(() => /* @__PURE__ */ new Set());
2513
+ const prevLenRef = React11.useRef(rules.length);
2514
+ React11.useEffect(() => {
2515
+ if (rules.length > prevLenRef.current && rules.length > 0) {
2516
+ const last = rules[rules.length - 1];
2517
+ setExpandedIds(/* @__PURE__ */ new Set([last.id]));
2518
+ }
2519
+ prevLenRef.current = rules.length;
2520
+ }, [rules]);
2521
+ function toggleExpanded(id) {
2522
+ setExpandedIds((prev) => {
2523
+ const next = new Set(prev);
2524
+ if (next.has(id)) next.delete(id);
2525
+ else next.add(id);
2526
+ return next;
2527
+ });
2528
+ }
2529
+ return /* @__PURE__ */ jsxs("div", { className: "px-4 py-4 space-y-2", children: [
2530
+ rules.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-dashed border-border bg-muted/30 px-4 py-6 text-center space-y-2", children: [
2531
+ /* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center size-9 rounded-lg bg-muted mb-1", children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-palette text-muted-foreground text-[16px]", "aria-hidden": "true" }) }),
2532
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "No rules yet" }),
2533
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: "Highlight cells with a background color based on their value." })
2534
+ ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: rules.map((rule) => {
2535
+ const fd = filterFields.find((f) => f.key === rule.fieldKey);
2536
+ if (!fd) return null;
2537
+ return /* @__PURE__ */ jsx(
2538
+ DrawerFilterCard,
2539
+ {
2540
+ variant: "conditional",
2541
+ filter: rule,
2542
+ fieldDef: fd,
2543
+ expanded: expandedIds.has(rule.id),
2544
+ onToggleExpand: () => toggleExpanded(rule.id),
2545
+ onUpdate,
2546
+ onRemove: (id) => {
2547
+ onRemove(id);
2548
+ setExpandedIds((prev) => {
2549
+ const next = new Set(prev);
2550
+ next.delete(id);
2551
+ return next;
2552
+ });
2553
+ },
2554
+ renderOptionLabel: (value) => renderFilterOptionValue?.(rule.fieldKey, value)
2555
+ },
2556
+ rule.id
2557
+ );
2558
+ }) }),
2559
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
2560
+ /* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
2561
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2562
+ Button,
2563
+ {
2564
+ type: "button",
2565
+ variant: "outline",
2566
+ className: "flex-1 gap-1.5 h-8 border-dashed text-muted-foreground",
2567
+ children: [
2568
+ /* @__PURE__ */ jsx("i", { className: "fa-light fa-plus text-xs", "aria-hidden": "true" }),
2569
+ "Add rule"
2570
+ ]
2571
+ }
2572
+ ) }),
2573
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", className: PROPERTIES_SHEET_PORTAL_Z, children: [
2574
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs", children: "Rule for column" }),
2575
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2576
+ filterFields.map((f) => /* @__PURE__ */ jsxs(
2577
+ DropdownMenuItem,
2578
+ {
2579
+ onSelect: () => onAdd({
2580
+ fieldKey: f.key,
2581
+ operator: f.operators[0],
2582
+ values: [],
2583
+ bgColor: RULE_COLORS[0].bg
2584
+ }),
2585
+ children: [
2586
+ /* @__PURE__ */ jsx("i", { className: `fa-light ${f.icon}`, "aria-hidden": "true" }),
2587
+ f.label
2588
+ ]
2589
+ },
2590
+ f.key
2591
+ ))
2592
+ ] })
2593
+ ] }),
2594
+ rules.length > 0 && /* @__PURE__ */ jsx(
2595
+ Button,
2596
+ {
2597
+ type: "button",
2598
+ variant: "ghost",
2599
+ size: "sm",
2600
+ className: "shrink-0 text-destructive hover:text-destructive hover:bg-destructive/10",
2601
+ onClick: () => {
2602
+ rules.forEach((r) => onRemove(r.id));
2603
+ setExpandedIds(/* @__PURE__ */ new Set());
2604
+ },
2605
+ children: "Remove all"
2606
+ }
2607
+ )
2608
+ ] })
2609
+ ] });
2610
+ }
2611
+ function TablePropertiesDrawerButton({
2612
+ state,
2613
+ totalRows,
2614
+ filterFields,
2615
+ fieldDefinitions,
2616
+ resolveColumnLabel,
2617
+ displayOptions,
2618
+ onDisplayOptionsChange,
2619
+ conditionalRules,
2620
+ onAddConditionalRule,
2621
+ onRemoveConditionalRule,
2622
+ onUpdateConditionalRule,
2623
+ pagination = false,
2624
+ onPaginationChange,
2625
+ currentView,
2626
+ onViewChange,
2627
+ supportedViewTypes,
2628
+ lifecycleTabLabel,
2629
+ boardGroupByColumnOptions,
2630
+ extraActions,
2631
+ renderFilterOptionValue
2632
+ }) {
2633
+ const {
2634
+ sheetOpen,
2635
+ setSheetOpen,
2636
+ sheetInitialPanel,
2637
+ setSheetInitialPanel,
2638
+ showGridlines,
2639
+ setShowGridlines,
2640
+ rowHeight,
2641
+ setRowHeight,
2642
+ activeFilters,
2643
+ filterBarVisible,
2644
+ drawerExpandedFilters,
2645
+ rows,
2646
+ sortRules,
2647
+ colOrder,
2648
+ hiddenCols,
2649
+ groupBy,
2650
+ sortKey
2651
+ } = state;
2652
+ const stateRef = React11.useRef(state);
2653
+ const ruleHandlersRef = React11.useRef({
2654
+ onAddConditionalRule,
2655
+ onRemoveConditionalRule,
2656
+ onUpdateConditionalRule,
2657
+ onDisplayOptionsChange,
2658
+ onPaginationChange
2659
+ });
2660
+ React11.useLayoutEffect(() => {
2661
+ stateRef.current = state;
2662
+ });
2663
+ React11.useLayoutEffect(() => {
2664
+ ruleHandlersRef.current = {
2665
+ onAddConditionalRule,
2666
+ onRemoveConditionalRule,
2667
+ onUpdateConditionalRule,
2668
+ onDisplayOptionsChange,
2669
+ onPaginationChange
2670
+ };
2671
+ });
2672
+ const onDrawerExpandedFiltersChange = React11.useCallback((next) => stateRef.current.setDrawerExpandedFilters(next), []);
2673
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2674
+ extraActions,
2675
+ /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
2676
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
2677
+ Button,
2678
+ {
2679
+ type: "button",
2680
+ variant: "ghost",
2681
+ size: "icon-sm",
2682
+ "aria-label": "Properties",
2683
+ onClick: () => {
2684
+ setSheetInitialPanel?.(null);
2685
+ setSheetOpen(true);
2686
+ },
2687
+ className: cn(
2688
+ sheetOpen ? "bg-accent text-accent-foreground" : "text-muted-foreground hover:text-interactive-hover-foreground hover:bg-interactive-hover"
2689
+ ),
2690
+ children: /* @__PURE__ */ jsx("i", { className: "fa-light fa-sliders text-[13px]", "aria-hidden": "true" })
2691
+ }
2692
+ ) }),
2693
+ /* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: "Properties" })
2694
+ ] }) }),
2695
+ /* @__PURE__ */ jsx(
2696
+ TablePropertiesDrawer,
2697
+ {
2698
+ open: sheetOpen,
2699
+ onOpenChange: setSheetOpen,
2700
+ initialPanel: sheetInitialPanel,
2701
+ showGridlines,
2702
+ onShowGridlinesChange: setShowGridlines,
2703
+ rowHeight,
2704
+ onRowHeightChange: setRowHeight,
2705
+ pagination,
2706
+ onPaginationChange: (v) => ruleHandlersRef.current.onPaginationChange?.(v),
2707
+ activeFilters,
2708
+ onAddFilter: (fieldKey) => stateRef.current.addFilter(fieldKey, true),
2709
+ onUpdateFilter: (id, patch) => stateRef.current.updateFilter(id, patch),
2710
+ onRemoveFilter: (id) => stateRef.current.removeFilter(id),
2711
+ getFilterConnector: (leftId) => stateRef.current.getConnector(leftId),
2712
+ onToggleFilterConnector: (leftId) => stateRef.current.toggleConnector(leftId),
2713
+ filterBarVisible,
2714
+ onFilterBarVisibleChange: (v) => stateRef.current.setFilterBarVisible(v),
2715
+ drawerExpandedFilters,
2716
+ onDrawerExpandedFiltersChange,
2717
+ totalRows,
2718
+ filteredRows: rows.length,
2719
+ sortRules,
2720
+ onSortRulesChange: (rules) => stateRef.current.setSortRules(rules),
2721
+ onAddSortRule: (fieldKey) => stateRef.current.addSortRule(fieldKey),
2722
+ onRemoveSortRule: (id) => stateRef.current.removeSortRule(id),
2723
+ onToggleSortDir: (id) => stateRef.current.toggleSortDir(id),
2724
+ colOrder,
2725
+ onColOrderChange: (order) => stateRef.current.setColOrder(order),
2726
+ hiddenCols,
2727
+ onToggleColVisibility: (key) => stateRef.current.toggleColVisibility(key),
2728
+ onMoveCol: (key, dir) => stateRef.current.moveCol(key, dir),
2729
+ groupBy,
2730
+ onGroupByChange: (key) => stateRef.current.setGroupBy(key),
2731
+ primarySortKey: sortKey,
2732
+ conditionalRules,
2733
+ onAddConditionalRule: (rule) => ruleHandlersRef.current.onAddConditionalRule(rule),
2734
+ onRemoveConditionalRule: (id) => ruleHandlersRef.current.onRemoveConditionalRule(id),
2735
+ onUpdateConditionalRule: (id, patch) => ruleHandlersRef.current.onUpdateConditionalRule(id, patch),
2736
+ filterFields,
2737
+ lifecycleTabLabel,
2738
+ fieldDefinitions,
2739
+ resolveColumnLabel,
2740
+ displayOptions,
2741
+ onDisplayOptionsChange: (patch) => ruleHandlersRef.current.onDisplayOptionsChange(patch),
2742
+ currentView,
2743
+ onViewChange,
2744
+ supportedViewTypes,
2745
+ boardGroupByColumnOptions,
2746
+ renderFilterOptionValue
2747
+ }
2748
+ )
2749
+ ] });
2750
+ }
2751
+
2752
+ // src/lib/list-page-table-properties.ts
2753
+ function createListPageEditViewHandler(tableRef, options) {
2754
+ const delay = options?.switchDelayMs ?? 160;
2755
+ return (tab, { updateTab }) => {
2756
+ const mustSwitchToTableSurface = !isDataListSurfaceViewType(tab.viewType);
2757
+ if (mustSwitchToTableSurface) {
2758
+ updateTab({ viewType: "table", icon: dataListViewIcon("table") });
2759
+ }
2760
+ window.setTimeout(() => {
2761
+ tableRef.current?.openPropertiesDrawer();
2762
+ }, mustSwitchToTableSurface ? delay : 0);
2763
+ };
2764
+ }
2765
+
2766
+ export { ColumnRow, DrawerFilterCard, DrawerSortCard, TablePropertiesDrawer, TablePropertiesDrawerButton, createListPageEditViewHandler, isDataListSurfaceViewType, useDraggableList };
2767
+ //# sourceMappingURL=index.js.map
2768
+ //# sourceMappingURL=index.js.map