@pilotiq/pilotiq 0.23.1 → 0.24.2

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 (500) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/boost/guidelines.md +566 -0
  3. package/boost/skills/pilotiq-fields/SKILL.md +47 -0
  4. package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
  5. package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
  6. package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
  7. package/boost/skills/pilotiq-relations/SKILL.md +47 -0
  8. package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
  9. package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
  10. package/boost/skills/pilotiq-resource/SKILL.md +61 -0
  11. package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
  12. package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
  13. package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
  14. package/dist/actions/exportFactory.d.ts +10 -0
  15. package/dist/actions/exportFactory.d.ts.map +1 -1
  16. package/dist/actions/exportFactory.js +10 -0
  17. package/dist/actions/exportFactory.js.map +1 -1
  18. package/dist/react/CollabRoomContext.d.ts +5 -5
  19. package/dist/react/index.d.ts +0 -1
  20. package/dist/react/index.d.ts.map +1 -1
  21. package/dist/react/index.js +0 -1
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/routes/helpers.d.ts.map +1 -1
  24. package/dist/routes/helpers.js +6 -2
  25. package/dist/routes/helpers.js.map +1 -1
  26. package/dist/routes/relations.d.ts.map +1 -1
  27. package/dist/routes/relations.js +12 -0
  28. package/dist/routes/relations.js.map +1 -1
  29. package/package.json +6 -1
  30. package/.turbo/turbo-build.log +0 -8
  31. package/CLAUDE.md +0 -265
  32. package/dist/react/useCollabSeed.d.ts +0 -23
  33. package/dist/react/useCollabSeed.d.ts.map +0 -1
  34. package/dist/react/useCollabSeed.js +0 -82
  35. package/dist/react/useCollabSeed.js.map +0 -1
  36. package/src/Cluster.test.ts +0 -283
  37. package/src/Cluster.ts +0 -83
  38. package/src/Column.test.ts +0 -199
  39. package/src/Column.ts +0 -710
  40. package/src/Global.test.ts +0 -367
  41. package/src/Global.ts +0 -169
  42. package/src/Page.test.ts +0 -114
  43. package/src/Page.ts +0 -208
  44. package/src/Pilotiq.perf.test.ts +0 -252
  45. package/src/Pilotiq.test.ts +0 -129
  46. package/src/Pilotiq.ts +0 -1158
  47. package/src/PilotiqRegistry.ts +0 -36
  48. package/src/PilotiqServiceProvider.ts +0 -121
  49. package/src/RelationManager.test.ts +0 -400
  50. package/src/RelationManager.ts +0 -527
  51. package/src/RenderHook.test.ts +0 -252
  52. package/src/RenderHook.ts +0 -242
  53. package/src/Resource.test.ts +0 -284
  54. package/src/Resource.ts +0 -526
  55. package/src/RightPanel.test.ts +0 -202
  56. package/src/RightPanel.ts +0 -132
  57. package/src/Tab.test.ts +0 -91
  58. package/src/Tab.ts +0 -156
  59. package/src/UserMenuItem.ts +0 -145
  60. package/src/actions/Action.test.ts +0 -2526
  61. package/src/actions/Action.ts +0 -1515
  62. package/src/actions/ActionGroup.test.ts +0 -112
  63. package/src/actions/ActionGroup.ts +0 -173
  64. package/src/actions/attachFactory.ts +0 -172
  65. package/src/actions/bulkFactories.ts +0 -168
  66. package/src/actions/crudFactories.ts +0 -220
  67. package/src/actions/exportFactory.ts +0 -215
  68. package/src/actions/factoryHelpers.ts +0 -177
  69. package/src/actions/importFactory.ts +0 -243
  70. package/src/actions/index.ts +0 -17
  71. package/src/actions/m2mFactories.ts +0 -193
  72. package/src/actions/relationFactories.ts +0 -372
  73. package/src/applyPageHooks.test.ts +0 -463
  74. package/src/applyPageHooks.ts +0 -330
  75. package/src/authorization.test.ts +0 -483
  76. package/src/breadcrumbs.test.ts +0 -238
  77. package/src/cells/coerce.test.ts +0 -85
  78. package/src/cells/coerce.ts +0 -84
  79. package/src/clusterPaths.ts +0 -35
  80. package/src/columns/BadgeColumn.test.ts +0 -54
  81. package/src/columns/BadgeColumn.ts +0 -32
  82. package/src/columns/BooleanColumn.test.ts +0 -41
  83. package/src/columns/BooleanColumn.ts +0 -18
  84. package/src/columns/ColorColumn.test.ts +0 -37
  85. package/src/columns/ColorColumn.ts +0 -38
  86. package/src/columns/IconColumn.test.ts +0 -54
  87. package/src/columns/IconColumn.ts +0 -37
  88. package/src/columns/ImageColumn.test.ts +0 -41
  89. package/src/columns/ImageColumn.ts +0 -28
  90. package/src/columns/SelectColumn.ts +0 -98
  91. package/src/columns/TextColumn.test.ts +0 -190
  92. package/src/columns/TextColumn.ts +0 -20
  93. package/src/columns/TextInputColumn.ts +0 -68
  94. package/src/columns/ToggleColumn.ts +0 -46
  95. package/src/columns/editableColumns.test.ts +0 -238
  96. package/src/columns/index.ts +0 -9
  97. package/src/defaultGlobalPages.ts +0 -95
  98. package/src/defaultPages.test.ts +0 -634
  99. package/src/defaultPages.ts +0 -617
  100. package/src/defaultViewPage.test.ts +0 -147
  101. package/src/elements/Form.test.ts +0 -223
  102. package/src/elements/Form.ts +0 -416
  103. package/src/elements/ListTabs.ts +0 -28
  104. package/src/elements/Table.test.ts +0 -422
  105. package/src/elements/Table.ts +0 -850
  106. package/src/elements/TableGroup.test.ts +0 -260
  107. package/src/elements/TableGroup.ts +0 -334
  108. package/src/elements/dispatchAction.test.ts +0 -463
  109. package/src/elements/dispatchAction.ts +0 -355
  110. package/src/elements/dispatchForm.test.ts +0 -477
  111. package/src/elements/dispatchForm.ts +0 -1993
  112. package/src/elements/dispatchTable.test.ts +0 -1514
  113. package/src/elements/dispatchTable.ts +0 -745
  114. package/src/elements/index.ts +0 -21
  115. package/src/entries/BadgeEntry.ts +0 -39
  116. package/src/entries/CodeEntry.test.ts +0 -40
  117. package/src/entries/CodeEntry.ts +0 -52
  118. package/src/entries/ColorEntry.ts +0 -63
  119. package/src/entries/ComponentEntry.test.ts +0 -173
  120. package/src/entries/ComponentEntry.ts +0 -95
  121. package/src/entries/Entry.ts +0 -304
  122. package/src/entries/IconEntry.ts +0 -49
  123. package/src/entries/ImageEntry.ts +0 -61
  124. package/src/entries/KeyValueEntry.ts +0 -47
  125. package/src/entries/RepeatableEntry.test.ts +0 -239
  126. package/src/entries/RepeatableEntry.ts +0 -173
  127. package/src/entries/TextEntry.test.ts +0 -394
  128. package/src/entries/TextEntry.ts +0 -60
  129. package/src/entries/index.ts +0 -12
  130. package/src/entries/leaves.test.ts +0 -306
  131. package/src/entries/registry.ts +0 -54
  132. package/src/fields/BuilderField.test.ts +0 -1188
  133. package/src/fields/BuilderField.ts +0 -605
  134. package/src/fields/BuilderRelationship.test.ts +0 -811
  135. package/src/fields/CheckboxField.test.ts +0 -44
  136. package/src/fields/CheckboxField.ts +0 -27
  137. package/src/fields/CheckboxListField.test.ts +0 -99
  138. package/src/fields/CheckboxListField.ts +0 -66
  139. package/src/fields/ColorPickerField.test.ts +0 -33
  140. package/src/fields/ColorPickerField.ts +0 -25
  141. package/src/fields/DateField.ts +0 -54
  142. package/src/fields/DateTimeField.test.ts +0 -55
  143. package/src/fields/EmailField.ts +0 -16
  144. package/src/fields/Field.test.ts +0 -654
  145. package/src/fields/Field.ts +0 -817
  146. package/src/fields/FileUploadField.test.ts +0 -143
  147. package/src/fields/FileUploadField.ts +0 -159
  148. package/src/fields/HiddenField.test.ts +0 -27
  149. package/src/fields/HiddenField.ts +0 -28
  150. package/src/fields/KeyValueField.test.ts +0 -105
  151. package/src/fields/KeyValueField.ts +0 -55
  152. package/src/fields/MarkdownField.test.ts +0 -167
  153. package/src/fields/MarkdownField.ts +0 -162
  154. package/src/fields/NumberField.ts +0 -33
  155. package/src/fields/RadioField.test.ts +0 -94
  156. package/src/fields/RadioField.ts +0 -67
  157. package/src/fields/RepeaterField.test.ts +0 -1806
  158. package/src/fields/RepeaterField.ts +0 -939
  159. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  160. package/src/fields/RepeaterSimple.test.ts +0 -248
  161. package/src/fields/RowButton.test.ts +0 -219
  162. package/src/fields/RowButton.ts +0 -135
  163. package/src/fields/SelectField.test.ts +0 -192
  164. package/src/fields/SelectField.ts +0 -235
  165. package/src/fields/SliderField.test.ts +0 -50
  166. package/src/fields/SliderField.ts +0 -53
  167. package/src/fields/SlugField.ts +0 -24
  168. package/src/fields/TagsInputField.test.ts +0 -154
  169. package/src/fields/TagsInputField.ts +0 -133
  170. package/src/fields/TextField.test.ts +0 -213
  171. package/src/fields/TextField.ts +0 -177
  172. package/src/fields/TextareaField.test.ts +0 -58
  173. package/src/fields/TextareaField.ts +0 -59
  174. package/src/fields/ToggleButtonsField.test.ts +0 -106
  175. package/src/fields/ToggleButtonsField.ts +0 -59
  176. package/src/fields/ToggleField.ts +0 -16
  177. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  178. package/src/fields/optionsResolver.ts +0 -95
  179. package/src/fields/resolveField.ts +0 -28
  180. package/src/filters/BooleanFilter.ts +0 -35
  181. package/src/filters/DateRangeFilter.test.ts +0 -194
  182. package/src/filters/DateRangeFilter.ts +0 -148
  183. package/src/filters/Filter.test.ts +0 -268
  184. package/src/filters/Filter.ts +0 -184
  185. package/src/filters/FormFilter.test.ts +0 -238
  186. package/src/filters/FormFilter.ts +0 -215
  187. package/src/filters/MultiSelectFilter.test.ts +0 -119
  188. package/src/filters/MultiSelectFilter.ts +0 -78
  189. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  190. package/src/filters/QueryBuilderFilter.ts +0 -398
  191. package/src/filters/SelectFilter.ts +0 -46
  192. package/src/filters/TernaryFilter.test.ts +0 -160
  193. package/src/filters/TernaryFilter.ts +0 -72
  194. package/src/filters/TrashedFilter.test.ts +0 -149
  195. package/src/filters/TrashedFilter.ts +0 -55
  196. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  197. package/src/filters/queryBuilder/Constraint.ts +0 -115
  198. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  199. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  200. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  201. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  202. package/src/filters/queryBuilder/index.ts +0 -12
  203. package/src/icons/index.ts +0 -2
  204. package/src/icons/lucide.ts +0 -204
  205. package/src/icons/registry.test.ts +0 -56
  206. package/src/icons/registry.ts +0 -41
  207. package/src/icons/types.ts +0 -47
  208. package/src/index.ts +0 -525
  209. package/src/io/csv.test.ts +0 -142
  210. package/src/io/csv.ts +0 -170
  211. package/src/nestedRelationManagerData.test.ts +0 -547
  212. package/src/notifications/Notification.test.ts +0 -210
  213. package/src/notifications/Notification.ts +0 -354
  214. package/src/notifications/broadcast.test.ts +0 -110
  215. package/src/notifications/broadcast.ts +0 -95
  216. package/src/notifications/database.test.ts +0 -383
  217. package/src/notifications/database.ts +0 -398
  218. package/src/notifications/databaseNotifications.test.ts +0 -187
  219. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  220. package/src/notifications/dispatchNotificationAction.ts +0 -142
  221. package/src/notifications/flash.test.ts +0 -89
  222. package/src/notifications/flash.ts +0 -71
  223. package/src/notifications/index.ts +0 -45
  224. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  225. package/src/notifications/registerBroadcastAuth.ts +0 -100
  226. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  227. package/src/notifications/resolveSavedNotification.ts +0 -59
  228. package/src/notifications/types.ts +0 -93
  229. package/src/orm/m2mAccessor.ts +0 -66
  230. package/src/orm/modelDefaults.test.ts +0 -633
  231. package/src/orm/modelDefaults.ts +0 -666
  232. package/src/pageData/breadcrumbs.ts +0 -288
  233. package/src/pageData/forms.ts +0 -578
  234. package/src/pageData/helpers.ts +0 -857
  235. package/src/pageData/misc.ts +0 -347
  236. package/src/pageData/navigation.ts +0 -842
  237. package/src/pageData/relationPages.ts +0 -1248
  238. package/src/pageData/relationTabs.ts +0 -286
  239. package/src/pageData/resourcePages.ts +0 -609
  240. package/src/pageData.test.ts +0 -1545
  241. package/src/pageData.ts +0 -341
  242. package/src/plugins/index.ts +0 -8
  243. package/src/plugins/themeEditor.test.ts +0 -36
  244. package/src/plugins/themeEditor.ts +0 -45
  245. package/src/react/AppShell.tsx +0 -251
  246. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  247. package/src/react/CollabRoomContext.ts +0 -98
  248. package/src/react/CollabTextRendererRegistry.ts +0 -102
  249. package/src/react/CommandPalette.tsx +0 -375
  250. package/src/react/CurrentUserContext.tsx +0 -50
  251. package/src/react/CustomPageWrapperGate.tsx +0 -69
  252. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  253. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  254. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  255. package/src/react/FieldPresenceRegistry.ts +0 -46
  256. package/src/react/FormCollabBindingRegistry.ts +0 -242
  257. package/src/react/FormStateContext.tsx +0 -591
  258. package/src/react/HeadHooks.tsx +0 -126
  259. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  260. package/src/react/MarkdownEditorRegistry.ts +0 -107
  261. package/src/react/NotificationActionStrip.tsx +0 -263
  262. package/src/react/NotificationBell.tsx +0 -426
  263. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  264. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  265. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  266. package/src/react/PendingSuggestionsContext.tsx +0 -172
  267. package/src/react/RecordWrapperGate.tsx +0 -58
  268. package/src/react/RecordWrapperRegistry.ts +0 -39
  269. package/src/react/RenderHookSlot.tsx +0 -32
  270. package/src/react/RightSidebar.tsx +0 -257
  271. package/src/react/RightSidebarContext.tsx +0 -234
  272. package/src/react/RightSidebarTrigger.tsx +0 -53
  273. package/src/react/RowCoordsContext.tsx +0 -23
  274. package/src/react/SchemaRenderer.tsx +0 -549
  275. package/src/react/SearchTrigger.tsx +0 -46
  276. package/src/react/ThemeProvider.tsx +0 -93
  277. package/src/react/ThemeSettingsPage.tsx +0 -579
  278. package/src/react/ThemeToggle.tsx +0 -20
  279. package/src/react/Toaster.tsx +0 -158
  280. package/src/react/UserMenu.tsx +0 -196
  281. package/src/react/WidgetDataContext.tsx +0 -157
  282. package/src/react/cells/EditableCell.tsx +0 -389
  283. package/src/react/component-slots.test.ts +0 -103
  284. package/src/react/component-slots.ts +0 -116
  285. package/src/react/fieldJsHandler.test.ts +0 -166
  286. package/src/react/fieldJsHandler.ts +0 -79
  287. package/src/react/fields/BuilderInput.tsx +0 -1078
  288. package/src/react/fields/CheckboxInput.tsx +0 -39
  289. package/src/react/fields/CheckboxListInput.tsx +0 -102
  290. package/src/react/fields/ColorInput.tsx +0 -71
  291. package/src/react/fields/DateFieldInput.tsx +0 -70
  292. package/src/react/fields/DateTimeInput.tsx +0 -62
  293. package/src/react/fields/FieldShell.tsx +0 -348
  294. package/src/react/fields/FileUploadInput.tsx +0 -639
  295. package/src/react/fields/HiddenInput.tsx +0 -17
  296. package/src/react/fields/KeyValueInput.tsx +0 -230
  297. package/src/react/fields/MarkdownInput.tsx +0 -560
  298. package/src/react/fields/RadioInput.tsx +0 -81
  299. package/src/react/fields/RepeaterInput.test.ts +0 -116
  300. package/src/react/fields/RepeaterInput.tsx +0 -1420
  301. package/src/react/fields/SelectFieldInput.tsx +0 -280
  302. package/src/react/fields/SliderInput.tsx +0 -81
  303. package/src/react/fields/TagsInput.tsx +0 -283
  304. package/src/react/fields/TextLikeInput.tsx +0 -256
  305. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  306. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  307. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  308. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  309. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  310. package/src/react/fields/repeaterReconcile.ts +0 -104
  311. package/src/react/fields/rowChromeButton.tsx +0 -336
  312. package/src/react/fields/rowState.ts +0 -106
  313. package/src/react/fields/syncRowGates.test.ts +0 -202
  314. package/src/react/fields/syncRowGates.ts +0 -66
  315. package/src/react/fields/textInputControls.tsx +0 -238
  316. package/src/react/fields/useRowReorderDnd.ts +0 -78
  317. package/src/react/formStateHelpers.test.ts +0 -508
  318. package/src/react/formStateHelpers.ts +0 -381
  319. package/src/react/hooks/use-mobile.ts +0 -19
  320. package/src/react/icon-context.tsx +0 -60
  321. package/src/react/index.ts +0 -195
  322. package/src/react/layouts/SidebarLayout.tsx +0 -250
  323. package/src/react/layouts/TopbarLayout.tsx +0 -258
  324. package/src/react/navigate.tsx +0 -37
  325. package/src/react/onProviderSynced.test.ts +0 -90
  326. package/src/react/parseRecordEditUrl.test.ts +0 -122
  327. package/src/react/parseRecordEditUrl.ts +0 -94
  328. package/src/react/persistedState.ts +0 -40
  329. package/src/react/registry.ts +0 -48
  330. package/src/react/right-panel-registry.tsx +0 -47
  331. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  332. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  333. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  334. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  335. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  336. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  337. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  338. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  339. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  340. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  341. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  342. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  343. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  344. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  345. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  346. package/src/react/schemaRenderer/constants.ts +0 -50
  347. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  348. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  349. package/src/react/schemaRenderer/helpers.tsx +0 -81
  350. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  351. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  352. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  353. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  354. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  355. package/src/react/schemaRenderer/table/links.tsx +0 -112
  356. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  357. package/src/react/schemaRenderer/table/url.tsx +0 -143
  358. package/src/react/theme-preview/apply.ts +0 -99
  359. package/src/react/theme-preview/build-html.ts +0 -436
  360. package/src/react/ui/button.tsx +0 -51
  361. package/src/react/ui/calendar.tsx +0 -67
  362. package/src/react/ui/checkbox.tsx +0 -29
  363. package/src/react/ui/dialog.tsx +0 -108
  364. package/src/react/ui/dropdown-menu.tsx +0 -97
  365. package/src/react/ui/input.tsx +0 -20
  366. package/src/react/ui/label.tsx +0 -21
  367. package/src/react/ui/popover.tsx +0 -50
  368. package/src/react/ui/select.tsx +0 -169
  369. package/src/react/ui/separator.tsx +0 -25
  370. package/src/react/ui/sheet.tsx +0 -136
  371. package/src/react/ui/sidebar.tsx +0 -723
  372. package/src/react/ui/skeleton.tsx +0 -13
  373. package/src/react/ui/slider.tsx +0 -34
  374. package/src/react/ui/switch.tsx +0 -28
  375. package/src/react/ui/table.tsx +0 -105
  376. package/src/react/ui/tabs.tsx +0 -63
  377. package/src/react/ui/textarea.tsx +0 -18
  378. package/src/react/ui/tooltip.tsx +0 -64
  379. package/src/react/useCollabSeed.ts +0 -86
  380. package/src/react/useResizableWidth.ts +0 -139
  381. package/src/react/utils.ts +0 -6
  382. package/src/react/widgetRegistry.test.ts +0 -43
  383. package/src/react/widgetRegistry.ts +0 -50
  384. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  385. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  386. package/src/react/widgets/ViewRenderer.tsx +0 -71
  387. package/src/relationManagerData.test.ts +0 -1595
  388. package/src/richtext/index.ts +0 -8
  389. package/src/richtext/registry.ts +0 -89
  390. package/src/routes/globals.ts +0 -148
  391. package/src/routes/guard.test.ts +0 -325
  392. package/src/routes/helpers.ts +0 -700
  393. package/src/routes/pages.ts +0 -175
  394. package/src/routes/panel.ts +0 -204
  395. package/src/routes/relations.ts +0 -1227
  396. package/src/routes/resources.ts +0 -781
  397. package/src/routes/theme.ts +0 -91
  398. package/src/routes-nested-relations.test.ts +0 -676
  399. package/src/routes-relations.test.ts +0 -972
  400. package/src/routes.test.ts +0 -2027
  401. package/src/routes.ts +0 -303
  402. package/src/schema/Alert.test.ts +0 -109
  403. package/src/schema/Alert.ts +0 -131
  404. package/src/schema/Block.ts +0 -169
  405. package/src/schema/Breadcrumbs.ts +0 -40
  406. package/src/schema/Card.ts +0 -35
  407. package/src/schema/Divider.ts +0 -20
  408. package/src/schema/Element.ts +0 -219
  409. package/src/schema/EmptyState.test.ts +0 -37
  410. package/src/schema/EmptyState.ts +0 -63
  411. package/src/schema/Fieldset.ts +0 -43
  412. package/src/schema/Grid.ts +0 -43
  413. package/src/schema/Group.ts +0 -30
  414. package/src/schema/Heading.ts +0 -39
  415. package/src/schema/Html.ts +0 -67
  416. package/src/schema/Icon.ts +0 -54
  417. package/src/schema/Image.ts +0 -57
  418. package/src/schema/LinkTag.ts +0 -41
  419. package/src/schema/Markdown.ts +0 -85
  420. package/src/schema/MetaTag.ts +0 -41
  421. package/src/schema/RelationTabs.ts +0 -71
  422. package/src/schema/ScriptTag.ts +0 -55
  423. package/src/schema/Section.ts +0 -160
  424. package/src/schema/ServerDataElement.test.ts +0 -140
  425. package/src/schema/ServerDataElement.ts +0 -156
  426. package/src/schema/SlotComponent.test.ts +0 -77
  427. package/src/schema/SlotComponent.ts +0 -71
  428. package/src/schema/Split.ts +0 -50
  429. package/src/schema/Stat.test.ts +0 -118
  430. package/src/schema/Stat.ts +0 -154
  431. package/src/schema/StatsOverview.test.ts +0 -141
  432. package/src/schema/StatsOverview.ts +0 -119
  433. package/src/schema/StyleTag.ts +0 -35
  434. package/src/schema/TableWidget.test.ts +0 -297
  435. package/src/schema/TableWidget.ts +0 -289
  436. package/src/schema/Tabs.ts +0 -79
  437. package/src/schema/Text.ts +0 -58
  438. package/src/schema/UnorderedList.ts +0 -49
  439. package/src/schema/View.test.ts +0 -111
  440. package/src/schema/View.ts +0 -127
  441. package/src/schema/Wizard.ts +0 -220
  442. package/src/schema/containers.test.ts +0 -564
  443. package/src/schema/headTags.test.ts +0 -134
  444. package/src/schema/index.ts +0 -40
  445. package/src/schema/primes.test.ts +0 -269
  446. package/src/schema/resolveSchema.test.ts +0 -379
  447. package/src/schema/resolveSchema.ts +0 -917
  448. package/src/schema/sanitize.ts +0 -58
  449. package/src/search.test.ts +0 -446
  450. package/src/search.ts +0 -178
  451. package/src/sessionFilters.test.ts +0 -375
  452. package/src/sessionFilters.ts +0 -143
  453. package/src/slot-components/index.ts +0 -10
  454. package/src/slot-components/registry.ts +0 -56
  455. package/src/styles/file-upload.css +0 -13
  456. package/src/summarizers/Summarizer.test.ts +0 -84
  457. package/src/summarizers/Summarizer.ts +0 -123
  458. package/src/summarizers/index.ts +0 -11
  459. package/src/theme/base-colors.ts +0 -68
  460. package/src/theme/chart-colors.ts +0 -50
  461. package/src/theme/colors.ts +0 -447
  462. package/src/theme/generate-css.test.ts +0 -139
  463. package/src/theme/generate-css.ts +0 -44
  464. package/src/theme/generate-scale.test.ts +0 -106
  465. package/src/theme/generate-scale.ts +0 -97
  466. package/src/theme/icon-map.ts +0 -42
  467. package/src/theme/index.ts +0 -34
  468. package/src/theme/migrate.test.ts +0 -178
  469. package/src/theme/migrate.ts +0 -81
  470. package/src/theme/presets.ts +0 -135
  471. package/src/theme/radius.ts +0 -18
  472. package/src/theme/resolve.test.ts +0 -238
  473. package/src/theme/resolve.ts +0 -96
  474. package/src/theme/spacing.ts +0 -18
  475. package/src/theme/storage.test.ts +0 -126
  476. package/src/theme/storage.ts +0 -106
  477. package/src/theme/theme-colors.ts +0 -88
  478. package/src/theme/types.ts +0 -125
  479. package/src/uploads/UploadAdapter.ts +0 -35
  480. package/src/uploads/index.ts +0 -2
  481. package/src/uploads/localUpload.test.ts +0 -70
  482. package/src/uploads/localUpload.ts +0 -84
  483. package/src/validation/Validator.ts +0 -49
  484. package/src/validation/index.ts +0 -28
  485. package/src/validation/rules.ts +0 -78
  486. package/src/validation/runValidators.ts +0 -435
  487. package/src/validation/uniqueValidator.test.ts +0 -196
  488. package/src/validation/uniqueValidator.ts +0 -133
  489. package/src/validation/validators.test.ts +0 -268
  490. package/src/vite.test.ts +0 -184
  491. package/src/vite.ts +0 -787
  492. package/src/widgets/index.ts +0 -10
  493. package/src/widgets/registry.ts +0 -45
  494. package/src/widgets.test.ts +0 -592
  495. package/tsconfig.build.json +0 -11
  496. package/tsconfig.json +0 -4
  497. package/tsconfig.test.json +0 -10
  498. package/views/react/Dashboard.tsx +0 -27
  499. package/views/react/Resources/Form.tsx +0 -102
  500. 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 `CollabRoomManager` (which is
28
- * what `@pilotiq-pro/collab@>=0.2`'s `<RecordCollabRoom>` does);
29
- * absent for legacy / hand-rolled providers. `useCollabSeed` gates
30
- * its seed callback on this Promise — adapters that need a
31
- * "fragment-empty?" check after first sync should consume the hook
32
- * rather than calling `onProviderSynced` themselves.
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
- }