@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
@@ -0,0 +1,8 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
6
+ });
7
+ //#endregion
8
+ export { __commonJSMin, __require };
@@ -0,0 +1,24 @@
1
+ import { Node } from '../../core/types';
2
+ import { ActionResponse } from '../effects';
3
+ type ActionFormProps = {
4
+ cancelLabel: string;
5
+ componentRef: string;
6
+ description?: string;
7
+ endpoint: string;
8
+ /** Extra payload merged into every request, e.g. a bulk action's selection. */
9
+ extraData?: Record<string, unknown>;
10
+ /** The form to render; null while a lazy schema is still being fetched. */
11
+ formNode: Node | null;
12
+ method: string;
13
+ onClose: () => void;
14
+ onSuccess: (response: ActionResponse) => void;
15
+ submitLabel: string;
16
+ title: string;
17
+ };
18
+ /**
19
+ * Fetch a lazily-served form schema from the action endpoint while `enabled`,
20
+ * so it can be prefilled per record. Returns null until it arrives.
21
+ */
22
+ export declare function useLazyActionForm(endpoint: string, method: string, componentRef: string, enabled: boolean): Node | null;
23
+ export declare function ActionForm({ description, formNode, onClose, title, ...rest }: ActionFormProps): import("react").JSX.Element;
24
+ export {};
@@ -0,0 +1,270 @@
1
+ import { withRefHeader } from "../../core/component-ref.js";
2
+ import { Button } from "../../core/components/button.js";
3
+ import { Icon } from "../../icons/sprite.js";
4
+ import { useT } from "../../i18n/instance.js";
5
+ import { Spinner } from "../../core/components/spinner.js";
6
+ import { dispatchActionError } from "../effects.js";
7
+ import { Renderer, useRendererContext } from "../../core/renderer.js";
8
+ import { FormProvider } from "../../form/components/context.js";
9
+ import { walkFields } from "../../form/components/field-props.js";
10
+ import { xsrfToken } from "../../form/components/form-transport.js";
11
+ import { ResolvedNodesProvider } from "../../form/components/resolved-nodes.js";
12
+ import { FormValuesProvider, useFormValues } from "../../form/components/values.js";
13
+ import { useFormResolver } from "../../form/components/use-form-resolver.js";
14
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ import * as Dialog from "@radix-ui/react-dialog";
17
+ //#region resources/js/action/components/action-form.tsx
18
+ function jsonHeaders(componentRef, extra) {
19
+ return {
20
+ Accept: "application/json",
21
+ "Content-Type": "application/json",
22
+ "X-Requested-With": "XMLHttpRequest",
23
+ "X-XSRF-TOKEN": xsrfToken(),
24
+ ...withRefHeader(componentRef),
25
+ ...extra
26
+ };
27
+ }
28
+ /**
29
+ * Fetch a lazily-served form schema from the action endpoint while `enabled`,
30
+ * so it can be prefilled per record. Returns null until it arrives.
31
+ */
32
+ function useLazyActionForm(endpoint, method, componentRef, enabled) {
33
+ const [node, setNode] = useState(null);
34
+ useEffect(() => {
35
+ if (!enabled) {
36
+ setNode(null);
37
+ return;
38
+ }
39
+ const controller = new AbortController();
40
+ fetch(endpoint, {
41
+ body: JSON.stringify({ _form: true }),
42
+ credentials: "same-origin",
43
+ headers: jsonHeaders(componentRef),
44
+ method: method.toUpperCase(),
45
+ signal: controller.signal
46
+ }).then((response) => response.ok ? response.json() : null).then((fetched) => setNode(fetched)).catch(() => {});
47
+ return () => controller.abort();
48
+ }, [
49
+ enabled,
50
+ endpoint,
51
+ method,
52
+ componentRef
53
+ ]);
54
+ return node;
55
+ }
56
+ function firstErrors(errors) {
57
+ const result = {};
58
+ for (const [key, value] of Object.entries(errors ?? {})) result[key] = Array.isArray(value) ? value[0] : value;
59
+ return result;
60
+ }
61
+ function ActionFormSkeleton() {
62
+ return /* @__PURE__ */ jsxs("div", {
63
+ className: "space-y-4",
64
+ "data-lattice-action-form-loading": true,
65
+ children: [
66
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-24 animate-pulse rounded bg-lt-muted" }),
67
+ /* @__PURE__ */ jsx("div", { className: "h-10 w-full animate-pulse rounded bg-lt-muted" }),
68
+ /* @__PURE__ */ jsx("div", { className: "h-10 w-full animate-pulse rounded bg-lt-muted" })
69
+ ]
70
+ });
71
+ }
72
+ function collectFields(formNode) {
73
+ const labels = {};
74
+ const values = {};
75
+ walkFields(formNode.schema, (props) => {
76
+ if (!props.name) return;
77
+ if (props.label) labels[props.name] = props.label;
78
+ if (props.value !== void 0) values[props.name] = props.value;
79
+ });
80
+ return {
81
+ labels,
82
+ values: {
83
+ ...values,
84
+ ...formNode.props?.state
85
+ }
86
+ };
87
+ }
88
+ function ActionFormBody({ cancelLabel, componentRef, endpoint, extraData, fieldLabels, formNode, method, onClose, onSuccess, precognitive, submitLabel }) {
89
+ const { fallback, missingComponent, registry } = useRendererContext();
90
+ const values = useFormValues();
91
+ const valuesRef = useRef(values);
92
+ valuesRef.current = values;
93
+ const extraDataRef = useRef(extraData);
94
+ extraDataRef.current = extraData;
95
+ const resolvedNodes = useFormResolver(endpoint, componentRef, formNode.schema);
96
+ const [errors, setErrors] = useState({});
97
+ const [processing, setProcessing] = useState(false);
98
+ const timer = useRef(void 0);
99
+ const request = useCallback((extraHeaders) => fetch(endpoint, {
100
+ body: JSON.stringify({
101
+ ...valuesRef.current,
102
+ ...extraDataRef.current
103
+ }),
104
+ credentials: "same-origin",
105
+ method: method.toUpperCase(),
106
+ headers: jsonHeaders(componentRef, extraHeaders)
107
+ }), [
108
+ componentRef,
109
+ endpoint,
110
+ method
111
+ ]);
112
+ const clearErrors = useCallback((field) => {
113
+ setErrors((current) => current[field] === void 0 ? current : {
114
+ ...current,
115
+ [field]: void 0
116
+ });
117
+ }, []);
118
+ const validate = useCallback((field) => {
119
+ if (!precognitive) return;
120
+ window.clearTimeout(timer.current);
121
+ timer.current = window.setTimeout(() => {
122
+ request({
123
+ Precognition: "true",
124
+ "Precognition-Validate-Only": field
125
+ }).then(async (response) => {
126
+ if (response.status === 422) {
127
+ const body = await response.json();
128
+ setErrors((current) => ({
129
+ ...current,
130
+ ...firstErrors(body.errors)
131
+ }));
132
+ return;
133
+ }
134
+ clearErrors(field);
135
+ }).catch(() => {});
136
+ }, 250);
137
+ }, [
138
+ clearErrors,
139
+ precognitive,
140
+ request
141
+ ]);
142
+ const submit = useCallback(() => {
143
+ setProcessing(true);
144
+ request().then(async (response) => {
145
+ if (response.status === 422) {
146
+ setErrors(firstErrors((await response.json()).errors));
147
+ return;
148
+ }
149
+ if (!response.ok) {
150
+ dispatchActionError(/* @__PURE__ */ new Error(`Action request failed with status ${response.status}`));
151
+ return;
152
+ }
153
+ onSuccess(await response.json());
154
+ }).catch((error) => dispatchActionError(error)).finally(() => setProcessing(false));
155
+ }, [onSuccess, request]);
156
+ return /* @__PURE__ */ jsx(FormProvider, {
157
+ value: useMemo(() => ({
158
+ action: endpoint,
159
+ clearErrors,
160
+ componentRef,
161
+ errors,
162
+ fieldLabels,
163
+ precognitive,
164
+ processing,
165
+ validate
166
+ }), [
167
+ clearErrors,
168
+ componentRef,
169
+ endpoint,
170
+ errors,
171
+ fieldLabels,
172
+ precognitive,
173
+ processing,
174
+ validate
175
+ ]),
176
+ children: /* @__PURE__ */ jsxs("form", {
177
+ className: "flex flex-col gap-6",
178
+ onSubmit: (event) => {
179
+ event.preventDefault();
180
+ submit();
181
+ },
182
+ children: [/* @__PURE__ */ jsx(ResolvedNodesProvider, {
183
+ nodes: resolvedNodes,
184
+ children: /* @__PURE__ */ jsx(Renderer, {
185
+ fallback,
186
+ missingComponent,
187
+ nodes: formNode.schema ?? [],
188
+ registry
189
+ })
190
+ }), /* @__PURE__ */ jsxs("div", {
191
+ className: "flex justify-end gap-3",
192
+ children: [/* @__PURE__ */ jsx(Button, {
193
+ "data-test": "action-form-cancel",
194
+ disabled: processing,
195
+ onClick: onClose,
196
+ type: "button",
197
+ variant: "ghost",
198
+ children: cancelLabel
199
+ }), /* @__PURE__ */ jsxs(Button, {
200
+ "data-test": "action-form-submit",
201
+ disabled: processing,
202
+ type: "submit",
203
+ children: [processing && /* @__PURE__ */ jsx(Spinner, {}), submitLabel]
204
+ })]
205
+ })]
206
+ })
207
+ });
208
+ }
209
+ function ActionFormContent({ formNode, ...rest }) {
210
+ const precognitive = Boolean(formNode.props?.precognitive);
211
+ const { labels: fieldLabels, values: initialValues } = useMemo(() => collectFields(formNode), [formNode]);
212
+ return /* @__PURE__ */ jsx(FormValuesProvider, {
213
+ initial: initialValues,
214
+ children: /* @__PURE__ */ jsx(ActionFormBody, {
215
+ fieldLabels,
216
+ formNode,
217
+ precognitive,
218
+ ...rest
219
+ })
220
+ });
221
+ }
222
+ function ActionForm({ description, formNode, onClose, title, ...rest }) {
223
+ const { t } = useT("lattice");
224
+ return /* @__PURE__ */ jsx(Dialog.Root, {
225
+ open: true,
226
+ onOpenChange: (open) => {
227
+ if (!open) onClose();
228
+ },
229
+ children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/50" }), /* @__PURE__ */ jsxs(Dialog.Content, {
230
+ ...description ? {} : { "aria-describedby": void 0 },
231
+ className: "fixed left-1/2 top-1/2 z-50 max-h-[min(680px,calc(100vh-2rem))] w-full max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-lt border border-lt-border bg-lt-bg p-6 shadow-lg",
232
+ children: [/* @__PURE__ */ jsxs("div", {
233
+ className: "flex items-start justify-between gap-4",
234
+ children: [/* @__PURE__ */ jsxs("div", {
235
+ className: "grid gap-2",
236
+ children: [/* @__PURE__ */ jsx(Dialog.Title, {
237
+ className: "text-lg font-semibold leading-none tracking-tight",
238
+ children: title
239
+ }), description && /* @__PURE__ */ jsx(Dialog.Description, {
240
+ className: "text-sm text-lt-muted-fg",
241
+ children: description
242
+ })]
243
+ }), /* @__PURE__ */ jsx(Dialog.Close, {
244
+ asChild: true,
245
+ children: /* @__PURE__ */ jsx(Button, {
246
+ "aria-label": t("a11y.close", "Close"),
247
+ size: "icon",
248
+ variant: "ghost",
249
+ children: /* @__PURE__ */ jsx(Icon, {
250
+ name: "x",
251
+ "aria-hidden": "true",
252
+ className: "size-lt-icon-md"
253
+ })
254
+ })
255
+ })]
256
+ }), /* @__PURE__ */ jsx("div", {
257
+ className: "mt-6",
258
+ children: formNode ? /* @__PURE__ */ jsx(ActionFormContent, {
259
+ formNode,
260
+ onClose,
261
+ ...rest
262
+ }) : /* @__PURE__ */ jsx(ActionFormSkeleton, {})
263
+ })]
264
+ })] })
265
+ });
266
+ }
267
+ //#endregion
268
+ export { ActionForm, useLazyActionForm };
269
+
270
+ //# sourceMappingURL=action-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-form.js","names":[],"sources":["../../../resources/js/action/components/action-form.tsx"],"sourcesContent":["import { Icon } from \"@lattice/lattice/icons\";\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { withRefHeader } from \"@lattice/lattice/core/component-ref\";\nimport { Button } from \"@lattice/lattice/core/components/button\";\nimport { Spinner } from \"@lattice/lattice/core/components/spinner\";\nimport { Renderer, useRendererContext } from \"@lattice/lattice/core/renderer\";\nimport type { Node } from \"@lattice/lattice/core/types\";\nimport { FormProvider } from \"@lattice/lattice/form/components/context\";\nimport { walkFields } from \"@lattice/lattice/form/components/field-props\";\nimport { FORM_DEBOUNCE_MS, xsrfToken } from \"@lattice/lattice/form/components/form-transport\";\nimport { ResolvedNodesProvider } from \"@lattice/lattice/form/components/resolved-nodes\";\nimport { useFormResolver } from \"@lattice/lattice/form/components/use-form-resolver\";\nimport { FormValuesProvider, useFormValues } from \"@lattice/lattice/form/components/values\";\nimport { useT } from \"@lattice/lattice/i18n\";\nimport { dispatchActionError } from \"../effects\";\nimport type { ActionResponse } from \"../effects\";\n\ntype FieldErrors = Record<string, string | undefined>;\n\ntype ActionFormProps = {\n cancelLabel: string;\n componentRef: string;\n description?: string;\n endpoint: string;\n /** Extra payload merged into every request, e.g. a bulk action's selection. */\n extraData?: Record<string, unknown>;\n /** The form to render; null while a lazy schema is still being fetched. */\n formNode: Node | null;\n method: string;\n onClose: () => void;\n onSuccess: (response: ActionResponse) => void;\n submitLabel: string;\n title: string;\n};\n\nfunction jsonHeaders(componentRef: string, extra?: Record<string, string>): Record<string, string> {\n return {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"X-Requested-With\": \"XMLHttpRequest\",\n \"X-XSRF-TOKEN\": xsrfToken(),\n ...withRefHeader(componentRef),\n ...extra,\n };\n}\n\n/**\n * Fetch a lazily-served form schema from the action endpoint while `enabled`,\n * so it can be prefilled per record. Returns null until it arrives.\n */\nexport function useLazyActionForm(\n endpoint: string,\n method: string,\n componentRef: string,\n enabled: boolean,\n): Node | null {\n const [node, setNode] = useState<Node | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n setNode(null);\n\n return;\n }\n\n const controller = new AbortController();\n\n void fetch(endpoint, {\n body: JSON.stringify({ _form: true }),\n credentials: \"same-origin\",\n headers: jsonHeaders(componentRef),\n method: method.toUpperCase(),\n signal: controller.signal,\n })\n .then((response) => (response.ok ? (response.json() as Promise<Node>) : null))\n .then((fetched) => setNode(fetched))\n .catch(() => {});\n\n return () => controller.abort();\n }, [enabled, endpoint, method, componentRef]);\n\n return node;\n}\n\nfunction firstErrors(errors: Record<string, string[] | string> | undefined): FieldErrors {\n const result: FieldErrors = {};\n\n for (const [key, value] of Object.entries(errors ?? {})) {\n result[key] = Array.isArray(value) ? value[0] : value;\n }\n\n return result;\n}\n\nfunction ActionFormSkeleton() {\n return (\n <div className=\"space-y-4\" data-lattice-action-form-loading>\n <div className=\"h-4 w-24 animate-pulse rounded bg-lt-muted\" />\n <div className=\"h-10 w-full animate-pulse rounded bg-lt-muted\" />\n <div className=\"h-10 w-full animate-pulse rounded bg-lt-muted\" />\n </div>\n );\n}\n\ntype CollectedFields = {\n labels: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nfunction collectFields(formNode: Node): CollectedFields {\n const labels: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n\n walkFields(formNode.schema, (props) => {\n if (!props.name) {\n return;\n }\n if (props.label) {\n labels[props.name] = props.label;\n }\n if (props.value !== undefined) {\n values[props.name] = props.value;\n }\n });\n\n return {\n labels,\n values: { ...values, ...(formNode.props?.state as Record<string, unknown> | undefined) },\n };\n}\n\nfunction ActionFormBody({\n cancelLabel,\n componentRef,\n endpoint,\n extraData,\n fieldLabels,\n formNode,\n method,\n onClose,\n onSuccess,\n precognitive,\n submitLabel,\n}: Omit<ActionFormProps, \"description\" | \"title\"> & {\n fieldLabels: Record<string, string>;\n formNode: Node;\n precognitive: boolean;\n}) {\n const { fallback, missingComponent, registry } = useRendererContext();\n const values = useFormValues();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n const extraDataRef = useRef(extraData);\n extraDataRef.current = extraData;\n const resolvedNodes = useFormResolver(endpoint, componentRef, formNode.schema);\n\n const [errors, setErrors] = useState<FieldErrors>({});\n const [processing, setProcessing] = useState(false);\n const timer = useRef<number | undefined>(undefined);\n\n const request = useCallback(\n (extraHeaders?: Record<string, string>): Promise<Response> =>\n fetch(endpoint, {\n body: JSON.stringify({ ...valuesRef.current, ...extraDataRef.current }),\n credentials: \"same-origin\",\n // fetch only upper-cases the standardized methods, leaving PATCH/DELETE as\n // given; some servers reject a lower-case method line, so normalize it.\n method: method.toUpperCase(),\n headers: jsonHeaders(componentRef, extraHeaders),\n }),\n [componentRef, endpoint, method],\n );\n\n const clearErrors = useCallback((field: string) => {\n setErrors((current) =>\n current[field] === undefined ? current : { ...current, [field]: undefined },\n );\n }, []);\n\n const validate = useCallback(\n (field: string) => {\n if (!precognitive) {\n return;\n }\n\n window.clearTimeout(timer.current);\n timer.current = window.setTimeout(() => {\n void request({ Precognition: \"true\", \"Precognition-Validate-Only\": field })\n .then(async (response) => {\n if (response.status === 422) {\n const body = (await response.json()) as { errors?: Record<string, string[]> };\n setErrors((current) => ({ ...current, ...firstErrors(body.errors) }));\n\n return;\n }\n\n clearErrors(field);\n })\n .catch(() => {});\n }, FORM_DEBOUNCE_MS);\n },\n [clearErrors, precognitive, request],\n );\n\n const submit = useCallback(() => {\n setProcessing(true);\n\n void request()\n .then(async (response) => {\n if (response.status === 422) {\n const body = (await response.json()) as { errors?: Record<string, string[]> };\n setErrors(firstErrors(body.errors));\n\n return;\n }\n\n if (!response.ok) {\n dispatchActionError(new Error(`Action request failed with status ${response.status}`));\n\n return;\n }\n\n onSuccess((await response.json()) as ActionResponse);\n })\n .catch((error: unknown) => dispatchActionError(error))\n .finally(() => setProcessing(false));\n }, [onSuccess, request]);\n\n const context = useMemo(\n () => ({\n action: endpoint,\n clearErrors,\n componentRef,\n errors,\n fieldLabels,\n precognitive,\n processing,\n validate,\n }),\n [clearErrors, componentRef, endpoint, errors, fieldLabels, precognitive, processing, validate],\n );\n\n return (\n <FormProvider value={context}>\n <form\n className=\"flex flex-col gap-6\"\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n >\n <ResolvedNodesProvider nodes={resolvedNodes}>\n <Renderer\n fallback={fallback}\n missingComponent={missingComponent}\n nodes={formNode.schema ?? []}\n registry={registry}\n />\n </ResolvedNodesProvider>\n\n <div className=\"flex justify-end gap-3\">\n <Button\n data-test=\"action-form-cancel\"\n disabled={processing}\n onClick={onClose}\n type=\"button\"\n variant=\"ghost\"\n >\n {cancelLabel}\n </Button>\n\n <Button data-test=\"action-form-submit\" disabled={processing} type=\"submit\">\n {processing && <Spinner />}\n {submitLabel}\n </Button>\n </div>\n </form>\n </FormProvider>\n );\n}\n\nfunction ActionFormContent({\n formNode,\n ...rest\n}: Omit<ActionFormProps, \"description\" | \"title\"> & { formNode: Node }) {\n const precognitive = Boolean(formNode.props?.precognitive);\n const { labels: fieldLabels, values: initialValues } = useMemo(\n () => collectFields(formNode),\n [formNode],\n );\n\n return (\n <FormValuesProvider initial={initialValues}>\n <ActionFormBody\n fieldLabels={fieldLabels}\n formNode={formNode}\n precognitive={precognitive}\n {...rest}\n />\n </FormValuesProvider>\n );\n}\n\nexport function ActionForm({ description, formNode, onClose, title, ...rest }: ActionFormProps) {\n const { t } = useT(\"lattice\");\n\n return (\n <Dialog.Root\n open\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n }\n }}\n >\n <Dialog.Portal>\n <Dialog.Overlay className=\"fixed inset-0 z-50 bg-black/50\" />\n <Dialog.Content\n {...(description ? {} : { \"aria-describedby\": undefined })}\n className=\"fixed left-1/2 top-1/2 z-50 max-h-[min(680px,calc(100vh-2rem))] w-full max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-lt border border-lt-border bg-lt-bg p-6 shadow-lg\"\n >\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"grid gap-2\">\n <Dialog.Title className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </Dialog.Title>\n\n {description && (\n <Dialog.Description className=\"text-sm text-lt-muted-fg\">\n {description}\n </Dialog.Description>\n )}\n </div>\n\n <Dialog.Close asChild>\n <Button aria-label={t(\"a11y.close\", \"Close\")} size=\"icon\" variant=\"ghost\">\n <Icon name=\"x\" aria-hidden=\"true\" className=\"size-lt-icon-md\" />\n </Button>\n </Dialog.Close>\n </div>\n\n <div className=\"mt-6\">\n {formNode ? (\n <ActionFormContent formNode={formNode} onClose={onClose} {...rest} />\n ) : (\n <ActionFormSkeleton />\n )}\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n"],"mappings":"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"}
@@ -1,10 +1,3 @@
1
- import { RendererComponent } from '../../../../core/types';
2
- declare module '../../../../core/types' {
3
- interface ComponentProps {
4
- "action.group": {
5
- label?: string;
6
- };
7
- }
8
- }
1
+ import { RendererComponent } from '../../core/types';
9
2
  declare const ActionGroupComponent: RendererComponent<"action.group">;
10
3
  export default ActionGroupComponent;
@@ -1,76 +1,34 @@
1
- import { getStringProp } from "../../core/props.js";
2
1
  import { Button } from "../../core/components/button.js";
3
- import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { Icon } from "../../icons/sprite.js";
4
3
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import { MoreHorizontal } from "lucide-react";
6
- import { createPortal } from "react-dom";
4
+ import * as Popover from "@radix-ui/react-popover";
7
5
  //#region resources/js/action/components/action-group.tsx
8
6
  var ActionGroupComponent = ({ children, node }) => {
9
- const label = getStringProp(node.props, "label", "Actions");
10
- const [open, setOpen] = useState(false);
11
- const [position, setPosition] = useState(null);
12
- const buttonRef = useRef(null);
13
- const menuRef = useRef(null);
14
- const updatePosition = useCallback(() => {
15
- const rect = buttonRef.current?.getBoundingClientRect();
16
- if (!rect) return;
17
- setPosition({
18
- right: Math.max(8, window.innerWidth - rect.right),
19
- top: rect.bottom + 8
20
- });
21
- }, []);
22
- useEffect(() => {
23
- if (!open) return;
24
- updatePosition();
25
- const closeWhenOutside = (event) => {
26
- const target = event.target;
27
- if (target instanceof Node && (buttonRef.current?.contains(target) || menuRef.current?.contains(target))) return;
28
- setOpen(false);
29
- };
30
- const closeOnEscape = (event) => {
31
- if (event.key === "Escape") setOpen(false);
32
- };
33
- window.addEventListener("resize", updatePosition);
34
- window.addEventListener("scroll", updatePosition, true);
35
- document.addEventListener("mousedown", closeWhenOutside);
36
- document.addEventListener("keydown", closeOnEscape);
37
- return () => {
38
- window.removeEventListener("resize", updatePosition);
39
- window.removeEventListener("scroll", updatePosition, true);
40
- document.removeEventListener("mousedown", closeWhenOutside);
41
- document.removeEventListener("keydown", closeOnEscape);
42
- };
43
- }, [open, updatePosition]);
44
- const toggle = () => {
45
- updatePosition();
46
- setOpen((current) => !current);
47
- };
48
- const menu = open && position && typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsx("div", {
49
- ref: menuRef,
50
- "aria-label": label,
51
- className: "fixed z-50 grid min-w-40 gap-1 rounded-lt-sm border border-lt-border bg-lt-popover p-1 text-lt-popover-fg shadow-md [&>button]:w-full [&>button]:justify-start",
52
- role: "menu",
53
- style: position,
54
- children
55
- }), document.body) : null;
56
- return /* @__PURE__ */ jsxs("div", {
7
+ const label = node.props.label;
8
+ return /* @__PURE__ */ jsx("div", {
57
9
  className: "inline-flex",
58
10
  "data-lattice-component": node.id,
59
- children: [/* @__PURE__ */ jsx(Button, {
60
- ref: buttonRef,
61
- "aria-label": label,
62
- "aria-expanded": open,
63
- "aria-haspopup": "menu",
64
- className: "size-8 text-lt-muted-fg shadow-none hover:text-lt-fg",
65
- onClick: toggle,
66
- size: "icon",
67
- type: "button",
68
- variant: "ghost",
69
- children: /* @__PURE__ */ jsx(MoreHorizontal, {
70
- "aria-hidden": "true",
71
- className: "size-4"
11
+ children: /* @__PURE__ */ jsxs(Popover.Root, { children: [/* @__PURE__ */ jsx(Popover.Trigger, {
12
+ asChild: true,
13
+ children: /* @__PURE__ */ jsx(Button, {
14
+ "aria-label": label,
15
+ className: "size-8 text-lt-muted-fg shadow-none hover:text-lt-fg",
16
+ size: "icon",
17
+ type: "button",
18
+ variant: "ghost",
19
+ children: /* @__PURE__ */ jsx(Icon, {
20
+ name: "more-horizontal",
21
+ "aria-hidden": "true",
22
+ className: "size-lt-icon-md"
23
+ })
72
24
  })
73
- }), menu]
25
+ }), /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Content, {
26
+ align: "end",
27
+ "aria-label": label,
28
+ className: "z-50 grid min-w-40 gap-1 rounded-lt-sm border border-lt-border bg-lt-popover p-1 text-lt-popover-fg shadow-md [&>button]:w-full [&>button]:justify-start",
29
+ sideOffset: 8,
30
+ children
31
+ }) })] })
74
32
  });
75
33
  };
76
34
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"action-group.js","names":[],"sources":["../../../resources/js/action/components/action-group.tsx"],"sourcesContent":["import { MoreHorizontal } from \"lucide-react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"@lattice/lattice/core/components/button\";\nimport { getStringProp } from \"@lattice/lattice/core/props\";\nimport type { RendererComponent } from \"@lattice/lattice/core/types\";\n\ndeclare module \"@lattice/lattice/core/types\" {\n interface ComponentProps {\n \"action.group\": {\n label?: string;\n };\n }\n}\n\nconst ActionGroupComponent: RendererComponent<\"action.group\"> = ({ children, node }) => {\n const label = getStringProp(node.props, \"label\", \"Actions\");\n const [open, setOpen] = useState(false);\n const [position, setPosition] = useState<{ right: number; top: number } | null>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const updatePosition = useCallback(() => {\n const rect = buttonRef.current?.getBoundingClientRect();\n\n if (!rect) {\n return;\n }\n\n setPosition({\n right: Math.max(8, window.innerWidth - rect.right),\n top: rect.bottom + 8,\n });\n }, []);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n updatePosition();\n\n const closeWhenOutside = (event: MouseEvent): void => {\n const target = event.target;\n\n if (\n target instanceof Node &&\n (buttonRef.current?.contains(target) || menuRef.current?.contains(target))\n ) {\n return;\n }\n\n setOpen(false);\n };\n\n const closeOnEscape = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n setOpen(false);\n }\n };\n\n window.addEventListener(\"resize\", updatePosition);\n window.addEventListener(\"scroll\", updatePosition, true);\n document.addEventListener(\"mousedown\", closeWhenOutside);\n document.addEventListener(\"keydown\", closeOnEscape);\n\n return () => {\n window.removeEventListener(\"resize\", updatePosition);\n window.removeEventListener(\"scroll\", updatePosition, true);\n document.removeEventListener(\"mousedown\", closeWhenOutside);\n document.removeEventListener(\"keydown\", closeOnEscape);\n };\n }, [open, updatePosition]);\n\n const toggle = (): void => {\n updatePosition();\n setOpen((current) => !current);\n };\n\n const menu =\n open && position && typeof document !== \"undefined\"\n ? createPortal(\n <div\n ref={menuRef}\n aria-label={label}\n className=\"fixed z-50 grid min-w-40 gap-1 rounded-lt-sm border border-lt-border bg-lt-popover p-1 text-lt-popover-fg shadow-md [&>button]:w-full [&>button]:justify-start\"\n role=\"menu\"\n style={position}\n >\n {children}\n </div>,\n document.body,\n )\n : null;\n\n return (\n <div className=\"inline-flex\" data-lattice-component={node.id}>\n <Button\n ref={buttonRef}\n aria-label={label}\n aria-expanded={open}\n aria-haspopup=\"menu\"\n className=\"size-8 text-lt-muted-fg shadow-none hover:text-lt-fg\"\n onClick={toggle}\n size=\"icon\"\n type=\"button\"\n variant=\"ghost\"\n >\n <MoreHorizontal aria-hidden=\"true\" className=\"size-4\" />\n </Button>\n\n {menu}\n </div>\n );\n};\n\nexport default ActionGroupComponent;\n"],"mappings":";;;;;;;AAeA,IAAM,wBAA2D,EAAE,UAAU,WAAW;CACtF,MAAM,QAAQ,cAAc,KAAK,OAAO,SAAS,SAAS;CAC1D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,UAAU,eAAe,SAAgD,IAAI;CACpF,MAAM,YAAY,OAA0B,IAAI;CAChD,MAAM,UAAU,OAAuB,IAAI;CAE3C,MAAM,iBAAiB,kBAAkB;EACvC,MAAM,OAAO,UAAU,SAAS,sBAAsB;EAEtD,IAAI,CAAC,MACH;EAGF,YAAY;GACV,OAAO,KAAK,IAAI,GAAG,OAAO,aAAa,KAAK,KAAK;GACjD,KAAK,KAAK,SAAS;EACrB,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,gBAAgB;EACd,IAAI,CAAC,MACH;EAGF,eAAe;EAEf,MAAM,oBAAoB,UAA4B;GACpD,MAAM,SAAS,MAAM;GAErB,IACE,kBAAkB,SACjB,UAAU,SAAS,SAAS,MAAM,KAAK,QAAQ,SAAS,SAAS,MAAM,IAExE;GAGF,QAAQ,KAAK;EACf;EAEA,MAAM,iBAAiB,UAA+B;GACpD,IAAI,MAAM,QAAQ,UAChB,QAAQ,KAAK;EAEjB;EAEA,OAAO,iBAAiB,UAAU,cAAc;EAChD,OAAO,iBAAiB,UAAU,gBAAgB,IAAI;EACtD,SAAS,iBAAiB,aAAa,gBAAgB;EACvD,SAAS,iBAAiB,WAAW,aAAa;EAElD,aAAa;GACX,OAAO,oBAAoB,UAAU,cAAc;GACnD,OAAO,oBAAoB,UAAU,gBAAgB,IAAI;GACzD,SAAS,oBAAoB,aAAa,gBAAgB;GAC1D,SAAS,oBAAoB,WAAW,aAAa;EACvD;CACF,GAAG,CAAC,MAAM,cAAc,CAAC;CAEzB,MAAM,eAAqB;EACzB,eAAe;EACf,SAAS,YAAY,CAAC,OAAO;CAC/B;CAEA,MAAM,OACJ,QAAQ,YAAY,OAAO,aAAa,cACpC,aACE,oBAAC,OAAD;EACE,KAAK;EACL,cAAY;EACZ,WAAU;EACV,MAAK;EACL,OAAO;EAEN;CACE,CAAA,GACL,SAAS,IACX,IACA;CAEN,OACE,qBAAC,OAAD;EAAK,WAAU;EAAc,0BAAwB,KAAK;YAA1D,CACE,oBAAC,QAAD;GACE,KAAK;GACL,cAAY;GACZ,iBAAe;GACf,iBAAc;GACd,WAAU;GACV,SAAS;GACT,MAAK;GACL,MAAK;GACL,SAAQ;aAER,oBAAC,gBAAD;IAAgB,eAAY;IAAO,WAAU;GAAU,CAAA;EACjD,CAAA,GAEP,IACE;;AAET"}
1
+ {"version":3,"file":"action-group.js","names":[],"sources":["../../../resources/js/action/components/action-group.tsx"],"sourcesContent":["import { Icon } from \"@lattice/lattice/icons\";\nimport * as Popover from \"@radix-ui/react-popover\";\nimport { Button } from \"@lattice/lattice/core/components/button\";\nimport type { RendererComponent } from \"@lattice/lattice/core/types\";\n\nconst ActionGroupComponent: RendererComponent<\"action.group\"> = ({ children, node }) => {\n const label = node.props.label;\n\n return (\n <div className=\"inline-flex\" data-lattice-component={node.id}>\n <Popover.Root>\n <Popover.Trigger asChild>\n <Button\n aria-label={label}\n className=\"size-8 text-lt-muted-fg shadow-none hover:text-lt-fg\"\n size=\"icon\"\n type=\"button\"\n variant=\"ghost\"\n >\n <Icon name=\"more-horizontal\" aria-hidden=\"true\" className=\"size-lt-icon-md\" />\n </Button>\n </Popover.Trigger>\n\n <Popover.Portal>\n <Popover.Content\n align=\"end\"\n aria-label={label}\n className=\"z-50 grid min-w-40 gap-1 rounded-lt-sm border border-lt-border bg-lt-popover p-1 text-lt-popover-fg shadow-md [&>button]:w-full [&>button]:justify-start\"\n sideOffset={8}\n >\n {children}\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n </div>\n );\n};\n\nexport default ActionGroupComponent;\n"],"mappings":";;;;;AAKA,IAAM,wBAA2D,EAAE,UAAU,WAAW;CACtF,MAAM,QAAQ,KAAK,MAAM;CAEzB,OACE,oBAAC,OAAD;EAAK,WAAU;EAAc,0BAAwB,KAAK;YACxD,qBAAC,QAAQ,MAAT,EAAA,UAAA,CACE,oBAAC,QAAQ,SAAT;GAAiB,SAAA;aACf,oBAAC,QAAD;IACE,cAAY;IACZ,WAAU;IACV,MAAK;IACL,MAAK;IACL,SAAQ;cAER,oBAAC,MAAD;KAAM,MAAK;KAAkB,eAAY;KAAO,WAAU;IAAmB,CAAA;GACvE,CAAA;EACO,CAAA,GAEjB,oBAAC,QAAQ,QAAT,EAAA,UACE,oBAAC,QAAQ,SAAT;GACE,OAAM;GACN,cAAY;GACZ,WAAU;GACV,YAAY;GAEX;EACc,CAAA,EACH,CAAA,CACJ,EAAA,CAAA;CACX,CAAA;AAET"}
@@ -1,26 +1,3 @@
1
- import { Method } from '@inertiajs/core';
2
- import { RendererComponent } from '../../../../core/types';
3
- import { ActionEffect } from '../effects';
4
- type ActionVariant = "default" | "destructive" | "ghost" | "link" | "outline" | "secondary";
5
- type ActionConfirmation = {
6
- cancelLabel?: string;
7
- confirmLabel?: string;
8
- description?: string;
9
- title?: string;
10
- };
11
- declare module '../../../../core/types' {
12
- interface ComponentProps {
13
- action: {
14
- confirmation?: ActionConfirmation;
15
- effects?: ActionEffect[];
16
- endpoint?: string;
17
- icon?: string;
18
- label?: string;
19
- ref?: string;
20
- method?: Method;
21
- variant?: ActionVariant;
22
- };
23
- }
24
- }
1
+ import { RendererComponent } from '../../core/types';
25
2
  declare const ActionComponent: RendererComponent<"action">;
26
3
  export default ActionComponent;
@@ -1,39 +1,30 @@
1
1
  import { withRefHeader } from "../../core/component-ref.js";
2
- import { getStringProp } from "../../core/props.js";
3
2
  import { Button } from "../../core/components/button.js";
3
+ import { IconRenderer } from "../../icons/icon-renderer.js";
4
4
  import { Spinner } from "../../core/components/spinner.js";
5
5
  import { ConfirmDialog } from "../../core/components/confirm-dialog.js";
6
- import { IconRenderer } from "../../icons/icon-renderer.js";
7
6
  import { dispatchActionEffects, dispatchActionError, getActionEffects } from "../effects.js";
7
+ import { ActionForm, useLazyActionForm } from "./action-form.js";
8
8
  import { useState } from "react";
9
9
  import { router, useHttp } from "@inertiajs/react";
10
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region resources/js/action/components/action.tsx
12
- var actionMethods = [
13
- "delete",
14
- "get",
15
- "patch",
16
- "post",
17
- "put"
18
- ];
19
- function getActionMethod(props) {
20
- const method = getStringProp(props, "method", "post");
21
- return actionMethods.includes(method) ? method : "post";
22
- }
23
- function getConfirmation(props) {
24
- const confirmation = props?.confirmation;
25
- if (typeof confirmation !== "object" || confirmation === null || Array.isArray(confirmation)) return null;
26
- return confirmation;
27
- }
28
12
  var ActionComponent = ({ node }) => {
29
- const endpoint = getStringProp(node.props, "endpoint");
30
- const icon = getStringProp(node.props, "icon");
31
- const label = getStringProp(node.props, "label", "Run action");
32
- const componentRef = getStringProp(node.props, "ref");
33
- const method = getActionMethod(node.props);
13
+ const endpoint = node.props.endpoint ?? "";
14
+ const icon = node.props.icon;
15
+ const label = node.props.label ?? "Run action";
16
+ const componentRef = node.props.ref ?? "";
17
+ const method = node.props.method ?? "post";
34
18
  const http = useHttp({});
35
19
  const [isConfirming, setIsConfirming] = useState(false);
36
- const confirmation = getConfirmation(node.props);
20
+ const [isFilling, setIsFilling] = useState(false);
21
+ const confirmation = node.props.confirmation;
22
+ const variant = node.props.variant ?? "default";
23
+ const inlineForm = node.props.form;
24
+ const lazyForm = node.props.lazyForm === true;
25
+ const hasForm = Boolean(inlineForm) || lazyForm;
26
+ const lazyNode = useLazyActionForm(endpoint, method, componentRef, isFilling && lazyForm);
27
+ const formNode = lazyForm ? lazyNode : inlineForm;
37
28
  const submit = async () => {
38
29
  if (!endpoint) return;
39
30
  try {
@@ -43,13 +34,17 @@ var ActionComponent = ({ node }) => {
43
34
  return;
44
35
  }
45
36
  const responseEffects = getActionEffects((await http[method](endpoint, { headers: withRefHeader(componentRef) })).effects);
46
- dispatchActionEffects(responseEffects.length > 0 ? responseEffects : getActionEffects(node.props?.effects));
37
+ dispatchActionEffects(responseEffects.length > 0 ? responseEffects : getActionEffects(node.props.effects));
47
38
  setIsConfirming(false);
48
39
  } catch (error) {
49
40
  dispatchActionError(error);
50
41
  }
51
42
  };
52
43
  const requestSubmit = () => {
44
+ if (hasForm) {
45
+ setIsFilling(true);
46
+ return;
47
+ }
53
48
  if (confirmation) {
54
49
  setIsConfirming(true);
55
50
  return;
@@ -59,27 +54,47 @@ var ActionComponent = ({ node }) => {
59
54
  const confirmationTitle = confirmation?.title ?? label;
60
55
  const confirmationConfirmLabel = confirmation?.confirmLabel ?? label;
61
56
  const confirmationCancelLabel = confirmation?.cancelLabel ?? "Cancel";
62
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Button, {
63
- "data-lattice-component": node.id,
64
- disabled: http.processing || !endpoint,
65
- onClick: requestSubmit,
66
- type: "button",
67
- variant: node.props?.variant ?? "default",
68
- children: [http.processing ? /* @__PURE__ */ jsx(Spinner, {}) : icon && /* @__PURE__ */ jsx(IconRenderer, {
69
- className: "size-4",
70
- icon
71
- }), label]
72
- }), isConfirming && confirmation && /* @__PURE__ */ jsx(ConfirmDialog, {
73
- title: confirmationTitle,
74
- description: confirmation.description,
75
- confirmLabel: confirmationConfirmLabel,
76
- cancelLabel: confirmationCancelLabel,
77
- confirmVariant: node.props?.variant ?? "default",
78
- processing: http.processing,
79
- confirmDisabled: !endpoint,
80
- onConfirm: () => void submit(),
81
- onCancel: () => setIsConfirming(false)
82
- })] });
57
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
58
+ /* @__PURE__ */ jsxs(Button, {
59
+ "data-lattice-component": node.id,
60
+ "data-test": `action-${label.toLowerCase().replace(/\s+/g, "-")}`,
61
+ disabled: http.processing || !endpoint,
62
+ onClick: requestSubmit,
63
+ type: "button",
64
+ variant,
65
+ children: [http.processing ? /* @__PURE__ */ jsx(Spinner, {}) : icon && /* @__PURE__ */ jsx(IconRenderer, {
66
+ className: "size-lt-icon-md",
67
+ icon
68
+ }), label]
69
+ }),
70
+ isConfirming && confirmation && /* @__PURE__ */ jsx(ConfirmDialog, {
71
+ title: confirmationTitle,
72
+ description: confirmation.description ?? void 0,
73
+ confirmLabel: confirmationConfirmLabel,
74
+ cancelLabel: confirmationCancelLabel,
75
+ confirmVariant: variant,
76
+ processing: http.processing,
77
+ confirmDisabled: !endpoint,
78
+ onConfirm: () => void submit(),
79
+ onCancel: () => setIsConfirming(false)
80
+ }),
81
+ isFilling && hasForm && /* @__PURE__ */ jsx(ActionForm, {
82
+ cancelLabel: confirmationCancelLabel,
83
+ componentRef,
84
+ description: confirmation?.description ?? void 0,
85
+ endpoint,
86
+ formNode,
87
+ method,
88
+ onClose: () => setIsFilling(false),
89
+ onSuccess: (response) => {
90
+ const responseEffects = getActionEffects(response.effects);
91
+ dispatchActionEffects(responseEffects.length > 0 ? responseEffects : getActionEffects(node.props.effects));
92
+ setIsFilling(false);
93
+ },
94
+ submitLabel: confirmationConfirmLabel,
95
+ title: confirmationTitle
96
+ })
97
+ ] });
83
98
  };
84
99
  //#endregion
85
100
  export { ActionComponent as default };