@pilotiq/pilotiq 0.24.1 → 0.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/boost/guidelines.md +571 -0
- package/boost/skills/pilotiq-actions/SKILL.md +49 -0
- package/boost/skills/pilotiq-actions/rules/dispatch-modes.md +177 -0
- package/boost/skills/pilotiq-actions/rules/factories.md +130 -0
- package/boost/skills/pilotiq-actions/rules/visibility-and-authorization.md +125 -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/Pilotiq.d.ts +31 -0
- package/dist/Pilotiq.d.ts.map +1 -1
- package/dist/Pilotiq.js +3 -1
- package/dist/Pilotiq.js.map +1 -1
- package/dist/PilotiqRegistry.d.ts +13 -0
- package/dist/PilotiqRegistry.d.ts.map +1 -1
- package/dist/PilotiqRegistry.js +15 -0
- package/dist/PilotiqRegistry.js.map +1 -1
- package/dist/pageData/misc.d.ts.map +1 -1
- package/dist/pageData/misc.js +6 -0
- package/dist/pageData/misc.js.map +1 -1
- package/dist/pageData/navigation.d.ts +1 -0
- package/dist/pageData/navigation.d.ts.map +1 -1
- package/dist/pageData/navigation.js +3 -0
- package/dist/pageData/navigation.js.map +1 -1
- package/dist/pageData/relationPages.d.ts.map +1 -1
- package/dist/pageData/relationPages.js +3 -0
- package/dist/pageData/relationPages.js.map +1 -1
- package/dist/pageData/resourcePages.d.ts.map +1 -1
- package/dist/pageData/resourcePages.js +8 -0
- package/dist/pageData/resourcePages.js.map +1 -1
- package/dist/react/AppShell.d.ts +8 -0
- package/dist/react/AppShell.d.ts.map +1 -1
- package/dist/react/AppShell.js.map +1 -1
- package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
- package/dist/react/layouts/SidebarLayout.js +10 -2
- package/dist/react/layouts/SidebarLayout.js.map +1 -1
- package/dist/react/widgets/StatsOverviewRenderer.d.ts.map +1 -1
- package/dist/react/widgets/StatsOverviewRenderer.js +32 -18
- package/dist/react/widgets/StatsOverviewRenderer.js.map +1 -1
- package/dist/routes/relations.d.ts.map +1 -1
- package/dist/routes/relations.js +25 -18
- package/dist/routes/relations.js.map +1 -1
- package/dist/routes/resources.js.map +1 -1
- package/package.json +10 -5
- package/.turbo/turbo-build.log +0 -8
- package/CLAUDE.md +0 -265
- 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 -225
- 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 -194
- 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/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 -704
- package/src/routes/pages.ts +0 -175
- package/src/routes/panel.ts +0 -204
- package/src/routes/relations.ts +0 -1243
- 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,139 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { generateThemeCSS } from './generate-css.js'
|
|
5
|
-
import type { ThemeMeta } from './types.js'
|
|
6
|
-
|
|
7
|
-
// Minimal-but-realistic theme meta the generator would receive from resolveTheme.
|
|
8
|
-
function fixture(overrides: Partial<ThemeMeta> = {}): ThemeMeta {
|
|
9
|
-
return {
|
|
10
|
-
light: {
|
|
11
|
-
'--background': 'oklch(1 0 0)',
|
|
12
|
-
'--foreground': 'oklch(0.15 0 0)',
|
|
13
|
-
'--primary': 'oklch(0.55 0.18 250)',
|
|
14
|
-
},
|
|
15
|
-
dark: {
|
|
16
|
-
'--background': 'oklch(0.15 0 0)',
|
|
17
|
-
'--foreground': 'oklch(0.98 0 0)',
|
|
18
|
-
'--primary': 'oklch(0.65 0.15 250)',
|
|
19
|
-
},
|
|
20
|
-
radius: '0.625rem',
|
|
21
|
-
spacing: '0.25rem',
|
|
22
|
-
iconLibrary: 'lucide',
|
|
23
|
-
...overrides,
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
describe('generateThemeCSS', () => {
|
|
28
|
-
// ─── Block structure ─────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
describe('block structure', () => {
|
|
31
|
-
it('emits :root and .dark blocks', () => {
|
|
32
|
-
const css = generateThemeCSS(fixture())
|
|
33
|
-
assert.match(css, /:root \{[^}]*\}/, 'should emit :root block')
|
|
34
|
-
assert.match(css, /\.dark \{[^}]*\}/, 'should emit .dark block')
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it(':root contains light vars; .dark contains dark vars', () => {
|
|
38
|
-
const css = generateThemeCSS(fixture())
|
|
39
|
-
const rootMatch = css.match(/:root \{([\s\S]*?)\}/)
|
|
40
|
-
const darkMatch = css.match(/\.dark \{([\s\S]*?)\}/)
|
|
41
|
-
assert.ok(rootMatch && darkMatch)
|
|
42
|
-
// Light --foreground (oklch(0.15 0 0)) lives in :root, not .dark.
|
|
43
|
-
assert.match(rootMatch[1]!, /--foreground: oklch\(0\.15 0 0\)/)
|
|
44
|
-
// Dark --foreground (oklch(0.98 0 0)) lives in .dark.
|
|
45
|
-
assert.match(darkMatch[1]!, /--foreground: oklch\(0\.98 0 0\)/)
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
// ─── !important flags ───────────────────────────────────
|
|
50
|
-
|
|
51
|
-
describe('!important flags', () => {
|
|
52
|
-
it('marks every emitted CSS variable as !important', () => {
|
|
53
|
-
const css = generateThemeCSS(fixture())
|
|
54
|
-
// Each var declaration we care about should end with `!important;`.
|
|
55
|
-
const decls = css.match(/--[\w-]+:\s*[^;]+;/g) ?? []
|
|
56
|
-
assert.ok(decls.length > 0, 'expected at least one var declaration')
|
|
57
|
-
for (const decl of decls) {
|
|
58
|
-
assert.match(decl, /!important;$/, `declaration "${decl}" should be !important`)
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
// ─── Radius + spacing always emitted ─────────────────────
|
|
64
|
-
|
|
65
|
-
describe('radius and spacing', () => {
|
|
66
|
-
it('emits --radius and --spacing inside :root', () => {
|
|
67
|
-
const css = generateThemeCSS(fixture({ radius: '1rem', spacing: '0.3rem' }))
|
|
68
|
-
const rootMatch = css.match(/:root \{([\s\S]*?)\}/)
|
|
69
|
-
assert.ok(rootMatch)
|
|
70
|
-
assert.match(rootMatch[1]!, /--radius: 1rem !important/)
|
|
71
|
-
assert.match(rootMatch[1]!, /--spacing: 0\.3rem !important/)
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
// ─── Font handling ───────────────────────────────────────
|
|
76
|
-
|
|
77
|
-
describe('fonts', () => {
|
|
78
|
-
it('omits font-family vars when fontFamily is unset', () => {
|
|
79
|
-
const css = generateThemeCSS(fixture())
|
|
80
|
-
assert.doesNotMatch(css, /--font-sans:/)
|
|
81
|
-
assert.doesNotMatch(css, /--font-heading:/)
|
|
82
|
-
assert.doesNotMatch(css, /--default-font-family:/)
|
|
83
|
-
assert.doesNotMatch(css, /^html \{/m)
|
|
84
|
-
assert.doesNotMatch(css, /^h1, h2, h3/m)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('emits body-font vars and html rule when body fontFamily set', () => {
|
|
88
|
-
const css = generateThemeCSS(fixture({
|
|
89
|
-
fontFamily: { body: "'Inter', system-ui, sans-serif" },
|
|
90
|
-
}))
|
|
91
|
-
assert.match(css, /--font-sans: 'Inter', system-ui, sans-serif !important/)
|
|
92
|
-
assert.match(css, /--default-font-family: 'Inter', system-ui, sans-serif !important/)
|
|
93
|
-
assert.match(css, /^html \{ font-family: var\(--default-font-family\) !important; \}$/m)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('emits heading-font var and h1-h6 rule when heading fontFamily set', () => {
|
|
97
|
-
const css = generateThemeCSS(fixture({
|
|
98
|
-
fontFamily: { heading: "'Playfair Display', serif" },
|
|
99
|
-
}))
|
|
100
|
-
assert.match(css, /--font-heading: 'Playfair Display', serif !important/)
|
|
101
|
-
assert.match(css, /^h1, h2, h3, h4, h5, h6 \{ font-family: var\(--font-heading, var\(--default-font-family\)\) !important; \}$/m)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('emits both body and heading rules together', () => {
|
|
105
|
-
const css = generateThemeCSS(fixture({
|
|
106
|
-
fontFamily: {
|
|
107
|
-
body: "'Inter', system-ui, sans-serif",
|
|
108
|
-
heading: "'Geist', system-ui, sans-serif",
|
|
109
|
-
},
|
|
110
|
-
}))
|
|
111
|
-
assert.match(css, /--font-sans:/)
|
|
112
|
-
assert.match(css, /--font-heading:/)
|
|
113
|
-
assert.match(css, /^html \{/m)
|
|
114
|
-
assert.match(css, /^h1, h2, h3/m)
|
|
115
|
-
})
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
// ─── Empty input resilience ──────────────────────────────
|
|
119
|
-
|
|
120
|
-
describe('resilience', () => {
|
|
121
|
-
it('handles empty light/dark var maps without crashing', () => {
|
|
122
|
-
const css = generateThemeCSS(fixture({ light: {}, dark: {} }))
|
|
123
|
-
// Still has the :root scaffolding (radius/spacing always emit).
|
|
124
|
-
assert.match(css, /:root \{/)
|
|
125
|
-
assert.match(css, /--radius:/)
|
|
126
|
-
assert.match(css, /\.dark \{\s*\n*\}/)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
it('passes through arbitrary CSS variable values unchanged (no escaping)', () => {
|
|
130
|
-
// Generator does not sanitize — input is trusted (already validated upstream).
|
|
131
|
-
// This test pins that contract so future "helpful" sanitization doesn't
|
|
132
|
-
// silently break the cssVariables escape hatch.
|
|
133
|
-
const css = generateThemeCSS(fixture({
|
|
134
|
-
light: { '--custom': 'color-mix(in oklch, var(--primary) 50%, white)' },
|
|
135
|
-
}))
|
|
136
|
-
assert.match(css, /--custom: color-mix\(in oklch, var\(--primary\) 50%, white\) !important/)
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { ThemeMeta } from './types.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Generates a CSS string from resolved theme meta.
|
|
5
|
-
* Produces `:root { ... }` and `.dark { ... }` blocks that override CSS custom properties.
|
|
6
|
-
*
|
|
7
|
-
* Used by both SSR (injected as `<style>` in React tree) and client (ThemeProvider).
|
|
8
|
-
*/
|
|
9
|
-
export function generateThemeCSS(theme: ThemeMeta): string {
|
|
10
|
-
const lightVars = Object.entries(theme.light)
|
|
11
|
-
.map(([k, v]) => ` ${k}: ${v} !important;`)
|
|
12
|
-
.join('\n')
|
|
13
|
-
|
|
14
|
-
const darkVars = Object.entries(theme.dark)
|
|
15
|
-
.map(([k, v]) => ` ${k}: ${v} !important;`)
|
|
16
|
-
.join('\n')
|
|
17
|
-
|
|
18
|
-
// !important ensures theme overrides Tailwind's @layer declarations
|
|
19
|
-
// and works correctly with .dark class toggling.
|
|
20
|
-
let css = `:root {\n${lightVars}\n --radius: ${theme.radius} !important;\n --spacing: ${theme.spacing} !important;\n`
|
|
21
|
-
|
|
22
|
-
if (theme.fontFamily?.body) {
|
|
23
|
-
css += ` --font-sans: ${theme.fontFamily.body} !important;\n`
|
|
24
|
-
css += ` --default-font-family: ${theme.fontFamily.body} !important;\n`
|
|
25
|
-
}
|
|
26
|
-
if (theme.fontFamily?.heading) {
|
|
27
|
-
css += ` --font-heading: ${theme.fontFamily.heading} !important;\n`
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
css += '}\n'
|
|
31
|
-
css += `.dark {\n${darkVars}\n}\n`
|
|
32
|
-
|
|
33
|
-
// Direct html rule as fallback for body font
|
|
34
|
-
if (theme.fontFamily?.body) {
|
|
35
|
-
css += `html { font-family: var(--default-font-family) !important; }\n`
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Auto-apply heading font to h1-h6
|
|
39
|
-
if (theme.fontFamily?.heading) {
|
|
40
|
-
css += 'h1, h2, h3, h4, h5, h6 { font-family: var(--font-heading, var(--default-font-family)) !important; }\n'
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return css
|
|
44
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { parseSeedToScale } from './generate-scale.js'
|
|
5
|
-
|
|
6
|
-
describe('parseSeedToScale', () => {
|
|
7
|
-
// ─── Hex parsing ─────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
describe('hex input', () => {
|
|
10
|
-
it('parses a valid 6-digit hex into an 11-step OKLCH scale', () => {
|
|
11
|
-
const scale = parseSeedToScale('#3b82f6') // tailwind blue-500
|
|
12
|
-
assert.ok(scale, 'scale should be returned')
|
|
13
|
-
// All 11 steps present.
|
|
14
|
-
for (const step of [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as const) {
|
|
15
|
-
assert.match(scale[step], /^oklch\([\d.]+ [\d.]+ [\d.]+\)$/, `step ${step} should be a valid oklch() string`)
|
|
16
|
-
}
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('accepts uppercase hex digits', () => {
|
|
20
|
-
const a = parseSeedToScale('#3B82F6')
|
|
21
|
-
const b = parseSeedToScale('#3b82f6')
|
|
22
|
-
assert.deepEqual(a, b)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('returns null for invalid hex', () => {
|
|
26
|
-
assert.equal(parseSeedToScale('#zzzzzz'), null)
|
|
27
|
-
assert.equal(parseSeedToScale('#12345'), null) // wrong length
|
|
28
|
-
assert.equal(parseSeedToScale('#1234567'), null)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('returns null for hex without # prefix', () => {
|
|
32
|
-
// Implementation gates hex parsing on a leading '#'.
|
|
33
|
-
assert.equal(parseSeedToScale('3b82f6'), null)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('preserves hue and chroma across all steps; only lightness varies', () => {
|
|
37
|
-
const scale = parseSeedToScale('#3b82f6')
|
|
38
|
-
assert.ok(scale)
|
|
39
|
-
const steps = Object.values(scale)
|
|
40
|
-
const parsed = steps.map(s => {
|
|
41
|
-
const m = s.match(/oklch\(([\d.]+) ([\d.]+) ([\d.]+)\)/)
|
|
42
|
-
return m ? { L: +m[1]!, C: +m[2]!, H: +m[3]! } : null
|
|
43
|
-
}).filter(Boolean) as { L: number; C: number; H: number }[]
|
|
44
|
-
|
|
45
|
-
// Hue and chroma constant.
|
|
46
|
-
const firstC = parsed[0]!.C
|
|
47
|
-
const firstH = parsed[0]!.H
|
|
48
|
-
for (const p of parsed) {
|
|
49
|
-
assert.equal(p.C, firstC, 'chroma should be constant across steps')
|
|
50
|
-
assert.equal(p.H, firstH, 'hue should be constant across steps')
|
|
51
|
-
}
|
|
52
|
-
// Lightness strictly decreases from step 50 → 950.
|
|
53
|
-
for (let i = 1; i < parsed.length; i++) {
|
|
54
|
-
assert.ok(parsed[i]!.L < parsed[i - 1]!.L, `step ${i} should be darker than ${i - 1}`)
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('discards seed lightness (same hue/chroma → same scale regardless of L)', () => {
|
|
59
|
-
// Two oklch seeds with identical hue + chroma but different lightness
|
|
60
|
-
// should produce identical scales — only H and C contribute.
|
|
61
|
-
const dark = parseSeedToScale('oklch(0.3 0.15 240)')
|
|
62
|
-
const light = parseSeedToScale('oklch(0.8 0.15 240)')
|
|
63
|
-
assert.deepEqual(dark, light)
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
// ─── oklch() parsing ─────────────────────────────────────
|
|
68
|
-
|
|
69
|
-
describe('oklch() input', () => {
|
|
70
|
-
it('parses a valid oklch() string', () => {
|
|
71
|
-
const scale = parseSeedToScale('oklch(0.55 0.18 250)')
|
|
72
|
-
assert.ok(scale)
|
|
73
|
-
// Hue 250 should appear in every step's serialized string (rounded to .1).
|
|
74
|
-
for (const v of Object.values(scale)) {
|
|
75
|
-
assert.match(v, / 250\.0\)$/)
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('is case-insensitive on the OKLCH prefix', () => {
|
|
80
|
-
const upper = parseSeedToScale('OKLCH(0.5 0.1 200)')
|
|
81
|
-
const lower = parseSeedToScale('oklch(0.5 0.1 200)')
|
|
82
|
-
assert.deepEqual(upper, lower)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('returns null for malformed oklch()', () => {
|
|
86
|
-
assert.equal(parseSeedToScale('oklch()'), null)
|
|
87
|
-
assert.equal(parseSeedToScale('oklch(0.5)'), null)
|
|
88
|
-
assert.equal(parseSeedToScale('oklch(0.5 0.1)'), null)
|
|
89
|
-
assert.equal(parseSeedToScale('oklch(0.5 0.1 200 0.5)'), null) // alpha not supported
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
// ─── Unsupported / edge cases ────────────────────────────
|
|
94
|
-
|
|
95
|
-
describe('unsupported input', () => {
|
|
96
|
-
it('returns null for empty string', () => {
|
|
97
|
-
assert.equal(parseSeedToScale(''), null)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
it('returns null for unsupported color formats', () => {
|
|
101
|
-
assert.equal(parseSeedToScale('rgb(255, 0, 0)'), null)
|
|
102
|
-
assert.equal(parseSeedToScale('hsl(120, 50%, 50%)'), null)
|
|
103
|
-
assert.equal(parseSeedToScale('red'), null)
|
|
104
|
-
})
|
|
105
|
-
})
|
|
106
|
-
})
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import type { ColorScale, ColorStep } from './colors.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Custom-color seed parsing — converts a hex (#RRGGBB) or `oklch(L C H)` string
|
|
5
|
-
* into a synthetic 50…950 ColorScale by holding hue+chroma constant and
|
|
6
|
-
* ramping lightness across a fixed curve.
|
|
7
|
-
*
|
|
8
|
-
* The seed's own lightness is discarded — only hue and chroma contribute.
|
|
9
|
-
* Returns `null` for unparseable input; the caller falls back to the base scale.
|
|
10
|
-
*
|
|
11
|
-
* Limitations:
|
|
12
|
-
* - Highly chromatic seeds (C > ~0.25) may go out of gamut at extreme
|
|
13
|
-
* lightness steps; the browser will clip. Use the `cssVariables` raw
|
|
14
|
-
* escape hatch for surgical control if this matters.
|
|
15
|
-
* - Alpha values are not supported.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const TARGET_LIGHTNESS: Record<ColorStep, number> = {
|
|
19
|
-
50: 0.985,
|
|
20
|
-
100: 0.96,
|
|
21
|
-
200: 0.91,
|
|
22
|
-
300: 0.85,
|
|
23
|
-
400: 0.75,
|
|
24
|
-
500: 0.65,
|
|
25
|
-
600: 0.55,
|
|
26
|
-
700: 0.48,
|
|
27
|
-
800: 0.40,
|
|
28
|
-
900: 0.34,
|
|
29
|
-
950: 0.25,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function hexToLinearRgb(hex: string): [number, number, number] | null {
|
|
33
|
-
const cleaned = hex.replace('#', '')
|
|
34
|
-
if (!/^[0-9a-fA-F]{6}$/.test(cleaned)) return null
|
|
35
|
-
const r = parseInt(cleaned.slice(0, 2), 16) / 255
|
|
36
|
-
const g = parseInt(cleaned.slice(2, 4), 16) / 255
|
|
37
|
-
const b = parseInt(cleaned.slice(4, 6), 16) / 255
|
|
38
|
-
const toLinear = (c: number) => c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
|
|
39
|
-
return [toLinear(r), toLinear(g), toLinear(b)]
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function linearRgbToOklch(lr: number, lg: number, lb: number): [number, number, number] {
|
|
43
|
-
const l = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb
|
|
44
|
-
const m = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb
|
|
45
|
-
const s = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb
|
|
46
|
-
|
|
47
|
-
const l_ = Math.cbrt(l)
|
|
48
|
-
const m_ = Math.cbrt(m)
|
|
49
|
-
const s_ = Math.cbrt(s)
|
|
50
|
-
|
|
51
|
-
const L = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_
|
|
52
|
-
const a = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_
|
|
53
|
-
const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_
|
|
54
|
-
|
|
55
|
-
const C = Math.sqrt(a * a + b2 * b2)
|
|
56
|
-
let H = Math.atan2(b2, a) * 180 / Math.PI
|
|
57
|
-
if (H < 0) H += 360
|
|
58
|
-
return [L, C, H]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function parseOklchString(s: string): [number, number, number] | null {
|
|
62
|
-
const match = s.match(/oklch\(\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*\)/i)
|
|
63
|
-
if (!match) return null
|
|
64
|
-
return [parseFloat(match[1]!), parseFloat(match[2]!), parseFloat(match[3]!)]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function parseSeedToScale(seed: string): ColorScale | null {
|
|
68
|
-
let lch: [number, number, number] | null = null
|
|
69
|
-
|
|
70
|
-
if (seed.startsWith('#')) {
|
|
71
|
-
const rgb = hexToLinearRgb(seed)
|
|
72
|
-
if (rgb) lch = linearRgbToOklch(rgb[0], rgb[1], rgb[2])
|
|
73
|
-
} else if (seed.toLowerCase().startsWith('oklch')) {
|
|
74
|
-
lch = parseOklchString(seed)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (!lch) return null
|
|
78
|
-
|
|
79
|
-
const C = lch[1]
|
|
80
|
-
const H = lch[2]
|
|
81
|
-
|
|
82
|
-
const fmt = (l: number) => `oklch(${l.toFixed(3)} ${C.toFixed(3)} ${H.toFixed(1)})`
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
50: fmt(TARGET_LIGHTNESS[50]),
|
|
86
|
-
100: fmt(TARGET_LIGHTNESS[100]),
|
|
87
|
-
200: fmt(TARGET_LIGHTNESS[200]),
|
|
88
|
-
300: fmt(TARGET_LIGHTNESS[300]),
|
|
89
|
-
400: fmt(TARGET_LIGHTNESS[400]),
|
|
90
|
-
500: fmt(TARGET_LIGHTNESS[500]),
|
|
91
|
-
600: fmt(TARGET_LIGHTNESS[600]),
|
|
92
|
-
700: fmt(TARGET_LIGHTNESS[700]),
|
|
93
|
-
800: fmt(TARGET_LIGHTNESS[800]),
|
|
94
|
-
900: fmt(TARGET_LIGHTNESS[900]),
|
|
95
|
-
950: fmt(TARGET_LIGHTNESS[950]),
|
|
96
|
-
}
|
|
97
|
-
}
|
package/src/theme/icon-map.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { IconLibrary } from './types.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Canonical icon name → library-specific component name mapping.
|
|
5
|
-
* Covers all icons used internally by the pilotiq UI.
|
|
6
|
-
*/
|
|
7
|
-
export const iconMap: Record<string, Record<IconLibrary, string>> = {
|
|
8
|
-
'chevron-right': { lucide: 'ChevronRight', tabler: 'IconChevronRight', phosphor: 'CaretRight', remix: 'RiArrowRightSLine' },
|
|
9
|
-
'chevrons-up-down': { lucide: 'ChevronsUpDown', tabler: 'IconSelector', phosphor: 'CaretUpDown', remix: 'RiExpandUpDownLine' },
|
|
10
|
-
'log-out': { lucide: 'LogOut', tabler: 'IconLogout', phosphor: 'SignOut', remix: 'RiLogoutBoxRLine' },
|
|
11
|
-
'badge-check': { lucide: 'BadgeCheck', tabler: 'IconRosetteDiscountCheck', phosphor: 'SealCheck', remix: 'RiVerifiedBadgeFill' },
|
|
12
|
-
'bell': { lucide: 'Bell', tabler: 'IconBell', phosphor: 'Bell', remix: 'RiNotification3Line' },
|
|
13
|
-
'x': { lucide: 'X', tabler: 'IconX', phosphor: 'X', remix: 'RiCloseLine' },
|
|
14
|
-
'plus': { lucide: 'Plus', tabler: 'IconPlus', phosphor: 'Plus', remix: 'RiAddLine' },
|
|
15
|
-
'arrow-up': { lucide: 'ArrowUp', tabler: 'IconArrowUp', phosphor: 'ArrowUp', remix: 'RiArrowUpLine' },
|
|
16
|
-
'sparkles': { lucide: 'Sparkles', tabler: 'IconSparkles', phosphor: 'Sparkle', remix: 'RiMagicLine' },
|
|
17
|
-
'check': { lucide: 'Check', tabler: 'IconCheck', phosphor: 'Check', remix: 'RiCheckLine' },
|
|
18
|
-
'chevron-down': { lucide: 'ChevronDown', tabler: 'IconChevronDown', phosphor: 'CaretDown', remix: 'RiArrowDownSLine' },
|
|
19
|
-
'trash': { lucide: 'Trash2', tabler: 'IconTrash', phosphor: 'Trash', remix: 'RiDeleteBinLine' },
|
|
20
|
-
'message-square': { lucide: 'MessageSquare', tabler: 'IconMessage', phosphor: 'ChatCircle', remix: 'RiChat1Line' },
|
|
21
|
-
'type': { lucide: 'Type', tabler: 'IconTypography', phosphor: 'TextT', remix: 'RiFontSize' },
|
|
22
|
-
'panel-left': { lucide: 'PanelLeft', tabler: 'IconLayoutSidebar', phosphor: 'SidebarSimple', remix: 'RiLayoutLeftLine' },
|
|
23
|
-
'grip-vertical': { lucide: 'GripVertical', tabler: 'IconGripVertical', phosphor: 'DotsSixVertical', remix: 'RiDraggable' },
|
|
24
|
-
'search': { lucide: 'Search', tabler: 'IconSearch', phosphor: 'MagnifyingGlass', remix: 'RiSearchLine' },
|
|
25
|
-
'settings': { lucide: 'Settings', tabler: 'IconSettings', phosphor: 'Gear', remix: 'RiSettings3Line' },
|
|
26
|
-
'file-text': { lucide: 'FileText', tabler: 'IconFileText', phosphor: 'FileText', remix: 'RiFileTextLine' },
|
|
27
|
-
'users': { lucide: 'Users', tabler: 'IconUsers', phosphor: 'Users', remix: 'RiGroupLine' },
|
|
28
|
-
'folder': { lucide: 'Folder', tabler: 'IconFolder', phosphor: 'Folder', remix: 'RiFolderLine' },
|
|
29
|
-
'sun': { lucide: 'Sun', tabler: 'IconSun', phosphor: 'Sun', remix: 'RiSunLine' },
|
|
30
|
-
'moon': { lucide: 'Moon', tabler: 'IconMoon', phosphor: 'Moon', remix: 'RiMoonLine' },
|
|
31
|
-
'palette': { lucide: 'Palette', tabler: 'IconPalette', phosphor: 'Palette', remix: 'RiPaletteLine' },
|
|
32
|
-
'copy': { lucide: 'Copy', tabler: 'IconCopy', phosphor: 'Copy', remix: 'RiFileCopyLine' },
|
|
33
|
-
'check-circle': { lucide: 'CheckCircle', tabler: 'IconCircleCheck', phosphor: 'CheckCircle', remix: 'RiCheckboxCircleLine' },
|
|
34
|
-
'bar-chart': { lucide: 'BarChart3', tabler: 'IconChartBar', phosphor: 'ChartBar', remix: 'RiBarChartLine' },
|
|
35
|
-
'link': { lucide: 'Link', tabler: 'IconLink', phosphor: 'Link', remix: 'RiLinkM' },
|
|
36
|
-
'folder-open': { lucide: 'FolderOpen', tabler: 'IconFolderOpen', phosphor: 'FolderOpen', remix: 'RiFolderOpenLine' },
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Get the library-specific icon name for a canonical name. */
|
|
40
|
-
export function resolveIconName(canonical: string, library: IconLibrary): string {
|
|
41
|
-
return iconMap[canonical]?.[library] ?? iconMap[canonical]?.lucide ?? canonical
|
|
42
|
-
}
|
package/src/theme/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export { resolveTheme } from './resolve.js'
|
|
2
|
-
export { generateThemeCSS } from './generate-css.js'
|
|
3
|
-
export { presets, PRESET_FONTS, PRESET_RADIUS, PRESET_SPACING } from './presets.js'
|
|
4
|
-
export { baseColors } from './base-colors.js'
|
|
5
|
-
export { resolveThemeColor } from './theme-colors.js'
|
|
6
|
-
export { resolveChartColor } from './chart-colors.js'
|
|
7
|
-
export { radiusMap } from './radius.js'
|
|
8
|
-
export { spacingMap } from './spacing.js'
|
|
9
|
-
export { iconMap, resolveIconName } from './icon-map.js'
|
|
10
|
-
export { colors, BASE_COLOR_NAMES, HUE_NAMES } from './colors.js'
|
|
11
|
-
export { parseSeedToScale } from './generate-scale.js'
|
|
12
|
-
export { migrateThemeOverrides } from './migrate.js'
|
|
13
|
-
export { prismaThemeStorage } from './storage.js'
|
|
14
|
-
export type {
|
|
15
|
-
ThemeStorageAdapter,
|
|
16
|
-
PanelGlobalDelegate,
|
|
17
|
-
PrismaThemeStorageOptions,
|
|
18
|
-
} from './storage.js'
|
|
19
|
-
|
|
20
|
-
export type { ColorName, ColorScale, ColorStep } from './colors.js'
|
|
21
|
-
export type {
|
|
22
|
-
StylePreset,
|
|
23
|
-
BaseColor,
|
|
24
|
-
HueColor,
|
|
25
|
-
ThemeColor,
|
|
26
|
-
ChartColor,
|
|
27
|
-
RadiusPreset,
|
|
28
|
-
SpacingPreset,
|
|
29
|
-
IconLibrary,
|
|
30
|
-
ThemeFonts,
|
|
31
|
-
ThemeConfig,
|
|
32
|
-
ThemeMeta,
|
|
33
|
-
PresetDefinition,
|
|
34
|
-
} from './types.js'
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { migrateThemeOverrides } from './migrate.js'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* `migrateThemeOverrides` reads legacy `panelGlobal` rows on every theme
|
|
7
|
-
* GET. It runs against rows persisted before the schema renames landed
|
|
8
|
-
* (accentColor→themeColor, chartPalette→chartColor, preset 'default'
|
|
9
|
-
* gone, baseColor sentinels dropped). A silent regression here corrupts
|
|
10
|
-
* user themes on the next page load — covering it with unit tests is
|
|
11
|
-
* cheap and the matrix is small.
|
|
12
|
-
*/
|
|
13
|
-
describe('migrateThemeOverrides — non-object input', () => {
|
|
14
|
-
for (const bad of [null, undefined, 0, 'string', true, false] as const) {
|
|
15
|
-
it(`returns {} for ${JSON.stringify(bad)}`, () => {
|
|
16
|
-
assert.deepEqual(migrateThemeOverrides(bad), {})
|
|
17
|
-
})
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Arrays are objects in JS but the function uses them via the same
|
|
21
|
-
// key-walk; nothing should match → empty result.
|
|
22
|
-
it('returns {} for an array', () => {
|
|
23
|
-
assert.deepEqual(migrateThemeOverrides([1, 2, 3]), {})
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
describe('migrateThemeOverrides — preset rename', () => {
|
|
28
|
-
it("maps the legacy 'default' preset to 'vega'", () => {
|
|
29
|
-
assert.deepEqual(migrateThemeOverrides({ preset: 'default' }), { preset: 'vega' })
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('passes other preset names through unchanged', () => {
|
|
33
|
-
for (const preset of ['nova', 'maia', 'lyra', 'vega'] as const) {
|
|
34
|
-
assert.deepEqual(migrateThemeOverrides({ preset }), { preset })
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('ignores non-string preset values', () => {
|
|
39
|
-
assert.deepEqual(migrateThemeOverrides({ preset: 42 }), {})
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
describe('migrateThemeOverrides — baseColor mapping', () => {
|
|
44
|
-
it("maps 'slate' to 'mist'", () => {
|
|
45
|
-
assert.deepEqual(migrateThemeOverrides({ baseColor: 'slate' }), { baseColor: 'mist' })
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it("drops 'cream' (Vega's bg already supplies it)", () => {
|
|
49
|
-
assert.deepEqual(migrateThemeOverrides({ baseColor: 'cream' }), {})
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it("drops 'default' (sentinel; no override)", () => {
|
|
53
|
-
assert.deepEqual(migrateThemeOverrides({ baseColor: 'default' }), {})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('passes other baseColor values through unchanged', () => {
|
|
57
|
-
assert.deepEqual(migrateThemeOverrides({ baseColor: 'mist' }), { baseColor: 'mist' })
|
|
58
|
-
assert.deepEqual(migrateThemeOverrides({ baseColor: 'taupe' }), { baseColor: 'taupe' })
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
describe('migrateThemeOverrides — accentColor → themeColor', () => {
|
|
63
|
-
it("'terracotta' becomes 'base' when paired with preset=vega", () => {
|
|
64
|
-
const out = migrateThemeOverrides({ preset: 'default', accentColor: 'terracotta' })
|
|
65
|
-
// preset: 'default' migrates to 'vega' first; the terracotta branch
|
|
66
|
-
// reads the *migrated* preset, so the Vega-specific 'base' wins.
|
|
67
|
-
assert.deepEqual(out, { preset: 'vega', themeColor: 'base' })
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it("'terracotta' falls back to 'orange' when preset is not vega", () => {
|
|
71
|
-
const out = migrateThemeOverrides({ preset: 'nova', accentColor: 'terracotta' })
|
|
72
|
-
assert.deepEqual(out, { preset: 'nova', themeColor: 'orange' })
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it("'terracotta' alone (no preset) falls back to 'orange'", () => {
|
|
76
|
-
const out = migrateThemeOverrides({ accentColor: 'terracotta' })
|
|
77
|
-
assert.deepEqual(out, { themeColor: 'orange' })
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('passes other accentColor names through as themeColor', () => {
|
|
81
|
-
assert.deepEqual(migrateThemeOverrides({ accentColor: 'blue' }), { themeColor: 'blue' })
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('explicit themeColor wins over legacy accentColor', () => {
|
|
85
|
-
const out = migrateThemeOverrides({ accentColor: 'blue', themeColor: 'red' })
|
|
86
|
-
assert.deepEqual(out, { themeColor: 'red' })
|
|
87
|
-
})
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
describe('migrateThemeOverrides — chartPalette → chartColor', () => {
|
|
91
|
-
const map: Record<string, string> = {
|
|
92
|
-
ocean: 'sky',
|
|
93
|
-
sunset: 'orange',
|
|
94
|
-
forest: 'emerald',
|
|
95
|
-
berry: 'fuchsia',
|
|
96
|
-
terracotta: 'base',
|
|
97
|
-
default: 'base',
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
for (const [from, to] of Object.entries(map)) {
|
|
101
|
-
it(`maps chartPalette '${from}' to chartColor '${to}'`, () => {
|
|
102
|
-
assert.deepEqual(migrateThemeOverrides({ chartPalette: from }), { chartColor: to })
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
it('passes unmapped chartPalette names through as chartColor', () => {
|
|
107
|
-
assert.deepEqual(migrateThemeOverrides({ chartPalette: 'blue' }), { chartColor: 'blue' })
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
it('explicit chartColor wins over legacy chartPalette', () => {
|
|
111
|
-
const out = migrateThemeOverrides({ chartPalette: 'ocean', chartColor: 'red' })
|
|
112
|
-
assert.deepEqual(out, { chartColor: 'red' })
|
|
113
|
-
})
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
describe('migrateThemeOverrides — pass-through fields', () => {
|
|
117
|
-
it('forwards radius, iconLibrary, fonts, and cssVariables when shapes match', () => {
|
|
118
|
-
const fonts = { heading: 'Space Grotesk', body: 'Inter' }
|
|
119
|
-
const cssVariables = { '--custom-x': 'oklch(0.5 0.1 100)' }
|
|
120
|
-
const out = migrateThemeOverrides({
|
|
121
|
-
radius: 'large',
|
|
122
|
-
iconLibrary: 'tabler',
|
|
123
|
-
fonts,
|
|
124
|
-
cssVariables,
|
|
125
|
-
})
|
|
126
|
-
assert.deepEqual(out, {
|
|
127
|
-
radius: 'large',
|
|
128
|
-
iconLibrary: 'tabler',
|
|
129
|
-
fonts,
|
|
130
|
-
cssVariables,
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
it('drops radius/iconLibrary when they are not strings', () => {
|
|
135
|
-
const out = migrateThemeOverrides({ radius: 42, iconLibrary: null })
|
|
136
|
-
assert.deepEqual(out, {})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('drops fonts/cssVariables when they are not objects', () => {
|
|
140
|
-
const out = migrateThemeOverrides({ fonts: 'Inter', cssVariables: 'bad' })
|
|
141
|
-
assert.deepEqual(out, {})
|
|
142
|
-
})
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
describe('migrateThemeOverrides — composite migration', () => {
|
|
146
|
-
it('migrates a realistic pre-rename payload end-to-end', () => {
|
|
147
|
-
const legacy = {
|
|
148
|
-
preset: 'default',
|
|
149
|
-
baseColor: 'slate',
|
|
150
|
-
accentColor: 'terracotta',
|
|
151
|
-
chartPalette: 'ocean',
|
|
152
|
-
radius: 'medium',
|
|
153
|
-
iconLibrary: 'lucide',
|
|
154
|
-
fonts: { heading: 'Satoshi' },
|
|
155
|
-
}
|
|
156
|
-
const out = migrateThemeOverrides(legacy)
|
|
157
|
-
assert.deepEqual(out, {
|
|
158
|
-
preset: 'vega',
|
|
159
|
-
baseColor: 'mist',
|
|
160
|
-
themeColor: 'base', // terracotta + preset=vega
|
|
161
|
-
chartColor: 'sky', // ocean → sky
|
|
162
|
-
radius: 'medium',
|
|
163
|
-
iconLibrary: 'lucide',
|
|
164
|
-
fonts: { heading: 'Satoshi' },
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
it('a clean already-migrated payload is preserved', () => {
|
|
169
|
-
const current = {
|
|
170
|
-
preset: 'vega',
|
|
171
|
-
baseColor: 'mist',
|
|
172
|
-
themeColor: 'blue',
|
|
173
|
-
chartColor: 'sky',
|
|
174
|
-
radius: 'small',
|
|
175
|
-
}
|
|
176
|
-
assert.deepEqual(migrateThemeOverrides(current), current)
|
|
177
|
-
})
|
|
178
|
-
})
|