@flanksource/clicky-ui 0.1.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +29 -2
  2. package/dist/api-explorer.d.ts +5 -0
  3. package/dist/api-explorer.d.ts.map +1 -0
  4. package/dist/api-explorer.js +25 -0
  5. package/dist/api-explorer.js.map +1 -0
  6. package/dist/clicky.d.ts +2 -0
  7. package/dist/clicky.d.ts.map +1 -0
  8. package/dist/clicky.js +5 -0
  9. package/dist/clicky.js.map +1 -0
  10. package/dist/components/DatePicker.d.ts +18 -0
  11. package/dist/components/DatePicker.d.ts.map +1 -0
  12. package/dist/components/DatePicker.js +63 -0
  13. package/dist/components/DatePicker.js.map +1 -0
  14. package/dist/components/DateTimePicker.d.ts +18 -0
  15. package/dist/components/DateTimePicker.d.ts.map +1 -0
  16. package/dist/components/DateTimePicker.js +84 -0
  17. package/dist/components/DateTimePicker.js.map +1 -0
  18. package/dist/components/FilterBar.d.ts +180 -0
  19. package/dist/components/FilterBar.d.ts.map +1 -0
  20. package/dist/components/FilterBar.js +1685 -0
  21. package/dist/components/FilterBar.js.map +1 -0
  22. package/dist/components/MultiSelect.d.ts +19 -0
  23. package/dist/components/MultiSelect.d.ts.map +1 -0
  24. package/dist/components/MultiSelect.js +143 -0
  25. package/dist/components/MultiSelect.js.map +1 -0
  26. package/dist/components/RangeSlider.d.ts +16 -0
  27. package/dist/components/RangeSlider.d.ts.map +1 -0
  28. package/dist/components/RangeSlider.js +92 -0
  29. package/dist/components/RangeSlider.js.map +1 -0
  30. package/dist/components/button.d.ts +21 -0
  31. package/dist/components/button.d.ts.map +1 -0
  32. package/dist/components/button.js +126 -0
  33. package/dist/components/button.js.map +1 -0
  34. package/dist/components/density-switcher.d.ts +7 -0
  35. package/dist/components/density-switcher.d.ts.map +1 -0
  36. package/dist/components/density-switcher.js +32 -0
  37. package/dist/components/density-switcher.js.map +1 -0
  38. package/dist/components/icon-menu-picker.d.ts +23 -0
  39. package/dist/components/icon-menu-picker.d.ts.map +1 -0
  40. package/dist/components/icon-menu-picker.js +192 -0
  41. package/dist/components/icon-menu-picker.js.map +1 -0
  42. package/dist/components/select.d.ts +15 -0
  43. package/dist/components/select.d.ts.map +1 -0
  44. package/dist/components/select.js +39 -0
  45. package/dist/components/select.js.map +1 -0
  46. package/dist/components/theme-switcher.d.ts +7 -0
  47. package/dist/components/theme-switcher.d.ts.map +1 -0
  48. package/dist/components/theme-switcher.js +42 -0
  49. package/dist/components/theme-switcher.js.map +1 -0
  50. package/dist/components.d.ts +15 -0
  51. package/dist/components.d.ts.map +1 -0
  52. package/dist/components.js +33 -0
  53. package/dist/components.js.map +1 -0
  54. package/dist/data/AnsiHtml.d.ts +7 -0
  55. package/dist/data/AnsiHtml.d.ts.map +1 -0
  56. package/dist/data/AnsiHtml.js +71 -0
  57. package/dist/data/AnsiHtml.js.map +1 -0
  58. package/dist/data/Avatar.d.ts +32 -0
  59. package/dist/data/Avatar.d.ts.map +1 -0
  60. package/dist/data/Avatar.js +201 -0
  61. package/dist/data/Avatar.js.map +1 -0
  62. package/dist/data/AvatarBadge.d.ts +26 -0
  63. package/dist/data/AvatarBadge.d.ts.map +1 -0
  64. package/dist/data/AvatarBadge.js +104 -0
  65. package/dist/data/AvatarBadge.js.map +1 -0
  66. package/dist/data/Badge.d.ts +44 -0
  67. package/dist/data/Badge.d.ts.map +1 -0
  68. package/dist/data/Badge.js +667 -0
  69. package/dist/data/Badge.js.map +1 -0
  70. package/dist/data/Clicky.d.ts +147 -0
  71. package/dist/data/Clicky.d.ts.map +1 -0
  72. package/dist/data/Clicky.fixtures.d.ts +3 -0
  73. package/dist/data/Clicky.fixtures.d.ts.map +1 -0
  74. package/dist/data/Clicky.js +1960 -0
  75. package/dist/data/Clicky.js.map +1 -0
  76. package/dist/data/DataTable.d.ts +95 -0
  77. package/dist/data/DataTable.d.ts.map +1 -0
  78. package/dist/data/DataTable.js +1464 -0
  79. package/dist/data/DataTable.js.map +1 -0
  80. package/dist/data/FilterPill.d.ts +29 -0
  81. package/dist/data/FilterPill.d.ts.map +1 -0
  82. package/dist/data/FilterPill.js +153 -0
  83. package/dist/data/FilterPill.js.map +1 -0
  84. package/dist/data/Gauge.d.ts +15 -0
  85. package/dist/data/Gauge.d.ts.map +1 -0
  86. package/dist/data/Gauge.js +63 -0
  87. package/dist/data/Gauge.js.map +1 -0
  88. package/dist/data/Icon.d.ts +53 -0
  89. package/dist/data/Icon.d.ts.map +1 -0
  90. package/dist/data/Icon.js +115 -0
  91. package/dist/data/Icon.js.map +1 -0
  92. package/dist/data/JsonView.d.ts +8 -0
  93. package/dist/data/JsonView.d.ts.map +1 -0
  94. package/dist/data/JsonView.js +74 -0
  95. package/dist/data/JsonView.js.map +1 -0
  96. package/dist/data/KeyValueList.d.ts +17 -0
  97. package/dist/data/KeyValueList.d.ts.map +1 -0
  98. package/dist/data/KeyValueList.js +33 -0
  99. package/dist/data/KeyValueList.js.map +1 -0
  100. package/dist/data/LogViewer.d.ts +10 -0
  101. package/dist/data/LogViewer.d.ts.map +1 -0
  102. package/dist/data/LogViewer.js +46 -0
  103. package/dist/data/LogViewer.js.map +1 -0
  104. package/dist/data/LogsTable.d.ts +27 -0
  105. package/dist/data/LogsTable.d.ts.map +1 -0
  106. package/dist/data/LogsTable.js +580 -0
  107. package/dist/data/LogsTable.js.map +1 -0
  108. package/dist/data/Markdown.d.ts +6 -0
  109. package/dist/data/Markdown.d.ts.map +1 -0
  110. package/dist/data/Markdown.js +59 -0
  111. package/dist/data/Markdown.js.map +1 -0
  112. package/dist/data/MatrixTable.d.ts +22 -0
  113. package/dist/data/MatrixTable.d.ts.map +1 -0
  114. package/dist/data/MatrixTable.js +164 -0
  115. package/dist/data/MatrixTable.js.map +1 -0
  116. package/dist/data/MethodBadge.d.ts +6 -0
  117. package/dist/data/MethodBadge.d.ts.map +1 -0
  118. package/dist/data/MethodBadge.js +18 -0
  119. package/dist/data/MethodBadge.js.map +1 -0
  120. package/dist/data/ProgressBar.d.ts +13 -0
  121. package/dist/data/ProgressBar.d.ts.map +1 -0
  122. package/dist/data/ProgressBar.js +34 -0
  123. package/dist/data/ProgressBar.js.map +1 -0
  124. package/dist/data/SortableHeader.d.ts +12 -0
  125. package/dist/data/SortableHeader.d.ts.map +1 -0
  126. package/dist/data/SortableHeader.js +33 -0
  127. package/dist/data/SortableHeader.js.map +1 -0
  128. package/dist/data/TabButton.d.ts +12 -0
  129. package/dist/data/TabButton.d.ts.map +1 -0
  130. package/dist/data/TabButton.js +45 -0
  131. package/dist/data/TabButton.js.map +1 -0
  132. package/dist/data/Tree.d.ts +35 -0
  133. package/dist/data/Tree.d.ts.map +1 -0
  134. package/dist/data/Tree.js +236 -0
  135. package/dist/data/Tree.js.map +1 -0
  136. package/dist/data/TreeGroupHeader.d.ts +11 -0
  137. package/dist/data/TreeGroupHeader.d.ts.map +1 -0
  138. package/dist/data/TreeGroupHeader.js +41 -0
  139. package/dist/data/TreeGroupHeader.js.map +1 -0
  140. package/dist/data/TreeNode.d.ts +43 -0
  141. package/dist/data/TreeNode.d.ts.map +1 -0
  142. package/dist/data/TreeNode.js +100 -0
  143. package/dist/data/TreeNode.js.map +1 -0
  144. package/dist/data/cells/StatusDot.d.ts +11 -0
  145. package/dist/data/cells/StatusDot.d.ts.map +1 -0
  146. package/dist/data/cells/StatusDot.js +38 -0
  147. package/dist/data/cells/StatusDot.js.map +1 -0
  148. package/dist/data/cells/TagList.d.ts +59 -0
  149. package/dist/data/cells/TagList.d.ts.map +1 -0
  150. package/dist/data/cells/TagList.js +257 -0
  151. package/dist/data/cells/TagList.js.map +1 -0
  152. package/dist/data/cells/Timestamp.d.ts +46 -0
  153. package/dist/data/cells/Timestamp.d.ts.map +1 -0
  154. package/dist/data/cells/Timestamp.js +146 -0
  155. package/dist/data/cells/Timestamp.js.map +1 -0
  156. package/dist/data/cells/status-mapping.d.ts +8 -0
  157. package/dist/data/cells/status-mapping.d.ts.map +1 -0
  158. package/dist/data/cells/status-mapping.js +44 -0
  159. package/dist/data/cells/status-mapping.js.map +1 -0
  160. package/dist/data/code-highlight.d.ts +12 -0
  161. package/dist/data/code-highlight.d.ts.map +1 -0
  162. package/dist/data/code-highlight.js +28 -0
  163. package/dist/data/code-highlight.js.map +1 -0
  164. package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts +9 -0
  165. package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts.map +1 -0
  166. package/dist/data/diagnostics/DiagnosticsDetailPanel.js +445 -0
  167. package/dist/data/diagnostics/DiagnosticsDetailPanel.js.map +1 -0
  168. package/dist/data/diagnostics/DiagnosticsTree.d.ts +9 -0
  169. package/dist/data/diagnostics/DiagnosticsTree.d.ts.map +1 -0
  170. package/dist/data/diagnostics/DiagnosticsTree.js +78 -0
  171. package/dist/data/diagnostics/DiagnosticsTree.js.map +1 -0
  172. package/dist/data/diagnostics/ErrorDetails.d.ts +20 -0
  173. package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -0
  174. package/dist/data/diagnostics/ErrorDetails.js +157 -0
  175. package/dist/data/diagnostics/ErrorDetails.js.map +1 -0
  176. package/dist/data/diagnostics/GoroutineCard.d.ts +10 -0
  177. package/dist/data/diagnostics/GoroutineCard.d.ts.map +1 -0
  178. package/dist/data/diagnostics/GoroutineCard.js +75 -0
  179. package/dist/data/diagnostics/GoroutineCard.js.map +1 -0
  180. package/dist/data/diagnostics/JvmStackTrace.d.ts +11 -0
  181. package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -0
  182. package/dist/data/diagnostics/JvmStackTrace.js +26 -0
  183. package/dist/data/diagnostics/JvmStackTrace.js.map +1 -0
  184. package/dist/data/diagnostics/RenderedStackTrace.d.ts +18 -0
  185. package/dist/data/diagnostics/RenderedStackTrace.d.ts.map +1 -0
  186. package/dist/data/diagnostics/RenderedStackTrace.js +235 -0
  187. package/dist/data/diagnostics/RenderedStackTrace.js.map +1 -0
  188. package/dist/data/diagnostics/ThreadCard.d.ts +10 -0
  189. package/dist/data/diagnostics/ThreadCard.d.ts.map +1 -0
  190. package/dist/data/diagnostics/ThreadCard.js +78 -0
  191. package/dist/data/diagnostics/ThreadCard.js.map +1 -0
  192. package/dist/data/diagnostics/error-diagnostics.d.ts +26 -0
  193. package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -0
  194. package/dist/data/diagnostics/error-diagnostics.js +108 -0
  195. package/dist/data/diagnostics/error-diagnostics.js.map +1 -0
  196. package/dist/data/diagnostics/fixtures.d.ts +3 -0
  197. package/dist/data/diagnostics/fixtures.d.ts.map +1 -0
  198. package/dist/data/diagnostics/jvm-stacktrace.d.ts +34 -0
  199. package/dist/data/diagnostics/jvm-stacktrace.d.ts.map +1 -0
  200. package/dist/data/diagnostics/jvm-stacktrace.js +190 -0
  201. package/dist/data/diagnostics/jvm-stacktrace.js.map +1 -0
  202. package/dist/data/diagnostics/stacktrace-parse.d.ts +11 -0
  203. package/dist/data/diagnostics/stacktrace-parse.d.ts.map +1 -0
  204. package/dist/data/diagnostics/stacktrace-parse.js +87 -0
  205. package/dist/data/diagnostics/stacktrace-parse.js.map +1 -0
  206. package/dist/data/diagnostics/stacktrace.d.ts +38 -0
  207. package/dist/data/diagnostics/stacktrace.d.ts.map +1 -0
  208. package/dist/data/diagnostics/stacktrace.js +119 -0
  209. package/dist/data/diagnostics/stacktrace.js.map +1 -0
  210. package/dist/data/diagnostics/types.d.ts +30 -0
  211. package/dist/data/diagnostics/types.d.ts.map +1 -0
  212. package/dist/data/diagnostics/utils.d.ts +8 -0
  213. package/dist/data/diagnostics/utils.d.ts.map +1 -0
  214. package/dist/data/diagnostics/utils.js +59 -0
  215. package/dist/data/diagnostics/utils.js.map +1 -0
  216. package/dist/data/har/HarPanel.d.ts +9 -0
  217. package/dist/data/har/HarPanel.d.ts.map +1 -0
  218. package/dist/data/har/HarPanel.js +175 -0
  219. package/dist/data/har/HarPanel.js.map +1 -0
  220. package/dist/data/har/fixtures.d.ts +3 -0
  221. package/dist/data/har/fixtures.d.ts.map +1 -0
  222. package/dist/data/har/types.d.ts +47 -0
  223. package/dist/data/har/types.d.ts.map +1 -0
  224. package/dist/data.d.ts +39 -0
  225. package/dist/data.d.ts.map +1 -0
  226. package/dist/data.js +109 -0
  227. package/dist/data.js.map +1 -0
  228. package/dist/hooks/use-density.d.ts +22 -0
  229. package/dist/hooks/use-density.d.ts.map +1 -0
  230. package/dist/hooks/use-density.js +54 -0
  231. package/dist/hooks/use-density.js.map +1 -0
  232. package/dist/hooks/use-history-route.d.ts +6 -0
  233. package/dist/hooks/use-history-route.d.ts.map +1 -0
  234. package/dist/hooks/use-history-route.js +31 -0
  235. package/dist/hooks/use-history-route.js.map +1 -0
  236. package/dist/hooks/use-sort.d.ts +17 -0
  237. package/dist/hooks/use-sort.d.ts.map +1 -0
  238. package/dist/hooks/use-sort.js +42 -0
  239. package/dist/hooks/use-sort.js.map +1 -0
  240. package/dist/hooks/use-theme.d.ts +17 -0
  241. package/dist/hooks/use-theme.d.ts.map +1 -0
  242. package/dist/hooks/use-theme.js +68 -0
  243. package/dist/hooks/use-theme.js.map +1 -0
  244. package/dist/hooks.d.ts +5 -0
  245. package/dist/hooks.d.ts.map +1 -0
  246. package/dist/hooks.js +14 -0
  247. package/dist/hooks.js.map +1 -0
  248. package/dist/index.d.ts +7 -0
  249. package/dist/index.d.ts.map +1 -0
  250. package/dist/index.js +195 -0
  251. package/dist/index.js.map +1 -0
  252. package/dist/layout/Section.d.ts +23 -0
  253. package/dist/layout/Section.d.ts.map +1 -0
  254. package/dist/layout/Section.js +73 -0
  255. package/dist/layout/Section.js.map +1 -0
  256. package/dist/layout/SplitPane.d.ts +13 -0
  257. package/dist/layout/SplitPane.d.ts.map +1 -0
  258. package/dist/layout/SplitPane.js +72 -0
  259. package/dist/layout/SplitPane.js.map +1 -0
  260. package/dist/lib/palette.d.ts +4 -0
  261. package/dist/lib/palette.d.ts.map +1 -0
  262. package/dist/lib/palette.js +35 -0
  263. package/dist/lib/palette.js.map +1 -0
  264. package/dist/lib/size.d.ts +6 -0
  265. package/dist/lib/size.d.ts.map +1 -0
  266. package/dist/lib/size.js +14 -0
  267. package/dist/lib/size.js.map +1 -0
  268. package/dist/lib/utils.d.ts +3 -0
  269. package/dist/lib/utils.d.ts.map +1 -0
  270. package/dist/lib/utils.js +9 -0
  271. package/dist/lib/utils.js.map +1 -0
  272. package/dist/overlay/HoverCard.d.ts +13 -0
  273. package/dist/overlay/HoverCard.d.ts.map +1 -0
  274. package/dist/overlay/HoverCard.js +170 -0
  275. package/dist/overlay/HoverCard.js.map +1 -0
  276. package/dist/overlay/Modal.d.ts +17 -0
  277. package/dist/overlay/Modal.d.ts.map +1 -0
  278. package/dist/overlay/Modal.js +91 -0
  279. package/dist/overlay/Modal.js.map +1 -0
  280. package/dist/rpc/AcceptPicker.d.ts +52 -0
  281. package/dist/rpc/AcceptPicker.d.ts.map +1 -0
  282. package/dist/rpc/AcceptPicker.js +126 -0
  283. package/dist/rpc/AcceptPicker.js.map +1 -0
  284. package/dist/rpc/ApiExplorer.d.ts +11 -0
  285. package/dist/rpc/ApiExplorer.d.ts.map +1 -0
  286. package/dist/rpc/ApiExplorer.js +37 -0
  287. package/dist/rpc/ApiExplorer.js.map +1 -0
  288. package/dist/rpc/CommandForm.d.ts +15 -0
  289. package/dist/rpc/CommandForm.d.ts.map +1 -0
  290. package/dist/rpc/CommandForm.js +356 -0
  291. package/dist/rpc/CommandForm.js.map +1 -0
  292. package/dist/rpc/CommandOutput.d.ts +11 -0
  293. package/dist/rpc/CommandOutput.d.ts.map +1 -0
  294. package/dist/rpc/CommandOutput.js +195 -0
  295. package/dist/rpc/CommandOutput.js.map +1 -0
  296. package/dist/rpc/EndpointList.d.ts +18 -0
  297. package/dist/rpc/EndpointList.d.ts.map +1 -0
  298. package/dist/rpc/EndpointList.js +56 -0
  299. package/dist/rpc/EndpointList.js.map +1 -0
  300. package/dist/rpc/EntityExplorerApp.d.ts +15 -0
  301. package/dist/rpc/EntityExplorerApp.d.ts.map +1 -0
  302. package/dist/rpc/EntityExplorerApp.js +282 -0
  303. package/dist/rpc/EntityExplorerApp.js.map +1 -0
  304. package/dist/rpc/ExecutionResult.d.ts +14 -0
  305. package/dist/rpc/ExecutionResult.d.ts.map +1 -0
  306. package/dist/rpc/ExecutionResult.js +51 -0
  307. package/dist/rpc/ExecutionResult.js.map +1 -0
  308. package/dist/rpc/FilterForm.d.ts +22 -0
  309. package/dist/rpc/FilterForm.d.ts.map +1 -0
  310. package/dist/rpc/FilterForm.js +392 -0
  311. package/dist/rpc/FilterForm.js.map +1 -0
  312. package/dist/rpc/InlineError.d.ts +7 -0
  313. package/dist/rpc/InlineError.d.ts.map +1 -0
  314. package/dist/rpc/InlineError.js +54 -0
  315. package/dist/rpc/InlineError.js.map +1 -0
  316. package/dist/rpc/OperationActionDialog.d.ts +12 -0
  317. package/dist/rpc/OperationActionDialog.d.ts.map +1 -0
  318. package/dist/rpc/OperationActionDialog.js +105 -0
  319. package/dist/rpc/OperationActionDialog.js.map +1 -0
  320. package/dist/rpc/OperationCatalog.d.ts +21 -0
  321. package/dist/rpc/OperationCatalog.d.ts.map +1 -0
  322. package/dist/rpc/OperationCatalog.js +339 -0
  323. package/dist/rpc/OperationCatalog.js.map +1 -0
  324. package/dist/rpc/OperationCommandPage.d.ts +22 -0
  325. package/dist/rpc/OperationCommandPage.d.ts.map +1 -0
  326. package/dist/rpc/OperationCommandPage.js +484 -0
  327. package/dist/rpc/OperationCommandPage.js.map +1 -0
  328. package/dist/rpc/OperationEntityPage.d.ts +23 -0
  329. package/dist/rpc/OperationEntityPage.d.ts.map +1 -0
  330. package/dist/rpc/OperationEntityPage.js +218 -0
  331. package/dist/rpc/OperationEntityPage.js.map +1 -0
  332. package/dist/rpc/classify.d.ts +8 -0
  333. package/dist/rpc/classify.d.ts.map +1 -0
  334. package/dist/rpc/classify.js +76 -0
  335. package/dist/rpc/classify.js.map +1 -0
  336. package/dist/rpc/clickyMetadata.d.ts +12 -0
  337. package/dist/rpc/clickyMetadata.d.ts.map +1 -0
  338. package/dist/rpc/clickyMetadata.js +71 -0
  339. package/dist/rpc/clickyMetadata.js.map +1 -0
  340. package/dist/rpc/formMetadata.d.ts +27 -0
  341. package/dist/rpc/formMetadata.d.ts.map +1 -0
  342. package/dist/rpc/formMetadata.js +250 -0
  343. package/dist/rpc/formMetadata.js.map +1 -0
  344. package/dist/rpc/types.d.ts +109 -0
  345. package/dist/rpc/types.d.ts.map +1 -0
  346. package/dist/rpc/types.js +8 -0
  347. package/dist/rpc/types.js.map +1 -0
  348. package/dist/rpc/useOperations.d.ts +346 -0
  349. package/dist/rpc/useOperations.d.ts.map +1 -0
  350. package/dist/rpc/useOperations.js +31 -0
  351. package/dist/rpc/useOperations.js.map +1 -0
  352. package/dist/rpc.d.ts +14 -0
  353. package/dist/rpc.d.ts.map +1 -0
  354. package/dist/rpc.js +37 -0
  355. package/dist/rpc.js.map +1 -0
  356. package/dist/styles.css +2 -0
  357. package/dist/styles.d.ts +1 -0
  358. package/dist/styles.d.ts.map +1 -0
  359. package/dist/styles.js +2 -0
  360. package/dist/styles.js.map +1 -0
  361. package/dist/tailwind-preset.d.ts +4 -0
  362. package/dist/tailwind-preset.d.ts.map +1 -0
  363. package/dist/tailwind-preset.js +69 -0
  364. package/dist/tailwind-preset.js.map +1 -0
  365. package/dist/utils.d.ts +4 -0
  366. package/dist/utils.d.ts.map +1 -0
  367. package/dist/utils.js +12 -0
  368. package/dist/utils.js.map +1 -0
  369. package/package.json +83 -40
  370. package/dist/index.d.mts +0 -834
  371. package/dist/index.d.mts.map +0 -1
  372. package/dist/index.mjs +0 -2918
  373. package/dist/index.mjs.map +0 -1
  374. package/dist/tailwind-preset.d.mts +0 -7
  375. package/dist/tailwind-preset.d.mts.map +0 -1
  376. package/dist/tailwind-preset.mjs +0 -64
  377. package/dist/tailwind-preset.mjs.map +0 -1
  378. package/src/styles/tokens.css +0 -78
@@ -0,0 +1,1464 @@
1
+ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
+ import { useMemo, useState, useEffect, Fragment as Fragment$1 } from "react";
3
+ import { useSort } from "../hooks/use-sort.js";
4
+ import { cn } from "../lib/utils.js";
5
+ import { FilterBar, FilterBarFilterPanel, FilterBarRangePanel } from "../components/FilterBar.js";
6
+ import { Icon } from "./Icon.js";
7
+ import { SortableHeader } from "./SortableHeader.js";
8
+ import { parseTimestamp, chooseTimestampFormat, modeToFormat, resolveDateMath, Timestamp } from "./cells/Timestamp.js";
9
+ import { tagActionsFromRecord, TagActionsProvider, tagFilterTokens, TagList, normalizeTags, splitTagToken } from "./cells/TagList.js";
10
+ import { StatusDot } from "./cells/StatusDot.js";
11
+ import { normalizeStatus } from "./cells/status-mapping.js";
12
+ const DEFAULT_COLUMN_MIN_WIDTH = 64;
13
+ const DEFAULT_COLUMN_WIDTH = 160;
14
+ const DEFAULT_GROW_COLUMN_WIDTH = 224;
15
+ const DEFAULT_SHRINK_COLUMN_WIDTH = 96;
16
+ const COLUMN_WIDTH_STORAGE_PREFIX = "clicky-ui-data-table-column-widths";
17
+ const COLUMN_VISIBILITY_STORAGE_PREFIX = "clicky-ui-data-table-column-visibility";
18
+ const DENSITY_STORAGE_PREFIX = "clicky-ui-data-table-density";
19
+ const DENSITY_OPTIONS = [
20
+ { value: "compact", icon: "ph:rows", label: "Compact" },
21
+ { value: "comfortable", icon: "ph:list", label: "Comfortable" },
22
+ { value: "spacious", icon: "ph:list-dashes", label: "Spacious" }
23
+ ];
24
+ const DATA_TABLE_HEADER_DENSITY_CLASS = "px-2.5 py-1.5 density-compact:px-2 density-compact:py-1 density-comfortable:px-2.5 density-comfortable:py-1.5 density-spacious:px-4 density-spacious:py-3";
25
+ const DATA_TABLE_CELL_DENSITY_CLASS = "px-2.5 py-1.5 density-compact:px-2 density-compact:py-0.5 density-comfortable:px-2.5 density-comfortable:py-1.5 density-spacious:px-4 density-spacious:py-3";
26
+ const TIMESTAMP_RANGE_PRESETS = [
27
+ { label: "Last 5 minutes", from: "now-5m", to: "now" },
28
+ { label: "Last 15 minutes", from: "now-15m", to: "now" },
29
+ { label: "Last 1 hour", from: "now-1h", to: "now" },
30
+ { label: "Last 6 hours", from: "now-6h", to: "now" },
31
+ { label: "Last 24 hours", from: "now-24h", to: "now" },
32
+ { label: "Last 7 days", from: "now-7d", to: "now" },
33
+ { label: "Last 30 days", from: "now-30d", to: "now" }
34
+ ];
35
+ function DataTable({
36
+ data,
37
+ columns: columnsInput,
38
+ emptyMessage: _emptyMessage = "No data",
39
+ className,
40
+ autoFilter = false,
41
+ showGlobalFilter = true,
42
+ globalFilter,
43
+ onGlobalFilterChange,
44
+ globalFilterPlaceholder = "Search all columns…",
45
+ defaultSort,
46
+ filterBarProps,
47
+ getRowId,
48
+ onRowClick,
49
+ isRowClickable,
50
+ getRowHref,
51
+ renderExpandedRow,
52
+ resizableColumns = true,
53
+ persistColumnWidths = true,
54
+ columnResizeStorageKey,
55
+ hideableColumns = true,
56
+ persistColumnVisibility = true,
57
+ columnVisibilityStorageKey,
58
+ density,
59
+ defaultDensity,
60
+ onDensityChange,
61
+ persistDensity = true,
62
+ densityStorageKey,
63
+ showDensityControl,
64
+ showHeaderFilters = true
65
+ }) {
66
+ const columns = useMemo(
67
+ () => columnsInput.map(
68
+ (column) => typeof column === "string" ? { key: column, label: column } : column
69
+ ),
70
+ [columnsInput]
71
+ );
72
+ const columnKeysSignature = useMemo(
73
+ () => columns.map((column) => column.key).join("|"),
74
+ [columns]
75
+ );
76
+ const resolvedColumnResizeStorageKey = columnResizeStorageKey ?? `${COLUMN_WIDTH_STORAGE_PREFIX}:${columnKeysSignature}`;
77
+ const resolvedColumnVisibilityStorageKey = columnVisibilityStorageKey ?? `${COLUMN_VISIBILITY_STORAGE_PREFIX}:${columnKeysSignature}`;
78
+ const resolvedDensityStorageKey = densityStorageKey ?? `${DENSITY_STORAGE_PREFIX}:${columnKeysSignature}`;
79
+ const [columnWidths, setColumnWidths] = useState(
80
+ () => persistColumnWidths ? readStoredColumnWidths(resolvedColumnResizeStorageKey, columns) : {}
81
+ );
82
+ const [hiddenColumns, setHiddenColumns] = useState(
83
+ () => persistColumnVisibility ? readStoredHiddenColumns(resolvedColumnVisibilityStorageKey, columns) : {}
84
+ );
85
+ const densityControlled = density !== void 0;
86
+ const [localDensityOverride, setLocalDensityOverride] = useState(() => {
87
+ if (densityControlled) return density;
88
+ if (persistDensity)
89
+ return readStoredDensityOverride(resolvedDensityStorageKey) ?? defaultDensity;
90
+ return defaultDensity;
91
+ });
92
+ const [columnMenu, setColumnMenu] = useState(null);
93
+ const [headerFilterMenu, setHeaderFilterMenu] = useState(null);
94
+ const [textFilters, setTextFilters] = useState({});
95
+ const [multiFilters, setMultiFilters] = useState({});
96
+ const [numberFilters, setNumberFilters] = useState({});
97
+ const [expandedRows, setExpandedRows] = useState({});
98
+ const [localGlobalFilter, setLocalGlobalFilter] = useState("");
99
+ const [timeRangeFilter, setTimeRangeFilter] = useState(() => {
100
+ var _a, _b, _c, _d;
101
+ const seed = columns.find(
102
+ (column) => {
103
+ var _a2;
104
+ return column.kind === "timestamp" && ((_a2 = column.timestamp) == null ? void 0 : _a2.defaultRange);
105
+ }
106
+ );
107
+ return {
108
+ from: ((_b = (_a = seed == null ? void 0 : seed.timestamp) == null ? void 0 : _a.defaultRange) == null ? void 0 : _b.from) ?? "",
109
+ to: ((_d = (_c = seed == null ? void 0 : seed.timestamp) == null ? void 0 : _c.defaultRange) == null ? void 0 : _d.to) ?? ""
110
+ };
111
+ });
112
+ useEffect(() => {
113
+ setColumnWidths((current) => {
114
+ const stored = persistColumnWidths ? readStoredColumnWidths(resolvedColumnResizeStorageKey, columns) : {};
115
+ const next = pruneColumnWidths({ ...stored, ...current }, columns);
116
+ return sameColumnWidths(current, next) ? current : next;
117
+ });
118
+ }, [columnKeysSignature, persistColumnWidths, resolvedColumnResizeStorageKey]);
119
+ useEffect(() => {
120
+ if (!persistColumnWidths) return;
121
+ writeStoredColumnWidths(resolvedColumnResizeStorageKey, columnWidths);
122
+ }, [columnWidths, persistColumnWidths, resolvedColumnResizeStorageKey]);
123
+ useEffect(() => {
124
+ setHiddenColumns((current) => {
125
+ const stored = persistColumnVisibility ? readStoredHiddenColumns(resolvedColumnVisibilityStorageKey, columns) : {};
126
+ const next = pruneHiddenColumns({ ...stored, ...current }, columns);
127
+ return sameHiddenColumns(current, next) ? current : next;
128
+ });
129
+ }, [columnKeysSignature, persistColumnVisibility, resolvedColumnVisibilityStorageKey]);
130
+ useEffect(() => {
131
+ if (!persistColumnVisibility) return;
132
+ writeStoredHiddenColumns(resolvedColumnVisibilityStorageKey, hiddenColumns);
133
+ }, [hiddenColumns, persistColumnVisibility, resolvedColumnVisibilityStorageKey]);
134
+ useEffect(() => {
135
+ if (densityControlled) return;
136
+ setLocalDensityOverride(
137
+ persistDensity ? readStoredDensityOverride(resolvedDensityStorageKey) ?? defaultDensity : defaultDensity
138
+ );
139
+ }, [defaultDensity, densityControlled, persistDensity, resolvedDensityStorageKey]);
140
+ useEffect(() => {
141
+ if (densityControlled || !persistDensity) return;
142
+ writeStoredDensityOverride(resolvedDensityStorageKey, localDensityOverride);
143
+ }, [densityControlled, localDensityOverride, persistDensity, resolvedDensityStorageKey]);
144
+ useEffect(() => {
145
+ if (!columnMenu && !headerFilterMenu) return;
146
+ const close = () => {
147
+ setColumnMenu(null);
148
+ setHeaderFilterMenu(null);
149
+ };
150
+ const closeOnEscape = (event) => {
151
+ if (event.key === "Escape") close();
152
+ };
153
+ document.addEventListener("click", close);
154
+ document.addEventListener("keydown", closeOnEscape);
155
+ return () => {
156
+ document.removeEventListener("click", close);
157
+ document.removeEventListener("keydown", closeOnEscape);
158
+ };
159
+ }, [columnMenu, headerFilterMenu]);
160
+ const rows = useMemo(
161
+ () => data.map((row, index) => ({
162
+ id: (getRowId == null ? void 0 : getRowId(row, index)) ?? String(index),
163
+ row
164
+ })),
165
+ [data, getRowId]
166
+ );
167
+ const timestampFormats = useMemo(() => {
168
+ var _a;
169
+ const out = {};
170
+ for (const column of columns) {
171
+ if (column.kind !== "timestamp") continue;
172
+ const dates = [];
173
+ for (const row of data) {
174
+ const raw = resolvePath(row, column.key);
175
+ const parsed = parseTimestamp(raw);
176
+ if (parsed) dates.push(parsed);
177
+ }
178
+ const dataFormat = chooseTimestampFormat(dates);
179
+ out[column.key] = modeToFormat(((_a = column.timestamp) == null ? void 0 : _a.mode) ?? "auto", dataFormat);
180
+ }
181
+ return out;
182
+ }, [columns, data]);
183
+ const effectiveColumns = useMemo(
184
+ () => columns.map((column) => applyKindDefaults(column, timestampFormats[column.key])),
185
+ [columns, timestampFormats]
186
+ );
187
+ const visibleColumns = useMemo(() => {
188
+ if (!hideableColumns) return effectiveColumns;
189
+ const next = effectiveColumns.filter((column) => !hiddenColumns[column.key]);
190
+ return next.length > 0 ? next : effectiveColumns;
191
+ }, [effectiveColumns, hiddenColumns, hideableColumns]);
192
+ const hideableColumnCount = useMemo(
193
+ () => effectiveColumns.filter(isColumnHideable).length,
194
+ [effectiveColumns]
195
+ );
196
+ const visibleHideableColumnCount = useMemo(
197
+ () => visibleColumns.filter(isColumnHideable).length,
198
+ [visibleColumns]
199
+ );
200
+ const showColumnVisibilityControl = hideableColumns && hideableColumnCount > 1;
201
+ const resolvedShowDensityControl = showDensityControl ?? showColumnVisibilityControl;
202
+ const showTablePreferencesControl = showColumnVisibilityControl || resolvedShowDensityControl;
203
+ const densityOverride = densityControlled ? density : localDensityOverride;
204
+ const tagActionsByColumn = useMemo(() => {
205
+ const out = {};
206
+ for (const column of visibleColumns) {
207
+ if (column.kind !== "tags") continue;
208
+ const columnKey = column.key;
209
+ const current = multiFilters[columnKey] ?? {};
210
+ const handler = (next) => setMultiFilters((state) => updateFilterRecord(state, columnKey, next));
211
+ out[columnKey] = tagActionsFromRecord(current, handler);
212
+ }
213
+ return out;
214
+ }, [multiFilters, visibleColumns]);
215
+ const timeRangeColumn = useMemo(() => {
216
+ if (filterBarProps == null ? void 0 : filterBarProps.timeRange) return null;
217
+ return visibleColumns.find(
218
+ (column) => {
219
+ var _a;
220
+ return column.kind === "timestamp" && column.filterable !== false && ((_a = column.timestamp) == null ? void 0 : _a.autoRangeFilter) !== false;
221
+ }
222
+ ) ?? null;
223
+ }, [filterBarProps == null ? void 0 : filterBarProps.timeRange, visibleColumns]);
224
+ const filterableColumns = useMemo(
225
+ () => visibleColumns.filter((column) => {
226
+ if (column.filterable === false) return false;
227
+ if (column.kind === "timestamp") return false;
228
+ return true;
229
+ }),
230
+ [visibleColumns]
231
+ );
232
+ const generatedFilters = useMemo(() => {
233
+ if (!autoFilter) return [];
234
+ return filterableColumns.map((column) => {
235
+ var _a;
236
+ const numberBounds = getNumericFilterBounds(rows, column);
237
+ if (numberBounds) {
238
+ return {
239
+ column,
240
+ kind: "number",
241
+ options: [],
242
+ numberBounds
243
+ };
244
+ }
245
+ const values = /* @__PURE__ */ new Set();
246
+ for (const record of rows) {
247
+ for (const token of getFilterTokens(record.row, column)) {
248
+ if (token) values.add(token);
249
+ }
250
+ }
251
+ const options = Array.from(values).sort((left, right) => left.localeCompare(right, void 0, { numeric: true })).map((value) => ({ value, label: value }));
252
+ const multiCap = column.kind === "tags" ? 50 : 20;
253
+ const fitsMulti = options.length >= 2 && options.length <= multiCap;
254
+ if (column.kind === "tags" && fitsMulti) {
255
+ const separator = ((_a = column.tags) == null ? void 0 : _a.separator) ?? "=";
256
+ const groups = groupTagOptions(options, separator);
257
+ if (groups.length >= 2) {
258
+ return {
259
+ column,
260
+ kind: "nested-multi",
261
+ options,
262
+ groups
263
+ };
264
+ }
265
+ }
266
+ return {
267
+ column,
268
+ kind: fitsMulti ? "multi" : "text",
269
+ options
270
+ };
271
+ });
272
+ }, [autoFilter, filterableColumns, rows]);
273
+ useEffect(() => {
274
+ setTextFilters((current) => pruneTextFilterState(current, generatedFilters));
275
+ setMultiFilters((current) => pruneMultiFilterState(current, generatedFilters));
276
+ setNumberFilters((current) => pruneNumberFilterState(current, generatedFilters));
277
+ }, [generatedFilters]);
278
+ const globalFilterControlled = globalFilter !== void 0;
279
+ const effectiveGlobalFilter = globalFilterControlled ? globalFilter : localGlobalFilter;
280
+ const setEffectiveGlobalFilter = globalFilterControlled ? onGlobalFilterChange ?? (() => {
281
+ }) : setLocalGlobalFilter;
282
+ const nativeFilters = useMemo(
283
+ () => generatedFilters.map((filter) => {
284
+ var _a, _b, _c;
285
+ const columnKey = filter.column.key;
286
+ if (filter.kind === "multi") {
287
+ return {
288
+ key: columnKey,
289
+ kind: "multi",
290
+ label: labelText(filter.column),
291
+ value: multiFilters[columnKey] ?? {},
292
+ onChange: (next) => setMultiFilters((current) => updateFilterRecord(current, columnKey, next)),
293
+ options: filter.options
294
+ };
295
+ }
296
+ if (filter.kind === "nested-multi") {
297
+ return {
298
+ key: columnKey,
299
+ kind: "nested-multi",
300
+ label: labelText(filter.column),
301
+ value: multiFilters[columnKey] ?? {},
302
+ onChange: (next) => setMultiFilters((current) => updateFilterRecord(current, columnKey, next)),
303
+ groups: filter.groups ?? []
304
+ };
305
+ }
306
+ if (filter.kind === "number") {
307
+ const numberFilter = {
308
+ key: columnKey,
309
+ kind: "number",
310
+ label: labelText(filter.column),
311
+ value: numberFilters[columnKey] ?? {},
312
+ onChange: (next) => setNumberFilters((current) => updateNumberFilterValue(current, columnKey, next))
313
+ };
314
+ if (((_a = filter.numberBounds) == null ? void 0 : _a.min) !== void 0) {
315
+ numberFilter.domainMin = filter.numberBounds.min;
316
+ }
317
+ if (((_b = filter.numberBounds) == null ? void 0 : _b.max) !== void 0) {
318
+ numberFilter.domainMax = filter.numberBounds.max;
319
+ }
320
+ if (((_c = filter.numberBounds) == null ? void 0 : _c.step) !== void 0) {
321
+ numberFilter.step = filter.numberBounds.step;
322
+ }
323
+ return numberFilter;
324
+ }
325
+ return {
326
+ key: columnKey,
327
+ kind: "text",
328
+ label: labelText(filter.column),
329
+ value: textFilters[columnKey] ?? "",
330
+ onChange: (next) => setTextFilters((current) => updateFilterValue(current, columnKey, next))
331
+ };
332
+ }),
333
+ [generatedFilters, multiFilters, numberFilters, textFilters]
334
+ );
335
+ const nativeFilterByColumn = useMemo(
336
+ () => new Map(nativeFilters.map((filter) => [filter.key, filter])),
337
+ [nativeFilters]
338
+ );
339
+ const hasCustomFilterBarContent = Boolean(
340
+ (filterBarProps == null ? void 0 : filterBarProps.leading) || (filterBarProps == null ? void 0 : filterBarProps.children) || (filterBarProps == null ? void 0 : filterBarProps.trailing) || (filterBarProps == null ? void 0 : filterBarProps.timeRange) || (filterBarProps == null ? void 0 : filterBarProps.dateRange)
341
+ );
342
+ const autoTimeRange = useMemo(() => {
343
+ var _a;
344
+ if (!autoFilter || !timeRangeColumn) return null;
345
+ return {
346
+ from: timeRangeFilter.from,
347
+ to: timeRangeFilter.to,
348
+ onApply: (from, to) => setTimeRangeFilter({ from, to }),
349
+ presets: ((_a = timeRangeColumn.timestamp) == null ? void 0 : _a.rangePresets) ?? TIMESTAMP_RANGE_PRESETS,
350
+ fromPlaceholder: "now-24h",
351
+ toPlaceholder: "now",
352
+ emptyLabel: "Any time"
353
+ };
354
+ }, [autoFilter, timeRangeColumn, timeRangeFilter.from, timeRangeFilter.to]);
355
+ const showFilterBar = autoFilter && (showGlobalFilter || nativeFilters.length > 0 || !!autoTimeRange) || hasCustomFilterBarContent || showTablePreferencesControl;
356
+ const setDensityOverride = (next) => {
357
+ if (!densityControlled) setLocalDensityOverride(next);
358
+ onDensityChange == null ? void 0 : onDensityChange(next);
359
+ };
360
+ const filterBarTrailing = showTablePreferencesControl ? /* @__PURE__ */ jsxs(Fragment, { children: [
361
+ filterBarProps == null ? void 0 : filterBarProps.trailing,
362
+ /* @__PURE__ */ jsx(ColumnVisibilityTrigger, { onOpen: (event) => setColumnMenu(menuStateFromTrigger(event)) })
363
+ ] }) : filterBarProps == null ? void 0 : filterBarProps.trailing;
364
+ const showHeaderFilterControls = autoFilter && showHeaderFilters;
365
+ const filteredRows = useMemo(() => {
366
+ const globalNeedle = effectiveGlobalFilter.trim().toLowerCase();
367
+ const now = /* @__PURE__ */ new Date();
368
+ const rangeFromDate = timeRangeColumn ? resolveDateMath(timeRangeFilter.from, now) : null;
369
+ const rangeToDate = timeRangeColumn ? resolveDateMath(timeRangeFilter.to, now) : null;
370
+ const rangeColumnKey = timeRangeColumn == null ? void 0 : timeRangeColumn.key;
371
+ return rows.filter(({ row }) => {
372
+ if (rangeColumnKey && (rangeFromDate || rangeToDate)) {
373
+ const raw = resolvePath(row, rangeColumnKey);
374
+ const ts = parseTimestamp(raw);
375
+ if (!ts) return false;
376
+ if (rangeFromDate && ts.getTime() < rangeFromDate.getTime()) return false;
377
+ if (rangeToDate && ts.getTime() > rangeToDate.getTime()) return false;
378
+ }
379
+ if (globalNeedle) {
380
+ const haystack = filterableColumns.flatMap((column) => getFilterTokens(row, column)).join(" ").toLowerCase();
381
+ if (!haystack.includes(globalNeedle)) {
382
+ return false;
383
+ }
384
+ }
385
+ for (const filter of generatedFilters) {
386
+ const tokens = getFilterTokens(row, filter.column);
387
+ if (filter.kind === "text") {
388
+ const needle = (textFilters[filter.column.key] ?? "").trim().toLowerCase();
389
+ if (needle && !tokens.some((token) => token.toLowerCase().includes(needle))) {
390
+ return false;
391
+ }
392
+ } else if (filter.kind === "number") {
393
+ const range = numberFilters[filter.column.key] ?? {};
394
+ const min = parseNumberInput(range.min);
395
+ const max = parseNumberInput(range.max);
396
+ const hasMin = String(range.min ?? "").trim() !== "";
397
+ const hasMax = String(range.max ?? "").trim() !== "";
398
+ if (hasMin || hasMax) {
399
+ const values = getFilterNumbers(row, filter.column);
400
+ const matches = values.some(
401
+ (value) => (min == null || value >= min) && (max == null || value <= max)
402
+ );
403
+ if (!matches) {
404
+ return false;
405
+ }
406
+ }
407
+ } else {
408
+ const selected = multiFilters[filter.column.key] ?? {};
409
+ const include = Object.entries(selected).filter(([, mode]) => mode === "include").map(([value]) => value);
410
+ const exclude = Object.entries(selected).filter(([, mode]) => mode === "exclude").map(([value]) => value);
411
+ if (include.length > 0 && !tokens.some((token) => include.includes(token))) {
412
+ return false;
413
+ }
414
+ if (exclude.length > 0 && tokens.some((token) => exclude.includes(token))) {
415
+ return false;
416
+ }
417
+ }
418
+ }
419
+ return true;
420
+ });
421
+ }, [
422
+ effectiveGlobalFilter,
423
+ filterableColumns,
424
+ generatedFilters,
425
+ multiFilters,
426
+ numberFilters,
427
+ rows,
428
+ textFilters,
429
+ timeRangeColumn,
430
+ timeRangeFilter.from,
431
+ timeRangeFilter.to
432
+ ]);
433
+ const sortResolvers = useMemo(
434
+ () => Object.fromEntries(
435
+ effectiveColumns.map((column) => [
436
+ column.key,
437
+ (record) => getSortValue(record.row, column)
438
+ ])
439
+ ),
440
+ [effectiveColumns]
441
+ );
442
+ const { sorted, sort, toggle } = useSort(filteredRows, {
443
+ defaultDir: (defaultSort == null ? void 0 : defaultSort.dir) ?? "asc",
444
+ resolvers: sortResolvers,
445
+ ...(defaultSort == null ? void 0 : defaultSort.key) ? { defaultKey: defaultSort.key } : {}
446
+ });
447
+ const startColumnResize = (event, column) => {
448
+ event.preventDefault();
449
+ event.stopPropagation();
450
+ const startX = event.clientX;
451
+ const header = event.currentTarget.closest("th");
452
+ const measuredWidth = (header == null ? void 0 : header.getBoundingClientRect().width) ?? 0;
453
+ const startWidth = measuredWidth || columnWidths[column.key] || defaultColumnWidth(column);
454
+ const onMove = (moveEvent) => {
455
+ const nextWidth = clampColumnWidth(column, startWidth + moveEvent.clientX - startX);
456
+ setColumnWidths((current) => ({
457
+ ...current,
458
+ [column.key]: nextWidth
459
+ }));
460
+ };
461
+ const onUp = () => {
462
+ document.removeEventListener("mousemove", onMove);
463
+ document.removeEventListener("mouseup", onUp);
464
+ document.body.style.cursor = "";
465
+ document.body.style.userSelect = "";
466
+ };
467
+ document.addEventListener("mousemove", onMove);
468
+ document.addEventListener("mouseup", onUp);
469
+ document.body.style.cursor = "col-resize";
470
+ document.body.style.userSelect = "none";
471
+ };
472
+ const autoFitColumn = (event, column) => {
473
+ var _a;
474
+ event.preventDefault();
475
+ event.stopPropagation();
476
+ const header = event.currentTarget.closest("th");
477
+ const table = event.currentTarget.closest("table");
478
+ if (!header || !table) return;
479
+ const columnIndex = Array.from(((_a = header.parentElement) == null ? void 0 : _a.children) ?? []).indexOf(header);
480
+ if (columnIndex < 0) return;
481
+ const width = measureColumnContentWidth(table, columnIndex, column);
482
+ setColumnWidths((current) => ({
483
+ ...current,
484
+ [column.key]: width
485
+ }));
486
+ };
487
+ const toggleColumnVisibility = (column) => {
488
+ if (!isColumnHideable(column)) return;
489
+ setHiddenColumns((current) => {
490
+ const hidden = current[column.key] === true;
491
+ if (!hidden && visibleHideableColumnCount <= 1) return current;
492
+ const next = { ...current };
493
+ if (hidden) {
494
+ delete next[column.key];
495
+ } else {
496
+ next[column.key] = true;
497
+ }
498
+ return pruneHiddenColumns(next, columns);
499
+ });
500
+ };
501
+ const showAllColumns = () => setHiddenColumns({});
502
+ const openHeaderColumnMenu = (event, column) => {
503
+ if (!showColumnVisibilityControl) return;
504
+ event.preventDefault();
505
+ setColumnMenu(menuStateFromPointer(event, column.key));
506
+ };
507
+ const openHeaderFilterMenu = (event, columnKey) => {
508
+ event.preventDefault();
509
+ event.stopPropagation();
510
+ setHeaderFilterMenu(menuStateFromTrigger(event, columnKey));
511
+ };
512
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-0 flex-col gap-3", className), "data-density": densityOverride, children: [
513
+ showFilterBar && /* @__PURE__ */ jsx(
514
+ FilterBar,
515
+ {
516
+ ...filterBarProps,
517
+ ...autoFilter && showGlobalFilter ? {
518
+ search: {
519
+ value: effectiveGlobalFilter,
520
+ onChange: setEffectiveGlobalFilter,
521
+ placeholder: globalFilterPlaceholder
522
+ }
523
+ } : {},
524
+ ...autoTimeRange ? { timeRange: autoTimeRange } : {},
525
+ trailing: filterBarTrailing,
526
+ filters: nativeFilters
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs("table", { className: "w-max table-auto text-left text-sm", children: [
530
+ /* @__PURE__ */ jsx("colgroup", { children: visibleColumns.map((column) => /* @__PURE__ */ jsx(
531
+ "col",
532
+ {
533
+ style: columnStyle(column, columnWidths),
534
+ className: column.shrink && !column.grow ? "w-px" : void 0
535
+ },
536
+ column.key
537
+ )) }),
538
+ /* @__PURE__ */ jsx("thead", { className: "sticky top-0 z-10 bg-muted shadow-[0_1px_0_0_var(--tw-shadow-color)] shadow-border", children: /* @__PURE__ */ jsx("tr", { className: "border-b border-border text-xs text-muted-foreground", children: visibleColumns.map((column) => /* @__PURE__ */ jsxs(
539
+ "th",
540
+ {
541
+ className: cn(
542
+ "group/header relative whitespace-nowrap font-medium",
543
+ DATA_TABLE_HEADER_DENSITY_CLASS,
544
+ alignmentClass(column.align),
545
+ resizableColumns && column.resizable !== false && "select-none",
546
+ column.headerClassName
547
+ ),
548
+ onContextMenu: (event) => openHeaderColumnMenu(event, column),
549
+ children: [
550
+ /* @__PURE__ */ jsxs(
551
+ "div",
552
+ {
553
+ className: cn(
554
+ "flex min-w-0 items-center gap-1",
555
+ headerAlignmentClass(column.align),
556
+ resizableColumns && column.resizable !== false && "pr-2"
557
+ ),
558
+ children: [
559
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: column.sortable === false ? /* @__PURE__ */ jsx("span", { children: column.label }) : /* @__PURE__ */ jsx(
560
+ SortableHeader,
561
+ {
562
+ active: (sort == null ? void 0 : sort.key) === column.key,
563
+ ...(sort == null ? void 0 : sort.key) === column.key ? { dir: sort.dir } : {},
564
+ ...column.align ? { align: column.align } : {},
565
+ onClick: () => toggle(column.key),
566
+ children: column.label
567
+ }
568
+ ) }),
569
+ showHeaderFilterControls && (nativeFilterByColumn.has(column.key) || autoTimeRange && (timeRangeColumn == null ? void 0 : timeRangeColumn.key) === column.key) && /* @__PURE__ */ jsx(
570
+ HeaderFilterButton,
571
+ {
572
+ column,
573
+ active: nativeFilterByColumn.has(column.key) ? isFilterBarFilterActive(nativeFilterByColumn.get(column.key)) : Boolean(timeRangeFilter.from || timeRangeFilter.to),
574
+ onOpen: (event) => openHeaderFilterMenu(event, column.key)
575
+ }
576
+ )
577
+ ]
578
+ }
579
+ ),
580
+ resizableColumns && column.resizable !== false && /* @__PURE__ */ jsx(
581
+ "span",
582
+ {
583
+ role: "separator",
584
+ "aria-label": `Resize ${labelText(column)} column`,
585
+ "aria-orientation": "vertical",
586
+ className: "absolute right-0 top-0 flex h-full w-3 cursor-col-resize touch-none items-center justify-center border-r border-border/70 bg-gradient-to-l from-border/30 to-transparent transition-colors hover:border-primary hover:from-primary/20",
587
+ onClick: (event) => {
588
+ event.preventDefault();
589
+ event.stopPropagation();
590
+ },
591
+ onDoubleClick: (event) => autoFitColumn(event, column),
592
+ onMouseDown: (event) => startColumnResize(event, column),
593
+ children: /* @__PURE__ */ jsx(
594
+ "span",
595
+ {
596
+ "aria-hidden": true,
597
+ className: "h-4 w-0.5 rounded-full bg-border transition-colors group-hover/header:bg-primary/70"
598
+ }
599
+ )
600
+ }
601
+ )
602
+ ]
603
+ },
604
+ column.key
605
+ )) }) }),
606
+ /* @__PURE__ */ jsx("tbody", { children: sorted.map((record) => {
607
+ const href = getRowHref == null ? void 0 : getRowHref(record.row);
608
+ const expanded = expandedRows[record.id] ?? false;
609
+ const expandedContent = (renderExpandedRow == null ? void 0 : renderExpandedRow(record.row, {
610
+ columns: effectiveColumns,
611
+ visibleColumns,
612
+ tagActionsByColumn
613
+ })) ?? null;
614
+ const expandable = expandedContent !== null;
615
+ const rowClickEnabled = (isRowClickable == null ? void 0 : isRowClickable(record.row)) ?? !!onRowClick;
616
+ const clickable = !!href || rowClickEnabled || expandable;
617
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
618
+ /* @__PURE__ */ jsx(
619
+ "tr",
620
+ {
621
+ className: cn(
622
+ "border-b border-border/60 align-top",
623
+ clickable && "cursor-pointer hover:bg-accent/40"
624
+ ),
625
+ onClick: () => {
626
+ if (expandable) {
627
+ setExpandedRows((current) => ({
628
+ ...current,
629
+ [record.id]: !current[record.id]
630
+ }));
631
+ }
632
+ if (rowClickEnabled) {
633
+ onRowClick == null ? void 0 : onRowClick(record.row);
634
+ }
635
+ },
636
+ children: visibleColumns.map((column, index) => {
637
+ const rawValue = resolvePath(record.row, column.key);
638
+ let content = column.render ? column.render(rawValue, record.row) : formatCell(rawValue);
639
+ if (column.kind === "tags" && tagActionsByColumn[column.key]) {
640
+ content = /* @__PURE__ */ jsx(TagActionsProvider, { value: tagActionsByColumn[column.key], children: content });
641
+ }
642
+ return /* @__PURE__ */ jsx(
643
+ "td",
644
+ {
645
+ className: cn(
646
+ DATA_TABLE_CELL_DENSITY_CLASS,
647
+ alignmentClass(column.align),
648
+ column.cellClassName
649
+ ),
650
+ children: /* @__PURE__ */ jsx(
651
+ CellContent,
652
+ {
653
+ column,
654
+ ...columnWidths[column.key] !== void 0 ? { width: columnWidths[column.key] } : {},
655
+ children: href && index === 0 ? /* @__PURE__ */ jsx("a", { href, className: "hover:underline", children: content }) : content
656
+ }
657
+ )
658
+ },
659
+ column.key
660
+ );
661
+ })
662
+ }
663
+ ),
664
+ expanded && expandedContent && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: visibleColumns.length, className: "bg-muted/40 p-density-3", children: /* @__PURE__ */ jsx("div", { className: "rounded-md border border-border bg-background p-density-3", children: expandedContent }) }) })
665
+ ] }, record.id);
666
+ }) })
667
+ ] }) }),
668
+ /* @__PURE__ */ jsxs("div", { className: "px-1 text-xs text-muted-foreground", children: [
669
+ sorted.length,
670
+ " of ",
671
+ data.length,
672
+ " row",
673
+ data.length === 1 ? "" : "s"
674
+ ] }),
675
+ columnMenu && showTablePreferencesControl && /* @__PURE__ */ jsx(
676
+ ColumnVisibilityMenu,
677
+ {
678
+ columns: effectiveColumns,
679
+ hiddenColumns,
680
+ anchor: columnMenu,
681
+ showColumnVisibilityControl,
682
+ showDensityControl: resolvedShowDensityControl,
683
+ densityOverride,
684
+ visibleHideableColumnCount,
685
+ onToggle: toggleColumnVisibility,
686
+ onShowAll: showAllColumns,
687
+ onDensityChange: setDensityOverride,
688
+ onClose: () => setColumnMenu(null)
689
+ }
690
+ ),
691
+ headerFilterMenu && /* @__PURE__ */ jsx(
692
+ HeaderFilterMenu,
693
+ {
694
+ filter: nativeFilterByColumn.get(headerFilterMenu.columnKey ?? ""),
695
+ ...autoTimeRange && (timeRangeColumn == null ? void 0 : timeRangeColumn.key) === headerFilterMenu.columnKey ? { timeRange: autoTimeRange } : {},
696
+ anchor: headerFilterMenu,
697
+ onClose: () => setHeaderFilterMenu(null)
698
+ }
699
+ )
700
+ ] });
701
+ }
702
+ function HeaderFilterButton({
703
+ column,
704
+ active,
705
+ onOpen
706
+ }) {
707
+ return /* @__PURE__ */ jsx(
708
+ "button",
709
+ {
710
+ type: "button",
711
+ "aria-label": `Open ${labelText(column)} column filter`,
712
+ "aria-haspopup": "dialog",
713
+ "aria-pressed": active,
714
+ className: cn(
715
+ "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
716
+ active && "bg-accent text-foreground"
717
+ ),
718
+ onClick: onOpen,
719
+ children: /* @__PURE__ */ jsx(Icon, { name: "codicon:filter", className: "text-xs" })
720
+ }
721
+ );
722
+ }
723
+ function HeaderFilterMenu({
724
+ filter,
725
+ timeRange,
726
+ anchor,
727
+ onClose
728
+ }) {
729
+ if (!filter && !timeRange) return null;
730
+ const label = (filter == null ? void 0 : filter.label) ?? "Time range";
731
+ const timeRangeActive = Boolean((timeRange == null ? void 0 : timeRange.from) || (timeRange == null ? void 0 : timeRange.to));
732
+ return /* @__PURE__ */ jsxs(
733
+ "div",
734
+ {
735
+ role: "dialog",
736
+ "aria-label": `${label} column filter`,
737
+ className: "fixed z-50 rounded-md border border-border bg-popover p-2 text-popover-foreground shadow-lg shadow-black/5",
738
+ style: { left: anchor.x, top: anchor.y },
739
+ onClick: (event) => event.stopPropagation(),
740
+ onContextMenu: (event) => event.preventDefault(),
741
+ children: [
742
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
743
+ /* @__PURE__ */ jsx("div", { className: "truncate text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: label }),
744
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
745
+ filter && /* @__PURE__ */ jsx(
746
+ "button",
747
+ {
748
+ type: "button",
749
+ className: "rounded px-1.5 py-0.5 text-xs text-primary transition-colors hover:bg-accent focus:bg-accent focus:outline-none disabled:text-muted-foreground",
750
+ onClick: () => clearFilterBarFilter(filter),
751
+ disabled: !isFilterBarFilterActive(filter),
752
+ children: "Clear all"
753
+ }
754
+ ),
755
+ timeRange && /* @__PURE__ */ jsx(
756
+ "button",
757
+ {
758
+ type: "button",
759
+ className: "rounded px-1.5 py-0.5 text-xs text-primary transition-colors hover:bg-accent focus:bg-accent focus:outline-none disabled:text-muted-foreground",
760
+ onClick: () => timeRange.onApply("", ""),
761
+ disabled: !timeRangeActive,
762
+ children: "Clear all"
763
+ }
764
+ ),
765
+ /* @__PURE__ */ jsx(
766
+ "button",
767
+ {
768
+ type: "button",
769
+ "aria-label": "Close column filter",
770
+ title: "Close",
771
+ className: "inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:outline-none",
772
+ onClick: onClose,
773
+ children: /* @__PURE__ */ jsx(Icon, { name: "codicon:close", className: "text-sm" })
774
+ }
775
+ )
776
+ ] })
777
+ ] }),
778
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
779
+ filter && /* @__PURE__ */ jsx(FilterBarFilterPanel, { filter, chrome: "embedded" }),
780
+ timeRange && /* @__PURE__ */ jsx(FilterBarRangePanel, { kind: "time", label: "Time range", ...timeRange })
781
+ ] })
782
+ ]
783
+ }
784
+ );
785
+ }
786
+ function clearFilterBarFilter(filter) {
787
+ if (filter.kind === "text" || filter.kind === "lookup" || filter.kind === "enum") {
788
+ filter.onChange("");
789
+ return;
790
+ }
791
+ if (filter.kind === "lookup-multi" || filter.kind === "select-multi") {
792
+ filter.onChange([]);
793
+ return;
794
+ }
795
+ if (filter.kind === "number") {
796
+ filter.onChange({});
797
+ return;
798
+ }
799
+ if (filter.kind === "boolean") {
800
+ filter.onChange(false);
801
+ return;
802
+ }
803
+ filter.onChange({});
804
+ }
805
+ function ColumnVisibilityTrigger({
806
+ onOpen
807
+ }) {
808
+ return /* @__PURE__ */ jsx(
809
+ "button",
810
+ {
811
+ type: "button",
812
+ "aria-label": "Open column menu",
813
+ "aria-haspopup": "menu",
814
+ className: "inline-flex h-[34px] w-[34px] items-center justify-center rounded-md border border-input bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
815
+ onClick: (event) => {
816
+ event.stopPropagation();
817
+ onOpen(event);
818
+ },
819
+ children: /* @__PURE__ */ jsx(Icon, { name: "codicon:ellipsis", className: "text-sm" })
820
+ }
821
+ );
822
+ }
823
+ function ColumnVisibilityMenu({
824
+ columns,
825
+ hiddenColumns,
826
+ anchor,
827
+ showColumnVisibilityControl,
828
+ showDensityControl,
829
+ densityOverride,
830
+ visibleHideableColumnCount,
831
+ onToggle,
832
+ onShowAll,
833
+ onDensityChange,
834
+ onClose
835
+ }) {
836
+ const activeColumn = anchor.columnKey ? columns.find((column) => column.key === anchor.columnKey) : void 0;
837
+ const canHideActiveColumn = activeColumn && isColumnHideable(activeColumn) && visibleHideableColumnCount > 1;
838
+ return /* @__PURE__ */ jsxs(
839
+ "div",
840
+ {
841
+ role: "menu",
842
+ "aria-label": "Column menu",
843
+ className: "fixed z-50 min-w-[16rem] rounded-md border border-border bg-popover p-1.5 text-popover-foreground shadow-lg shadow-black/5",
844
+ style: { left: anchor.x, top: anchor.y },
845
+ onClick: (event) => event.stopPropagation(),
846
+ onContextMenu: (event) => event.preventDefault(),
847
+ children: [
848
+ showColumnVisibilityControl && /* @__PURE__ */ jsxs(Fragment, { children: [
849
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-2 py-1.5 text-xs font-medium text-muted-foreground", children: [
850
+ /* @__PURE__ */ jsx("span", { children: "Columns" }),
851
+ /* @__PURE__ */ jsx(
852
+ "button",
853
+ {
854
+ type: "button",
855
+ className: "rounded px-1.5 py-0.5 text-xs text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:outline-none",
856
+ onClick: onShowAll,
857
+ children: "Show all"
858
+ }
859
+ )
860
+ ] }),
861
+ activeColumn && /* @__PURE__ */ jsxs(Fragment, { children: [
862
+ /* @__PURE__ */ jsxs(
863
+ "button",
864
+ {
865
+ type: "button",
866
+ role: "menuitem",
867
+ disabled: !canHideActiveColumn,
868
+ className: cn(
869
+ "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:outline-none",
870
+ !canHideActiveColumn && "cursor-not-allowed opacity-50"
871
+ ),
872
+ onClick: () => {
873
+ if (!canHideActiveColumn) return;
874
+ onToggle(activeColumn);
875
+ onClose();
876
+ },
877
+ children: [
878
+ /* @__PURE__ */ jsx(Icon, { name: "codicon:eye-closed", className: "text-sm text-muted-foreground" }),
879
+ /* @__PURE__ */ jsxs("span", { children: [
880
+ "Hide ",
881
+ labelText(activeColumn)
882
+ ] })
883
+ ]
884
+ }
885
+ ),
886
+ /* @__PURE__ */ jsx("div", { className: "my-1 h-px bg-border" })
887
+ ] }),
888
+ /* @__PURE__ */ jsx("div", { className: "max-h-72 overflow-auto", children: columns.map((column) => {
889
+ const hideable = isColumnHideable(column);
890
+ const visible = hiddenColumns[column.key] !== true;
891
+ const disabled = !hideable || visible && visibleHideableColumnCount <= 1;
892
+ return /* @__PURE__ */ jsxs(
893
+ "label",
894
+ {
895
+ className: cn(
896
+ "flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-accent hover:text-accent-foreground",
897
+ disabled && "cursor-not-allowed opacity-50"
898
+ ),
899
+ children: [
900
+ /* @__PURE__ */ jsx(
901
+ "input",
902
+ {
903
+ type: "checkbox",
904
+ className: "h-4 w-4 rounded border-border",
905
+ checked: visible,
906
+ disabled,
907
+ onChange: () => onToggle(column)
908
+ }
909
+ ),
910
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: labelText(column) })
911
+ ]
912
+ },
913
+ column.key
914
+ );
915
+ }) })
916
+ ] }),
917
+ showDensityControl && /* @__PURE__ */ jsx(
918
+ DensityMenuSection,
919
+ {
920
+ densityOverride,
921
+ separated: showColumnVisibilityControl,
922
+ onDensityChange
923
+ }
924
+ )
925
+ ]
926
+ }
927
+ );
928
+ }
929
+ function DensityMenuSection({
930
+ densityOverride,
931
+ separated,
932
+ onDensityChange
933
+ }) {
934
+ const current = densityOverride ?? "inherit";
935
+ return /* @__PURE__ */ jsxs("div", { className: cn(separated && "mt-1 border-t border-border pt-1"), children: [
936
+ /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-medium text-muted-foreground", children: "Density" }),
937
+ /* @__PURE__ */ jsxs(
938
+ "button",
939
+ {
940
+ type: "button",
941
+ role: "menuitemradio",
942
+ "aria-checked": current === "inherit",
943
+ className: densityMenuItemClassName(current === "inherit"),
944
+ onClick: () => onDensityChange(void 0),
945
+ children: [
946
+ /* @__PURE__ */ jsx(Icon, { name: "ph:arrows-in-line-vertical", className: "text-sm text-muted-foreground" }),
947
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: "Use page density" }),
948
+ current === "inherit" ? /* @__PURE__ */ jsx(Icon, { name: "ph:check", className: "text-sm text-foreground" }) : /* @__PURE__ */ jsx("span", { className: "inline-block h-4 w-4", "aria-hidden": true })
949
+ ]
950
+ }
951
+ ),
952
+ DENSITY_OPTIONS.map((option) => {
953
+ const active = current === option.value;
954
+ return /* @__PURE__ */ jsxs(
955
+ "button",
956
+ {
957
+ type: "button",
958
+ role: "menuitemradio",
959
+ "aria-checked": active,
960
+ className: densityMenuItemClassName(active),
961
+ onClick: () => onDensityChange(option.value),
962
+ children: [
963
+ /* @__PURE__ */ jsx(Icon, { name: option.icon, className: "text-sm text-muted-foreground" }),
964
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: option.label }),
965
+ active ? /* @__PURE__ */ jsx(Icon, { name: "ph:check", className: "text-sm text-foreground" }) : /* @__PURE__ */ jsx("span", { className: "inline-block h-4 w-4", "aria-hidden": true })
966
+ ]
967
+ },
968
+ option.value
969
+ );
970
+ })
971
+ ] });
972
+ }
973
+ function densityMenuItemClassName(active) {
974
+ return cn(
975
+ "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:outline-none",
976
+ active && "text-foreground"
977
+ );
978
+ }
979
+ function CellContent({
980
+ column,
981
+ width,
982
+ children
983
+ }) {
984
+ return /* @__PURE__ */ jsx(
985
+ "div",
986
+ {
987
+ className: cn(cellContentClassName(column, width), alignmentClass(column.align)),
988
+ style: cellContentStyle(width),
989
+ children
990
+ }
991
+ );
992
+ }
993
+ function getSortValue(row, column) {
994
+ const rawValue = resolvePath(row, column.key);
995
+ return column.sortValue ? column.sortValue(rawValue, row) : rawValue;
996
+ }
997
+ function getFilterCandidate(row, column) {
998
+ const rawValue = resolvePath(row, column.key);
999
+ return column.filterValue ? column.filterValue(rawValue, row) : rawValue;
1000
+ }
1001
+ function getFilterTokens(row, column) {
1002
+ return normalizeTokens(getFilterCandidate(row, column));
1003
+ }
1004
+ function getFilterNumbers(row, column) {
1005
+ return normalizeNumbers(getFilterCandidate(row, column));
1006
+ }
1007
+ function normalizeTokens(value) {
1008
+ if (Array.isArray(value)) {
1009
+ return value.flatMap((item) => normalizeTokens(item)).filter(Boolean);
1010
+ }
1011
+ if (value == null) return [];
1012
+ if (typeof value === "object") return [JSON.stringify(value)];
1013
+ const token = String(value).trim();
1014
+ return token ? [token] : [];
1015
+ }
1016
+ function normalizeNumbers(value) {
1017
+ if (Array.isArray(value)) {
1018
+ return value.flatMap((item) => normalizeNumbers(item));
1019
+ }
1020
+ const parsed = parseNumberInput(value);
1021
+ return parsed == null ? [] : [parsed];
1022
+ }
1023
+ function updateFilterValue(state, key, nextValue) {
1024
+ const next = { ...state };
1025
+ if (nextValue.trim()) {
1026
+ next[key] = nextValue;
1027
+ } else {
1028
+ delete next[key];
1029
+ }
1030
+ return next;
1031
+ }
1032
+ function updateFilterRecord(state, key, nextValue) {
1033
+ const next = { ...state };
1034
+ if (Object.keys(nextValue).length > 0) {
1035
+ next[key] = nextValue;
1036
+ } else {
1037
+ delete next[key];
1038
+ }
1039
+ return next;
1040
+ }
1041
+ function updateNumberFilterValue(state, key, nextValue) {
1042
+ const next = { ...state };
1043
+ const hasMin = String(nextValue.min ?? "").trim() !== "";
1044
+ const hasMax = String(nextValue.max ?? "").trim() !== "";
1045
+ if (hasMin || hasMax) {
1046
+ next[key] = nextValue;
1047
+ } else {
1048
+ delete next[key];
1049
+ }
1050
+ return next;
1051
+ }
1052
+ function pruneTextFilterState(state, filters) {
1053
+ return pruneFilterState(state, filters, "text", (value) => !String(value ?? "").trim());
1054
+ }
1055
+ function pruneMultiFilterState(state, filters) {
1056
+ const allowed = new Set(
1057
+ filters.filter((filter) => filter.kind === "multi" || filter.kind === "nested-multi").map((filter) => filter.column.key)
1058
+ );
1059
+ return Object.fromEntries(
1060
+ Object.entries(state).filter(
1061
+ ([key, value]) => allowed.has(key) && Object.keys(value).length > 0
1062
+ )
1063
+ );
1064
+ }
1065
+ function pruneNumberFilterState(state, filters) {
1066
+ return pruneFilterState(
1067
+ state,
1068
+ filters,
1069
+ "number",
1070
+ (value) => !String(value.min ?? "").trim() && !String(value.max ?? "").trim()
1071
+ );
1072
+ }
1073
+ function pruneFilterState(state, filters, kind, isEmpty) {
1074
+ const allowed = new Set(
1075
+ filters.filter((filter) => filter.kind === kind).map((filter) => filter.column.key)
1076
+ );
1077
+ return Object.fromEntries(
1078
+ Object.entries(state).filter(([key, value]) => allowed.has(key) && !isEmpty(value))
1079
+ );
1080
+ }
1081
+ function resolvePath(obj, path) {
1082
+ return path.split(".").reduce((current, key) => {
1083
+ if (current && typeof current === "object") {
1084
+ return current[key];
1085
+ }
1086
+ return void 0;
1087
+ }, obj);
1088
+ }
1089
+ function formatCell(value) {
1090
+ if (value == null || value === "") {
1091
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "—" });
1092
+ }
1093
+ if (typeof value === "boolean") return value ? "True" : "False";
1094
+ if (typeof value === "object") return JSON.stringify(value);
1095
+ return String(value);
1096
+ }
1097
+ function groupTagOptions(options, separator) {
1098
+ const byKey = /* @__PURE__ */ new Map();
1099
+ for (const option of options) {
1100
+ const { key } = splitTagToken(option.value, separator);
1101
+ const list = byKey.get(key) ?? [];
1102
+ list.push(option);
1103
+ byKey.set(key, list);
1104
+ }
1105
+ return Array.from(byKey.entries()).sort(([a], [b]) => {
1106
+ if (a === "" && b !== "") return 1;
1107
+ if (b === "" && a !== "") return -1;
1108
+ return a.localeCompare(b);
1109
+ }).map(([groupKey, groupOptions]) => ({
1110
+ groupKey,
1111
+ label: groupKey === "" ? "Other" : groupKey,
1112
+ options: groupOptions
1113
+ }));
1114
+ }
1115
+ function applyKindDefaults(column, timestampFormat) {
1116
+ if (!column.kind) return column;
1117
+ if (column.kind === "timestamp") {
1118
+ const format = timestampFormat ?? "iso";
1119
+ return {
1120
+ ...column,
1121
+ render: column.render ?? ((value) => {
1122
+ var _a;
1123
+ return /* @__PURE__ */ jsx(
1124
+ Timestamp,
1125
+ {
1126
+ value,
1127
+ format,
1128
+ showTitleOnHover: ((_a = column.timestamp) == null ? void 0 : _a.alwaysShowFullOnHover) !== false
1129
+ }
1130
+ );
1131
+ }),
1132
+ sortValue: column.sortValue ?? ((value) => {
1133
+ var _a;
1134
+ return ((_a = parseTimestamp(value)) == null ? void 0 : _a.getTime()) ?? null;
1135
+ }),
1136
+ filterValue: column.filterValue ?? ((value) => {
1137
+ const parsed = parseTimestamp(value);
1138
+ return parsed ? parsed.toISOString() : "";
1139
+ })
1140
+ };
1141
+ }
1142
+ if (column.kind === "tags") {
1143
+ const opts = column.tags;
1144
+ const separator = (opts == null ? void 0 : opts.separator) ?? "=";
1145
+ return {
1146
+ ...column,
1147
+ render: column.render ?? ((value) => /* @__PURE__ */ jsx(
1148
+ TagList,
1149
+ {
1150
+ tags: normalizeTags(value, separator),
1151
+ maxVisible: (opts == null ? void 0 : opts.maxVisible) ?? 3
1152
+ }
1153
+ )),
1154
+ filterValue: column.filterValue ?? ((value) => tagFilterTokens(value, separator)),
1155
+ sortValue: column.sortValue ?? ((value) => tagFilterTokens(value, separator).length)
1156
+ };
1157
+ }
1158
+ if (column.kind === "status") {
1159
+ const opts = column.status;
1160
+ const map = (opts == null ? void 0 : opts.map) ?? ((raw) => normalizeStatus(raw));
1161
+ return {
1162
+ ...column,
1163
+ render: column.render ?? ((value, row) => {
1164
+ var _a;
1165
+ const status = map(value, row);
1166
+ if (!status) return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "—" });
1167
+ const label = (opts == null ? void 0 : opts.showLabel) ? typeof value === "string" ? value : status : void 0;
1168
+ const title = ((_a = opts == null ? void 0 : opts.title) == null ? void 0 : _a.call(opts, value, row)) ?? (typeof value === "string" ? value : void 0);
1169
+ return /* @__PURE__ */ jsx(
1170
+ StatusDot,
1171
+ {
1172
+ status,
1173
+ ...label ? { label } : {},
1174
+ ...title ? { title } : {}
1175
+ }
1176
+ );
1177
+ }),
1178
+ filterValue: column.filterValue ?? ((value, row) => {
1179
+ const status = map(value, row);
1180
+ return status ?? "";
1181
+ }),
1182
+ sortValue: column.sortValue ?? ((value, row) => map(value, row) ?? "")
1183
+ };
1184
+ }
1185
+ return column;
1186
+ }
1187
+ function prettifyKey(key) {
1188
+ return key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (value) => value.toUpperCase()).trim();
1189
+ }
1190
+ function labelText(column) {
1191
+ if (typeof column.label === "string") return column.label;
1192
+ return prettifyKey(column.key.split(".").at(-1) ?? column.key);
1193
+ }
1194
+ function isColumnHideable(column) {
1195
+ return column.hideable !== false;
1196
+ }
1197
+ function isFilterBarFilterActive(filter) {
1198
+ if (filter.kind === "text" || filter.kind === "lookup" || filter.kind === "enum") {
1199
+ return String(filter.value ?? "").trim() !== "";
1200
+ }
1201
+ if (filter.kind === "lookup-multi" || filter.kind === "select-multi") {
1202
+ return filter.value.length > 0;
1203
+ }
1204
+ if (filter.kind === "number") {
1205
+ return String(filter.value.min ?? "").trim() !== "" || String(filter.value.max ?? "").trim() !== "";
1206
+ }
1207
+ if (filter.kind === "boolean") return filter.value;
1208
+ return Object.keys(filter.value).length > 0;
1209
+ }
1210
+ function menuStateFromPointer(event, columnKey) {
1211
+ const padding = 8;
1212
+ const width = 256;
1213
+ const height = 320;
1214
+ const viewportWidth = typeof window === "undefined" ? event.clientX + width : window.innerWidth;
1215
+ const viewportHeight = typeof window === "undefined" ? event.clientY + height : window.innerHeight;
1216
+ const position = {
1217
+ x: Math.max(padding, Math.min(event.clientX, viewportWidth - width - padding)),
1218
+ y: Math.max(padding, Math.min(event.clientY, viewportHeight - height - padding))
1219
+ };
1220
+ return columnKey ? { ...position, columnKey } : position;
1221
+ }
1222
+ function menuStateFromTrigger(event, columnKey) {
1223
+ const rect = event.currentTarget.getBoundingClientRect();
1224
+ const padding = 8;
1225
+ const width = 256;
1226
+ const height = 320;
1227
+ const viewportWidth = typeof window === "undefined" ? rect.right + width : window.innerWidth;
1228
+ const viewportHeight = typeof window === "undefined" ? rect.bottom + height : window.innerHeight;
1229
+ const position = {
1230
+ x: Math.max(padding, Math.min(rect.right - width, viewportWidth - width - padding)),
1231
+ y: Math.max(padding, Math.min(rect.bottom + 6, viewportHeight - height - padding))
1232
+ };
1233
+ return columnKey ? { ...position, columnKey } : position;
1234
+ }
1235
+ function columnStyle(column, widths) {
1236
+ const width = widths[column.key];
1237
+ return width ? { width: `${width}px` } : void 0;
1238
+ }
1239
+ function measureColumnContentWidth(table, columnIndex, column) {
1240
+ const cells = Array.from(table.querySelectorAll("th, td")).filter(
1241
+ (cell) => cell instanceof HTMLTableCellElement && cell.cellIndex === columnIndex && cell.colSpan === 1
1242
+ );
1243
+ const measured = cells.reduce((current, cell) => {
1244
+ const horizontalPadding = getHorizontalPadding(cell);
1245
+ const contentWidths = Array.from(cell.children).map(
1246
+ (child) => child instanceof HTMLElement ? child.scrollWidth + horizontalPadding : 0
1247
+ );
1248
+ return Math.max(current, cell.scrollWidth, ...contentWidths);
1249
+ }, 0);
1250
+ return clampColumnWidth(column, measured || defaultColumnWidth(column));
1251
+ }
1252
+ function getHorizontalPadding(element) {
1253
+ if (typeof window === "undefined") return 0;
1254
+ const styles = window.getComputedStyle(element);
1255
+ return parseCssPixelValue(styles.paddingLeft) + parseCssPixelValue(styles.paddingRight);
1256
+ }
1257
+ function parseCssPixelValue(value) {
1258
+ const parsed = Number.parseFloat(value);
1259
+ return Number.isFinite(parsed) ? parsed : 0;
1260
+ }
1261
+ function readStoredColumnWidths(storageKey, columns) {
1262
+ if (typeof window === "undefined") return {};
1263
+ try {
1264
+ const raw = window.localStorage.getItem(storageKey);
1265
+ if (!raw) return {};
1266
+ const parsed = JSON.parse(raw);
1267
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
1268
+ return pruneColumnWidths(parsed, columns);
1269
+ } catch {
1270
+ return {};
1271
+ }
1272
+ }
1273
+ function writeStoredColumnWidths(storageKey, widths) {
1274
+ if (typeof window === "undefined") return;
1275
+ try {
1276
+ if (Object.keys(widths).length === 0) {
1277
+ window.localStorage.removeItem(storageKey);
1278
+ } else {
1279
+ window.localStorage.setItem(storageKey, JSON.stringify(widths));
1280
+ }
1281
+ } catch {
1282
+ }
1283
+ }
1284
+ function readStoredHiddenColumns(storageKey, columns) {
1285
+ if (typeof window === "undefined") return {};
1286
+ try {
1287
+ const raw = window.localStorage.getItem(storageKey);
1288
+ if (!raw) return {};
1289
+ const parsed = JSON.parse(raw);
1290
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
1291
+ return pruneHiddenColumns(parsed, columns);
1292
+ } catch {
1293
+ return {};
1294
+ }
1295
+ }
1296
+ function writeStoredHiddenColumns(storageKey, hiddenColumns) {
1297
+ if (typeof window === "undefined") return;
1298
+ try {
1299
+ if (Object.keys(hiddenColumns).length === 0) {
1300
+ window.localStorage.removeItem(storageKey);
1301
+ } else {
1302
+ window.localStorage.setItem(storageKey, JSON.stringify(hiddenColumns));
1303
+ }
1304
+ } catch {
1305
+ }
1306
+ }
1307
+ function readStoredDensityOverride(storageKey) {
1308
+ if (typeof window === "undefined") return void 0;
1309
+ try {
1310
+ const raw = window.localStorage.getItem(storageKey);
1311
+ return isDensity(raw) ? raw : void 0;
1312
+ } catch {
1313
+ return void 0;
1314
+ }
1315
+ }
1316
+ function writeStoredDensityOverride(storageKey, density) {
1317
+ if (typeof window === "undefined") return;
1318
+ try {
1319
+ if (density) {
1320
+ window.localStorage.setItem(storageKey, density);
1321
+ } else {
1322
+ window.localStorage.removeItem(storageKey);
1323
+ }
1324
+ } catch {
1325
+ }
1326
+ }
1327
+ function isDensity(value) {
1328
+ return value === "compact" || value === "comfortable" || value === "spacious";
1329
+ }
1330
+ function pruneColumnWidths(widths, columns) {
1331
+ const byKey = new Map(columns.map((column) => [column.key, column]));
1332
+ const next = {};
1333
+ for (const [key, width] of Object.entries(widths)) {
1334
+ const column = byKey.get(key);
1335
+ if (!column || typeof width !== "number" || !Number.isFinite(width)) continue;
1336
+ next[key] = clampColumnWidth(column, width);
1337
+ }
1338
+ return next;
1339
+ }
1340
+ function pruneHiddenColumns(hiddenColumns, columns) {
1341
+ const byKey = new Map(columns.map((column) => [column.key, column]));
1342
+ const next = {};
1343
+ for (const [key, hidden] of Object.entries(hiddenColumns)) {
1344
+ const column = byKey.get(key);
1345
+ if (!column || hidden !== true || !isColumnHideable(column)) continue;
1346
+ next[key] = true;
1347
+ }
1348
+ const hideable = columns.filter(isColumnHideable);
1349
+ const visibleHideableCount = hideable.filter((column) => next[column.key] !== true).length;
1350
+ if (hideable.length > 0 && visibleHideableCount === 0) {
1351
+ delete next[hideable[0].key];
1352
+ }
1353
+ return next;
1354
+ }
1355
+ function sameColumnWidths(left, right) {
1356
+ const leftKeys = Object.keys(left);
1357
+ const rightKeys = Object.keys(right);
1358
+ return leftKeys.length === rightKeys.length && leftKeys.every(
1359
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && left[key] === right[key]
1360
+ );
1361
+ }
1362
+ function sameHiddenColumns(left, right) {
1363
+ const leftKeys = Object.keys(left);
1364
+ const rightKeys = Object.keys(right);
1365
+ return leftKeys.length === rightKeys.length && leftKeys.every(
1366
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && left[key] === right[key]
1367
+ );
1368
+ }
1369
+ function defaultColumnWidth(column) {
1370
+ if (column.grow) return DEFAULT_GROW_COLUMN_WIDTH;
1371
+ if (column.shrink) return DEFAULT_SHRINK_COLUMN_WIDTH;
1372
+ return DEFAULT_COLUMN_WIDTH;
1373
+ }
1374
+ function clampColumnWidth(column, width) {
1375
+ const minWidth = column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH;
1376
+ const maxWidth = column.maxWidth;
1377
+ const minimum = Number.isFinite(minWidth) ? Math.max(1, minWidth) : DEFAULT_COLUMN_MIN_WIDTH;
1378
+ const maximum = maxWidth != null && Number.isFinite(maxWidth) ? Math.max(minimum, maxWidth) : Infinity;
1379
+ return Math.round(Math.max(minimum, Math.min(maximum, width)));
1380
+ }
1381
+ function getNumericFilterBounds(rows, column) {
1382
+ const values = rows.flatMap(
1383
+ (record) => collectFilterValues(getFilterCandidate(record.row, column))
1384
+ );
1385
+ const populated = values.filter(hasFilterValue);
1386
+ const numericValues = populated.map((value) => parseNumberInput(value)).filter((value) => value != null);
1387
+ if (populated.length === 0 || numericValues.length !== populated.length) {
1388
+ return null;
1389
+ }
1390
+ return {
1391
+ min: Math.min(...numericValues),
1392
+ max: Math.max(...numericValues),
1393
+ step: inferNumericStep(numericValues)
1394
+ };
1395
+ }
1396
+ function collectFilterValues(value) {
1397
+ if (Array.isArray(value)) {
1398
+ return value.flatMap((item) => collectFilterValues(item));
1399
+ }
1400
+ return [value];
1401
+ }
1402
+ function hasFilterValue(value) {
1403
+ return value != null && !(typeof value === "string" && value.trim() === "");
1404
+ }
1405
+ function parseNumberInput(value) {
1406
+ if (typeof value === "number") {
1407
+ return Number.isFinite(value) ? value : null;
1408
+ }
1409
+ if (typeof value !== "string") {
1410
+ return null;
1411
+ }
1412
+ const trimmed = value.trim();
1413
+ if (!trimmed) return null;
1414
+ const parsed = Number(trimmed);
1415
+ return Number.isFinite(parsed) ? parsed : null;
1416
+ }
1417
+ function inferNumericStep(values) {
1418
+ if (values.every(Number.isInteger)) {
1419
+ return 1;
1420
+ }
1421
+ const maxFractionDigits = values.reduce((current, value) => {
1422
+ const [, fraction = ""] = String(value).split(".");
1423
+ return Math.max(current, fraction.length);
1424
+ }, 0);
1425
+ return 10 ** -Math.min(maxFractionDigits || 2, 6);
1426
+ }
1427
+ function alignmentClass(align) {
1428
+ if (align === "right") return "text-right";
1429
+ if (align === "center") return "text-center";
1430
+ return "text-left";
1431
+ }
1432
+ function headerAlignmentClass(align) {
1433
+ if (align === "right") return "justify-end";
1434
+ if (align === "center") return "justify-center";
1435
+ return "justify-start";
1436
+ }
1437
+ function cellContentStyle(width) {
1438
+ return width ? { maxWidth: `${width}px` } : void 0;
1439
+ }
1440
+ function cellContentClassName(column, width) {
1441
+ const resized = width !== void 0;
1442
+ const base = "w-full truncate";
1443
+ if (column.grow) return cn(base, resized ? "min-w-0" : "min-w-56 max-w-[36rem]");
1444
+ if (column.shrink) return cn(base, "min-w-0 whitespace-nowrap", !resized && "max-w-[16rem]");
1445
+ return cn(base, "min-w-0", !resized && "max-w-[18rem]");
1446
+ }
1447
+ function inferColumns(data) {
1448
+ if (data.length === 0) return [];
1449
+ const keys = /* @__PURE__ */ new Set();
1450
+ for (const row of data.slice(0, 20)) {
1451
+ Object.keys(row).filter((key) => !key.startsWith("_")).forEach((key) => keys.add(key));
1452
+ }
1453
+ return Array.from(keys).map((key) => ({
1454
+ key,
1455
+ label: prettifyKey(key),
1456
+ sortable: true,
1457
+ filterable: true
1458
+ }));
1459
+ }
1460
+ export {
1461
+ DataTable,
1462
+ inferColumns
1463
+ };
1464
+ //# sourceMappingURL=DataTable.js.map