@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,308 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { ChevronDownIcon, InboxIcon } from 'lucide-react'
|
|
3
|
-
import type { ElementMeta } from '../../../schema/Element.js'
|
|
4
|
-
import { Checkbox } from '../../ui/checkbox.js'
|
|
5
|
-
import { GroupHeadingLink, useSpaNavClick } from './links.js'
|
|
6
|
-
import { GroupHeaderText } from './filters.js'
|
|
7
|
-
import type { NavigateFn } from '../../navigate.js'
|
|
8
|
-
|
|
9
|
-
// ─── Cards layout for `Table.contentLayout('cards')` ────────
|
|
10
|
-
|
|
11
|
-
type RenderElement = (el: ElementMeta, index: number) => React.ReactNode
|
|
12
|
-
type RenderRowActions = (rowId: string, rowRecord: Record<string, unknown> | undefined, actions: ElementMeta[]) => React.ReactNode
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Lookup tables for responsive grid column-counts in `contentLayout:
|
|
16
|
-
* 'cards'`. Tailwind's JIT scanner needs **literal** class strings; we
|
|
17
|
-
* can't construct them at runtime via template literals (`grid-cols-${n}`
|
|
18
|
-
* would never be matched). Limit to 1–6 columns + 12 — covers every
|
|
19
|
-
* reasonable card grid; bigger values are silently capped at 6 for
|
|
20
|
-
* non-base breakpoints in `cardsPerRowClasses`.
|
|
21
|
-
*/
|
|
22
|
-
const CARDS_GRID_COLS_BASE: Record<number, string> = {
|
|
23
|
-
1: 'grid-cols-1',
|
|
24
|
-
2: 'grid-cols-2',
|
|
25
|
-
3: 'grid-cols-3',
|
|
26
|
-
4: 'grid-cols-4',
|
|
27
|
-
5: 'grid-cols-5',
|
|
28
|
-
6: 'grid-cols-6',
|
|
29
|
-
12: 'grid-cols-12',
|
|
30
|
-
}
|
|
31
|
-
const CARDS_GRID_COLS_SM: Record<number, string> = {
|
|
32
|
-
1: 'sm:grid-cols-1', 2: 'sm:grid-cols-2', 3: 'sm:grid-cols-3',
|
|
33
|
-
4: 'sm:grid-cols-4', 5: 'sm:grid-cols-5', 6: 'sm:grid-cols-6',
|
|
34
|
-
12: 'sm:grid-cols-12',
|
|
35
|
-
}
|
|
36
|
-
const CARDS_GRID_COLS_MD: Record<number, string> = {
|
|
37
|
-
1: 'md:grid-cols-1', 2: 'md:grid-cols-2', 3: 'md:grid-cols-3',
|
|
38
|
-
4: 'md:grid-cols-4', 5: 'md:grid-cols-5', 6: 'md:grid-cols-6',
|
|
39
|
-
12: 'md:grid-cols-12',
|
|
40
|
-
}
|
|
41
|
-
const CARDS_GRID_COLS_LG: Record<number, string> = {
|
|
42
|
-
1: 'lg:grid-cols-1', 2: 'lg:grid-cols-2', 3: 'lg:grid-cols-3',
|
|
43
|
-
4: 'lg:grid-cols-4', 5: 'lg:grid-cols-5', 6: 'lg:grid-cols-6',
|
|
44
|
-
12: 'lg:grid-cols-12',
|
|
45
|
-
}
|
|
46
|
-
const CARDS_GRID_COLS_XL: Record<number, string> = {
|
|
47
|
-
1: 'xl:grid-cols-1', 2: 'xl:grid-cols-2', 3: 'xl:grid-cols-3',
|
|
48
|
-
4: 'xl:grid-cols-4', 5: 'xl:grid-cols-5', 6: 'xl:grid-cols-6',
|
|
49
|
-
12: 'xl:grid-cols-12',
|
|
50
|
-
}
|
|
51
|
-
const CARDS_GRID_COLS_2XL: Record<number, string> = {
|
|
52
|
-
1: '2xl:grid-cols-1', 2: '2xl:grid-cols-2', 3: '2xl:grid-cols-3',
|
|
53
|
-
4: '2xl:grid-cols-4', 5: '2xl:grid-cols-5', 6: '2xl:grid-cols-6',
|
|
54
|
-
12: '2xl:grid-cols-12',
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function pickCardCols(table: Record<number, string>, raw: number | undefined): string | undefined {
|
|
58
|
-
if (raw === undefined) return undefined
|
|
59
|
-
if (table[raw]) return table[raw]
|
|
60
|
-
// Snap unsupported values to nearest available — values outside [1,6]∪{12}
|
|
61
|
-
// round down. Already-clamped to [1,12] server-side.
|
|
62
|
-
if (raw >= 12) return table[12]
|
|
63
|
-
if (raw >= 6) return table[6]
|
|
64
|
-
if (raw >= 5) return table[5]
|
|
65
|
-
if (raw >= 4) return table[4]
|
|
66
|
-
if (raw >= 3) return table[3]
|
|
67
|
-
if (raw >= 2) return table[2]
|
|
68
|
-
return table[1]
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** Build a Tailwind grid-cols class string from a per-row config. Default
|
|
72
|
-
* `{ default: 1, sm: 2, lg: 3 }` mirrors Filament's typical card grid. */
|
|
73
|
-
export function cardsPerRowClasses(opts: Record<string, number> | undefined): string {
|
|
74
|
-
const cfg = opts ?? {}
|
|
75
|
-
const baseN = cfg['default'] ?? 1
|
|
76
|
-
const out: string[] = [pickCardCols(CARDS_GRID_COLS_BASE, baseN)!]
|
|
77
|
-
if (cfg['sm'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_SM, cfg['sm']); if (c) out.push(c) }
|
|
78
|
-
if (cfg['md'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_MD, cfg['md']); if (c) out.push(c) }
|
|
79
|
-
if (cfg['lg'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_LG, cfg['lg']); if (c) out.push(c) }
|
|
80
|
-
if (cfg['xl'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_XL, cfg['xl']); if (c) out.push(c) }
|
|
81
|
-
if (cfg['2xl'] !== undefined) { const c = pickCardCols(CARDS_GRID_COLS_2XL, cfg['2xl']); if (c) out.push(c) }
|
|
82
|
-
// Unset fallback covers Filament's typical default — 1 column on mobile,
|
|
83
|
-
// 2 on small screens, 3 on large.
|
|
84
|
-
if (Object.keys(cfg).length === 0) {
|
|
85
|
-
return 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3'
|
|
86
|
-
}
|
|
87
|
-
return out.join(' ')
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Card-grid body for `Table.contentLayout('cards')`. Renders the rows
|
|
93
|
-
* area only — the surrounding chrome (heading / search / filters /
|
|
94
|
-
* pagination / bulk-action toolbar / "Sort by" picker) lives in the
|
|
95
|
-
* parent `TableRendererBody` so both layouts share it.
|
|
96
|
-
*
|
|
97
|
-
* Each card renders its `_cardChildren` schema via the standard
|
|
98
|
-
* `renderElement` walker, so any display-Element (Heading, Text, Image,
|
|
99
|
-
* Icon, Badge entries, layout primitives, etc.) drops in without a new
|
|
100
|
-
* renderer. Per-row chrome attaches via the same `_recordUrl` /
|
|
101
|
-
* `_recordClasses` / `_visibleActions` / `_disabledActions` keys the
|
|
102
|
-
* table-mode renderer reads from — `loadTableRecords` is unchanged.
|
|
103
|
-
*
|
|
104
|
-
* Group banding splits the rows into contiguous sections by
|
|
105
|
-
* `_groupValue`, emitting a heading row above each section. The user's
|
|
106
|
-
* configured per-card grid (`cardsPerRow`) re-applies inside every
|
|
107
|
-
* section so the column count stays consistent.
|
|
108
|
-
*/
|
|
109
|
-
export function CardsLayoutBody({
|
|
110
|
-
rows, visibleIds, selected, toggleRow,
|
|
111
|
-
hasBulkActions, hasRowActions, rowActions, hasRecordUrl, hasRecordClasses,
|
|
112
|
-
activeEmpty, EmptyIcon, hasFilterOrSearch,
|
|
113
|
-
defaultGroup, groupColumnLabel, groupCollapsible, collapsedGroups, toggleGroupCollapsed,
|
|
114
|
-
cardsPerRow, navigate,
|
|
115
|
-
groupHeadingScopable, buildGroupKeyHref,
|
|
116
|
-
renderElement, renderRowActions,
|
|
117
|
-
}: {
|
|
118
|
-
rows: unknown[]
|
|
119
|
-
visibleIds: string[]
|
|
120
|
-
selected: Set<string>
|
|
121
|
-
toggleRow: (id: string) => void
|
|
122
|
-
hasBulkActions: boolean
|
|
123
|
-
hasRowActions: boolean
|
|
124
|
-
rowActions: ElementMeta[]
|
|
125
|
-
hasRecordUrl: boolean
|
|
126
|
-
hasRecordClasses: boolean
|
|
127
|
-
activeEmpty: { heading?: string; description?: string; icon?: string } | undefined
|
|
128
|
-
EmptyIcon: React.ComponentType<{ className?: string }>
|
|
129
|
-
hasFilterOrSearch: boolean
|
|
130
|
-
defaultGroup: string | undefined
|
|
131
|
-
groupColumnLabel: string | undefined
|
|
132
|
-
groupCollapsible: boolean
|
|
133
|
-
collapsedGroups: Record<string, boolean>
|
|
134
|
-
toggleGroupCollapsed: (groupValue: string) => void
|
|
135
|
-
cardsPerRow: Record<string, number> | undefined
|
|
136
|
-
navigate: NavigateFn
|
|
137
|
-
// Drill-in affordances. Sparse: when `groupHeadingScopable` is false,
|
|
138
|
-
// the heading renders as before; `buildGroupKeyHref` is unused.
|
|
139
|
-
groupHeadingScopable?: boolean
|
|
140
|
-
buildGroupKeyHref?: (value: string) => string
|
|
141
|
-
// Injected renderers — keeps the import cycle clean between
|
|
142
|
-
// SchemaRenderer.tsx's top-level dispatch and this body.
|
|
143
|
-
renderElement: RenderElement
|
|
144
|
-
renderRowActions: RenderRowActions
|
|
145
|
-
}) {
|
|
146
|
-
const gridClass = `grid gap-4 ${cardsPerRowClasses(cardsPerRow)}`
|
|
147
|
-
|
|
148
|
-
if (rows.length === 0) {
|
|
149
|
-
return (
|
|
150
|
-
<div className="rounded-xl border bg-card py-12 text-center">
|
|
151
|
-
<div className="flex flex-col items-center gap-2 text-muted-foreground">
|
|
152
|
-
<EmptyIcon className="size-8 opacity-60" />
|
|
153
|
-
<p className="text-base font-medium text-foreground">
|
|
154
|
-
{activeEmpty?.heading
|
|
155
|
-
?? (hasFilterOrSearch ? 'No matching records' : 'No records yet')}
|
|
156
|
-
</p>
|
|
157
|
-
{(activeEmpty?.description ||
|
|
158
|
-
(hasFilterOrSearch && !activeEmpty?.description)) && (
|
|
159
|
-
<p className="text-sm">
|
|
160
|
-
{activeEmpty?.description
|
|
161
|
-
?? 'Try clearing filters or adjusting your search.'}
|
|
162
|
-
</p>
|
|
163
|
-
)}
|
|
164
|
-
</div>
|
|
165
|
-
</div>
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Split rows into contiguous group-banded sections so each section
|
|
170
|
-
// can render its own heading + grid. Without an active group this is
|
|
171
|
-
// one section with no heading.
|
|
172
|
-
type Section = {
|
|
173
|
-
groupValue?: string
|
|
174
|
-
title?: string
|
|
175
|
-
description?: string
|
|
176
|
-
indices: number[]
|
|
177
|
-
}
|
|
178
|
-
const sections: Section[] = []
|
|
179
|
-
if (defaultGroup === undefined) {
|
|
180
|
-
sections.push({ indices: rows.map((_, i) => i) })
|
|
181
|
-
} else {
|
|
182
|
-
let current: Section | undefined
|
|
183
|
-
for (let i = 0; i < rows.length; i++) {
|
|
184
|
-
const r = rows[i] as Record<string, unknown>
|
|
185
|
-
const v = String(r['_groupValue'] ?? '')
|
|
186
|
-
if (current === undefined || current.groupValue !== v) {
|
|
187
|
-
const title = r['_groupTitle'] as string | undefined
|
|
188
|
-
const description = r['_groupDescription'] as string | undefined
|
|
189
|
-
current = { groupValue: v, indices: [], ...(title ? { title } : {}), ...(description ? { description } : {}) }
|
|
190
|
-
sections.push(current)
|
|
191
|
-
}
|
|
192
|
-
current.indices.push(i)
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return (
|
|
197
|
-
<div className="flex flex-col gap-4">
|
|
198
|
-
{sections.map((section, si) => {
|
|
199
|
-
const collapsed = groupCollapsible
|
|
200
|
-
&& section.groupValue !== undefined
|
|
201
|
-
&& collapsedGroups[section.groupValue] === true
|
|
202
|
-
return (
|
|
203
|
-
<div key={si} className="flex flex-col gap-3">
|
|
204
|
-
{section.groupValue !== undefined && (() => {
|
|
205
|
-
const drillable = groupHeadingScopable === true
|
|
206
|
-
&& buildGroupKeyHref !== undefined
|
|
207
|
-
&& section.groupValue !== ''
|
|
208
|
-
const headingText = (
|
|
209
|
-
<GroupHeaderText
|
|
210
|
-
label={groupColumnLabel}
|
|
211
|
-
value={section.groupValue}
|
|
212
|
-
title={section.title}
|
|
213
|
-
description={section.description}
|
|
214
|
-
/>
|
|
215
|
-
)
|
|
216
|
-
const headingNode = drillable
|
|
217
|
-
? <GroupHeadingLink href={buildGroupKeyHref!(section.groupValue!)} navigate={navigate}>{headingText}</GroupHeadingLink>
|
|
218
|
-
: headingText
|
|
219
|
-
if (groupCollapsible) {
|
|
220
|
-
return (
|
|
221
|
-
<div className="flex w-full items-center gap-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
222
|
-
<button
|
|
223
|
-
type="button"
|
|
224
|
-
className="inline-flex items-center"
|
|
225
|
-
onClick={() => toggleGroupCollapsed(section.groupValue!)}
|
|
226
|
-
aria-expanded={!collapsed}
|
|
227
|
-
aria-label={collapsed ? 'Expand group' : 'Collapse group'}
|
|
228
|
-
>
|
|
229
|
-
<ChevronDownIcon
|
|
230
|
-
className={[
|
|
231
|
-
'size-4 transition-transform',
|
|
232
|
-
collapsed ? '-rotate-90' : '',
|
|
233
|
-
].filter(Boolean).join(' ')}
|
|
234
|
-
/>
|
|
235
|
-
</button>
|
|
236
|
-
{headingNode}
|
|
237
|
-
</div>
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
return (
|
|
241
|
-
<div className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
242
|
-
{headingNode}
|
|
243
|
-
</div>
|
|
244
|
-
)
|
|
245
|
-
})()}
|
|
246
|
-
{!collapsed && (
|
|
247
|
-
<div className={gridClass}>
|
|
248
|
-
{section.indices.map((ri) => {
|
|
249
|
-
const id = visibleIds[ri]!
|
|
250
|
-
const recordObj = rows[ri] as Record<string, unknown>
|
|
251
|
-
const isSelected = selected.has(id)
|
|
252
|
-
const recordUrl = hasRecordUrl ? (recordObj['_recordUrl'] as string | undefined) : undefined
|
|
253
|
-
const customRowClasses = hasRecordClasses
|
|
254
|
-
? (recordObj['_recordClasses'] as string | undefined) ?? ''
|
|
255
|
-
: ''
|
|
256
|
-
const cardChildren = (recordObj['_cardChildren'] as ElementMeta[] | undefined) ?? []
|
|
257
|
-
const cardClassName = [
|
|
258
|
-
'group relative flex flex-col gap-3 rounded-xl border bg-card p-4 transition-colors',
|
|
259
|
-
recordUrl ? 'hover:border-primary/40 hover:bg-accent/30' : '',
|
|
260
|
-
isSelected ? 'border-primary ring-2 ring-primary/20' : '',
|
|
261
|
-
customRowClasses,
|
|
262
|
-
].filter(Boolean).join(' ')
|
|
263
|
-
|
|
264
|
-
return (
|
|
265
|
-
<div key={id} className={cardClassName}>
|
|
266
|
-
{recordUrl !== undefined && (
|
|
267
|
-
<a
|
|
268
|
-
href={recordUrl}
|
|
269
|
-
onClick={useSpaNavClick(recordUrl, navigate)}
|
|
270
|
-
aria-label="Open record"
|
|
271
|
-
className="absolute inset-0 z-0 rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
272
|
-
>
|
|
273
|
-
<span className="sr-only">Open record</span>
|
|
274
|
-
</a>
|
|
275
|
-
)}
|
|
276
|
-
{hasBulkActions && (
|
|
277
|
-
<div className="absolute top-3 right-3 z-10">
|
|
278
|
-
<Checkbox
|
|
279
|
-
aria-label={`Select row ${id}`}
|
|
280
|
-
checked={isSelected}
|
|
281
|
-
onCheckedChange={() => toggleRow(id)}
|
|
282
|
-
data-no-row-nav
|
|
283
|
-
/>
|
|
284
|
-
</div>
|
|
285
|
-
)}
|
|
286
|
-
<div className="relative z-[1] flex flex-col gap-3">
|
|
287
|
-
{cardChildren.length === 0 ? (
|
|
288
|
-
<div className="text-xs italic text-muted-foreground">
|
|
289
|
-
No card content configured.
|
|
290
|
-
</div>
|
|
291
|
-
) : cardChildren.map((c, i) => renderElement(c, i))}
|
|
292
|
-
</div>
|
|
293
|
-
{hasRowActions && (
|
|
294
|
-
<div className="relative z-10 mt-auto flex items-center justify-end pt-2 border-t border-border/60">
|
|
295
|
-
{renderRowActions(id, recordObj, rowActions)}
|
|
296
|
-
</div>
|
|
297
|
-
)}
|
|
298
|
-
</div>
|
|
299
|
-
)
|
|
300
|
-
})}
|
|
301
|
-
</div>
|
|
302
|
-
)}
|
|
303
|
-
</div>
|
|
304
|
-
)
|
|
305
|
-
})}
|
|
306
|
-
</div>
|
|
307
|
-
)
|
|
308
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import type { ElementMeta } from '../../../schema/Element.js'
|
|
3
|
-
import { TableRendererBody, type TableBodyDeps } from './TableRendererBody.js'
|
|
4
|
-
|
|
5
|
-
// ─── Table wrapper + deferred-load shell ────────────────────
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Tier-3 deferred-load shell. When `Resource.deferLoading = true`, the
|
|
10
|
-
* SSR pass marks each Table on the page as `deferred` + stamps a
|
|
11
|
-
* `tableUrl`. This wrapper paints a skeleton on first frame and fetches
|
|
12
|
-
* the actual rows from the JSON endpoint after mount; the inner
|
|
13
|
-
* `TableRendererBody` renders identically against either the SSR meta
|
|
14
|
-
* (non-deferred case) or the fetched meta (deferred case).
|
|
15
|
-
*
|
|
16
|
-
* SPA nav with a query change re-runs SSR, which re-stamps `deferred`
|
|
17
|
-
* — so the URL-change effect fires another fetch. The skeleton frame
|
|
18
|
-
* still shows current sort / search / page / filter chrome because the
|
|
19
|
-
* SSR pass mirrors URL state on the deferred Table.
|
|
20
|
-
*/
|
|
21
|
-
export function TableRenderer({ el, deps }: { el: ElementMeta; deps: TableBodyDeps }) {
|
|
22
|
-
const isDeferred = el['deferred'] === true && typeof el['tableUrl'] === 'string'
|
|
23
|
-
const tableUrl = isDeferred ? (el['tableUrl'] as string) : ''
|
|
24
|
-
|
|
25
|
-
// Track the URL search string so a navigation that changes filters /
|
|
26
|
-
// sort / page re-fires the fetch. Initialized lazy on first client
|
|
27
|
-
// render; on the SSR pass we just fall through to skeleton.
|
|
28
|
-
const [search, setSearch] = useState<string>(() =>
|
|
29
|
-
typeof window === 'undefined' ? '' : window.location.search,
|
|
30
|
-
)
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
if (!isDeferred) return
|
|
33
|
-
if (typeof window === 'undefined') return
|
|
34
|
-
setSearch(window.location.search)
|
|
35
|
-
}, [isDeferred, el])
|
|
36
|
-
|
|
37
|
-
const [deferredMeta, setDeferredMeta] = useState<ElementMeta | null>(null)
|
|
38
|
-
const [deferredError, setDeferredError] = useState<string | null>(null)
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
if (!isDeferred || !tableUrl) return
|
|
42
|
-
if (typeof window === 'undefined') return
|
|
43
|
-
let cancelled = false
|
|
44
|
-
setDeferredMeta(null)
|
|
45
|
-
setDeferredError(null)
|
|
46
|
-
fetch(tableUrl + search, {
|
|
47
|
-
headers: { 'Accept': 'application/json' },
|
|
48
|
-
credentials: 'same-origin',
|
|
49
|
-
})
|
|
50
|
-
.then(async r => {
|
|
51
|
-
const data = (await r.json()) as {
|
|
52
|
-
ok?: boolean
|
|
53
|
-
tables?: Record<string, unknown>[]
|
|
54
|
-
error?: string
|
|
55
|
-
}
|
|
56
|
-
if (cancelled) return
|
|
57
|
-
if (data.ok && Array.isArray(data.tables) && data.tables.length > 0) {
|
|
58
|
-
setDeferredMeta(data.tables[0] as ElementMeta)
|
|
59
|
-
} else {
|
|
60
|
-
setDeferredError(data.error ?? 'Failed to load table')
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
.catch(err => {
|
|
64
|
-
if (cancelled) return
|
|
65
|
-
setDeferredError(err instanceof Error ? err.message : 'Failed to load table')
|
|
66
|
-
})
|
|
67
|
-
return () => { cancelled = true }
|
|
68
|
-
}, [isDeferred, tableUrl, search])
|
|
69
|
-
|
|
70
|
-
if (isDeferred && deferredError) {
|
|
71
|
-
return (
|
|
72
|
-
<div className="rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive">
|
|
73
|
-
Failed to load table: {deferredError}
|
|
74
|
-
</div>
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
if (isDeferred && !deferredMeta) {
|
|
78
|
-
return <TableSkeleton el={el} />
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return <TableRendererBody el={isDeferred ? deferredMeta! : el} deps={deps} />
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Skeleton placeholder painted while a deferred-loaded table fetches
|
|
86
|
-
* its rows. Mirrors the table's heading + description chrome (already
|
|
87
|
-
* present on `el`) so the frame doesn't pop layout when the real rows
|
|
88
|
-
* arrive. Renders a small column header strip + 5 placeholder rows.
|
|
89
|
-
*/
|
|
90
|
-
export function TableSkeleton({ el }: { el: ElementMeta }) {
|
|
91
|
-
const heading = typeof el['heading'] === 'string' ? (el['heading'] as string) : undefined
|
|
92
|
-
const description = typeof el['description'] === 'string' ? (el['description'] as string) : undefined
|
|
93
|
-
const children = el.children ?? []
|
|
94
|
-
const colCount = Math.max(1, children.filter(c => c.type === 'column').length)
|
|
95
|
-
return (
|
|
96
|
-
<div className="space-y-3">
|
|
97
|
-
{(heading || description) ? (
|
|
98
|
-
<div className="space-y-1">
|
|
99
|
-
{heading ? <div className="text-lg font-semibold">{heading}</div> : null}
|
|
100
|
-
{description ? <div className="text-sm text-muted-foreground">{description}</div> : null}
|
|
101
|
-
</div>
|
|
102
|
-
) : null}
|
|
103
|
-
<div className="rounded-md border">
|
|
104
|
-
<div className="grid border-b bg-muted/50 px-4 py-2"
|
|
105
|
-
style={{ gridTemplateColumns: `repeat(${colCount}, minmax(0, 1fr))` }}>
|
|
106
|
-
{Array.from({ length: colCount }).map((_, i) => (
|
|
107
|
-
<div key={i} className="h-4 w-20 rounded bg-muted-foreground/20" />
|
|
108
|
-
))}
|
|
109
|
-
</div>
|
|
110
|
-
<div className="divide-y">
|
|
111
|
-
{Array.from({ length: 5 }).map((_, rowIdx) => (
|
|
112
|
-
<div key={rowIdx} className="grid items-center px-4 py-3"
|
|
113
|
-
style={{ gridTemplateColumns: `repeat(${colCount}, minmax(0, 1fr))` }}>
|
|
114
|
-
{Array.from({ length: colCount }).map((_, colIdx) => (
|
|
115
|
-
<div key={colIdx} className="h-4 w-2/3 rounded bg-muted-foreground/10 animate-pulse" />
|
|
116
|
-
))}
|
|
117
|
-
</div>
|
|
118
|
-
))}
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
</div>
|
|
122
|
-
)
|
|
123
|
-
}
|