@pilotiq/pilotiq 0.7.1 → 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 +154 -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 +31 -10
  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 +31 -9
@@ -0,0 +1,173 @@
1
+ import type { Router } from '@rudderjs/router'
2
+ import { view } from '@rudderjs/view'
3
+ import type { Pilotiq } from '../Pilotiq.js'
4
+ import type { Page } from '../Page.js'
5
+ import { resolveSchema, type SchemaContext } from '../schema/resolveSchema.js'
6
+ import { dispatchFormSubmit, findForms, selectForm } from '../elements/dispatchForm.js'
7
+ import { dispatchAction, parseActionBody } from '../elements/dispatchAction.js'
8
+ import { pageBasePath } from '../clusterPaths.js'
9
+ import {
10
+ panelInfo, callPageSchema, tagFormActions, tagActionDispatch,
11
+ customPageData,
12
+ } from '../pageData.js'
13
+ import {
14
+ wantsJson,
15
+ readFormBody,
16
+ normalizeRedirect,
17
+ splitMeta,
18
+ forbidden,
19
+ policyAccess,
20
+ resolveDispatchTarget,
21
+ handleFormState,
22
+ handleFormWizard,
23
+ handleFormCreateOption,
24
+ handleFormMentions,
25
+ handleWidgetData,
26
+ sendActionResult,
27
+ sendRedirectResponse,
28
+ } from './helpers.js'
29
+
30
+ /**
31
+ * Register the routes for a single custom Page — the optional widget /
32
+ * form-state companions, the GET render, action dispatch, and the
33
+ * page-level POST (when the page's schema includes a `Form`).
34
+ *
35
+ * Pulled out of `registerPilotiqRoutes` in 2026-05-12 (Phase 3 of the
36
+ * routes.ts split). Called once per `cfg.pages` entry. The caller is
37
+ * responsible for skipping the dashboard page (it's served by the
38
+ * panel-base GET).
39
+ */
40
+ export function registerCustomPageRoutes(
41
+ router: Router,
42
+ pilotiq: Pilotiq,
43
+ PageClass: typeof Page,
44
+ base: string,
45
+ ): void {
46
+ const cfg = pilotiq.getConfig()
47
+ const pageSlug = PageClass.getSlug()
48
+ const pageUrl = pageBasePath(base, PageClass)
49
+
50
+ // Plan #15 — per-page widget polling endpoint. Mirrors the
51
+ // panel-scope `${base}/_widget/:id` but resolves the custom page's
52
+ // schema instead of the dashboard's.
53
+ router.post(`${pageUrl}/_widget/:id`, async (req, res) => {
54
+ const user = await pilotiq.resolveUser(req)
55
+ if (!await policyAccess(PageClass, user)) return forbidden(res, true)
56
+ return handleWidgetData(req, res, pilotiq, { kind: 'page', pageSlug }, req.params['id']!)
57
+ })
58
+
59
+ // Plan #5 partial-resolve endpoint for custom pages with reactive forms.
60
+ // POST ${base}/${pageSlug}/_form/:formId/state
61
+ router.post(`${pageUrl}/_form/:formId/state`, async (req, res) => {
62
+ const user = await pilotiq.resolveUser(req)
63
+ if (!await policyAccess(PageClass, user)) return forbidden(res, true)
64
+ const formId = req.params['formId']!
65
+ return handleFormState(req, res, pilotiq, { kind: 'page', pageSlug }, formId)
66
+ })
67
+
68
+ // Plan #8 wizard step-validate endpoint for custom pages.
69
+ router.post(`${pageUrl}/_form/:formId/wizard`, async (req, res) => {
70
+ const user = await pilotiq.resolveUser(req)
71
+ if (!await policyAccess(PageClass, user)) return forbidden(res, true)
72
+ const formId = req.params['formId']!
73
+ return handleFormWizard(req, res, pilotiq, { kind: 'page', pageSlug }, formId)
74
+ })
75
+
76
+ // Async-mention endpoint for custom pages.
77
+ router.post(`${pageUrl}/_form/:formId/mentions`, async (req, res) => {
78
+ const user = await pilotiq.resolveUser(req)
79
+ if (!await policyAccess(PageClass, user)) return forbidden(res, true)
80
+ const formId = req.params['formId']!
81
+ return handleFormMentions(req, res, pilotiq, { kind: 'page', pageSlug }, formId)
82
+ })
83
+
84
+ // SelectField inline-create modal endpoint for custom pages.
85
+ router.post(`${pageUrl}/_form/:formId/create-option/:fieldName`, async (req, res) => {
86
+ const user = await pilotiq.resolveUser(req)
87
+ if (!await policyAccess(PageClass, user)) return forbidden(res, true)
88
+ const formId = req.params['formId']!
89
+ const fieldName = req.params['fieldName']!
90
+ return handleFormCreateOption(req, res, pilotiq, { kind: 'page', pageSlug }, formId, fieldName)
91
+ })
92
+
93
+ router.get(pageUrl, async (req, res) => {
94
+ const user = await pilotiq.resolveUser(req)
95
+ if (!await policyAccess(PageClass, user)) return forbidden(res, wantsJson(req))
96
+ const data = await customPageData(pilotiq, pageSlug, req)
97
+ return view('pilotiq.slug', data ?? {})
98
+ })
99
+
100
+ // Action dispatch — POST ${base}/${pageSlug}/_action/:actionName
101
+ router.post(`${pageUrl}/_action/:actionName`, async (req, res) => {
102
+ const user = await pilotiq.resolveUser(req)
103
+ if (!await policyAccess(PageClass, user)) return forbidden(res, wantsJson(req))
104
+
105
+ const actionName = req.params['actionName']!
106
+ const json = wantsJson(req)
107
+ const body = await readFormBody(req)
108
+ const input = parseActionBody(body)
109
+
110
+ const ctx: SchemaContext = user !== null ? { user: user as NonNullable<SchemaContext['user']> } : {}
111
+ const elements = await callPageSchema(PageClass, ctx)
112
+ tagActionDispatch(elements, pageUrl)
113
+ const target = resolveDispatchTarget(elements, actionName)
114
+ if (!target) {
115
+ if (json) { res.status(404); return res.json({ ok: false, error: `Action "${actionName}" not found` }) }
116
+ res.status(404)
117
+ return res.send(`Action "${actionName}" not found on page`)
118
+ }
119
+
120
+ const result = await dispatchAction(target.action, {
121
+ ...input,
122
+ request: req,
123
+ user,
124
+ ...(target.rowField ? { rowField: target.rowField } : {}),
125
+ ...(target.formSchema ? { formSchema: target.formSchema } : {}),
126
+ })
127
+ return sendActionResult(req, res, json, result, base, pageUrl)
128
+ })
129
+
130
+ // Custom pages can also accept submits when their schema includes a Form.
131
+ router.post(pageUrl, async (req, res) => {
132
+ const body = await readFormBody(req)
133
+ const { values, formId } = splitMeta(body)
134
+ const json = wantsJson(req)
135
+
136
+ const user = await pilotiq.resolveUser(req)
137
+ if (!await policyAccess(PageClass, user)) return forbidden(res, json)
138
+
139
+ const ctx: SchemaContext = user !== null ? { user: user as NonNullable<SchemaContext['user']> } : {}
140
+ const elements = await callPageSchema(PageClass, ctx)
141
+ tagFormActions(elements, pageUrl)
142
+ const form = selectForm(findForms(elements), formId)
143
+ if (!form) {
144
+ if (json) { res.status(404); return res.json({ ok: false, error: 'No form found on page' }) }
145
+ res.status(404)
146
+ return res.send('No form found on page')
147
+ }
148
+
149
+ const result = await dispatchFormSubmit(form, values, { values, basePath: base })
150
+
151
+ if (!result.ok) {
152
+ if (json) {
153
+ res.status(422)
154
+ return res.json({ ok: false, errors: result.errors })
155
+ }
156
+ form.withValues(values).withErrors(result.errors)
157
+ const schemaData = await resolveSchema(elements, ctx)
158
+ res.status(422)
159
+ return view('pilotiq.slug', {
160
+ pageType: 'page',
161
+ panel: await panelInfo(pilotiq, req),
162
+ page: PageClass.toMeta(),
163
+ schemaData,
164
+ basePath: base,
165
+ layout: cfg.layout,
166
+ hasErrors: true,
167
+ })
168
+ }
169
+
170
+ const redirect = normalizeRedirect(result.redirect, base) ?? pageUrl
171
+ return sendRedirectResponse(req, res, json, redirect, result.notifications)
172
+ })
173
+ }
@@ -0,0 +1,204 @@
1
+ import type { Router } from '@rudderjs/router'
2
+ import type { AppRequest } from '@rudderjs/contracts'
3
+ import { view } from '@rudderjs/view'
4
+ import type { Pilotiq } from '../Pilotiq.js'
5
+ import { dashboardData, searchData } from '../pageData.js'
6
+ import {
7
+ listForUser as listDatabaseNotifications,
8
+ markAsRead as markDatabaseNotificationAsRead,
9
+ markAsUnread as markDatabaseNotificationAsUnread,
10
+ markAllAsRead as markAllDatabaseNotificationsAsRead,
11
+ } from '../notifications/database.js'
12
+ import { dispatchNotificationAction } from '../notifications/dispatchNotificationAction.js'
13
+ import { registerBroadcastAuth } from '../notifications/registerBroadcastAuth.js'
14
+ import {
15
+ wantsJson,
16
+ forbidden,
17
+ policyAccess,
18
+ handleWidgetData,
19
+ handleUploadRequest,
20
+ } from './helpers.js'
21
+
22
+ /**
23
+ * Register the panel-level sibling routes — the ones that don't belong
24
+ * to any individual Resource / Global / custom Page:
25
+ *
26
+ * - `GET ${base}` — dashboard
27
+ * - `POST ${base}/_uploads` — `FileUpload` field POST target
28
+ * - `POST ${base}/_widget/:id` — Plan #15 dashboard widget polling
29
+ * - `GET ${base}/_search` — Plan #12 global search
30
+ * - `${base}/_notifications/...` — bell-icon dropdown endpoints (only
31
+ * mounted when `Pilotiq.databaseNotifications()` was called)
32
+ *
33
+ * Plus the broadcast-auth registration that the notifications path
34
+ * needs in the same `if` branch. Reads `cfg = pilotiq.getConfig()`
35
+ * internally so the call site only has to thread the basePath.
36
+ */
37
+ export function registerPanelRoutes(
38
+ router: Router,
39
+ pilotiq: Pilotiq,
40
+ base: string,
41
+ ): void {
42
+ const cfg = pilotiq.getConfig()
43
+
44
+ // ── Dashboard (1-segment) ─────────────────────────────
45
+ router.get(base, async (req, res) => {
46
+ // Plan #15 — when `panel.dashboard(P)` is set, gate the dashboard
47
+ // route through the page's `canAccess` predicate. Same posture as
48
+ // custom pages — fail-closed on throw.
49
+ if (cfg.dashboardPage) {
50
+ const user = await pilotiq.resolveUser(req)
51
+ if (!await policyAccess(cfg.dashboardPage!, user)) {
52
+ return forbidden(res, wantsJson(req))
53
+ }
54
+ }
55
+ return view('pilotiq.dashboard', await dashboardData(pilotiq, req))
56
+ })
57
+
58
+ // ── File uploads (FileUpload field POST target) ───────
59
+ router.post(`${base}/_uploads`, async (req, res) => {
60
+ return handleUploadRequest(req, res, pilotiq)
61
+ })
62
+
63
+ // ── Plan #15 dashboard widget polling ─────────────────
64
+ // POST ${base}/_widget/:id — re-resolves the dashboard page schema,
65
+ // finds widget by id, runs `getServerData(ctx)`. Body: `{ filter? }`.
66
+ // Mounted unconditionally — widgetData() returns 404 when no
67
+ // dashboard page is registered, so this stays cheap when unused.
68
+ router.post(`${base}/_widget/:id`, async (req, res) => {
69
+ if (cfg.dashboardPage) {
70
+ const user = await pilotiq.resolveUser(req)
71
+ if (!await policyAccess(cfg.dashboardPage!, user)) return forbidden(res, true)
72
+ }
73
+ return handleWidgetData(req, res, pilotiq, { kind: 'panel' }, req.params['id']!)
74
+ })
75
+
76
+ // ── Plan #12 global search ────────────────────────────
77
+ // GET ${base}/_search?q=…&limit=… → { ok, results }
78
+ // No 403 on unrecognised users — `searchAllResources` filters per
79
+ // resource. The Pilotiq.guard() layer above is the panel-level gate.
80
+ router.get(`${base}/_search`, async (req, res) => {
81
+ const query = req.query as Record<string, unknown> | undefined
82
+ const rawQ = query?.['q']
83
+ const q = typeof rawQ === 'string' ? rawQ.slice(0, 200) : ''
84
+ const data = await searchData(pilotiq, q, req)
85
+ return res.json(data)
86
+ })
87
+
88
+ // ── Database notifications (bell-icon dropdown) ───────
89
+ // Only mounted when `Pilotiq.databaseNotifications()` was called.
90
+ // Every route 401s when no user resolves so a non-authenticated
91
+ // request never sees another user's inbox. The `notifiable_type`
92
+ // value is configurable but defaults to `'users'` to match
93
+ // `@rudderjs/notification`'s `DatabaseChannel` writes.
94
+ if (cfg.databaseNotifications?.enabled) {
95
+ const dn = cfg.databaseNotifications
96
+ const notifiableType = dn.notifiableType ?? 'users'
97
+ const pageSize = dn.pageSize ?? 25
98
+
99
+ /** Resolve `{ id }` from the panel's user resolver. Returns null
100
+ * when no user / unknown id — every route then 401s. The user
101
+ * object is opaque to pilotiq; we duck-type `.id`. */
102
+ const resolveUserId = async (req: AppRequest): Promise<string | null> => {
103
+ const user = await pilotiq.resolveUser(req)
104
+ if (!user || typeof user !== 'object') return null
105
+ const id = (user as { id?: unknown }).id
106
+ if (id === undefined || id === null) return null
107
+ return String(id)
108
+ }
109
+
110
+ // GET ${base}/_notifications → { notifications, unreadCount }
111
+ router.get(`${base}/_notifications`, async (req, res) => {
112
+ const id = await resolveUserId(req)
113
+ if (id === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
114
+ const url = new URL(req.url ?? '/', 'http://localhost')
115
+ const unreadOnly = url.searchParams.get('unread') === 'true'
116
+ const limitRaw = Number(url.searchParams.get('limit') ?? pageSize)
117
+ const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? Math.min(limitRaw, 100) : pageSize
118
+ const data = await listDatabaseNotifications({
119
+ notifiableType,
120
+ notifiableId: id,
121
+ limit,
122
+ unreadOnly,
123
+ })
124
+ return res.json({ ok: true, ...data })
125
+ })
126
+
127
+ // POST ${base}/_notifications/:id/read
128
+ router.post(`${base}/_notifications/:id/read`, async (req, res) => {
129
+ const userId = await resolveUserId(req)
130
+ if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
131
+ const rowId = (req.params as Record<string, string | undefined>)['id'] ?? ''
132
+ const updated = await markDatabaseNotificationAsRead(rowId, {
133
+ notifiableType,
134
+ notifiableId: userId,
135
+ })
136
+ return res.json({ ok: updated })
137
+ })
138
+
139
+ // POST ${base}/_notifications/:id/unread
140
+ router.post(`${base}/_notifications/:id/unread`, async (req, res) => {
141
+ const userId = await resolveUserId(req)
142
+ if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
143
+ const rowId = (req.params as Record<string, string | undefined>)['id'] ?? ''
144
+ const updated = await markDatabaseNotificationAsUnread(rowId, {
145
+ notifiableType,
146
+ notifiableId: userId,
147
+ })
148
+ return res.json({ ok: updated })
149
+ })
150
+
151
+ // POST ${base}/_notifications/read-all
152
+ router.post(`${base}/_notifications/read-all`, async (req, res) => {
153
+ const userId = await resolveUserId(req)
154
+ if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
155
+ const count = await markAllDatabaseNotificationsAsRead({
156
+ notifiableType,
157
+ notifiableId: userId,
158
+ })
159
+ return res.json({ ok: true, count })
160
+ })
161
+
162
+ // POST ${base}/_notifications/:id/_action/:actionName
163
+ //
164
+ // Notification action dispatch — looks up the stored action on the
165
+ // row, resolves the named handler against the panel's
166
+ // `notificationHandlers` registry, and runs it with the row's
167
+ // stored payload. Optionally flips `read_at` server-side when the
168
+ // action carried `markAsRead: true`.
169
+ //
170
+ // Defends in depth: 404s on missing row / wrong owner / action
171
+ // missing / non-string handler / unknown registry name. Body is
172
+ // ignored — payload reads exclusively from the stored row, so a
173
+ // tampered client can't inject extra payload keys.
174
+ router.post(`${base}/_notifications/:id/_action/:actionName`, async (req, res) => {
175
+ const user = await pilotiq.resolveUser(req)
176
+ const userId = user && typeof user === 'object'
177
+ ? ((user as { id?: unknown }).id !== undefined && (user as { id?: unknown }).id !== null
178
+ ? String((user as { id: unknown }).id) : null)
179
+ : null
180
+ if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
181
+
182
+ const params = (req.params as Record<string, string | undefined>)
183
+ const result = await dispatchNotificationAction(pilotiq, {
184
+ notificationId: params['id'] ?? '',
185
+ actionName: params['actionName'] ?? '',
186
+ notifiableType,
187
+ notifiableId: userId,
188
+ user,
189
+ request: req,
190
+ })
191
+ if (!result.ok) {
192
+ res.status(result.status)
193
+ return res.json({ ok: false, error: result.error })
194
+ }
195
+ return res.json(result)
196
+ })
197
+
198
+ // Phase 2 — register the broadcast auth callback for private
199
+ // `pilotiq-notifications.<userId>` channels. Soft-fails when
200
+ // `@rudderjs/broadcast` isn't installed; apps that haven't enabled
201
+ // broadcast on the toggle stay quiet either way.
202
+ void registerBroadcastAuth(pilotiq)
203
+ }
204
+ }