@pilotiq/pilotiq 0.24.1 → 0.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -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/package.json +6 -1
- 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,348 +0,0 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useRef } from 'react'
|
|
2
|
-
import type { ElementMeta } from '../../schema/Element.js'
|
|
3
|
-
import { getIcon } from '../../icons/registry.js'
|
|
4
|
-
import { usePendingSuggestions, usePendingSuggestionsForField, type PendingSuggestion } from '../PendingSuggestionsContext.js'
|
|
5
|
-
import { getPendingSuggestionOverlay } from '../PendingSuggestionOverlayRegistry.js'
|
|
6
|
-
import { registerPendingSuggestionApplier, type PendingSuggestionApplier } from '../PendingSuggestionApplierRegistry.js'
|
|
7
|
-
import { FormIdContext, useFieldState } from '../FormStateContext.js'
|
|
8
|
-
import { getFieldPresenceComponent } from '../FieldPresenceRegistry.js'
|
|
9
|
-
import { getFieldFocusReporter } from '../FieldFocusReporterRegistry.js'
|
|
10
|
-
import { useCollabRoom } from '../CollabRoomContext.js'
|
|
11
|
-
import { getCollabTextRenderer } from '../CollabTextRendererRegistry.js'
|
|
12
|
-
import { getMarkdownEditor } from '../MarkdownEditorRegistry.js'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Field types whose visible state is driven by React (not by a matching
|
|
16
|
-
* `[name]` DOM input). Each registers its own applier inside the field
|
|
17
|
-
* renderer; FieldShell skips its generic DOM-write applier for these so
|
|
18
|
-
* the field-owned applier stays last-write-wins in the registry. Keep in
|
|
19
|
-
* sync with the per-field `useEffect(registerPendingSuggestionApplier…)`
|
|
20
|
-
* blocks under `react/fields/`.
|
|
21
|
-
*/
|
|
22
|
-
const SELF_APPLIER_FIELD_TYPES = new Set<string>([
|
|
23
|
-
'select',
|
|
24
|
-
'toggle',
|
|
25
|
-
'slider',
|
|
26
|
-
'color',
|
|
27
|
-
'keyValue',
|
|
28
|
-
'fileUpload',
|
|
29
|
-
'tagsInput',
|
|
30
|
-
'dateTime',
|
|
31
|
-
'radio',
|
|
32
|
-
'checkboxList',
|
|
33
|
-
])
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Shared chrome around every field input — label + required asterisk +
|
|
37
|
-
* helper text + prefix/suffix decoration. The actual input component
|
|
38
|
-
* is passed as `children`. Keeps `renderField` in `SchemaRenderer.tsx`
|
|
39
|
-
* lean: dispatcher above, layout here.
|
|
40
|
-
*
|
|
41
|
-
* Decoration: `prefix` / `suffix` may be a plain string or an icon
|
|
42
|
-
* descriptor (`{ icon: 'name' }` / `{ icon: { class } }`). Strings
|
|
43
|
-
* render inside a muted-foreground span; icons resolve via the
|
|
44
|
-
* registry. When neither prefix nor suffix is present the input
|
|
45
|
-
* renders without any extra wrapper to preserve the legacy DOM.
|
|
46
|
-
*/
|
|
47
|
-
export interface FieldShellProps {
|
|
48
|
-
el: ElementMeta
|
|
49
|
-
name: string
|
|
50
|
-
label: string
|
|
51
|
-
required: boolean
|
|
52
|
-
children: React.ReactNode
|
|
53
|
-
/** Optional ReactNode rendered to the left of the input, after the
|
|
54
|
-
* passive `prefix` decoration (when set). Used by `TextField`'s
|
|
55
|
-
* `prefixAction()` / mask / datalist / etc. — composes with the
|
|
56
|
-
* passive `prefix` slot rather than replacing it. */
|
|
57
|
-
before?: React.ReactNode
|
|
58
|
-
/** Right-of-input counterpart. Used by `revealable() / copyable() /
|
|
59
|
-
* suffixAction()`. Renders after the passive `suffix` decoration. */
|
|
60
|
-
after?: React.ReactNode
|
|
61
|
-
/** Optional ReactNode rendered inline next to the label — used by
|
|
62
|
-
* plugins that register via `registerFieldLabelSlot()`. */
|
|
63
|
-
labelSlot?: React.ReactNode
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function FieldShell({ el, name, label, required, children, before, after, labelSlot }: FieldShellProps): React.ReactElement {
|
|
67
|
-
const prefix = el['prefix'] as string | { icon: string } | undefined
|
|
68
|
-
const suffix = el['suffix'] as string | { icon: string } | undefined
|
|
69
|
-
const helperText = el['helperText'] as string | undefined
|
|
70
|
-
const inline = el['inlineLabel'] === true
|
|
71
|
-
const hiddenLabel = el['hiddenLabel'] === true
|
|
72
|
-
const wrapperAttrs = pickWrapperAttrs(el)
|
|
73
|
-
|
|
74
|
-
// Pending-suggestion overlay (Plan 6/7). RichText fields render the diff
|
|
75
|
-
// inline inside the editor instead — they opt out via the hidden marker
|
|
76
|
-
// below. Other field types pick up the slot whenever a plugin (e.g.
|
|
77
|
-
// `@pilotiq-pro/ai`) has registered a renderer AND there's a matching
|
|
78
|
-
// suggestion in the queue.
|
|
79
|
-
const fieldType = el['fieldType'] as string | undefined
|
|
80
|
-
// `isTiptapMounted` widens "richtext only" to every field whose visible
|
|
81
|
-
// surface is actually a Tiptap editor — covers MarkdownField (always
|
|
82
|
-
// Tiptap via `MarkdownEditor`), TextField / TextareaField when a collab
|
|
83
|
-
// room is active OR when AI agents are attached (uses `CollabTextRenderer`
|
|
84
|
-
// via @pilotiq/tiptap). For these the editor renders inline-diff
|
|
85
|
-
// Approve/Reject chips and owns its own applier through
|
|
86
|
-
// `useAiSuggestionBridge` — FieldShell hides the legacy overlay AND skips
|
|
87
|
-
// registering its DOM-write applier so the bridge's applier stays
|
|
88
|
-
// last-write-wins.
|
|
89
|
-
//
|
|
90
|
-
// Keep the AI-attached branch in sync with `TextLikeInput`'s gate — both
|
|
91
|
-
// need to flip together or the surface diverges (overlay would mount
|
|
92
|
-
// alongside the inline chip, etc.).
|
|
93
|
-
const collabRoom = useCollabRoom()
|
|
94
|
-
const hasCollabTextRenderer = getCollabTextRenderer() !== null
|
|
95
|
-
const hasMarkdownEditor = getMarkdownEditor() !== null
|
|
96
|
-
const aiActions = el['aiActions']
|
|
97
|
-
const hasAi = Array.isArray(aiActions) && aiActions.length > 0
|
|
98
|
-
const isTextLikeTiptap =
|
|
99
|
-
(fieldType === 'text' || fieldType === 'textarea') &&
|
|
100
|
-
(collabRoom !== null || hasAi) && hasCollabTextRenderer
|
|
101
|
-
const isMarkdownTiptap = fieldType === 'markdown' && hasMarkdownEditor
|
|
102
|
-
const isRichText = fieldType === 'richtext' || isMarkdownTiptap || isTextLikeTiptap
|
|
103
|
-
// Field types that drive their visible state from React (not from a
|
|
104
|
-
// matching `[name]` DOM input) register their own applier — see
|
|
105
|
-
// `SelectFieldInput` for the canonical example. FieldShell's generic
|
|
106
|
-
// DOM-write applier would silently no-op on these, and (since parent
|
|
107
|
-
// effects run AFTER children) would overwrite the field-owned applier
|
|
108
|
-
// in the registry. Skip registration here so the field-owned applier
|
|
109
|
-
// stays the winner.
|
|
110
|
-
const ownsApplier = fieldType !== undefined && SELF_APPLIER_FIELD_TYPES.has(fieldType)
|
|
111
|
-
const { list: pending, dismiss } = usePendingSuggestionsForField(name)
|
|
112
|
-
const { approve } = usePendingSuggestions()
|
|
113
|
-
const Overlay = isRichText ? null : getPendingSuggestionOverlay()
|
|
114
|
-
const overlaySuggestion = pending[0] ?? null
|
|
115
|
-
// Approve routes through the cross-tree applier registry (Phase 8.5)
|
|
116
|
-
// so field types that own their visible state (Select / Toggle / Slider /
|
|
117
|
-
// Color / etc.) get their registered applier — not the overlay's
|
|
118
|
-
// hardcoded `field.setValue` + DOM-write fallback, which would silently
|
|
119
|
-
// miss the React state of those custom components. Reject just dismisses
|
|
120
|
-
// and restores focus to the input so the user can keep typing without
|
|
121
|
-
// a stray click.
|
|
122
|
-
const onReject = (): void => {
|
|
123
|
-
dismiss(overlaySuggestion!.id)
|
|
124
|
-
if (typeof document === 'undefined') return
|
|
125
|
-
queueMicrotask(() => {
|
|
126
|
-
const el = document.getElementsByName(name)[0]
|
|
127
|
-
if (el instanceof HTMLElement) el.focus()
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
const overlayNode = Overlay && overlaySuggestion ? (
|
|
131
|
-
<Overlay
|
|
132
|
-
suggestion={overlaySuggestion}
|
|
133
|
-
onApprove={() => approve(overlaySuggestion.id)}
|
|
134
|
-
onReject={onReject}
|
|
135
|
-
{...(fieldType !== undefined ? { fieldType } : {})}
|
|
136
|
-
el={el}
|
|
137
|
-
/>
|
|
138
|
-
) : null
|
|
139
|
-
|
|
140
|
-
// Cross-tree applier registration (Phase 8.5). Lets aggregate consumers
|
|
141
|
-
// (e.g. a chat-sidebar pending-pill living outside the form's React
|
|
142
|
-
// tree) reach this field's mutator via
|
|
143
|
-
// `PendingSuggestionApplierRegistry`. Skipped for richtext — the
|
|
144
|
-
// Tiptap bridge registers its own editor-command applier. Skipped for
|
|
145
|
-
// dotted-path fields (Repeater inner rows) since `useFieldState` is
|
|
146
|
-
// a no-op for them; pill-driven approve falls back to `dismiss` which
|
|
147
|
-
// is the right semantics (pill cannot reach into row state).
|
|
148
|
-
const fieldState = useFieldState(name)
|
|
149
|
-
const fieldStateRef = useRef(fieldState)
|
|
150
|
-
useEffect(() => { fieldStateRef.current = fieldState }, [fieldState])
|
|
151
|
-
const formId = useContext(FormIdContext) || undefined
|
|
152
|
-
useEffect(() => {
|
|
153
|
-
if (isRichText) return
|
|
154
|
-
if (ownsApplier) return
|
|
155
|
-
if (name.includes('.')) return
|
|
156
|
-
const applier: PendingSuggestionApplier = (suggestion) => {
|
|
157
|
-
const fs = fieldStateRef.current
|
|
158
|
-
if (fs.controlled) {
|
|
159
|
-
fs.setValue(suggestion.suggestedValue)
|
|
160
|
-
} else {
|
|
161
|
-
applyToUncontrolledInputs(name, suggestion.suggestedValue)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return registerPendingSuggestionApplier(formId, name, applier)
|
|
165
|
-
}, [isRichText, ownsApplier, name, formId])
|
|
166
|
-
|
|
167
|
-
const labelClass = hiddenLabel
|
|
168
|
-
? 'sr-only'
|
|
169
|
-
: 'text-sm font-medium leading-none'
|
|
170
|
-
// Phase F4 — presence chip + focus reporter slots. The chip mounts
|
|
171
|
-
// alongside the label so remote-focus indicators don't shift the
|
|
172
|
-
// input geometry; the focus reporter sits on the outer wrapper using
|
|
173
|
-
// capture-phase listeners so any inner-input focus event flows
|
|
174
|
-
// through. Both slots are gated on `meta.collab !== false` (Q3 from
|
|
175
|
-
// the F-plan — opted-out fields are fully invisible to the collab
|
|
176
|
-
// layer) AND on the field having a stable top-level name (dotted-path
|
|
177
|
-
// Repeater rows skip presence in v1 — Phase F.5).
|
|
178
|
-
const collabOptedOut = (el as { collab?: boolean })['collab'] === false
|
|
179
|
-
const dottedName = name.includes('.')
|
|
180
|
-
const presenceSlotEligible = !collabOptedOut && !dottedName
|
|
181
|
-
const PresenceChip = presenceSlotEligible ? getFieldPresenceComponent() : null
|
|
182
|
-
const focusReporter = presenceSlotEligible ? getFieldFocusReporter() : null
|
|
183
|
-
|
|
184
|
-
const labelEl = label !== '' ? (
|
|
185
|
-
<label htmlFor={name} className={labelClass}>
|
|
186
|
-
{label}{required && <span className="text-destructive ml-0.5">*</span>}
|
|
187
|
-
{labelSlot}
|
|
188
|
-
{PresenceChip && <PresenceChip fieldName={name} formId={formId ?? ''} />}
|
|
189
|
-
</label>
|
|
190
|
-
) : null
|
|
191
|
-
|
|
192
|
-
const hasDecoration = !!(prefix || suffix || before || after)
|
|
193
|
-
const input = hasDecoration
|
|
194
|
-
? (
|
|
195
|
-
<div className="flex items-center gap-2">
|
|
196
|
-
{before}
|
|
197
|
-
{prefix && <Decoration content={prefix} side="prefix" />}
|
|
198
|
-
<div className="flex-1 min-w-0">{children}</div>
|
|
199
|
-
{suffix && <Decoration content={suffix} side="suffix" />}
|
|
200
|
-
{after}
|
|
201
|
-
</div>
|
|
202
|
-
)
|
|
203
|
-
: children
|
|
204
|
-
|
|
205
|
-
// When a suggestion is pending we hide the real input visually but
|
|
206
|
-
// keep it in the DOM — both so the applier's DOM-write fallback can
|
|
207
|
-
// resolve `[name="…"]` and so the input doesn't unmount + lose its
|
|
208
|
-
// typed value. The wrapper div is rendered unconditionally (just
|
|
209
|
-
// toggling a class) — switching between bare input and wrapped input
|
|
210
|
-
// would unmount the uncontrolled `<input>`, resetting its value to
|
|
211
|
-
// `defaultValue` and silently undoing the approved write right after
|
|
212
|
-
// the overlay closes.
|
|
213
|
-
const inputBlock = (
|
|
214
|
-
<>
|
|
215
|
-
<div className={overlayNode !== null ? 'hidden' : 'contents'} aria-hidden={overlayNode !== null}>
|
|
216
|
-
{input}
|
|
217
|
-
</div>
|
|
218
|
-
{overlayNode}
|
|
219
|
-
</>
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
// Capture-phase focus / blur dispatch — runs even when the inner
|
|
223
|
-
// input is wrapped in custom NodeViews (Select / Date / Slider). One
|
|
224
|
-
// wrapper-level handler covers every controlled input in the tree.
|
|
225
|
-
const onFocusCapture = focusReporter
|
|
226
|
-
? () => focusReporter.onFocus({ fieldName: name, formId: formId ?? '' })
|
|
227
|
-
: undefined
|
|
228
|
-
const onBlurCapture = focusReporter
|
|
229
|
-
? () => focusReporter.onBlur({ fieldName: name, formId: formId ?? '' })
|
|
230
|
-
: undefined
|
|
231
|
-
|
|
232
|
-
if (inline) {
|
|
233
|
-
return (
|
|
234
|
-
<div
|
|
235
|
-
className="flex items-baseline gap-3"
|
|
236
|
-
{...wrapperAttrs}
|
|
237
|
-
{...(onFocusCapture ? { onFocusCapture } : {})}
|
|
238
|
-
{...(onBlurCapture ? { onBlurCapture } : {})}
|
|
239
|
-
>
|
|
240
|
-
{labelEl && <div className="min-w-32 pt-2">{labelEl}</div>}
|
|
241
|
-
<div className="min-w-0 flex-1">
|
|
242
|
-
{inputBlock}
|
|
243
|
-
{helperText && (
|
|
244
|
-
<p className="mt-1 text-xs text-muted-foreground">{helperText}</p>
|
|
245
|
-
)}
|
|
246
|
-
</div>
|
|
247
|
-
</div>
|
|
248
|
-
)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return (
|
|
252
|
-
<div
|
|
253
|
-
className="flex flex-col gap-1.5"
|
|
254
|
-
{...wrapperAttrs}
|
|
255
|
-
{...(onFocusCapture ? { onFocusCapture } : {})}
|
|
256
|
-
{...(onBlurCapture ? { onBlurCapture } : {})}
|
|
257
|
-
>
|
|
258
|
-
{labelEl}
|
|
259
|
-
{inputBlock}
|
|
260
|
-
{helperText && (
|
|
261
|
-
<p className="text-xs text-muted-foreground">{helperText}</p>
|
|
262
|
-
)}
|
|
263
|
-
</div>
|
|
264
|
-
)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Best-effort DOM apply for forms without a `<FormStateProvider>` (i.e.
|
|
269
|
-
* forms whose fields aren't `live()`). Walks every `[name="…"]` input,
|
|
270
|
-
* uses React's internal value-setter (`Object.getOwnPropertyDescriptor`)
|
|
271
|
-
* so the change is visible to `onChange` handlers + uncontrolled
|
|
272
|
-
* `defaultValue` paths. Coercion is intentionally minimal — `String()`
|
|
273
|
-
* for primitives, `JSON.stringify` for objects/arrays.
|
|
274
|
-
*
|
|
275
|
-
* Used by FieldShell's pending-suggestion applier and exposed for
|
|
276
|
-
* plugins that need the same fallback.
|
|
277
|
-
*/
|
|
278
|
-
function applyToUncontrolledInputs(fieldName: string, value: unknown): void {
|
|
279
|
-
if (typeof document === 'undefined') return
|
|
280
|
-
const stringValue = typeof value === 'string'
|
|
281
|
-
? value
|
|
282
|
-
: typeof value === 'number' || typeof value === 'boolean'
|
|
283
|
-
? String(value)
|
|
284
|
-
: safeStringify(value)
|
|
285
|
-
|
|
286
|
-
const elements = document.getElementsByName(fieldName)
|
|
287
|
-
for (const el of Array.from(elements)) {
|
|
288
|
-
if (el instanceof HTMLInputElement) {
|
|
289
|
-
if (el.type === 'checkbox') {
|
|
290
|
-
const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'checked')?.set
|
|
291
|
-
setter?.call(el, Boolean(value))
|
|
292
|
-
} else {
|
|
293
|
-
setNativeValue(HTMLInputElement.prototype, el, stringValue)
|
|
294
|
-
}
|
|
295
|
-
} else if (el instanceof HTMLTextAreaElement) {
|
|
296
|
-
setNativeValue(HTMLTextAreaElement.prototype, el, stringValue)
|
|
297
|
-
} else if (el instanceof HTMLSelectElement) {
|
|
298
|
-
setNativeValue(HTMLSelectElement.prototype, el, stringValue)
|
|
299
|
-
} else {
|
|
300
|
-
continue
|
|
301
|
-
}
|
|
302
|
-
el.dispatchEvent(new Event('input', { bubbles: true }))
|
|
303
|
-
el.dispatchEvent(new Event('change', { bubbles: true }))
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function setNativeValue(proto: object, el: HTMLElement, value: string): void {
|
|
308
|
-
const desc = Object.getOwnPropertyDescriptor(proto, 'value')
|
|
309
|
-
desc?.set?.call(el, value)
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function safeStringify(value: unknown): string {
|
|
313
|
-
if (value === null || value === undefined) return ''
|
|
314
|
-
try { return JSON.stringify(value) ?? '' }
|
|
315
|
-
catch { return '' }
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Merge `extraAttributes` (Filament-parity short name) and
|
|
320
|
-
* `extraFieldWrapperAttributes` (verbose alias) into one record. Latter
|
|
321
|
-
* wins on key collisions so callers who set both can override.
|
|
322
|
-
*/
|
|
323
|
-
function pickWrapperAttrs(el: ElementMeta): Record<string, string | number | boolean> {
|
|
324
|
-
const a = el['extraAttributes'] as Record<string, string | number | boolean> | undefined
|
|
325
|
-
const b = el['extraFieldWrapperAttributes'] as Record<string, string | number | boolean> | undefined
|
|
326
|
-
if (!a && !b) return {}
|
|
327
|
-
return { ...(a ?? {}), ...(b ?? {}) }
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function Decoration({ content, side }: {
|
|
331
|
-
content: string | { icon: string }
|
|
332
|
-
side: 'prefix' | 'suffix'
|
|
333
|
-
}): React.ReactElement {
|
|
334
|
-
if (typeof content === 'string') {
|
|
335
|
-
return (
|
|
336
|
-
<span className="text-sm text-muted-foreground shrink-0" data-side={side}>
|
|
337
|
-
{content}
|
|
338
|
-
</span>
|
|
339
|
-
)
|
|
340
|
-
}
|
|
341
|
-
return <DecorationIcon name={content.icon} />
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function DecorationIcon({ name }: { name: string }): React.ReactElement | null {
|
|
345
|
-
const Icon = getIcon(name) as React.ComponentType<{ className?: string; 'aria-hidden'?: boolean | 'true' | 'false' }> | undefined
|
|
346
|
-
if (!Icon) return null
|
|
347
|
-
return <Icon className="size-4 text-muted-foreground shrink-0" aria-hidden="true" />
|
|
348
|
-
}
|