@pilotiq/pilotiq 0.7.2 → 0.8.1

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 (371) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/CHANGELOG.md +208 -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/FormStateContext.d.ts.map +1 -1
  93. package/dist/react/FormStateContext.js +87 -0
  94. package/dist/react/FormStateContext.js.map +1 -1
  95. package/dist/react/RecordWrapperGate.d.ts +25 -0
  96. package/dist/react/RecordWrapperGate.d.ts.map +1 -0
  97. package/dist/react/RecordWrapperGate.js +30 -0
  98. package/dist/react/RecordWrapperGate.js.map +1 -0
  99. package/dist/react/RecordWrapperRegistry.d.ts +31 -0
  100. package/dist/react/RecordWrapperRegistry.d.ts.map +1 -0
  101. package/dist/react/RecordWrapperRegistry.js +15 -0
  102. package/dist/react/RecordWrapperRegistry.js.map +1 -0
  103. package/dist/react/SchemaRenderer.d.ts +17 -23
  104. package/dist/react/SchemaRenderer.d.ts.map +1 -1
  105. package/dist/react/SchemaRenderer.js +71 -3647
  106. package/dist/react/SchemaRenderer.js.map +1 -1
  107. package/dist/react/component-slots.d.ts +103 -0
  108. package/dist/react/component-slots.d.ts.map +1 -0
  109. package/dist/react/component-slots.js +18 -0
  110. package/dist/react/component-slots.js.map +1 -0
  111. package/dist/react/fields/BuilderInput.d.ts.map +1 -1
  112. package/dist/react/fields/BuilderInput.js +21 -117
  113. package/dist/react/fields/BuilderInput.js.map +1 -1
  114. package/dist/react/fields/MarkdownInput.d.ts.map +1 -1
  115. package/dist/react/fields/MarkdownInput.js +1 -3
  116. package/dist/react/fields/MarkdownInput.js.map +1 -1
  117. package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
  118. package/dist/react/fields/RepeaterInput.js +22 -127
  119. package/dist/react/fields/RepeaterInput.js.map +1 -1
  120. package/dist/react/fields/rowState.d.ts +40 -0
  121. package/dist/react/fields/rowState.d.ts.map +1 -0
  122. package/dist/react/fields/rowState.js +60 -0
  123. package/dist/react/fields/rowState.js.map +1 -0
  124. package/dist/react/fields/useRowReorderDnd.d.ts +28 -0
  125. package/dist/react/fields/useRowReorderDnd.d.ts.map +1 -0
  126. package/dist/react/fields/useRowReorderDnd.js +51 -0
  127. package/dist/react/fields/useRowReorderDnd.js.map +1 -0
  128. package/dist/react/index.d.ts +9 -0
  129. package/dist/react/index.d.ts.map +1 -1
  130. package/dist/react/index.js +8 -0
  131. package/dist/react/index.js.map +1 -1
  132. package/dist/react/layouts/SidebarLayout.d.ts +1 -1
  133. package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
  134. package/dist/react/layouts/SidebarLayout.js +10 -2
  135. package/dist/react/layouts/SidebarLayout.js.map +1 -1
  136. package/dist/react/layouts/TopbarLayout.d.ts +1 -1
  137. package/dist/react/layouts/TopbarLayout.d.ts.map +1 -1
  138. package/dist/react/layouts/TopbarLayout.js +19 -11
  139. package/dist/react/layouts/TopbarLayout.js.map +1 -1
  140. package/dist/react/parseRecordEditUrl.d.ts +29 -0
  141. package/dist/react/parseRecordEditUrl.d.ts.map +1 -0
  142. package/dist/react/parseRecordEditUrl.js +25 -0
  143. package/dist/react/parseRecordEditUrl.js.map +1 -0
  144. package/dist/react/persistedState.d.ts +19 -0
  145. package/dist/react/persistedState.d.ts.map +1 -0
  146. package/dist/react/persistedState.js +51 -0
  147. package/dist/react/persistedState.js.map +1 -0
  148. package/dist/react/schemaRenderer/AlertRenderer.d.ts +12 -0
  149. package/dist/react/schemaRenderer/AlertRenderer.d.ts.map +1 -0
  150. package/dist/react/schemaRenderer/AlertRenderer.js +61 -0
  151. package/dist/react/schemaRenderer/AlertRenderer.js.map +1 -0
  152. package/dist/react/schemaRenderer/EntryRenderer.d.ts +13 -0
  153. package/dist/react/schemaRenderer/EntryRenderer.d.ts.map +1 -0
  154. package/dist/react/schemaRenderer/EntryRenderer.js +277 -0
  155. package/dist/react/schemaRenderer/EntryRenderer.js.map +1 -0
  156. package/dist/react/schemaRenderer/SectionRenderer.d.ts +16 -0
  157. package/dist/react/schemaRenderer/SectionRenderer.d.ts.map +1 -0
  158. package/dist/react/schemaRenderer/SectionRenderer.js +62 -0
  159. package/dist/react/schemaRenderer/SectionRenderer.js.map +1 -0
  160. package/dist/react/schemaRenderer/SimpleElements.d.ts +25 -0
  161. package/dist/react/schemaRenderer/SimpleElements.d.ts.map +1 -0
  162. package/dist/react/schemaRenderer/SimpleElements.js +147 -0
  163. package/dist/react/schemaRenderer/SimpleElements.js.map +1 -0
  164. package/dist/react/schemaRenderer/TabsRenderer.d.ts +17 -0
  165. package/dist/react/schemaRenderer/TabsRenderer.d.ts.map +1 -0
  166. package/dist/react/schemaRenderer/TabsRenderer.js +31 -0
  167. package/dist/react/schemaRenderer/TabsRenderer.js.map +1 -0
  168. package/dist/react/schemaRenderer/WizardRenderer.d.ts +34 -0
  169. package/dist/react/schemaRenderer/WizardRenderer.d.ts.map +1 -0
  170. package/dist/react/schemaRenderer/WizardRenderer.js +208 -0
  171. package/dist/react/schemaRenderer/WizardRenderer.js.map +1 -0
  172. package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts +21 -0
  173. package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts.map +1 -0
  174. package/dist/react/schemaRenderer/action/ActionGroupTrigger.js +82 -0
  175. package/dist/react/schemaRenderer/action/ActionGroupTrigger.js.map +1 -0
  176. package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts +30 -0
  177. package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts.map +1 -0
  178. package/dist/react/schemaRenderer/action/ActionModalDialog.js +182 -0
  179. package/dist/react/schemaRenderer/action/ActionModalDialog.js.map +1 -0
  180. package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts +17 -0
  181. package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts.map +1 -0
  182. package/dist/react/schemaRenderer/action/ConfirmActionDialog.js +19 -0
  183. package/dist/react/schemaRenderer/action/ConfirmActionDialog.js.map +1 -0
  184. package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts +16 -0
  185. package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts.map +1 -0
  186. package/dist/react/schemaRenderer/action/HandlerActionButton.js +16 -0
  187. package/dist/react/schemaRenderer/action/HandlerActionButton.js.map +1 -0
  188. package/dist/react/schemaRenderer/action/MethodActionButton.d.ts +22 -0
  189. package/dist/react/schemaRenderer/action/MethodActionButton.d.ts.map +1 -0
  190. package/dist/react/schemaRenderer/action/MethodActionButton.js +26 -0
  191. package/dist/react/schemaRenderer/action/MethodActionButton.js.map +1 -0
  192. package/dist/react/schemaRenderer/action/buttons.d.ts +18 -0
  193. package/dist/react/schemaRenderer/action/buttons.d.ts.map +1 -0
  194. package/dist/react/schemaRenderer/action/buttons.js +74 -0
  195. package/dist/react/schemaRenderer/action/buttons.js.map +1 -0
  196. package/dist/react/schemaRenderer/action/helpers.d.ts +26 -0
  197. package/dist/react/schemaRenderer/action/helpers.d.ts.map +1 -0
  198. package/dist/react/schemaRenderer/action/helpers.js +126 -0
  199. package/dist/react/schemaRenderer/action/helpers.js.map +1 -0
  200. package/dist/react/schemaRenderer/action/renderAction.d.ts +21 -0
  201. package/dist/react/schemaRenderer/action/renderAction.d.ts.map +1 -0
  202. package/dist/react/schemaRenderer/action/renderAction.js +102 -0
  203. package/dist/react/schemaRenderer/action/renderAction.js.map +1 -0
  204. package/dist/react/schemaRenderer/columnFormat.d.ts +10 -0
  205. package/dist/react/schemaRenderer/columnFormat.d.ts.map +1 -0
  206. package/dist/react/schemaRenderer/columnFormat.js +76 -0
  207. package/dist/react/schemaRenderer/columnFormat.js.map +1 -0
  208. package/dist/react/schemaRenderer/constants.d.ts +8 -0
  209. package/dist/react/schemaRenderer/constants.d.ts.map +1 -0
  210. package/dist/react/schemaRenderer/constants.js +45 -0
  211. package/dist/react/schemaRenderer/constants.js.map +1 -0
  212. package/dist/react/schemaRenderer/form/FormRenderer.d.ts +29 -0
  213. package/dist/react/schemaRenderer/form/FormRenderer.d.ts.map +1 -0
  214. package/dist/react/schemaRenderer/form/FormRenderer.js +163 -0
  215. package/dist/react/schemaRenderer/form/FormRenderer.js.map +1 -0
  216. package/dist/react/schemaRenderer/form/renderField.d.ts +6 -0
  217. package/dist/react/schemaRenderer/form/renderField.d.ts.map +1 -0
  218. package/dist/react/schemaRenderer/form/renderField.js +239 -0
  219. package/dist/react/schemaRenderer/form/renderField.js.map +1 -0
  220. package/dist/react/schemaRenderer/helpers.d.ts +32 -0
  221. package/dist/react/schemaRenderer/helpers.d.ts.map +1 -0
  222. package/dist/react/schemaRenderer/helpers.js +52 -0
  223. package/dist/react/schemaRenderer/helpers.js.map +1 -0
  224. package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts +60 -0
  225. package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts.map +1 -0
  226. package/dist/react/schemaRenderer/table/CardsLayoutBody.js +189 -0
  227. package/dist/react/schemaRenderer/table/CardsLayoutBody.js.map +1 -0
  228. package/dist/react/schemaRenderer/table/TableRenderer.d.ts +29 -0
  229. package/dist/react/schemaRenderer/table/TableRenderer.d.ts.map +1 -0
  230. package/dist/react/schemaRenderer/table/TableRenderer.js +85 -0
  231. package/dist/react/schemaRenderer/table/TableRenderer.js.map +1 -0
  232. package/dist/react/schemaRenderer/table/TableRendererBody.d.ts +18 -0
  233. package/dist/react/schemaRenderer/table/TableRendererBody.d.ts.map +1 -0
  234. package/dist/react/schemaRenderer/table/TableRendererBody.js +555 -0
  235. package/dist/react/schemaRenderer/table/TableRendererBody.js.map +1 -0
  236. package/dist/react/schemaRenderer/table/filters.d.ts +263 -0
  237. package/dist/react/schemaRenderer/table/filters.d.ts.map +1 -0
  238. package/dist/react/schemaRenderer/table/filters.js +497 -0
  239. package/dist/react/schemaRenderer/table/filters.js.map +1 -0
  240. package/dist/react/schemaRenderer/table/formatCell.d.ts +11 -0
  241. package/dist/react/schemaRenderer/table/formatCell.d.ts.map +1 -0
  242. package/dist/react/schemaRenderer/table/formatCell.js +172 -0
  243. package/dist/react/schemaRenderer/table/formatCell.js.map +1 -0
  244. package/dist/react/schemaRenderer/table/links.d.ts +42 -0
  245. package/dist/react/schemaRenderer/table/links.d.ts.map +1 -0
  246. package/dist/react/schemaRenderer/table/links.js +55 -0
  247. package/dist/react/schemaRenderer/table/links.js.map +1 -0
  248. package/dist/react/schemaRenderer/table/renderRowActions.d.ts +13 -0
  249. package/dist/react/schemaRenderer/table/renderRowActions.d.ts.map +1 -0
  250. package/dist/react/schemaRenderer/table/renderRowActions.js +25 -0
  251. package/dist/react/schemaRenderer/table/renderRowActions.js.map +1 -0
  252. package/dist/react/schemaRenderer/table/url.d.ts +41 -0
  253. package/dist/react/schemaRenderer/table/url.d.ts.map +1 -0
  254. package/dist/react/schemaRenderer/table/url.js +114 -0
  255. package/dist/react/schemaRenderer/table/url.js.map +1 -0
  256. package/dist/routes/globals.d.ts +13 -0
  257. package/dist/routes/globals.d.ts.map +1 -0
  258. package/dist/routes/globals.js +131 -0
  259. package/dist/routes/globals.js.map +1 -0
  260. package/dist/routes/helpers.d.ts +217 -0
  261. package/dist/routes/helpers.d.ts.map +1 -0
  262. package/dist/routes/helpers.js +498 -0
  263. package/dist/routes/helpers.js.map +1 -0
  264. package/dist/routes/pages.d.ts +15 -0
  265. package/dist/routes/pages.d.ts.map +1 -0
  266. package/dist/routes/pages.js +145 -0
  267. package/dist/routes/pages.js.map +1 -0
  268. package/dist/routes/panel.d.ts +19 -0
  269. package/dist/routes/panel.d.ts.map +1 -0
  270. package/dist/routes/panel.js +191 -0
  271. package/dist/routes/panel.js.map +1 -0
  272. package/dist/routes/relations.d.ts +21 -0
  273. package/dist/routes/relations.d.ts.map +1 -0
  274. package/dist/routes/relations.js +1239 -0
  275. package/dist/routes/relations.js.map +1 -0
  276. package/dist/routes/resources.d.ts +28 -0
  277. package/dist/routes/resources.d.ts.map +1 -0
  278. package/dist/routes/resources.js +741 -0
  279. package/dist/routes/resources.js.map +1 -0
  280. package/dist/routes/theme.d.ts +12 -0
  281. package/dist/routes/theme.d.ts.map +1 -0
  282. package/dist/routes/theme.js +82 -0
  283. package/dist/routes/theme.js.map +1 -0
  284. package/dist/routes.d.ts.map +1 -1
  285. package/dist/routes.js +64 -3078
  286. package/dist/routes.js.map +1 -1
  287. package/dist/vite.d.ts +1 -0
  288. package/dist/vite.d.ts.map +1 -1
  289. package/dist/vite.js +26 -5
  290. package/dist/vite.js.map +1 -1
  291. package/package.json +2 -1
  292. package/src/Pilotiq.ts +95 -0
  293. package/src/actions/Action.ts +79 -723
  294. package/src/actions/bulkFactories.ts +168 -0
  295. package/src/actions/crudFactories.ts +220 -0
  296. package/src/actions/factoryHelpers.ts +177 -0
  297. package/src/actions/m2mFactories.ts +193 -0
  298. package/src/actions/relationFactories.ts +372 -0
  299. package/src/elements/dispatchForm.ts +1 -1
  300. package/src/elements/dispatchTable.ts +1 -1
  301. package/src/fields/Field.ts +39 -0
  302. package/src/pageData/breadcrumbs.ts +288 -0
  303. package/src/pageData/forms.ts +578 -0
  304. package/src/pageData/helpers.ts +764 -0
  305. package/src/pageData/misc.ts +347 -0
  306. package/src/pageData/navigation.ts +779 -0
  307. package/src/pageData/relationPages.ts +1246 -0
  308. package/src/pageData/relationTabs.ts +286 -0
  309. package/src/pageData/resourcePages.ts +593 -0
  310. package/src/pageData.ts +122 -4731
  311. package/src/react/AppShell.tsx +27 -1
  312. package/src/react/CollabExtensionFactoryRegistry.ts +55 -0
  313. package/src/react/CollabRoomContext.ts +42 -0
  314. package/src/react/FormCollabBindingRegistry.ts +72 -0
  315. package/src/react/FormStateContext.tsx +91 -0
  316. package/src/react/RecordWrapperGate.tsx +40 -0
  317. package/src/react/RecordWrapperRegistry.ts +39 -0
  318. package/src/react/SchemaRenderer.tsx +230 -6479
  319. package/src/react/component-slots.test.ts +103 -0
  320. package/src/react/component-slots.ts +116 -0
  321. package/src/react/fields/BuilderInput.tsx +29 -117
  322. package/src/react/fields/MarkdownInput.tsx +0 -1
  323. package/src/react/fields/RepeaterInput.tsx +29 -130
  324. package/src/react/fields/rowState.ts +106 -0
  325. package/src/react/fields/useRowReorderDnd.ts +78 -0
  326. package/src/react/index.ts +38 -0
  327. package/src/react/layouts/SidebarLayout.tsx +39 -28
  328. package/src/react/layouts/TopbarLayout.tsx +70 -57
  329. package/src/react/parseRecordEditUrl.test.ts +75 -0
  330. package/src/react/parseRecordEditUrl.ts +55 -0
  331. package/src/react/persistedState.ts +40 -0
  332. package/src/react/schemaRenderer/AlertRenderer.tsx +112 -0
  333. package/src/react/schemaRenderer/EntryRenderer.tsx +501 -0
  334. package/src/react/schemaRenderer/SectionRenderer.tsx +120 -0
  335. package/src/react/schemaRenderer/SimpleElements.tsx +306 -0
  336. package/src/react/schemaRenderer/TabsRenderer.tsx +62 -0
  337. package/src/react/schemaRenderer/WizardRenderer.tsx +338 -0
  338. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +177 -0
  339. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +273 -0
  340. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +61 -0
  341. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +43 -0
  342. package/src/react/schemaRenderer/action/MethodActionButton.tsx +64 -0
  343. package/src/react/schemaRenderer/action/buttons.tsx +99 -0
  344. package/src/react/schemaRenderer/action/helpers.ts +140 -0
  345. package/src/react/schemaRenderer/action/renderAction.tsx +245 -0
  346. package/src/react/schemaRenderer/columnFormat.ts +65 -0
  347. package/src/react/schemaRenderer/constants.ts +50 -0
  348. package/src/react/schemaRenderer/form/FormRenderer.tsx +245 -0
  349. package/src/react/schemaRenderer/form/renderField.tsx +511 -0
  350. package/src/react/schemaRenderer/helpers.tsx +81 -0
  351. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +308 -0
  352. package/src/react/schemaRenderer/table/TableRenderer.tsx +123 -0
  353. package/src/react/schemaRenderer/table/TableRendererBody.tsx +974 -0
  354. package/src/react/schemaRenderer/table/filters.tsx +1233 -0
  355. package/src/react/schemaRenderer/table/formatCell.tsx +264 -0
  356. package/src/react/schemaRenderer/table/links.tsx +112 -0
  357. package/src/react/schemaRenderer/table/renderRowActions.tsx +52 -0
  358. package/src/react/schemaRenderer/table/url.tsx +143 -0
  359. package/src/routes/globals.ts +154 -0
  360. package/src/routes/helpers.ts +668 -0
  361. package/src/routes/pages.ts +173 -0
  362. package/src/routes/panel.ts +204 -0
  363. package/src/routes/relations.ts +1219 -0
  364. package/src/routes/resources.ts +786 -0
  365. package/src/routes/theme.ts +109 -0
  366. package/src/routes.test.ts +1 -1
  367. package/src/routes.ts +64 -3176
  368. package/src/schema/TableWidget.test.ts +2 -2
  369. package/src/theme/migrate.test.ts +178 -0
  370. package/src/vite.test.ts +184 -0
  371. package/src/vite.ts +26 -4
@@ -10,10 +10,12 @@ import type { RightPanelRegistry } from './right-panel-registry.js'
10
10
  import { RightPanelRegistryProvider } from './right-panel-registry.js'
11
11
  import { RightSidebarProvider, useRightSidebarOptional } from './RightSidebarContext.js'
12
12
  import { RightSidebar } from './RightSidebar.js'
13
+ import { RecordWrapperGate } from './RecordWrapperGate.js'
13
14
  import { useIsMobile } from './hooks/use-mobile.js'
14
15
  import type { NavItem, UserMenuMeta, DatabaseNotificationsMeta, RightSidebarMeta } from '../pageData.js'
15
16
  import type { RenderHookMap } from '../RenderHook.js'
16
17
  import { RenderHookSlot } from './RenderHookSlot.js'
18
+ import type { ComponentSlotRegistry } from './component-slots.js'
17
19
 
18
20
  export interface AppShellProps {
19
21
  panel: {
@@ -73,6 +75,13 @@ export interface AppShellProps {
73
75
  * default — chrome renders without any extra wrapping.
74
76
  */
75
77
  layoutProviderRegistry?: ReadonlyArray<React.ComponentType<{ children: React.ReactNode; basePath?: string }>>
78
+ /**
79
+ * Build-time chrome-slot overrides from the Vite plugin. Populated
80
+ * when the panel module calls `Pilotiq.components({ nav, … })`.
81
+ * Sparse `{}` is the no-op default. Currently only `nav` is honored;
82
+ * additional slots will land as concrete consumers ask.
83
+ */
84
+ componentSlotRegistry?: ComponentSlotRegistry
76
85
  children: React.ReactNode
77
86
  }
78
87
 
@@ -110,12 +119,29 @@ export function AppShell({ layout = 'sidebar', notifications, componentRegistry,
110
119
  const hooks = props.panel.renderHooks
111
120
  const rightSidebarMeta = props.panel.rightSidebar
112
121
 
122
+ // Record-scoped wrapper (collab room, audit trail, …) — pass-through
123
+ // when no plugin registered a wrapper or when the URL isn't a
124
+ // record-edit page. Wrapping `children` before forwarding to `Layout`
125
+ // mounts the wrapper around the page content area only, leaving the
126
+ // sidebar / topbar chrome outside.
127
+ const layoutProps = {
128
+ ...props,
129
+ children: (
130
+ <RecordWrapperGate
131
+ basePath={props.basePath}
132
+ {...(props.currentPath !== undefined ? { currentPath: props.currentPath } : {})}
133
+ >
134
+ {props.children}
135
+ </RecordWrapperGate>
136
+ ),
137
+ }
138
+
113
139
  const inner = (
114
140
  <ToasterProvider {...toasterProps}>
115
141
  <CommandPaletteProvider setOpen={setPaletteOpen}>
116
142
  <RenderHookSlot name="panels::body.start" hooks={hooks} />
117
143
  <RightSidebarLayoutFrame>
118
- <Layout {...props} />
144
+ <Layout {...layoutProps} />
119
145
  </RightSidebarLayoutFrame>
120
146
  <RenderHookSlot name="panels::body.end" hooks={hooks} />
121
147
  <CommandPalette {...paletteProps} />
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Module-level registry slot for the Tiptap extension factory that turns
3
+ * a collab room into editor-attachable extensions (`Collaboration` +
4
+ * `CollaborationCursor`).
5
+ *
6
+ * Wiring posture (mirrors `PendingSuggestionOverlayRegistry`):
7
+ * - `@pilotiq-pro/collab`'s plugin calls `registerCollabExtensions(...)`
8
+ * once at boot from inside `register(panel)`. The factory closes over
9
+ * the `@tiptap/extension-collaboration` + `-cursor` imports, so pilotiq
10
+ * core (and `@pilotiq/tiptap`) never carry those as peer deps.
11
+ * - `@pilotiq/tiptap`'s `TiptapEditor` calls `getCollabExtensions()` at
12
+ * mount; if non-null AND a `useCollabRoom()` value is present, it calls
13
+ * the factory and spreads the returned array into the editor's
14
+ * `extensions` slot. If either is missing, plain Tiptap + History runs.
15
+ *
16
+ * `unknown[]` return type is deliberate — pilotiq core has zero `@tiptap/*`
17
+ * imports and treats the returned values as opaque editor-extension refs.
18
+ * The Tiptap host trusts them and spreads them in.
19
+ */
20
+ export interface CollabExtensionFactoryArgs {
21
+ /** `Y.Doc` for the surrounding record. Opaque to pilotiq core. */
22
+ ydoc: unknown
23
+ /** `WebsocketProvider` for the same room. Opaque to pilotiq core. */
24
+ provider: unknown
25
+ /**
26
+ * Field name — becomes the `Y.XmlFragment` selector
27
+ * (`Collaboration.configure({ field: fieldName })`) so multiple
28
+ * collab editors on the same record write to distinct fragments
29
+ * inside one shared ydoc.
30
+ */
31
+ fieldName: string
32
+ /** Presence info forwarded to `CollaborationCursor`. Sparse. */
33
+ user?: {
34
+ name?: string
35
+ color?: string
36
+ }
37
+ }
38
+
39
+ export type CollabExtensionFactory = (args: CollabExtensionFactoryArgs) => unknown[]
40
+
41
+ let _factory: CollabExtensionFactory | null = null
42
+
43
+ /**
44
+ * Register the factory that builds collab extensions for one field +
45
+ * room. Called once at boot by `@pilotiq-pro/collab`'s plugin. No-op when
46
+ * no plugin registers — Tiptap renderers fall back to plain editing.
47
+ */
48
+ export function registerCollabExtensions(factory: CollabExtensionFactory): void {
49
+ _factory = factory
50
+ }
51
+
52
+ /** Returns the registered factory, or `null`. */
53
+ export function getCollabExtensions(): CollabExtensionFactory | null {
54
+ return _factory
55
+ }
@@ -0,0 +1,42 @@
1
+ import { createContext, useContext } from 'react'
2
+
3
+ /**
4
+ * Per-record realtime-collab room — a Y.Doc plus its WebsocketProvider,
5
+ * shared across every collaborative field in the same form. Mirrors the
6
+ * Tiptap "Collaborative Fields" pattern: one ydoc per record, each editor
7
+ * scopes itself to its own `Y.XmlFragment` via the field's `name`.
8
+ *
9
+ * Pilotiq core does NOT instantiate the room — implementation lives in
10
+ * `@pilotiq-pro/collab`, which mounts the context with real Yjs values
11
+ * via `<RecordCollabRoom>`. Core just owns the shape so any field
12
+ * renderer (Tiptap, in-house, third-party) can subscribe through one
13
+ * open-core seam without taking a hard peer dep on Yjs.
14
+ *
15
+ * `ydoc` and `provider` are typed `unknown` deliberately — the consumer
16
+ * (typically `@pilotiq/tiptap`) hands them straight to a registered
17
+ * `CollabExtensionFactory` and never touches them directly, so pilotiq
18
+ * core stays Yjs-free.
19
+ */
20
+ export interface CollabRoom {
21
+ /** `Y.Doc` instance. Opaque to pilotiq core. */
22
+ ydoc: unknown
23
+ /** `WebsocketProvider` instance. Opaque to pilotiq core. */
24
+ provider: unknown
25
+ /** Presence info for cursors / avatars. Forwarded to the extension factory. */
26
+ user?: {
27
+ name?: string
28
+ color?: string
29
+ }
30
+ }
31
+
32
+ /**
33
+ * `null` default — fields read the context, and a null result means
34
+ * "no collab room mounted, fall back to local-only editing." This is
35
+ * the 99% case (collab plugin not installed).
36
+ */
37
+ export const CollabRoomContext = createContext<CollabRoom | null>(null)
38
+
39
+ /** Read the active collab room for the surrounding record, or `null`. */
40
+ export function useCollabRoom(): CollabRoom | null {
41
+ return useContext(CollabRoomContext)
42
+ }
@@ -0,0 +1,72 @@
1
+ import type { CollabRoom } from './CollabRoomContext.js'
2
+
3
+ /**
4
+ * Binding contract that a collab plugin returns from
5
+ * `registerFormCollabBinding` — wraps a single form's value map in a
6
+ * shared CRDT type (typically a `Y.Map` on the surrounding record's
7
+ * `Y.Doc`) so every field on the form syncs across clients.
8
+ *
9
+ * Pilotiq's `FormStateProvider` calls into this contract when a
10
+ * `<RecordCollabRoom>` is mounted up-tree:
11
+ *
12
+ * - `get()` is read once on mount to overlay any already-synced
13
+ * state on top of the form's SSR-rendered defaults.
14
+ * - `set(name, v)` is called from `setValue` after the local React
15
+ * state update — every controlled field's edit lands in the CRDT.
16
+ * - `subscribe(fn)` registers a listener that fires when REMOTE
17
+ * changes land; `fn(snapshot)` receives the full updated map.
18
+ * The provider re-applies this snapshot onto its React state.
19
+ * - `destroy()` is called on unmount — gives the plugin a chance to
20
+ * remove its CRDT observer.
21
+ *
22
+ * `unknown` payloads keep pilotiq core Yjs-free; the binding owns its
23
+ * own type knowledge. Same posture as `CollabExtensionFactory`.
24
+ */
25
+ export interface FormCollabBinding {
26
+ /** Snapshot of the current synced values. Called once on mount. */
27
+ get(): Record<string, unknown>
28
+ /** Write the local edit to the CRDT. Triggers a broadcast to peers. */
29
+ set(name: string, value: unknown): void
30
+ /** Subscribe to remote changes. Returns an unsubscribe function. */
31
+ subscribe(fn: (snapshot: Record<string, unknown>) => void): () => void
32
+ /** Cleanup hook called when the form unmounts. */
33
+ destroy(): void
34
+ }
35
+
36
+ export interface FormCollabBindingFactoryArgs {
37
+ /** Active collab room — provides `ydoc`, `provider`, `user`. Opaque to pilotiq core. */
38
+ room: CollabRoom
39
+ /**
40
+ * Form identifier — used by the binding to partition CRDT state when
41
+ * multiple forms render against the same room (e.g. a record page that
42
+ * shows a primary form plus a side-mounted action form). Most pages
43
+ * only have one form, so most bindings use this as the `Y.Map` name.
44
+ */
45
+ formId: string
46
+ /**
47
+ * Initial values from pilotiq's normal SSR resolution. The binding
48
+ * uses these to perform the idempotent "first-load seed" (`!ymap.has(k)`
49
+ * gated write) so the first client to open a record populates the
50
+ * Y.Map with the DB-derived defaults; subsequent clients find the
51
+ * map already populated and skip.
52
+ */
53
+ initial: Record<string, unknown>
54
+ }
55
+
56
+ export type FormCollabBindingFactory = (args: FormCollabBindingFactoryArgs) => FormCollabBinding
57
+
58
+ let _factory: FormCollabBindingFactory | null = null
59
+
60
+ /**
61
+ * Register the form-level CRDT binding factory. Called once at boot by
62
+ * `@pilotiq-pro/collab`'s plugin. No-op when no plugin registers —
63
+ * `FormStateProvider` falls back to its plain local-state path.
64
+ */
65
+ export function registerFormCollabBinding(factory: FormCollabBindingFactory): void {
66
+ _factory = factory
67
+ }
68
+
69
+ /** Returns the registered binding factory, or `null`. */
70
+ export function getFormCollabBinding(): FormCollabBindingFactory | null {
71
+ return _factory
72
+ }
@@ -17,6 +17,8 @@ import {
17
17
  } from './formStateHelpers.js'
18
18
  import { runJsHandler } from './fieldJsHandler.js'
19
19
  import { useToast } from './Toaster.js'
20
+ import { useCollabRoom } from './CollabRoomContext.js'
21
+ import { getFormCollabBinding, type FormCollabBinding } from './FormCollabBindingRegistry.js'
20
22
 
21
23
  export type FieldStatus = 'idle' | 'pending'
22
24
 
@@ -58,6 +60,19 @@ export function useFormState(): FormStateApi | null {
58
60
  */
59
61
  export const FormIdContext = createContext<string>('')
60
62
 
63
+ /**
64
+ * Phase F2 — returns `true` iff the named field has explicitly opted out
65
+ * of realtime collab via `Field.collab(false)`. Sparse meta — absent =
66
+ * inherit the panel default (collab on). Walks the form meta tree the
67
+ * same way `findFieldMeta` does; cheap because it only runs on the
68
+ * per-write path (already a hot path, but every check is one map
69
+ * lookup + one boolean compare).
70
+ */
71
+ function fieldOptsOutOfCollab(formMeta: ElementMeta, name: string): boolean {
72
+ const meta = findFieldMeta(formMeta, name) as { collab?: boolean } | undefined
73
+ return meta?.collab === false
74
+ }
75
+
61
76
  export interface UseFieldStateResult {
62
77
  /** True when the field is inside a controlled form (live fields enabled).
63
78
  * Renderers should fall back to their `defaultValue` path when false.
@@ -184,6 +199,62 @@ export function FormStateProvider({
184
199
  useEffect(() => { formMetaRef.current = formMeta }, [formMeta])
185
200
 
186
201
  const stateUrl = (formMeta as { stateUrl?: string })['stateUrl']
202
+ const formId = (formMeta as { formId?: string })['formId'] ?? ''
203
+
204
+ // Phase F2 — collab binding. When `<RecordCollabRoom>` is mounted up-tree
205
+ // AND `@pilotiq-pro/collab` registered a `FormCollabBinding` factory, we
206
+ // construct a binding for this form, lift any already-synced state on
207
+ // top of the SSR-rendered defaults, and proxy every local write through
208
+ // it. Remote writes flow back via `subscribe`. Outside a room (or with
209
+ // no factory registered), `bindingRef` stays null and the plain
210
+ // local-state path runs unchanged.
211
+ const collabRoom = useCollabRoom()
212
+ const bindingFactory = getFormCollabBinding()
213
+ const bindingRef = useRef<FormCollabBinding | null>(null)
214
+
215
+ useEffect(() => {
216
+ if (!collabRoom || !bindingFactory || !formId) return
217
+
218
+ const binding = bindingFactory({ room: collabRoom, formId, initial: valuesRef.current })
219
+ bindingRef.current = binding
220
+
221
+ // Lift any state already in the room (subsequent joiners — first
222
+ // mover sees an empty snapshot here and the local SSR defaults
223
+ // stay authoritative). Shallow merge so fields the binding doesn't
224
+ // know about (defaults the seed skipped, dotted-path Repeater rows
225
+ // we don't sync in F2) survive.
226
+ const synced = binding.get()
227
+ if (Object.keys(synced).length > 0) {
228
+ setValuesState((prev) => ({ ...prev, ...synced }))
229
+ }
230
+
231
+ // Subscribe to remote changes. Local writes ALSO trigger this
232
+ // (Yjs observers fire on local transactions too) — the per-key
233
+ // Object.is short-circuit below collapses them into no-op renders.
234
+ const unsubscribe = binding.subscribe((snapshot) => {
235
+ setValuesState((prev) => {
236
+ let changed = false
237
+ const next: Record<string, unknown> = { ...prev }
238
+ for (const [k, v] of Object.entries(snapshot)) {
239
+ if (!Object.is(prev[k], v)) {
240
+ next[k] = v
241
+ changed = true
242
+ }
243
+ }
244
+ return changed ? next : prev
245
+ })
246
+ })
247
+
248
+ return () => {
249
+ unsubscribe()
250
+ binding.destroy()
251
+ bindingRef.current = null
252
+ }
253
+ // `valuesRef.current` is intentionally read once at mount — initial
254
+ // values seed the binding; subsequent edits flow through `setValue`
255
+ // and remote changes flow through `subscribe`.
256
+ // eslint-disable-next-line react-hooks/exhaustive-deps
257
+ }, [collabRoom, bindingFactory, formId])
187
258
 
188
259
  /**
189
260
  * Tier-2 follow-up to Plan #5 — fire `Field.afterStateUpdatedJs(body)`
@@ -238,6 +309,14 @@ export function FormStateProvider({
238
309
  if (Object.is(prev[name], value)) return prev
239
310
  return { ...prev, [name]: value }
240
311
  })
312
+ // Phase F2 — proxy the write through the collab binding when active
313
+ // AND the field hasn't opted out via `.collab(false)`. Dotted-path
314
+ // names (Repeater / Builder row leaves) stay local-only in v1; their
315
+ // syncing belongs to Phase F.5 (`Y.Array<Y.Map>` row identity).
316
+ const binding = bindingRef.current
317
+ if (binding && !name.includes('.') && !fieldOptsOutOfCollab(formMetaRef.current, name)) {
318
+ binding.set(name, value)
319
+ }
241
320
  // Fire the client-side JS hook synchronously after the state write.
242
321
  // Dotted-name fields don't go through here (their setter is a no-op
243
322
  // in `useFieldState`); they fire JS via `triggerLive` instead so we
@@ -311,6 +390,18 @@ export function FormStateProvider({
311
390
  const serverValues = (data.form as { values?: Record<string, unknown> }).values
312
391
  if (serverValues) {
313
392
  setValuesState((prev) => ({ ...prev, ...serverValues }))
393
+ // Phase F2 (Q2) — derived fields propagate to peers via the
394
+ // collab binding so every client sees the auto-`slug` / etc.
395
+ // without each peer roundtripping the server. Skip dotted-path
396
+ // names + fields that opted out.
397
+ const binding = bindingRef.current
398
+ if (binding) {
399
+ for (const [k, v] of Object.entries(serverValues)) {
400
+ if (k.includes('.')) continue
401
+ if (fieldOptsOutOfCollab(data.form, k)) continue
402
+ binding.set(k, v)
403
+ }
404
+ }
314
405
  }
315
406
  setErrors({})
316
407
  }
@@ -0,0 +1,40 @@
1
+ import { type ReactNode } from 'react'
2
+ import { getRecordWrapper } from './RecordWrapperRegistry.js'
3
+ import { parseRecordEditUrl } from './parseRecordEditUrl.js'
4
+
5
+ export interface RecordWrapperGateProps {
6
+ currentPath?: string
7
+ basePath: string
8
+ children: ReactNode
9
+ }
10
+
11
+ /**
12
+ * Conditionally wraps the page tree with the plugin-registered
13
+ * `RecordWrapper` when the current URL resolves to a record-bound edit
14
+ * page. Pass-through in every other case:
15
+ *
16
+ * - no plugin registered a wrapper (`getRecordWrapper() === null`)
17
+ * - the URL isn't a record-edit URL (list / create / view / dashboard / …)
18
+ * - `currentPath` not yet known on the very first SSR render
19
+ *
20
+ * Mounted once inside `AppShell` around the page content area so
21
+ * record-scoped plugins (collab room, audit trail, …) get one
22
+ * lifetimed mount per record-view-or-edit without each plugin having
23
+ * to thread URL parsing into its own provider.
24
+ *
25
+ * Scope limited to `/edit` URLs in v1; view-page support (read-only
26
+ * collab cursors on `ViewPage`) is a follow-up.
27
+ */
28
+ export function RecordWrapperGate({ currentPath, basePath, children }: RecordWrapperGateProps) {
29
+ const Wrapper = getRecordWrapper()
30
+ if (!Wrapper || !currentPath) return <>{children}</>
31
+
32
+ const identity = parseRecordEditUrl(currentPath, basePath)
33
+ if (!identity) return <>{children}</>
34
+
35
+ return (
36
+ <Wrapper resourceSlug={identity.resourceSlug} recordId={identity.recordId}>
37
+ {children}
38
+ </Wrapper>
39
+ )
40
+ }
@@ -0,0 +1,39 @@
1
+ import type { ComponentType, ReactNode } from 'react'
2
+
3
+ /**
4
+ * Props the page-record wrapper receives from `RecordWrapperGate` when
5
+ * the current URL resolves to a record-bound edit page (`${base}/.../:id/edit`).
6
+ *
7
+ * The wrapper is responsible for whatever record-scoped context the
8
+ * plugin owns — `@pilotiq-pro/collab` mounts a `<RecordCollabRoom>`
9
+ * here so every collab field inside the page shares one Y.Doc + WS
10
+ * connection. Other plugins could mount per-record presence, audit
11
+ * logging, or anything else that's record-bound rather than panel-bound.
12
+ *
13
+ * `resourceSlug` is the slash-joined slug-path (cluster-prefixed for
14
+ * clustered resources, parent-prefixed for nested-relation edits) so
15
+ * two URLs that target different records always produce distinct
16
+ * wrapper keys / room names.
17
+ */
18
+ export interface RecordWrapperProps {
19
+ resourceSlug: string
20
+ recordId: string
21
+ children: ReactNode
22
+ }
23
+
24
+ let _component: ComponentType<RecordWrapperProps> | null = null
25
+
26
+ /**
27
+ * Register a component that wraps the page tree on every record-edit
28
+ * route. Called once at boot by a plugin (e.g. `@pilotiq-pro/collab`).
29
+ * No-op when no plugin registers — `RecordWrapperGate` passes through
30
+ * unchanged.
31
+ */
32
+ export function registerRecordWrapper(C: ComponentType<RecordWrapperProps>): void {
33
+ _component = C
34
+ }
35
+
36
+ /** Returns the registered wrapper component, or `null`. */
37
+ export function getRecordWrapper(): ComponentType<RecordWrapperProps> | null {
38
+ return _component
39
+ }