@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
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { parseRecordEditUrl, parseRecordPageUrl } from './parseRecordEditUrl.js'
|
|
4
|
-
|
|
5
|
-
test('parseRecordEditUrl: bare resource edit', () => {
|
|
6
|
-
assert.deepEqual(
|
|
7
|
-
parseRecordEditUrl('/admin/articles/123/edit', '/admin'),
|
|
8
|
-
{ resourceSlug: 'articles', recordId: '123' },
|
|
9
|
-
)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test('parseRecordEditUrl: cluster-prefixed resource edit', () => {
|
|
13
|
-
assert.deepEqual(
|
|
14
|
-
parseRecordEditUrl('/admin/blog/articles/123/edit', '/admin'),
|
|
15
|
-
{ resourceSlug: 'blog/articles', recordId: '123' },
|
|
16
|
-
)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
test('parseRecordEditUrl: nested-relation edit picks child id', () => {
|
|
20
|
-
assert.deepEqual(
|
|
21
|
-
parseRecordEditUrl('/admin/articles/123/comments/456/edit', '/admin'),
|
|
22
|
-
{ resourceSlug: 'articles/123/comments', recordId: '456' },
|
|
23
|
-
)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test('parseRecordEditUrl: list page returns null', () => {
|
|
27
|
-
assert.equal(parseRecordEditUrl('/admin/articles', '/admin'), null)
|
|
28
|
-
assert.equal(parseRecordEditUrl('/admin/articles/123', '/admin'), null)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test('parseRecordEditUrl: create page returns null', () => {
|
|
32
|
-
assert.equal(parseRecordEditUrl('/admin/articles/create', '/admin'), null)
|
|
33
|
-
assert.equal(parseRecordEditUrl('/admin/articles/123/comments/create', '/admin'), null)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('parseRecordEditUrl: basePath mismatch returns null', () => {
|
|
37
|
-
assert.equal(parseRecordEditUrl('/site/articles/123/edit', '/admin'), null)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
test('parseRecordEditUrl: trailing slashes tolerated on URL', () => {
|
|
41
|
-
assert.deepEqual(
|
|
42
|
-
parseRecordEditUrl('/admin/articles/123/edit/', '/admin'),
|
|
43
|
-
{ resourceSlug: 'articles', recordId: '123' },
|
|
44
|
-
)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test('parseRecordEditUrl: trailing slashes tolerated on basePath', () => {
|
|
48
|
-
assert.deepEqual(
|
|
49
|
-
parseRecordEditUrl('/admin/articles/123/edit', '/admin/'),
|
|
50
|
-
{ resourceSlug: 'articles', recordId: '123' },
|
|
51
|
-
)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('parseRecordEditUrl: root basePath', () => {
|
|
55
|
-
assert.deepEqual(
|
|
56
|
-
parseRecordEditUrl('/articles/123/edit', ''),
|
|
57
|
-
{ resourceSlug: 'articles', recordId: '123' },
|
|
58
|
-
)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('parseRecordEditUrl: empty path returns null', () => {
|
|
62
|
-
assert.equal(parseRecordEditUrl('', '/admin'), null)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
test('parseRecordEditUrl: too-short path returns null', () => {
|
|
66
|
-
assert.equal(parseRecordEditUrl('/admin/edit', '/admin'), null)
|
|
67
|
-
// 'edit' alone after basePath isn't enough — needs slug + id + 'edit'.
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('parseRecordEditUrl: slug-only edit (no record id) returns null', () => {
|
|
71
|
-
// '/admin/123/edit' would technically match parts.length===3 with
|
|
72
|
-
// 'edit' last and '123' as recordId — but with empty slug after the
|
|
73
|
-
// slice. Defensive: reject when slugParts is empty.
|
|
74
|
-
assert.equal(parseRecordEditUrl('/admin/edit', '/admin'), null)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
// ─── parseRecordPageUrl (role-aware) ─────────────────────────
|
|
78
|
-
|
|
79
|
-
test('parseRecordPageUrl: edit URL returns role=edit', () => {
|
|
80
|
-
assert.deepEqual(
|
|
81
|
-
parseRecordPageUrl('/admin/articles/123/edit', '/admin'),
|
|
82
|
-
{ resourceSlug: 'articles', recordId: '123', role: 'edit' },
|
|
83
|
-
)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
test('parseRecordPageUrl: view URL returns role=view', () => {
|
|
87
|
-
assert.deepEqual(
|
|
88
|
-
parseRecordPageUrl('/admin/articles/123/view', '/admin'),
|
|
89
|
-
{ resourceSlug: 'articles', recordId: '123', role: 'view' },
|
|
90
|
-
)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
test('parseRecordPageUrl: cluster-prefixed view URL', () => {
|
|
94
|
-
assert.deepEqual(
|
|
95
|
-
parseRecordPageUrl('/admin/blog/articles/123/view', '/admin'),
|
|
96
|
-
{ resourceSlug: 'blog/articles', recordId: '123', role: 'view' },
|
|
97
|
-
)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
test('parseRecordPageUrl: terminal token other than edit|view returns null', () => {
|
|
101
|
-
// 'delete' / 'restore' / 'force-delete' are POST handlers, not pages.
|
|
102
|
-
assert.equal(parseRecordPageUrl('/admin/articles/123/delete', '/admin'), null)
|
|
103
|
-
assert.equal(parseRecordPageUrl('/admin/articles/123/restore', '/admin'), null)
|
|
104
|
-
// Custom record sub-pages also fall through here — they have their own
|
|
105
|
-
// gate path (not record-bound for collab purposes in v1).
|
|
106
|
-
assert.equal(parseRecordPageUrl('/admin/articles/123/history', '/admin'), null)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
test('parseRecordPageUrl: view URL in nested-relation form', () => {
|
|
110
|
-
assert.deepEqual(
|
|
111
|
-
parseRecordPageUrl('/admin/articles/123/comments/456/view', '/admin'),
|
|
112
|
-
{ resourceSlug: 'articles/123/comments', recordId: '456', role: 'view' },
|
|
113
|
-
)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
// ─── Legacy alias: parseRecordEditUrl filters view URLs ──────
|
|
117
|
-
|
|
118
|
-
test('parseRecordEditUrl: view URL returns null (back-compat: edit-only)', () => {
|
|
119
|
-
// A consumer still calling the legacy `parseRecordEditUrl` should
|
|
120
|
-
// continue to see view URLs filtered out — only edit URLs round-trip.
|
|
121
|
-
assert.equal(parseRecordEditUrl('/admin/articles/123/view', '/admin'), null)
|
|
122
|
-
})
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* URL → record-page identity parser. Used by `RecordWrapperGate` (and any
|
|
3
|
-
* plugin that wants to reason about record-bound URLs) to decide whether
|
|
4
|
-
* the current page is a record-edit or record-view route.
|
|
5
|
-
*
|
|
6
|
-
* A URL matches when:
|
|
7
|
-
* 1. it starts with the panel's `basePath`
|
|
8
|
-
* 2. after stripping the prefix it ends with `/edit` or `/view`
|
|
9
|
-
* 3. there are at least three remaining segments (resource slug,
|
|
10
|
-
* record id, terminal token)
|
|
11
|
-
*
|
|
12
|
-
* The `resourceSlug` is the slash-joined chain of every segment up to
|
|
13
|
-
* the record id — this gives clustered resources (`${base}/blog/articles/123/edit`)
|
|
14
|
-
* and nested-relation edits (`${base}/articles/123/comments/456/edit`)
|
|
15
|
-
* distinct slugs so two URLs that target different records always
|
|
16
|
-
* produce different room names downstream.
|
|
17
|
-
*
|
|
18
|
-
* `/admin/articles/123/edit` → { slug: 'articles', id: '123', role: 'edit' }
|
|
19
|
-
* `/admin/articles/123/view` → { slug: 'articles', id: '123', role: 'view' }
|
|
20
|
-
* `/admin/blog/articles/123/edit` → { slug: 'blog/articles', id: '123', role: 'edit' }
|
|
21
|
-
* `/admin/articles/123/comments/456/edit` → { slug: 'articles/123/comments', id: '456', role: 'edit' }
|
|
22
|
-
* `/admin/articles/123/comments` → null (no trailing /edit or /view)
|
|
23
|
-
* `/admin/articles/123/comments/create` → null (terminal token isn't edit|view)
|
|
24
|
-
* `/site/articles/123/edit` → null (basePath mismatch when basePath='/admin')
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/** Page roles `parseRecordPageUrl` recognizes. `'edit'` and `'view'`
|
|
28
|
-
* are the two record-scoped page roles where collab and other
|
|
29
|
-
* record-bound plugins want to mount their per-record wrapper. */
|
|
30
|
-
export type RecordPageRole = 'edit' | 'view'
|
|
31
|
-
|
|
32
|
-
export interface RecordPageIdentity {
|
|
33
|
-
resourceSlug: string
|
|
34
|
-
recordId: string
|
|
35
|
-
/** Which terminal URL segment matched — `'edit'` for the writable edit
|
|
36
|
-
* page, `'view'` for the read-only view page. Lets the gate decide per
|
|
37
|
-
* resource whether collab activates on this role (defaults to `'edit'`
|
|
38
|
-
* only; resources opt into `'view'` for presence-only experiences). */
|
|
39
|
-
role: RecordPageRole
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const RECOGNIZED_ROLES: ReadonlyArray<RecordPageRole> = ['edit', 'view']
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Parse a pilotiq URL into a `{ slug, id, role }` identity. Returns
|
|
46
|
-
* `null` for any URL that isn't a record-edit or record-view page.
|
|
47
|
-
*/
|
|
48
|
-
export function parseRecordPageUrl(
|
|
49
|
-
currentPath: string,
|
|
50
|
-
basePath: string,
|
|
51
|
-
): RecordPageIdentity | null {
|
|
52
|
-
if (!currentPath) return null
|
|
53
|
-
// Normalise — trailing slashes on the URL or trailing slashes on
|
|
54
|
-
// basePath would otherwise reject perfectly valid matches.
|
|
55
|
-
const trimmedPath = currentPath.replace(/\/+$/, '')
|
|
56
|
-
const trimmedBase = basePath.replace(/\/+$/, '')
|
|
57
|
-
|
|
58
|
-
if (trimmedBase !== '' && !trimmedPath.startsWith(trimmedBase)) return null
|
|
59
|
-
|
|
60
|
-
const tail = trimmedPath.slice(trimmedBase.length).replace(/^\/+/, '')
|
|
61
|
-
const parts = tail.split('/').filter(Boolean)
|
|
62
|
-
|
|
63
|
-
if (parts.length < 3) return null
|
|
64
|
-
const terminal = parts[parts.length - 1]!
|
|
65
|
-
if (!RECOGNIZED_ROLES.includes(terminal as RecordPageRole)) return null
|
|
66
|
-
|
|
67
|
-
const recordId = parts[parts.length - 2]!
|
|
68
|
-
const slugParts = parts.slice(0, parts.length - 2)
|
|
69
|
-
if (slugParts.length === 0) return null
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
resourceSlug: slugParts.join('/'),
|
|
73
|
-
recordId,
|
|
74
|
-
role: terminal as RecordPageRole,
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Legacy alias: parse a URL into an edit-only identity. Returns `null`
|
|
79
|
-
* for view URLs (and any non-edit URL). Kept for back-compat with the
|
|
80
|
-
* pre-`parseRecordPageUrl` public API; new code should call
|
|
81
|
-
* `parseRecordPageUrl` and branch on `role`. */
|
|
82
|
-
export interface RecordEditIdentity {
|
|
83
|
-
resourceSlug: string
|
|
84
|
-
recordId: string
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function parseRecordEditUrl(
|
|
88
|
-
currentPath: string,
|
|
89
|
-
basePath: string,
|
|
90
|
-
): RecordEditIdentity | null {
|
|
91
|
-
const identity = parseRecordPageUrl(currentPath, basePath)
|
|
92
|
-
if (!identity || identity.role !== 'edit') return null
|
|
93
|
-
return { resourceSlug: identity.resourceSlug, recordId: identity.recordId }
|
|
94
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Thin localStorage wrappers shared by every persistable surface
|
|
3
|
-
* (collapsible sections, dismissible alerts, wizard step, hidden table
|
|
4
|
-
* columns, group fold state, filter strip toggle, Repeater / Builder
|
|
5
|
-
* row collapse + accordion).
|
|
6
|
-
*
|
|
7
|
-
* Every helper silently no-ops on SSR / private mode / quota — callers
|
|
8
|
-
* already treat all three the same way.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export function readStoredString(key: string): string | null {
|
|
12
|
-
if (typeof window === 'undefined') return null
|
|
13
|
-
try { return window.localStorage.getItem(key) }
|
|
14
|
-
catch { return null }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function writeStoredString(key: string, value: string): void {
|
|
18
|
-
if (typeof window === 'undefined') return
|
|
19
|
-
try { window.localStorage.setItem(key, value) } catch { /* quota / blocked */ }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function removeStoredString(key: string): void {
|
|
23
|
-
if (typeof window === 'undefined') return
|
|
24
|
-
try { window.localStorage.removeItem(key) } catch { /* */ }
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Boolean flag using `'1'` / `'0'` encoding. Returns `defaultValue`
|
|
29
|
-
* when the key is unset, SSR, or storage is blocked.
|
|
30
|
-
*/
|
|
31
|
-
export function readStoredFlag(key: string, defaultValue: boolean): boolean {
|
|
32
|
-
const raw = readStoredString(key)
|
|
33
|
-
if (raw === '1') return true
|
|
34
|
-
if (raw === '0') return false
|
|
35
|
-
return defaultValue
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function writeStoredFlag(key: string, value: boolean): void {
|
|
39
|
-
writeStoredString(key, value ? '1' : '0')
|
|
40
|
-
}
|
package/src/react/registry.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { ComponentType } from 'react'
|
|
2
|
-
import type { ElementMeta } from '../schema/Element.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Props every registered field renderer receives. The renderer owns how it
|
|
6
|
-
* wires the input value into form POST — typically via a hidden `<input>`.
|
|
7
|
-
*
|
|
8
|
-
* Kept narrow on purpose: the renderer reads everything else (rules, options,
|
|
9
|
-
* etc.) off `el` directly. Adding more discrete props here forces every
|
|
10
|
-
* registered renderer to accept them whether it cares or not.
|
|
11
|
-
*/
|
|
12
|
-
export interface FieldRendererProps {
|
|
13
|
-
el: ElementMeta
|
|
14
|
-
name: string
|
|
15
|
-
defaultValue: unknown
|
|
16
|
-
required: boolean
|
|
17
|
-
disabled: boolean
|
|
18
|
-
placeholder: string | undefined
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const renderers = new Map<string, ComponentType<FieldRendererProps>>()
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Register a custom React component to render a `fieldType`. Used by external
|
|
25
|
-
* packages (e.g. `@pilotiq/tiptap`) to plug in input UIs without forcing
|
|
26
|
-
* pilotiq core to import their dependencies.
|
|
27
|
-
*
|
|
28
|
-
* Built-in field types (`text`, `textarea`, `select`, `toggle`, `date`, …)
|
|
29
|
-
* are handled by SchemaRenderer's internal switch and don't need to register.
|
|
30
|
-
* Calling `registerFieldRenderer` for a built-in fieldType wins — the registry
|
|
31
|
-
* is checked first.
|
|
32
|
-
*
|
|
33
|
-
* Call once at app boot (client-side). Re-calling with the same fieldType
|
|
34
|
-
* overwrites the previous registration, which is convenient for HMR.
|
|
35
|
-
*/
|
|
36
|
-
export function registerFieldRenderer(
|
|
37
|
-
fieldType: string,
|
|
38
|
-
Component: ComponentType<FieldRendererProps>,
|
|
39
|
-
): void {
|
|
40
|
-
renderers.set(fieldType, Component)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Look up a registered renderer. Returns undefined for unregistered types. */
|
|
44
|
-
export function getFieldRenderer(
|
|
45
|
-
fieldType: string,
|
|
46
|
-
): ComponentType<FieldRendererProps> | undefined {
|
|
47
|
-
return renderers.get(fieldType)
|
|
48
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import React, { createContext, useContext, type ComponentType } from 'react'
|
|
2
|
-
import type { RightPanelProps } from '../RightPanel.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Build-time right-panel manifest. Maps each registered contribution's
|
|
6
|
-
* `id` (e.g. `'ai.chat'`) to the React component the user passed as
|
|
7
|
-
* `render`. The Pilotiq Vite plugin emits this map by walking every
|
|
8
|
-
* panel's `cfg.rightPanels` and stamping `_rightPanels[c.id] = c.render`
|
|
9
|
-
* into `pages/(pilotiq)/_components.ts`.
|
|
10
|
-
*
|
|
11
|
-
* The body component never crosses the wire — only its tab-strip meta
|
|
12
|
-
* does (`RightPanelMeta`). The chrome (Phase C) calls
|
|
13
|
-
* `getRightPanelComponent(id)` to resolve a `RightPanelMeta.id` into
|
|
14
|
-
* the actual component at mount time.
|
|
15
|
-
*
|
|
16
|
-
* Sparse: when a panel has no contributions, the registry is `{}` and
|
|
17
|
-
* the chrome never mounts (server-side `RightSidebarMeta` is also
|
|
18
|
-
* absent in that case — defense in depth).
|
|
19
|
-
*/
|
|
20
|
-
export type RightPanelRegistry = Record<string, ComponentType<RightPanelProps>>
|
|
21
|
-
|
|
22
|
-
const Ctx = createContext<RightPanelRegistry | undefined>(undefined)
|
|
23
|
-
|
|
24
|
-
export function RightPanelRegistryProvider({
|
|
25
|
-
value,
|
|
26
|
-
children,
|
|
27
|
-
}: {
|
|
28
|
-
value: RightPanelRegistry | undefined
|
|
29
|
-
children: React.ReactNode
|
|
30
|
-
}) {
|
|
31
|
-
return <Ctx.Provider value={value}>{children}</Ctx.Provider>
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Read the full registry (for chrome that wants to enumerate). */
|
|
35
|
-
export function useRightPanelRegistry(): RightPanelRegistry | undefined {
|
|
36
|
-
return useContext(Ctx)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Look up a single registered body component by `id`. Returns
|
|
41
|
-
* `undefined` when the registry is missing or the id was never
|
|
42
|
-
* registered — the caller paints its own missing-component fallback.
|
|
43
|
-
*/
|
|
44
|
-
export function useRightPanelComponent(id: string): ComponentType<RightPanelProps> | undefined {
|
|
45
|
-
const registry = useContext(Ctx)
|
|
46
|
-
return registry?.[id]
|
|
47
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import type { ComponentType } from 'react'
|
|
3
|
-
import {
|
|
4
|
-
CircleAlertIcon,
|
|
5
|
-
CircleCheckIcon,
|
|
6
|
-
InfoIcon,
|
|
7
|
-
TriangleAlertIcon,
|
|
8
|
-
XIcon,
|
|
9
|
-
} from 'lucide-react'
|
|
10
|
-
import { readStoredString, writeStoredString } from '../persistedState.js'
|
|
11
|
-
import { alertStyles, TEXT_COLOR_CLASSES } from './constants.js'
|
|
12
|
-
|
|
13
|
-
// ─── Alert renderer ─────────────────────────────────────────
|
|
14
|
-
//
|
|
15
|
-
// Owns dismissal state (per-mount + optional localStorage persistence)
|
|
16
|
-
// + icon dispatch + footer-actions alignment. Lifted out of the inline
|
|
17
|
-
// `case 'alert'` branch when Alert gained `dismissible() / iconColor() /
|
|
18
|
-
// footerActionsAlignment()` setters — those need component-local state
|
|
19
|
-
// (the dismiss button, the persisted-dismissal hydration on mount), and
|
|
20
|
-
// inlining the hooks under a switch arm is fragile.
|
|
21
|
-
|
|
22
|
-
const ALERT_TYPE_ICONS: Record<string, ComponentType<{ className?: string; 'aria-hidden'?: boolean | 'true' | 'false' }>> = {
|
|
23
|
-
info: InfoIcon,
|
|
24
|
-
warning: TriangleAlertIcon,
|
|
25
|
-
success: CircleCheckIcon,
|
|
26
|
-
danger: CircleAlertIcon,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const ALERT_TYPE_DEFAULT_ICON_COLOR: Record<string, string> = {
|
|
30
|
-
info: 'info',
|
|
31
|
-
warning: 'warning',
|
|
32
|
-
success: 'success',
|
|
33
|
-
danger: 'destructive',
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const ALERT_ACTIONS_ALIGNMENT: Record<string, string> = {
|
|
37
|
-
start: 'justify-start',
|
|
38
|
-
center: 'justify-center',
|
|
39
|
-
end: 'justify-end',
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function alertPersistKey(persistKey: string): string {
|
|
43
|
-
return `pilotiq.alert.${persistKey}`
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function AlertRenderer(props: {
|
|
47
|
-
alertType: string
|
|
48
|
-
content: string
|
|
49
|
-
title?: string
|
|
50
|
-
dismissible?: boolean
|
|
51
|
-
persistDismissal?: string
|
|
52
|
-
iconColor?: string
|
|
53
|
-
actionsAlignment?: string
|
|
54
|
-
footer: React.ReactNode[]
|
|
55
|
-
}): React.ReactNode {
|
|
56
|
-
const {
|
|
57
|
-
alertType, content, title, dismissible,
|
|
58
|
-
persistDismissal, iconColor, actionsAlignment, footer,
|
|
59
|
-
} = props
|
|
60
|
-
const [dismissed, setDismissed] = useState(false)
|
|
61
|
-
|
|
62
|
-
// Hydrate persisted-dismissal on first paint. `useState(false)` keeps
|
|
63
|
-
// SSR + first client paint identical (Hydration safe); the effect
|
|
64
|
-
// flips to dismissed if localStorage has the flag set.
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (!persistDismissal) return
|
|
67
|
-
if (readStoredString(alertPersistKey(persistDismissal)) === '1') {
|
|
68
|
-
setDismissed(true)
|
|
69
|
-
}
|
|
70
|
-
}, [persistDismissal])
|
|
71
|
-
|
|
72
|
-
if (dismissed) return null
|
|
73
|
-
|
|
74
|
-
const styles = alertStyles[alertType] ?? alertStyles['info']!
|
|
75
|
-
const Icon = ALERT_TYPE_ICONS[alertType] ?? InfoIcon
|
|
76
|
-
const iconColorKey = iconColor ?? ALERT_TYPE_DEFAULT_ICON_COLOR[alertType] ?? 'info'
|
|
77
|
-
const iconColorCls = TEXT_COLOR_CLASSES[iconColorKey] ?? ''
|
|
78
|
-
const alignCls = ALERT_ACTIONS_ALIGNMENT[actionsAlignment ?? 'start'] ?? 'justify-start'
|
|
79
|
-
|
|
80
|
-
const handleDismiss = (): void => {
|
|
81
|
-
setDismissed(true)
|
|
82
|
-
if (persistDismissal) writeStoredString(alertPersistKey(persistDismissal), '1')
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<div className={`relative rounded-lg border p-4 ${styles} ${dismissible ? 'pr-9' : ''}`}>
|
|
87
|
-
<div className="flex gap-3">
|
|
88
|
-
<Icon className={`size-5 shrink-0 mt-0.5 ${iconColorCls}`} aria-hidden="true" />
|
|
89
|
-
<div className="flex-1 min-w-0">
|
|
90
|
-
{title !== undefined && <p className="font-medium mb-1">{title}</p>}
|
|
91
|
-
<p className="text-sm">{content}</p>
|
|
92
|
-
{footer.length > 0 && (
|
|
93
|
-
<div className={`flex items-center gap-2 mt-3 ${alignCls}`}>
|
|
94
|
-
{footer}
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
{dismissible && (
|
|
100
|
-
<button
|
|
101
|
-
type="button"
|
|
102
|
-
onClick={handleDismiss}
|
|
103
|
-
aria-label="Dismiss"
|
|
104
|
-
title="Dismiss"
|
|
105
|
-
className="absolute top-3 right-3 inline-flex h-6 w-6 items-center justify-center rounded opacity-70 hover:opacity-100 transition-opacity"
|
|
106
|
-
>
|
|
107
|
-
<XIcon className="size-4" aria-hidden="true" />
|
|
108
|
-
</button>
|
|
109
|
-
)}
|
|
110
|
-
</div>
|
|
111
|
-
)
|
|
112
|
-
}
|