@lattice-php/lattice 0.1.0 → 0.2.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 (367) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +8 -0
  2. package/dist/action/components/action-form.d.ts +24 -0
  3. package/dist/action/components/action-form.js +270 -0
  4. package/dist/action/components/action-form.js.map +1 -0
  5. package/dist/action/components/action-group.d.ts +1 -8
  6. package/dist/action/components/action-group.js +24 -66
  7. package/dist/action/components/action-group.js.map +1 -1
  8. package/dist/action/components/action.d.ts +1 -24
  9. package/dist/action/components/action.js +61 -46
  10. package/dist/action/components/action.js.map +1 -1
  11. package/dist/action/effects.d.ts +6 -25
  12. package/dist/action/effects.js +2 -2
  13. package/dist/action/effects.js.map +1 -1
  14. package/dist/action/index.d.ts +1 -1
  15. package/dist/core/components/badge.d.ts +1 -8
  16. package/dist/core/components/badge.js +2 -3
  17. package/dist/core/components/badge.js.map +1 -1
  18. package/dist/core/components/button.d.ts +4 -12
  19. package/dist/core/components/button.js +6 -9
  20. package/dist/core/components/button.js.map +1 -1
  21. package/dist/core/components/card.d.ts +1 -9
  22. package/dist/core/components/card.js +1 -3
  23. package/dist/core/components/card.js.map +1 -1
  24. package/dist/core/components/confirm-dialog.d.ts +2 -3
  25. package/dist/core/components/confirm-dialog.js +19 -13
  26. package/dist/core/components/confirm-dialog.js.map +1 -1
  27. package/dist/core/components/fragment.d.ts +1 -10
  28. package/dist/core/components/fragment.js +5 -6
  29. package/dist/core/components/fragment.js.map +1 -1
  30. package/dist/core/components/grid.d.ts +1 -8
  31. package/dist/core/components/grid.js +1 -2
  32. package/dist/core/components/grid.js.map +1 -1
  33. package/dist/core/components/heading.d.ts +1 -9
  34. package/dist/core/components/heading.js +2 -3
  35. package/dist/core/components/heading.js.map +1 -1
  36. package/dist/core/components/icon.d.ts +3 -0
  37. package/dist/core/components/icon.js +30 -0
  38. package/dist/core/components/icon.js.map +1 -0
  39. package/dist/core/components/index.d.ts +1 -1
  40. package/dist/core/components/index.js +4 -0
  41. package/dist/core/components/index.js.map +1 -1
  42. package/dist/core/components/link.d.ts +1 -12
  43. package/dist/core/components/link.js +4 -9
  44. package/dist/core/components/link.js.map +1 -1
  45. package/dist/core/components/modal.d.ts +1 -11
  46. package/dist/core/components/modal.js +27 -31
  47. package/dist/core/components/modal.js.map +1 -1
  48. package/dist/core/components/section.d.ts +3 -0
  49. package/dist/core/components/section.js +79 -0
  50. package/dist/core/components/section.js.map +1 -0
  51. package/dist/core/components/segmented-control.d.ts +1 -14
  52. package/dist/core/components/segmented-control.js +4 -7
  53. package/dist/core/components/segmented-control.js.map +1 -1
  54. package/dist/core/components/segmented-pills.d.ts +4 -2
  55. package/dist/core/components/segmented-pills.js +10 -1
  56. package/dist/core/components/segmented-pills.js.map +1 -1
  57. package/dist/core/components/spinner.js +8 -4
  58. package/dist/core/components/spinner.js.map +1 -1
  59. package/dist/core/components/stack.d.ts +1 -11
  60. package/dist/core/components/stack.js +5 -5
  61. package/dist/core/components/stack.js.map +1 -1
  62. package/dist/core/components/tabs.d.ts +1 -19
  63. package/dist/core/components/tabs.js +45 -21
  64. package/dist/core/components/tabs.js.map +1 -1
  65. package/dist/core/components/text.d.ts +1 -9
  66. package/dist/core/components/text.js +2 -3
  67. package/dist/core/components/text.js.map +1 -1
  68. package/dist/core/registry.d.ts +9 -3
  69. package/dist/core/registry.js +21 -5
  70. package/dist/core/registry.js.map +1 -1
  71. package/dist/core/renderer.js +7 -13
  72. package/dist/core/renderer.js.map +1 -1
  73. package/dist/core/types.d.ts +54 -26
  74. package/dist/form/components/base/checkbox.js +5 -2
  75. package/dist/form/components/base/checkbox.js.map +1 -1
  76. package/dist/form/components/base/field.d.ts +2 -1
  77. package/dist/form/components/base/field.js +5 -1
  78. package/dist/form/components/base/field.js.map +1 -1
  79. package/dist/form/components/base/password-input.js +9 -2
  80. package/dist/form/components/base/password-input.js.map +1 -1
  81. package/dist/form/components/base/submit-button.d.ts +4 -4
  82. package/dist/form/components/base/submit-button.js +2 -2
  83. package/dist/form/components/base/submit-button.js.map +1 -1
  84. package/dist/form/components/conditions.d.ts +6 -9
  85. package/dist/form/components/conditions.js +10 -2
  86. package/dist/form/components/conditions.js.map +1 -1
  87. package/dist/form/components/context.d.ts +0 -4
  88. package/dist/form/components/context.js +1 -5
  89. package/dist/form/components/context.js.map +1 -1
  90. package/dist/form/components/field-props.d.ts +24 -0
  91. package/dist/form/components/field-props.js +15 -0
  92. package/dist/form/components/field-props.js.map +1 -0
  93. package/dist/form/components/fields/checkbox.d.ts +1 -15
  94. package/dist/form/components/fields/checkbox.js +16 -21
  95. package/dist/form/components/fields/checkbox.js.map +1 -1
  96. package/dist/form/components/fields/choice.d.ts +1 -13
  97. package/dist/form/components/fields/choice.js +13 -20
  98. package/dist/form/components/fields/choice.js.map +1 -1
  99. package/dist/form/components/fields/date-input.d.ts +1 -19
  100. package/dist/form/components/fields/date-input.js +11 -16
  101. package/dist/form/components/fields/date-input.js.map +1 -1
  102. package/dist/form/components/fields/hidden-input.d.ts +1 -9
  103. package/dist/form/components/fields/hidden-input.js +2 -3
  104. package/dist/form/components/fields/hidden-input.js.map +1 -1
  105. package/dist/form/components/fields/number-input.d.ts +1 -22
  106. package/dist/form/components/fields/number-input.js +38 -41
  107. package/dist/form/components/fields/number-input.js.map +1 -1
  108. package/dist/form/components/fields/password-input.d.ts +1 -28
  109. package/dist/form/components/fields/password-input.js +15 -24
  110. package/dist/form/components/fields/password-input.js.map +1 -1
  111. package/dist/form/components/fields/rich-editor.d.ts +1 -16
  112. package/dist/form/components/fields/rich-editor.js +57 -47
  113. package/dist/form/components/fields/rich-editor.js.map +1 -1
  114. package/dist/form/components/fields/select.d.ts +1 -22
  115. package/dist/form/components/fields/select.js +85 -74
  116. package/dist/form/components/fields/select.js.map +1 -1
  117. package/dist/form/components/fields/simple-field.d.ts +9 -0
  118. package/dist/form/components/fields/simple-field.js +22 -0
  119. package/dist/form/components/fields/simple-field.js.map +1 -0
  120. package/dist/form/components/fields/text-input.d.ts +1 -20
  121. package/dist/form/components/fields/text-input.js +12 -17
  122. package/dist/form/components/fields/text-input.js.map +1 -1
  123. package/dist/form/components/fields/textarea.d.ts +1 -19
  124. package/dist/form/components/fields/textarea.js +11 -16
  125. package/dist/form/components/fields/textarea.js.map +1 -1
  126. package/dist/form/components/form.d.ts +1 -20
  127. package/dist/form/components/form.js +29 -36
  128. package/dist/form/components/form.js.map +1 -1
  129. package/dist/form/components/index.d.ts +0 -1
  130. package/dist/form/components/index.js +1 -2
  131. package/dist/form/components/resolved-nodes.d.ts +1 -1
  132. package/dist/form/components/resolved-nodes.js +2 -2
  133. package/dist/form/components/resolved-nodes.js.map +1 -1
  134. package/dist/form/components/types.d.ts +1 -0
  135. package/dist/form/components/use-controlled-field.d.ts +3 -9
  136. package/dist/form/components/use-controlled-field.js +5 -9
  137. package/dist/form/components/use-controlled-field.js.map +1 -1
  138. package/dist/form/components/use-dependent-field.d.ts +1 -1
  139. package/dist/form/components/use-dependent-field.js +8 -8
  140. package/dist/form/components/use-dependent-field.js.map +1 -1
  141. package/dist/form/components/use-form-resolver.d.ts +1 -1
  142. package/dist/form/components/use-form-resolver.js +8 -13
  143. package/dist/form/components/use-form-resolver.js.map +1 -1
  144. package/dist/form/components/use-seed-default.d.ts +5 -0
  145. package/dist/form/components/use-seed-default.js +23 -0
  146. package/dist/form/components/use-seed-default.js.map +1 -0
  147. package/dist/form/index.d.ts +1 -1
  148. package/dist/form/index.js +0 -1
  149. package/dist/form/index.js.map +1 -1
  150. package/dist/form/skeleton.d.ts +1 -1
  151. package/dist/form/skeleton.js +1 -1
  152. package/dist/form/skeleton.js.map +1 -1
  153. package/dist/i18n/backend.d.ts +24 -0
  154. package/dist/i18n/backend.js +39 -0
  155. package/dist/i18n/backend.js.map +1 -0
  156. package/dist/i18n/index.d.ts +3 -0
  157. package/dist/i18n/index.js +3 -0
  158. package/dist/i18n/instance.js +48 -0
  159. package/dist/i18n/instance.js.map +1 -0
  160. package/dist/icons/icon-renderer.js +30 -5
  161. package/dist/icons/icon-renderer.js.map +1 -1
  162. package/dist/icons/index.d.ts +2 -0
  163. package/dist/icons/index.js +2 -1
  164. package/dist/icons/sprite.d.ts +30 -0
  165. package/dist/icons/sprite.js +40 -0
  166. package/dist/icons/sprite.js.map +1 -0
  167. package/dist/index.d.ts +9 -5
  168. package/dist/index.js +7 -3
  169. package/dist/inertia.d.ts +1 -6
  170. package/dist/inertia.js +4 -8
  171. package/dist/inertia.js.map +1 -1
  172. package/dist/lattice.css +129 -5
  173. package/dist/layout/components.d.ts +1 -0
  174. package/dist/layout/components.js +19 -0
  175. package/dist/layout/components.js.map +1 -0
  176. package/dist/layout/context.d.ts +12 -0
  177. package/dist/layout/context.js +19 -0
  178. package/dist/layout/context.js.map +1 -0
  179. package/dist/layout/index.d.ts +3 -0
  180. package/dist/layout/index.js +4 -0
  181. package/dist/layout/menu-item.d.ts +3 -0
  182. package/dist/layout/menu-item.js +130 -0
  183. package/dist/layout/menu-item.js.map +1 -0
  184. package/dist/layout/menu.d.ts +3 -0
  185. package/dist/layout/menu.js +13 -0
  186. package/dist/layout/menu.js.map +1 -0
  187. package/dist/layout/outlet.d.ts +6 -0
  188. package/dist/layout/outlet.js +14 -0
  189. package/dist/layout/outlet.js.map +1 -0
  190. package/dist/layout/schema-layout.d.ts +10 -0
  191. package/dist/layout/schema-layout.js +30 -0
  192. package/dist/layout/schema-layout.js.map +1 -0
  193. package/dist/layout/sidebar.d.ts +3 -0
  194. package/dist/layout/sidebar.js +48 -0
  195. package/dist/layout/sidebar.js.map +1 -0
  196. package/dist/lib/utils.d.ts +0 -2
  197. package/dist/lib/utils.js +1 -4
  198. package/dist/lib/utils.js.map +1 -1
  199. package/dist/node_modules/i18next/dist/esm/i18next.js +1982 -0
  200. package/dist/node_modules/i18next/dist/esm/i18next.js.map +1 -0
  201. package/dist/node_modules/i18next-http-backend/esm/index.js +352 -0
  202. package/dist/node_modules/i18next-http-backend/esm/index.js.map +1 -0
  203. package/dist/node_modules/react-i18next/dist/es/context.js +23 -0
  204. package/dist/node_modules/react-i18next/dist/es/context.js.map +1 -0
  205. package/dist/node_modules/react-i18next/dist/es/defaults.js +29 -0
  206. package/dist/node_modules/react-i18next/dist/es/defaults.js.map +1 -0
  207. package/dist/node_modules/react-i18next/dist/es/i18nInstance.js +10 -0
  208. package/dist/node_modules/react-i18next/dist/es/i18nInstance.js.map +1 -0
  209. package/dist/node_modules/react-i18next/dist/es/initReactI18next.js +14 -0
  210. package/dist/node_modules/react-i18next/dist/es/initReactI18next.js.map +1 -0
  211. package/dist/node_modules/react-i18next/dist/es/unescape.js +30 -0
  212. package/dist/node_modules/react-i18next/dist/es/unescape.js.map +1 -0
  213. package/dist/node_modules/react-i18next/dist/es/useTranslation.js +157 -0
  214. package/dist/node_modules/react-i18next/dist/es/useTranslation.js.map +1 -0
  215. package/dist/node_modules/react-i18next/dist/es/utils.js +58 -0
  216. package/dist/node_modules/react-i18next/dist/es/utils.js.map +1 -0
  217. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js +70 -0
  218. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +1 -0
  219. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js +61 -0
  220. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +1 -0
  221. package/dist/node_modules/use-sync-external-store/shim/index.js +13 -0
  222. package/dist/node_modules/use-sync-external-store/shim/index.js.map +1 -0
  223. package/dist/page.d.ts +1 -1
  224. package/dist/page.js +2 -2
  225. package/dist/page.js.map +1 -1
  226. package/dist/provider.d.ts +8 -3
  227. package/dist/provider.js +17 -9
  228. package/dist/provider.js.map +1 -1
  229. package/dist/registry.d.ts +1 -1
  230. package/dist/registry.js +2 -1
  231. package/dist/registry.js.map +1 -1
  232. package/dist/table/bulk.d.ts +6 -10
  233. package/dist/table/bulk.js +13 -35
  234. package/dist/table/bulk.js.map +1 -1
  235. package/dist/table/column-registry.d.ts +9 -0
  236. package/dist/table/components/bulk-bar.js +34 -3
  237. package/dist/table/components/bulk-bar.js.map +1 -1
  238. package/dist/table/components/cells/badge-cell.d.ts +5 -0
  239. package/dist/table/components/cells/badge-cell.js +16 -0
  240. package/dist/table/components/cells/badge-cell.js.map +1 -0
  241. package/dist/table/components/cells/icon-cell.d.ts +5 -0
  242. package/dist/table/components/cells/icon-cell.js +22 -0
  243. package/dist/table/components/cells/icon-cell.js.map +1 -0
  244. package/dist/table/components/cells/image-cell.d.ts +5 -0
  245. package/dist/table/components/cells/image-cell.js +24 -0
  246. package/dist/table/components/cells/image-cell.js.map +1 -0
  247. package/dist/table/components/cells/text-cell.d.ts +6 -0
  248. package/dist/table/components/cells/text-cell.js +50 -0
  249. package/dist/table/components/cells/text-cell.js.map +1 -0
  250. package/dist/table/components/column-filter-control.js +59 -96
  251. package/dist/table/components/column-filter-control.js.map +1 -1
  252. package/dist/table/components/column-header.js +22 -11
  253. package/dist/table/components/column-header.js.map +1 -1
  254. package/dist/table/components/filter-stack-bar.d.ts +2 -2
  255. package/dist/table/components/filter-stack-bar.js +10 -8
  256. package/dist/table/components/filter-stack-bar.js.map +1 -1
  257. package/dist/table/components/filter-value-input.d.ts +5 -3
  258. package/dist/table/components/filter-value-input.js +25 -16
  259. package/dist/table/components/filter-value-input.js.map +1 -1
  260. package/dist/table/components/pagination.d.ts +1 -1
  261. package/dist/table/components/pagination.js +20 -8
  262. package/dist/table/components/pagination.js.map +1 -1
  263. package/dist/table/components/sort-bar.d.ts +2 -2
  264. package/dist/table/components/sort-bar.js +12 -10
  265. package/dist/table/components/sort-bar.js.map +1 -1
  266. package/dist/table/components/table-action-node.d.ts +1 -1
  267. package/dist/table/components/table-action-node.js +1 -1
  268. package/dist/table/components/table-action-node.js.map +1 -1
  269. package/dist/table/components/table-cell.d.ts +1 -1
  270. package/dist/table/components/table-cell.js +24 -43
  271. package/dist/table/components/table-cell.js.map +1 -1
  272. package/dist/table/components/table.d.ts +6 -2
  273. package/dist/table/components/table.js +40 -17
  274. package/dist/table/components/table.js.map +1 -1
  275. package/dist/table/format.js +5 -3
  276. package/dist/table/format.js.map +1 -1
  277. package/dist/table/index.d.ts +1 -1
  278. package/dist/table/index.js.map +1 -1
  279. package/dist/table/payload.d.ts +1 -1
  280. package/dist/table/query.d.ts +0 -1
  281. package/dist/table/query.js +8 -9
  282. package/dist/table/query.js.map +1 -1
  283. package/dist/table/types.d.ts +38 -42
  284. package/dist/table/use-table.d.ts +3 -4
  285. package/dist/table/use-table.js +12 -23
  286. package/dist/table/use-table.js.map +1 -1
  287. package/dist/test-support.d.ts +14 -0
  288. package/dist/test-support.js +14 -0
  289. package/dist/test-support.js.map +1 -0
  290. package/dist/toast/index.d.ts +1 -0
  291. package/dist/toast/index.js +2 -0
  292. package/dist/toast/toaster.d.ts +3 -0
  293. package/dist/toast/toaster.js +126 -0
  294. package/dist/toast/toaster.js.map +1 -0
  295. package/dist/types/generated.d.ts +677 -0
  296. package/dist/types/generated.js +0 -0
  297. package/dist/types/index.d.ts +1 -1
  298. package/package.json +18 -3
  299. package/resources/icons/align-center.svg +17 -0
  300. package/resources/icons/align-justify.svg +17 -0
  301. package/resources/icons/align-left.svg +17 -0
  302. package/resources/icons/align-right.svg +17 -0
  303. package/resources/icons/arrow-down.svg +16 -0
  304. package/resources/icons/arrow-up.svg +16 -0
  305. package/resources/icons/bold.svg +15 -0
  306. package/resources/icons/check.svg +15 -0
  307. package/resources/icons/chevron-down.svg +15 -0
  308. package/resources/icons/chevron-right.svg +15 -0
  309. package/resources/icons/chevrons-up-down.svg +16 -0
  310. package/resources/icons/circle-alert.svg +17 -0
  311. package/resources/icons/circle-check.svg +16 -0
  312. package/resources/icons/circle-help.svg +17 -0
  313. package/resources/icons/circle-x.svg +17 -0
  314. package/resources/icons/code.svg +16 -0
  315. package/resources/icons/columns-3.svg +17 -0
  316. package/resources/icons/copy.svg +16 -0
  317. package/resources/icons/external-link.svg +17 -0
  318. package/resources/icons/eye-off.svg +18 -0
  319. package/resources/icons/eye.svg +16 -0
  320. package/resources/icons/filter.svg +15 -0
  321. package/resources/icons/heading-1.svg +18 -0
  322. package/resources/icons/heading-2.svg +18 -0
  323. package/resources/icons/heading-3.svg +19 -0
  324. package/resources/icons/highlighter.svg +16 -0
  325. package/resources/icons/info.svg +17 -0
  326. package/resources/icons/italic.svg +17 -0
  327. package/resources/icons/layout-dashboard.svg +18 -0
  328. package/resources/icons/link.svg +16 -0
  329. package/resources/icons/list-ordered.svg +20 -0
  330. package/resources/icons/list.svg +20 -0
  331. package/resources/icons/loader-2.svg +15 -0
  332. package/resources/icons/minus.svg +15 -0
  333. package/resources/icons/more-horizontal.svg +17 -0
  334. package/resources/icons/panel-left.svg +16 -0
  335. package/resources/icons/pencil-line.svg +17 -0
  336. package/resources/icons/pencil.svg +16 -0
  337. package/resources/icons/plus.svg +16 -0
  338. package/resources/icons/quote.svg +16 -0
  339. package/resources/icons/rows-3.svg +17 -0
  340. package/resources/icons/search.svg +16 -0
  341. package/resources/icons/send.svg +16 -0
  342. package/resources/icons/settings.svg +16 -0
  343. package/resources/icons/smile.svg +18 -0
  344. package/resources/icons/strikethrough.svg +17 -0
  345. package/resources/icons/table.svg +18 -0
  346. package/resources/icons/trash-2.svg +19 -0
  347. package/resources/icons/underline.svg +16 -0
  348. package/resources/icons/x.svg +16 -0
  349. package/dist/core/props.d.ts +0 -14
  350. package/dist/core/props.js +0 -30
  351. package/dist/core/props.js.map +0 -1
  352. package/dist/form/components/fields/submit-button.d.ts +0 -10
  353. package/dist/form/components/fields/submit-button.js +0 -14
  354. package/dist/form/components/fields/submit-button.js.map +0 -1
  355. package/dist/generated/types.d.ts +0 -17
  356. package/dist/icons/default-icons.d.ts +0 -3
  357. package/dist/icons/default-icons.js +0 -44
  358. package/dist/icons/default-icons.js.map +0 -1
  359. package/dist/icons/dynamic-lucide-renderer.d.ts +0 -2
  360. package/dist/icons/dynamic-lucide-renderer.js +0 -18
  361. package/dist/icons/dynamic-lucide-renderer.js.map +0 -1
  362. package/dist/menu/index.d.ts +0 -1
  363. package/dist/menu/index.js +0 -2
  364. package/dist/menu/use-menu.d.ts +0 -2
  365. package/dist/menu/use-menu.js +0 -9
  366. package/dist/menu/use-menu.js.map +0 -1
  367. /package/dist/{generated/types.js → table/column-registry.js} +0 -0
@@ -1,34 +1,45 @@
1
+ import { Icon } from "../../icons/sprite.js";
1
2
  import { getColumnAriaSort, getColumnSort } from "../query.js";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
4
4
  //#region resources/js/table/components/column-header.tsx
5
5
  function SortIndicator({ sort }) {
6
- if (sort?.direction === "asc") return /* @__PURE__ */ jsx(ArrowUp, {
6
+ if (sort?.direction === "asc") return /* @__PURE__ */ jsx(Icon, {
7
+ name: "arrow-up",
7
8
  "aria-hidden": "true",
8
- className: "size-3.5"
9
+ className: "size-lt-icon-sm shrink-0"
9
10
  });
10
- if (sort?.direction === "desc") return /* @__PURE__ */ jsx(ArrowDown, {
11
+ if (sort?.direction === "desc") return /* @__PURE__ */ jsx(Icon, {
12
+ name: "arrow-down",
11
13
  "aria-hidden": "true",
12
- className: "size-3.5"
14
+ className: "size-lt-icon-sm shrink-0"
13
15
  });
14
- return /* @__PURE__ */ jsx(ChevronsUpDown, {
16
+ return /* @__PURE__ */ jsx(Icon, {
17
+ name: "chevrons-up-down",
15
18
  "aria-hidden": "true",
16
- className: "size-3.5 opacity-50"
19
+ className: "size-lt-icon-sm shrink-0 opacity-50"
17
20
  });
18
21
  }
19
22
  function ColumnHeader({ column, processing, sort, state }) {
20
23
  const columnSort = getColumnSort(state, column);
21
24
  return /* @__PURE__ */ jsx("div", {
22
25
  "aria-sort": getColumnAriaSort(columnSort),
23
- className: "px-4 py-3 text-left align-middle font-medium text-lt-muted-fg",
26
+ className: "min-w-0 px-4 py-3 text-left align-middle font-medium text-lt-muted-fg",
24
27
  role: "columnheader",
25
28
  children: column.sortable ? /* @__PURE__ */ jsxs("button", {
26
29
  type: "button",
27
- className: "inline-flex items-center gap-1.5 font-medium",
30
+ "aria-label": `Sort ${column.label}`,
31
+ className: "flex w-full items-center gap-1.5 font-medium",
32
+ "data-test": `sort-${column.key}`,
28
33
  disabled: processing,
29
34
  onClick: () => sort(column),
30
- children: [`Sort ${column.label}`, /* @__PURE__ */ jsx(SortIndicator, { sort: columnSort })]
31
- }) : /* @__PURE__ */ jsx("span", { children: column.label })
35
+ children: [/* @__PURE__ */ jsx("span", {
36
+ className: "min-w-0 flex-1 truncate text-left",
37
+ children: column.label
38
+ }), /* @__PURE__ */ jsx(SortIndicator, { sort: columnSort })]
39
+ }) : /* @__PURE__ */ jsx("span", {
40
+ className: "block truncate",
41
+ children: column.label
42
+ })
32
43
  });
33
44
  }
34
45
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"column-header.js","names":[],"sources":["../../../resources/js/table/components/column-header.tsx"],"sourcesContent":["import { ArrowDown, ArrowUp, ChevronsUpDown } from \"lucide-react\";\nimport { getColumnAriaSort, getColumnSort } from \"../query\";\nimport type { TableColumn, TableSort, TableState } from \"../types\";\n\nfunction SortIndicator({ sort }: { sort: TableSort | undefined }) {\n if (sort?.direction === \"asc\") {\n return <ArrowUp aria-hidden=\"true\" className=\"size-3.5\" />;\n }\n\n if (sort?.direction === \"desc\") {\n return <ArrowDown aria-hidden=\"true\" className=\"size-3.5\" />;\n }\n\n return <ChevronsUpDown aria-hidden=\"true\" className=\"size-3.5 opacity-50\" />;\n}\n\nexport function ColumnHeader({\n column,\n processing,\n sort,\n state,\n}: {\n column: TableColumn;\n processing: boolean;\n sort: (column: TableColumn) => void;\n state: TableState;\n}) {\n const columnSort = getColumnSort(state, column);\n\n return (\n <div\n aria-sort={getColumnAriaSort(columnSort)}\n className=\"px-4 py-3 text-left align-middle font-medium text-lt-muted-fg\"\n role=\"columnheader\"\n >\n {column.sortable ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1.5 font-medium\"\n disabled={processing}\n onClick={() => sort(column)}\n >\n {`Sort ${column.label}`}\n <SortIndicator sort={columnSort} />\n </button>\n ) : (\n <span>{column.label}</span>\n )}\n </div>\n );\n}\n"],"mappings":";;;;AAIA,SAAS,cAAc,EAAE,QAAyC;CAChE,IAAI,MAAM,cAAc,OACtB,OAAO,oBAAC,SAAD;EAAS,eAAY;EAAO,WAAU;CAAY,CAAA;CAG3D,IAAI,MAAM,cAAc,QACtB,OAAO,oBAAC,WAAD;EAAW,eAAY;EAAO,WAAU;CAAY,CAAA;CAG7D,OAAO,oBAAC,gBAAD;EAAgB,eAAY;EAAO,WAAU;CAAuB,CAAA;AAC7E;AAEA,SAAgB,aAAa,EAC3B,QACA,YACA,MACA,SAMC;CACD,MAAM,aAAa,cAAc,OAAO,MAAM;CAE9C,OACE,oBAAC,OAAD;EACE,aAAW,kBAAkB,UAAU;EACvC,WAAU;EACV,MAAK;YAEJ,OAAO,WACN,qBAAC,UAAD;GACE,MAAK;GACL,WAAU;GACV,UAAU;GACV,eAAe,KAAK,MAAM;aAJ5B,CAMG,QAAQ,OAAO,SAChB,oBAAC,eAAD,EAAe,MAAM,WAAa,CAAA,CAC5B;OAER,oBAAC,QAAD,EAAA,UAAO,OAAO,MAAY,CAAA;CAEzB,CAAA;AAET"}
1
+ {"version":3,"file":"column-header.js","names":[],"sources":["../../../resources/js/table/components/column-header.tsx"],"sourcesContent":["import { Icon } from \"@lattice/lattice/icons\";\nimport { getColumnAriaSort, getColumnSort } from \"../query\";\nimport type { TableColumn, TableSort, TableState } from \"../types\";\n\nfunction SortIndicator({ sort }: { sort: TableSort | undefined }) {\n if (sort?.direction === \"asc\") {\n return <Icon name=\"arrow-up\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />;\n }\n\n if (sort?.direction === \"desc\") {\n return <Icon name=\"arrow-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />;\n }\n\n return (\n <Icon\n name=\"chevrons-up-down\"\n aria-hidden=\"true\"\n className=\"size-lt-icon-sm shrink-0 opacity-50\"\n />\n );\n}\n\nexport function ColumnHeader({\n column,\n processing,\n sort,\n state,\n}: {\n column: TableColumn;\n processing: boolean;\n sort: (column: TableColumn) => void;\n state: TableState;\n}) {\n const columnSort = getColumnSort(state, column);\n\n return (\n <div\n aria-sort={getColumnAriaSort(columnSort)}\n className=\"min-w-0 px-4 py-3 text-left align-middle font-medium text-lt-muted-fg\"\n role=\"columnheader\"\n >\n {column.sortable ? (\n <button\n type=\"button\"\n aria-label={`Sort ${column.label}`}\n className=\"flex w-full items-center gap-1.5 font-medium\"\n data-test={`sort-${column.key}`}\n disabled={processing}\n onClick={() => sort(column)}\n >\n <span className=\"min-w-0 flex-1 truncate text-left\">{column.label}</span>\n <SortIndicator sort={columnSort} />\n </button>\n ) : (\n <span className=\"block truncate\">{column.label}</span>\n )}\n </div>\n );\n}\n"],"mappings":";;;;AAIA,SAAS,cAAc,EAAE,QAAyC;CAChE,IAAI,MAAM,cAAc,OACtB,OAAO,oBAAC,MAAD;EAAM,MAAK;EAAW,eAAY;EAAO,WAAU;CAA4B,CAAA;CAGxF,IAAI,MAAM,cAAc,QACtB,OAAO,oBAAC,MAAD;EAAM,MAAK;EAAa,eAAY;EAAO,WAAU;CAA4B,CAAA;CAG1F,OACE,oBAAC,MAAD;EACE,MAAK;EACL,eAAY;EACZ,WAAU;CACX,CAAA;AAEL;AAEA,SAAgB,aAAa,EAC3B,QACA,YACA,MACA,SAMC;CACD,MAAM,aAAa,cAAc,OAAO,MAAM;CAE9C,OACE,oBAAC,OAAD;EACE,aAAW,kBAAkB,UAAU;EACvC,WAAU;EACV,MAAK;YAEJ,OAAO,WACN,qBAAC,UAAD;GACE,MAAK;GACL,cAAY,QAAQ,OAAO;GAC3B,WAAU;GACV,aAAW,QAAQ,OAAO;GAC1B,UAAU;GACV,eAAe,KAAK,MAAM;aAN5B,CAQE,oBAAC,QAAD;IAAM,WAAU;cAAqC,OAAO;GAAY,CAAA,GACxE,oBAAC,eAAD,EAAe,MAAM,WAAa,CAAA,CAC5B;OAER,oBAAC,QAAD;GAAM,WAAU;aAAkB,OAAO;EAAY,CAAA;CAEpD,CAAA;AAET"}
@@ -1,7 +1,7 @@
1
1
  import { FilterClause, TableColumn } from '../types';
2
- export declare function FilterStackBar({ filters, columns, processing, onRemove, }: {
2
+ export declare function FilterStackBar({ filters, columnsByKey, processing, onRemove, }: {
3
3
  filters: FilterClause[];
4
- columns: TableColumn[];
4
+ columnsByKey: Map<string, TableColumn>;
5
5
  processing: boolean;
6
6
  onRemove: (index: number) => void;
7
7
  }): import("react").JSX.Element;
@@ -1,14 +1,14 @@
1
- import { flattenColumns } from "../payload.js";
1
+ import { Icon } from "../../icons/sprite.js";
2
+ import { useT } from "../../i18n/instance.js";
2
3
  import { operatorLabel } from "../query.js";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
- import { X } from "lucide-react";
5
5
  //#region resources/js/table/components/filter-stack-bar.tsx
6
- function FilterStackBar({ filters, columns, processing, onRemove }) {
7
- const labels = new Map(flattenColumns(columns).map((column) => [column.key, column.label]));
6
+ function FilterStackBar({ filters, columnsByKey, processing, onRemove }) {
7
+ const { t } = useT("lattice");
8
8
  return /* @__PURE__ */ jsx("div", {
9
9
  className: "flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm",
10
10
  children: filters.map((clause, index) => {
11
- const label = labels.get(clause.field) ?? clause.field;
11
+ const label = columnsByKey.get(clause.field)?.label ?? clause.field;
12
12
  return /* @__PURE__ */ jsxs("span", {
13
13
  className: "inline-flex items-center gap-1.5",
14
14
  children: [/* @__PURE__ */ jsxs("span", { children: [`${label} ${operatorLabel(clause.operator)}: `, /* @__PURE__ */ jsx("span", {
@@ -16,13 +16,15 @@ function FilterStackBar({ filters, columns, processing, onRemove }) {
16
16
  children: clause.value
17
17
  })] }), /* @__PURE__ */ jsx("button", {
18
18
  type: "button",
19
+ "data-test": `filter-chip-${clause.field}-remove`,
19
20
  className: "inline-flex size-5 items-center justify-center rounded text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50",
20
21
  disabled: processing,
21
- "aria-label": `Remove ${label} filter`,
22
+ "aria-label": t("filter.remove", "Remove {{label}} filter", { label }),
22
23
  onClick: () => onRemove(index),
23
- children: /* @__PURE__ */ jsx(X, {
24
+ children: /* @__PURE__ */ jsx(Icon, {
25
+ name: "x",
24
26
  "aria-hidden": "true",
25
- className: "size-3.5"
27
+ className: "size-lt-icon-sm"
26
28
  })
27
29
  })]
28
30
  }, `${clause.field}-${clause.operator}-${index}`);
@@ -1 +1 @@
1
- {"version":3,"file":"filter-stack-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-stack-bar.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport { flattenColumns } from \"../payload\";\nimport { operatorLabel } from \"../query\";\nimport type { FilterClause, TableColumn } from \"../types\";\n\nexport function FilterStackBar({\n filters,\n columns,\n processing,\n onRemove,\n}: {\n filters: FilterClause[];\n columns: TableColumn[];\n processing: boolean;\n onRemove: (index: number) => void;\n}) {\n const labels = new Map(flattenColumns(columns).map((column) => [column.key, column.label]));\n\n return (\n <div className=\"flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm\">\n {filters.map((clause, index) => {\n const label = labels.get(clause.field) ?? clause.field;\n\n return (\n <span\n key={`${clause.field}-${clause.operator}-${index}`}\n className=\"inline-flex items-center gap-1.5\"\n >\n <span>\n {`${label} ${operatorLabel(clause.operator)}: `}\n <span className=\"font-semibold\">{clause.value}</span>\n </span>\n <button\n type=\"button\"\n className=\"inline-flex size-5 items-center justify-center rounded text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n aria-label={`Remove ${label} filter`}\n onClick={() => onRemove(index)}\n >\n <X aria-hidden=\"true\" className=\"size-3.5\" />\n </button>\n </span>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,eAAe,EAC7B,SACA,SACA,YACA,YAMC;CACD,MAAM,SAAS,IAAI,IAAI,eAAe,OAAO,EAAE,KAAK,WAAW,CAAC,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC;CAE1F,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,QAAQ,KAAK,QAAQ,UAAU;GAC9B,MAAM,QAAQ,OAAO,IAAI,OAAO,KAAK,KAAK,OAAO;GAEjD,OACE,qBAAC,QAAD;IAEE,WAAU;cAFZ,CAIE,qBAAC,QAAD,EAAA,UAAA,CACG,GAAG,MAAM,GAAG,cAAc,OAAO,QAAQ,EAAE,KAC5C,oBAAC,QAAD;KAAM,WAAU;eAAiB,OAAO;IAAY,CAAA,CAChD,EAAA,CAAA,GACN,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,UAAU;KACV,cAAY,UAAU,MAAM;KAC5B,eAAe,SAAS,KAAK;eAE7B,oBAAC,GAAD;MAAG,eAAY;MAAO,WAAU;KAAY,CAAA;IACtC,CAAA,CACJ;MAhBC,GAAG,OAAO,MAAM,GAAG,OAAO,SAAS,GAAG,OAgBvC;EAEV,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"filter-stack-bar.js","names":[],"sources":["../../../resources/js/table/components/filter-stack-bar.tsx"],"sourcesContent":["import { Icon } from \"@lattice/lattice/icons\";\nimport { useT } from \"@lattice/lattice/i18n\";\nimport { operatorLabel } from \"../query\";\nimport type { FilterClause, TableColumn } from \"../types\";\n\nexport function FilterStackBar({\n filters,\n columnsByKey,\n processing,\n onRemove,\n}: {\n filters: FilterClause[];\n columnsByKey: Map<string, TableColumn>;\n processing: boolean;\n onRemove: (index: number) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm\">\n {filters.map((clause, index) => {\n const label = columnsByKey.get(clause.field)?.label ?? clause.field;\n\n return (\n <span\n key={`${clause.field}-${clause.operator}-${index}`}\n className=\"inline-flex items-center gap-1.5\"\n >\n <span>\n {`${label} ${operatorLabel(clause.operator)}: `}\n <span className=\"font-semibold\">{clause.value}</span>\n </span>\n <button\n type=\"button\"\n data-test={`filter-chip-${clause.field}-remove`}\n className=\"inline-flex size-5 items-center justify-center rounded text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n aria-label={t(\"filter.remove\", \"Remove {{label}} filter\", { label })}\n onClick={() => onRemove(index)}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n </span>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAgB,eAAe,EAC7B,SACA,cACA,YACA,YAMC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,QAAQ,KAAK,QAAQ,UAAU;GAC9B,MAAM,QAAQ,aAAa,IAAI,OAAO,KAAK,GAAG,SAAS,OAAO;GAE9D,OACE,qBAAC,QAAD;IAEE,WAAU;cAFZ,CAIE,qBAAC,QAAD,EAAA,UAAA,CACG,GAAG,MAAM,GAAG,cAAc,OAAO,QAAQ,EAAE,KAC5C,oBAAC,QAAD;KAAM,WAAU;eAAiB,OAAO;IAAY,CAAA,CAChD,EAAA,CAAA,GACN,oBAAC,UAAD;KACE,MAAK;KACL,aAAW,eAAe,OAAO,MAAM;KACvC,WAAU;KACV,UAAU;KACV,cAAY,EAAE,iBAAiB,2BAA2B,EAAE,MAAM,CAAC;KACnE,eAAe,SAAS,KAAK;eAE7B,oBAAC,MAAD;MAAM,MAAK;MAAI,eAAY;MAAO,WAAU;KAAmB,CAAA;IACzD,CAAA,CACJ;MAjBC,GAAG,OAAO,MAAM,GAAG,OAAO,SAAS,GAAG,OAiBvC;EAEV,CAAC;CACE,CAAA;AAET"}
@@ -1,11 +1,13 @@
1
- import { ControlType } from '../../../../generated/types';
2
- export declare function FilterValueInput({ type, label, value, processing, withSearchIcon, ariaLabel, onCommit, onClear, }: {
3
- type: ControlType;
1
+ import { FilterType } from '../../types/generated';
2
+ export declare function FilterValueInput({ type, label, value, processing, withSearchIcon, grouped, ariaLabel, testId, onCommit, onClear, }: {
3
+ type: FilterType;
4
4
  label: string;
5
5
  value: string;
6
6
  processing: boolean;
7
7
  withSearchIcon?: boolean;
8
+ grouped?: boolean;
8
9
  ariaLabel?: string;
10
+ testId?: string;
9
11
  onCommit: (value: string) => void;
10
12
  onClear?: () => void;
11
13
  }): import("react").JSX.Element;
@@ -1,39 +1,44 @@
1
+ import { Icon } from "../../icons/sprite.js";
2
+ import { useT } from "../../i18n/instance.js";
1
3
  import { useEffect, useState } from "react";
2
4
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Search, X } from "lucide-react";
4
5
  //#region resources/js/table/components/filter-value-input.tsx
5
- var baseClass = "h-9 w-full rounded-lt-sm border border-lt-input bg-lt-bg px-2 text-sm font-normal";
6
- function FilterValueInput({ type, label, value, processing, withSearchIcon = false, ariaLabel, onCommit, onClear }) {
6
+ var baseClass = "h-9 w-full min-w-0 rounded-lt-sm border border-lt-input bg-lt-bg px-2 text-sm font-normal";
7
+ function FilterValueInput({ type, label, value, processing, withSearchIcon = false, grouped = false, ariaLabel, testId, onCommit, onClear }) {
8
+ const { t } = useT("lattice");
7
9
  const [draft, setDraft] = useState(value);
8
- const inputLabel = ariaLabel ?? `Filter ${label}`;
10
+ const inputLabel = ariaLabel ?? t("filter.filterBy", "Filter {{label}}", { label });
11
+ const groupedClass = grouped ? "rounded-r-none" : "";
9
12
  useEffect(() => {
10
13
  setDraft(value);
11
14
  }, [value]);
12
15
  if (type === "boolean") return /* @__PURE__ */ jsxs("select", {
13
16
  "aria-label": inputLabel,
14
- className: baseClass,
17
+ "data-test": testId,
18
+ className: `${baseClass} ${groupedClass}`,
15
19
  disabled: processing,
16
20
  value,
17
21
  onChange: (event) => onCommit(event.target.value),
18
22
  children: [
19
23
  /* @__PURE__ */ jsx("option", {
20
24
  value: "",
21
- children: "All"
25
+ children: t("filter.all", "All")
22
26
  }),
23
27
  /* @__PURE__ */ jsx("option", {
24
28
  value: "true",
25
- children: "True"
29
+ children: t("filter.true", "True")
26
30
  }),
27
31
  /* @__PURE__ */ jsx("option", {
28
32
  value: "false",
29
- children: "False"
33
+ children: t("filter.false", "False")
30
34
  })
31
35
  ]
32
36
  });
33
37
  if (type === "date") return /* @__PURE__ */ jsx("input", {
34
38
  type: "date",
35
39
  "aria-label": inputLabel,
36
- className: baseClass,
40
+ "data-test": testId,
41
+ className: `${baseClass} ${groupedClass}`,
37
42
  disabled: processing,
38
43
  value: draft,
39
44
  onChange: (event) => {
@@ -42,16 +47,18 @@ function FilterValueInput({ type, label, value, processing, withSearchIcon = fal
42
47
  }
43
48
  });
44
49
  return /* @__PURE__ */ jsxs("div", {
45
- className: "relative flex items-center",
50
+ className: "relative flex w-full min-w-0 items-center",
46
51
  children: [
47
- withSearchIcon && /* @__PURE__ */ jsx(Search, {
52
+ withSearchIcon && /* @__PURE__ */ jsx(Icon, {
53
+ name: "search",
48
54
  "aria-hidden": "true",
49
- className: "pointer-events-none absolute left-2 size-4 text-lt-muted-fg"
55
+ className: "pointer-events-none absolute left-2 size-lt-icon-md text-lt-muted-fg"
50
56
  }),
51
57
  /* @__PURE__ */ jsx("input", {
52
58
  type: type === "number" ? "number" : "text",
53
59
  "aria-label": inputLabel,
54
- className: `${baseClass} ${withSearchIcon ? "pl-8" : ""} ${onClear ? "pr-8" : ""}`,
60
+ "data-test": testId,
61
+ className: `${baseClass} ${groupedClass} ${withSearchIcon ? "pl-8" : ""} ${onClear ? "pr-8" : ""}`,
55
62
  disabled: processing,
56
63
  value: draft,
57
64
  onChange: (event) => setDraft(event.target.value),
@@ -64,13 +71,15 @@ function FilterValueInput({ type, label, value, processing, withSearchIcon = fal
64
71
  }),
65
72
  onClear && draft !== "" && /* @__PURE__ */ jsx("button", {
66
73
  type: "button",
67
- "aria-label": `Clear ${label} filter`,
74
+ "aria-label": t("filter.clear", "Clear {{label}} filter", { label }),
75
+ "data-test": testId ? `${testId}-clear` : void 0,
68
76
  className: "absolute right-1 inline-flex size-6 items-center justify-center rounded hover:bg-lt-muted disabled:opacity-50",
69
77
  disabled: processing,
70
78
  onClick: onClear,
71
- children: /* @__PURE__ */ jsx(X, {
79
+ children: /* @__PURE__ */ jsx(Icon, {
80
+ name: "x",
72
81
  "aria-hidden": "true",
73
- className: "size-3.5"
82
+ className: "size-lt-icon-sm"
74
83
  })
75
84
  })
76
85
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"filter-value-input.js","names":[],"sources":["../../../resources/js/table/components/filter-value-input.tsx"],"sourcesContent":["import { Search, X } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport type { ControlType } from \"@lattice/lattice/generated/types\";\n\nconst baseClass =\n \"h-9 w-full rounded-lt-sm border border-lt-input bg-lt-bg px-2 text-sm font-normal\";\n\nexport function FilterValueInput({\n type,\n label,\n value,\n processing,\n withSearchIcon = false,\n ariaLabel,\n onCommit,\n onClear,\n}: {\n type: ControlType;\n label: string;\n value: string;\n processing: boolean;\n withSearchIcon?: boolean;\n ariaLabel?: string;\n onCommit: (value: string) => void;\n onClear?: () => void;\n}) {\n const [draft, setDraft] = useState(value);\n const inputLabel = ariaLabel ?? `Filter ${label}`;\n\n useEffect(() => {\n setDraft(value);\n }, [value]);\n\n if (type === \"boolean\") {\n return (\n <select\n aria-label={inputLabel}\n className={baseClass}\n disabled={processing}\n value={value}\n onChange={(event) => onCommit(event.target.value)}\n >\n <option value=\"\">All</option>\n <option value=\"true\">True</option>\n <option value=\"false\">False</option>\n </select>\n );\n }\n\n if (type === \"date\") {\n return (\n <input\n type=\"date\"\n aria-label={inputLabel}\n className={baseClass}\n disabled={processing}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n onCommit(event.target.value);\n }}\n />\n );\n }\n\n return (\n <div className=\"relative flex items-center\">\n {withSearchIcon && (\n <Search\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-2 size-4 text-lt-muted-fg\"\n />\n )}\n <input\n type={type === \"number\" ? \"number\" : \"text\"}\n aria-label={inputLabel}\n className={`${baseClass} ${withSearchIcon ? \"pl-8\" : \"\"} ${onClear ? \"pr-8\" : \"\"}`}\n disabled={processing}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n onCommit(draft);\n }\n }}\n onBlur={() => {\n if (draft !== value) {\n onCommit(draft);\n }\n }}\n />\n {onClear && draft !== \"\" && (\n <button\n type=\"button\"\n aria-label={`Clear ${label} filter`}\n className=\"absolute right-1 inline-flex size-6 items-center justify-center rounded hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n onClick={onClear}\n >\n <X aria-hidden=\"true\" className=\"size-3.5\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;AAIA,IAAM,YACJ;AAEF,SAAgB,iBAAiB,EAC/B,MACA,OACA,OACA,YACA,iBAAiB,OACjB,WACA,UACA,WAUC;CACD,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,aAAa,aAAa,UAAU;CAE1C,gBAAgB;EACd,SAAS,KAAK;CAChB,GAAG,CAAC,KAAK,CAAC;CAEV,IAAI,SAAS,WACX,OACE,qBAAC,UAAD;EACE,cAAY;EACZ,WAAW;EACX,UAAU;EACH;EACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;YALlD;GAOE,oBAAC,UAAD;IAAQ,OAAM;cAAG;GAAW,CAAA;GAC5B,oBAAC,UAAD;IAAQ,OAAM;cAAO;GAAY,CAAA;GACjC,oBAAC,UAAD;IAAQ,OAAM;cAAQ;GAAa,CAAA;EAC7B;;CAIZ,IAAI,SAAS,QACX,OACE,oBAAC,SAAD;EACE,MAAK;EACL,cAAY;EACZ,WAAW;EACX,UAAU;EACV,OAAO;EACP,WAAW,UAAU;GACnB,SAAS,MAAM,OAAO,KAAK;GAC3B,SAAS,MAAM,OAAO,KAAK;EAC7B;CACD,CAAA;CAIL,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,kBACC,oBAAC,QAAD;IACE,eAAY;IACZ,WAAU;GACX,CAAA;GAEH,oBAAC,SAAD;IACE,MAAM,SAAS,WAAW,WAAW;IACrC,cAAY;IACZ,WAAW,GAAG,UAAU,GAAG,iBAAiB,SAAS,GAAG,GAAG,UAAU,SAAS;IAC9E,UAAU;IACV,OAAO;IACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;IAChD,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,SAChB,SAAS,KAAK;IAElB;IACA,cAAc;KACZ,IAAI,UAAU,OACZ,SAAS,KAAK;IAElB;GACD,CAAA;GACA,WAAW,UAAU,MACpB,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,SAAS,MAAM;IAC3B,WAAU;IACV,UAAU;IACV,SAAS;cAET,oBAAC,GAAD;KAAG,eAAY;KAAO,WAAU;IAAY,CAAA;GACtC,CAAA;EAEP;;AAET"}
1
+ {"version":3,"file":"filter-value-input.js","names":[],"sources":["../../../resources/js/table/components/filter-value-input.tsx"],"sourcesContent":["import { Icon } from \"@lattice/lattice/icons\";\nimport { useEffect, useState } from \"react\";\nimport { useT } from \"@lattice/lattice/i18n\";\nimport type { FilterType } from \"@lattice/lattice/types/generated\";\n\nconst baseClass =\n \"h-9 w-full min-w-0 rounded-lt-sm border border-lt-input bg-lt-bg px-2 text-sm font-normal\";\n\nexport function FilterValueInput({\n type,\n label,\n value,\n processing,\n withSearchIcon = false,\n grouped = false,\n ariaLabel,\n testId,\n onCommit,\n onClear,\n}: {\n type: FilterType;\n label: string;\n value: string;\n processing: boolean;\n withSearchIcon?: boolean;\n grouped?: boolean;\n ariaLabel?: string;\n testId?: string;\n onCommit: (value: string) => void;\n onClear?: () => void;\n}) {\n const { t } = useT(\"lattice\");\n const [draft, setDraft] = useState(value);\n const inputLabel = ariaLabel ?? t(\"filter.filterBy\", \"Filter {{label}}\", { label });\n const groupedClass = grouped ? \"rounded-r-none\" : \"\";\n\n useEffect(() => {\n setDraft(value);\n }, [value]);\n\n if (type === \"boolean\") {\n return (\n <select\n aria-label={inputLabel}\n data-test={testId}\n className={`${baseClass} ${groupedClass}`}\n disabled={processing}\n value={value}\n onChange={(event) => onCommit(event.target.value)}\n >\n <option value=\"\">{t(\"filter.all\", \"All\")}</option>\n <option value=\"true\">{t(\"filter.true\", \"True\")}</option>\n <option value=\"false\">{t(\"filter.false\", \"False\")}</option>\n </select>\n );\n }\n\n if (type === \"date\") {\n return (\n <input\n type=\"date\"\n aria-label={inputLabel}\n data-test={testId}\n className={`${baseClass} ${groupedClass}`}\n disabled={processing}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n onCommit(event.target.value);\n }}\n />\n );\n }\n\n return (\n <div className=\"relative flex w-full min-w-0 items-center\">\n {withSearchIcon && (\n <Icon\n name=\"search\"\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-2 size-lt-icon-md text-lt-muted-fg\"\n />\n )}\n <input\n type={type === \"number\" ? \"number\" : \"text\"}\n aria-label={inputLabel}\n data-test={testId}\n className={`${baseClass} ${groupedClass} ${withSearchIcon ? \"pl-8\" : \"\"} ${onClear ? \"pr-8\" : \"\"}`}\n disabled={processing}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n onCommit(draft);\n }\n }}\n onBlur={() => {\n if (draft !== value) {\n onCommit(draft);\n }\n }}\n />\n {onClear && draft !== \"\" && (\n <button\n type=\"button\"\n aria-label={t(\"filter.clear\", \"Clear {{label}} filter\", { label })}\n data-test={testId ? `${testId}-clear` : undefined}\n className=\"absolute right-1 inline-flex size-6 items-center justify-center rounded hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n onClick={onClear}\n >\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-sm\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,YACJ;AAEF,SAAgB,iBAAiB,EAC/B,MACA,OACA,OACA,YACA,iBAAiB,OACjB,UAAU,OACV,WACA,QACA,UACA,WAYC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,aAAa,aAAa,EAAE,mBAAmB,oBAAoB,EAAE,MAAM,CAAC;CAClF,MAAM,eAAe,UAAU,mBAAmB;CAElD,gBAAgB;EACd,SAAS,KAAK;CAChB,GAAG,CAAC,KAAK,CAAC;CAEV,IAAI,SAAS,WACX,OACE,qBAAC,UAAD;EACE,cAAY;EACZ,aAAW;EACX,WAAW,GAAG,UAAU,GAAG;EAC3B,UAAU;EACH;EACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;YANlD;GAQE,oBAAC,UAAD;IAAQ,OAAM;cAAI,EAAE,cAAc,KAAK;GAAU,CAAA;GACjD,oBAAC,UAAD;IAAQ,OAAM;cAAQ,EAAE,eAAe,MAAM;GAAU,CAAA;GACvD,oBAAC,UAAD;IAAQ,OAAM;cAAS,EAAE,gBAAgB,OAAO;GAAU,CAAA;EACpD;;CAIZ,IAAI,SAAS,QACX,OACE,oBAAC,SAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAW;EACX,WAAW,GAAG,UAAU,GAAG;EAC3B,UAAU;EACV,OAAO;EACP,WAAW,UAAU;GACnB,SAAS,MAAM,OAAO,KAAK;GAC3B,SAAS,MAAM,OAAO,KAAK;EAC7B;CACD,CAAA;CAIL,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,kBACC,oBAAC,MAAD;IACE,MAAK;IACL,eAAY;IACZ,WAAU;GACX,CAAA;GAEH,oBAAC,SAAD;IACE,MAAM,SAAS,WAAW,WAAW;IACrC,cAAY;IACZ,aAAW;IACX,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,iBAAiB,SAAS,GAAG,GAAG,UAAU,SAAS;IAC9F,UAAU;IACV,OAAO;IACP,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;IAChD,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,SAChB,SAAS,KAAK;IAElB;IACA,cAAc;KACZ,IAAI,UAAU,OACZ,SAAS,KAAK;IAElB;GACD,CAAA;GACA,WAAW,UAAU,MACpB,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,EAAE,gBAAgB,0BAA0B,EAAE,MAAM,CAAC;IACjE,aAAW,SAAS,GAAG,OAAO,UAAU,KAAA;IACxC,WAAU;IACV,UAAU;IACV,SAAS;cAET,oBAAC,MAAD;KAAM,MAAK;KAAI,eAAY;KAAO,WAAU;IAAmB,CAAA;GACzD,CAAA;EAEP;;AAET"}
@@ -1,5 +1,5 @@
1
1
  import { RefObject } from 'react';
2
- import { PaginationType } from '../../../../generated/types';
2
+ import { PaginationType } from '../../types/generated';
3
3
  import { TablePagination as TablePaginationData } from '../types';
4
4
  export declare function TablePagination({ pagination, currentPage, processing, mode, hasNextPage, visiblePages, infiniteLoaderRef, onPage, onLoadMore, }: {
5
5
  pagination: TablePaginationData;
@@ -1,61 +1,73 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { jsx, jsxs } from "react/jsx-runtime";
2
3
  //#region resources/js/table/components/pagination.tsx
3
4
  function TablePagination({ pagination, currentPage, processing, mode, hasNextPage, visiblePages, infiniteLoaderRef, onPage, onLoadMore }) {
5
+ const { t } = useT("lattice");
4
6
  return /* @__PURE__ */ jsxs("div", {
5
7
  className: "flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm",
6
- children: [/* @__PURE__ */ jsx("span", { children: pagination.total === void 0 ? `Page ${currentPage}` : `Showing ${pagination.from ?? 0}-${pagination.to ?? 0} of ${pagination.total}` }), mode === "infinite" ? /* @__PURE__ */ jsx("div", {
8
+ children: [/* @__PURE__ */ jsx("span", { children: pagination.total === void 0 ? t("pagination.page", "Page {{page}}", { page: currentPage }) : t("pagination.showing", "Showing {{from}}-{{to}} of {{total}}", {
9
+ from: pagination.from ?? 0,
10
+ to: pagination.to ?? 0,
11
+ total: pagination.total
12
+ }) }), mode === "infinite" ? /* @__PURE__ */ jsx("div", {
7
13
  ref: infiniteLoaderRef,
8
14
  className: "flex items-center gap-2",
9
15
  children: pagination.hasMore ? /* @__PURE__ */ jsx("button", {
10
16
  type: "button",
17
+ "data-test": "pagination-load-more",
11
18
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
12
19
  disabled: processing,
13
20
  onClick: onLoadMore,
14
- children: processing ? "Loading..." : "Load more"
21
+ children: processing ? t("pagination.loading", "Loading...") : t("pagination.loadMore", "Load more")
15
22
  }) : /* @__PURE__ */ jsx("span", {
16
23
  className: "text-lt-muted-fg",
17
- children: "All rows loaded"
24
+ children: t("pagination.allLoaded", "All rows loaded")
18
25
  })
19
26
  }) : mode === "simple" ? /* @__PURE__ */ jsxs("div", {
20
27
  className: "flex items-center gap-2",
21
28
  children: [/* @__PURE__ */ jsx("button", {
22
29
  type: "button",
30
+ "data-test": "pagination-previous",
23
31
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
24
32
  disabled: processing || currentPage <= 1,
25
33
  onClick: () => onPage(currentPage - 1),
26
- children: "Previous"
34
+ children: t("pagination.previous", "Previous")
27
35
  }), /* @__PURE__ */ jsx("button", {
28
36
  type: "button",
37
+ "data-test": "pagination-next",
29
38
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
30
39
  disabled: processing || !hasNextPage,
31
40
  onClick: () => onPage(currentPage + 1),
32
- children: "Next"
41
+ children: t("pagination.next", "Next")
33
42
  })]
34
43
  }) : mode === "table" ? /* @__PURE__ */ jsxs("div", {
35
44
  className: "flex items-center gap-2",
36
45
  children: [
37
46
  /* @__PURE__ */ jsx("button", {
38
47
  type: "button",
48
+ "data-test": "pagination-previous",
39
49
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
40
50
  disabled: processing || currentPage <= 1,
41
51
  onClick: () => onPage(currentPage - 1),
42
- children: "Previous"
52
+ children: t("pagination.previous", "Previous")
43
53
  }),
44
54
  visiblePages.map((pageNumber) => /* @__PURE__ */ jsx("button", {
45
55
  type: "button",
56
+ "data-test": `pagination-page-${pageNumber}`,
46
57
  className: "inline-flex size-9 items-center justify-center rounded-lt-sm border border-lt-border font-medium disabled:opacity-50",
47
58
  disabled: processing || pageNumber === currentPage,
48
59
  "aria-current": pageNumber === currentPage ? "page" : void 0,
49
- "aria-label": `Page ${pageNumber}`,
60
+ "aria-label": t("pagination.page", "Page {{page}}", { page: pageNumber }),
50
61
  onClick: () => onPage(pageNumber),
51
62
  children: pageNumber
52
63
  }, pageNumber)),
53
64
  /* @__PURE__ */ jsx("button", {
54
65
  type: "button",
66
+ "data-test": "pagination-next",
55
67
  className: "h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50",
56
68
  disabled: processing || !hasNextPage,
57
69
  onClick: () => onPage(currentPage + 1),
58
- children: "Next"
70
+ children: t("pagination.next", "Next")
59
71
  })
60
72
  ]
61
73
  }) : null]
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","names":[],"sources":["../../../resources/js/table/components/pagination.tsx"],"sourcesContent":["import type { RefObject } from \"react\";\nimport type { PaginationType } from \"@lattice/lattice/generated/types\";\nimport type { TablePagination as TablePaginationData } from \"../types\";\n\nexport function TablePagination({\n pagination,\n currentPage,\n processing,\n mode,\n hasNextPage,\n visiblePages,\n infiniteLoaderRef,\n onPage,\n onLoadMore,\n}: {\n pagination: TablePaginationData;\n currentPage: number;\n processing: boolean;\n mode: PaginationType;\n hasNextPage: boolean;\n visiblePages: number[];\n infiniteLoaderRef: RefObject<HTMLDivElement | null>;\n onPage: (page: number) => void;\n onLoadMore: () => void;\n}) {\n return (\n <div className=\"flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm\">\n <span>\n {pagination.total === undefined\n ? `Page ${currentPage}`\n : `Showing ${pagination.from ?? 0}-${pagination.to ?? 0} of ${pagination.total}`}\n </span>\n {mode === \"infinite\" ? (\n <div ref={infiniteLoaderRef} className=\"flex items-center gap-2\">\n {pagination.hasMore ? (\n <button\n type=\"button\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing}\n onClick={onLoadMore}\n >\n {processing ? \"Loading...\" : \"Load more\"}\n </button>\n ) : (\n <span className=\"text-lt-muted-fg\">All rows loaded</span>\n )}\n </div>\n ) : mode === \"simple\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n Previous\n </button>\n <button\n type=\"button\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n Next\n </button>\n </div>\n ) : mode === \"table\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n Previous\n </button>\n {visiblePages.map((pageNumber) => (\n <button\n key={pageNumber}\n type=\"button\"\n className=\"inline-flex size-9 items-center justify-center rounded-lt-sm border border-lt-border font-medium disabled:opacity-50\"\n disabled={processing || pageNumber === currentPage}\n aria-current={pageNumber === currentPage ? \"page\" : undefined}\n aria-label={`Page ${pageNumber}`}\n onClick={() => onPage(pageNumber)}\n >\n {pageNumber}\n </button>\n ))}\n <button\n type=\"button\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n Next\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;AAIA,SAAgB,gBAAgB,EAC9B,YACA,aACA,YACA,MACA,aACA,cACA,mBACA,QACA,cAWC;CACD,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,QAAD,EAAA,UACG,WAAW,UAAU,KAAA,IAClB,QAAQ,gBACR,WAAW,WAAW,QAAQ,EAAE,GAAG,WAAW,MAAM,EAAE,MAAM,WAAW,QACvE,CAAA,GACL,SAAS,aACR,oBAAC,OAAD;GAAK,KAAK;GAAmB,WAAU;aACpC,WAAW,UACV,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,UAAU;IACV,SAAS;cAER,aAAa,eAAe;GACvB,CAAA,IAER,oBAAC,QAAD;IAAM,WAAU;cAAmB;GAAqB,CAAA;EAEvD,CAAA,IACH,SAAS,WACX,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,UAAU,cAAc,eAAe;IACvC,eAAe,OAAO,cAAc,CAAC;cACtC;GAEO,CAAA,GACR,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,UAAU,cAAc,CAAC;IACzB,eAAe,OAAO,cAAc,CAAC;cACtC;GAEO,CAAA,CACL;OACH,SAAS,UACX,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,eAAe,OAAO,cAAc,CAAC;eACtC;IAEO,CAAA;IACP,aAAa,KAAK,eACjB,oBAAC,UAAD;KAEE,MAAK;KACL,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,gBAAc,eAAe,cAAc,SAAS,KAAA;KACpD,cAAY,QAAQ;KACpB,eAAe,OAAO,UAAU;eAE/B;IACK,GATD,UASC,CACT;IACD,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,UAAU,cAAc,CAAC;KACzB,eAAe,OAAO,cAAc,CAAC;eACtC;IAEO,CAAA;GACL;OACH,IACD;;AAET"}
1
+ {"version":3,"file":"pagination.js","names":[],"sources":["../../../resources/js/table/components/pagination.tsx"],"sourcesContent":["import type { RefObject } from \"react\";\nimport { useT } from \"@lattice/lattice/i18n\";\nimport type { PaginationType } from \"@lattice/lattice/types/generated\";\nimport type { TablePagination as TablePaginationData } from \"../types\";\n\nexport function TablePagination({\n pagination,\n currentPage,\n processing,\n mode,\n hasNextPage,\n visiblePages,\n infiniteLoaderRef,\n onPage,\n onLoadMore,\n}: {\n pagination: TablePaginationData;\n currentPage: number;\n processing: boolean;\n mode: PaginationType;\n hasNextPage: boolean;\n visiblePages: number[];\n infiniteLoaderRef: RefObject<HTMLDivElement | null>;\n onPage: (page: number) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex items-center justify-between gap-3 border-t border-lt-border p-4 text-sm\">\n <span>\n {pagination.total === undefined\n ? t(\"pagination.page\", \"Page {{page}}\", { page: currentPage })\n : t(\"pagination.showing\", \"Showing {{from}}-{{to}} of {{total}}\", {\n from: pagination.from ?? 0,\n to: pagination.to ?? 0,\n total: pagination.total,\n })}\n </span>\n {mode === \"infinite\" ? (\n <div ref={infiniteLoaderRef} className=\"flex items-center gap-2\">\n {pagination.hasMore ? (\n <button\n type=\"button\"\n data-test=\"pagination-load-more\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing}\n onClick={onLoadMore}\n >\n {processing\n ? t(\"pagination.loading\", \"Loading...\")\n : t(\"pagination.loadMore\", \"Load more\")}\n </button>\n ) : (\n <span className=\"text-lt-muted-fg\">{t(\"pagination.allLoaded\", \"All rows loaded\")}</span>\n )}\n </div>\n ) : mode === \"simple\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-test=\"pagination-previous\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"pagination.previous\", \"Previous\")}\n </button>\n <button\n type=\"button\"\n data-test=\"pagination-next\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"pagination.next\", \"Next\")}\n </button>\n </div>\n ) : mode === \"table\" ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n data-test=\"pagination-previous\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || currentPage <= 1}\n onClick={() => onPage(currentPage - 1)}\n >\n {t(\"pagination.previous\", \"Previous\")}\n </button>\n {visiblePages.map((pageNumber) => (\n <button\n key={pageNumber}\n type=\"button\"\n data-test={`pagination-page-${pageNumber}`}\n className=\"inline-flex size-9 items-center justify-center rounded-lt-sm border border-lt-border font-medium disabled:opacity-50\"\n disabled={processing || pageNumber === currentPage}\n aria-current={pageNumber === currentPage ? \"page\" : undefined}\n aria-label={t(\"pagination.page\", \"Page {{page}}\", { page: pageNumber })}\n onClick={() => onPage(pageNumber)}\n >\n {pageNumber}\n </button>\n ))}\n <button\n type=\"button\"\n data-test=\"pagination-next\"\n className=\"h-9 rounded-lt-sm border border-lt-border px-3 font-medium disabled:opacity-50\"\n disabled={processing || !hasNextPage}\n onClick={() => onPage(currentPage + 1)}\n >\n {t(\"pagination.next\", \"Next\")}\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;AAKA,SAAgB,gBAAgB,EAC9B,YACA,aACA,YACA,MACA,aACA,cACA,mBACA,QACA,cAWC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,QAAD,EAAA,UACG,WAAW,UAAU,KAAA,IAClB,EAAE,mBAAmB,iBAAiB,EAAE,MAAM,YAAY,CAAC,IAC3D,EAAE,sBAAsB,wCAAwC;GAC9D,MAAM,WAAW,QAAQ;GACzB,IAAI,WAAW,MAAM;GACrB,OAAO,WAAW;EACpB,CAAC,EACD,CAAA,GACL,SAAS,aACR,oBAAC,OAAD;GAAK,KAAK;GAAmB,WAAU;aACpC,WAAW,UACV,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU;IACV,SAAS;cAER,aACG,EAAE,sBAAsB,YAAY,IACpC,EAAE,uBAAuB,WAAW;GAClC,CAAA,IAER,oBAAC,QAAD;IAAM,WAAU;cAAoB,EAAE,wBAAwB,iBAAiB;GAAQ,CAAA;EAEtF,CAAA,IACH,SAAS,WACX,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU,cAAc,eAAe;IACvC,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,uBAAuB,UAAU;GAC9B,CAAA,GACR,oBAAC,UAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;IACV,UAAU,cAAc,CAAC;IACzB,eAAe,OAAO,cAAc,CAAC;cAEpC,EAAE,mBAAmB,MAAM;GACtB,CAAA,CACL;OACH,SAAS,UACX,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,UAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,uBAAuB,UAAU;IAC9B,CAAA;IACP,aAAa,KAAK,eACjB,oBAAC,UAAD;KAEE,MAAK;KACL,aAAW,mBAAmB;KAC9B,WAAU;KACV,UAAU,cAAc,eAAe;KACvC,gBAAc,eAAe,cAAc,SAAS,KAAA;KACpD,cAAY,EAAE,mBAAmB,iBAAiB,EAAE,MAAM,WAAW,CAAC;KACtE,eAAe,OAAO,UAAU;eAE/B;IACK,GAVD,UAUC,CACT;IACD,oBAAC,UAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KACV,UAAU,cAAc,CAAC;KACzB,eAAe,OAAO,cAAc,CAAC;eAEpC,EAAE,mBAAmB,MAAM;IACtB,CAAA;GACL;OACH,IACD;;AAET"}
@@ -1,6 +1,6 @@
1
1
  import { TableColumn, TableSort, TableState } from '../types';
2
- export declare function SortBar({ columns, state, processing, onClear, }: {
3
- columns: TableColumn[];
2
+ export declare function SortBar({ columnsByKey, state, processing, onClear, }: {
3
+ columnsByKey: Map<string, TableColumn>;
4
4
  state: TableState;
5
5
  processing: boolean;
6
6
  onClear: (sort: TableSort) => void;
@@ -1,13 +1,13 @@
1
- import { getSortColumn, getSortDirectionLabel } from "../query.js";
1
+ import { Icon } from "../../icons/sprite.js";
2
+ import { getSortDirectionLabel } from "../query.js";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { ArrowDown, ArrowUp, X } from "lucide-react";
4
4
  //#region resources/js/table/components/sort-bar.tsx
5
- function SortBar({ columns, state, processing, onClear }) {
5
+ function SortBar({ columnsByKey, state, processing, onClear }) {
6
6
  return /* @__PURE__ */ jsx("div", {
7
7
  className: "flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm",
8
8
  children: state.sorts.map((sort, index) => {
9
- const label = getSortColumn(columns, sort)?.label ?? sort.key;
10
- const Chevron = sort.direction === "desc" ? ArrowDown : ArrowUp;
9
+ const label = columnsByKey.get(sort.key)?.label ?? sort.key;
10
+ const arrow = sort.direction === "desc" ? "arrow-down" : "arrow-up";
11
11
  return /* @__PURE__ */ jsxs("span", {
12
12
  className: "inline-flex items-center gap-1.5",
13
13
  children: [
@@ -15,10 +15,12 @@ function SortBar({ columns, state, processing, onClear }) {
15
15
  className: "font-medium",
16
16
  children: `${index + 1}. ${label}`
17
17
  }),
18
- /* @__PURE__ */ jsx(Chevron, {
18
+ /* @__PURE__ */ jsx(Icon, {
19
+ name: arrow,
19
20
  role: "img",
21
+ "aria-hidden": false,
20
22
  "aria-label": getSortDirectionLabel(sort.direction),
21
- className: "size-3.5 text-lt-muted-fg"
23
+ className: "size-lt-icon-sm text-lt-muted-fg"
22
24
  }),
23
25
  /* @__PURE__ */ jsx("button", {
24
26
  type: "button",
@@ -27,9 +29,9 @@ function SortBar({ columns, state, processing, onClear }) {
27
29
  "aria-label": `Clear ${label} sort`,
28
30
  "data-test": `clear-${sort.key}-sort`,
29
31
  onClick: () => onClear(sort),
30
- children: /* @__PURE__ */ jsx(X, {
31
- "aria-hidden": "true",
32
- className: "size-3.5"
32
+ children: /* @__PURE__ */ jsx(Icon, {
33
+ name: "x",
34
+ className: "size-lt-icon-sm"
33
35
  })
34
36
  })
35
37
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"sort-bar.js","names":[],"sources":["../../../resources/js/table/components/sort-bar.tsx"],"sourcesContent":["import { ArrowDown, ArrowUp, X } from \"lucide-react\";\nimport { getSortColumn, getSortDirectionLabel } from \"../query\";\nimport type { TableColumn, TableSort, TableState } from \"../types\";\n\nexport function SortBar({\n columns,\n state,\n processing,\n onClear,\n}: {\n columns: TableColumn[];\n state: TableState;\n processing: boolean;\n onClear: (sort: TableSort) => void;\n}) {\n return (\n <div className=\"flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm\">\n {state.sorts.map((sort, index) => {\n const column = getSortColumn(columns, sort);\n const label = column?.label ?? sort.key;\n const Chevron = sort.direction === \"desc\" ? ArrowDown : ArrowUp;\n\n return (\n <span key={sort.key} className=\"inline-flex items-center gap-1.5\">\n <span className=\"font-medium\">{`${index + 1}. ${label}`}</span>\n <Chevron\n role=\"img\"\n aria-label={getSortDirectionLabel(sort.direction)}\n className=\"size-3.5 text-lt-muted-fg\"\n />\n <button\n type=\"button\"\n className=\"inline-flex size-5 items-center justify-center rounded text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n aria-label={`Clear ${label} sort`}\n data-test={`clear-${sort.key}-sort`}\n onClick={() => onClear(sort)}\n >\n <X aria-hidden=\"true\" className=\"size-3.5\" />\n </button>\n </span>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;AAIA,SAAgB,QAAQ,EACtB,SACA,OACA,YACA,WAMC;CACD,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,MAAM,MAAM,KAAK,MAAM,UAAU;GAEhC,MAAM,QADS,cAAc,SAAS,IACxB,GAAQ,SAAS,KAAK;GACpC,MAAM,UAAU,KAAK,cAAc,SAAS,YAAY;GAExD,OACE,qBAAC,QAAD;IAAqB,WAAU;cAA/B;KACE,oBAAC,QAAD;MAAM,WAAU;gBAAe,GAAG,QAAQ,EAAE,IAAI;KAAc,CAAA;KAC9D,oBAAC,SAAD;MACE,MAAK;MACL,cAAY,sBAAsB,KAAK,SAAS;MAChD,WAAU;KACX,CAAA;KACD,oBAAC,UAAD;MACE,MAAK;MACL,WAAU;MACV,UAAU;MACV,cAAY,SAAS,MAAM;MAC3B,aAAW,SAAS,KAAK,IAAI;MAC7B,eAAe,QAAQ,IAAI;gBAE3B,oBAAC,GAAD;OAAG,eAAY;OAAO,WAAU;MAAY,CAAA;KACtC,CAAA;IACJ;MAjBK,KAAK,GAiBV;EAEV,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"sort-bar.js","names":[],"sources":["../../../resources/js/table/components/sort-bar.tsx"],"sourcesContent":["import { Icon } from \"@lattice/lattice/icons\";\nimport { getSortDirectionLabel } from \"../query\";\nimport type { TableColumn, TableSort, TableState } from \"../types\";\n\nexport function SortBar({\n columnsByKey,\n state,\n processing,\n onClear,\n}: {\n columnsByKey: Map<string, TableColumn>;\n state: TableState;\n processing: boolean;\n onClear: (sort: TableSort) => void;\n}) {\n return (\n <div className=\"flex flex-wrap items-center gap-4 border-b border-lt-border px-4 py-2.5 text-sm\">\n {state.sorts.map((sort, index) => {\n const column = columnsByKey.get(sort.key);\n const label = column?.label ?? sort.key;\n const arrow = sort.direction === \"desc\" ? \"arrow-down\" : \"arrow-up\";\n\n return (\n <span key={sort.key} className=\"inline-flex items-center gap-1.5\">\n <span className=\"font-medium\">{`${index + 1}. ${label}`}</span>\n <Icon\n name={arrow}\n role=\"img\"\n aria-hidden={false}\n aria-label={getSortDirectionLabel(sort.direction)}\n className=\"size-lt-icon-sm text-lt-muted-fg\"\n />\n <button\n type=\"button\"\n className=\"inline-flex size-5 items-center justify-center rounded text-lt-muted-fg hover:bg-lt-muted disabled:opacity-50\"\n disabled={processing}\n aria-label={`Clear ${label} sort`}\n data-test={`clear-${sort.key}-sort`}\n onClick={() => onClear(sort)}\n >\n <Icon name=\"x\" className=\"size-lt-icon-sm\" />\n </button>\n </span>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;AAIA,SAAgB,QAAQ,EACtB,cACA,OACA,YACA,WAMC;CACD,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,MAAM,MAAM,KAAK,MAAM,UAAU;GAEhC,MAAM,QADS,aAAa,IAAI,KAAK,GACvB,GAAQ,SAAS,KAAK;GACpC,MAAM,QAAQ,KAAK,cAAc,SAAS,eAAe;GAEzD,OACE,qBAAC,QAAD;IAAqB,WAAU;cAA/B;KACE,oBAAC,QAAD;MAAM,WAAU;gBAAe,GAAG,QAAQ,EAAE,IAAI;KAAc,CAAA;KAC9D,oBAAC,MAAD;MACE,MAAM;MACN,MAAK;MACL,eAAa;MACb,cAAY,sBAAsB,KAAK,SAAS;MAChD,WAAU;KACX,CAAA;KACD,oBAAC,UAAD;MACE,MAAK;MACL,WAAU;MACV,UAAU;MACV,cAAY,SAAS,MAAM;MAC3B,aAAW,SAAS,KAAK,IAAI;MAC7B,eAAe,QAAQ,IAAI;gBAE3B,oBAAC,MAAD;OAAM,MAAK;OAAI,WAAU;MAAmB,CAAA;KACtC,CAAA;IACJ;MAnBK,KAAK,GAmBV;EAEV,CAAC;CACE,CAAA;AAET"}
@@ -1,4 +1,4 @@
1
- import { Node } from '../../../../core/types';
1
+ import { Node } from '../../core/types';
2
2
  export declare function TableActionNode({ node }: {
3
3
  node: Node;
4
4
  }): import("react").JSX.Element | null;
@@ -10,7 +10,7 @@ function TableActionNode({ node }) {
10
10
  });
11
11
  if (node.type === "action.group") return /* @__PURE__ */ jsx(ActionGroupComponent, {
12
12
  node,
13
- children: node.children?.map((childNode, index) => /* @__PURE__ */ jsx(TableActionNode, { node: childNode }, childNode.key ?? childNode.id ?? `${childNode.type}-${index}`)) ?? null
13
+ children: node.schema?.map((childNode, index) => /* @__PURE__ */ jsx(TableActionNode, { node: childNode }, childNode.key ?? childNode.id ?? `${childNode.type}-${index}`)) ?? null
14
14
  });
15
15
  if (node.type === "link") return /* @__PURE__ */ jsx(LinkComponent, {
16
16
  node,
@@ -1 +1 @@
1
- {"version":3,"file":"table-action-node.js","names":[],"sources":["../../../resources/js/table/components/table-action-node.tsx"],"sourcesContent":["import type { Node } from \"@lattice/lattice/core/types\";\nimport ActionComponent from \"@lattice/lattice/action/components/action\";\nimport ActionGroupComponent from \"@lattice/lattice/action/components/action-group\";\nimport LinkComponent from \"@lattice/lattice/core/components/link\";\n\nexport function TableActionNode({ node }: { node: Node }) {\n if (node.type === \"action\") {\n return <ActionComponent node={node as Node<\"action\">}>{null}</ActionComponent>;\n }\n\n if (node.type === \"action.group\") {\n return (\n <ActionGroupComponent node={node as Node<\"action.group\">}>\n {node.children?.map((childNode, index) => (\n <TableActionNode\n key={childNode.key ?? childNode.id ?? `${childNode.type}-${index}`}\n node={childNode}\n />\n )) ?? null}\n </ActionGroupComponent>\n );\n }\n\n if (node.type === \"link\") {\n return <LinkComponent node={node as Node<\"link\">}>{null}</LinkComponent>;\n }\n\n return null;\n}\n"],"mappings":";;;;;AAKA,SAAgB,gBAAgB,EAAE,QAAwB;CACxD,IAAI,KAAK,SAAS,UAChB,OAAO,oBAAC,iBAAD;EAAuB;YAAyB;CAAsB,CAAA;CAG/E,IAAI,KAAK,SAAS,gBAChB,OACE,oBAAC,sBAAD;EAA4B;YACzB,KAAK,UAAU,KAAK,WAAW,UAC9B,oBAAC,iBAAD,EAEE,MAAM,UACP,GAFM,UAAU,OAAO,UAAU,MAAM,GAAG,UAAU,KAAK,GAAG,OAE5D,CACF,KAAK;CACc,CAAA;CAI1B,IAAI,KAAK,SAAS,QAChB,OAAO,oBAAC,eAAD;EAAqB;YAAuB;CAAoB,CAAA;CAGzE,OAAO;AACT"}
1
+ {"version":3,"file":"table-action-node.js","names":[],"sources":["../../../resources/js/table/components/table-action-node.tsx"],"sourcesContent":["import type { Node } from \"@lattice/lattice/core/types\";\nimport ActionComponent from \"@lattice/lattice/action/components/action\";\nimport ActionGroupComponent from \"@lattice/lattice/action/components/action-group\";\nimport LinkComponent from \"@lattice/lattice/core/components/link\";\n\nexport function TableActionNode({ node }: { node: Node }) {\n if (node.type === \"action\") {\n return <ActionComponent node={node as Node<\"action\">}>{null}</ActionComponent>;\n }\n\n if (node.type === \"action.group\") {\n return (\n <ActionGroupComponent node={node as Node<\"action.group\">}>\n {node.schema?.map((childNode, index) => (\n <TableActionNode\n key={childNode.key ?? childNode.id ?? `${childNode.type}-${index}`}\n node={childNode}\n />\n )) ?? null}\n </ActionGroupComponent>\n );\n }\n\n if (node.type === \"link\") {\n return <LinkComponent node={node as Node<\"link\">}>{null}</LinkComponent>;\n }\n\n return null;\n}\n"],"mappings":";;;;;AAKA,SAAgB,gBAAgB,EAAE,QAAwB;CACxD,IAAI,KAAK,SAAS,UAChB,OAAO,oBAAC,iBAAD;EAAuB;YAAyB;CAAsB,CAAA;CAG/E,IAAI,KAAK,SAAS,gBAChB,OACE,oBAAC,sBAAD;EAA4B;YACzB,KAAK,QAAQ,KAAK,WAAW,UAC5B,oBAAC,iBAAD,EAEE,MAAM,UACP,GAFM,UAAU,OAAO,UAAU,MAAM,GAAG,UAAU,KAAK,GAAG,OAE5D,CACF,KAAK;CACc,CAAA;CAI1B,IAAI,KAAK,SAAS,QAChB,OAAO,oBAAC,eAAD;EAAqB;YAAuB;CAAoB,CAAA;CAGzE,OAAO;AACT"}
@@ -2,4 +2,4 @@ import { TableColumn, TableRow } from '../types';
2
2
  export declare function ColumnCell({ column, row }: {
3
3
  column: TableColumn;
4
4
  row: TableRow;
5
- }): import("react").JSX.Element;
5
+ }): string | number | bigint | boolean | Iterable<import('react').ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<import('react').ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
@@ -1,10 +1,17 @@
1
- import { copyToClipboard } from "../../clipboard/index.js";
2
- import { formatCell, resolveLink } from "../format.js";
3
- import { useEffect, useState } from "react";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
- import { Check, Copy } from "lucide-react";
1
+ import { useColumnRegistry } from "../../provider.js";
2
+ import { BadgeCell } from "./cells/badge-cell.js";
3
+ import { IconCell } from "./cells/icon-cell.js";
4
+ import { ImageCell } from "./cells/image-cell.js";
5
+ import { TextCell } from "./cells/text-cell.js";
6
+ import { jsx } from "react/jsx-runtime";
6
7
  //#region resources/js/table/components/table-cell.tsx
7
8
  function ColumnCell({ column, row }) {
9
+ const customRenderer = useColumnRegistry()[column.type];
10
+ if (customRenderer) return customRenderer({
11
+ column,
12
+ row,
13
+ value: row[column.key]
14
+ });
8
15
  if (column.type === "stack") return /* @__PURE__ */ jsx("div", {
9
16
  className: "grid gap-1",
10
17
  children: (column.columns ?? []).map((stackedColumn) => /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(TextCell, {
@@ -13,50 +20,24 @@ function ColumnCell({ column, row }) {
13
20
  value: row[stackedColumn.key]
14
21
  }) }, stackedColumn.key))
15
22
  });
23
+ if (column.type === "badge") return /* @__PURE__ */ jsx(BadgeCell, {
24
+ column,
25
+ value: row[column.key]
26
+ });
27
+ if (column.type === "icon") return /* @__PURE__ */ jsx(IconCell, {
28
+ column,
29
+ value: row[column.key]
30
+ });
31
+ if (column.type === "image") return /* @__PURE__ */ jsx(ImageCell, {
32
+ column,
33
+ value: row[column.key]
34
+ });
16
35
  return /* @__PURE__ */ jsx(TextCell, {
17
36
  column,
18
37
  row,
19
38
  value: row[column.key]
20
39
  });
21
40
  }
22
- function TextCell({ column, row, value }) {
23
- const text = formatCell(value, column);
24
- const [copied, setCopied] = useState(false);
25
- const href = resolveLink(column, row, value);
26
- const content = href ? /* @__PURE__ */ jsx("a", {
27
- className: "underline underline-offset-2",
28
- href,
29
- rel: column.link?.external ? "noreferrer" : void 0,
30
- target: column.link?.external ? "_blank" : void 0,
31
- children: text
32
- }) : text;
33
- useEffect(() => {
34
- if (!copied) return;
35
- const timeout = window.setTimeout(() => setCopied(false), 1500);
36
- return () => window.clearTimeout(timeout);
37
- }, [copied]);
38
- function handleCopy() {
39
- copyToClipboard(text);
40
- setCopied(true);
41
- }
42
- if (!column.copyable) return content;
43
- return /* @__PURE__ */ jsxs("span", {
44
- className: "inline-flex items-center gap-2",
45
- children: [/* @__PURE__ */ jsx("span", { children: content }), /* @__PURE__ */ jsxs("button", {
46
- type: "button",
47
- className: "inline-flex items-center gap-1 rounded border border-lt-border px-2 py-1 text-xs",
48
- "aria-label": `${copied ? "Copied" : "Copy"} ${column.label}`,
49
- onClick: handleCopy,
50
- children: [copied ? /* @__PURE__ */ jsx(Check, {
51
- "aria-hidden": "true",
52
- className: "size-3"
53
- }) : /* @__PURE__ */ jsx(Copy, {
54
- "aria-hidden": "true",
55
- className: "size-3"
56
- }), copied ? "Copied" : "Copy"]
57
- })]
58
- });
59
- }
60
41
  //#endregion
61
42
  export { ColumnCell };
62
43