@pilotiq/pilotiq 0.7.2 → 0.8.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/.turbo/turbo-build.log +2 -2
  2. package/CHANGELOG.md +142 -0
  3. package/CLAUDE.md +59 -3
  4. package/dist/Pilotiq.d.ts +83 -0
  5. package/dist/Pilotiq.d.ts.map +1 -1
  6. package/dist/Pilotiq.js +39 -0
  7. package/dist/Pilotiq.js.map +1 -1
  8. package/dist/actions/Action.d.ts +27 -99
  9. package/dist/actions/Action.d.ts.map +1 -1
  10. package/dist/actions/Action.js +52 -754
  11. package/dist/actions/Action.js.map +1 -1
  12. package/dist/actions/bulkFactories.d.ts +46 -0
  13. package/dist/actions/bulkFactories.d.ts.map +1 -0
  14. package/dist/actions/bulkFactories.js +144 -0
  15. package/dist/actions/bulkFactories.js.map +1 -0
  16. package/dist/actions/crudFactories.d.ts +94 -0
  17. package/dist/actions/crudFactories.d.ts.map +1 -0
  18. package/dist/actions/crudFactories.js +209 -0
  19. package/dist/actions/crudFactories.js.map +1 -0
  20. package/dist/actions/factoryHelpers.d.ts +108 -0
  21. package/dist/actions/factoryHelpers.d.ts.map +1 -0
  22. package/dist/actions/factoryHelpers.js +138 -0
  23. package/dist/actions/factoryHelpers.js.map +1 -0
  24. package/dist/actions/m2mFactories.d.ts +47 -0
  25. package/dist/actions/m2mFactories.d.ts.map +1 -0
  26. package/dist/actions/m2mFactories.js +173 -0
  27. package/dist/actions/m2mFactories.js.map +1 -0
  28. package/dist/actions/relationFactories.d.ts +93 -0
  29. package/dist/actions/relationFactories.d.ts.map +1 -0
  30. package/dist/actions/relationFactories.js +321 -0
  31. package/dist/actions/relationFactories.js.map +1 -0
  32. package/dist/elements/dispatchForm.js +1 -1
  33. package/dist/elements/dispatchForm.js.map +1 -1
  34. package/dist/elements/dispatchTable.js +1 -1
  35. package/dist/elements/dispatchTable.js.map +1 -1
  36. package/dist/fields/Field.d.ts +31 -0
  37. package/dist/fields/Field.d.ts.map +1 -1
  38. package/dist/fields/Field.js +25 -0
  39. package/dist/fields/Field.js.map +1 -1
  40. package/dist/pageData/breadcrumbs.d.ts +42 -0
  41. package/dist/pageData/breadcrumbs.d.ts.map +1 -0
  42. package/dist/pageData/breadcrumbs.js +172 -0
  43. package/dist/pageData/breadcrumbs.js.map +1 -0
  44. package/dist/pageData/forms.d.ts +137 -0
  45. package/dist/pageData/forms.d.ts.map +1 -0
  46. package/dist/pageData/forms.js +427 -0
  47. package/dist/pageData/forms.js.map +1 -0
  48. package/dist/pageData/helpers.d.ts +239 -0
  49. package/dist/pageData/helpers.d.ts.map +1 -0
  50. package/dist/pageData/helpers.js +703 -0
  51. package/dist/pageData/helpers.js.map +1 -0
  52. package/dist/pageData/misc.d.ts +76 -0
  53. package/dist/pageData/misc.d.ts.map +1 -0
  54. package/dist/pageData/misc.js +263 -0
  55. package/dist/pageData/misc.js.map +1 -0
  56. package/dist/pageData/navigation.d.ts +292 -0
  57. package/dist/pageData/navigation.d.ts.map +1 -0
  58. package/dist/pageData/navigation.js +591 -0
  59. package/dist/pageData/navigation.js.map +1 -0
  60. package/dist/pageData/relationPages.d.ts +172 -0
  61. package/dist/pageData/relationPages.d.ts.map +1 -0
  62. package/dist/pageData/relationPages.js +867 -0
  63. package/dist/pageData/relationPages.js.map +1 -0
  64. package/dist/pageData/relationTabs.d.ts +65 -0
  65. package/dist/pageData/relationTabs.d.ts.map +1 -0
  66. package/dist/pageData/relationTabs.js +258 -0
  67. package/dist/pageData/relationTabs.js.map +1 -0
  68. package/dist/pageData/resourcePages.d.ts +48 -0
  69. package/dist/pageData/resourcePages.d.ts.map +1 -0
  70. package/dist/pageData/resourcePages.js +504 -0
  71. package/dist/pageData/resourcePages.js.map +1 -0
  72. package/dist/pageData.d.ts +12 -792
  73. package/dist/pageData.d.ts.map +1 -1
  74. package/dist/pageData.js +24 -3797
  75. package/dist/pageData.js.map +1 -1
  76. package/dist/react/AppShell.d.ts +8 -0
  77. package/dist/react/AppShell.d.ts.map +1 -1
  78. package/dist/react/AppShell.js +11 -1
  79. package/dist/react/AppShell.js.map +1 -1
  80. package/dist/react/CollabExtensionFactoryRegistry.d.ts +47 -0
  81. package/dist/react/CollabExtensionFactoryRegistry.d.ts.map +1 -0
  82. package/dist/react/CollabExtensionFactoryRegistry.js +14 -0
  83. package/dist/react/CollabExtensionFactoryRegistry.js.map +1 -0
  84. package/dist/react/CollabRoomContext.d.ts +37 -0
  85. package/dist/react/CollabRoomContext.d.ts.map +1 -0
  86. package/dist/react/CollabRoomContext.js +12 -0
  87. package/dist/react/CollabRoomContext.js.map +1 -0
  88. package/dist/react/FormCollabBindingRegistry.d.ts +62 -0
  89. package/dist/react/FormCollabBindingRegistry.d.ts.map +1 -0
  90. package/dist/react/FormCollabBindingRegistry.js +14 -0
  91. package/dist/react/FormCollabBindingRegistry.js.map +1 -0
  92. package/dist/react/RecordWrapperGate.d.ts +25 -0
  93. package/dist/react/RecordWrapperGate.d.ts.map +1 -0
  94. package/dist/react/RecordWrapperGate.js +30 -0
  95. package/dist/react/RecordWrapperGate.js.map +1 -0
  96. package/dist/react/RecordWrapperRegistry.d.ts +31 -0
  97. package/dist/react/RecordWrapperRegistry.d.ts.map +1 -0
  98. package/dist/react/RecordWrapperRegistry.js +15 -0
  99. package/dist/react/RecordWrapperRegistry.js.map +1 -0
  100. package/dist/react/SchemaRenderer.d.ts +17 -23
  101. package/dist/react/SchemaRenderer.d.ts.map +1 -1
  102. package/dist/react/SchemaRenderer.js +71 -3647
  103. package/dist/react/SchemaRenderer.js.map +1 -1
  104. package/dist/react/component-slots.d.ts +103 -0
  105. package/dist/react/component-slots.d.ts.map +1 -0
  106. package/dist/react/component-slots.js +18 -0
  107. package/dist/react/component-slots.js.map +1 -0
  108. package/dist/react/fields/BuilderInput.d.ts.map +1 -1
  109. package/dist/react/fields/BuilderInput.js +21 -117
  110. package/dist/react/fields/BuilderInput.js.map +1 -1
  111. package/dist/react/fields/MarkdownInput.d.ts.map +1 -1
  112. package/dist/react/fields/MarkdownInput.js +1 -3
  113. package/dist/react/fields/MarkdownInput.js.map +1 -1
  114. package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
  115. package/dist/react/fields/RepeaterInput.js +22 -127
  116. package/dist/react/fields/RepeaterInput.js.map +1 -1
  117. package/dist/react/fields/rowState.d.ts +40 -0
  118. package/dist/react/fields/rowState.d.ts.map +1 -0
  119. package/dist/react/fields/rowState.js +60 -0
  120. package/dist/react/fields/rowState.js.map +1 -0
  121. package/dist/react/fields/useRowReorderDnd.d.ts +28 -0
  122. package/dist/react/fields/useRowReorderDnd.d.ts.map +1 -0
  123. package/dist/react/fields/useRowReorderDnd.js +51 -0
  124. package/dist/react/fields/useRowReorderDnd.js.map +1 -0
  125. package/dist/react/index.d.ts +9 -0
  126. package/dist/react/index.d.ts.map +1 -1
  127. package/dist/react/index.js +8 -0
  128. package/dist/react/index.js.map +1 -1
  129. package/dist/react/layouts/SidebarLayout.d.ts +1 -1
  130. package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
  131. package/dist/react/layouts/SidebarLayout.js +10 -2
  132. package/dist/react/layouts/SidebarLayout.js.map +1 -1
  133. package/dist/react/layouts/TopbarLayout.d.ts +1 -1
  134. package/dist/react/layouts/TopbarLayout.d.ts.map +1 -1
  135. package/dist/react/layouts/TopbarLayout.js +19 -11
  136. package/dist/react/layouts/TopbarLayout.js.map +1 -1
  137. package/dist/react/parseRecordEditUrl.d.ts +29 -0
  138. package/dist/react/parseRecordEditUrl.d.ts.map +1 -0
  139. package/dist/react/parseRecordEditUrl.js +25 -0
  140. package/dist/react/parseRecordEditUrl.js.map +1 -0
  141. package/dist/react/persistedState.d.ts +19 -0
  142. package/dist/react/persistedState.d.ts.map +1 -0
  143. package/dist/react/persistedState.js +51 -0
  144. package/dist/react/persistedState.js.map +1 -0
  145. package/dist/react/schemaRenderer/AlertRenderer.d.ts +12 -0
  146. package/dist/react/schemaRenderer/AlertRenderer.d.ts.map +1 -0
  147. package/dist/react/schemaRenderer/AlertRenderer.js +61 -0
  148. package/dist/react/schemaRenderer/AlertRenderer.js.map +1 -0
  149. package/dist/react/schemaRenderer/EntryRenderer.d.ts +13 -0
  150. package/dist/react/schemaRenderer/EntryRenderer.d.ts.map +1 -0
  151. package/dist/react/schemaRenderer/EntryRenderer.js +277 -0
  152. package/dist/react/schemaRenderer/EntryRenderer.js.map +1 -0
  153. package/dist/react/schemaRenderer/SectionRenderer.d.ts +16 -0
  154. package/dist/react/schemaRenderer/SectionRenderer.d.ts.map +1 -0
  155. package/dist/react/schemaRenderer/SectionRenderer.js +62 -0
  156. package/dist/react/schemaRenderer/SectionRenderer.js.map +1 -0
  157. package/dist/react/schemaRenderer/SimpleElements.d.ts +25 -0
  158. package/dist/react/schemaRenderer/SimpleElements.d.ts.map +1 -0
  159. package/dist/react/schemaRenderer/SimpleElements.js +147 -0
  160. package/dist/react/schemaRenderer/SimpleElements.js.map +1 -0
  161. package/dist/react/schemaRenderer/TabsRenderer.d.ts +17 -0
  162. package/dist/react/schemaRenderer/TabsRenderer.d.ts.map +1 -0
  163. package/dist/react/schemaRenderer/TabsRenderer.js +31 -0
  164. package/dist/react/schemaRenderer/TabsRenderer.js.map +1 -0
  165. package/dist/react/schemaRenderer/WizardRenderer.d.ts +34 -0
  166. package/dist/react/schemaRenderer/WizardRenderer.d.ts.map +1 -0
  167. package/dist/react/schemaRenderer/WizardRenderer.js +208 -0
  168. package/dist/react/schemaRenderer/WizardRenderer.js.map +1 -0
  169. package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts +21 -0
  170. package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts.map +1 -0
  171. package/dist/react/schemaRenderer/action/ActionGroupTrigger.js +82 -0
  172. package/dist/react/schemaRenderer/action/ActionGroupTrigger.js.map +1 -0
  173. package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts +30 -0
  174. package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts.map +1 -0
  175. package/dist/react/schemaRenderer/action/ActionModalDialog.js +182 -0
  176. package/dist/react/schemaRenderer/action/ActionModalDialog.js.map +1 -0
  177. package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts +17 -0
  178. package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts.map +1 -0
  179. package/dist/react/schemaRenderer/action/ConfirmActionDialog.js +19 -0
  180. package/dist/react/schemaRenderer/action/ConfirmActionDialog.js.map +1 -0
  181. package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts +16 -0
  182. package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts.map +1 -0
  183. package/dist/react/schemaRenderer/action/HandlerActionButton.js +16 -0
  184. package/dist/react/schemaRenderer/action/HandlerActionButton.js.map +1 -0
  185. package/dist/react/schemaRenderer/action/MethodActionButton.d.ts +22 -0
  186. package/dist/react/schemaRenderer/action/MethodActionButton.d.ts.map +1 -0
  187. package/dist/react/schemaRenderer/action/MethodActionButton.js +26 -0
  188. package/dist/react/schemaRenderer/action/MethodActionButton.js.map +1 -0
  189. package/dist/react/schemaRenderer/action/buttons.d.ts +18 -0
  190. package/dist/react/schemaRenderer/action/buttons.d.ts.map +1 -0
  191. package/dist/react/schemaRenderer/action/buttons.js +74 -0
  192. package/dist/react/schemaRenderer/action/buttons.js.map +1 -0
  193. package/dist/react/schemaRenderer/action/helpers.d.ts +26 -0
  194. package/dist/react/schemaRenderer/action/helpers.d.ts.map +1 -0
  195. package/dist/react/schemaRenderer/action/helpers.js +126 -0
  196. package/dist/react/schemaRenderer/action/helpers.js.map +1 -0
  197. package/dist/react/schemaRenderer/action/renderAction.d.ts +21 -0
  198. package/dist/react/schemaRenderer/action/renderAction.d.ts.map +1 -0
  199. package/dist/react/schemaRenderer/action/renderAction.js +102 -0
  200. package/dist/react/schemaRenderer/action/renderAction.js.map +1 -0
  201. package/dist/react/schemaRenderer/columnFormat.d.ts +10 -0
  202. package/dist/react/schemaRenderer/columnFormat.d.ts.map +1 -0
  203. package/dist/react/schemaRenderer/columnFormat.js +76 -0
  204. package/dist/react/schemaRenderer/columnFormat.js.map +1 -0
  205. package/dist/react/schemaRenderer/constants.d.ts +8 -0
  206. package/dist/react/schemaRenderer/constants.d.ts.map +1 -0
  207. package/dist/react/schemaRenderer/constants.js +45 -0
  208. package/dist/react/schemaRenderer/constants.js.map +1 -0
  209. package/dist/react/schemaRenderer/form/FormRenderer.d.ts +29 -0
  210. package/dist/react/schemaRenderer/form/FormRenderer.d.ts.map +1 -0
  211. package/dist/react/schemaRenderer/form/FormRenderer.js +152 -0
  212. package/dist/react/schemaRenderer/form/FormRenderer.js.map +1 -0
  213. package/dist/react/schemaRenderer/form/renderField.d.ts +6 -0
  214. package/dist/react/schemaRenderer/form/renderField.d.ts.map +1 -0
  215. package/dist/react/schemaRenderer/form/renderField.js +239 -0
  216. package/dist/react/schemaRenderer/form/renderField.js.map +1 -0
  217. package/dist/react/schemaRenderer/helpers.d.ts +32 -0
  218. package/dist/react/schemaRenderer/helpers.d.ts.map +1 -0
  219. package/dist/react/schemaRenderer/helpers.js +52 -0
  220. package/dist/react/schemaRenderer/helpers.js.map +1 -0
  221. package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts +60 -0
  222. package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts.map +1 -0
  223. package/dist/react/schemaRenderer/table/CardsLayoutBody.js +189 -0
  224. package/dist/react/schemaRenderer/table/CardsLayoutBody.js.map +1 -0
  225. package/dist/react/schemaRenderer/table/TableRenderer.d.ts +29 -0
  226. package/dist/react/schemaRenderer/table/TableRenderer.d.ts.map +1 -0
  227. package/dist/react/schemaRenderer/table/TableRenderer.js +85 -0
  228. package/dist/react/schemaRenderer/table/TableRenderer.js.map +1 -0
  229. package/dist/react/schemaRenderer/table/TableRendererBody.d.ts +18 -0
  230. package/dist/react/schemaRenderer/table/TableRendererBody.d.ts.map +1 -0
  231. package/dist/react/schemaRenderer/table/TableRendererBody.js +555 -0
  232. package/dist/react/schemaRenderer/table/TableRendererBody.js.map +1 -0
  233. package/dist/react/schemaRenderer/table/filters.d.ts +263 -0
  234. package/dist/react/schemaRenderer/table/filters.d.ts.map +1 -0
  235. package/dist/react/schemaRenderer/table/filters.js +497 -0
  236. package/dist/react/schemaRenderer/table/filters.js.map +1 -0
  237. package/dist/react/schemaRenderer/table/formatCell.d.ts +11 -0
  238. package/dist/react/schemaRenderer/table/formatCell.d.ts.map +1 -0
  239. package/dist/react/schemaRenderer/table/formatCell.js +172 -0
  240. package/dist/react/schemaRenderer/table/formatCell.js.map +1 -0
  241. package/dist/react/schemaRenderer/table/links.d.ts +42 -0
  242. package/dist/react/schemaRenderer/table/links.d.ts.map +1 -0
  243. package/dist/react/schemaRenderer/table/links.js +55 -0
  244. package/dist/react/schemaRenderer/table/links.js.map +1 -0
  245. package/dist/react/schemaRenderer/table/renderRowActions.d.ts +13 -0
  246. package/dist/react/schemaRenderer/table/renderRowActions.d.ts.map +1 -0
  247. package/dist/react/schemaRenderer/table/renderRowActions.js +25 -0
  248. package/dist/react/schemaRenderer/table/renderRowActions.js.map +1 -0
  249. package/dist/react/schemaRenderer/table/url.d.ts +41 -0
  250. package/dist/react/schemaRenderer/table/url.d.ts.map +1 -0
  251. package/dist/react/schemaRenderer/table/url.js +114 -0
  252. package/dist/react/schemaRenderer/table/url.js.map +1 -0
  253. package/dist/routes/globals.d.ts +13 -0
  254. package/dist/routes/globals.d.ts.map +1 -0
  255. package/dist/routes/globals.js +131 -0
  256. package/dist/routes/globals.js.map +1 -0
  257. package/dist/routes/helpers.d.ts +217 -0
  258. package/dist/routes/helpers.d.ts.map +1 -0
  259. package/dist/routes/helpers.js +498 -0
  260. package/dist/routes/helpers.js.map +1 -0
  261. package/dist/routes/pages.d.ts +15 -0
  262. package/dist/routes/pages.d.ts.map +1 -0
  263. package/dist/routes/pages.js +145 -0
  264. package/dist/routes/pages.js.map +1 -0
  265. package/dist/routes/panel.d.ts +19 -0
  266. package/dist/routes/panel.d.ts.map +1 -0
  267. package/dist/routes/panel.js +191 -0
  268. package/dist/routes/panel.js.map +1 -0
  269. package/dist/routes/relations.d.ts +21 -0
  270. package/dist/routes/relations.d.ts.map +1 -0
  271. package/dist/routes/relations.js +1239 -0
  272. package/dist/routes/relations.js.map +1 -0
  273. package/dist/routes/resources.d.ts +28 -0
  274. package/dist/routes/resources.d.ts.map +1 -0
  275. package/dist/routes/resources.js +741 -0
  276. package/dist/routes/resources.js.map +1 -0
  277. package/dist/routes/theme.d.ts +12 -0
  278. package/dist/routes/theme.d.ts.map +1 -0
  279. package/dist/routes/theme.js +82 -0
  280. package/dist/routes/theme.js.map +1 -0
  281. package/dist/routes.d.ts.map +1 -1
  282. package/dist/routes.js +64 -3078
  283. package/dist/routes.js.map +1 -1
  284. package/dist/vite.d.ts +1 -0
  285. package/dist/vite.d.ts.map +1 -1
  286. package/dist/vite.js +26 -5
  287. package/dist/vite.js.map +1 -1
  288. package/package.json +2 -1
  289. package/src/Pilotiq.ts +95 -0
  290. package/src/actions/Action.ts +79 -723
  291. package/src/actions/bulkFactories.ts +168 -0
  292. package/src/actions/crudFactories.ts +220 -0
  293. package/src/actions/factoryHelpers.ts +177 -0
  294. package/src/actions/m2mFactories.ts +193 -0
  295. package/src/actions/relationFactories.ts +372 -0
  296. package/src/elements/dispatchForm.ts +1 -1
  297. package/src/elements/dispatchTable.ts +1 -1
  298. package/src/fields/Field.ts +39 -0
  299. package/src/pageData/breadcrumbs.ts +288 -0
  300. package/src/pageData/forms.ts +578 -0
  301. package/src/pageData/helpers.ts +764 -0
  302. package/src/pageData/misc.ts +347 -0
  303. package/src/pageData/navigation.ts +779 -0
  304. package/src/pageData/relationPages.ts +1246 -0
  305. package/src/pageData/relationTabs.ts +286 -0
  306. package/src/pageData/resourcePages.ts +593 -0
  307. package/src/pageData.ts +122 -4731
  308. package/src/react/AppShell.tsx +27 -1
  309. package/src/react/CollabExtensionFactoryRegistry.ts +55 -0
  310. package/src/react/CollabRoomContext.ts +42 -0
  311. package/src/react/FormCollabBindingRegistry.ts +72 -0
  312. package/src/react/RecordWrapperGate.tsx +40 -0
  313. package/src/react/RecordWrapperRegistry.ts +39 -0
  314. package/src/react/SchemaRenderer.tsx +230 -6479
  315. package/src/react/component-slots.test.ts +103 -0
  316. package/src/react/component-slots.ts +116 -0
  317. package/src/react/fields/BuilderInput.tsx +29 -117
  318. package/src/react/fields/MarkdownInput.tsx +0 -1
  319. package/src/react/fields/RepeaterInput.tsx +29 -130
  320. package/src/react/fields/rowState.ts +106 -0
  321. package/src/react/fields/useRowReorderDnd.ts +78 -0
  322. package/src/react/index.ts +38 -0
  323. package/src/react/layouts/SidebarLayout.tsx +39 -28
  324. package/src/react/layouts/TopbarLayout.tsx +70 -57
  325. package/src/react/parseRecordEditUrl.test.ts +75 -0
  326. package/src/react/parseRecordEditUrl.ts +55 -0
  327. package/src/react/persistedState.ts +40 -0
  328. package/src/react/schemaRenderer/AlertRenderer.tsx +112 -0
  329. package/src/react/schemaRenderer/EntryRenderer.tsx +501 -0
  330. package/src/react/schemaRenderer/SectionRenderer.tsx +120 -0
  331. package/src/react/schemaRenderer/SimpleElements.tsx +306 -0
  332. package/src/react/schemaRenderer/TabsRenderer.tsx +62 -0
  333. package/src/react/schemaRenderer/WizardRenderer.tsx +338 -0
  334. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +177 -0
  335. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +273 -0
  336. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +61 -0
  337. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +43 -0
  338. package/src/react/schemaRenderer/action/MethodActionButton.tsx +64 -0
  339. package/src/react/schemaRenderer/action/buttons.tsx +99 -0
  340. package/src/react/schemaRenderer/action/helpers.ts +140 -0
  341. package/src/react/schemaRenderer/action/renderAction.tsx +245 -0
  342. package/src/react/schemaRenderer/columnFormat.ts +65 -0
  343. package/src/react/schemaRenderer/constants.ts +50 -0
  344. package/src/react/schemaRenderer/form/FormRenderer.tsx +233 -0
  345. package/src/react/schemaRenderer/form/renderField.tsx +511 -0
  346. package/src/react/schemaRenderer/helpers.tsx +81 -0
  347. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +308 -0
  348. package/src/react/schemaRenderer/table/TableRenderer.tsx +123 -0
  349. package/src/react/schemaRenderer/table/TableRendererBody.tsx +974 -0
  350. package/src/react/schemaRenderer/table/filters.tsx +1233 -0
  351. package/src/react/schemaRenderer/table/formatCell.tsx +264 -0
  352. package/src/react/schemaRenderer/table/links.tsx +112 -0
  353. package/src/react/schemaRenderer/table/renderRowActions.tsx +52 -0
  354. package/src/react/schemaRenderer/table/url.tsx +143 -0
  355. package/src/routes/globals.ts +154 -0
  356. package/src/routes/helpers.ts +668 -0
  357. package/src/routes/pages.ts +173 -0
  358. package/src/routes/panel.ts +204 -0
  359. package/src/routes/relations.ts +1219 -0
  360. package/src/routes/resources.ts +786 -0
  361. package/src/routes/theme.ts +109 -0
  362. package/src/routes.test.ts +1 -1
  363. package/src/routes.ts +64 -3176
  364. package/src/schema/TableWidget.test.ts +2 -2
  365. package/src/theme/migrate.test.ts +178 -0
  366. package/src/vite.test.ts +184 -0
  367. package/src/vite.ts +26 -4
@@ -0,0 +1,308 @@
1
+ import React from 'react'
2
+ import { ChevronDownIcon, InboxIcon } from 'lucide-react'
3
+ import type { ElementMeta } from '../../../schema/Element.js'
4
+ import { Checkbox } from '../../ui/checkbox.js'
5
+ import { GroupHeadingLink, useSpaNavClick } from './links.js'
6
+ import { GroupHeaderText } from './filters.js'
7
+ import type { NavigateFn } from '../../navigate.js'
8
+
9
+ // ─── Cards layout for `Table.contentLayout('cards')` ────────
10
+
11
+ type RenderElement = (el: ElementMeta, index: number) => React.ReactNode
12
+ type RenderRowActions = (rowId: string, rowRecord: Record<string, unknown> | undefined, actions: ElementMeta[]) => React.ReactNode
13
+
14
+ /**
15
+ * Lookup tables for responsive grid column-counts in `contentLayout:
16
+ * 'cards'`. Tailwind's JIT scanner needs **literal** class strings; we
17
+ * can't construct them at runtime via template literals (`grid-cols-${n}`
18
+ * would never be matched). Limit to 1–6 columns + 12 — covers every
19
+ * reasonable card grid; bigger values are silently capped at 6 for
20
+ * non-base breakpoints in `cardsPerRowClasses`.
21
+ */
22
+ const CARDS_GRID_COLS_BASE: Record<number, string> = {
23
+ 1: 'grid-cols-1',
24
+ 2: 'grid-cols-2',
25
+ 3: 'grid-cols-3',
26
+ 4: 'grid-cols-4',
27
+ 5: 'grid-cols-5',
28
+ 6: 'grid-cols-6',
29
+ 12: 'grid-cols-12',
30
+ }
31
+ const CARDS_GRID_COLS_SM: Record<number, string> = {
32
+ 1: 'sm:grid-cols-1', 2: 'sm:grid-cols-2', 3: 'sm:grid-cols-3',
33
+ 4: 'sm:grid-cols-4', 5: 'sm:grid-cols-5', 6: 'sm:grid-cols-6',
34
+ 12: 'sm:grid-cols-12',
35
+ }
36
+ const CARDS_GRID_COLS_MD: Record<number, string> = {
37
+ 1: 'md:grid-cols-1', 2: 'md:grid-cols-2', 3: 'md:grid-cols-3',
38
+ 4: 'md:grid-cols-4', 5: 'md:grid-cols-5', 6: 'md:grid-cols-6',
39
+ 12: 'md:grid-cols-12',
40
+ }
41
+ const CARDS_GRID_COLS_LG: Record<number, string> = {
42
+ 1: 'lg:grid-cols-1', 2: 'lg:grid-cols-2', 3: 'lg:grid-cols-3',
43
+ 4: 'lg:grid-cols-4', 5: 'lg:grid-cols-5', 6: 'lg:grid-cols-6',
44
+ 12: 'lg:grid-cols-12',
45
+ }
46
+ const CARDS_GRID_COLS_XL: Record<number, string> = {
47
+ 1: 'xl:grid-cols-1', 2: 'xl:grid-cols-2', 3: 'xl:grid-cols-3',
48
+ 4: 'xl:grid-cols-4', 5: 'xl:grid-cols-5', 6: 'xl:grid-cols-6',
49
+ 12: 'xl:grid-cols-12',
50
+ }
51
+ const CARDS_GRID_COLS_2XL: Record<number, string> = {
52
+ 1: '2xl:grid-cols-1', 2: '2xl:grid-cols-2', 3: '2xl:grid-cols-3',
53
+ 4: '2xl:grid-cols-4', 5: '2xl:grid-cols-5', 6: '2xl:grid-cols-6',
54
+ 12: '2xl:grid-cols-12',
55
+ }
56
+
57
+ export function pickCardCols(table: Record<number, string>, raw: number | undefined): string | undefined {
58
+ if (raw === undefined) return undefined
59
+ if (table[raw]) return table[raw]
60
+ // Snap unsupported values to nearest available — values outside [1,6]∪{12}
61
+ // round down. Already-clamped to [1,12] server-side.
62
+ if (raw >= 12) return table[12]
63
+ if (raw >= 6) return table[6]
64
+ if (raw >= 5) return table[5]
65
+ if (raw >= 4) return table[4]
66
+ if (raw >= 3) return table[3]
67
+ if (raw >= 2) return table[2]
68
+ return table[1]
69
+ }
70
+
71
+ /** Build a Tailwind grid-cols class string from a per-row config. Default
72
+ * `{ default: 1, sm: 2, lg: 3 }` mirrors Filament's typical card grid. */
73
+ export function cardsPerRowClasses(opts: Record<string, number> | undefined): string {
74
+ const cfg = opts ?? {}
75
+ const baseN = cfg['default'] ?? 1
76
+ const out: string[] = [pickCardCols(CARDS_GRID_COLS_BASE, baseN)!]
77
+ if (cfg['sm'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_SM, cfg['sm']); if (c) out.push(c) }
78
+ if (cfg['md'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_MD, cfg['md']); if (c) out.push(c) }
79
+ if (cfg['lg'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_LG, cfg['lg']); if (c) out.push(c) }
80
+ if (cfg['xl'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_XL, cfg['xl']); if (c) out.push(c) }
81
+ if (cfg['2xl'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_2XL, cfg['2xl']); if (c) out.push(c) }
82
+ // Unset fallback covers Filament's typical default — 1 column on mobile,
83
+ // 2 on small screens, 3 on large.
84
+ if (Object.keys(cfg).length === 0) {
85
+ return 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3'
86
+ }
87
+ return out.join(' ')
88
+ }
89
+
90
+
91
+ /**
92
+ * Card-grid body for `Table.contentLayout('cards')`. Renders the rows
93
+ * area only — the surrounding chrome (heading / search / filters /
94
+ * pagination / bulk-action toolbar / "Sort by" picker) lives in the
95
+ * parent `TableRendererBody` so both layouts share it.
96
+ *
97
+ * Each card renders its `_cardChildren` schema via the standard
98
+ * `renderElement` walker, so any display-Element (Heading, Text, Image,
99
+ * Icon, Badge entries, layout primitives, etc.) drops in without a new
100
+ * renderer. Per-row chrome attaches via the same `_recordUrl` /
101
+ * `_recordClasses` / `_visibleActions` / `_disabledActions` keys the
102
+ * table-mode renderer reads from — `loadTableRecords` is unchanged.
103
+ *
104
+ * Group banding splits the rows into contiguous sections by
105
+ * `_groupValue`, emitting a heading row above each section. The user's
106
+ * configured per-card grid (`cardsPerRow`) re-applies inside every
107
+ * section so the column count stays consistent.
108
+ */
109
+ export function CardsLayoutBody({
110
+ rows, visibleIds, selected, toggleRow,
111
+ hasBulkActions, hasRowActions, rowActions, hasRecordUrl, hasRecordClasses,
112
+ activeEmpty, EmptyIcon, hasFilterOrSearch,
113
+ defaultGroup, groupColumnLabel, groupCollapsible, collapsedGroups, toggleGroupCollapsed,
114
+ cardsPerRow, navigate,
115
+ groupHeadingScopable, buildGroupKeyHref,
116
+ renderElement, renderRowActions,
117
+ }: {
118
+ rows: unknown[]
119
+ visibleIds: string[]
120
+ selected: Set<string>
121
+ toggleRow: (id: string) => void
122
+ hasBulkActions: boolean
123
+ hasRowActions: boolean
124
+ rowActions: ElementMeta[]
125
+ hasRecordUrl: boolean
126
+ hasRecordClasses: boolean
127
+ activeEmpty: { heading?: string; description?: string; icon?: string } | undefined
128
+ EmptyIcon: React.ComponentType<{ className?: string }>
129
+ hasFilterOrSearch: boolean
130
+ defaultGroup: string | undefined
131
+ groupColumnLabel: string | undefined
132
+ groupCollapsible: boolean
133
+ collapsedGroups: Record<string, boolean>
134
+ toggleGroupCollapsed: (groupValue: string) => void
135
+ cardsPerRow: Record<string, number> | undefined
136
+ navigate: NavigateFn
137
+ // Drill-in affordances. Sparse: when `groupHeadingScopable` is false,
138
+ // the heading renders as before; `buildGroupKeyHref` is unused.
139
+ groupHeadingScopable?: boolean
140
+ buildGroupKeyHref?: (value: string) => string
141
+ // Injected renderers — keeps the import cycle clean between
142
+ // SchemaRenderer.tsx's top-level dispatch and this body.
143
+ renderElement: RenderElement
144
+ renderRowActions: RenderRowActions
145
+ }) {
146
+ const gridClass = `grid gap-4 ${cardsPerRowClasses(cardsPerRow)}`
147
+
148
+ if (rows.length === 0) {
149
+ return (
150
+ <div className="rounded-xl border bg-card py-12 text-center">
151
+ <div className="flex flex-col items-center gap-2 text-muted-foreground">
152
+ <EmptyIcon className="size-8 opacity-60" />
153
+ <p className="text-base font-medium text-foreground">
154
+ {activeEmpty?.heading
155
+ ?? (hasFilterOrSearch ? 'No matching records' : 'No records yet')}
156
+ </p>
157
+ {(activeEmpty?.description ||
158
+ (hasFilterOrSearch && !activeEmpty?.description)) && (
159
+ <p className="text-sm">
160
+ {activeEmpty?.description
161
+ ?? 'Try clearing filters or adjusting your search.'}
162
+ </p>
163
+ )}
164
+ </div>
165
+ </div>
166
+ )
167
+ }
168
+
169
+ // Split rows into contiguous group-banded sections so each section
170
+ // can render its own heading + grid. Without an active group this is
171
+ // one section with no heading.
172
+ type Section = {
173
+ groupValue?: string
174
+ title?: string
175
+ description?: string
176
+ indices: number[]
177
+ }
178
+ const sections: Section[] = []
179
+ if (defaultGroup === undefined) {
180
+ sections.push({ indices: rows.map((_, i) => i) })
181
+ } else {
182
+ let current: Section | undefined
183
+ for (let i = 0; i < rows.length; i++) {
184
+ const r = rows[i] as Record<string, unknown>
185
+ const v = String(r['_groupValue'] ?? '')
186
+ if (current === undefined || current.groupValue !== v) {
187
+ const title = r['_groupTitle'] as string | undefined
188
+ const description = r['_groupDescription'] as string | undefined
189
+ current = { groupValue: v, indices: [], ...(title ? { title } : {}), ...(description ? { description } : {}) }
190
+ sections.push(current)
191
+ }
192
+ current.indices.push(i)
193
+ }
194
+ }
195
+
196
+ return (
197
+ <div className="flex flex-col gap-4">
198
+ {sections.map((section, si) => {
199
+ const collapsed = groupCollapsible
200
+ && section.groupValue !== undefined
201
+ && collapsedGroups[section.groupValue] === true
202
+ return (
203
+ <div key={si} className="flex flex-col gap-3">
204
+ {section.groupValue !== undefined && (() => {
205
+ const drillable = groupHeadingScopable === true
206
+ && buildGroupKeyHref !== undefined
207
+ && section.groupValue !== ''
208
+ const headingText = (
209
+ <GroupHeaderText
210
+ label={groupColumnLabel}
211
+ value={section.groupValue}
212
+ title={section.title}
213
+ description={section.description}
214
+ />
215
+ )
216
+ const headingNode = drillable
217
+ ? <GroupHeadingLink href={buildGroupKeyHref!(section.groupValue!)} navigate={navigate}>{headingText}</GroupHeadingLink>
218
+ : headingText
219
+ if (groupCollapsible) {
220
+ return (
221
+ <div className="flex w-full items-center gap-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
222
+ <button
223
+ type="button"
224
+ className="inline-flex items-center"
225
+ onClick={() => toggleGroupCollapsed(section.groupValue!)}
226
+ aria-expanded={!collapsed}
227
+ aria-label={collapsed ? 'Expand group' : 'Collapse group'}
228
+ >
229
+ <ChevronDownIcon
230
+ className={[
231
+ 'size-4 transition-transform',
232
+ collapsed ? '-rotate-90' : '',
233
+ ].filter(Boolean).join(' ')}
234
+ />
235
+ </button>
236
+ {headingNode}
237
+ </div>
238
+ )
239
+ }
240
+ return (
241
+ <div className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
242
+ {headingNode}
243
+ </div>
244
+ )
245
+ })()}
246
+ {!collapsed && (
247
+ <div className={gridClass}>
248
+ {section.indices.map((ri) => {
249
+ const id = visibleIds[ri]!
250
+ const recordObj = rows[ri] as Record<string, unknown>
251
+ const isSelected = selected.has(id)
252
+ const recordUrl = hasRecordUrl ? (recordObj['_recordUrl'] as string | undefined) : undefined
253
+ const customRowClasses = hasRecordClasses
254
+ ? (recordObj['_recordClasses'] as string | undefined) ?? ''
255
+ : ''
256
+ const cardChildren = (recordObj['_cardChildren'] as ElementMeta[] | undefined) ?? []
257
+ const cardClassName = [
258
+ 'group relative flex flex-col gap-3 rounded-xl border bg-card p-4 transition-colors',
259
+ recordUrl ? 'hover:border-primary/40 hover:bg-accent/30' : '',
260
+ isSelected ? 'border-primary ring-2 ring-primary/20' : '',
261
+ customRowClasses,
262
+ ].filter(Boolean).join(' ')
263
+
264
+ return (
265
+ <div key={id} className={cardClassName}>
266
+ {recordUrl !== undefined && (
267
+ <a
268
+ href={recordUrl}
269
+ onClick={useSpaNavClick(recordUrl, navigate)}
270
+ aria-label="Open record"
271
+ className="absolute inset-0 z-0 rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
272
+ >
273
+ <span className="sr-only">Open record</span>
274
+ </a>
275
+ )}
276
+ {hasBulkActions && (
277
+ <div className="absolute top-3 right-3 z-10">
278
+ <Checkbox
279
+ aria-label={`Select row ${id}`}
280
+ checked={isSelected}
281
+ onCheckedChange={() => toggleRow(id)}
282
+ data-no-row-nav
283
+ />
284
+ </div>
285
+ )}
286
+ <div className="relative z-[1] flex flex-col gap-3">
287
+ {cardChildren.length === 0 ? (
288
+ <div className="text-xs italic text-muted-foreground">
289
+ No card content configured.
290
+ </div>
291
+ ) : cardChildren.map((c, i) => renderElement(c, i))}
292
+ </div>
293
+ {hasRowActions && (
294
+ <div className="relative z-10 mt-auto flex items-center justify-end pt-2 border-t border-border/60">
295
+ {renderRowActions(id, recordObj, rowActions)}
296
+ </div>
297
+ )}
298
+ </div>
299
+ )
300
+ })}
301
+ </div>
302
+ )}
303
+ </div>
304
+ )
305
+ })}
306
+ </div>
307
+ )
308
+ }
@@ -0,0 +1,123 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import type { ElementMeta } from '../../../schema/Element.js'
3
+ import { TableRendererBody, type TableBodyDeps } from './TableRendererBody.js'
4
+
5
+ // ─── Table wrapper + deferred-load shell ────────────────────
6
+
7
+
8
+ /**
9
+ * Tier-3 deferred-load shell. When `Resource.deferLoading = true`, the
10
+ * SSR pass marks each Table on the page as `deferred` + stamps a
11
+ * `tableUrl`. This wrapper paints a skeleton on first frame and fetches
12
+ * the actual rows from the JSON endpoint after mount; the inner
13
+ * `TableRendererBody` renders identically against either the SSR meta
14
+ * (non-deferred case) or the fetched meta (deferred case).
15
+ *
16
+ * SPA nav with a query change re-runs SSR, which re-stamps `deferred`
17
+ * — so the URL-change effect fires another fetch. The skeleton frame
18
+ * still shows current sort / search / page / filter chrome because the
19
+ * SSR pass mirrors URL state on the deferred Table.
20
+ */
21
+ export function TableRenderer({ el, deps }: { el: ElementMeta; deps: TableBodyDeps }) {
22
+ const isDeferred = el['deferred'] === true && typeof el['tableUrl'] === 'string'
23
+ const tableUrl = isDeferred ? (el['tableUrl'] as string) : ''
24
+
25
+ // Track the URL search string so a navigation that changes filters /
26
+ // sort / page re-fires the fetch. Initialized lazy on first client
27
+ // render; on the SSR pass we just fall through to skeleton.
28
+ const [search, setSearch] = useState<string>(() =>
29
+ typeof window === 'undefined' ? '' : window.location.search,
30
+ )
31
+ useEffect(() => {
32
+ if (!isDeferred) return
33
+ if (typeof window === 'undefined') return
34
+ setSearch(window.location.search)
35
+ }, [isDeferred, el])
36
+
37
+ const [deferredMeta, setDeferredMeta] = useState<ElementMeta | null>(null)
38
+ const [deferredError, setDeferredError] = useState<string | null>(null)
39
+
40
+ useEffect(() => {
41
+ if (!isDeferred || !tableUrl) return
42
+ if (typeof window === 'undefined') return
43
+ let cancelled = false
44
+ setDeferredMeta(null)
45
+ setDeferredError(null)
46
+ fetch(tableUrl + search, {
47
+ headers: { 'Accept': 'application/json' },
48
+ credentials: 'same-origin',
49
+ })
50
+ .then(async r => {
51
+ const data = (await r.json()) as {
52
+ ok?: boolean
53
+ tables?: Record<string, unknown>[]
54
+ error?: string
55
+ }
56
+ if (cancelled) return
57
+ if (data.ok && Array.isArray(data.tables) && data.tables.length > 0) {
58
+ setDeferredMeta(data.tables[0] as ElementMeta)
59
+ } else {
60
+ setDeferredError(data.error ?? 'Failed to load table')
61
+ }
62
+ })
63
+ .catch(err => {
64
+ if (cancelled) return
65
+ setDeferredError(err instanceof Error ? err.message : 'Failed to load table')
66
+ })
67
+ return () => { cancelled = true }
68
+ }, [isDeferred, tableUrl, search])
69
+
70
+ if (isDeferred && deferredError) {
71
+ return (
72
+ <div className="rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive">
73
+ Failed to load table: {deferredError}
74
+ </div>
75
+ )
76
+ }
77
+ if (isDeferred && !deferredMeta) {
78
+ return <TableSkeleton el={el} />
79
+ }
80
+
81
+ return <TableRendererBody el={isDeferred ? deferredMeta! : el} deps={deps} />
82
+ }
83
+
84
+ /**
85
+ * Skeleton placeholder painted while a deferred-loaded table fetches
86
+ * its rows. Mirrors the table's heading + description chrome (already
87
+ * present on `el`) so the frame doesn't pop layout when the real rows
88
+ * arrive. Renders a small column header strip + 5 placeholder rows.
89
+ */
90
+ export function TableSkeleton({ el }: { el: ElementMeta }) {
91
+ const heading = typeof el['heading'] === 'string' ? (el['heading'] as string) : undefined
92
+ const description = typeof el['description'] === 'string' ? (el['description'] as string) : undefined
93
+ const children = el.children ?? []
94
+ const colCount = Math.max(1, children.filter(c => c.type === 'column').length)
95
+ return (
96
+ <div className="space-y-3">
97
+ {(heading || description) ? (
98
+ <div className="space-y-1">
99
+ {heading ? <div className="text-lg font-semibold">{heading}</div> : null}
100
+ {description ? <div className="text-sm text-muted-foreground">{description}</div> : null}
101
+ </div>
102
+ ) : null}
103
+ <div className="rounded-md border">
104
+ <div className="grid border-b bg-muted/50 px-4 py-2"
105
+ style={{ gridTemplateColumns: `repeat(${colCount}, minmax(0, 1fr))` }}>
106
+ {Array.from({ length: colCount }).map((_, i) => (
107
+ <div key={i} className="h-4 w-20 rounded bg-muted-foreground/20" />
108
+ ))}
109
+ </div>
110
+ <div className="divide-y">
111
+ {Array.from({ length: 5 }).map((_, rowIdx) => (
112
+ <div key={rowIdx} className="grid items-center px-4 py-3"
113
+ style={{ gridTemplateColumns: `repeat(${colCount}, minmax(0, 1fr))` }}>
114
+ {Array.from({ length: colCount }).map((_, colIdx) => (
115
+ <div key={colIdx} className="h-4 w-2/3 rounded bg-muted-foreground/10 animate-pulse" />
116
+ ))}
117
+ </div>
118
+ ))}
119
+ </div>
120
+ </div>
121
+ </div>
122
+ )
123
+ }