@pilotiq/pilotiq 0.24.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 (480) hide show
  1. package/CHANGELOG.md +33 -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/package.json +6 -1
  15. package/.turbo/turbo-build.log +0 -8
  16. package/CLAUDE.md +0 -265
  17. package/src/Cluster.test.ts +0 -283
  18. package/src/Cluster.ts +0 -83
  19. package/src/Column.test.ts +0 -199
  20. package/src/Column.ts +0 -710
  21. package/src/Global.test.ts +0 -367
  22. package/src/Global.ts +0 -169
  23. package/src/Page.test.ts +0 -114
  24. package/src/Page.ts +0 -208
  25. package/src/Pilotiq.perf.test.ts +0 -252
  26. package/src/Pilotiq.test.ts +0 -129
  27. package/src/Pilotiq.ts +0 -1158
  28. package/src/PilotiqRegistry.ts +0 -36
  29. package/src/PilotiqServiceProvider.ts +0 -121
  30. package/src/RelationManager.test.ts +0 -400
  31. package/src/RelationManager.ts +0 -527
  32. package/src/RenderHook.test.ts +0 -252
  33. package/src/RenderHook.ts +0 -242
  34. package/src/Resource.test.ts +0 -284
  35. package/src/Resource.ts +0 -526
  36. package/src/RightPanel.test.ts +0 -202
  37. package/src/RightPanel.ts +0 -132
  38. package/src/Tab.test.ts +0 -91
  39. package/src/Tab.ts +0 -156
  40. package/src/UserMenuItem.ts +0 -145
  41. package/src/actions/Action.test.ts +0 -2526
  42. package/src/actions/Action.ts +0 -1515
  43. package/src/actions/ActionGroup.test.ts +0 -112
  44. package/src/actions/ActionGroup.ts +0 -173
  45. package/src/actions/attachFactory.ts +0 -172
  46. package/src/actions/bulkFactories.ts +0 -168
  47. package/src/actions/crudFactories.ts +0 -220
  48. package/src/actions/exportFactory.ts +0 -225
  49. package/src/actions/factoryHelpers.ts +0 -177
  50. package/src/actions/importFactory.ts +0 -243
  51. package/src/actions/index.ts +0 -17
  52. package/src/actions/m2mFactories.ts +0 -193
  53. package/src/actions/relationFactories.ts +0 -372
  54. package/src/applyPageHooks.test.ts +0 -463
  55. package/src/applyPageHooks.ts +0 -330
  56. package/src/authorization.test.ts +0 -483
  57. package/src/breadcrumbs.test.ts +0 -238
  58. package/src/cells/coerce.test.ts +0 -85
  59. package/src/cells/coerce.ts +0 -84
  60. package/src/clusterPaths.ts +0 -35
  61. package/src/columns/BadgeColumn.test.ts +0 -54
  62. package/src/columns/BadgeColumn.ts +0 -32
  63. package/src/columns/BooleanColumn.test.ts +0 -41
  64. package/src/columns/BooleanColumn.ts +0 -18
  65. package/src/columns/ColorColumn.test.ts +0 -37
  66. package/src/columns/ColorColumn.ts +0 -38
  67. package/src/columns/IconColumn.test.ts +0 -54
  68. package/src/columns/IconColumn.ts +0 -37
  69. package/src/columns/ImageColumn.test.ts +0 -41
  70. package/src/columns/ImageColumn.ts +0 -28
  71. package/src/columns/SelectColumn.ts +0 -98
  72. package/src/columns/TextColumn.test.ts +0 -190
  73. package/src/columns/TextColumn.ts +0 -20
  74. package/src/columns/TextInputColumn.ts +0 -68
  75. package/src/columns/ToggleColumn.ts +0 -46
  76. package/src/columns/editableColumns.test.ts +0 -238
  77. package/src/columns/index.ts +0 -9
  78. package/src/defaultGlobalPages.ts +0 -95
  79. package/src/defaultPages.test.ts +0 -634
  80. package/src/defaultPages.ts +0 -617
  81. package/src/defaultViewPage.test.ts +0 -147
  82. package/src/elements/Form.test.ts +0 -223
  83. package/src/elements/Form.ts +0 -416
  84. package/src/elements/ListTabs.ts +0 -28
  85. package/src/elements/Table.test.ts +0 -422
  86. package/src/elements/Table.ts +0 -850
  87. package/src/elements/TableGroup.test.ts +0 -260
  88. package/src/elements/TableGroup.ts +0 -334
  89. package/src/elements/dispatchAction.test.ts +0 -463
  90. package/src/elements/dispatchAction.ts +0 -355
  91. package/src/elements/dispatchForm.test.ts +0 -477
  92. package/src/elements/dispatchForm.ts +0 -1993
  93. package/src/elements/dispatchTable.test.ts +0 -1514
  94. package/src/elements/dispatchTable.ts +0 -745
  95. package/src/elements/index.ts +0 -21
  96. package/src/entries/BadgeEntry.ts +0 -39
  97. package/src/entries/CodeEntry.test.ts +0 -40
  98. package/src/entries/CodeEntry.ts +0 -52
  99. package/src/entries/ColorEntry.ts +0 -63
  100. package/src/entries/ComponentEntry.test.ts +0 -173
  101. package/src/entries/ComponentEntry.ts +0 -95
  102. package/src/entries/Entry.ts +0 -304
  103. package/src/entries/IconEntry.ts +0 -49
  104. package/src/entries/ImageEntry.ts +0 -61
  105. package/src/entries/KeyValueEntry.ts +0 -47
  106. package/src/entries/RepeatableEntry.test.ts +0 -239
  107. package/src/entries/RepeatableEntry.ts +0 -173
  108. package/src/entries/TextEntry.test.ts +0 -394
  109. package/src/entries/TextEntry.ts +0 -60
  110. package/src/entries/index.ts +0 -12
  111. package/src/entries/leaves.test.ts +0 -306
  112. package/src/entries/registry.ts +0 -54
  113. package/src/fields/BuilderField.test.ts +0 -1188
  114. package/src/fields/BuilderField.ts +0 -605
  115. package/src/fields/BuilderRelationship.test.ts +0 -811
  116. package/src/fields/CheckboxField.test.ts +0 -44
  117. package/src/fields/CheckboxField.ts +0 -27
  118. package/src/fields/CheckboxListField.test.ts +0 -99
  119. package/src/fields/CheckboxListField.ts +0 -66
  120. package/src/fields/ColorPickerField.test.ts +0 -33
  121. package/src/fields/ColorPickerField.ts +0 -25
  122. package/src/fields/DateField.ts +0 -54
  123. package/src/fields/DateTimeField.test.ts +0 -55
  124. package/src/fields/EmailField.ts +0 -16
  125. package/src/fields/Field.test.ts +0 -654
  126. package/src/fields/Field.ts +0 -817
  127. package/src/fields/FileUploadField.test.ts +0 -143
  128. package/src/fields/FileUploadField.ts +0 -159
  129. package/src/fields/HiddenField.test.ts +0 -27
  130. package/src/fields/HiddenField.ts +0 -28
  131. package/src/fields/KeyValueField.test.ts +0 -105
  132. package/src/fields/KeyValueField.ts +0 -55
  133. package/src/fields/MarkdownField.test.ts +0 -167
  134. package/src/fields/MarkdownField.ts +0 -162
  135. package/src/fields/NumberField.ts +0 -33
  136. package/src/fields/RadioField.test.ts +0 -94
  137. package/src/fields/RadioField.ts +0 -67
  138. package/src/fields/RepeaterField.test.ts +0 -1806
  139. package/src/fields/RepeaterField.ts +0 -939
  140. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  141. package/src/fields/RepeaterSimple.test.ts +0 -248
  142. package/src/fields/RowButton.test.ts +0 -219
  143. package/src/fields/RowButton.ts +0 -135
  144. package/src/fields/SelectField.test.ts +0 -192
  145. package/src/fields/SelectField.ts +0 -235
  146. package/src/fields/SliderField.test.ts +0 -50
  147. package/src/fields/SliderField.ts +0 -53
  148. package/src/fields/SlugField.ts +0 -24
  149. package/src/fields/TagsInputField.test.ts +0 -154
  150. package/src/fields/TagsInputField.ts +0 -133
  151. package/src/fields/TextField.test.ts +0 -213
  152. package/src/fields/TextField.ts +0 -177
  153. package/src/fields/TextareaField.test.ts +0 -58
  154. package/src/fields/TextareaField.ts +0 -59
  155. package/src/fields/ToggleButtonsField.test.ts +0 -106
  156. package/src/fields/ToggleButtonsField.ts +0 -59
  157. package/src/fields/ToggleField.ts +0 -16
  158. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  159. package/src/fields/optionsResolver.ts +0 -95
  160. package/src/fields/resolveField.ts +0 -28
  161. package/src/filters/BooleanFilter.ts +0 -35
  162. package/src/filters/DateRangeFilter.test.ts +0 -194
  163. package/src/filters/DateRangeFilter.ts +0 -148
  164. package/src/filters/Filter.test.ts +0 -268
  165. package/src/filters/Filter.ts +0 -184
  166. package/src/filters/FormFilter.test.ts +0 -238
  167. package/src/filters/FormFilter.ts +0 -215
  168. package/src/filters/MultiSelectFilter.test.ts +0 -119
  169. package/src/filters/MultiSelectFilter.ts +0 -78
  170. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  171. package/src/filters/QueryBuilderFilter.ts +0 -398
  172. package/src/filters/SelectFilter.ts +0 -46
  173. package/src/filters/TernaryFilter.test.ts +0 -160
  174. package/src/filters/TernaryFilter.ts +0 -72
  175. package/src/filters/TrashedFilter.test.ts +0 -149
  176. package/src/filters/TrashedFilter.ts +0 -55
  177. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  178. package/src/filters/queryBuilder/Constraint.ts +0 -115
  179. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  180. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  181. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  182. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  183. package/src/filters/queryBuilder/index.ts +0 -12
  184. package/src/icons/index.ts +0 -2
  185. package/src/icons/lucide.ts +0 -204
  186. package/src/icons/registry.test.ts +0 -56
  187. package/src/icons/registry.ts +0 -41
  188. package/src/icons/types.ts +0 -47
  189. package/src/index.ts +0 -525
  190. package/src/io/csv.test.ts +0 -142
  191. package/src/io/csv.ts +0 -170
  192. package/src/nestedRelationManagerData.test.ts +0 -547
  193. package/src/notifications/Notification.test.ts +0 -210
  194. package/src/notifications/Notification.ts +0 -354
  195. package/src/notifications/broadcast.test.ts +0 -110
  196. package/src/notifications/broadcast.ts +0 -95
  197. package/src/notifications/database.test.ts +0 -383
  198. package/src/notifications/database.ts +0 -398
  199. package/src/notifications/databaseNotifications.test.ts +0 -187
  200. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  201. package/src/notifications/dispatchNotificationAction.ts +0 -142
  202. package/src/notifications/flash.test.ts +0 -89
  203. package/src/notifications/flash.ts +0 -71
  204. package/src/notifications/index.ts +0 -45
  205. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  206. package/src/notifications/registerBroadcastAuth.ts +0 -100
  207. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  208. package/src/notifications/resolveSavedNotification.ts +0 -59
  209. package/src/notifications/types.ts +0 -93
  210. package/src/orm/m2mAccessor.ts +0 -66
  211. package/src/orm/modelDefaults.test.ts +0 -633
  212. package/src/orm/modelDefaults.ts +0 -666
  213. package/src/pageData/breadcrumbs.ts +0 -288
  214. package/src/pageData/forms.ts +0 -578
  215. package/src/pageData/helpers.ts +0 -857
  216. package/src/pageData/misc.ts +0 -347
  217. package/src/pageData/navigation.ts +0 -842
  218. package/src/pageData/relationPages.ts +0 -1248
  219. package/src/pageData/relationTabs.ts +0 -286
  220. package/src/pageData/resourcePages.ts +0 -609
  221. package/src/pageData.test.ts +0 -1545
  222. package/src/pageData.ts +0 -341
  223. package/src/plugins/index.ts +0 -8
  224. package/src/plugins/themeEditor.test.ts +0 -36
  225. package/src/plugins/themeEditor.ts +0 -45
  226. package/src/react/AppShell.tsx +0 -251
  227. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  228. package/src/react/CollabRoomContext.ts +0 -98
  229. package/src/react/CollabTextRendererRegistry.ts +0 -102
  230. package/src/react/CommandPalette.tsx +0 -375
  231. package/src/react/CurrentUserContext.tsx +0 -50
  232. package/src/react/CustomPageWrapperGate.tsx +0 -69
  233. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  234. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  235. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  236. package/src/react/FieldPresenceRegistry.ts +0 -46
  237. package/src/react/FormCollabBindingRegistry.ts +0 -242
  238. package/src/react/FormStateContext.tsx +0 -591
  239. package/src/react/HeadHooks.tsx +0 -126
  240. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  241. package/src/react/MarkdownEditorRegistry.ts +0 -107
  242. package/src/react/NotificationActionStrip.tsx +0 -263
  243. package/src/react/NotificationBell.tsx +0 -426
  244. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  245. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  246. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  247. package/src/react/PendingSuggestionsContext.tsx +0 -172
  248. package/src/react/RecordWrapperGate.tsx +0 -58
  249. package/src/react/RecordWrapperRegistry.ts +0 -39
  250. package/src/react/RenderHookSlot.tsx +0 -32
  251. package/src/react/RightSidebar.tsx +0 -257
  252. package/src/react/RightSidebarContext.tsx +0 -234
  253. package/src/react/RightSidebarTrigger.tsx +0 -53
  254. package/src/react/RowCoordsContext.tsx +0 -23
  255. package/src/react/SchemaRenderer.tsx +0 -549
  256. package/src/react/SearchTrigger.tsx +0 -46
  257. package/src/react/ThemeProvider.tsx +0 -93
  258. package/src/react/ThemeSettingsPage.tsx +0 -579
  259. package/src/react/ThemeToggle.tsx +0 -20
  260. package/src/react/Toaster.tsx +0 -158
  261. package/src/react/UserMenu.tsx +0 -196
  262. package/src/react/WidgetDataContext.tsx +0 -157
  263. package/src/react/cells/EditableCell.tsx +0 -389
  264. package/src/react/component-slots.test.ts +0 -103
  265. package/src/react/component-slots.ts +0 -116
  266. package/src/react/fieldJsHandler.test.ts +0 -166
  267. package/src/react/fieldJsHandler.ts +0 -79
  268. package/src/react/fields/BuilderInput.tsx +0 -1078
  269. package/src/react/fields/CheckboxInput.tsx +0 -39
  270. package/src/react/fields/CheckboxListInput.tsx +0 -102
  271. package/src/react/fields/ColorInput.tsx +0 -71
  272. package/src/react/fields/DateFieldInput.tsx +0 -70
  273. package/src/react/fields/DateTimeInput.tsx +0 -62
  274. package/src/react/fields/FieldShell.tsx +0 -348
  275. package/src/react/fields/FileUploadInput.tsx +0 -639
  276. package/src/react/fields/HiddenInput.tsx +0 -17
  277. package/src/react/fields/KeyValueInput.tsx +0 -230
  278. package/src/react/fields/MarkdownInput.tsx +0 -560
  279. package/src/react/fields/RadioInput.tsx +0 -81
  280. package/src/react/fields/RepeaterInput.test.ts +0 -116
  281. package/src/react/fields/RepeaterInput.tsx +0 -1420
  282. package/src/react/fields/SelectFieldInput.tsx +0 -280
  283. package/src/react/fields/SliderInput.tsx +0 -81
  284. package/src/react/fields/TagsInput.tsx +0 -283
  285. package/src/react/fields/TextLikeInput.tsx +0 -256
  286. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  287. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  288. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  289. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  290. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  291. package/src/react/fields/repeaterReconcile.ts +0 -104
  292. package/src/react/fields/rowChromeButton.tsx +0 -336
  293. package/src/react/fields/rowState.ts +0 -106
  294. package/src/react/fields/syncRowGates.test.ts +0 -202
  295. package/src/react/fields/syncRowGates.ts +0 -66
  296. package/src/react/fields/textInputControls.tsx +0 -238
  297. package/src/react/fields/useRowReorderDnd.ts +0 -78
  298. package/src/react/formStateHelpers.test.ts +0 -508
  299. package/src/react/formStateHelpers.ts +0 -381
  300. package/src/react/hooks/use-mobile.ts +0 -19
  301. package/src/react/icon-context.tsx +0 -60
  302. package/src/react/index.ts +0 -194
  303. package/src/react/layouts/SidebarLayout.tsx +0 -250
  304. package/src/react/layouts/TopbarLayout.tsx +0 -258
  305. package/src/react/navigate.tsx +0 -37
  306. package/src/react/onProviderSynced.test.ts +0 -90
  307. package/src/react/parseRecordEditUrl.test.ts +0 -122
  308. package/src/react/parseRecordEditUrl.ts +0 -94
  309. package/src/react/persistedState.ts +0 -40
  310. package/src/react/registry.ts +0 -48
  311. package/src/react/right-panel-registry.tsx +0 -47
  312. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  313. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  314. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  315. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  316. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  317. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  318. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  319. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  320. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  321. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  322. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  323. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  324. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  325. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  326. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  327. package/src/react/schemaRenderer/constants.ts +0 -50
  328. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  329. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  330. package/src/react/schemaRenderer/helpers.tsx +0 -81
  331. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  332. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  333. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  334. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  335. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  336. package/src/react/schemaRenderer/table/links.tsx +0 -112
  337. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  338. package/src/react/schemaRenderer/table/url.tsx +0 -143
  339. package/src/react/theme-preview/apply.ts +0 -99
  340. package/src/react/theme-preview/build-html.ts +0 -436
  341. package/src/react/ui/button.tsx +0 -51
  342. package/src/react/ui/calendar.tsx +0 -67
  343. package/src/react/ui/checkbox.tsx +0 -29
  344. package/src/react/ui/dialog.tsx +0 -108
  345. package/src/react/ui/dropdown-menu.tsx +0 -97
  346. package/src/react/ui/input.tsx +0 -20
  347. package/src/react/ui/label.tsx +0 -21
  348. package/src/react/ui/popover.tsx +0 -50
  349. package/src/react/ui/select.tsx +0 -169
  350. package/src/react/ui/separator.tsx +0 -25
  351. package/src/react/ui/sheet.tsx +0 -136
  352. package/src/react/ui/sidebar.tsx +0 -723
  353. package/src/react/ui/skeleton.tsx +0 -13
  354. package/src/react/ui/slider.tsx +0 -34
  355. package/src/react/ui/switch.tsx +0 -28
  356. package/src/react/ui/table.tsx +0 -105
  357. package/src/react/ui/tabs.tsx +0 -63
  358. package/src/react/ui/textarea.tsx +0 -18
  359. package/src/react/ui/tooltip.tsx +0 -64
  360. package/src/react/useResizableWidth.ts +0 -139
  361. package/src/react/utils.ts +0 -6
  362. package/src/react/widgetRegistry.test.ts +0 -43
  363. package/src/react/widgetRegistry.ts +0 -50
  364. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  365. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  366. package/src/react/widgets/ViewRenderer.tsx +0 -71
  367. package/src/relationManagerData.test.ts +0 -1595
  368. package/src/richtext/index.ts +0 -8
  369. package/src/richtext/registry.ts +0 -89
  370. package/src/routes/globals.ts +0 -148
  371. package/src/routes/guard.test.ts +0 -325
  372. package/src/routes/helpers.ts +0 -704
  373. package/src/routes/pages.ts +0 -175
  374. package/src/routes/panel.ts +0 -204
  375. package/src/routes/relations.ts +0 -1243
  376. package/src/routes/resources.ts +0 -781
  377. package/src/routes/theme.ts +0 -91
  378. package/src/routes-nested-relations.test.ts +0 -676
  379. package/src/routes-relations.test.ts +0 -972
  380. package/src/routes.test.ts +0 -2027
  381. package/src/routes.ts +0 -303
  382. package/src/schema/Alert.test.ts +0 -109
  383. package/src/schema/Alert.ts +0 -131
  384. package/src/schema/Block.ts +0 -169
  385. package/src/schema/Breadcrumbs.ts +0 -40
  386. package/src/schema/Card.ts +0 -35
  387. package/src/schema/Divider.ts +0 -20
  388. package/src/schema/Element.ts +0 -219
  389. package/src/schema/EmptyState.test.ts +0 -37
  390. package/src/schema/EmptyState.ts +0 -63
  391. package/src/schema/Fieldset.ts +0 -43
  392. package/src/schema/Grid.ts +0 -43
  393. package/src/schema/Group.ts +0 -30
  394. package/src/schema/Heading.ts +0 -39
  395. package/src/schema/Html.ts +0 -67
  396. package/src/schema/Icon.ts +0 -54
  397. package/src/schema/Image.ts +0 -57
  398. package/src/schema/LinkTag.ts +0 -41
  399. package/src/schema/Markdown.ts +0 -85
  400. package/src/schema/MetaTag.ts +0 -41
  401. package/src/schema/RelationTabs.ts +0 -71
  402. package/src/schema/ScriptTag.ts +0 -55
  403. package/src/schema/Section.ts +0 -160
  404. package/src/schema/ServerDataElement.test.ts +0 -140
  405. package/src/schema/ServerDataElement.ts +0 -156
  406. package/src/schema/SlotComponent.test.ts +0 -77
  407. package/src/schema/SlotComponent.ts +0 -71
  408. package/src/schema/Split.ts +0 -50
  409. package/src/schema/Stat.test.ts +0 -118
  410. package/src/schema/Stat.ts +0 -154
  411. package/src/schema/StatsOverview.test.ts +0 -141
  412. package/src/schema/StatsOverview.ts +0 -119
  413. package/src/schema/StyleTag.ts +0 -35
  414. package/src/schema/TableWidget.test.ts +0 -297
  415. package/src/schema/TableWidget.ts +0 -289
  416. package/src/schema/Tabs.ts +0 -79
  417. package/src/schema/Text.ts +0 -58
  418. package/src/schema/UnorderedList.ts +0 -49
  419. package/src/schema/View.test.ts +0 -111
  420. package/src/schema/View.ts +0 -127
  421. package/src/schema/Wizard.ts +0 -220
  422. package/src/schema/containers.test.ts +0 -564
  423. package/src/schema/headTags.test.ts +0 -134
  424. package/src/schema/index.ts +0 -40
  425. package/src/schema/primes.test.ts +0 -269
  426. package/src/schema/resolveSchema.test.ts +0 -379
  427. package/src/schema/resolveSchema.ts +0 -917
  428. package/src/schema/sanitize.ts +0 -58
  429. package/src/search.test.ts +0 -446
  430. package/src/search.ts +0 -178
  431. package/src/sessionFilters.test.ts +0 -375
  432. package/src/sessionFilters.ts +0 -143
  433. package/src/slot-components/index.ts +0 -10
  434. package/src/slot-components/registry.ts +0 -56
  435. package/src/styles/file-upload.css +0 -13
  436. package/src/summarizers/Summarizer.test.ts +0 -84
  437. package/src/summarizers/Summarizer.ts +0 -123
  438. package/src/summarizers/index.ts +0 -11
  439. package/src/theme/base-colors.ts +0 -68
  440. package/src/theme/chart-colors.ts +0 -50
  441. package/src/theme/colors.ts +0 -447
  442. package/src/theme/generate-css.test.ts +0 -139
  443. package/src/theme/generate-css.ts +0 -44
  444. package/src/theme/generate-scale.test.ts +0 -106
  445. package/src/theme/generate-scale.ts +0 -97
  446. package/src/theme/icon-map.ts +0 -42
  447. package/src/theme/index.ts +0 -34
  448. package/src/theme/migrate.test.ts +0 -178
  449. package/src/theme/migrate.ts +0 -81
  450. package/src/theme/presets.ts +0 -135
  451. package/src/theme/radius.ts +0 -18
  452. package/src/theme/resolve.test.ts +0 -238
  453. package/src/theme/resolve.ts +0 -96
  454. package/src/theme/spacing.ts +0 -18
  455. package/src/theme/storage.test.ts +0 -126
  456. package/src/theme/storage.ts +0 -106
  457. package/src/theme/theme-colors.ts +0 -88
  458. package/src/theme/types.ts +0 -125
  459. package/src/uploads/UploadAdapter.ts +0 -35
  460. package/src/uploads/index.ts +0 -2
  461. package/src/uploads/localUpload.test.ts +0 -70
  462. package/src/uploads/localUpload.ts +0 -84
  463. package/src/validation/Validator.ts +0 -49
  464. package/src/validation/index.ts +0 -28
  465. package/src/validation/rules.ts +0 -78
  466. package/src/validation/runValidators.ts +0 -435
  467. package/src/validation/uniqueValidator.test.ts +0 -196
  468. package/src/validation/uniqueValidator.ts +0 -133
  469. package/src/validation/validators.test.ts +0 -268
  470. package/src/vite.test.ts +0 -184
  471. package/src/vite.ts +0 -787
  472. package/src/widgets/index.ts +0 -10
  473. package/src/widgets/registry.ts +0 -45
  474. package/src/widgets.test.ts +0 -592
  475. package/tsconfig.build.json +0 -11
  476. package/tsconfig.json +0 -4
  477. package/tsconfig.test.json +0 -10
  478. package/views/react/Dashboard.tsx +0 -27
  479. package/views/react/Resources/Form.tsx +0 -102
  480. package/views/react/Resources/Index.tsx +0 -49
@@ -1,549 +0,0 @@
1
- import React, { useEffect, useRef, useState } from 'react'
2
- import type { ElementMeta } from '../schema/Element.js'
3
- import { getFieldRenderer } from './registry.js'
4
- import { getFieldLabelSlot } from './FieldLabelSlotRegistry.js'
5
- import { FormStateProvider, useFormState, FormIdContext } from './FormStateContext.js'
6
- import { CircleIcon } from 'lucide-react'
7
- import { useNavigate } from './navigate.js'
8
- import { useIconFor } from './icon-context.js'
9
- import type { SerializedIcon } from '../icons/types.js'
10
- import { useToast } from './Toaster.js'
11
- import { pickEditableCell } from './cells/EditableCell.js'
12
- import { WidgetDataProvider } from './WidgetDataContext.js'
13
- import { StatsOverviewRenderer } from './widgets/StatsOverviewRenderer.js'
14
- import { TableWidgetRenderer } from './widgets/TableWidgetRenderer.js'
15
- import { ViewRenderer } from './widgets/ViewRenderer.js'
16
- import { getSlotComponent } from '../slot-components/registry.js'
17
- import { getWidgetRenderer } from './widgetRegistry.js'
18
- import type { NotificationMeta } from '../notifications/Notification.js'
19
- import {
20
- BADGE_COLOR_CLASSES,
21
- COLUMN_COLOR_CLASSES,
22
- COLUMN_WEIGHT_CLASSES,
23
- } from './schemaRenderer/constants.js'
24
- import {
25
- layoutClasses,
26
- renderChildren,
27
- resolveIcon,
28
- withTooltip,
29
- } from './schemaRenderer/helpers.js'
30
- import { renderSimpleElement } from './schemaRenderer/SimpleElements.js'
31
- import { AlertRenderer } from './schemaRenderer/AlertRenderer.js'
32
- import { SectionRenderer } from './schemaRenderer/SectionRenderer.js'
33
- import { TabsRenderer } from './schemaRenderer/TabsRenderer.js'
34
- import { WizardRenderer } from './schemaRenderer/WizardRenderer.js'
35
- import { renderEntry } from './schemaRenderer/EntryRenderer.js'
36
- import { applyColumnFormat } from './schemaRenderer/columnFormat.js'
37
- import type { RenderActionOptions } from './schemaRenderer/action/buttons.js'
38
- import {
39
- dispatchHandlerAction as actionDispatchHandlerAction,
40
- } from './schemaRenderer/action/helpers.js'
41
- import { renderAction, renderActionLike as renderActionLikeImpl } from './schemaRenderer/action/renderAction.js'
42
- import { ActionGroupTrigger } from './schemaRenderer/action/ActionGroupTrigger.js'
43
- import {
44
- renderField as renderFieldImpl,
45
- } from './schemaRenderer/form/renderField.js'
46
- import {
47
- FormRenderer as FormRendererImpl,
48
- renderFormChild as renderFormChildImpl,
49
- } from './schemaRenderer/form/FormRenderer.js'
50
- import { TableRenderer as TableRendererImpl } from './schemaRenderer/table/TableRenderer.js'
51
- import type { TableBodyDeps } from './schemaRenderer/table/TableRendererBody.js'
52
-
53
- /**
54
- * Re-export `dispatchHandlerAction` from the action helpers so existing
55
- * consumers (e.g. `RepeaterInput.tsx`) keep working through this barrel.
56
- * Phase 4 may shift these imports onto the action subpath directly.
57
- */
58
- export const dispatchHandlerAction = actionDispatchHandlerAction
59
-
60
- /**
61
- * Render a flat list of resolved field-meta as standalone form inputs,
62
- * outside any pilotiq Form wrapper. Useful for embedding the schema
63
- * input layer in custom surfaces (e.g. the rich-text custom-block side
64
- * panel) where the consumer drives reads/writes directly on a host
65
- * `<form>` via DOM event delegation.
66
- *
67
- * Behavior:
68
- * - Each field renders through the same `renderField` switch the
69
- * SchemaRenderer uses for in-form fields, so chrome (label, helper
70
- * text, prefix/suffix) and field-type coverage stay in lockstep.
71
- * - `values`, when supplied, overrides each field's `defaultValue`
72
- * so the consumer can prefill from external state.
73
- * - Inputs are uncontrolled (`defaultValue`-based) — outside a
74
- * `FormStateProvider`, `useFieldState` falls back automatically.
75
- * The host captures changes via container-level event delegation.
76
- *
77
- * Not for: container layouts (Card / Tabs / Section / Wizard), Action
78
- * triggers, or anything beyond a flat field list. Use SchemaRenderer
79
- * for full pages.
80
- */
81
- export interface FormFieldsProps {
82
- elements: ElementMeta[]
83
- values?: Record<string, unknown>
84
- }
85
-
86
- export function FormFields({ elements, values }: FormFieldsProps): React.ReactElement {
87
- return (
88
- <>
89
- {elements.map((el, i) => {
90
- if (el['type'] !== 'field') return null
91
- const name = String(el['name'] ?? '')
92
- const merged = values && name in values
93
- ? { ...el, defaultValue: values[name] } as ElementMeta
94
- : el
95
- return renderField(merged, i)
96
- })}
97
- </>
98
- )
99
- }
100
-
101
-
102
-
103
-
104
-
105
- /** Thin wrapper that binds the renderer-injected deps so call sites
106
- * inside this file can keep the original three-arg signature. The
107
- * action layer (Phase 3) lives behind `renderActionLikeImpl`; it needs
108
- * `renderElement` + `renderFormChild` for nested schemas + modal-form
109
- * bodies. Both are function declarations so hoisting handles the
110
- * forward reference cleanly. */
111
- function renderActionLike(
112
- el: ElementMeta,
113
- index: number,
114
- opts: RenderActionOptions = {},
115
- ): React.ReactNode {
116
- return renderActionLikeImpl(el, index, opts, { renderElement, renderFormChild })
117
- }
118
-
119
- /** Thin wrapper around `renderFieldImpl` that pre-binds `renderElement`.
120
- * Lets `FormFields`, `renderFormChild`, and the renderElement switch
121
- * call the form-layer field renderer with the original two-arg signature. */
122
- function renderField(el: ElementMeta, index: number): React.ReactNode {
123
- return renderFieldImpl(el, index, renderElement)
124
- }
125
-
126
- /** Re-export the form-layer `renderFormChild` with `renderElement`
127
- * pre-bound, so external consumers (e.g. `SelectFieldInput.tsx`) keep
128
- * importing it from `SchemaRenderer.js` with the same four-arg signature.
129
- * Internal callers (action layer dialogs, ActionGroupTrigger) get the
130
- * same closure through prop injection. */
131
- export function renderFormChild(
132
- child: ElementMeta,
133
- index: number,
134
- values: Record<string, unknown>,
135
- errors: Record<string, string[]>,
136
- ): React.ReactNode {
137
- return renderFormChildImpl(child, index, values, errors, renderElement)
138
- }
139
-
140
- /** Local wrapper around the form-layer `FormRenderer` that pre-binds
141
- * `renderElement`. Kept thin so the switch case below stays a one-liner. */
142
- function FormRenderer({ el }: { el: ElementMeta }) {
143
- return <FormRendererImpl el={el} renderElement={renderElement} />
144
- }
145
-
146
- /** Pre-bind the three injected deps that `TableRendererBody` needs:
147
- * - `renderElement` for column cells holding Element-typed children
148
- * - `renderActionLike` for row + bulk action dispatch
149
- * - `renderFormChild` for the inline-edit modal's form schema body */
150
- const tableBodyDeps: TableBodyDeps = {
151
- get renderElement() { return renderElement },
152
- get renderActionLike() { return renderActionLike },
153
- get renderFormChild() { return renderFormChild },
154
- }
155
-
156
- /** Local wrapper around the table-layer `TableRenderer` that injects the
157
- * three renderer deps. The body lives behind a separate import so the
158
- * module cycle stays clean. */
159
- function TableRenderer({ el }: { el: ElementMeta }) {
160
- return <TableRendererImpl el={el} deps={tableBodyDeps} />
161
- }
162
-
163
- function renderElement(el: ElementMeta, index: number): React.ReactNode {
164
- // Stateless leaves + layout primitives — text/image/icon/markdown/html/
165
- // heading/emptyState/divider/unorderedList/card/grid/group/split/fieldset.
166
- // Returns undefined for unhandled types so the switch below picks them up.
167
- const simple = renderSimpleElement(el, index, { renderElement, renderActionLike })
168
- if (simple !== undefined) return simple
169
-
170
- switch (el.type) {
171
- case 'alert': {
172
- const footer = (el.children ?? []).filter(c => c.type === 'action' || c.type === 'actionGroup' || c.type === 'slotComponent')
173
- return (
174
- <AlertRenderer
175
- key={index}
176
- alertType={String(el['alertType'] ?? 'info')}
177
- content={String(el['content'] ?? '')}
178
- {...(el['title'] !== undefined ? { title: String(el['title']) } : {})}
179
- {...(el['dismissible'] ? { dismissible: Boolean(el['dismissible']) } : {})}
180
- {...(el['persistDismissal'] !== undefined ? { persistDismissal: String(el['persistDismissal']) } : {})}
181
- {...(el['iconColor'] !== undefined ? { iconColor: String(el['iconColor']) } : {})}
182
- {...(el['actionsAlignment'] !== undefined ? { actionsAlignment: String(el['actionsAlignment']) } : {})}
183
- footer={footer.map((a, i) => renderActionLike(a, i))}
184
- />
185
- )
186
- }
187
-
188
- case 'section':
189
- return <SectionRenderer key={index} el={el} index={index} renderElement={renderElement} />
190
-
191
- case 'tabs':
192
- return <TabsRenderer key={index} el={el} index={index} renderElement={renderElement} />
193
-
194
- case 'tab':
195
- // Tabs are rendered by their parent `tabs` element; standalone Tab is a no-op.
196
- return null
197
-
198
- case 'listTabs':
199
- return <ListTabsRenderer key={index} el={el} />
200
-
201
- case 'relation-tabs':
202
- return <RelationTabsRenderer key={index} el={el} />
203
-
204
- case 'breadcrumbs':
205
- return <BreadcrumbsRenderer key={index} el={el} />
206
-
207
- case 'listTab':
208
- // List tabs are rendered by their parent `listTabs` strip; standalone is a no-op.
209
- return null
210
-
211
- case 'wizard':
212
- return (
213
- <WizardRenderer
214
- key={index}
215
- el={el}
216
- index={index}
217
- deps={{ renderElement }}
218
- />
219
- )
220
-
221
- case 'step':
222
- // Steps are rendered by their parent Wizard; standalone Step is a no-op.
223
- return null
224
-
225
- case 'field':
226
- return renderField(el, index)
227
-
228
- case 'entry':
229
- return renderEntry(el, index, renderElement)
230
-
231
- case 'action':
232
- return renderAction(el, index, {}, { renderElement, renderFormChild })
233
-
234
- case 'actionGroup':
235
- return (
236
- <ActionGroupTrigger
237
- key={index}
238
- el={el}
239
- renderFormChild={renderFormChild}
240
- renderElement={renderElement}
241
- />
242
- )
243
-
244
- case 'form': {
245
- // Key on formId so SPA navigation between pages with different
246
- // forms (list → edit, edit → edit-of-different-record, etc.)
247
- // forces a fresh React mount. Form fields are uncontrolled
248
- // (`defaultValue`), so without remount, prop updates wouldn't
249
- // propagate into the rendered <input>s — the form would render
250
- // with stale or empty values.
251
- const formId = String(el['formId'] ?? index)
252
- return <FormRenderer key={formId} el={el} />
253
- }
254
-
255
- case 'table':
256
- return <TableRenderer key={index} el={el} />
257
-
258
- case 'column':
259
- // Columns are rendered by their parent table; standalone column is a no-op.
260
- return null
261
-
262
- case 'stats':
263
- return <StatsOverviewRenderer key={index} meta={el} />
264
-
265
- case 'tableWidget':
266
- return <TableWidgetRenderer key={index} meta={el} />
267
-
268
- case 'view':
269
- return <ViewRenderer key={index} meta={el} />
270
-
271
- case 'slotComponent': {
272
- const componentName = String(el['component'] ?? '')
273
- if (!componentName) {
274
- return (
275
- <div
276
- key={index}
277
- className="rounded-md border border-amber-500/40 bg-amber-50 p-3 text-sm text-amber-800 dark:bg-amber-950/30 dark:text-amber-200"
278
- role="alert"
279
- >
280
- SlotComponent without a registered <code className="font-mono">component</code> name.
281
- </div>
282
- )
283
- }
284
- const Component = getSlotComponent(componentName)
285
- if (!Component) {
286
- return (
287
- <div
288
- key={index}
289
- className="rounded-md border border-amber-500/40 bg-amber-50 p-3 text-sm text-amber-800 dark:bg-amber-950/30 dark:text-amber-200"
290
- role="alert"
291
- >
292
- No slot component registered for <code className="font-mono">{componentName}</code>.
293
- Call <code className="font-mono">registerSlotComponents({'{ '}{componentName}{' }'})</code> at app boot.
294
- </div>
295
- )
296
- }
297
- const props = (el['props'] ?? {}) as Record<string, unknown>
298
- return <Component key={index} {...props} />
299
- }
300
-
301
- default: {
302
- // Plan #15 Phase C — server-data widget elements registered by
303
- // adapter packages (`@pilotiq/recharts` for `'chart'`, future
304
- // `@pilotiq/chartjs`, etc.) dispatch through the runtime widget
305
- // registry. The fallback error message points the consumer at the
306
- // install command — silent `null` here would let a missing
307
- // `registerChartRenderer()` slip through.
308
- if (el['serverData'] === true) {
309
- const widgetType = String(el.type ?? '')
310
- const Renderer = getWidgetRenderer(widgetType)
311
- if (Renderer) return <Renderer key={index} meta={el} />
312
- return (
313
- <div
314
- key={index}
315
- className="rounded-md border border-amber-500/40 bg-amber-50 p-3 text-sm text-amber-800 dark:bg-amber-950/30 dark:text-amber-200"
316
- role="alert"
317
- >
318
- No renderer registered for widget type <code className="font-mono">{widgetType}</code>.
319
- {widgetType === 'chart' && (
320
- <> Install <code className="font-mono">@pilotiq/recharts</code> and
321
- call <code className="font-mono">registerChartRenderer()</code> at app boot.</>
322
- )}
323
- </div>
324
- )
325
- }
326
- return null
327
- }
328
- }
329
- }
330
-
331
-
332
-
333
- /**
334
- * List-page tab strip — Filament-style query shortcuts above the table
335
- * ("All / Drafts / Published / Archived"). Each trigger is a real `<a>`
336
- * (right-click / cmd-click "open in new tab" works); plain left-click is
337
- * intercepted for SPA navigation. Active tab carries `data-active`.
338
- *
339
- * The server stamps `active` + per-tab `url` + resolved badge string on
340
- * each `listTab` meta entry — this component just renders.
341
- */
342
- function ListTabsRenderer({ el }: { el: ElementMeta }) {
343
- const navigate = useNavigate()
344
- const tabs = (el.children ?? []).filter(c => c.type === 'listTab')
345
- if (tabs.length === 0) return null
346
-
347
- return (
348
- <div className="border-b border-border">
349
- <nav className="flex items-center gap-1 -mb-px overflow-x-auto" role="tablist">
350
- {tabs.map((t, i) => {
351
- const name = String(t['name'] ?? '')
352
- const label = String(t['label'] ?? name)
353
- const active = Boolean(t['active'])
354
- const url = String(t['url'] ?? `?tab=${encodeURIComponent(name)}`)
355
- const iconKey = t['icon'] ? String(t['icon']) : undefined
356
- const Icon = iconKey ? (resolveIcon(iconKey) ?? CircleIcon) : undefined
357
- const badge = t['badge'] !== undefined ? String(t['badge']) : undefined
358
- const badgeKey = t['badgeColor'] ? String(t['badgeColor']) : (active ? 'primary' : 'gray')
359
- const badgeCls = BADGE_COLOR_CLASSES[badgeKey] ?? BADGE_COLOR_CLASSES['gray']
360
-
361
- const triggerCls = [
362
- 'inline-flex items-center gap-1.5 px-3 py-2 text-sm border-b-2 transition-colors whitespace-nowrap',
363
- active
364
- ? 'border-primary text-foreground font-medium'
365
- : 'border-transparent text-muted-foreground hover:text-foreground hover:border-border',
366
- ].join(' ')
367
-
368
- const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
369
- if (e.button !== 0) return
370
- if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return
371
- e.preventDefault()
372
- void navigate(url)
373
- }
374
-
375
- return (
376
- <a
377
- key={i}
378
- href={url}
379
- onClick={onClick}
380
- role="tab"
381
- aria-selected={active}
382
- data-active={active || undefined}
383
- className={triggerCls}
384
- >
385
- {Icon && <Icon className="size-4" aria-hidden="true" />}
386
- <span>{label}</span>
387
- {badge !== undefined && (
388
- <span className={`ml-1 inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${badgeCls}`}>
389
- {badge}
390
- </span>
391
- )}
392
- </a>
393
- )
394
- })}
395
- </nav>
396
- </div>
397
- )
398
- }
399
-
400
- interface RelationTabMetaShape {
401
- key: string
402
- label: string
403
- url: string
404
- active: boolean
405
- icon?: unknown
406
- }
407
-
408
- interface BreadcrumbItemShape {
409
- label: string
410
- url?: string
411
- }
412
-
413
- /** Phase C — server-resolved breadcrumb chain rendered above any other
414
- * top-of-page chrome. The trailing item carries no `url` and renders
415
- * as plain text + `aria-current="page"`. SPA-navigates on plain
416
- * left-click; modified clicks fall through. */
417
- function BreadcrumbsRenderer({ el }: { el: ElementMeta }) {
418
- const navigate = useNavigate()
419
- const items = (el['items'] as BreadcrumbItemShape[] | undefined) ?? []
420
- if (items.length < 2) return null
421
-
422
- return (
423
- <nav aria-label="Breadcrumb" className="text-sm text-muted-foreground">
424
- <ol className="flex flex-wrap items-center gap-1.5">
425
- {items.map((item, i) => {
426
- const isLast = i === items.length - 1
427
- const linkable = !!item.url && !isLast
428
-
429
- const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
430
- if (e.button !== 0) return
431
- if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return
432
- if (!item.url) return
433
- e.preventDefault()
434
- void navigate(item.url)
435
- }
436
-
437
- return (
438
- <li key={`${i}:${item.label}`} className="inline-flex items-center gap-1.5">
439
- {linkable
440
- ? (
441
- <a
442
- href={item.url}
443
- onClick={onClick}
444
- className="hover:text-foreground transition-colors"
445
- >
446
- {item.label}
447
- </a>
448
- )
449
- : (
450
- <span
451
- aria-current={isLast ? 'page' : undefined}
452
- className={isLast ? 'text-foreground font-medium' : undefined}
453
- >
454
- {item.label}
455
- </span>
456
- )}
457
- {!isLast && (
458
- <span aria-hidden="true" className="text-muted-foreground/50">/</span>
459
- )}
460
- </li>
461
- )
462
- })}
463
- </ol>
464
- </nav>
465
- )
466
- }
467
-
468
- /** Plan #11 — relation manager nav strip. Renders one anchor per tab;
469
- * the active tab gets the same border-primary styling as ListTabs.
470
- * SPA-navigates on plain left-click; cmd/ctrl/shift/middle-click fall
471
- * through so users can open a manager in a new tab. */
472
- function RelationTabsRenderer({ el }: { el: ElementMeta }) {
473
- const navigate = useNavigate()
474
- const tabs = (el['tabs'] as RelationTabMetaShape[] | undefined) ?? []
475
- if (tabs.length === 0) return null
476
-
477
- return (
478
- <div className="border-b border-border">
479
- <nav className="flex items-center gap-1 -mb-px overflow-x-auto" role="tablist">
480
- {tabs.map((t, i) => {
481
- const triggerCls = [
482
- 'inline-flex items-center gap-1.5 px-3 py-2 text-sm border-b-2 transition-colors whitespace-nowrap',
483
- t.active
484
- ? 'border-primary text-foreground font-medium'
485
- : 'border-transparent text-muted-foreground hover:text-foreground hover:border-border',
486
- ].join(' ')
487
-
488
- const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
489
- if (e.button !== 0) return
490
- if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return
491
- e.preventDefault()
492
- void navigate(t.url)
493
- }
494
-
495
- return (
496
- <a
497
- key={t.key + ':' + i}
498
- href={t.url}
499
- onClick={onClick}
500
- role="tab"
501
- aria-selected={t.active}
502
- data-active={t.active || undefined}
503
- className={triggerCls}
504
- >
505
- <RelationTabIcon icon={t.icon} />
506
- <span>{t.label}</span>
507
- </a>
508
- )
509
- })}
510
- </nav>
511
- </div>
512
- )
513
- }
514
-
515
- function RelationTabIcon({ icon }: { icon: unknown }) {
516
- // SerializedIcon is `string | { class: string }`. Use useIconFor to
517
- // resolve component-typed icons through the Vite plugin's manifest.
518
- const Icon = useIconFor(icon as SerializedIcon | undefined)
519
- if (!Icon) return null
520
- return <Icon className="size-4 inline" aria-hidden="true" />
521
- }
522
-
523
- export interface SchemaRendererProps {
524
- /** Resolved schema elements (server-side `resolveSchema` output) that
525
- * the renderer walks recursively. */
526
- elements: ElementMeta[]
527
- /**
528
- * Initial widget data — a record keyed by widget id whose values are
529
- * stamped onto the SSR pass by `tagWidgetUrls` + `resolveServerDataElements`.
530
- * Surfaces through `<WidgetDataProvider>` so per-widget components
531
- * can read their first-paint payload through `useInitialWidgetData`.
532
- * Optional — pages with no widgets ship `undefined` and the provider
533
- * is a no-op.
534
- */
535
- widgetData?: Record<string, unknown>
536
- }
537
-
538
- export function SchemaRenderer({ elements, widgetData }: SchemaRendererProps) {
539
- if (!elements || elements.length === 0) return null
540
- // exactOptionalPropertyTypes: only spread `data` when defined.
541
- const providerProps = widgetData !== undefined ? { data: widgetData } : {}
542
- return (
543
- <WidgetDataProvider {...providerProps}>
544
- <div className="flex flex-col gap-6">
545
- {elements.map((el, i) => renderElement(el, i))}
546
- </div>
547
- </WidgetDataProvider>
548
- )
549
- }
@@ -1,46 +0,0 @@
1
- import * as React from 'react'
2
- import { useEffect, useState } from 'react'
3
- import { SearchIcon } from 'lucide-react'
4
-
5
- import { useCommandPaletteOpener } from './CommandPalette.js'
6
-
7
- /**
8
- * Plan #12 — compact "Search… ⌘K" pill that lives in the sidebar /
9
- * topbar header. Clicking it opens the command palette via the
10
- * `useCommandPaletteOpener()` context hook (AppShell hosts the
11
- * provider).
12
- *
13
- * Renders nothing when the opener isn't mounted (panel without
14
- * AppShell — e.g., a custom embedding). The keyboard shortcut hint
15
- * adapts to platform: ⌘ on macOS, Ctrl elsewhere.
16
- */
17
- export function SearchTrigger(): React.ReactElement | null {
18
- const open = useCommandPaletteOpener()
19
- const [isMac, setIsMac] = useState(false)
20
-
21
- // Detect macOS after mount — server renders with the default ("Ctrl"),
22
- // client refines after hydration. SSR-stable, no flash on macOS users
23
- // because the symbol is resolved before the icon paints.
24
- useEffect(() => {
25
- if (typeof navigator !== 'undefined') {
26
- setIsMac(/Mac|iPhone|iPad|iPod/.test(navigator.platform))
27
- }
28
- }, [])
29
-
30
- if (!open) return null
31
-
32
- return (
33
- <button
34
- type="button"
35
- onClick={open}
36
- aria-label="Open search"
37
- className="flex h-8 items-center gap-2 rounded-md border border-border bg-muted/40 px-2.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground transition"
38
- >
39
- <SearchIcon className="size-3.5" aria-hidden="true" />
40
- <span className="hidden sm:inline">Search…</span>
41
- <kbd className="hidden sm:inline-flex items-center font-mono text-[10px] text-muted-foreground/80 border border-border/60 rounded px-1 ml-1">
42
- {isMac ? '⌘K' : 'Ctrl K'}
43
- </kbd>
44
- </button>
45
- )
46
- }
@@ -1,93 +0,0 @@
1
- 'use client'
2
-
3
- import { createContext, useContext, useEffect, useState } from 'react'
4
- import { generateThemeCSS } from '../theme/index.js'
5
- import type { ThemeMeta } from '../theme/index.js'
6
-
7
- type Theme = 'light' | 'dark' | 'system'
8
-
9
- interface ThemeProviderProps {
10
- children: React.ReactNode
11
- defaultTheme?: Theme
12
- storageKey?: string
13
- /** Resolved theme — injects CSS variables when provided. */
14
- theme?: ThemeMeta
15
- }
16
-
17
- interface ThemeContextValue {
18
- theme: Theme
19
- setTheme: (theme: Theme) => void
20
- resolved: 'light' | 'dark'
21
- }
22
-
23
- const ThemeContext = createContext<ThemeContextValue>({
24
- theme: 'system',
25
- setTheme: () => {},
26
- resolved: 'light',
27
- })
28
-
29
- function getSystemTheme(): 'light' | 'dark' {
30
- if (typeof window === 'undefined') return 'light'
31
- return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
32
- }
33
-
34
- export function ThemeProvider({ children, defaultTheme = 'system', storageKey = 'pilotiq-theme', theme: themeMeta }: ThemeProviderProps) {
35
- const [theme, setThemeState] = useState<Theme>(defaultTheme)
36
- const [mounted, setMounted] = useState(false)
37
-
38
- useEffect(() => {
39
- const stored = localStorage.getItem(storageKey) as Theme | null
40
- if (stored) setThemeState(stored)
41
- setMounted(true)
42
- }, [storageKey])
43
-
44
- const resolved = theme === 'system' ? getSystemTheme() : theme
45
-
46
- useEffect(() => {
47
- if (!mounted) return
48
- const root = document.documentElement
49
- root.classList.remove('light', 'dark')
50
- root.classList.add(resolved)
51
- }, [resolved, mounted])
52
-
53
- useEffect(() => {
54
- if (theme === 'system') {
55
- const mq = window.matchMedia('(prefers-color-scheme: dark)')
56
- const handler = () => {
57
- const r = mq.matches ? 'dark' : 'light'
58
- document.documentElement.classList.remove('light', 'dark')
59
- document.documentElement.classList.add(r)
60
- }
61
- mq.addEventListener('change', handler)
62
- return () => mq.removeEventListener('change', handler)
63
- }
64
- }, [theme])
65
-
66
- // Inject theme CSS variables
67
- useEffect(() => {
68
- if (!themeMeta) return
69
- const id = 'pilotiq-theme'
70
- let style = document.getElementById(id) as HTMLStyleElement | null
71
- if (!style) {
72
- style = document.createElement('style')
73
- style.id = id
74
- document.head.appendChild(style)
75
- }
76
- style.textContent = generateThemeCSS(themeMeta)
77
- }, [themeMeta])
78
-
79
- function setTheme(t: Theme) {
80
- setThemeState(t)
81
- localStorage.setItem(storageKey, t)
82
- }
83
-
84
- return (
85
- <ThemeContext.Provider value={{ theme, setTheme, resolved }}>
86
- {children}
87
- </ThemeContext.Provider>
88
- )
89
- }
90
-
91
- export function useTheme() {
92
- return useContext(ThemeContext)
93
- }