@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.
- package/CHANGELOG.md +91 -0
- package/boost/guidelines.md +566 -0
- package/boost/skills/pilotiq-fields/SKILL.md +47 -0
- package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
- package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
- package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
- package/boost/skills/pilotiq-relations/SKILL.md +47 -0
- package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
- package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
- package/boost/skills/pilotiq-resource/SKILL.md +61 -0
- package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
- package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
- package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
- package/dist/actions/exportFactory.d.ts +10 -0
- package/dist/actions/exportFactory.d.ts.map +1 -1
- package/dist/actions/exportFactory.js +10 -0
- package/dist/actions/exportFactory.js.map +1 -1
- package/dist/react/CollabRoomContext.d.ts +5 -5
- package/dist/react/index.d.ts +0 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +0 -1
- package/dist/react/index.js.map +1 -1
- package/dist/routes/helpers.d.ts.map +1 -1
- package/dist/routes/helpers.js +6 -2
- package/dist/routes/helpers.js.map +1 -1
- package/dist/routes/relations.d.ts.map +1 -1
- package/dist/routes/relations.js +12 -0
- package/dist/routes/relations.js.map +1 -1
- package/package.json +6 -1
- package/.turbo/turbo-build.log +0 -8
- package/CLAUDE.md +0 -265
- package/dist/react/useCollabSeed.d.ts +0 -23
- package/dist/react/useCollabSeed.d.ts.map +0 -1
- package/dist/react/useCollabSeed.js +0 -82
- package/dist/react/useCollabSeed.js.map +0 -1
- package/src/Cluster.test.ts +0 -283
- package/src/Cluster.ts +0 -83
- package/src/Column.test.ts +0 -199
- package/src/Column.ts +0 -710
- package/src/Global.test.ts +0 -367
- package/src/Global.ts +0 -169
- package/src/Page.test.ts +0 -114
- package/src/Page.ts +0 -208
- package/src/Pilotiq.perf.test.ts +0 -252
- package/src/Pilotiq.test.ts +0 -129
- package/src/Pilotiq.ts +0 -1158
- package/src/PilotiqRegistry.ts +0 -36
- package/src/PilotiqServiceProvider.ts +0 -121
- package/src/RelationManager.test.ts +0 -400
- package/src/RelationManager.ts +0 -527
- package/src/RenderHook.test.ts +0 -252
- package/src/RenderHook.ts +0 -242
- package/src/Resource.test.ts +0 -284
- package/src/Resource.ts +0 -526
- package/src/RightPanel.test.ts +0 -202
- package/src/RightPanel.ts +0 -132
- package/src/Tab.test.ts +0 -91
- package/src/Tab.ts +0 -156
- package/src/UserMenuItem.ts +0 -145
- package/src/actions/Action.test.ts +0 -2526
- package/src/actions/Action.ts +0 -1515
- package/src/actions/ActionGroup.test.ts +0 -112
- package/src/actions/ActionGroup.ts +0 -173
- package/src/actions/attachFactory.ts +0 -172
- package/src/actions/bulkFactories.ts +0 -168
- package/src/actions/crudFactories.ts +0 -220
- package/src/actions/exportFactory.ts +0 -215
- package/src/actions/factoryHelpers.ts +0 -177
- package/src/actions/importFactory.ts +0 -243
- package/src/actions/index.ts +0 -17
- package/src/actions/m2mFactories.ts +0 -193
- package/src/actions/relationFactories.ts +0 -372
- package/src/applyPageHooks.test.ts +0 -463
- package/src/applyPageHooks.ts +0 -330
- package/src/authorization.test.ts +0 -483
- package/src/breadcrumbs.test.ts +0 -238
- package/src/cells/coerce.test.ts +0 -85
- package/src/cells/coerce.ts +0 -84
- package/src/clusterPaths.ts +0 -35
- package/src/columns/BadgeColumn.test.ts +0 -54
- package/src/columns/BadgeColumn.ts +0 -32
- package/src/columns/BooleanColumn.test.ts +0 -41
- package/src/columns/BooleanColumn.ts +0 -18
- package/src/columns/ColorColumn.test.ts +0 -37
- package/src/columns/ColorColumn.ts +0 -38
- package/src/columns/IconColumn.test.ts +0 -54
- package/src/columns/IconColumn.ts +0 -37
- package/src/columns/ImageColumn.test.ts +0 -41
- package/src/columns/ImageColumn.ts +0 -28
- package/src/columns/SelectColumn.ts +0 -98
- package/src/columns/TextColumn.test.ts +0 -190
- package/src/columns/TextColumn.ts +0 -20
- package/src/columns/TextInputColumn.ts +0 -68
- package/src/columns/ToggleColumn.ts +0 -46
- package/src/columns/editableColumns.test.ts +0 -238
- package/src/columns/index.ts +0 -9
- package/src/defaultGlobalPages.ts +0 -95
- package/src/defaultPages.test.ts +0 -634
- package/src/defaultPages.ts +0 -617
- package/src/defaultViewPage.test.ts +0 -147
- package/src/elements/Form.test.ts +0 -223
- package/src/elements/Form.ts +0 -416
- package/src/elements/ListTabs.ts +0 -28
- package/src/elements/Table.test.ts +0 -422
- package/src/elements/Table.ts +0 -850
- package/src/elements/TableGroup.test.ts +0 -260
- package/src/elements/TableGroup.ts +0 -334
- package/src/elements/dispatchAction.test.ts +0 -463
- package/src/elements/dispatchAction.ts +0 -355
- package/src/elements/dispatchForm.test.ts +0 -477
- package/src/elements/dispatchForm.ts +0 -1993
- package/src/elements/dispatchTable.test.ts +0 -1514
- package/src/elements/dispatchTable.ts +0 -745
- package/src/elements/index.ts +0 -21
- package/src/entries/BadgeEntry.ts +0 -39
- package/src/entries/CodeEntry.test.ts +0 -40
- package/src/entries/CodeEntry.ts +0 -52
- package/src/entries/ColorEntry.ts +0 -63
- package/src/entries/ComponentEntry.test.ts +0 -173
- package/src/entries/ComponentEntry.ts +0 -95
- package/src/entries/Entry.ts +0 -304
- package/src/entries/IconEntry.ts +0 -49
- package/src/entries/ImageEntry.ts +0 -61
- package/src/entries/KeyValueEntry.ts +0 -47
- package/src/entries/RepeatableEntry.test.ts +0 -239
- package/src/entries/RepeatableEntry.ts +0 -173
- package/src/entries/TextEntry.test.ts +0 -394
- package/src/entries/TextEntry.ts +0 -60
- package/src/entries/index.ts +0 -12
- package/src/entries/leaves.test.ts +0 -306
- package/src/entries/registry.ts +0 -54
- package/src/fields/BuilderField.test.ts +0 -1188
- package/src/fields/BuilderField.ts +0 -605
- package/src/fields/BuilderRelationship.test.ts +0 -811
- package/src/fields/CheckboxField.test.ts +0 -44
- package/src/fields/CheckboxField.ts +0 -27
- package/src/fields/CheckboxListField.test.ts +0 -99
- package/src/fields/CheckboxListField.ts +0 -66
- package/src/fields/ColorPickerField.test.ts +0 -33
- package/src/fields/ColorPickerField.ts +0 -25
- package/src/fields/DateField.ts +0 -54
- package/src/fields/DateTimeField.test.ts +0 -55
- package/src/fields/EmailField.ts +0 -16
- package/src/fields/Field.test.ts +0 -654
- package/src/fields/Field.ts +0 -817
- package/src/fields/FileUploadField.test.ts +0 -143
- package/src/fields/FileUploadField.ts +0 -159
- package/src/fields/HiddenField.test.ts +0 -27
- package/src/fields/HiddenField.ts +0 -28
- package/src/fields/KeyValueField.test.ts +0 -105
- package/src/fields/KeyValueField.ts +0 -55
- package/src/fields/MarkdownField.test.ts +0 -167
- package/src/fields/MarkdownField.ts +0 -162
- package/src/fields/NumberField.ts +0 -33
- package/src/fields/RadioField.test.ts +0 -94
- package/src/fields/RadioField.ts +0 -67
- package/src/fields/RepeaterField.test.ts +0 -1806
- package/src/fields/RepeaterField.ts +0 -939
- package/src/fields/RepeaterRelationship.test.ts +0 -1923
- package/src/fields/RepeaterSimple.test.ts +0 -248
- package/src/fields/RowButton.test.ts +0 -219
- package/src/fields/RowButton.ts +0 -135
- package/src/fields/SelectField.test.ts +0 -192
- package/src/fields/SelectField.ts +0 -235
- package/src/fields/SliderField.test.ts +0 -50
- package/src/fields/SliderField.ts +0 -53
- package/src/fields/SlugField.ts +0 -24
- package/src/fields/TagsInputField.test.ts +0 -154
- package/src/fields/TagsInputField.ts +0 -133
- package/src/fields/TextField.test.ts +0 -213
- package/src/fields/TextField.ts +0 -177
- package/src/fields/TextareaField.test.ts +0 -58
- package/src/fields/TextareaField.ts +0 -59
- package/src/fields/ToggleButtonsField.test.ts +0 -106
- package/src/fields/ToggleButtonsField.ts +0 -59
- package/src/fields/ToggleField.ts +0 -16
- package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
- package/src/fields/optionsResolver.ts +0 -95
- package/src/fields/resolveField.ts +0 -28
- package/src/filters/BooleanFilter.ts +0 -35
- package/src/filters/DateRangeFilter.test.ts +0 -194
- package/src/filters/DateRangeFilter.ts +0 -148
- package/src/filters/Filter.test.ts +0 -268
- package/src/filters/Filter.ts +0 -184
- package/src/filters/FormFilter.test.ts +0 -238
- package/src/filters/FormFilter.ts +0 -215
- package/src/filters/MultiSelectFilter.test.ts +0 -119
- package/src/filters/MultiSelectFilter.ts +0 -78
- package/src/filters/QueryBuilderFilter.test.ts +0 -662
- package/src/filters/QueryBuilderFilter.ts +0 -398
- package/src/filters/SelectFilter.ts +0 -46
- package/src/filters/TernaryFilter.test.ts +0 -160
- package/src/filters/TernaryFilter.ts +0 -72
- package/src/filters/TrashedFilter.test.ts +0 -149
- package/src/filters/TrashedFilter.ts +0 -55
- package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
- package/src/filters/queryBuilder/Constraint.ts +0 -115
- package/src/filters/queryBuilder/DateConstraint.ts +0 -69
- package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
- package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
- package/src/filters/queryBuilder/TextConstraint.ts +0 -64
- package/src/filters/queryBuilder/index.ts +0 -12
- package/src/icons/index.ts +0 -2
- package/src/icons/lucide.ts +0 -204
- package/src/icons/registry.test.ts +0 -56
- package/src/icons/registry.ts +0 -41
- package/src/icons/types.ts +0 -47
- package/src/index.ts +0 -525
- package/src/io/csv.test.ts +0 -142
- package/src/io/csv.ts +0 -170
- package/src/nestedRelationManagerData.test.ts +0 -547
- package/src/notifications/Notification.test.ts +0 -210
- package/src/notifications/Notification.ts +0 -354
- package/src/notifications/broadcast.test.ts +0 -110
- package/src/notifications/broadcast.ts +0 -95
- package/src/notifications/database.test.ts +0 -383
- package/src/notifications/database.ts +0 -398
- package/src/notifications/databaseNotifications.test.ts +0 -187
- package/src/notifications/dispatchNotificationAction.test.ts +0 -341
- package/src/notifications/dispatchNotificationAction.ts +0 -142
- package/src/notifications/flash.test.ts +0 -89
- package/src/notifications/flash.ts +0 -71
- package/src/notifications/index.ts +0 -45
- package/src/notifications/registerBroadcastAuth.test.ts +0 -134
- package/src/notifications/registerBroadcastAuth.ts +0 -100
- package/src/notifications/resolveSavedNotification.test.ts +0 -82
- package/src/notifications/resolveSavedNotification.ts +0 -59
- package/src/notifications/types.ts +0 -93
- package/src/orm/m2mAccessor.ts +0 -66
- package/src/orm/modelDefaults.test.ts +0 -633
- package/src/orm/modelDefaults.ts +0 -666
- package/src/pageData/breadcrumbs.ts +0 -288
- package/src/pageData/forms.ts +0 -578
- package/src/pageData/helpers.ts +0 -857
- package/src/pageData/misc.ts +0 -347
- package/src/pageData/navigation.ts +0 -842
- package/src/pageData/relationPages.ts +0 -1248
- package/src/pageData/relationTabs.ts +0 -286
- package/src/pageData/resourcePages.ts +0 -609
- package/src/pageData.test.ts +0 -1545
- package/src/pageData.ts +0 -341
- package/src/plugins/index.ts +0 -8
- package/src/plugins/themeEditor.test.ts +0 -36
- package/src/plugins/themeEditor.ts +0 -45
- package/src/react/AppShell.tsx +0 -251
- package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
- package/src/react/CollabRoomContext.ts +0 -98
- package/src/react/CollabTextRendererRegistry.ts +0 -102
- package/src/react/CommandPalette.tsx +0 -375
- package/src/react/CurrentUserContext.tsx +0 -50
- package/src/react/CustomPageWrapperGate.tsx +0 -69
- package/src/react/CustomPageWrapperRegistry.ts +0 -45
- package/src/react/FieldFocusReporterRegistry.ts +0 -37
- package/src/react/FieldLabelSlotRegistry.ts +0 -30
- package/src/react/FieldPresenceRegistry.ts +0 -46
- package/src/react/FormCollabBindingRegistry.ts +0 -242
- package/src/react/FormStateContext.tsx +0 -591
- package/src/react/HeadHooks.tsx +0 -126
- package/src/react/MarkdownEditorRegistry.test.ts +0 -38
- package/src/react/MarkdownEditorRegistry.ts +0 -107
- package/src/react/NotificationActionStrip.tsx +0 -263
- package/src/react/NotificationBell.tsx +0 -426
- package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
- package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
- package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
- package/src/react/PendingSuggestionsContext.tsx +0 -172
- package/src/react/RecordWrapperGate.tsx +0 -58
- package/src/react/RecordWrapperRegistry.ts +0 -39
- package/src/react/RenderHookSlot.tsx +0 -32
- package/src/react/RightSidebar.tsx +0 -257
- package/src/react/RightSidebarContext.tsx +0 -234
- package/src/react/RightSidebarTrigger.tsx +0 -53
- package/src/react/RowCoordsContext.tsx +0 -23
- package/src/react/SchemaRenderer.tsx +0 -549
- package/src/react/SearchTrigger.tsx +0 -46
- package/src/react/ThemeProvider.tsx +0 -93
- package/src/react/ThemeSettingsPage.tsx +0 -579
- package/src/react/ThemeToggle.tsx +0 -20
- package/src/react/Toaster.tsx +0 -158
- package/src/react/UserMenu.tsx +0 -196
- package/src/react/WidgetDataContext.tsx +0 -157
- package/src/react/cells/EditableCell.tsx +0 -389
- package/src/react/component-slots.test.ts +0 -103
- package/src/react/component-slots.ts +0 -116
- package/src/react/fieldJsHandler.test.ts +0 -166
- package/src/react/fieldJsHandler.ts +0 -79
- package/src/react/fields/BuilderInput.tsx +0 -1078
- package/src/react/fields/CheckboxInput.tsx +0 -39
- package/src/react/fields/CheckboxListInput.tsx +0 -102
- package/src/react/fields/ColorInput.tsx +0 -71
- package/src/react/fields/DateFieldInput.tsx +0 -70
- package/src/react/fields/DateTimeInput.tsx +0 -62
- package/src/react/fields/FieldShell.tsx +0 -348
- package/src/react/fields/FileUploadInput.tsx +0 -639
- package/src/react/fields/HiddenInput.tsx +0 -17
- package/src/react/fields/KeyValueInput.tsx +0 -230
- package/src/react/fields/MarkdownInput.tsx +0 -560
- package/src/react/fields/RadioInput.tsx +0 -81
- package/src/react/fields/RepeaterInput.test.ts +0 -116
- package/src/react/fields/RepeaterInput.tsx +0 -1420
- package/src/react/fields/SelectFieldInput.tsx +0 -280
- package/src/react/fields/SliderInput.tsx +0 -81
- package/src/react/fields/TagsInput.tsx +0 -283
- package/src/react/fields/TextLikeInput.tsx +0 -256
- package/src/react/fields/ToggleButtonsInput.tsx +0 -60
- package/src/react/fields/ToggleFieldInput.tsx +0 -56
- package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
- package/src/react/fields/relationshipRenameDispatch.ts +0 -97
- package/src/react/fields/repeaterReconcile.test.ts +0 -114
- package/src/react/fields/repeaterReconcile.ts +0 -104
- package/src/react/fields/rowChromeButton.tsx +0 -336
- package/src/react/fields/rowState.ts +0 -106
- package/src/react/fields/syncRowGates.test.ts +0 -202
- package/src/react/fields/syncRowGates.ts +0 -66
- package/src/react/fields/textInputControls.tsx +0 -238
- package/src/react/fields/useRowReorderDnd.ts +0 -78
- package/src/react/formStateHelpers.test.ts +0 -508
- package/src/react/formStateHelpers.ts +0 -381
- package/src/react/hooks/use-mobile.ts +0 -19
- package/src/react/icon-context.tsx +0 -60
- package/src/react/index.ts +0 -195
- package/src/react/layouts/SidebarLayout.tsx +0 -250
- package/src/react/layouts/TopbarLayout.tsx +0 -258
- package/src/react/navigate.tsx +0 -37
- package/src/react/onProviderSynced.test.ts +0 -90
- package/src/react/parseRecordEditUrl.test.ts +0 -122
- package/src/react/parseRecordEditUrl.ts +0 -94
- package/src/react/persistedState.ts +0 -40
- package/src/react/registry.ts +0 -48
- package/src/react/right-panel-registry.tsx +0 -47
- package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
- package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
- package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
- package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
- package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
- package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
- package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
- package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
- package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
- package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
- package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
- package/src/react/schemaRenderer/action/buttons.tsx +0 -99
- package/src/react/schemaRenderer/action/helpers.ts +0 -140
- package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
- package/src/react/schemaRenderer/columnFormat.ts +0 -65
- package/src/react/schemaRenderer/constants.ts +0 -50
- package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
- package/src/react/schemaRenderer/form/renderField.tsx +0 -511
- package/src/react/schemaRenderer/helpers.tsx +0 -81
- package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
- package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
- package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
- package/src/react/schemaRenderer/table/filters.tsx +0 -1233
- package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
- package/src/react/schemaRenderer/table/links.tsx +0 -112
- package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
- package/src/react/schemaRenderer/table/url.tsx +0 -143
- package/src/react/theme-preview/apply.ts +0 -99
- package/src/react/theme-preview/build-html.ts +0 -436
- package/src/react/ui/button.tsx +0 -51
- package/src/react/ui/calendar.tsx +0 -67
- package/src/react/ui/checkbox.tsx +0 -29
- package/src/react/ui/dialog.tsx +0 -108
- package/src/react/ui/dropdown-menu.tsx +0 -97
- package/src/react/ui/input.tsx +0 -20
- package/src/react/ui/label.tsx +0 -21
- package/src/react/ui/popover.tsx +0 -50
- package/src/react/ui/select.tsx +0 -169
- package/src/react/ui/separator.tsx +0 -25
- package/src/react/ui/sheet.tsx +0 -136
- package/src/react/ui/sidebar.tsx +0 -723
- package/src/react/ui/skeleton.tsx +0 -13
- package/src/react/ui/slider.tsx +0 -34
- package/src/react/ui/switch.tsx +0 -28
- package/src/react/ui/table.tsx +0 -105
- package/src/react/ui/tabs.tsx +0 -63
- package/src/react/ui/textarea.tsx +0 -18
- package/src/react/ui/tooltip.tsx +0 -64
- package/src/react/useCollabSeed.ts +0 -86
- package/src/react/useResizableWidth.ts +0 -139
- package/src/react/utils.ts +0 -6
- package/src/react/widgetRegistry.test.ts +0 -43
- package/src/react/widgetRegistry.ts +0 -50
- package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
- package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
- package/src/react/widgets/ViewRenderer.tsx +0 -71
- package/src/relationManagerData.test.ts +0 -1595
- package/src/richtext/index.ts +0 -8
- package/src/richtext/registry.ts +0 -89
- package/src/routes/globals.ts +0 -148
- package/src/routes/guard.test.ts +0 -325
- package/src/routes/helpers.ts +0 -700
- package/src/routes/pages.ts +0 -175
- package/src/routes/panel.ts +0 -204
- package/src/routes/relations.ts +0 -1227
- package/src/routes/resources.ts +0 -781
- package/src/routes/theme.ts +0 -91
- package/src/routes-nested-relations.test.ts +0 -676
- package/src/routes-relations.test.ts +0 -972
- package/src/routes.test.ts +0 -2027
- package/src/routes.ts +0 -303
- package/src/schema/Alert.test.ts +0 -109
- package/src/schema/Alert.ts +0 -131
- package/src/schema/Block.ts +0 -169
- package/src/schema/Breadcrumbs.ts +0 -40
- package/src/schema/Card.ts +0 -35
- package/src/schema/Divider.ts +0 -20
- package/src/schema/Element.ts +0 -219
- package/src/schema/EmptyState.test.ts +0 -37
- package/src/schema/EmptyState.ts +0 -63
- package/src/schema/Fieldset.ts +0 -43
- package/src/schema/Grid.ts +0 -43
- package/src/schema/Group.ts +0 -30
- package/src/schema/Heading.ts +0 -39
- package/src/schema/Html.ts +0 -67
- package/src/schema/Icon.ts +0 -54
- package/src/schema/Image.ts +0 -57
- package/src/schema/LinkTag.ts +0 -41
- package/src/schema/Markdown.ts +0 -85
- package/src/schema/MetaTag.ts +0 -41
- package/src/schema/RelationTabs.ts +0 -71
- package/src/schema/ScriptTag.ts +0 -55
- package/src/schema/Section.ts +0 -160
- package/src/schema/ServerDataElement.test.ts +0 -140
- package/src/schema/ServerDataElement.ts +0 -156
- package/src/schema/SlotComponent.test.ts +0 -77
- package/src/schema/SlotComponent.ts +0 -71
- package/src/schema/Split.ts +0 -50
- package/src/schema/Stat.test.ts +0 -118
- package/src/schema/Stat.ts +0 -154
- package/src/schema/StatsOverview.test.ts +0 -141
- package/src/schema/StatsOverview.ts +0 -119
- package/src/schema/StyleTag.ts +0 -35
- package/src/schema/TableWidget.test.ts +0 -297
- package/src/schema/TableWidget.ts +0 -289
- package/src/schema/Tabs.ts +0 -79
- package/src/schema/Text.ts +0 -58
- package/src/schema/UnorderedList.ts +0 -49
- package/src/schema/View.test.ts +0 -111
- package/src/schema/View.ts +0 -127
- package/src/schema/Wizard.ts +0 -220
- package/src/schema/containers.test.ts +0 -564
- package/src/schema/headTags.test.ts +0 -134
- package/src/schema/index.ts +0 -40
- package/src/schema/primes.test.ts +0 -269
- package/src/schema/resolveSchema.test.ts +0 -379
- package/src/schema/resolveSchema.ts +0 -917
- package/src/schema/sanitize.ts +0 -58
- package/src/search.test.ts +0 -446
- package/src/search.ts +0 -178
- package/src/sessionFilters.test.ts +0 -375
- package/src/sessionFilters.ts +0 -143
- package/src/slot-components/index.ts +0 -10
- package/src/slot-components/registry.ts +0 -56
- package/src/styles/file-upload.css +0 -13
- package/src/summarizers/Summarizer.test.ts +0 -84
- package/src/summarizers/Summarizer.ts +0 -123
- package/src/summarizers/index.ts +0 -11
- package/src/theme/base-colors.ts +0 -68
- package/src/theme/chart-colors.ts +0 -50
- package/src/theme/colors.ts +0 -447
- package/src/theme/generate-css.test.ts +0 -139
- package/src/theme/generate-css.ts +0 -44
- package/src/theme/generate-scale.test.ts +0 -106
- package/src/theme/generate-scale.ts +0 -97
- package/src/theme/icon-map.ts +0 -42
- package/src/theme/index.ts +0 -34
- package/src/theme/migrate.test.ts +0 -178
- package/src/theme/migrate.ts +0 -81
- package/src/theme/presets.ts +0 -135
- package/src/theme/radius.ts +0 -18
- package/src/theme/resolve.test.ts +0 -238
- package/src/theme/resolve.ts +0 -96
- package/src/theme/spacing.ts +0 -18
- package/src/theme/storage.test.ts +0 -126
- package/src/theme/storage.ts +0 -106
- package/src/theme/theme-colors.ts +0 -88
- package/src/theme/types.ts +0 -125
- package/src/uploads/UploadAdapter.ts +0 -35
- package/src/uploads/index.ts +0 -2
- package/src/uploads/localUpload.test.ts +0 -70
- package/src/uploads/localUpload.ts +0 -84
- package/src/validation/Validator.ts +0 -49
- package/src/validation/index.ts +0 -28
- package/src/validation/rules.ts +0 -78
- package/src/validation/runValidators.ts +0 -435
- package/src/validation/uniqueValidator.test.ts +0 -196
- package/src/validation/uniqueValidator.ts +0 -133
- package/src/validation/validators.test.ts +0 -268
- package/src/vite.test.ts +0 -184
- package/src/vite.ts +0 -787
- package/src/widgets/index.ts +0 -10
- package/src/widgets/registry.ts +0 -45
- package/src/widgets.test.ts +0 -592
- package/tsconfig.build.json +0 -11
- package/tsconfig.json +0 -4
- package/tsconfig.test.json +0 -10
- package/views/react/Dashboard.tsx +0 -27
- package/views/react/Resources/Form.tsx +0 -102
- package/views/react/Resources/Index.tsx +0 -49
package/src/pageData.ts
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-page-role data builders. The framework's GET route handlers and
|
|
3
|
-
* Vike's auto-generated `+data.ts` hooks both call these to produce the
|
|
4
|
-
* exact props the page renderer needs.
|
|
5
|
-
*
|
|
6
|
-
* Why this exists: SSR runs through the rudder router (which calls
|
|
7
|
-
* `view(...)` and populates `pageContext.viewProps`). SPA navigation only
|
|
8
|
-
* triggers Vike's `+data` hook — the rudder handler doesn't run, so the
|
|
9
|
-
* data needs to come from the same builder. Routing both paths through a
|
|
10
|
-
* single builder keeps them in sync.
|
|
11
|
-
*/
|
|
12
|
-
import { PilotiqRegistry } from './PilotiqRegistry.js'
|
|
13
|
-
|
|
14
|
-
// Re-export `RelationChainStep` so external callsites importing it via
|
|
15
|
-
// `./pageData.js` keep working.
|
|
16
|
-
export type { RelationChainStep } from './pageData/breadcrumbs.js'
|
|
17
|
-
|
|
18
|
-
// Re-export `ServerDataMap` so external imports via `./pageData.js` keep
|
|
19
|
-
// working — the type is also surfaced from `packages/pilotiq/src/index.ts`.
|
|
20
|
-
export type { ServerDataMap } from './pageData/helpers.js'
|
|
21
|
-
|
|
22
|
-
// Re-export the URL-tag helpers + fill pipeline + server-data resolver
|
|
23
|
-
// for consumers that import them through `./pageData.js`.
|
|
24
|
-
export {
|
|
25
|
-
applyEditPageHydrators,
|
|
26
|
-
applyFillPipeline,
|
|
27
|
-
applyRelationshipBuilderFill,
|
|
28
|
-
applyRelationshipRepeaterFill,
|
|
29
|
-
callPageSchema,
|
|
30
|
-
normalizeArrayFieldStrings,
|
|
31
|
-
resolveServerDataElements,
|
|
32
|
-
tagActionDispatch,
|
|
33
|
-
tagCellEditUrls,
|
|
34
|
-
tagFieldAiUrls,
|
|
35
|
-
tagFormActions,
|
|
36
|
-
tagFormStateUrls,
|
|
37
|
-
tagFormWizardUrls,
|
|
38
|
-
tagRichTextMentionUrls,
|
|
39
|
-
tagSelectCreateOptionUrls,
|
|
40
|
-
tagTableDeferred,
|
|
41
|
-
tagTableReorderUrls,
|
|
42
|
-
tagWidgetUrls,
|
|
43
|
-
} from './pageData/helpers.js'
|
|
44
|
-
|
|
45
|
-
// Re-export navigation chrome surface so external callsites importing
|
|
46
|
-
// it via `./pageData.js` keep working (e.g. routes/test harnesses).
|
|
47
|
-
export type {
|
|
48
|
-
DatabaseNotificationsMeta,
|
|
49
|
-
NavItem,
|
|
50
|
-
PanelInfoRoute,
|
|
51
|
-
RightPanelMeta,
|
|
52
|
-
RightSidebarMeta,
|
|
53
|
-
UserMenuMeta,
|
|
54
|
-
} from './pageData/navigation.js'
|
|
55
|
-
export {
|
|
56
|
-
applyRoleHooks,
|
|
57
|
-
panelInfo,
|
|
58
|
-
resolvePageHooks,
|
|
59
|
-
} from './pageData/navigation.js'
|
|
60
|
-
|
|
61
|
-
import {
|
|
62
|
-
dashboardData,
|
|
63
|
-
resourceCreateData,
|
|
64
|
-
resourceEditData,
|
|
65
|
-
resourceIndexData,
|
|
66
|
-
resourceRecordPageData,
|
|
67
|
-
resourceViewData,
|
|
68
|
-
} from './pageData/resourcePages.js'
|
|
69
|
-
|
|
70
|
-
// Re-export resource page builders so external callsites importing
|
|
71
|
-
// through `./pageData.js` keep working (e.g. routes.ts handlers, tests).
|
|
72
|
-
export {
|
|
73
|
-
dashboardData,
|
|
74
|
-
resolveActiveTab,
|
|
75
|
-
resourceCreateData,
|
|
76
|
-
resourceEditData,
|
|
77
|
-
resourceIndexData,
|
|
78
|
-
resourceRecordPageData,
|
|
79
|
-
resourceTableData,
|
|
80
|
-
resourceViewData,
|
|
81
|
-
} from './pageData/resourcePages.js'
|
|
82
|
-
|
|
83
|
-
import { relationManagerData } from './pageData/relationPages.js'
|
|
84
|
-
|
|
85
|
-
// Re-export relation manager builder surface for external consumers
|
|
86
|
-
// (routes.ts dispatches every relation-* role through these).
|
|
87
|
-
export type {
|
|
88
|
-
RelationManagerResult,
|
|
89
|
-
RelationManagerScope,
|
|
90
|
-
ResolvedChain,
|
|
91
|
-
} from './pageData/relationPages.js'
|
|
92
|
-
export {
|
|
93
|
-
findRelatedResource,
|
|
94
|
-
relationManagerData,
|
|
95
|
-
resolveRelationChain,
|
|
96
|
-
safeManagerPolicy,
|
|
97
|
-
} from './pageData/relationPages.js'
|
|
98
|
-
|
|
99
|
-
// Re-export form-related builders + types for external callsites.
|
|
100
|
-
export type {
|
|
101
|
-
FormCreateOptionFailure,
|
|
102
|
-
FormCreateOptionRequest,
|
|
103
|
-
FormCreateOptionSuccess,
|
|
104
|
-
FormStateError,
|
|
105
|
-
FormStateRequest,
|
|
106
|
-
FormStateResult,
|
|
107
|
-
FormStateScope,
|
|
108
|
-
FormWizardFailure,
|
|
109
|
-
FormWizardRequest,
|
|
110
|
-
FormWizardSuccess,
|
|
111
|
-
} from './pageData/forms.js'
|
|
112
|
-
export {
|
|
113
|
-
formCreateOptionData,
|
|
114
|
-
formStateData,
|
|
115
|
-
formWizardData,
|
|
116
|
-
mentionResolveData,
|
|
117
|
-
} from './pageData/forms.js'
|
|
118
|
-
|
|
119
|
-
import {
|
|
120
|
-
customPageData,
|
|
121
|
-
globalEditData,
|
|
122
|
-
globalViewData,
|
|
123
|
-
} from './pageData/misc.js'
|
|
124
|
-
|
|
125
|
-
// Re-export the misc page builders for external callsites (routes.ts
|
|
126
|
-
// dispatches into globals / custom-page / widget / search routes).
|
|
127
|
-
export {
|
|
128
|
-
customPageData,
|
|
129
|
-
globalEditData,
|
|
130
|
-
globalViewData,
|
|
131
|
-
searchData,
|
|
132
|
-
widgetData,
|
|
133
|
-
} from './pageData/misc.js'
|
|
134
|
-
export type {
|
|
135
|
-
WidgetFailure,
|
|
136
|
-
WidgetRequest,
|
|
137
|
-
WidgetScope,
|
|
138
|
-
WidgetSuccess,
|
|
139
|
-
} from './pageData/misc.js'
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// ─── Vike +data dispatcher ───────────────────────────────────
|
|
143
|
-
|
|
144
|
-
export interface PageContextLike {
|
|
145
|
-
urlPathname?: string
|
|
146
|
-
urlOriginal?: string
|
|
147
|
-
urlParsed?: { search?: Record<string, string>; searchOriginal?: string }
|
|
148
|
-
routeParams?: Record<string, string | undefined>
|
|
149
|
-
pageId?: string
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Single entry point Vike's `+data` hook calls. Inspects the page id and
|
|
154
|
-
* route params, finds the panel via `PilotiqRegistry`, and dispatches to
|
|
155
|
-
* the matching builder. Returns the same shape SSR's `viewProps` carries.
|
|
156
|
-
*/
|
|
157
|
-
export async function dispatchPageData(pageContext: PageContextLike): Promise<unknown | null> {
|
|
158
|
-
const { pageId, routeParams = {} } = pageContext
|
|
159
|
-
const search = pageContext.urlParsed?.search ?? {}
|
|
160
|
-
const basePathParam = routeParams['basePath']
|
|
161
|
-
const basePath = basePathParam ? `/${basePathParam}` : ''
|
|
162
|
-
const panel = basePath ? PilotiqRegistry.findByPath(basePath) : null
|
|
163
|
-
|
|
164
|
-
if (!panel) return null
|
|
165
|
-
|
|
166
|
-
switch (pageId) {
|
|
167
|
-
case '/pages/(pilotiq)/dashboard':
|
|
168
|
-
return dashboardData(panel)
|
|
169
|
-
|
|
170
|
-
case '/pages/(pilotiq)/slug': {
|
|
171
|
-
// 2-segment URL: could be a resource list, a global edit, or a custom page.
|
|
172
|
-
const slug = routeParams['slug']
|
|
173
|
-
if (!slug) return null
|
|
174
|
-
const cfg = panel.getConfig()
|
|
175
|
-
if (cfg.resources.some(R => R.getSlug() === slug)) {
|
|
176
|
-
return resourceIndexData(panel, slug, search)
|
|
177
|
-
}
|
|
178
|
-
if (cfg.globals.some(G => G.getSlug() === slug)) {
|
|
179
|
-
return globalEditData(panel, slug)
|
|
180
|
-
}
|
|
181
|
-
return customPageData(panel, slug)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
case '/pages/(pilotiq)/resource-create': {
|
|
185
|
-
const slug = routeParams['slug']
|
|
186
|
-
if (!slug) return null
|
|
187
|
-
return resourceCreateData(panel, slug)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
case '/pages/(pilotiq)/resource-edit': {
|
|
191
|
-
const slug = routeParams['slug']
|
|
192
|
-
const id = routeParams['id']
|
|
193
|
-
if (!slug || !id) return null
|
|
194
|
-
return resourceEditData(panel, slug, id)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
case '/pages/(pilotiq)/resource-view': {
|
|
198
|
-
const slug = routeParams['slug']
|
|
199
|
-
const id = routeParams['id']
|
|
200
|
-
if (!slug) return null
|
|
201
|
-
// Globals also use this route under `/{slug}/view` — id will be 'view'.
|
|
202
|
-
if (id === 'view') return globalViewData(panel, slug)
|
|
203
|
-
if (!id) return null
|
|
204
|
-
return resourceViewData(panel, slug, id)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
case '/pages/(pilotiq)/relation-list': {
|
|
208
|
-
const slug = routeParams['slug']
|
|
209
|
-
const id = routeParams['id']
|
|
210
|
-
const relationship = routeParams['relationship']
|
|
211
|
-
if (!slug || !id || !relationship) return null
|
|
212
|
-
const out = await relationManagerData(panel, {
|
|
213
|
-
kind: 'relation-list', slug, recordId: id, relationship,
|
|
214
|
-
query: search as Record<string, string>,
|
|
215
|
-
})
|
|
216
|
-
// Tagged failure shapes (`{ ok: false, status: 403 }`) leak straight
|
|
217
|
-
// through to the +Page renderer, which can branch on the shape.
|
|
218
|
-
// null = no manager named `relationship` on R; fall through to the
|
|
219
|
-
// record sub-page lookup so URLs like `/admin/users/u1/activity`
|
|
220
|
-
// (where `activity` is registered under `pages().record`) route
|
|
221
|
-
// through `resourceRecordPageData` rather than 404ing.
|
|
222
|
-
if (out !== null) return out as Record<string, unknown>
|
|
223
|
-
const recordOut = await resourceRecordPageData(panel, slug, id, relationship)
|
|
224
|
-
return recordOut === null ? null : (recordOut as Record<string, unknown>)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
case '/pages/(pilotiq)/relation-create': {
|
|
228
|
-
const slug = routeParams['slug']
|
|
229
|
-
const id = routeParams['id']
|
|
230
|
-
const relationship = routeParams['relationship']
|
|
231
|
-
if (!slug || !id || !relationship) return null
|
|
232
|
-
const out = await relationManagerData(panel, {
|
|
233
|
-
kind: 'relation-create', slug, recordId: id, relationship,
|
|
234
|
-
})
|
|
235
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
case '/pages/(pilotiq)/relation-view': {
|
|
239
|
-
const slug = routeParams['slug']
|
|
240
|
-
const id = routeParams['id']
|
|
241
|
-
const relationship = routeParams['relationship']
|
|
242
|
-
const childId = routeParams['childId']
|
|
243
|
-
if (!slug || !id || !relationship || !childId) return null
|
|
244
|
-
const out = await relationManagerData(panel, {
|
|
245
|
-
kind: 'relation-view', slug, recordId: id, relationship, childId,
|
|
246
|
-
})
|
|
247
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
case '/pages/(pilotiq)/relation-edit': {
|
|
251
|
-
const slug = routeParams['slug']
|
|
252
|
-
const id = routeParams['id']
|
|
253
|
-
const relationship = routeParams['relationship']
|
|
254
|
-
const childId = routeParams['childId']
|
|
255
|
-
if (!slug || !id || !relationship || !childId) return null
|
|
256
|
-
const out = await relationManagerData(panel, {
|
|
257
|
-
kind: 'relation-edit', slug, recordId: id, relationship, childId,
|
|
258
|
-
})
|
|
259
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Phase B nested-relation routes. Param names match those declared
|
|
263
|
-
// by the auto-gen Vike stubs in `src/vite.ts`:
|
|
264
|
-
// id, relationship, childId1, relationship2, childId2.
|
|
265
|
-
case '/pages/(pilotiq)/nested-relation-list': {
|
|
266
|
-
const slug = routeParams['slug']
|
|
267
|
-
const id = routeParams['id']
|
|
268
|
-
const relationship = routeParams['relationship']
|
|
269
|
-
const childId1 = routeParams['childId1']
|
|
270
|
-
const relationship2 = routeParams['relationship2']
|
|
271
|
-
if (!slug || !id || !relationship || !childId1 || !relationship2) return null
|
|
272
|
-
const out = await relationManagerData(panel, {
|
|
273
|
-
kind: 'nested-relation-list', slug,
|
|
274
|
-
chain: [
|
|
275
|
-
{ recordId: id, relationship },
|
|
276
|
-
{ recordId: childId1, relationship: relationship2 },
|
|
277
|
-
],
|
|
278
|
-
query: search as Record<string, string>,
|
|
279
|
-
})
|
|
280
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
case '/pages/(pilotiq)/nested-relation-create': {
|
|
284
|
-
const slug = routeParams['slug']
|
|
285
|
-
const id = routeParams['id']
|
|
286
|
-
const relationship = routeParams['relationship']
|
|
287
|
-
const childId1 = routeParams['childId1']
|
|
288
|
-
const relationship2 = routeParams['relationship2']
|
|
289
|
-
if (!slug || !id || !relationship || !childId1 || !relationship2) return null
|
|
290
|
-
const out = await relationManagerData(panel, {
|
|
291
|
-
kind: 'nested-relation-create', slug,
|
|
292
|
-
chain: [
|
|
293
|
-
{ recordId: id, relationship },
|
|
294
|
-
{ recordId: childId1, relationship: relationship2 },
|
|
295
|
-
],
|
|
296
|
-
})
|
|
297
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
case '/pages/(pilotiq)/nested-relation-view': {
|
|
301
|
-
const slug = routeParams['slug']
|
|
302
|
-
const id = routeParams['id']
|
|
303
|
-
const relationship = routeParams['relationship']
|
|
304
|
-
const childId1 = routeParams['childId1']
|
|
305
|
-
const relationship2 = routeParams['relationship2']
|
|
306
|
-
const childId2 = routeParams['childId2']
|
|
307
|
-
if (!slug || !id || !relationship || !childId1 || !relationship2 || !childId2) return null
|
|
308
|
-
const out = await relationManagerData(panel, {
|
|
309
|
-
kind: 'nested-relation-view', slug,
|
|
310
|
-
chain: [
|
|
311
|
-
{ recordId: id, relationship },
|
|
312
|
-
{ recordId: childId1, relationship: relationship2 },
|
|
313
|
-
],
|
|
314
|
-
childId: childId2,
|
|
315
|
-
})
|
|
316
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
case '/pages/(pilotiq)/nested-relation-edit': {
|
|
320
|
-
const slug = routeParams['slug']
|
|
321
|
-
const id = routeParams['id']
|
|
322
|
-
const relationship = routeParams['relationship']
|
|
323
|
-
const childId1 = routeParams['childId1']
|
|
324
|
-
const relationship2 = routeParams['relationship2']
|
|
325
|
-
const childId2 = routeParams['childId2']
|
|
326
|
-
if (!slug || !id || !relationship || !childId1 || !relationship2 || !childId2) return null
|
|
327
|
-
const out = await relationManagerData(panel, {
|
|
328
|
-
kind: 'nested-relation-edit', slug,
|
|
329
|
-
chain: [
|
|
330
|
-
{ recordId: id, relationship },
|
|
331
|
-
{ recordId: childId1, relationship: relationship2 },
|
|
332
|
-
],
|
|
333
|
-
childId: childId2,
|
|
334
|
-
})
|
|
335
|
-
return out === null ? null : (out as Record<string, unknown>)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
default:
|
|
339
|
-
return null
|
|
340
|
-
}
|
|
341
|
-
}
|
package/src/plugins/index.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { themeEditor } from './themeEditor.js'
|
|
2
|
-
export type { ThemeEditorOptions } from './themeEditor.js'
|
|
3
|
-
export { prismaThemeStorage } from '../theme/storage.js'
|
|
4
|
-
export type {
|
|
5
|
-
ThemeStorageAdapter,
|
|
6
|
-
PanelGlobalDelegate,
|
|
7
|
-
PrismaThemeStorageOptions,
|
|
8
|
-
} from '../theme/storage.js'
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { Pilotiq } from '../Pilotiq.js'
|
|
4
|
-
import { themeEditor } from './themeEditor.js'
|
|
5
|
-
import type { ThemeStorageAdapter } from '../theme/storage.js'
|
|
6
|
-
|
|
7
|
-
function makeStubAdapter(): ThemeStorageAdapter {
|
|
8
|
-
return {
|
|
9
|
-
async load() { return null },
|
|
10
|
-
async save() { /* noop */ },
|
|
11
|
-
async clear() { /* noop */ },
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe('themeEditor() plugin', () => {
|
|
16
|
-
it('bare themeEditor() leaves the storage slot undefined (boot resolves it)', () => {
|
|
17
|
-
const panel = Pilotiq.make('admin').use(themeEditor())
|
|
18
|
-
assert.equal(panel.getConfig().themeEditor, true)
|
|
19
|
-
assert.equal(panel.getThemeStorage(), undefined)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('themeEditor({ storage }) stamps the adapter onto the panel', () => {
|
|
23
|
-
const adapter = makeStubAdapter()
|
|
24
|
-
const panel = Pilotiq.make('admin').use(themeEditor({ storage: adapter }))
|
|
25
|
-
assert.equal(panel.getThemeStorage(), adapter)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('themeEditor() can be called on multiple panels without leaking adapters', () => {
|
|
29
|
-
const a = makeStubAdapter()
|
|
30
|
-
const b = makeStubAdapter()
|
|
31
|
-
const panelA = Pilotiq.make('admin').use(themeEditor({ storage: a }))
|
|
32
|
-
const panelB = Pilotiq.make('billing').use(themeEditor({ storage: b }))
|
|
33
|
-
assert.equal(panelA.getThemeStorage(), a)
|
|
34
|
-
assert.equal(panelB.getThemeStorage(), b)
|
|
35
|
-
})
|
|
36
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { PilotiqPlugin } from '../Pilotiq.js'
|
|
2
|
-
import type { ThemeStorageAdapter } from '../theme/storage.js'
|
|
3
|
-
|
|
4
|
-
export interface ThemeEditorOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Override persistence adapter. Defaults to the implicit Prisma
|
|
7
|
-
* fallback (auto-resolved from `app.make('prisma')` against the
|
|
8
|
-
* `panelGlobal` row) — that fallback is deprecated; pass an explicit
|
|
9
|
-
* adapter to opt out and silence the deprecation warning.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* import { prismaThemeStorage, themeEditor } from '@pilotiq/pilotiq/plugins'
|
|
14
|
-
*
|
|
15
|
-
* .use(themeEditor({
|
|
16
|
-
* storage: prismaThemeStorage(prisma, { slug: 'admin__theme' }),
|
|
17
|
-
* }))
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
storage?: ThemeStorageAdapter
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Theme editor plugin — adds an interactive theme customization page
|
|
25
|
-
* with live preview, save/reset functionality, and DB persistence.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```ts
|
|
29
|
-
* import { Pilotiq } from '@pilotiq/pilotiq'
|
|
30
|
-
* import { themeEditor } from '@pilotiq/pilotiq/plugins'
|
|
31
|
-
*
|
|
32
|
-
* Pilotiq.make('Admin')
|
|
33
|
-
* .theme({ preset: 'vega', themeColor: 'blue' })
|
|
34
|
-
* .use(themeEditor())
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
export function themeEditor(opts: ThemeEditorOptions = {}): PilotiqPlugin {
|
|
38
|
-
return {
|
|
39
|
-
name: 'theme-editor',
|
|
40
|
-
register(panel) {
|
|
41
|
-
panel.enableThemeEditor()
|
|
42
|
-
if (opts.storage) panel._setThemeStorage(opts.storage)
|
|
43
|
-
},
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/react/AppShell.tsx
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import { SidebarLayout } from './layouts/SidebarLayout.js'
|
|
3
|
-
import { TopbarLayout } from './layouts/TopbarLayout.js'
|
|
4
|
-
import { ToasterProvider } from './Toaster.js'
|
|
5
|
-
import { CommandPalette, CommandPaletteProvider } from './CommandPalette.js'
|
|
6
|
-
import type { NotificationMeta } from '../notifications/Notification.js'
|
|
7
|
-
import type { ComponentRegistry } from './icon-context.js'
|
|
8
|
-
import { ComponentRegistryProvider } from './icon-context.js'
|
|
9
|
-
import type { RightPanelRegistry } from './right-panel-registry.js'
|
|
10
|
-
import { RightPanelRegistryProvider } from './right-panel-registry.js'
|
|
11
|
-
import { RightSidebarProvider, useRightSidebarOptional } from './RightSidebarContext.js'
|
|
12
|
-
import { RightSidebar } from './RightSidebar.js'
|
|
13
|
-
import { RecordWrapperGate, type RecordCollabMap } from './RecordWrapperGate.js'
|
|
14
|
-
import { CustomPageWrapperGate, type PageCollabMap } from './CustomPageWrapperGate.js'
|
|
15
|
-
import { useIsMobile } from './hooks/use-mobile.js'
|
|
16
|
-
import type { NavItem, UserMenuMeta, DatabaseNotificationsMeta, RightSidebarMeta } from '../pageData.js'
|
|
17
|
-
import type { RenderHookMap } from '../RenderHook.js'
|
|
18
|
-
import { RenderHookSlot } from './RenderHookSlot.js'
|
|
19
|
-
import type { ComponentSlotRegistry } from './component-slots.js'
|
|
20
|
-
import { CurrentUserProvider } from './CurrentUserContext.js'
|
|
21
|
-
|
|
22
|
-
export interface AppShellProps {
|
|
23
|
-
panel: {
|
|
24
|
-
name: string
|
|
25
|
-
branding: { title?: string; logo?: string }
|
|
26
|
-
/** Pre-grouped navigation tree built by `panelInfo()` (Plan #9). */
|
|
27
|
-
navigation?: NavItem[]
|
|
28
|
-
/** Top-right dropdown shape — `null`/absent suppresses the menu
|
|
29
|
-
* entirely (no resolver configured or no logged-in user). */
|
|
30
|
-
userMenu?: UserMenuMeta | null
|
|
31
|
-
/** Bell-icon dropdown config — absent suppresses the bell.
|
|
32
|
-
* `panelInfo()` only ships this when the panel opted in via
|
|
33
|
-
* `Pilotiq.databaseNotifications()` AND a user resolved. */
|
|
34
|
-
databaseNotifications?: DatabaseNotificationsMeta
|
|
35
|
-
/** Right-sidebar plugin meta — absent suppresses the surface.
|
|
36
|
-
* `panelInfo()` only ships this when at least one contribution
|
|
37
|
-
* was registered AND passed the auth gate AND is non-hidden. */
|
|
38
|
-
rightSidebar?: RightSidebarMeta
|
|
39
|
-
/** Per-resource collab opt-in map — read by `RecordWrapperGate` to
|
|
40
|
-
* decide whether to mount the plugin-registered RecordWrapper on
|
|
41
|
-
* a record edit/view URL. Absent when no resource opted in. */
|
|
42
|
-
recordCollab?: RecordCollabMap
|
|
43
|
-
/** Per-custom-page collab opt-in map — read by `CustomPageWrapperGate`
|
|
44
|
-
* to decide whether to mount the plugin-registered CustomPageWrapper
|
|
45
|
-
* on a custom-page URL. Absent when no page opted in. */
|
|
46
|
-
pageCollab?: PageCollabMap
|
|
47
|
-
/** Pre-resolved render-hook slots for the panel chrome (body /
|
|
48
|
-
* topbar / sidebar / user-menu / footer / head). Sparse map —
|
|
49
|
-
* slots with no registered entries are absent. Built by
|
|
50
|
-
* `panelInfo()` server-side. */
|
|
51
|
-
renderHooks?: RenderHookMap
|
|
52
|
-
themeEditor?: boolean
|
|
53
|
-
/** AI suggestion mode — absent means `'auto'` (the default). When
|
|
54
|
-
* set to `'review'`, AI plugins read this and stage writes as
|
|
55
|
-
* `PendingSuggestion`s for user approval instead of applying
|
|
56
|
-
* immediately. Plan: `docs/plans/ai-review-mode.md`. */
|
|
57
|
-
aiSuggestionsMode?: 'auto' | 'review'
|
|
58
|
-
}
|
|
59
|
-
basePath: string
|
|
60
|
-
/** Pathname used to compute active-link state in the sidebar/topbar. */
|
|
61
|
-
currentPath?: string
|
|
62
|
-
layout?: 'sidebar' | 'topbar'
|
|
63
|
-
/** Server-flashed notifications from `viewProps.notifications`. The
|
|
64
|
-
* Toaster mounts them on first render. */
|
|
65
|
-
notifications?: NotificationMeta[]
|
|
66
|
-
/** Build-time class manifest emitted by the Pilotiq Vite plugin
|
|
67
|
-
* (`pages/(pilotiq)/_components.ts`). Maps Resource/Global/Page class
|
|
68
|
-
* names to the actual class refs so component-typed icons (e.g.,
|
|
69
|
-
* `Resource.icon = Newspaper`) render. Optional — when missing, only
|
|
70
|
-
* string-registry icons resolve. */
|
|
71
|
-
componentRegistry?: ComponentRegistry
|
|
72
|
-
/**
|
|
73
|
-
* Build-time right-panel registry from the Vite plugin. Maps each
|
|
74
|
-
* `RightPanelContribution.id` to the React component supplied as
|
|
75
|
-
* `render`. Phase C's `RightSidebar` chrome reads this via
|
|
76
|
-
* `useRightPanelComponent(id)`. Sparse `{}` is a valid value — the
|
|
77
|
-
* chrome simply doesn't mount.
|
|
78
|
-
*/
|
|
79
|
-
rightPanelRegistry?: RightPanelRegistry
|
|
80
|
-
/**
|
|
81
|
-
* Build-time layout-provider registry from the Vite plugin. Each entry
|
|
82
|
-
* is a React component that wraps the panel's layout tree at the
|
|
83
|
-
* root. Plugins register via `Pilotiq.layoutProvider(C)`; the Vite
|
|
84
|
-
* plugin harvests refs into this array. Empty `[]` is the no-op
|
|
85
|
-
* default — chrome renders without any extra wrapping.
|
|
86
|
-
*/
|
|
87
|
-
layoutProviderRegistry?: ReadonlyArray<React.ComponentType<{ children: React.ReactNode; basePath?: string }>>
|
|
88
|
-
/**
|
|
89
|
-
* Build-time chrome-slot overrides from the Vite plugin. Populated
|
|
90
|
-
* when the panel module calls `Pilotiq.components({ nav, … })`.
|
|
91
|
-
* Sparse `{}` is the no-op default. Currently only `nav` is honored;
|
|
92
|
-
* additional slots will land as concrete consumers ask.
|
|
93
|
-
*/
|
|
94
|
-
componentSlotRegistry?: ComponentSlotRegistry
|
|
95
|
-
children: React.ReactNode
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function AppShell({ layout = 'sidebar', notifications, componentRegistry, rightPanelRegistry, layoutProviderRegistry, ...props }: AppShellProps) {
|
|
99
|
-
const Layout = layout === 'topbar' ? TopbarLayout : SidebarLayout
|
|
100
|
-
// exactOptionalPropertyTypes: only spread `initialNotifications` when set.
|
|
101
|
-
const toasterProps = notifications ? { initialNotifications: notifications } : {}
|
|
102
|
-
|
|
103
|
-
// Stamp the panel-wide AI suggestion mode on a window global so the
|
|
104
|
-
// AI plugin's `update_form_state` client-tool handler can read it
|
|
105
|
-
// without context plumbing. Singleton flag — doesn't change between
|
|
106
|
-
// pages within the same panel. Plan: `docs/plans/ai-review-mode.md`.
|
|
107
|
-
const aiSuggestionsMode = props.panel.aiSuggestionsMode ?? 'auto'
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
if (typeof window === 'undefined') return
|
|
110
|
-
;(window as unknown as { __pilotiqAiSuggestionsMode?: 'auto' | 'review' }).__pilotiqAiSuggestionsMode = aiSuggestionsMode
|
|
111
|
-
}, [aiSuggestionsMode])
|
|
112
|
-
|
|
113
|
-
// Plan #12 — palette open state lives at AppShell so the trigger pill
|
|
114
|
-
// (rendered inside the layout's header) and the palette dialog both
|
|
115
|
-
// observe the same flag via context.
|
|
116
|
-
const [paletteOpen, setPaletteOpen] = useState(false)
|
|
117
|
-
const paletteProps: {
|
|
118
|
-
basePath: string
|
|
119
|
-
navigation?: NavItem[]
|
|
120
|
-
open: boolean
|
|
121
|
-
onOpenChange: (open: boolean) => void
|
|
122
|
-
} = {
|
|
123
|
-
basePath: props.basePath,
|
|
124
|
-
open: paletteOpen,
|
|
125
|
-
onOpenChange: setPaletteOpen,
|
|
126
|
-
}
|
|
127
|
-
if (props.panel.navigation) paletteProps.navigation = props.panel.navigation
|
|
128
|
-
|
|
129
|
-
const hooks = props.panel.renderHooks
|
|
130
|
-
const rightSidebarMeta = props.panel.rightSidebar
|
|
131
|
-
|
|
132
|
-
// Record-scoped wrapper (collab room, audit trail, …) — pass-through
|
|
133
|
-
// when no plugin registered a wrapper or when the URL isn't a
|
|
134
|
-
// record-edit page. Wrapping `children` before forwarding to `Layout`
|
|
135
|
-
// mounts the wrapper around the page content area only, leaving the
|
|
136
|
-
// sidebar / topbar chrome outside.
|
|
137
|
-
const layoutProps = {
|
|
138
|
-
...props,
|
|
139
|
-
children: (
|
|
140
|
-
<RecordWrapperGate
|
|
141
|
-
basePath={props.basePath}
|
|
142
|
-
{...(props.currentPath !== undefined ? { currentPath: props.currentPath } : {})}
|
|
143
|
-
{...(props.panel.recordCollab !== undefined ? { recordCollab: props.panel.recordCollab } : {})}
|
|
144
|
-
>
|
|
145
|
-
<CustomPageWrapperGate
|
|
146
|
-
basePath={props.basePath}
|
|
147
|
-
{...(props.currentPath !== undefined ? { currentPath: props.currentPath } : {})}
|
|
148
|
-
{...(props.panel.pageCollab !== undefined ? { pageCollab: props.panel.pageCollab } : {})}
|
|
149
|
-
>
|
|
150
|
-
{props.children}
|
|
151
|
-
</CustomPageWrapperGate>
|
|
152
|
-
</RecordWrapperGate>
|
|
153
|
-
),
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const inner = (
|
|
157
|
-
<ToasterProvider {...toasterProps}>
|
|
158
|
-
<CommandPaletteProvider setOpen={setPaletteOpen}>
|
|
159
|
-
<RenderHookSlot name="panels::body.start" hooks={hooks} />
|
|
160
|
-
<RightSidebarLayoutFrame>
|
|
161
|
-
<Layout {...layoutProps} />
|
|
162
|
-
</RightSidebarLayoutFrame>
|
|
163
|
-
<RenderHookSlot name="panels::body.end" hooks={hooks} />
|
|
164
|
-
<CommandPalette {...paletteProps} />
|
|
165
|
-
{rightSidebarMeta && (
|
|
166
|
-
<RightSidebar
|
|
167
|
-
basePath={props.basePath}
|
|
168
|
-
{...(props.currentPath !== undefined ? { currentPath: props.currentPath } : {})}
|
|
169
|
-
/>
|
|
170
|
-
)}
|
|
171
|
-
</CommandPaletteProvider>
|
|
172
|
-
</ToasterProvider>
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
// Plugin-registered layout providers (e.g. AI chat queue, tenant
|
|
176
|
-
// theme switcher). Wraps in registration order: the FIRST registered
|
|
177
|
-
// provider sits OUTERMOST (closest to the layout root); LAST sits
|
|
178
|
-
// INNERMOST (closest to the page tree). Empty / unset → no wrap.
|
|
179
|
-
const wrapped = wrapInLayoutProviders(
|
|
180
|
-
<ComponentRegistryProvider value={componentRegistry}>
|
|
181
|
-
<RightPanelRegistryProvider value={rightPanelRegistry}>
|
|
182
|
-
{rightSidebarMeta ? (
|
|
183
|
-
<RightSidebarProvider meta={rightSidebarMeta} basePath={props.basePath}>
|
|
184
|
-
{inner}
|
|
185
|
-
</RightSidebarProvider>
|
|
186
|
-
) : (
|
|
187
|
-
inner
|
|
188
|
-
)}
|
|
189
|
-
</RightPanelRegistryProvider>
|
|
190
|
-
</ComponentRegistryProvider>,
|
|
191
|
-
layoutProviderRegistry,
|
|
192
|
-
props.basePath,
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
// `CurrentUserProvider` sits OUTSIDE the layout-provider chain so
|
|
196
|
-
// plugin-registered providers (e.g. `@pilotiq-pro/collab`'s
|
|
197
|
-
// CollabProvider, which threads the user into CollaborationCaret
|
|
198
|
-
// presence labels) can read the active user via `useCurrentUser()`.
|
|
199
|
-
// Value source mirrors what the top-right user dropdown renders.
|
|
200
|
-
return (
|
|
201
|
-
<CurrentUserProvider value={props.panel.userMenu?.user ?? null}>
|
|
202
|
-
{wrapped}
|
|
203
|
-
</CurrentUserProvider>
|
|
204
|
-
)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Fold registered layout providers around `tree` from last to first so
|
|
209
|
-
* the first-registered provider ends up outermost in the React tree
|
|
210
|
-
* (closest to the layout root) — matches the registration-order
|
|
211
|
-
* intuition documented on `Pilotiq.layoutProvider`.
|
|
212
|
-
*/
|
|
213
|
-
function wrapInLayoutProviders(
|
|
214
|
-
tree: React.ReactElement,
|
|
215
|
-
registry: ReadonlyArray<React.ComponentType<{ children: React.ReactNode; basePath?: string }>> | undefined,
|
|
216
|
-
basePath: string,
|
|
217
|
-
): React.ReactElement {
|
|
218
|
-
if (!registry || registry.length === 0) return tree
|
|
219
|
-
let acc: React.ReactElement = tree
|
|
220
|
-
for (let i = registry.length - 1; i >= 0; i--) {
|
|
221
|
-
const Provider = registry[i]!
|
|
222
|
-
acc = <Provider basePath={basePath}>{acc}</Provider>
|
|
223
|
-
}
|
|
224
|
-
return acc
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Padding shim that compresses host content when the right sidebar is
|
|
229
|
-
* open on desktop. The fixed-position rail would otherwise overlap
|
|
230
|
-
* content; this wrapper reads the optional `RightSidebarProvider`
|
|
231
|
-
* context (it's a no-op when the surface isn't mounted) and applies
|
|
232
|
-
* `padding-inline-end` matching the active panel width.
|
|
233
|
-
*
|
|
234
|
-
* The shim avoids touching SidebarLayout / TopbarLayout internals — the
|
|
235
|
-
* layouts expand to fill the wrapper's content box, so trimming inside
|
|
236
|
-
* the wrapper compresses both the sticky header and the main scroll
|
|
237
|
-
* region together.
|
|
238
|
-
*/
|
|
239
|
-
function RightSidebarLayoutFrame({ children }: { children: React.ReactNode }) {
|
|
240
|
-
const sidebar = useRightSidebarOptional()
|
|
241
|
-
const isMobile = useIsMobile()
|
|
242
|
-
const apply = sidebar && sidebar.open && !isMobile
|
|
243
|
-
// Always render the same wrapper element so toggling open/closed
|
|
244
|
-
// doesn't remount the Layout subtree (which would drop the user's
|
|
245
|
-
// scroll position and any uncontrolled-input state). Only the inline
|
|
246
|
-
// style flips.
|
|
247
|
-
const style: React.CSSProperties | undefined = apply
|
|
248
|
-
? { paddingInlineEnd: sidebar!.width, transition: 'padding-inline-end 150ms ease-out' }
|
|
249
|
-
: { transition: 'padding-inline-end 150ms ease-out' }
|
|
250
|
-
return <div style={style}>{children}</div>
|
|
251
|
-
}
|