@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,120 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import type { ElementMeta } from '../../schema/Element.js'
3
+ import { readStoredFlag, writeStoredFlag } from '../persistedState.js'
4
+ import { layoutClasses, resolveIcon } from './helpers.js'
5
+
6
+ // ─── Section (stateful when collapsible) ────────────────────
7
+
8
+ /**
9
+ * `Section` chrome with optional collapse + persisted open/closed state.
10
+ * Renders a card-style border, header (title / description / icon / badge
11
+ * / after-header actions), body, and the collapse toggle when enabled.
12
+ *
13
+ * `renderElement` is injected so the body can re-enter the main switch
14
+ * without creating a SchemaRenderer ↔ SectionRenderer import cycle.
15
+ */
16
+ export function SectionRenderer({
17
+ el,
18
+ index,
19
+ renderElement,
20
+ }: {
21
+ el: ElementMeta
22
+ index: number
23
+ renderElement: (el: ElementMeta, index: number) => React.ReactNode
24
+ }) {
25
+ const title = el['title'] ? String(el['title']) : undefined
26
+ const description = el['description'] ? String(el['description']) : undefined
27
+ const iconName = el['icon'] ? String(el['icon']) : undefined
28
+ const badge = el['badge'] ? String(el['badge']) : undefined
29
+ const columns = Number(el['columns'] ?? 1)
30
+ const collapsible = Boolean(el['collapsible'])
31
+ const compact = Boolean(el['compact'])
32
+ const dense = Boolean(el['dense'])
33
+ const secondary = Boolean(el['secondary'])
34
+ const afterHeader = (el['afterHeader'] as ElementMeta[] | undefined) ?? []
35
+ const persist = Boolean(el['persistCollapsed'])
36
+ const persistKey = el['persistKey']
37
+ ? `pilotiq.section.${String(el['persistKey'])}`
38
+ : title
39
+ ? `pilotiq.section.${title.toLowerCase().replace(/\s+/g, '-')}`
40
+ : undefined
41
+
42
+ const defaultCollapsed = Boolean(el['defaultCollapsed'])
43
+ const [collapsed, setCollapsed] = useState(defaultCollapsed)
44
+
45
+ // Plan #8 — persist open/closed state to localStorage. Hydration-safe:
46
+ // initial render uses `defaultCollapsed`; effect overrides from storage
47
+ // after mount so server + client first paint agree.
48
+ useEffect(() => {
49
+ if (!persist || !persistKey) return
50
+ setCollapsed(readStoredFlag(persistKey, defaultCollapsed))
51
+ }, [persist, persistKey, defaultCollapsed])
52
+
53
+ useEffect(() => {
54
+ if (!persist || !persistKey) return
55
+ writeStoredFlag(persistKey, collapsed)
56
+ }, [persist, persistKey, collapsed])
57
+
58
+ // `dense` tightens the inner spacing between the section's children
59
+ // (orthogonal to `compact`, which trims the section's outer padding /
60
+ // heading). gap-2 ≈ 8px vs gap-4 ≈ 16px.
61
+ const innerGap = dense ? 'gap-2' : 'gap-4'
62
+ const gridClass = columns === 2 ? `grid grid-cols-2 ${innerGap}` : columns === 3 ? `grid grid-cols-3 ${innerGap}` : `flex flex-col ${innerGap}`
63
+ const padding = compact ? 'p-3' : 'p-4'
64
+ const titleSize = compact ? 'text-sm' : 'text-base'
65
+ const Icon = resolveIcon(iconName)
66
+
67
+ // `secondary()` flips the section background to the muted token so it
68
+ // visually recedes beneath a primary section. The border thins to the
69
+ // same muted tone for the same reason — a sharp `border-input` line
70
+ // around a muted block looks like a typographic ledger rather than a
71
+ // grouping container.
72
+ const surfaceClass = secondary ? 'bg-muted/40 border-muted' : 'bg-card'
73
+
74
+ return (
75
+ <section
76
+ key={index}
77
+ className={`flex flex-col ${compact ? 'gap-2' : 'gap-3'} rounded-lg border ${surfaceClass} ${padding} ${layoutClasses(el)}`.trim()}
78
+ >
79
+ {(title || description || collapsible || badge || afterHeader.length > 0) && (
80
+ <header className="flex items-start justify-between gap-2">
81
+ <div className="flex items-start gap-2">
82
+ {Icon && <Icon className="size-4 mt-0.5 text-muted-foreground" aria-hidden="true" />}
83
+ <div>
84
+ <div className="flex items-center gap-2">
85
+ {title && <h3 className={`${titleSize} font-semibold`}>{title}</h3>}
86
+ {badge && (
87
+ <span className="rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
88
+ {badge}
89
+ </span>
90
+ )}
91
+ </div>
92
+ {description && <p className="text-xs text-muted-foreground mt-0.5">{description}</p>}
93
+ </div>
94
+ </div>
95
+ <div className="flex items-center gap-2">
96
+ {afterHeader.length > 0 && (
97
+ <div className="flex items-center gap-1">
98
+ {afterHeader.map((a, i) => renderElement(a, i))}
99
+ </div>
100
+ )}
101
+ {collapsible && (
102
+ <button
103
+ type="button"
104
+ onClick={() => setCollapsed(c => !c)}
105
+ className="text-xs text-muted-foreground hover:text-foreground"
106
+ >
107
+ {collapsed ? 'Expand' : 'Collapse'}
108
+ </button>
109
+ )}
110
+ </div>
111
+ </header>
112
+ )}
113
+ {!collapsed && el.children && el.children.length > 0 && (
114
+ <div className={gridClass}>
115
+ {el.children.map((c, i) => renderElement(c, i))}
116
+ </div>
117
+ )}
118
+ </section>
119
+ )
120
+ }
@@ -0,0 +1,306 @@
1
+ import React from 'react'
2
+ import type { ElementMeta } from '../../schema/Element.js'
3
+ import {
4
+ BADGE_COLOR_CLASSES,
5
+ COLUMN_COLOR_CLASSES,
6
+ TEXT_COLOR_CLASSES,
7
+ TEXT_SIZE_CLASSES,
8
+ TEXT_WEIGHT_CLASSES,
9
+ } from './constants.js'
10
+ import { layoutClasses, renderChildren, resolveIcon } from './helpers.js'
11
+
12
+ /** Stateless leaf renderers — every element here is a pure function of
13
+ * its meta. Cases that own children defer back to the caller's
14
+ * `renderElement` via `deps.renderElement`. Cases that mount Action
15
+ * triggers in header / footer slots defer to `deps.renderActionLike`.
16
+ *
17
+ * `renderSimpleElement` returns `null` only when the type is one of the
18
+ * handled leaves and resolves to no output (e.g. `icon` with no
19
+ * registered name). For unknown types it returns the sentinel
20
+ * `undefined` so the caller falls through to the rest of its switch. */
21
+
22
+ export interface SimpleElementDeps {
23
+ /** Recurse into a child element. Injected to avoid the cycle with
24
+ * SchemaRenderer's main dispatch. */
25
+ renderElement: (el: ElementMeta, index: number) => React.ReactNode
26
+ /** Render an action / actionGroup / slotComponent meta as a button or
27
+ * trigger. Used by `heading` and `emptyState` for their header /
28
+ * footer action slots. */
29
+ renderActionLike: (el: ElementMeta, index: number) => React.ReactNode
30
+ }
31
+
32
+ /** Render the `text` element. Hot path — pulled out so the `case 'text'`
33
+ * branch in the main switch stays a one-liner. */
34
+ function renderText(el: ElementMeta, index: number): React.ReactNode {
35
+ const content = String(el['content'] ?? '')
36
+ const color = el['color'] ? String(el['color']) : undefined
37
+ const size = el['size'] ? String(el['size']) : undefined
38
+ const weight = el['weight'] ? String(el['weight']) : undefined
39
+ const isBadge = el['badge'] === true
40
+
41
+ if (isBadge) {
42
+ const badgeKey = el['badgeColor'] ? String(el['badgeColor']) : 'gray'
43
+ const cls = BADGE_COLOR_CLASSES[badgeKey] ?? BADGE_COLOR_CLASSES['gray']
44
+ return (
45
+ <span
46
+ key={index}
47
+ className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${cls}`}
48
+ >
49
+ {content}
50
+ </span>
51
+ )
52
+ }
53
+
54
+ // Defaults match the previous bare `<p>` for back-compat: text-sm + muted.
55
+ const sizeCls = size ? (TEXT_SIZE_CLASSES[size] ?? '') : 'text-sm'
56
+ const colorCls = color ? (TEXT_COLOR_CLASSES[color] ?? '') : 'text-muted-foreground'
57
+ const weightCls = weight ? (TEXT_WEIGHT_CLASSES[weight] ?? '') : ''
58
+ return (
59
+ <p key={index} className={`${sizeCls} ${colorCls} ${weightCls}`.trim()}>
60
+ {content}
61
+ </p>
62
+ )
63
+ }
64
+
65
+ /** Dispatch helper for stateless leaf + layout-primitive element types.
66
+ * Returns `undefined` when the type isn't handled here, letting the
67
+ * caller fall through to its remaining switch arms. */
68
+ export function renderSimpleElement(
69
+ el: ElementMeta,
70
+ index: number,
71
+ deps: SimpleElementDeps,
72
+ ): React.ReactNode | undefined {
73
+ const { renderElement, renderActionLike } = deps
74
+
75
+ switch (el.type) {
76
+ case 'text':
77
+ return renderText(el, index)
78
+
79
+ case 'image': {
80
+ const url = String(el['url'] ?? '')
81
+ const alt = String(el['alt'] ?? '')
82
+ const width = el['width'] as number | undefined
83
+ const height = el['height'] as number | undefined
84
+ const shape = String(el['shape'] ?? 'square')
85
+ const shapeCls = shape === 'circle' ? 'rounded-full' : shape === 'rounded' ? 'rounded-md' : ''
86
+ return (
87
+ <img
88
+ key={index}
89
+ src={url}
90
+ alt={alt}
91
+ {...(width !== undefined ? { width } : {})}
92
+ {...(height !== undefined ? { height } : {})}
93
+ className={`inline-block object-cover ${shapeCls}`}
94
+ />
95
+ )
96
+ }
97
+
98
+ case 'icon': {
99
+ const name = el['name'] ? String(el['name']) : undefined
100
+ const size = (el['size'] as number | undefined) ?? 16
101
+ const color = String(el['color'] ?? 'default')
102
+ const label = el['label'] ? String(el['label']) : undefined
103
+ const Cmp = resolveIcon(name)
104
+ if (!Cmp) return null
105
+ const colorClass = COLUMN_COLOR_CLASSES[color] ?? ''
106
+ return (
107
+ <Cmp
108
+ key={index}
109
+ className={`inline ${colorClass}`}
110
+ {...(label ? { 'aria-label': label } : { 'aria-hidden': true })}
111
+ style={{ width: size, height: size }}
112
+ />
113
+ )
114
+ }
115
+
116
+ case 'markdown':
117
+ case 'html': {
118
+ const html = String(el['html'] ?? '')
119
+ const prose = el['prose'] !== false
120
+ const size = el['size'] ? String(el['size']) : undefined
121
+ const proseCls = prose
122
+ ? `prose max-w-none ${size === 'sm' ? 'prose-sm' : size === 'lg' ? 'prose-lg' : ''}`.trim()
123
+ : ''
124
+ return (
125
+ <div
126
+ key={index}
127
+ className={proseCls || undefined}
128
+ dangerouslySetInnerHTML={{ __html: html }}
129
+ />
130
+ )
131
+ }
132
+
133
+ case 'heading': {
134
+ const level = (el['level'] as number) ?? 1
135
+ const content = String(el['content'] ?? '')
136
+ const description = el['description'] ? String(el['description']) : undefined
137
+ const headerActions = (el.children ?? []).filter(c => c.type === 'action' || c.type === 'actionGroup' || c.type === 'slotComponent')
138
+ const Tag = level === 1 ? 'h1' : level === 2 ? 'h2' : 'h3'
139
+ const sizes = { 1: 'text-2xl', 2: 'text-xl', 3: 'text-lg' } as const
140
+ const titleBlock = (
141
+ <div>
142
+ <Tag className={`${sizes[level as 1 | 2 | 3]} font-bold tracking-tight`}>
143
+ {content}
144
+ </Tag>
145
+ {description && (
146
+ <p className="text-sm text-muted-foreground mt-1">{description}</p>
147
+ )}
148
+ </div>
149
+ )
150
+ if (headerActions.length === 0) {
151
+ return <div key={index}>{titleBlock}</div>
152
+ }
153
+ return (
154
+ <div key={index} className="flex items-start justify-between gap-4">
155
+ {titleBlock}
156
+ <div className="flex items-center gap-2 shrink-0">
157
+ {headerActions.map((a, i) => renderActionLike(a, i))}
158
+ </div>
159
+ </div>
160
+ )
161
+ }
162
+
163
+ case 'emptyState': {
164
+ const heading = String(el['heading'] ?? '')
165
+ const description = el['description'] ? String(el['description']) : undefined
166
+ const iconName = el['icon'] ? String(el['icon']) : undefined
167
+ const contained = el['contained'] !== false
168
+ const Icon = iconName ? resolveIcon(iconName) : undefined
169
+ const footer = (el.children ?? []).filter(c => c.type === 'action' || c.type === 'actionGroup' || c.type === 'slotComponent')
170
+ const wrapper = contained
171
+ ? 'rounded-lg border border-border bg-card text-card-foreground py-12 px-6'
172
+ : 'py-8'
173
+ return (
174
+ <div key={index} className={`${wrapper} flex flex-col items-center text-center gap-3`}>
175
+ {Icon && <Icon className="size-10 text-muted-foreground" aria-hidden="true" />}
176
+ <h3 className="text-lg font-semibold">{heading}</h3>
177
+ {description && <p className="text-sm text-muted-foreground max-w-md">{description}</p>}
178
+ {footer.length > 0 && (
179
+ <div className="flex items-center gap-2 mt-2">
180
+ {footer.map((a, i) => renderActionLike(a, i))}
181
+ </div>
182
+ )}
183
+ </div>
184
+ )
185
+ }
186
+
187
+ case 'divider': {
188
+ const label = el['label'] ? String(el['label']) : undefined
189
+ return label
190
+ ? <div key={index} className="relative py-2">
191
+ <div className="absolute inset-0 flex items-center"><span className="w-full border-t border-border" /></div>
192
+ <div className="relative flex justify-center"><span className="bg-background px-2 text-xs text-muted-foreground">{label}</span></div>
193
+ </div>
194
+ : <hr key={index} className="border-border" />
195
+ }
196
+
197
+ case 'unorderedList': {
198
+ const items = (el['items'] as unknown[] | undefined) ?? []
199
+ const color = el['color'] ? String(el['color']) : undefined
200
+ const size = el['size'] ? String(el['size']) : undefined
201
+ const weight = el['weight'] ? String(el['weight']) : undefined
202
+ const sizeCls = size ? (TEXT_SIZE_CLASSES[size] ?? '') : 'text-sm'
203
+ const colorCls = color ? (TEXT_COLOR_CLASSES[color] ?? '') : ''
204
+ const weightCls = weight ? (TEXT_WEIGHT_CLASSES[weight] ?? '') : ''
205
+ return (
206
+ <ul key={index} className={`list-disc list-inside space-y-1 ${sizeCls} ${colorCls} ${weightCls}`.trim()}>
207
+ {items.map((item, i) => (
208
+ <li key={i}>{String(item)}</li>
209
+ ))}
210
+ </ul>
211
+ )
212
+ }
213
+
214
+ case 'card': {
215
+ const title = el['title'] ? String(el['title']) : undefined
216
+ const description = el['description'] ? String(el['description']) : undefined
217
+ return (
218
+ <div key={index} className="rounded-xl border bg-card p-6 shadow-sm">
219
+ {title && <h3 className="font-semibold mb-1">{title}</h3>}
220
+ {description && <p className="text-sm text-muted-foreground mb-4">{description}</p>}
221
+ {renderChildren(el.children, 'gap-4', renderElement)}
222
+ </div>
223
+ )
224
+ }
225
+
226
+ case 'grid': {
227
+ const columns = Math.max(1, Math.min(12, Number(el['columns'] ?? 2)))
228
+ const gapPx = el['gap'] !== undefined ? `${Number(el['gap'])}px` : undefined
229
+ return (
230
+ <div
231
+ key={index}
232
+ className={`grid gap-4 ${layoutClasses(el)}`.trim()}
233
+ style={{
234
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
235
+ ...(gapPx ? { gap: gapPx } : {}),
236
+ }}
237
+ >
238
+ {(el.children ?? []).map((c, i) => renderElement(c, i))}
239
+ </div>
240
+ )
241
+ }
242
+
243
+ case 'group': {
244
+ const layout = layoutClasses(el)
245
+ return (
246
+ <div key={index} className={layout || undefined}>
247
+ {renderChildren(el.children, 'gap-4', renderElement)}
248
+ </div>
249
+ )
250
+ }
251
+
252
+ case 'split': {
253
+ const from = el['from'] === 'left' ? 'left' : 'right'
254
+ const gap = Math.max(0, Math.min(12, Number(el['gap'] ?? 6)))
255
+ const children = el.children ?? []
256
+ // Find the explicit aside child first; fall back to "second child is
257
+ // aside" so terse Split.make().schema([main, aside]) still works.
258
+ let asideIdx = children.findIndex(c => c['aside'] === true)
259
+ if (asideIdx === -1 && children.length >= 2) asideIdx = 1
260
+ const mainChildren = children.filter((_, i) => i !== asideIdx)
261
+ const asideChild = asideIdx >= 0 ? children[asideIdx] : undefined
262
+
263
+ const orderClasses = from === 'left'
264
+ ? { aside: '@md:order-first', main: '@md:order-last' }
265
+ : { aside: '@md:order-last', main: '@md:order-first' }
266
+
267
+ return (
268
+ <div
269
+ key={index}
270
+ className={`@container flex flex-col @md:flex-row gap-${gap} ${layoutClasses(el)}`.trim()}
271
+ >
272
+ <div className={`flex flex-col gap-4 flex-1 min-w-0 ${orderClasses.main}`}>
273
+ {mainChildren.map((c, i) => renderElement(c, i))}
274
+ </div>
275
+ {asideChild && (
276
+ <aside className={`flex flex-col gap-4 @md:w-80 @md:shrink-0 ${orderClasses.aside}`}>
277
+ {renderElement(asideChild, asideIdx)}
278
+ </aside>
279
+ )}
280
+ </div>
281
+ )
282
+ }
283
+
284
+ case 'fieldset': {
285
+ const label = String(el['label'] ?? '')
286
+ const columns = Math.max(1, Math.min(3, Number(el['columns'] ?? 1)))
287
+ const gridStyle = columns > 1
288
+ ? { display: 'grid', gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`, gap: '1rem' }
289
+ : undefined
290
+ return (
291
+ <fieldset
292
+ key={index}
293
+ className={`rounded-md border border-border px-4 pt-3 pb-4 ${layoutClasses(el)}`.trim()}
294
+ >
295
+ {label && <legend className="px-1 text-xs font-medium text-muted-foreground">{label}</legend>}
296
+ <div className={columns === 1 ? 'flex flex-col gap-3' : undefined} style={gridStyle}>
297
+ {(el.children ?? []).map((c, i) => renderElement(c, i))}
298
+ </div>
299
+ </fieldset>
300
+ )
301
+ }
302
+
303
+ default:
304
+ return undefined
305
+ }
306
+ }
@@ -0,0 +1,62 @@
1
+ import React from 'react'
2
+ import type { ElementMeta } from '../../schema/Element.js'
3
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs.js'
4
+ import { renderChildren } from './helpers.js'
5
+
6
+ /**
7
+ * Top-level `Tabs` element. Variants:
8
+ * - `'pills'` (default) — uses the shadcn Tabs primitive's stock chrome.
9
+ * - `'underline'` — flat tab strip with a bottom border and per-tab
10
+ * underline on selection.
11
+ *
12
+ * `renderElement` is injected for the body content of each tab so the
13
+ * renderer can recurse without re-importing the main switch.
14
+ */
15
+ export function TabsRenderer({
16
+ el,
17
+ index,
18
+ renderElement,
19
+ }: {
20
+ el: ElementMeta
21
+ index: number
22
+ renderElement: (el: ElementMeta, index: number) => React.ReactNode
23
+ }) {
24
+ const tabs = (el.children ?? []).filter(c => c.type === 'tab')
25
+ if (tabs.length === 0) return null
26
+
27
+ const variant = el['variant'] === 'underline' ? 'underline' : 'pills'
28
+ const tabValues = tabs.map((_, i) => `tab-${i}`)
29
+ const defaultValue = tabValues[0]!
30
+
31
+ // Underline variant overrides the primitive's pill chrome with a bottom
32
+ // border on the list and per-trigger underline-on-selected. No
33
+ // `<TabsIndicator>` is rendered, so there's no sliding pill to hide.
34
+ const listClass = variant === 'underline'
35
+ ? 'relative flex h-auto w-fit justify-start gap-0 rounded-none bg-transparent p-0 text-muted-foreground border-b border-border'
36
+ : undefined
37
+ const triggerClass = variant === 'underline'
38
+ ? 'rounded-none border-0 border-b-2 border-transparent bg-transparent px-4 py-2 text-sm font-medium -mb-px data-[active]:border-primary data-[active]:text-foreground data-[active]:bg-transparent data-[active]:shadow-none'
39
+ : undefined
40
+
41
+ return (
42
+ <Tabs key={index} defaultValue={defaultValue}>
43
+ <TabsList className={listClass}>
44
+ {tabs.map((tab, i) => (
45
+ <TabsTrigger key={i} value={tabValues[i]!} className={triggerClass}>
46
+ {String(tab['label'] ?? '')}
47
+ {tab['badge'] ? (
48
+ <span className="ml-2 text-xs px-1.5 py-0.5 rounded-full bg-muted">
49
+ {String(tab['badge'])}
50
+ </span>
51
+ ) : null}
52
+ </TabsTrigger>
53
+ ))}
54
+ </TabsList>
55
+ {tabs.map((tab, i) => (
56
+ <TabsContent key={i} value={tabValues[i]!} className="pt-2">
57
+ {renderChildren(tab['children'] as ElementMeta[] | undefined, 'gap-4', renderElement)}
58
+ </TabsContent>
59
+ ))}
60
+ </Tabs>
61
+ )
62
+ }