@pilotiq/pilotiq 0.24.1 → 0.24.3

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 (518) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/boost/guidelines.md +571 -0
  3. package/boost/skills/pilotiq-actions/SKILL.md +49 -0
  4. package/boost/skills/pilotiq-actions/rules/dispatch-modes.md +177 -0
  5. package/boost/skills/pilotiq-actions/rules/factories.md +130 -0
  6. package/boost/skills/pilotiq-actions/rules/visibility-and-authorization.md +125 -0
  7. package/boost/skills/pilotiq-fields/SKILL.md +47 -0
  8. package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
  9. package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
  10. package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
  11. package/boost/skills/pilotiq-relations/SKILL.md +47 -0
  12. package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
  13. package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
  14. package/boost/skills/pilotiq-resource/SKILL.md +61 -0
  15. package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
  16. package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
  17. package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
  18. package/dist/Pilotiq.d.ts +31 -0
  19. package/dist/Pilotiq.d.ts.map +1 -1
  20. package/dist/Pilotiq.js +3 -1
  21. package/dist/Pilotiq.js.map +1 -1
  22. package/dist/PilotiqRegistry.d.ts +13 -0
  23. package/dist/PilotiqRegistry.d.ts.map +1 -1
  24. package/dist/PilotiqRegistry.js +15 -0
  25. package/dist/PilotiqRegistry.js.map +1 -1
  26. package/dist/pageData/misc.d.ts.map +1 -1
  27. package/dist/pageData/misc.js +6 -0
  28. package/dist/pageData/misc.js.map +1 -1
  29. package/dist/pageData/navigation.d.ts +1 -0
  30. package/dist/pageData/navigation.d.ts.map +1 -1
  31. package/dist/pageData/navigation.js +3 -0
  32. package/dist/pageData/navigation.js.map +1 -1
  33. package/dist/pageData/relationPages.d.ts.map +1 -1
  34. package/dist/pageData/relationPages.js +3 -0
  35. package/dist/pageData/relationPages.js.map +1 -1
  36. package/dist/pageData/resourcePages.d.ts.map +1 -1
  37. package/dist/pageData/resourcePages.js +8 -0
  38. package/dist/pageData/resourcePages.js.map +1 -1
  39. package/dist/react/AppShell.d.ts +8 -0
  40. package/dist/react/AppShell.d.ts.map +1 -1
  41. package/dist/react/AppShell.js.map +1 -1
  42. package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
  43. package/dist/react/layouts/SidebarLayout.js +10 -2
  44. package/dist/react/layouts/SidebarLayout.js.map +1 -1
  45. package/dist/react/widgets/StatsOverviewRenderer.d.ts.map +1 -1
  46. package/dist/react/widgets/StatsOverviewRenderer.js +32 -18
  47. package/dist/react/widgets/StatsOverviewRenderer.js.map +1 -1
  48. package/dist/routes/relations.d.ts.map +1 -1
  49. package/dist/routes/relations.js +25 -18
  50. package/dist/routes/relations.js.map +1 -1
  51. package/dist/routes/resources.js.map +1 -1
  52. package/package.json +10 -5
  53. package/.turbo/turbo-build.log +0 -8
  54. package/CLAUDE.md +0 -265
  55. package/src/Cluster.test.ts +0 -283
  56. package/src/Cluster.ts +0 -83
  57. package/src/Column.test.ts +0 -199
  58. package/src/Column.ts +0 -710
  59. package/src/Global.test.ts +0 -367
  60. package/src/Global.ts +0 -169
  61. package/src/Page.test.ts +0 -114
  62. package/src/Page.ts +0 -208
  63. package/src/Pilotiq.perf.test.ts +0 -252
  64. package/src/Pilotiq.test.ts +0 -129
  65. package/src/Pilotiq.ts +0 -1158
  66. package/src/PilotiqRegistry.ts +0 -36
  67. package/src/PilotiqServiceProvider.ts +0 -121
  68. package/src/RelationManager.test.ts +0 -400
  69. package/src/RelationManager.ts +0 -527
  70. package/src/RenderHook.test.ts +0 -252
  71. package/src/RenderHook.ts +0 -242
  72. package/src/Resource.test.ts +0 -284
  73. package/src/Resource.ts +0 -526
  74. package/src/RightPanel.test.ts +0 -202
  75. package/src/RightPanel.ts +0 -132
  76. package/src/Tab.test.ts +0 -91
  77. package/src/Tab.ts +0 -156
  78. package/src/UserMenuItem.ts +0 -145
  79. package/src/actions/Action.test.ts +0 -2526
  80. package/src/actions/Action.ts +0 -1515
  81. package/src/actions/ActionGroup.test.ts +0 -112
  82. package/src/actions/ActionGroup.ts +0 -173
  83. package/src/actions/attachFactory.ts +0 -172
  84. package/src/actions/bulkFactories.ts +0 -168
  85. package/src/actions/crudFactories.ts +0 -220
  86. package/src/actions/exportFactory.ts +0 -225
  87. package/src/actions/factoryHelpers.ts +0 -177
  88. package/src/actions/importFactory.ts +0 -243
  89. package/src/actions/index.ts +0 -17
  90. package/src/actions/m2mFactories.ts +0 -193
  91. package/src/actions/relationFactories.ts +0 -372
  92. package/src/applyPageHooks.test.ts +0 -463
  93. package/src/applyPageHooks.ts +0 -330
  94. package/src/authorization.test.ts +0 -483
  95. package/src/breadcrumbs.test.ts +0 -238
  96. package/src/cells/coerce.test.ts +0 -85
  97. package/src/cells/coerce.ts +0 -84
  98. package/src/clusterPaths.ts +0 -35
  99. package/src/columns/BadgeColumn.test.ts +0 -54
  100. package/src/columns/BadgeColumn.ts +0 -32
  101. package/src/columns/BooleanColumn.test.ts +0 -41
  102. package/src/columns/BooleanColumn.ts +0 -18
  103. package/src/columns/ColorColumn.test.ts +0 -37
  104. package/src/columns/ColorColumn.ts +0 -38
  105. package/src/columns/IconColumn.test.ts +0 -54
  106. package/src/columns/IconColumn.ts +0 -37
  107. package/src/columns/ImageColumn.test.ts +0 -41
  108. package/src/columns/ImageColumn.ts +0 -28
  109. package/src/columns/SelectColumn.ts +0 -98
  110. package/src/columns/TextColumn.test.ts +0 -190
  111. package/src/columns/TextColumn.ts +0 -20
  112. package/src/columns/TextInputColumn.ts +0 -68
  113. package/src/columns/ToggleColumn.ts +0 -46
  114. package/src/columns/editableColumns.test.ts +0 -238
  115. package/src/columns/index.ts +0 -9
  116. package/src/defaultGlobalPages.ts +0 -95
  117. package/src/defaultPages.test.ts +0 -634
  118. package/src/defaultPages.ts +0 -617
  119. package/src/defaultViewPage.test.ts +0 -147
  120. package/src/elements/Form.test.ts +0 -223
  121. package/src/elements/Form.ts +0 -416
  122. package/src/elements/ListTabs.ts +0 -28
  123. package/src/elements/Table.test.ts +0 -422
  124. package/src/elements/Table.ts +0 -850
  125. package/src/elements/TableGroup.test.ts +0 -260
  126. package/src/elements/TableGroup.ts +0 -334
  127. package/src/elements/dispatchAction.test.ts +0 -463
  128. package/src/elements/dispatchAction.ts +0 -355
  129. package/src/elements/dispatchForm.test.ts +0 -477
  130. package/src/elements/dispatchForm.ts +0 -1993
  131. package/src/elements/dispatchTable.test.ts +0 -1514
  132. package/src/elements/dispatchTable.ts +0 -745
  133. package/src/elements/index.ts +0 -21
  134. package/src/entries/BadgeEntry.ts +0 -39
  135. package/src/entries/CodeEntry.test.ts +0 -40
  136. package/src/entries/CodeEntry.ts +0 -52
  137. package/src/entries/ColorEntry.ts +0 -63
  138. package/src/entries/ComponentEntry.test.ts +0 -173
  139. package/src/entries/ComponentEntry.ts +0 -95
  140. package/src/entries/Entry.ts +0 -304
  141. package/src/entries/IconEntry.ts +0 -49
  142. package/src/entries/ImageEntry.ts +0 -61
  143. package/src/entries/KeyValueEntry.ts +0 -47
  144. package/src/entries/RepeatableEntry.test.ts +0 -239
  145. package/src/entries/RepeatableEntry.ts +0 -173
  146. package/src/entries/TextEntry.test.ts +0 -394
  147. package/src/entries/TextEntry.ts +0 -60
  148. package/src/entries/index.ts +0 -12
  149. package/src/entries/leaves.test.ts +0 -306
  150. package/src/entries/registry.ts +0 -54
  151. package/src/fields/BuilderField.test.ts +0 -1188
  152. package/src/fields/BuilderField.ts +0 -605
  153. package/src/fields/BuilderRelationship.test.ts +0 -811
  154. package/src/fields/CheckboxField.test.ts +0 -44
  155. package/src/fields/CheckboxField.ts +0 -27
  156. package/src/fields/CheckboxListField.test.ts +0 -99
  157. package/src/fields/CheckboxListField.ts +0 -66
  158. package/src/fields/ColorPickerField.test.ts +0 -33
  159. package/src/fields/ColorPickerField.ts +0 -25
  160. package/src/fields/DateField.ts +0 -54
  161. package/src/fields/DateTimeField.test.ts +0 -55
  162. package/src/fields/EmailField.ts +0 -16
  163. package/src/fields/Field.test.ts +0 -654
  164. package/src/fields/Field.ts +0 -817
  165. package/src/fields/FileUploadField.test.ts +0 -143
  166. package/src/fields/FileUploadField.ts +0 -159
  167. package/src/fields/HiddenField.test.ts +0 -27
  168. package/src/fields/HiddenField.ts +0 -28
  169. package/src/fields/KeyValueField.test.ts +0 -105
  170. package/src/fields/KeyValueField.ts +0 -55
  171. package/src/fields/MarkdownField.test.ts +0 -167
  172. package/src/fields/MarkdownField.ts +0 -162
  173. package/src/fields/NumberField.ts +0 -33
  174. package/src/fields/RadioField.test.ts +0 -94
  175. package/src/fields/RadioField.ts +0 -67
  176. package/src/fields/RepeaterField.test.ts +0 -1806
  177. package/src/fields/RepeaterField.ts +0 -939
  178. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  179. package/src/fields/RepeaterSimple.test.ts +0 -248
  180. package/src/fields/RowButton.test.ts +0 -219
  181. package/src/fields/RowButton.ts +0 -135
  182. package/src/fields/SelectField.test.ts +0 -192
  183. package/src/fields/SelectField.ts +0 -235
  184. package/src/fields/SliderField.test.ts +0 -50
  185. package/src/fields/SliderField.ts +0 -53
  186. package/src/fields/SlugField.ts +0 -24
  187. package/src/fields/TagsInputField.test.ts +0 -154
  188. package/src/fields/TagsInputField.ts +0 -133
  189. package/src/fields/TextField.test.ts +0 -213
  190. package/src/fields/TextField.ts +0 -177
  191. package/src/fields/TextareaField.test.ts +0 -58
  192. package/src/fields/TextareaField.ts +0 -59
  193. package/src/fields/ToggleButtonsField.test.ts +0 -106
  194. package/src/fields/ToggleButtonsField.ts +0 -59
  195. package/src/fields/ToggleField.ts +0 -16
  196. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  197. package/src/fields/optionsResolver.ts +0 -95
  198. package/src/fields/resolveField.ts +0 -28
  199. package/src/filters/BooleanFilter.ts +0 -35
  200. package/src/filters/DateRangeFilter.test.ts +0 -194
  201. package/src/filters/DateRangeFilter.ts +0 -148
  202. package/src/filters/Filter.test.ts +0 -268
  203. package/src/filters/Filter.ts +0 -184
  204. package/src/filters/FormFilter.test.ts +0 -238
  205. package/src/filters/FormFilter.ts +0 -215
  206. package/src/filters/MultiSelectFilter.test.ts +0 -119
  207. package/src/filters/MultiSelectFilter.ts +0 -78
  208. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  209. package/src/filters/QueryBuilderFilter.ts +0 -398
  210. package/src/filters/SelectFilter.ts +0 -46
  211. package/src/filters/TernaryFilter.test.ts +0 -160
  212. package/src/filters/TernaryFilter.ts +0 -72
  213. package/src/filters/TrashedFilter.test.ts +0 -149
  214. package/src/filters/TrashedFilter.ts +0 -55
  215. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  216. package/src/filters/queryBuilder/Constraint.ts +0 -115
  217. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  218. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  219. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  220. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  221. package/src/filters/queryBuilder/index.ts +0 -12
  222. package/src/icons/index.ts +0 -2
  223. package/src/icons/lucide.ts +0 -204
  224. package/src/icons/registry.test.ts +0 -56
  225. package/src/icons/registry.ts +0 -41
  226. package/src/icons/types.ts +0 -47
  227. package/src/index.ts +0 -525
  228. package/src/io/csv.test.ts +0 -142
  229. package/src/io/csv.ts +0 -170
  230. package/src/nestedRelationManagerData.test.ts +0 -547
  231. package/src/notifications/Notification.test.ts +0 -210
  232. package/src/notifications/Notification.ts +0 -354
  233. package/src/notifications/broadcast.test.ts +0 -110
  234. package/src/notifications/broadcast.ts +0 -95
  235. package/src/notifications/database.test.ts +0 -383
  236. package/src/notifications/database.ts +0 -398
  237. package/src/notifications/databaseNotifications.test.ts +0 -187
  238. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  239. package/src/notifications/dispatchNotificationAction.ts +0 -142
  240. package/src/notifications/flash.test.ts +0 -89
  241. package/src/notifications/flash.ts +0 -71
  242. package/src/notifications/index.ts +0 -45
  243. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  244. package/src/notifications/registerBroadcastAuth.ts +0 -100
  245. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  246. package/src/notifications/resolveSavedNotification.ts +0 -59
  247. package/src/notifications/types.ts +0 -93
  248. package/src/orm/m2mAccessor.ts +0 -66
  249. package/src/orm/modelDefaults.test.ts +0 -633
  250. package/src/orm/modelDefaults.ts +0 -666
  251. package/src/pageData/breadcrumbs.ts +0 -288
  252. package/src/pageData/forms.ts +0 -578
  253. package/src/pageData/helpers.ts +0 -857
  254. package/src/pageData/misc.ts +0 -347
  255. package/src/pageData/navigation.ts +0 -842
  256. package/src/pageData/relationPages.ts +0 -1248
  257. package/src/pageData/relationTabs.ts +0 -286
  258. package/src/pageData/resourcePages.ts +0 -609
  259. package/src/pageData.test.ts +0 -1545
  260. package/src/pageData.ts +0 -341
  261. package/src/plugins/index.ts +0 -8
  262. package/src/plugins/themeEditor.test.ts +0 -36
  263. package/src/plugins/themeEditor.ts +0 -45
  264. package/src/react/AppShell.tsx +0 -251
  265. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  266. package/src/react/CollabRoomContext.ts +0 -98
  267. package/src/react/CollabTextRendererRegistry.ts +0 -102
  268. package/src/react/CommandPalette.tsx +0 -375
  269. package/src/react/CurrentUserContext.tsx +0 -50
  270. package/src/react/CustomPageWrapperGate.tsx +0 -69
  271. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  272. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  273. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  274. package/src/react/FieldPresenceRegistry.ts +0 -46
  275. package/src/react/FormCollabBindingRegistry.ts +0 -242
  276. package/src/react/FormStateContext.tsx +0 -591
  277. package/src/react/HeadHooks.tsx +0 -126
  278. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  279. package/src/react/MarkdownEditorRegistry.ts +0 -107
  280. package/src/react/NotificationActionStrip.tsx +0 -263
  281. package/src/react/NotificationBell.tsx +0 -426
  282. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  283. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  284. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  285. package/src/react/PendingSuggestionsContext.tsx +0 -172
  286. package/src/react/RecordWrapperGate.tsx +0 -58
  287. package/src/react/RecordWrapperRegistry.ts +0 -39
  288. package/src/react/RenderHookSlot.tsx +0 -32
  289. package/src/react/RightSidebar.tsx +0 -257
  290. package/src/react/RightSidebarContext.tsx +0 -234
  291. package/src/react/RightSidebarTrigger.tsx +0 -53
  292. package/src/react/RowCoordsContext.tsx +0 -23
  293. package/src/react/SchemaRenderer.tsx +0 -549
  294. package/src/react/SearchTrigger.tsx +0 -46
  295. package/src/react/ThemeProvider.tsx +0 -93
  296. package/src/react/ThemeSettingsPage.tsx +0 -579
  297. package/src/react/ThemeToggle.tsx +0 -20
  298. package/src/react/Toaster.tsx +0 -158
  299. package/src/react/UserMenu.tsx +0 -196
  300. package/src/react/WidgetDataContext.tsx +0 -157
  301. package/src/react/cells/EditableCell.tsx +0 -389
  302. package/src/react/component-slots.test.ts +0 -103
  303. package/src/react/component-slots.ts +0 -116
  304. package/src/react/fieldJsHandler.test.ts +0 -166
  305. package/src/react/fieldJsHandler.ts +0 -79
  306. package/src/react/fields/BuilderInput.tsx +0 -1078
  307. package/src/react/fields/CheckboxInput.tsx +0 -39
  308. package/src/react/fields/CheckboxListInput.tsx +0 -102
  309. package/src/react/fields/ColorInput.tsx +0 -71
  310. package/src/react/fields/DateFieldInput.tsx +0 -70
  311. package/src/react/fields/DateTimeInput.tsx +0 -62
  312. package/src/react/fields/FieldShell.tsx +0 -348
  313. package/src/react/fields/FileUploadInput.tsx +0 -639
  314. package/src/react/fields/HiddenInput.tsx +0 -17
  315. package/src/react/fields/KeyValueInput.tsx +0 -230
  316. package/src/react/fields/MarkdownInput.tsx +0 -560
  317. package/src/react/fields/RadioInput.tsx +0 -81
  318. package/src/react/fields/RepeaterInput.test.ts +0 -116
  319. package/src/react/fields/RepeaterInput.tsx +0 -1420
  320. package/src/react/fields/SelectFieldInput.tsx +0 -280
  321. package/src/react/fields/SliderInput.tsx +0 -81
  322. package/src/react/fields/TagsInput.tsx +0 -283
  323. package/src/react/fields/TextLikeInput.tsx +0 -256
  324. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  325. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  326. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  327. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  328. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  329. package/src/react/fields/repeaterReconcile.ts +0 -104
  330. package/src/react/fields/rowChromeButton.tsx +0 -336
  331. package/src/react/fields/rowState.ts +0 -106
  332. package/src/react/fields/syncRowGates.test.ts +0 -202
  333. package/src/react/fields/syncRowGates.ts +0 -66
  334. package/src/react/fields/textInputControls.tsx +0 -238
  335. package/src/react/fields/useRowReorderDnd.ts +0 -78
  336. package/src/react/formStateHelpers.test.ts +0 -508
  337. package/src/react/formStateHelpers.ts +0 -381
  338. package/src/react/hooks/use-mobile.ts +0 -19
  339. package/src/react/icon-context.tsx +0 -60
  340. package/src/react/index.ts +0 -194
  341. package/src/react/layouts/SidebarLayout.tsx +0 -250
  342. package/src/react/layouts/TopbarLayout.tsx +0 -258
  343. package/src/react/navigate.tsx +0 -37
  344. package/src/react/onProviderSynced.test.ts +0 -90
  345. package/src/react/parseRecordEditUrl.test.ts +0 -122
  346. package/src/react/parseRecordEditUrl.ts +0 -94
  347. package/src/react/persistedState.ts +0 -40
  348. package/src/react/registry.ts +0 -48
  349. package/src/react/right-panel-registry.tsx +0 -47
  350. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  351. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  352. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  353. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  354. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  355. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  356. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  357. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  358. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  359. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  360. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  361. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  362. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  363. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  364. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  365. package/src/react/schemaRenderer/constants.ts +0 -50
  366. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  367. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  368. package/src/react/schemaRenderer/helpers.tsx +0 -81
  369. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  370. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  371. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  372. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  373. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  374. package/src/react/schemaRenderer/table/links.tsx +0 -112
  375. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  376. package/src/react/schemaRenderer/table/url.tsx +0 -143
  377. package/src/react/theme-preview/apply.ts +0 -99
  378. package/src/react/theme-preview/build-html.ts +0 -436
  379. package/src/react/ui/button.tsx +0 -51
  380. package/src/react/ui/calendar.tsx +0 -67
  381. package/src/react/ui/checkbox.tsx +0 -29
  382. package/src/react/ui/dialog.tsx +0 -108
  383. package/src/react/ui/dropdown-menu.tsx +0 -97
  384. package/src/react/ui/input.tsx +0 -20
  385. package/src/react/ui/label.tsx +0 -21
  386. package/src/react/ui/popover.tsx +0 -50
  387. package/src/react/ui/select.tsx +0 -169
  388. package/src/react/ui/separator.tsx +0 -25
  389. package/src/react/ui/sheet.tsx +0 -136
  390. package/src/react/ui/sidebar.tsx +0 -723
  391. package/src/react/ui/skeleton.tsx +0 -13
  392. package/src/react/ui/slider.tsx +0 -34
  393. package/src/react/ui/switch.tsx +0 -28
  394. package/src/react/ui/table.tsx +0 -105
  395. package/src/react/ui/tabs.tsx +0 -63
  396. package/src/react/ui/textarea.tsx +0 -18
  397. package/src/react/ui/tooltip.tsx +0 -64
  398. package/src/react/useResizableWidth.ts +0 -139
  399. package/src/react/utils.ts +0 -6
  400. package/src/react/widgetRegistry.test.ts +0 -43
  401. package/src/react/widgetRegistry.ts +0 -50
  402. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  403. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  404. package/src/react/widgets/ViewRenderer.tsx +0 -71
  405. package/src/relationManagerData.test.ts +0 -1595
  406. package/src/richtext/index.ts +0 -8
  407. package/src/richtext/registry.ts +0 -89
  408. package/src/routes/globals.ts +0 -148
  409. package/src/routes/guard.test.ts +0 -325
  410. package/src/routes/helpers.ts +0 -704
  411. package/src/routes/pages.ts +0 -175
  412. package/src/routes/panel.ts +0 -204
  413. package/src/routes/relations.ts +0 -1243
  414. package/src/routes/resources.ts +0 -781
  415. package/src/routes/theme.ts +0 -91
  416. package/src/routes-nested-relations.test.ts +0 -676
  417. package/src/routes-relations.test.ts +0 -972
  418. package/src/routes.test.ts +0 -2027
  419. package/src/routes.ts +0 -303
  420. package/src/schema/Alert.test.ts +0 -109
  421. package/src/schema/Alert.ts +0 -131
  422. package/src/schema/Block.ts +0 -169
  423. package/src/schema/Breadcrumbs.ts +0 -40
  424. package/src/schema/Card.ts +0 -35
  425. package/src/schema/Divider.ts +0 -20
  426. package/src/schema/Element.ts +0 -219
  427. package/src/schema/EmptyState.test.ts +0 -37
  428. package/src/schema/EmptyState.ts +0 -63
  429. package/src/schema/Fieldset.ts +0 -43
  430. package/src/schema/Grid.ts +0 -43
  431. package/src/schema/Group.ts +0 -30
  432. package/src/schema/Heading.ts +0 -39
  433. package/src/schema/Html.ts +0 -67
  434. package/src/schema/Icon.ts +0 -54
  435. package/src/schema/Image.ts +0 -57
  436. package/src/schema/LinkTag.ts +0 -41
  437. package/src/schema/Markdown.ts +0 -85
  438. package/src/schema/MetaTag.ts +0 -41
  439. package/src/schema/RelationTabs.ts +0 -71
  440. package/src/schema/ScriptTag.ts +0 -55
  441. package/src/schema/Section.ts +0 -160
  442. package/src/schema/ServerDataElement.test.ts +0 -140
  443. package/src/schema/ServerDataElement.ts +0 -156
  444. package/src/schema/SlotComponent.test.ts +0 -77
  445. package/src/schema/SlotComponent.ts +0 -71
  446. package/src/schema/Split.ts +0 -50
  447. package/src/schema/Stat.test.ts +0 -118
  448. package/src/schema/Stat.ts +0 -154
  449. package/src/schema/StatsOverview.test.ts +0 -141
  450. package/src/schema/StatsOverview.ts +0 -119
  451. package/src/schema/StyleTag.ts +0 -35
  452. package/src/schema/TableWidget.test.ts +0 -297
  453. package/src/schema/TableWidget.ts +0 -289
  454. package/src/schema/Tabs.ts +0 -79
  455. package/src/schema/Text.ts +0 -58
  456. package/src/schema/UnorderedList.ts +0 -49
  457. package/src/schema/View.test.ts +0 -111
  458. package/src/schema/View.ts +0 -127
  459. package/src/schema/Wizard.ts +0 -220
  460. package/src/schema/containers.test.ts +0 -564
  461. package/src/schema/headTags.test.ts +0 -134
  462. package/src/schema/index.ts +0 -40
  463. package/src/schema/primes.test.ts +0 -269
  464. package/src/schema/resolveSchema.test.ts +0 -379
  465. package/src/schema/resolveSchema.ts +0 -917
  466. package/src/schema/sanitize.ts +0 -58
  467. package/src/search.test.ts +0 -446
  468. package/src/search.ts +0 -178
  469. package/src/sessionFilters.test.ts +0 -375
  470. package/src/sessionFilters.ts +0 -143
  471. package/src/slot-components/index.ts +0 -10
  472. package/src/slot-components/registry.ts +0 -56
  473. package/src/styles/file-upload.css +0 -13
  474. package/src/summarizers/Summarizer.test.ts +0 -84
  475. package/src/summarizers/Summarizer.ts +0 -123
  476. package/src/summarizers/index.ts +0 -11
  477. package/src/theme/base-colors.ts +0 -68
  478. package/src/theme/chart-colors.ts +0 -50
  479. package/src/theme/colors.ts +0 -447
  480. package/src/theme/generate-css.test.ts +0 -139
  481. package/src/theme/generate-css.ts +0 -44
  482. package/src/theme/generate-scale.test.ts +0 -106
  483. package/src/theme/generate-scale.ts +0 -97
  484. package/src/theme/icon-map.ts +0 -42
  485. package/src/theme/index.ts +0 -34
  486. package/src/theme/migrate.test.ts +0 -178
  487. package/src/theme/migrate.ts +0 -81
  488. package/src/theme/presets.ts +0 -135
  489. package/src/theme/radius.ts +0 -18
  490. package/src/theme/resolve.test.ts +0 -238
  491. package/src/theme/resolve.ts +0 -96
  492. package/src/theme/spacing.ts +0 -18
  493. package/src/theme/storage.test.ts +0 -126
  494. package/src/theme/storage.ts +0 -106
  495. package/src/theme/theme-colors.ts +0 -88
  496. package/src/theme/types.ts +0 -125
  497. package/src/uploads/UploadAdapter.ts +0 -35
  498. package/src/uploads/index.ts +0 -2
  499. package/src/uploads/localUpload.test.ts +0 -70
  500. package/src/uploads/localUpload.ts +0 -84
  501. package/src/validation/Validator.ts +0 -49
  502. package/src/validation/index.ts +0 -28
  503. package/src/validation/rules.ts +0 -78
  504. package/src/validation/runValidators.ts +0 -435
  505. package/src/validation/uniqueValidator.test.ts +0 -196
  506. package/src/validation/uniqueValidator.ts +0 -133
  507. package/src/validation/validators.test.ts +0 -268
  508. package/src/vite.test.ts +0 -184
  509. package/src/vite.ts +0 -787
  510. package/src/widgets/index.ts +0 -10
  511. package/src/widgets/registry.ts +0 -45
  512. package/src/widgets.test.ts +0 -592
  513. package/tsconfig.build.json +0 -11
  514. package/tsconfig.json +0 -4
  515. package/tsconfig.test.json +0 -10
  516. package/views/react/Dashboard.tsx +0 -27
  517. package/views/react/Resources/Form.tsx +0 -102
  518. package/views/react/Resources/Index.tsx +0 -49
@@ -1,55 +0,0 @@
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
- }
@@ -1,98 +0,0 @@
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
- /**
26
- * Resolves on the provider's first sync. Present when the room is
27
- * wired through `@rudderjs/sync/react`'s `useCollabRoom` (which is
28
- * what `@pilotiq-pro/collab@>=0.2`'s `<RecordCollabRoom>` does);
29
- * absent for legacy / hand-rolled providers. Threaded into the
30
- * framework's `useCollabSeed` / `useCollabSeedText` (from
31
- * `@rudderjs/sync/react`) so adapters can gate seed callbacks on
32
- * first sync without calling `onProviderSynced` directly.
33
- */
34
- synced?: Promise<void>
35
- /** IndexedDB persistence handle, when the room wraps `y-indexeddb`. Opaque. */
36
- persistence?: unknown
37
- /** Presence info for cursors / avatars. Forwarded to the extension factory. */
38
- user?: {
39
- name?: string
40
- color?: string
41
- }
42
- }
43
-
44
- /**
45
- * `null` default — fields read the context, and a null result means
46
- * "no collab room mounted, fall back to local-only editing." This is
47
- * the 99% case (collab plugin not installed).
48
- */
49
- export const CollabRoomContext = createContext<CollabRoom | null>(null)
50
-
51
- /** Read the active collab room for the surrounding record, or `null`. */
52
- export function useCollabRoom(): CollabRoom | null {
53
- return useContext(CollabRoomContext)
54
- }
55
-
56
- /**
57
- * Minimal structural shape every collab provider exposes for the
58
- * "initial room state has streamed in" signal. Kept structural so callers
59
- * (`@pilotiq/tiptap`, `@pilotiq/codemirror`, future adapters) can pass
60
- * `provider as unknown as SyncedProviderLike` without taking a hard peer
61
- * dep on yjs / y-websocket / y-webrtc.
62
- */
63
- export interface SyncedProviderLike {
64
- synced?: boolean
65
- once?(event: 'synced', fn: () => void): void
66
- off?(event: 'synced', fn: () => void): void
67
- }
68
-
69
- const NOOP_CLEANUP = (): void => {}
70
-
71
- /**
72
- * Run `fn` once the collab provider's initial room state has streamed in.
73
- * If the provider is already synced, `fn` fires synchronously; otherwise
74
- * it's registered via `provider.once('synced', fn)`. The returned cleanup
75
- * unregisters the once handler safely (idempotent + try/catch) so callers
76
- * can wire it directly into a React effect's cleanup return.
77
- *
78
- * Useful for the brand-new-record seed pattern: editors mounting against
79
- * a freshly-created record want to push the SSR-rendered default into
80
- * the empty `Y.Text` / `Y.XmlFragment` exactly once after sync, before
81
- * the user types. Race caveat: two peers simultaneously mounting against
82
- * a brand-new record can both see `length === 0` and both seed —
83
- * accepted today across every adapter's seed path.
84
- */
85
- export function onProviderSynced(
86
- provider: SyncedProviderLike | null | undefined,
87
- fn: () => void,
88
- ): () => void {
89
- if (!provider) return NOOP_CLEANUP
90
- if (provider.synced) {
91
- fn()
92
- return NOOP_CLEANUP
93
- }
94
- provider.once?.('synced', fn)
95
- return () => {
96
- try { provider.off?.('synced', fn) } catch { /* ignore */ }
97
- }
98
- }
@@ -1,102 +0,0 @@
1
- import type { ComponentType } from 'react'
2
-
3
- /**
4
- * Module-level registry slot for the collab-aware plain-text editor renderer.
5
- *
6
- * Wiring posture (mirrors `CollabExtensionFactoryRegistry` /
7
- * `FormCollabBindingRegistry`):
8
- * - `@pilotiq/tiptap`'s `registerTiptap(...)` calls `registerCollabTextRenderer(...)`
9
- * once at boot. The registered component closes over `@tiptap/*` imports so
10
- * pilotiq core stays free of any tiptap peer dep — same posture as the
11
- * existing rich-text renderer registry.
12
- * - `TextLikeInput` checks for the registered component when a `<RecordCollabRoom>`
13
- * is mounted up-tree AND the field hasn't opted out via `.collab(false)` AND
14
- * the field has no `.mask()`. If present, the legacy `BoundTextInput`
15
- * (Y.Text + `computeDelta` + heuristic `preserveCursor`) is bypassed in
16
- * favour of a y-prosemirror-backed Tiptap editor that anchors selections to
17
- * `Yjs.RelativePosition` — the architectural fix for the cursor-jump and
18
- * two-peer concurrent-insert races documented in
19
- * `docs/plans/text-fields-tiptap-backed-collab.md`.
20
- *
21
- * Wire props are deliberately framework-agnostic — the renderer doesn't take a
22
- * `binding` since it consumes the room's `ydoc` directly via the existing
23
- * `useCollabRoom()` + `getCollabExtensions()` plumbing on its own side. Core
24
- * keeps the seam narrow: handler callbacks + DOM chrome only.
25
- */
26
- export interface CollabTextRendererProps {
27
- /**
28
- * Field name — drives the FormData hidden input AND the routing key
29
- * for AI suggestion delivery (chip widget, applier registry). For
30
- * Repeater / Builder row leaves this is the dotted positional path
31
- * (`items.0.title`).
32
- */
33
- name: string
34
- /**
35
- * Collab-stable identifier for the `Y.XmlFragment` selector. When
36
- * present, the renderer binds its collab fragment under this key
37
- * instead of `name`. Row leaves pass a row-id-anchored composite
38
- * (`items.<rowId>.title`) so the fragment survives reorders even
39
- * as the dotted positional `name` shifts. Top-level fields omit
40
- * it — `name` is stable on its own.
41
- *
42
- * AI suggestion routing continues to use `name` regardless. Tool
43
- * calls reference fields by their positional FormData name, not
44
- * the collab-stable composite.
45
- */
46
- fragmentKey?: string
47
- /** `true` for textarea-like (multiple paragraphs); `false` for input-like. */
48
- multiline: boolean
49
- /**
50
- * Server-rendered default value. The renderer is expected to seed the
51
- * `Y.XmlFragment` from this on first connect when the room has no
52
- * persisted state for this field (i.e. brand-new record).
53
- */
54
- defaultValue: string
55
- /** Optional placeholder hint. */
56
- placeholder?: string
57
- /** Disabled / read-only state. */
58
- disabled?: boolean
59
- /** Fired on every editor `update` with the editor's current plain text. */
60
- onChange: (text: string) => void
61
- /** Fired on editor blur — host wires this to live-onBlur trigger semantics. */
62
- onBlur: () => void
63
- /**
64
- * Single-line submit — fired when `multiline: false` AND the user presses
65
- * Enter. The renderer is expected to blur the editor after invoking this.
66
- * Multiline mode ignores it (Enter inserts a paragraph instead).
67
- */
68
- onSubmit?: () => void
69
- /**
70
- * Tailwind className applied to the editor's contenteditable wrapper so the
71
- * rendered editor matches the native `<input>` / `<textarea>` chrome it
72
- * replaces. The host owns the styling — the adapter just forwards.
73
- */
74
- className?: string
75
- /**
76
- * Additional DOM attributes for the editor's contenteditable wrapper —
77
- * typically `id`, `aria-*`, `autocomplete`, etc.
78
- */
79
- editorAttributes?: Record<string, string>
80
- }
81
-
82
- export type CollabTextRenderer = ComponentType<CollabTextRendererProps>
83
-
84
- let _renderer: CollabTextRenderer | null = null
85
-
86
- /**
87
- * Register the collab plain-text editor component. Called once at boot by
88
- * `@pilotiq/tiptap`'s `registerTiptap()` (or directly by an app that imports
89
- * the renderer). Calling with `null` clears the registry — useful for tests.
90
- *
91
- * No-op behaviour when no renderer is registered: `TextLikeInput` falls back
92
- * to the legacy `BoundTextInput` path (or the plain controlled / uncontrolled
93
- * input when no collab room is mounted).
94
- */
95
- export function registerCollabTextRenderer(component: CollabTextRenderer | null): void {
96
- _renderer = component
97
- }
98
-
99
- /** Returns the registered component, or `null` when no adapter is installed. */
100
- export function getCollabTextRenderer(): CollabTextRenderer | null {
101
- return _renderer
102
- }
@@ -1,375 +0,0 @@
1
- import * as React from 'react'
2
- import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
3
- import { SearchIcon, CornerDownLeftIcon, ArrowUpDownIcon } from 'lucide-react'
4
-
5
- import { Dialog, DialogContent } from './ui/dialog.js'
6
- import { useNavigate } from './navigate.js'
7
- import { useIconFor } from './icon-context.js'
8
- import { RenderHookSlot } from './RenderHookSlot.js'
9
- import type { GlobalSearchResult } from '../search.js'
10
- import type { NavItem } from '../pageData.js'
11
- import type { SerializedIcon } from '../icons/types.js'
12
- import type { RenderHookMap } from '../RenderHook.js'
13
-
14
- /**
15
- * Context exposing the palette's open setter. AppShell hosts the
16
- * provider; trigger pills (sidebar + topbar headers) call
17
- * `useCommandPaletteOpener()` to open the palette from anywhere in the
18
- * tree without prop-drilling.
19
- */
20
- const CommandPaletteContext = createContext<((open: boolean) => void) | null>(null)
21
-
22
- export function CommandPaletteProvider({
23
- children,
24
- setOpen,
25
- }: {
26
- children: React.ReactNode
27
- setOpen: (open: boolean) => void
28
- }): React.ReactElement {
29
- return (
30
- <CommandPaletteContext.Provider value={setOpen}>
31
- {children}
32
- </CommandPaletteContext.Provider>
33
- )
34
- }
35
-
36
- export function useCommandPaletteOpener(): (() => void) | null {
37
- const setOpen = useContext(CommandPaletteContext)
38
- return setOpen ? () => setOpen(true) : null
39
- }
40
-
41
- /**
42
- * Plan #12 — Cmd+K palette. Hand-rolled on the existing Dialog primitive
43
- * (no `cmdk` dep yet). Listens for Cmd/Ctrl+K globally; renders an input
44
- * + grouped result list; debounced fetch with in-flight cancellation
45
- * (same pattern as Plan #5 FormStateContext).
46
- *
47
- * Empty input shows the panel navigation entries — Cmd+K becomes a fast
48
- * resource picker. Typing replaces the list with search results grouped
49
- * by resource.
50
- */
51
-
52
- const DEBOUNCE_MS = 150
53
- const MIN_QUERY_LENGTH = 2
54
-
55
- interface SearchResponse {
56
- ok: boolean
57
- results: GlobalSearchResult[]
58
- renderHooks?: RenderHookMap
59
- error?: string
60
- }
61
-
62
- export interface CommandPaletteProps {
63
- basePath: string
64
- navigation?: NavItem[]
65
- /** Controlled open state. AppShell hosts; the palette + the trigger
66
- * pill share via context. */
67
- open: boolean
68
- onOpenChange: (open: boolean) => void
69
- /** Test seam — defaults to `globalThis.fetch`. */
70
- fetchImpl?: typeof fetch
71
- /** Test seam — defaults to `useNavigate()`. */
72
- navigateOverride?: (url: string) => void
73
- }
74
-
75
- interface PaletteEntry {
76
- /** `'result'` rows are search hits; `'nav'` rows are nav-entry shortcuts. */
77
- kind: 'result' | 'nav'
78
- /** Group header label (resource label for results, group name for nav). */
79
- group: string
80
- title: string
81
- subtitle?: string
82
- url: string
83
- icon?: SerializedIcon
84
- /** Stable key for keyboard nav. */
85
- key: string
86
- }
87
-
88
- export function CommandPalette({
89
- basePath,
90
- navigation,
91
- open,
92
- onOpenChange,
93
- fetchImpl,
94
- navigateOverride,
95
- }: CommandPaletteProps): React.ReactElement {
96
- const navigate = useNavigate()
97
- const go = navigateOverride ?? navigate
98
-
99
- const setOpen = onOpenChange
100
- const [query, setQuery] = useState('')
101
- const [results, setResults] = useState<GlobalSearchResult[]>([])
102
- const [renderHooks, setRenderHooks] = useState<RenderHookMap | undefined>(undefined)
103
- const [active, setActive] = useState(0)
104
- const [loading, setLoading] = useState(false)
105
-
106
- // ─── Cmd+K global listener ───────────────────────────
107
- useEffect(() => {
108
- function onKey(e: KeyboardEvent) {
109
- const isCmdK = (e.metaKey || e.ctrlKey) && (e.key === 'k' || e.key === 'K')
110
- if (!isCmdK) return
111
- e.preventDefault()
112
- setOpen(!open)
113
- }
114
- document.addEventListener('keydown', onKey)
115
- return () => document.removeEventListener('keydown', onKey)
116
- }, [open, setOpen])
117
-
118
- // Reset query + active row whenever the palette closes.
119
- useEffect(() => {
120
- if (!open) {
121
- setQuery('')
122
- setResults([])
123
- setRenderHooks(undefined)
124
- setActive(0)
125
- }
126
- }, [open])
127
-
128
- // ─── Fetch with debounce + in-flight seq ─────────────
129
- // Mirrors Plan #5 FormStateContext: refs (not state) for the seq
130
- // counters so React StrictMode dev double-invokes don't produce
131
- // stale closures.
132
- const requestSeqRef = useRef(0)
133
- const latestSeenRef = useRef(0)
134
- const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
135
-
136
- const runFetch = useCallback(async (q: string) => {
137
- if (q.trim().length < MIN_QUERY_LENGTH) {
138
- setResults([])
139
- setRenderHooks(undefined)
140
- setLoading(false)
141
- return
142
- }
143
- const seq = ++requestSeqRef.current
144
- const doFetch = fetchImpl ?? fetch
145
- setLoading(true)
146
- try {
147
- const url = `${basePath}/_search?q=${encodeURIComponent(q)}`
148
- const res = await doFetch(url, {
149
- method: 'GET',
150
- headers: { 'Accept': 'application/json' },
151
- })
152
- if (seq < latestSeenRef.current) return
153
- latestSeenRef.current = seq
154
- if (!res.ok) {
155
- setResults([])
156
- setRenderHooks(undefined)
157
- return
158
- }
159
- const data = await res.json().catch(() => null) as SearchResponse | null
160
- if (!data?.ok) {
161
- setResults([])
162
- setRenderHooks(undefined)
163
- return
164
- }
165
- setResults(data.results ?? [])
166
- setRenderHooks(data.renderHooks)
167
- setActive(0)
168
- } catch {
169
- setResults([])
170
- setRenderHooks(undefined)
171
- } finally {
172
- // Only flip loading off when this is the latest in-flight.
173
- if (seq === requestSeqRef.current) setLoading(false)
174
- }
175
- }, [basePath, fetchImpl])
176
-
177
- // Debounce on query change.
178
- useEffect(() => {
179
- if (debounceRef.current) clearTimeout(debounceRef.current)
180
- if (!open) return
181
- debounceRef.current = setTimeout(() => {
182
- void runFetch(query)
183
- }, DEBOUNCE_MS)
184
- return () => {
185
- if (debounceRef.current) clearTimeout(debounceRef.current)
186
- }
187
- }, [query, open, runFetch])
188
-
189
- // ─── Compose the entry list shown in the palette ─────
190
- const entries = useMemo<PaletteEntry[]>(() => {
191
- if (query.trim().length >= MIN_QUERY_LENGTH) {
192
- return results.map((r, i) => {
193
- const entry: PaletteEntry = {
194
- kind: 'result',
195
- group: r.resourceLabel,
196
- title: r.title,
197
- url: r.url,
198
- key: `${r.resource}:${r.id}:${i}`,
199
- }
200
- if (r.subtitle !== undefined) entry.subtitle = r.subtitle
201
- if (r.icon !== undefined) entry.icon = r.icon
202
- return entry
203
- })
204
- }
205
- // Empty-input state: flatten navigation tree.
206
- return flattenNavigation(navigation ?? [])
207
- }, [query, results, navigation])
208
-
209
- // ─── Keyboard navigation ─────────────────────────────
210
- const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
211
- if (e.key === 'ArrowDown') {
212
- e.preventDefault()
213
- setActive((i) => Math.min(i + 1, Math.max(0, entries.length - 1)))
214
- } else if (e.key === 'ArrowUp') {
215
- e.preventDefault()
216
- setActive((i) => Math.max(i - 1, 0))
217
- } else if (e.key === 'Enter') {
218
- e.preventDefault()
219
- const entry = entries[active]
220
- if (entry) {
221
- setOpen(false)
222
- // Defer the navigate so the close transition fires first.
223
- Promise.resolve().then(() => go(entry.url))
224
- }
225
- } else if (e.key === 'Escape') {
226
- setOpen(false)
227
- }
228
- }, [entries, active, go])
229
-
230
- // Hooks render only when the user is actively searching (>= MIN_QUERY_LENGTH);
231
- // empty-input nav state stays clean — chrome / nav slots cover that elsewhere.
232
- const showHooks = query.trim().length >= MIN_QUERY_LENGTH
233
-
234
- // ─── Group entries for rendering ─────────────────────
235
- const grouped = useMemo(() => {
236
- const map = new Map<string, PaletteEntry[]>()
237
- for (const e of entries) {
238
- const arr = map.get(e.group) ?? []
239
- arr.push(e)
240
- map.set(e.group, arr)
241
- }
242
- return [...map.entries()]
243
- }, [entries])
244
-
245
- return (
246
- <Dialog open={open} onOpenChange={setOpen}>
247
- <DialogContent className="max-w-xl p-0 gap-0 overflow-hidden">
248
- <div className="flex items-center gap-2 border-b border-border px-4 py-3">
249
- <SearchIcon className="size-4 text-muted-foreground" aria-hidden="true" />
250
- <input
251
- type="text"
252
- autoFocus
253
- placeholder="Search resources, records, or pages…"
254
- value={query}
255
- onChange={(e) => setQuery(e.target.value)}
256
- onKeyDown={onKeyDown}
257
- className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
258
- aria-label="Search"
259
- />
260
- {loading && <span className="text-xs text-muted-foreground">…</span>}
261
- <kbd className="text-[10px] font-mono text-muted-foreground border border-border rounded px-1 py-0.5">esc</kbd>
262
- </div>
263
-
264
- <div className="max-h-96 overflow-y-auto py-1">
265
- {showHooks && renderHooks?.['panels::global-search.results.before'] && (
266
- <div className="px-4 py-2">
267
- <RenderHookSlot name="panels::global-search.results.before" hooks={renderHooks} />
268
- </div>
269
- )}
270
- {entries.length === 0 && (
271
- <p className="px-4 py-6 text-center text-sm text-muted-foreground">
272
- {query.trim().length < MIN_QUERY_LENGTH
273
- ? 'Type to search…'
274
- : loading
275
- ? 'Searching…'
276
- : 'No results.'}
277
- </p>
278
- )}
279
- {grouped.map(([group, rows]) => (
280
- <div key={group}>
281
- <div className="px-4 pt-3 pb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
282
- {group}
283
- </div>
284
- <ul role="listbox">
285
- {rows.map((entry) => {
286
- const flatIdx = entries.indexOf(entry)
287
- const isActive = flatIdx === active
288
- return (
289
- <li key={entry.key}>
290
- <button
291
- type="button"
292
- role="option"
293
- aria-selected={isActive}
294
- onMouseEnter={() => setActive(flatIdx)}
295
- onClick={() => {
296
- setOpen(false)
297
- Promise.resolve().then(() => go(entry.url))
298
- }}
299
- className={[
300
- 'flex w-full items-center gap-3 px-4 py-2 text-left text-sm transition',
301
- isActive ? 'bg-accent text-accent-foreground' : 'hover:bg-muted',
302
- ].join(' ')}
303
- >
304
- <PaletteIcon icon={entry.icon} />
305
- <div className="min-w-0 flex-1">
306
- <div className="truncate font-medium">{entry.title}</div>
307
- {entry.subtitle && (
308
- <div className="truncate text-xs text-muted-foreground">{entry.subtitle}</div>
309
- )}
310
- </div>
311
- {isActive && (
312
- <CornerDownLeftIcon className="size-3 text-muted-foreground" aria-hidden="true" />
313
- )}
314
- </button>
315
- </li>
316
- )
317
- })}
318
- </ul>
319
- </div>
320
- ))}
321
- {showHooks && renderHooks?.['panels::global-search.results.after'] && (
322
- <div className="px-4 py-2">
323
- <RenderHookSlot name="panels::global-search.results.after" hooks={renderHooks} />
324
- </div>
325
- )}
326
- </div>
327
-
328
- <div className="flex items-center justify-between border-t border-border px-4 py-2 text-[10px] text-muted-foreground">
329
- <span className="flex items-center gap-1">
330
- <ArrowUpDownIcon className="size-3" aria-hidden="true" />
331
- navigate
332
- </span>
333
- <span className="flex items-center gap-1">
334
- <CornerDownLeftIcon className="size-3" aria-hidden="true" />
335
- open
336
- </span>
337
- </div>
338
- </DialogContent>
339
- </Dialog>
340
- )
341
- }
342
-
343
- function PaletteIcon({ icon }: { icon: SerializedIcon | undefined }) {
344
- const Icon = useIconFor(icon)
345
- if (!Icon) {
346
- return <span className="size-4 rounded bg-muted" aria-hidden="true" />
347
- }
348
- return <Icon className="size-4 text-muted-foreground" aria-hidden="true" />
349
- }
350
-
351
- /**
352
- * Flatten the navigation tree (nested children) into a single PaletteEntry
353
- * list. Used for the empty-input quick-nav state. Group label is the
354
- * NavItem's `group` (or `'Navigation'` when unset).
355
- */
356
- function flattenNavigation(items: NavItem[]): PaletteEntry[] {
357
- const out: PaletteEntry[] = []
358
- const walk = (nodes: NavItem[], inheritedGroup?: string) => {
359
- for (const n of nodes) {
360
- const group = n.group ?? inheritedGroup ?? 'Navigation'
361
- const entry: PaletteEntry = {
362
- kind: 'nav',
363
- group,
364
- title: n.label,
365
- url: n.url,
366
- key: `nav:${n.name}:${n.url}`,
367
- }
368
- if (n.icon !== undefined) entry.icon = n.icon
369
- out.push(entry)
370
- if (n.children && n.children.length > 0) walk(n.children, group)
371
- }
372
- }
373
- walk(items)
374
- return out
375
- }
@@ -1,50 +0,0 @@
1
- import { createContext, useContext, type ReactNode } from 'react'
2
-
3
- /**
4
- * Resolved identity of the user driving the current page. Mirrors the
5
- * `UserMenuMeta.user` shape that `panelInfo()` ships to the renderer —
6
- * whichever fields the `Pilotiq.user(req => …)` resolver populated.
7
- *
8
- * `null` is the no-user state: either the panel never wired a resolver,
9
- * or the resolver returned `null` for this request. Consumers should
10
- * gracefully fall back (no avatar, no presence label, etc.) rather than
11
- * treating absence as an error.
12
- */
13
- export interface CurrentUser {
14
- name?: string
15
- email?: string
16
- avatar?: string
17
- }
18
-
19
- const CurrentUserContext = createContext<CurrentUser | null>(null)
20
-
21
- /**
22
- * Mounted by `AppShell` around the layout-provider chain so plugins
23
- * (collab user presence, audit-trail attribution, analytics
24
- * client-side opt-outs, …) can read the active user via
25
- * `useCurrentUser()` without prop-drilling through `panel`.
26
- *
27
- * Value source is `viewProps.panel.userMenu?.user` — the same shape the
28
- * top-right dropdown renders. The provider sits OUTSIDE
29
- * `layoutProviderRegistry` so plugin-registered layout providers can
30
- * subscribe.
31
- */
32
- export function CurrentUserProvider({
33
- value,
34
- children,
35
- }: {
36
- value: CurrentUser | null
37
- children: ReactNode
38
- }): ReactNode {
39
- return <CurrentUserContext.Provider value={value}>{children}</CurrentUserContext.Provider>
40
- }
41
-
42
- /**
43
- * Read the active user inside any descendant of `<AppShell>`. Returns
44
- * `null` outside an `AppShell` mount (defensive — keeps storybook /
45
- * isolated-render tests from throwing) and when no user resolved for
46
- * the request.
47
- */
48
- export function useCurrentUser(): CurrentUser | null {
49
- return useContext(CurrentUserContext)
50
- }