@object-ui/app-shell 6.2.3 → 7.0.0
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 +948 -0
- package/README.md +292 -0
- package/dist/assistant/assistantBus.d.ts +72 -0
- package/dist/assistant/assistantBus.js +133 -0
- package/dist/chrome/CommandPalette.d.ts +1 -1
- package/dist/chrome/CommandPalette.js +26 -22
- package/dist/chrome/ConditionalAuthWrapper.d.ts +1 -1
- package/dist/chrome/ConsoleToaster.d.ts +1 -1
- package/dist/chrome/ConsoleToaster.js +3 -1
- package/dist/chrome/ErrorBoundary.d.ts +1 -1
- package/dist/chrome/KeyboardShortcutsDialog.d.ts +1 -1
- package/dist/chrome/KeyboardShortcutsDialog.js +16 -5
- package/dist/chrome/LoadingScreen.d.ts +1 -1
- package/dist/chrome/LoadingScreen.js +22 -26
- package/dist/chrome/RouteFader.d.ts +1 -1
- package/dist/chrome/ThemeProvider.d.ts +1 -1
- package/dist/components/ManagedByBadge.d.ts +1 -1
- package/dist/console/AppContent.d.ts +1 -1
- package/dist/console/AppContent.js +170 -37
- package/dist/console/ConsoleShell.d.ts +7 -7
- package/dist/console/ConsoleShell.js +32 -3
- package/dist/console/ai/AiChatPage.d.ts +88 -1
- package/dist/console/ai/AiChatPage.js +743 -66
- package/dist/console/ai/ConversationsSidebar.d.ts +26 -1
- package/dist/console/ai/ConversationsSidebar.js +149 -34
- package/dist/console/ai/LiveCanvas.d.ts +22 -0
- package/dist/console/ai/LiveCanvas.js +78 -0
- package/dist/console/ai/reconcileTurn.d.ts +8 -0
- package/dist/console/ai/reconcileTurn.js +20 -0
- package/dist/console/auth/AuthPageLayout.d.ts +1 -1
- package/dist/console/auth/ForgotPasswordPage.d.ts +1 -1
- package/dist/console/auth/LoginPage.d.ts +1 -1
- package/dist/console/auth/RegisterPage.d.ts +1 -1
- package/dist/console/auth/RegisterPage.js +23 -3
- package/dist/console/cloud-connection/CloudConnectionPanel.d.ts +1 -0
- package/dist/console/cloud-connection/CloudConnectionPanel.js +169 -0
- package/dist/console/home/AppCard.d.ts +1 -1
- package/dist/console/home/AppCard.js +6 -12
- package/dist/console/home/HomeAppsStrip.d.ts +8 -0
- package/dist/console/home/HomeAppsStrip.js +61 -0
- package/dist/console/home/HomeLayout.d.ts +1 -1
- package/dist/console/home/HomeLayout.js +3 -1
- package/dist/console/home/HomePage.d.ts +1 -2
- package/dist/console/home/HomePage.js +149 -21
- package/dist/console/home/HomeRail.d.ts +22 -0
- package/dist/console/home/HomeRail.js +62 -0
- package/dist/console/home/QuickActions.d.ts +1 -1
- package/dist/console/home/QuickActions.js +3 -11
- package/dist/console/home/RecentApps.d.ts +1 -1
- package/dist/console/home/RecentApps.js +2 -2
- package/dist/console/home/StarredApps.d.ts +1 -1
- package/dist/console/home/StarredApps.js +2 -2
- package/dist/console/marketplace/InstalledListWidget.d.ts +1 -0
- package/dist/console/marketplace/InstalledListWidget.js +93 -0
- package/dist/console/marketplace/MarkdownText.d.ts +1 -1
- package/dist/console/marketplace/MarketplaceAccessDenied.d.ts +1 -1
- package/dist/console/marketplace/MarketplaceInstalledPage.d.ts +8 -14
- package/dist/console/marketplace/MarketplaceInstalledPage.js +14 -66
- package/dist/console/marketplace/MarketplacePackagePage.d.ts +1 -1
- package/dist/console/marketplace/MarketplacePackagePage.js +249 -8
- package/dist/console/marketplace/MarketplacePage.d.ts +1 -1
- package/dist/console/marketplace/MarketplacePage.js +60 -3
- package/dist/console/marketplace/PackageIcon.d.ts +1 -1
- package/dist/console/marketplace/PluginDisclosure.d.ts +14 -0
- package/dist/console/marketplace/PluginDisclosure.js +38 -0
- package/dist/console/marketplace/marketplaceApi.d.ts +123 -0
- package/dist/console/marketplace/marketplaceApi.js +254 -1
- package/dist/console/organizations/CreateWorkspaceDialog.d.ts +1 -1
- package/dist/console/organizations/OrganizationsLayout.d.ts +1 -1
- package/dist/console/organizations/OrganizationsPage.d.ts +1 -1
- package/dist/console/organizations/manage/AcceptInvitationPage.d.ts +1 -1
- package/dist/console/organizations/manage/InvitationsPage.d.ts +1 -1
- package/dist/console/organizations/manage/InviteMemberDialog.d.ts +1 -1
- package/dist/console/organizations/manage/MembersPage.d.ts +1 -1
- package/dist/console/organizations/manage/OrganizationLayout.d.ts +1 -1
- package/dist/console/organizations/manage/SettingsPage.d.ts +1 -1
- package/dist/context/CommandPaletteProvider.d.ts +44 -0
- package/dist/context/CommandPaletteProvider.js +71 -0
- package/dist/context/FavoritesProvider.d.ts +1 -1
- package/dist/context/NavigationContext.d.ts +1 -1
- package/dist/context/RecentItemsProvider.d.ts +2 -2
- package/dist/context/UserStateAdapters.d.ts +1 -1
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.js +1 -0
- package/dist/hooks/index.d.ts +5 -2
- package/dist/hooks/index.js +4 -1
- package/dist/hooks/useActionModal.d.ts +53 -0
- package/dist/hooks/useActionModal.js +111 -0
- package/dist/hooks/useChatConversation.d.ts +107 -4
- package/dist/hooks/useChatConversation.js +253 -25
- package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
- package/dist/hooks/useConsoleActionRuntime.js +560 -0
- package/dist/hooks/useConversationList.js +61 -3
- package/dist/hooks/useHomeInbox.d.ts +13 -0
- package/dist/hooks/useHomeInbox.js +142 -0
- package/dist/hooks/useNavPins.js +17 -23
- package/dist/hooks/useNavigationSync.d.ts +33 -0
- package/dist/hooks/useNavigationSync.js +98 -12
- package/dist/hooks/useReconcileOnError.d.ts +40 -0
- package/dist/hooks/useReconcileOnError.js +37 -0
- package/dist/hooks/useRecordApprovals.d.ts +18 -19
- package/dist/hooks/useRecordApprovals.js +24 -40
- package/dist/hooks/useResponsiveSidebar.js +14 -5
- package/dist/hooks/useSettleSignal.d.ts +19 -0
- package/dist/hooks/useSettleSignal.js +20 -0
- package/dist/hooks/useTrackRouteAsRecent.js +35 -0
- package/dist/hooks/useUrlOverlay.d.ts +62 -0
- package/dist/hooks/useUrlOverlay.js +88 -0
- package/dist/index.d.ts +16 -7
- package/dist/index.js +12 -4
- package/dist/layout/ActivityFeed.d.ts +1 -1
- package/dist/layout/AppHeader.d.ts +3 -2
- package/dist/layout/AppHeader.js +237 -72
- package/dist/layout/AppSidebar.d.ts +2 -1
- package/dist/layout/AppSidebar.js +26 -46
- package/dist/layout/AppSwitcher.d.ts +2 -1
- package/dist/layout/AppSwitcher.js +9 -5
- package/dist/layout/AuthPageLayout.d.ts +1 -1
- package/dist/layout/ConnectionStatus.d.ts +1 -1
- package/dist/layout/ConnectionStatus.js +9 -6
- package/dist/layout/ConsoleChatbotFab.d.ts +19 -1
- package/dist/layout/ConsoleChatbotFab.js +16 -2
- package/dist/layout/ConsoleFloatingChatbot.d.ts +32 -2
- package/dist/layout/ConsoleFloatingChatbot.js +374 -41
- package/dist/layout/ConsoleLayout.d.ts +1 -1
- package/dist/layout/ConsoleLayout.js +27 -11
- package/dist/layout/ContextSelectors.d.ts +44 -0
- package/dist/layout/ContextSelectors.js +218 -0
- package/dist/layout/InboxPopover.d.ts +6 -1
- package/dist/layout/InboxPopover.js +25 -6
- package/dist/layout/LocaleSwitcher.d.ts +1 -1
- package/dist/layout/LocalizedSidebarTrigger.d.ts +2 -0
- package/dist/layout/LocalizedSidebarTrigger.js +15 -0
- package/dist/layout/MobileViewSwitcherContext.d.ts +1 -1
- package/dist/layout/ModeToggle.d.ts +1 -1
- package/dist/layout/PageHeader.d.ts +1 -1
- package/dist/layout/UnifiedSidebar.d.ts +2 -1
- package/dist/layout/UnifiedSidebar.js +116 -15
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.js +1 -0
- package/dist/observability/settleSignal.d.ts +64 -0
- package/dist/observability/settleSignal.js +131 -0
- package/dist/preview/DraftChangesPanel.d.ts +19 -0
- package/dist/preview/DraftChangesPanel.js +114 -0
- package/dist/preview/DraftPreviewBar.d.ts +8 -0
- package/dist/preview/DraftPreviewBar.js +86 -0
- package/dist/preview/PreviewDraftEmptyState.d.ts +16 -0
- package/dist/preview/PreviewDraftEmptyState.js +47 -0
- package/dist/preview/PreviewModeContext.d.ts +57 -0
- package/dist/preview/PreviewModeContext.js +99 -0
- package/dist/preview/UnpublishedAppBar.d.ts +8 -0
- package/dist/preview/UnpublishedAppBar.js +79 -0
- package/dist/preview/draftStatus.d.ts +20 -0
- package/dist/preview/draftStatus.js +27 -0
- package/dist/preview/usePublishAllDrafts.d.ts +18 -0
- package/dist/preview/usePublishAllDrafts.js +106 -0
- package/dist/providers/AdapterProvider.d.ts +1 -1
- package/dist/providers/AdapterProvider.js +6 -1
- package/dist/providers/ExpressionProvider.d.ts +1 -1
- package/dist/providers/MetadataProvider.d.ts +17 -2
- package/dist/providers/MetadataProvider.js +183 -12
- package/dist/runtime-config.d.ts +46 -2
- package/dist/runtime-config.js +39 -2
- package/dist/services/builtinComponents.js +68 -59
- package/dist/skeletons/SkeletonDashboard.d.ts +1 -1
- package/dist/skeletons/SkeletonDetail.d.ts +1 -1
- package/dist/skeletons/SkeletonGrid.d.ts +1 -1
- package/dist/utils/appRoute.d.ts +21 -0
- package/dist/utils/appRoute.js +25 -0
- package/dist/utils/deriveRelatedLists.d.ts +54 -0
- package/dist/utils/deriveRelatedLists.js +91 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/managedByEmptyState.d.ts +8 -1
- package/dist/utils/managedByEmptyState.js +13 -7
- package/dist/utils/preferLocal.d.ts +18 -0
- package/dist/utils/preferLocal.js +24 -0
- package/dist/views/ActionConfirmDialog.d.ts +1 -1
- package/dist/views/ActionConfirmDialog.js +3 -1
- package/dist/views/ActionParamDialog.d.ts +6 -1
- package/dist/views/ActionParamDialog.js +9 -3
- package/dist/views/ActionResultDialog.d.ts +13 -0
- package/dist/views/ActionResultDialog.js +134 -0
- package/dist/views/ComponentNavView.d.ts +14 -1
- package/dist/views/CreateViewDialog.d.ts +1 -1
- package/dist/views/DashboardConfigPanel.d.ts +28 -0
- package/dist/views/DashboardConfigPanel.js +81 -0
- package/dist/views/DashboardView.d.ts +4 -3
- package/dist/views/DashboardView.js +38 -239
- package/dist/views/FlowRunner.d.ts +59 -0
- package/dist/views/FlowRunner.js +153 -0
- package/dist/views/InterfaceListPage.d.ts +49 -0
- package/dist/views/InterfaceListPage.js +347 -0
- package/dist/views/MetadataInspector.d.ts +2 -2
- package/dist/views/ObjectView.d.ts +1 -1
- package/dist/views/ObjectView.js +209 -532
- package/dist/views/PageView.d.ts +8 -3
- package/dist/views/PageView.js +45 -32
- package/dist/views/RecordDetailView.d.ts +1 -1
- package/dist/views/RecordDetailView.js +363 -148
- package/dist/views/RecordFormPage.d.ts +1 -1
- package/dist/views/RecordFormPage.js +26 -1
- package/dist/views/ReportConfigPanel.d.ts +37 -0
- package/dist/views/ReportConfigPanel.js +85 -0
- package/dist/views/ReportView.d.ts +1 -1
- package/dist/views/ReportView.js +116 -7
- package/dist/views/RuntimeDraftBar.d.ts +30 -0
- package/dist/views/RuntimeDraftBar.js +112 -0
- package/dist/views/SearchResultsPage.d.ts +1 -1
- package/dist/views/SearchResultsPage.js +8 -18
- package/dist/views/ViewConfigPanel.d.ts +24 -17
- package/dist/views/ViewConfigPanel.js +121 -77
- package/dist/views/index.d.ts +1 -1
- package/dist/views/index.js +1 -1
- package/dist/views/metadata-admin/AuditPanel.d.ts +28 -0
- package/dist/views/metadata-admin/AuditPanel.js +79 -0
- package/dist/views/metadata-admin/DiagnosticsPage.d.ts +20 -0
- package/dist/views/metadata-admin/DiagnosticsPage.js +69 -0
- package/dist/views/metadata-admin/DirectoryPage.d.ts +16 -1
- package/dist/views/metadata-admin/DirectoryPage.js +113 -24
- package/dist/views/metadata-admin/DraftReviewPanel.d.ts +33 -0
- package/dist/views/metadata-admin/DraftReviewPanel.js +77 -0
- package/dist/views/metadata-admin/EmbeddedItemEditor.d.ts +17 -1
- package/dist/views/metadata-admin/EmbeddedItemEditor.js +15 -8
- package/dist/views/metadata-admin/JsonSourceEditor.d.ts +37 -0
- package/dist/views/metadata-admin/JsonSourceEditor.js +178 -0
- package/dist/views/metadata-admin/LayeredDiff.d.ts +39 -1
- package/dist/views/metadata-admin/LayeredDiff.js +171 -5
- package/dist/views/metadata-admin/MetadataDetailDrawer.d.ts +15 -1
- package/dist/views/metadata-admin/MetadataTypeActions.d.ts +48 -0
- package/dist/views/metadata-admin/MetadataTypeActions.js +165 -0
- package/dist/views/metadata-admin/PackagesPage.d.ts +18 -0
- package/dist/views/metadata-admin/PackagesPage.js +395 -0
- package/dist/views/metadata-admin/PageShell.d.ts +1 -1
- package/dist/views/metadata-admin/PageShell.js +9 -4
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +35 -1
- package/dist/views/metadata-admin/QuickFind.d.ts +21 -1
- package/dist/views/metadata-admin/QuickFind.js +6 -3
- package/dist/views/metadata-admin/RelatedPanel.d.ts +24 -1
- package/dist/views/metadata-admin/RelatedPanel.js +20 -18
- package/dist/views/metadata-admin/ResourceEditPage.d.ts +40 -1
- package/dist/views/metadata-admin/ResourceEditPage.js +1223 -60
- package/dist/views/metadata-admin/ResourceHistoryPage.d.ts +39 -1
- package/dist/views/metadata-admin/ResourceHistoryPage.js +66 -16
- package/dist/views/metadata-admin/ResourceListPage.d.ts +13 -1
- package/dist/views/metadata-admin/ResourceListPage.js +266 -30
- package/dist/views/metadata-admin/ResourceRouter.d.ts +23 -1
- package/dist/views/metadata-admin/SchemaForm.d.ts +34 -1
- package/dist/views/metadata-admin/SchemaForm.js +559 -49
- package/dist/views/metadata-admin/StudioHomePage.d.ts +22 -0
- package/dist/views/metadata-admin/StudioHomePage.js +213 -0
- package/dist/views/metadata-admin/anchors.js +237 -24
- package/dist/views/metadata-admin/clientValidation.d.ts +50 -0
- package/dist/views/metadata-admin/clientValidation.js +169 -0
- package/dist/views/metadata-admin/color-variant-field.d.ts +30 -0
- package/dist/views/metadata-admin/color-variant-field.js +38 -0
- package/dist/views/metadata-admin/createDerive.d.ts +75 -0
- package/dist/views/metadata-admin/createDerive.js +179 -0
- package/dist/views/metadata-admin/dashboard-schema.d.ts +12 -0
- package/dist/views/metadata-admin/dashboard-schema.js +80 -0
- package/dist/views/metadata-admin/datasource/DatasourceResourcePage.d.ts +35 -0
- package/dist/views/metadata-admin/datasource/DatasourceResourcePage.js +327 -0
- package/dist/views/metadata-admin/datasource/register.d.ts +1 -0
- package/dist/views/metadata-admin/datasource/register.js +24 -0
- package/dist/views/metadata-admin/default-inspector-registry.d.ts +49 -0
- package/dist/views/metadata-admin/default-inspector-registry.js +8 -0
- package/dist/views/metadata-admin/default-schemas.js +115 -10
- package/dist/views/metadata-admin/external/ExternalDatasourcePanel.d.ts +27 -0
- package/dist/views/metadata-admin/external/ExternalDatasourcePanel.js +69 -0
- package/dist/views/metadata-admin/external/ImportObjectDialog.d.ts +27 -0
- package/dist/views/metadata-admin/external/ImportObjectDialog.js +77 -0
- package/dist/views/metadata-admin/external/SchemaBrowser.d.ts +16 -0
- package/dist/views/metadata-admin/external/SchemaBrowser.js +74 -0
- package/dist/views/metadata-admin/external/ValidationPanel.d.ts +16 -0
- package/dist/views/metadata-admin/external/ValidationPanel.js +68 -0
- package/dist/views/metadata-admin/external/api.d.ts +100 -0
- package/dist/views/metadata-admin/external/api.js +124 -0
- package/dist/views/metadata-admin/i18n.d.ts +1 -0
- package/dist/views/metadata-admin/i18n.js +1166 -2
- package/dist/views/metadata-admin/index.d.ts +8 -5
- package/dist/views/metadata-admin/index.js +12 -2
- package/dist/views/metadata-admin/inspector-registry.d.ts +51 -0
- package/dist/views/metadata-admin/inspector-registry.js +11 -0
- package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.d.ts +30 -0
- package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.js +180 -0
- package/dist/views/metadata-admin/inspectors/AppNavInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/AppNavInspector.js +110 -0
- package/dist/views/metadata-admin/inspectors/ConditionBuilder.d.ts +29 -0
- package/dist/views/metadata-admin/inspectors/ConditionBuilder.js +154 -0
- package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.d.ts +28 -0
- package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.js +110 -0
- package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.d.ts +18 -0
- package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.js +139 -0
- package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.js +107 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +45 -0
- package/dist/views/metadata-admin/inspectors/FlowInspector.d.ts +12 -0
- package/dist/views/metadata-admin/inspectors/FlowInspector.js +9 -0
- package/dist/views/metadata-admin/inspectors/FlowKeyValueField.d.ts +30 -0
- package/dist/views/metadata-admin/inspectors/FlowKeyValueField.js +125 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.d.ts +18 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.js +40 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeInspector.d.ts +14 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeInspector.js +140 -0
- package/dist/views/metadata-admin/inspectors/FlowObjectListField.d.ts +26 -0
- package/dist/views/metadata-admin/inspectors/FlowObjectListField.js +105 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.d.ts +83 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.js +181 -0
- package/dist/views/metadata-admin/inspectors/FlowStringListField.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/FlowStringListField.js +60 -0
- package/dist/views/metadata-admin/inspectors/InspectorComboField.d.ts +40 -0
- package/dist/views/metadata-admin/inspectors/InspectorComboField.js +61 -0
- package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.js +54 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +330 -0
- package/dist/views/metadata-admin/inspectors/PageBlockInspector.d.ts +48 -0
- package/dist/views/metadata-admin/inspectors/PageBlockInspector.js +332 -0
- package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.d.ts +58 -0
- package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.js +160 -0
- package/dist/views/metadata-admin/inspectors/ViewColumnInspector.d.ts +19 -0
- package/dist/views/metadata-admin/inspectors/ViewColumnInspector.js +144 -0
- package/dist/views/metadata-admin/inspectors/ViewInspector.d.ts +19 -0
- package/dist/views/metadata-admin/inspectors/ViewInspector.js +21 -0
- package/dist/views/metadata-admin/inspectors/ViewVariantInspector.d.ts +54 -0
- package/dist/views/metadata-admin/inspectors/ViewVariantInspector.js +191 -0
- package/dist/views/metadata-admin/inspectors/_shared.d.ts +124 -0
- package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
- package/dist/views/metadata-admin/inspectors/expression-validate.d.ts +26 -0
- package/dist/views/metadata-admin/inspectors/expression-validate.js +66 -0
- package/dist/views/metadata-admin/inspectors/flow-node-config.d.ts +143 -0
- package/dist/views/metadata-admin/inspectors/flow-node-config.js +461 -0
- package/dist/views/metadata-admin/inspectors/index.d.ts +1 -0
- package/dist/views/metadata-admin/inspectors/index.js +45 -0
- package/dist/views/metadata-admin/inspectors/json-schema-to-fields.d.ts +40 -0
- package/dist/views/metadata-admin/inspectors/json-schema-to-fields.js +227 -0
- package/dist/views/metadata-admin/inspectors/useDatasetFields.d.ts +72 -0
- package/dist/views/metadata-admin/inspectors/useDatasetFields.js +0 -0
- package/dist/views/metadata-admin/mergeServerFields.d.ts +65 -0
- package/dist/views/metadata-admin/mergeServerFields.js +56 -0
- package/dist/views/metadata-admin/preview-registry.d.ts +55 -0
- package/dist/views/metadata-admin/previews/ActionPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/ActionPreview.js +238 -0
- package/dist/views/metadata-admin/previews/AddWidgetPicker.d.ts +12 -0
- package/dist/views/metadata-admin/previews/AddWidgetPicker.js +56 -0
- package/dist/views/metadata-admin/previews/AgentPreview.d.ts +24 -0
- package/dist/views/metadata-admin/previews/AgentPreview.js +100 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.d.ts +31 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.js +260 -0
- package/dist/views/metadata-admin/previews/AppPreview.d.ts +16 -1
- package/dist/views/metadata-admin/previews/AppPreview.js +23 -14
- package/dist/views/metadata-admin/previews/BookPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/BookPreview.js +132 -0
- package/dist/views/metadata-admin/previews/DashboardPreview.d.ts +16 -1
- package/dist/views/metadata-admin/previews/DashboardPreview.js +110 -8
- package/dist/views/metadata-admin/previews/DatasetPreview.d.ts +18 -0
- package/dist/views/metadata-admin/previews/DatasetPreview.js +89 -0
- package/dist/views/metadata-admin/previews/DatasourcePreview.d.ts +23 -0
- package/dist/views/metadata-admin/previews/DatasourcePreview.js +68 -0
- package/dist/views/metadata-admin/previews/EmailTemplatePreview.d.ts +14 -1
- package/dist/views/metadata-admin/previews/FieldStub.d.ts +30 -0
- package/dist/views/metadata-admin/previews/FieldStub.js +104 -0
- package/dist/views/metadata-admin/previews/FieldsListEditor.d.ts +50 -0
- package/dist/views/metadata-admin/previews/FieldsListEditor.js +97 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.d.ts +43 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.js +328 -0
- package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/FlowPreview.js +92 -0
- package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +46 -0
- package/dist/views/metadata-admin/previews/FlowRunsPanel.js +97 -0
- package/dist/views/metadata-admin/previews/FlowSimulatorPanel.d.ts +25 -0
- package/dist/views/metadata-admin/previews/FlowSimulatorPanel.js +170 -0
- package/dist/views/metadata-admin/previews/JobPreview.d.ts +28 -0
- package/dist/views/metadata-admin/previews/JobPreview.js +290 -0
- package/dist/views/metadata-admin/previews/ObjectFormCanvas.d.ts +30 -0
- package/dist/views/metadata-admin/previews/ObjectFormCanvas.js +547 -0
- package/dist/views/metadata-admin/previews/ObjectPreview.d.ts +14 -1
- package/dist/views/metadata-admin/previews/ObjectPreview.js +5 -30
- package/dist/views/metadata-admin/previews/OutlineStrip.d.ts +32 -0
- package/dist/views/metadata-admin/previews/OutlineStrip.js +8 -0
- package/dist/views/metadata-admin/previews/PageBlockCanvas.d.ts +49 -0
- package/dist/views/metadata-admin/previews/PageBlockCanvas.js +510 -0
- package/dist/views/metadata-admin/previews/PagePreview.d.ts +10 -1
- package/dist/views/metadata-admin/previews/PagePreview.js +90 -4
- package/dist/views/metadata-admin/previews/PermissionPreview.d.ts +27 -0
- package/dist/views/metadata-admin/previews/PermissionPreview.js +115 -0
- package/dist/views/metadata-admin/previews/PreviewShell.d.ts +29 -6
- package/dist/views/metadata-admin/previews/PreviewShell.js +16 -3
- package/dist/views/metadata-admin/previews/ReportPreview.d.ts +18 -1
- package/dist/views/metadata-admin/previews/ReportPreview.js +23 -15
- package/dist/views/metadata-admin/previews/RolePreview.d.ts +19 -0
- package/dist/views/metadata-admin/previews/RolePreview.js +14 -0
- package/dist/views/metadata-admin/previews/SkillPreview.d.ts +22 -0
- package/dist/views/metadata-admin/previews/SkillPreview.js +34 -0
- package/dist/views/metadata-admin/previews/ToolPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/ToolPreview.js +122 -0
- package/dist/views/metadata-admin/previews/TranslationPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/TranslationPreview.js +52 -0
- package/dist/views/metadata-admin/previews/ValidationPreview.d.ts +27 -0
- package/dist/views/metadata-admin/previews/ValidationPreview.js +110 -0
- package/dist/views/metadata-admin/previews/ViewColumnPanes.d.ts +62 -0
- package/dist/views/metadata-admin/previews/ViewColumnPanes.js +140 -0
- package/dist/views/metadata-admin/previews/ViewPreview.d.ts +23 -1
- package/dist/views/metadata-admin/previews/ViewPreview.js +101 -73
- package/dist/views/metadata-admin/previews/block-config.d.ts +82 -0
- package/dist/views/metadata-admin/previews/block-config.js +324 -0
- package/dist/views/metadata-admin/previews/block-types.d.ts +40 -0
- package/dist/views/metadata-admin/previews/block-types.js +110 -0
- package/dist/views/metadata-admin/previews/field-types.d.ts +53 -0
- package/dist/views/metadata-admin/previews/field-types.js +97 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.d.ts +88 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.js +190 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +88 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.js +358 -0
- package/dist/views/metadata-admin/previews/form-preview.d.ts +24 -0
- package/dist/views/metadata-admin/previews/form-preview.js +29 -0
- package/dist/views/metadata-admin/previews/index.js +43 -0
- package/dist/views/metadata-admin/previews/object-fields-bridge.d.ts +66 -0
- package/dist/views/metadata-admin/previews/object-fields-bridge.js +171 -0
- package/dist/views/metadata-admin/previews/object-fields-io.d.ts +109 -0
- package/dist/views/metadata-admin/previews/object-fields-io.js +208 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +91 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.js +2 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.d.ts +8 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +113 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +44 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +316 -0
- package/dist/views/metadata-admin/previews/useDatasetCatalog.d.ts +47 -0
- package/dist/views/metadata-admin/previews/useDatasetCatalog.js +133 -0
- package/dist/views/metadata-admin/previews/useFlowNodePalette.d.ts +44 -0
- package/dist/views/metadata-admin/previews/useFlowNodePalette.js +124 -0
- package/dist/views/metadata-admin/previews/useMetaOptions.d.ts +8 -0
- package/dist/views/metadata-admin/previews/useMetaOptions.js +50 -0
- package/dist/views/metadata-admin/previews/useObjectFields.d.ts +23 -0
- package/dist/views/metadata-admin/previews/useObjectFields.js +79 -0
- package/dist/views/metadata-admin/previews/useObjectOptions.d.ts +8 -0
- package/dist/views/metadata-admin/previews/useObjectOptions.js +43 -0
- package/dist/views/metadata-admin/previews/view-column-io.d.ts +42 -0
- package/dist/views/metadata-admin/previews/view-column-io.js +73 -0
- package/dist/views/metadata-admin/previews/widget-types.d.ts +24 -0
- package/dist/views/metadata-admin/previews/widget-types.js +40 -0
- package/dist/views/metadata-admin/registry.d.ts +140 -19
- package/dist/views/metadata-admin/report-schema.d.ts +26 -0
- package/dist/views/metadata-admin/report-schema.js +121 -0
- package/dist/views/metadata-admin/useMetadata.d.ts +100 -2
- package/dist/views/metadata-admin/useMetadata.js +155 -4
- package/dist/views/metadata-admin/view-item-normalize.d.ts +20 -0
- package/dist/views/metadata-admin/view-item-normalize.js +68 -0
- package/dist/views/metadata-admin/view-schema.d.ts +16 -0
- package/dist/views/metadata-admin/view-schema.js +107 -0
- package/dist/views/metadata-admin/view-variant-model.d.ts +23 -0
- package/dist/views/metadata-admin/view-variant-model.js +64 -0
- package/dist/views/metadata-admin/widgets.d.ts +89 -1
- package/dist/views/metadata-admin/widgets.js +491 -17
- package/dist/views/runtime-metadata-persistence.d.ts +78 -0
- package/dist/views/runtime-metadata-persistence.js +89 -0
- package/dist/views/useOpenRecordList.d.ts +18 -0
- package/dist/views/useOpenRecordList.js +36 -0
- package/dist/views/userFilterUrlState.d.ts +15 -0
- package/dist/views/userFilterUrlState.js +53 -0
- package/dist/views/view-config-adapter.d.ts +38 -0
- package/dist/views/view-config-adapter.js +80 -0
- package/package.json +52 -34
- package/dist/views/DesignDrawer.d.ts +0 -28
- package/dist/views/DesignDrawer.js +0 -51
- package/dist/views/metadata-admin/DesignerEditorWrapper.d.ts +0 -68
- package/dist/views/metadata-admin/DesignerEditorWrapper.js +0 -158
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* PageBlockInspector — scoped editor for the selected page block /
|
|
5
|
+
* component subtree.
|
|
6
|
+
*
|
|
7
|
+
* Selection shape: { kind: 'block', id: 'children[i]' | 'children[i].children[j]' | … }
|
|
8
|
+
*
|
|
9
|
+
* A Page schema is a SDUI tree; "blocks" are children nodes. The id
|
|
10
|
+
* is a dotted path of `children[i]` hops, identical in spirit to
|
|
11
|
+
* AppNavInspector but always rooted at top-level `children`.
|
|
12
|
+
*/
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import { t } from '../i18n';
|
|
15
|
+
import { InspectorShell, InspectorReorderButtons, InspectorTextField, InspectorNumberField, InspectorSelectField, InspectorCheckboxField, InspectorRemoveButton, InspectorEmptyState, moveArray, } from './_shared';
|
|
16
|
+
import { BLOCK_CONFIG, blockHasConfig } from '../previews/block-config';
|
|
17
|
+
import { ColorVariantPicker } from '../color-variant-field';
|
|
18
|
+
import { ConditionBuilder } from './ConditionBuilder';
|
|
19
|
+
import { useObjectOptions } from '../previews/useObjectOptions';
|
|
20
|
+
import { useObjectFields } from '../previews/useObjectFields';
|
|
21
|
+
import { Button, Input, Label, Select, SelectTrigger, SelectContent, SelectItem, SelectValue, } from '@object-ui/components';
|
|
22
|
+
import { Plus, X, Trash2 } from 'lucide-react';
|
|
23
|
+
// ── Schema-driven picker fields ──────────────────────────────────────────────
|
|
24
|
+
/** Field options for an object (visible fields), as {value,label}. */
|
|
25
|
+
function useFieldOptions(objectName) {
|
|
26
|
+
const { fields } = useObjectFields(objectName);
|
|
27
|
+
return React.useMemo(() => fields
|
|
28
|
+
.filter((f) => !f.hidden)
|
|
29
|
+
.map((f) => ({ value: f.name, label: f.label && f.label !== f.name ? `${f.label} (${f.name})` : f.name })), [fields]);
|
|
30
|
+
}
|
|
31
|
+
/** Object dropdown; falls back to a free-text input when the list is empty. */
|
|
32
|
+
function ObjectPickerField({ label, value, onCommit, disabled }) {
|
|
33
|
+
const { options } = useObjectOptions();
|
|
34
|
+
if (options.length === 0) {
|
|
35
|
+
return _jsx(InspectorTextField, { label: label, value: value ?? '', placeholder: "snake_case object", onCommit: onCommit, disabled: disabled, mono: true });
|
|
36
|
+
}
|
|
37
|
+
return _jsx(InspectorSelectField, { label: label, value: value || undefined, options: options, onCommit: onCommit, disabled: disabled });
|
|
38
|
+
}
|
|
39
|
+
/** Field dropdown for `objectName`; falls back to free text when unresolved. */
|
|
40
|
+
function FieldPickerField({ label, objectName, value, onCommit, disabled }) {
|
|
41
|
+
const options = useFieldOptions(objectName);
|
|
42
|
+
if (!objectName || options.length === 0) {
|
|
43
|
+
return _jsx(InspectorTextField, { label: label, value: value ?? '', onCommit: onCommit, disabled: disabled, mono: true });
|
|
44
|
+
}
|
|
45
|
+
return _jsx(InspectorSelectField, { label: label, value: value || undefined, options: options, onCommit: onCommit, disabled: disabled });
|
|
46
|
+
}
|
|
47
|
+
/** Editable list of field names — each row a field dropdown (or text fallback). */
|
|
48
|
+
function FieldListField({ label, objectName, value, onChange, disabled }) {
|
|
49
|
+
const options = useFieldOptions(objectName);
|
|
50
|
+
const arr = Array.isArray(value) ? value : [];
|
|
51
|
+
return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), arr.map((s, i) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [options.length > 0 ? (_jsx("div", { className: "flex-1", children: _jsxs(Select, { value: s ? String(s) : '', onValueChange: (v) => { const n = [...arr]; n[i] = v; onChange(n); }, disabled: disabled, children: [_jsx(SelectTrigger, { className: "h-8", children: _jsx(SelectValue, { placeholder: "\u2014" }) }), _jsx(SelectContent, { children: options.map((o) => _jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })] }) })) : (_jsx(Input, { className: "h-8 text-sm", value: String(s ?? ''), placeholder: "field name", disabled: disabled, onChange: (e) => { const n = [...arr]; n[i] = e.target.value; onChange(n); } })), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-8 w-8", disabled: disabled, "aria-label": "Remove", onClick: () => onChange(arr.filter((_, j) => j !== i)), children: _jsx(X, { className: "h-4 w-4" }) })] }, i))), !disabled && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange([...arr, '']), children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), " Add"] }))] }));
|
|
52
|
+
}
|
|
53
|
+
/** Pretty-print a value for the JSON editor; undefined → empty string. */
|
|
54
|
+
function safeStringify(value) {
|
|
55
|
+
if (value === undefined)
|
|
56
|
+
return '';
|
|
57
|
+
try {
|
|
58
|
+
return JSON.stringify(value, null, 2);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Editable JSON field for object/array properties — commits on blur so a
|
|
65
|
+
* half-typed value never trips the parser. Empty clears the property. */
|
|
66
|
+
function InspectorJsonField({ label, value, onCommit, disabled }) {
|
|
67
|
+
const initial = React.useMemo(() => safeStringify(value), [value]);
|
|
68
|
+
const [text, setText] = React.useState(initial);
|
|
69
|
+
const [error, setError] = React.useState(null);
|
|
70
|
+
React.useEffect(() => { setText(initial); setError(null); }, [initial]);
|
|
71
|
+
const commit = () => {
|
|
72
|
+
if (disabled)
|
|
73
|
+
return;
|
|
74
|
+
const trimmed = text.trim();
|
|
75
|
+
if (trimmed === '') {
|
|
76
|
+
setError(null);
|
|
77
|
+
onCommit(undefined);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(trimmed);
|
|
82
|
+
setError(null);
|
|
83
|
+
onCommit(parsed);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
setError('Invalid JSON');
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsx("textarea", { value: text, onChange: (e) => setText(e.target.value), onBlur: commit, disabled: disabled, spellCheck: false, rows: Math.min(12, Math.max(2, text.split('\n').length)), className: "w-full rounded border border-input bg-background px-2 py-1.5 text-xs font-mono outline-none focus:ring-1 focus:ring-primary resize-y disabled:opacity-60" }), error && _jsx("div", { className: "text-[11px] text-destructive", children: error })] }));
|
|
90
|
+
}
|
|
91
|
+
/** Renders one arbitrary block property by inferring an editor from its
|
|
92
|
+
* runtime type. Guarantees the inspector can edit anything visible in the
|
|
93
|
+
* source, even block types with no curated BLOCK_CONFIG entry. */
|
|
94
|
+
function GenericPropField({ name, value, onCommit, disabled }) {
|
|
95
|
+
if (typeof value === 'boolean') {
|
|
96
|
+
return _jsx(InspectorCheckboxField, { label: name, value: value, onCommit: onCommit, disabled: disabled });
|
|
97
|
+
}
|
|
98
|
+
if (typeof value === 'number') {
|
|
99
|
+
return _jsx(InspectorNumberField, { label: name, value: value, onCommit: (v) => onCommit(v), disabled: disabled });
|
|
100
|
+
}
|
|
101
|
+
if (value === null || typeof value === 'string') {
|
|
102
|
+
return _jsx(InspectorTextField, { label: name, value: value == null ? '' : value, onCommit: onCommit, disabled: disabled, mono: true });
|
|
103
|
+
}
|
|
104
|
+
return _jsx(InspectorJsonField, { label: name, value: value, onCommit: onCommit, disabled: disabled });
|
|
105
|
+
}
|
|
106
|
+
/** Block `properties` keys whose values are nested block trees — these are
|
|
107
|
+
* edited visually on the canvas, so they are excluded from the generic
|
|
108
|
+
* property editor to avoid two conflicting editors for the same data. */
|
|
109
|
+
const STRUCTURAL_PROP_KEYS = new Set(['children', 'body']);
|
|
110
|
+
const REMOVE = Symbol('remove');
|
|
111
|
+
/** A segment is `key` (object) or `key[i]` (array). */
|
|
112
|
+
export function parsePath(id) {
|
|
113
|
+
const segs = id.split('.');
|
|
114
|
+
const hops = [];
|
|
115
|
+
for (const s of segs) {
|
|
116
|
+
const m = /^([a-zA-Z_]\w*)(?:\[(\d+)\])?$/.exec(s);
|
|
117
|
+
if (!m)
|
|
118
|
+
return null;
|
|
119
|
+
hops.push({ key: m[1], index: m[2] != null ? Number(m[2]) : -1 });
|
|
120
|
+
}
|
|
121
|
+
return hops.length > 0 ? hops : null;
|
|
122
|
+
}
|
|
123
|
+
/** Flatten hops to a JSON-pointer-like path: object key, then index if any. */
|
|
124
|
+
export function hopsToPath(hops) {
|
|
125
|
+
const p = [];
|
|
126
|
+
for (const h of hops) {
|
|
127
|
+
p.push(h.key);
|
|
128
|
+
if (h.index >= 0)
|
|
129
|
+
p.push(h.index);
|
|
130
|
+
}
|
|
131
|
+
return p;
|
|
132
|
+
}
|
|
133
|
+
export function getByPath(root, path) {
|
|
134
|
+
let node = root;
|
|
135
|
+
for (const seg of path) {
|
|
136
|
+
if (node == null)
|
|
137
|
+
return null;
|
|
138
|
+
node = node[seg];
|
|
139
|
+
}
|
|
140
|
+
return node ?? null;
|
|
141
|
+
}
|
|
142
|
+
/** Immutable set/remove along a path. `value === REMOVE` deletes the leaf. */
|
|
143
|
+
export function setByPath(root, path, value) {
|
|
144
|
+
if (path.length === 0)
|
|
145
|
+
return value;
|
|
146
|
+
const [head, ...rest] = path;
|
|
147
|
+
if (typeof head === 'number') {
|
|
148
|
+
const arr = Array.isArray(root) ? [...root] : [];
|
|
149
|
+
if (rest.length === 0) {
|
|
150
|
+
if (value === REMOVE)
|
|
151
|
+
arr.splice(head, 1);
|
|
152
|
+
else
|
|
153
|
+
arr[head] = value;
|
|
154
|
+
}
|
|
155
|
+
else
|
|
156
|
+
arr[head] = setByPath(arr[head], rest, value);
|
|
157
|
+
return arr;
|
|
158
|
+
}
|
|
159
|
+
const obj = { ...(root || {}) };
|
|
160
|
+
if (rest.length === 0) {
|
|
161
|
+
if (value === REMOVE)
|
|
162
|
+
delete obj[head];
|
|
163
|
+
else
|
|
164
|
+
obj[head] = value;
|
|
165
|
+
}
|
|
166
|
+
else
|
|
167
|
+
obj[head] = setByPath(obj[head], rest, value);
|
|
168
|
+
return obj;
|
|
169
|
+
}
|
|
170
|
+
export function readAt(root, hops) {
|
|
171
|
+
return getByPath(root, hopsToPath(hops));
|
|
172
|
+
}
|
|
173
|
+
/** Returns a shallow patch `{ [topKey]: newValue }` for onPatch. */
|
|
174
|
+
export function writeAt(root, hops, replacement) {
|
|
175
|
+
const path = hopsToPath(hops);
|
|
176
|
+
const next = setByPath(root, path, replacement === null ? REMOVE : replacement);
|
|
177
|
+
const topKey = path[0];
|
|
178
|
+
return { [topKey]: next[topKey] };
|
|
179
|
+
}
|
|
180
|
+
export function readSiblings(root, hops) {
|
|
181
|
+
const path = hopsToPath(hops);
|
|
182
|
+
const last = path[path.length - 1];
|
|
183
|
+
if (typeof last !== 'number')
|
|
184
|
+
return null;
|
|
185
|
+
const siblings = getByPath(root, path.slice(0, -1));
|
|
186
|
+
if (!Array.isArray(siblings))
|
|
187
|
+
return null;
|
|
188
|
+
return { siblings: siblings, index: last };
|
|
189
|
+
}
|
|
190
|
+
export function writeSiblings(root, hops, nextSiblings) {
|
|
191
|
+
const path = hopsToPath(hops);
|
|
192
|
+
const next = setByPath(root, path.slice(0, -1), nextSiblings);
|
|
193
|
+
const topKey = path[0];
|
|
194
|
+
return { [topKey]: next[topKey] };
|
|
195
|
+
}
|
|
196
|
+
export function PageBlockInspector({ selection, draft, onPatch, onClearSelection, onSelectionChange, locale, readOnly }) {
|
|
197
|
+
// Slotted record page: selection ids are `slot:<name>:<index>` and address
|
|
198
|
+
// `draft.slots.<name>` (a single component is normalised to a 1-element array).
|
|
199
|
+
// `slot:<name>:<idx>` optionally followed by a nested sub-path within the
|
|
200
|
+
// slot's block (e.g. `slot:tabs:0.properties.items[0].children[0]`), so a
|
|
201
|
+
// block inside a slotted container is addressable too (issue #1499).
|
|
202
|
+
const slotMatch = /^slot:([a-zA-Z_]+):(\d+)(?:\.(.+))?$/.exec(selection.id);
|
|
203
|
+
const hops = slotMatch ? null : parsePath(selection.id);
|
|
204
|
+
const slotName = slotMatch ? slotMatch[1] : '';
|
|
205
|
+
const slotIdx = slotMatch ? Number(slotMatch[2]) : -1;
|
|
206
|
+
const slotSub = slotMatch ? slotMatch[3] : undefined;
|
|
207
|
+
const subHops = slotSub ? parsePath(slotSub) : null;
|
|
208
|
+
const slotsObj = draft.slots && typeof draft.slots === 'object' ? draft.slots : {};
|
|
209
|
+
const slotArr = slotMatch
|
|
210
|
+
? Array.isArray(slotsObj[slotName])
|
|
211
|
+
? slotsObj[slotName]
|
|
212
|
+
: slotsObj[slotName] != null
|
|
213
|
+
? [slotsObj[slotName]]
|
|
214
|
+
: []
|
|
215
|
+
: [];
|
|
216
|
+
const slotBase = slotMatch ? (slotArr[slotIdx] ?? null) : null;
|
|
217
|
+
// Write the slot's whole array back (delete the base block when null).
|
|
218
|
+
const writeSlot = (nextArr) => onPatch({ slots: { ...slotsObj, [slotName]: nextArr } });
|
|
219
|
+
const writeSlotBase = (nextBase) => writeSlot(nextBase === null ? slotArr.filter((_, i) => i !== slotIdx) : slotArr.map((b, i) => (i === slotIdx ? nextBase : b)));
|
|
220
|
+
const block = slotMatch
|
|
221
|
+
? subHops
|
|
222
|
+
? readAt((slotBase || {}), subHops)
|
|
223
|
+
: slotBase
|
|
224
|
+
: hops
|
|
225
|
+
? readAt(draft, hops)
|
|
226
|
+
: null;
|
|
227
|
+
const sibInfo = slotMatch
|
|
228
|
+
? subHops
|
|
229
|
+
? readSiblings((slotBase || {}), subHops)
|
|
230
|
+
: { siblings: slotArr, index: slotIdx }
|
|
231
|
+
: hops
|
|
232
|
+
? readSiblings(draft, hops)
|
|
233
|
+
: null;
|
|
234
|
+
if ((!slotMatch && !hops) || !block) {
|
|
235
|
+
return (_jsx(InspectorShell, { kindLabel: t('engine.inspector.pageBlock.kind', locale), title: selection.label ?? selection.id, onClose: onClearSelection, closeLabel: t('engine.inspector.pageBlock.close', locale), children: _jsx(InspectorEmptyState, { message: selection.id }) }));
|
|
236
|
+
}
|
|
237
|
+
const patch = (updates) => {
|
|
238
|
+
if (!slotMatch)
|
|
239
|
+
return onPatch(writeAt(draft, hops, { ...block, ...updates }));
|
|
240
|
+
if (subHops)
|
|
241
|
+
return writeSlotBase({ ...slotBase, ...writeAt((slotBase || {}), subHops, { ...block, ...updates }) });
|
|
242
|
+
return writeSlotBase({ ...block, ...updates });
|
|
243
|
+
};
|
|
244
|
+
// Per-block configurable properties (spec `properties`). The renderer hoists
|
|
245
|
+
// `properties.*` to the top level, so we read from either and always write
|
|
246
|
+
// back to `properties` (the canonical shape).
|
|
247
|
+
const blockProps = block.properties || {};
|
|
248
|
+
// The record page's bound object — drives `field-picker`/`field-list` with
|
|
249
|
+
// objectFrom:'page'. (objectFrom:'self' reads a sibling block property.)
|
|
250
|
+
const pageObject = typeof draft?.object === 'string' ? draft.object : undefined;
|
|
251
|
+
const resolveObject = (src) => src.objectFrom === 'page'
|
|
252
|
+
? pageObject
|
|
253
|
+
: src.objectProp != null && blockProps[src.objectProp] != null
|
|
254
|
+
? String(blockProps[src.objectProp])
|
|
255
|
+
: undefined;
|
|
256
|
+
const readProp = (name) => blockProps[name] ?? block[name];
|
|
257
|
+
const patchProp = (name, value) => patch({ properties: { ...blockProps, [name]: value } });
|
|
258
|
+
// Properties already handled by curated fields — excluded from the generic
|
|
259
|
+
// "Advanced" section so each property has exactly one editor.
|
|
260
|
+
const curatedNames = new Set((blockHasConfig(block.type) ? BLOCK_CONFIG[block.type] : []).map((f) => f.name));
|
|
261
|
+
const advancedKeys = Object.keys(blockProps).filter((key) => !curatedNames.has(key) && !STRUCTURAL_PROP_KEYS.has(key));
|
|
262
|
+
// Generic, recursive field renderer. `read`/`write` abstract the value source
|
|
263
|
+
// (the block's `properties` at the top level, or an item object inside an
|
|
264
|
+
// `array` field), so the same code drives nested array-item editors.
|
|
265
|
+
const renderField = (f, read, write, keyPrefix = '') => {
|
|
266
|
+
const k = `${keyPrefix}${f.name}`;
|
|
267
|
+
switch (f.kind) {
|
|
268
|
+
case 'number':
|
|
269
|
+
return (_jsx(InspectorNumberField, { label: f.label, value: typeof read(f.name) === 'number' ? read(f.name) : undefined, placeholder: f.placeholder, onCommit: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
270
|
+
case 'boolean':
|
|
271
|
+
return (_jsx(InspectorCheckboxField, { label: f.label, value: !!read(f.name), onCommit: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
272
|
+
case 'color':
|
|
273
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: f.label }), _jsx(ColorVariantPicker, { value: read(f.name) != null ? String(read(f.name)) : undefined, onChange: (v) => write(f.name, v), disabled: readOnly, options: f.options })] }, k));
|
|
274
|
+
case 'select':
|
|
275
|
+
return (_jsx(InspectorSelectField, { label: f.label, value: read(f.name) != null ? String(read(f.name)) : undefined, options: f.options, onCommit: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
276
|
+
case 'string-list': {
|
|
277
|
+
const arr = Array.isArray(read(f.name)) ? read(f.name) : [];
|
|
278
|
+
return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: f.label }), arr.map((s, i) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Input, { className: "h-8 text-sm", value: String(s ?? ''), placeholder: f.placeholder, disabled: readOnly, onChange: (e) => { const next = [...arr]; next[i] = e.target.value; write(f.name, next); } }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-8 w-8", disabled: readOnly, "aria-label": "Remove", onClick: () => write(f.name, arr.filter((_, j) => j !== i)), children: _jsx(X, { className: "h-4 w-4" }) })] }, i))), !readOnly && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => write(f.name, [...arr, '']), children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), " Add"] }))] }, k));
|
|
279
|
+
}
|
|
280
|
+
case 'array': {
|
|
281
|
+
const arr = Array.isArray(read(f.name)) ? read(f.name) : [];
|
|
282
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: f.label }), arr.map((item, i) => {
|
|
283
|
+
const itemObj = item && typeof item === 'object' ? item : {};
|
|
284
|
+
return (_jsxs("div", { className: "space-y-2 rounded-md border border-border p-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("span", { className: "text-xs text-muted-foreground", children: ["#", i + 1] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-7 w-7", disabled: readOnly, "aria-label": "Remove item", onClick: () => write(f.name, arr.filter((_, j) => j !== i)), children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] }), f.itemFields.map((itf) => renderField(itf, (n) => itemObj[n], (n, v) => { const next = [...arr]; next[i] = { ...itemObj, [n]: v }; write(f.name, next); }, `${k}-${i}-`))] }, i));
|
|
285
|
+
}), !readOnly && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => write(f.name, [...arr, {}]), children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), " ", f.addLabel || 'Add'] }))] }, k));
|
|
286
|
+
}
|
|
287
|
+
case 'object-picker':
|
|
288
|
+
return (_jsx(ObjectPickerField, { label: f.label, value: read(f.name) != null ? String(read(f.name)) : undefined, onCommit: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
289
|
+
case 'field-picker':
|
|
290
|
+
return (_jsx(FieldPickerField, { label: f.label, objectName: resolveObject(f), value: read(f.name) != null ? String(read(f.name)) : undefined, onCommit: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
291
|
+
case 'field-list':
|
|
292
|
+
return (_jsx(FieldListField, { label: f.label, objectName: resolveObject(f), value: read(f.name), onChange: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
293
|
+
default:
|
|
294
|
+
return (_jsx(InspectorTextField, { label: f.label, value: read(f.name) != null ? String(read(f.name)) : '', placeholder: f.placeholder, onCommit: (v) => write(f.name, v), disabled: readOnly }, k));
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
const remove = () => {
|
|
298
|
+
if (slotMatch) {
|
|
299
|
+
if (subHops)
|
|
300
|
+
writeSlotBase({ ...slotBase, ...writeAt((slotBase || {}), subHops, null) });
|
|
301
|
+
else
|
|
302
|
+
writeSlotBase(null);
|
|
303
|
+
}
|
|
304
|
+
else
|
|
305
|
+
onPatch(writeAt(draft, hops, null));
|
|
306
|
+
onClearSelection();
|
|
307
|
+
};
|
|
308
|
+
// Re-serialise hops to an id, honouring object hops (index < 0 → no `[i]`).
|
|
309
|
+
const fmtHops = (hs) => hs.map((h) => (h.index >= 0 ? `${h.key}[${h.index}]` : h.key)).join('.');
|
|
310
|
+
const move = (to) => {
|
|
311
|
+
if (!sibInfo)
|
|
312
|
+
return;
|
|
313
|
+
if (slotMatch) {
|
|
314
|
+
if (subHops) {
|
|
315
|
+
const next = moveArray(sibInfo.siblings, sibInfo.index, to);
|
|
316
|
+
writeSlotBase({ ...slotBase, ...writeSiblings((slotBase || {}), subHops, next) });
|
|
317
|
+
const newSub = fmtHops([...subHops.slice(0, -1), { key: subHops[subHops.length - 1].key, index: to }]);
|
|
318
|
+
onSelectionChange?.({ kind: 'block', id: `slot:${slotName}:${slotIdx}.${newSub}`, label: String(block.id || block.type || to) });
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
writeSlot(moveArray(slotArr, slotIdx, to));
|
|
322
|
+
onSelectionChange?.({ kind: 'block', id: `slot:${slotName}:${to}`, label: String(block.id || block.type || to) });
|
|
323
|
+
}
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const next = moveArray(sibInfo.siblings, sibInfo.index, to);
|
|
327
|
+
onPatch(writeSiblings(draft, hops, next));
|
|
328
|
+
const newId = fmtHops([...hops.slice(0, -1), { key: hops[hops.length - 1].key, index: to }]);
|
|
329
|
+
onSelectionChange?.({ kind: 'block', id: newId, label: String(block.id || block.type || newId) });
|
|
330
|
+
};
|
|
331
|
+
return (_jsxs(InspectorShell, { kindLabel: t('engine.inspector.pageBlock.kind', locale), title: String(block.id || block.type || selection.id), onClose: onClearSelection, closeLabel: t('engine.inspector.pageBlock.close', locale), headerActions: sibInfo ? (_jsx(InspectorReorderButtons, { index: sibInfo.index, total: sibInfo.siblings.length, onMove: move, upLabel: t('engine.inspector.reorder.up', locale), downLabel: t('engine.inspector.reorder.down', locale), disabled: readOnly })) : undefined, footer: _jsx(InspectorRemoveButton, { label: t('engine.inspector.pageBlock.remove', locale), onClick: remove, disabled: readOnly }), children: [_jsx(InspectorTextField, { label: t('engine.inspector.pageBlock.type', locale), value: block.type ?? '', onCommit: (v) => patch({ type: v }), disabled: readOnly, mono: true }), _jsx(InspectorTextField, { label: t('engine.inspector.pageBlock.id', locale), value: block.id ?? '', onCommit: (v) => patch({ id: v }), disabled: readOnly, mono: true }), _jsx(InspectorTextField, { label: t('engine.inspector.pageBlock.className', locale), value: block.className ?? '', onCommit: (v) => patch({ className: v }), disabled: readOnly, mono: true }), _jsx(ConditionBuilder, { label: t('engine.inspector.pageBlock.hidden', locale), value: block.hidden ?? '', onCommit: (v) => patch({ hidden: v || undefined }), objectName: pageObject, disabled: readOnly }), blockHasConfig(block.type) && (_jsxs("div", { className: "space-y-3 border-t border-border pt-3", children: [_jsx("div", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: t('engine.inspector.pageBlock.properties', locale) }), BLOCK_CONFIG[block.type].map((f) => renderField(f, readProp, patchProp))] })), advancedKeys.length > 0 && (_jsxs("div", { className: "space-y-3 border-t border-border pt-3", children: [_jsx("div", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: t('engine.inspector.pageBlock.advanced', locale) }), advancedKeys.map((key) => (_jsx(GenericPropField, { name: key, value: blockProps[key], onCommit: (v) => patchProp(key, v), disabled: readOnly }, key)))] }))] }));
|
|
332
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReportDefaultInspector — the curated "home" panel for a Report.
|
|
3
|
+
*
|
|
4
|
+
* Shown as the DEFAULT right panel (no selection) for a report. Mirrors
|
|
5
|
+
* {@link ViewVariantInspector} but for the flat Report document.
|
|
6
|
+
*
|
|
7
|
+
* SPEC-DRIVEN: the per-report-type config fields are NOT hardcoded. They are
|
|
8
|
+
* rendered by feeding the spec's canonical authoring form (`reportForm`) and
|
|
9
|
+
* the spec-derived Report JSONSchema into the generic {@link SchemaForm}. The
|
|
10
|
+
* form's type-conditional `visibleOn` section (joined blocks) automatically
|
|
11
|
+
* surfaces the right fields — adding a new report type or prop to
|
|
12
|
+
* `@objectstack/spec` flows through with zero code changes here.
|
|
13
|
+
*
|
|
14
|
+
* ADR-0021 single-form: a 9.0 report is dataset-bound — it binds a
|
|
15
|
+
* semantic-layer `dataset` and selects its `values` (measure names) grouped
|
|
16
|
+
* by `rows` (dimension names). The inspector keeps a thin curated layer for
|
|
17
|
+
* the concerns the spec form can't express well on its own:
|
|
18
|
+
* 1. the REPORT TYPE picker (options sourced from the spec `type` enum),
|
|
19
|
+
* 2. the DATASET binding (drives the measure/dimension catalogs), and
|
|
20
|
+
* 3. the VALUES / ROWS lists — add / remove / reorder from the bound
|
|
21
|
+
* dataset's measures and dimensions.
|
|
22
|
+
* Those fields are pruned from the spec form to avoid double-editing.
|
|
23
|
+
*
|
|
24
|
+
* Unlike a View (a nested document with a variant BODY), a Report is FLAT:
|
|
25
|
+
* label / dataset / type / values / rows all live at the draft top level, so
|
|
26
|
+
* every write is a plain shallow `onPatch`.
|
|
27
|
+
*/
|
|
28
|
+
import * as React from 'react';
|
|
29
|
+
import type { MetadataDefaultInspectorProps } from '../default-inspector-registry';
|
|
30
|
+
import type { ObjectFieldInfo } from '../previews/useObjectFields';
|
|
31
|
+
import { type DatasetCatalogEntry } from '../previews/useDatasetCatalog';
|
|
32
|
+
export interface ReportDefaultInspectorProps extends MetadataDefaultInspectorProps {
|
|
33
|
+
/**
|
|
34
|
+
* Pre-resolved dataset catalog. When supplied, the inspector skips the
|
|
35
|
+
* network fetches (`useDatasetCatalog`) and uses this list instead. Hosts
|
|
36
|
+
* that already hold the catalog pass it to keep the inspector free of any
|
|
37
|
+
* network dependency.
|
|
38
|
+
*/
|
|
39
|
+
datasetCatalogOverride?: DatasetCatalogEntry[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A reorderable list of dataset member names (the report's `values` or
|
|
43
|
+
* `rows`) with an add-popover fed by the bound dataset's catalog. Exported so
|
|
44
|
+
* the Dashboard widget inspector can bind the same governed dimensions/measures
|
|
45
|
+
* the same way (single source of truth for dataset-member editing).
|
|
46
|
+
*/
|
|
47
|
+
export declare function DatasetNamesEditor({ label, emptyText, names, options, loading, error, readOnly, onCommit, }: {
|
|
48
|
+
label: string;
|
|
49
|
+
emptyText: string;
|
|
50
|
+
names: string[];
|
|
51
|
+
/** Picker options from the dataset's semantic layer. */
|
|
52
|
+
options: ObjectFieldInfo[];
|
|
53
|
+
loading: boolean;
|
|
54
|
+
error: string | null;
|
|
55
|
+
readOnly?: boolean;
|
|
56
|
+
onCommit: (next: string[]) => void;
|
|
57
|
+
}): React.JSX.Element;
|
|
58
|
+
export declare function ReportDefaultInspector({ draft, onPatch, readOnly, locale, datasetCatalogOverride, serverSchema, }: ReportDefaultInspectorProps): React.JSX.Element;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ReportDefaultInspector — the curated "home" panel for a Report.
|
|
5
|
+
*
|
|
6
|
+
* Shown as the DEFAULT right panel (no selection) for a report. Mirrors
|
|
7
|
+
* {@link ViewVariantInspector} but for the flat Report document.
|
|
8
|
+
*
|
|
9
|
+
* SPEC-DRIVEN: the per-report-type config fields are NOT hardcoded. They are
|
|
10
|
+
* rendered by feeding the spec's canonical authoring form (`reportForm`) and
|
|
11
|
+
* the spec-derived Report JSONSchema into the generic {@link SchemaForm}. The
|
|
12
|
+
* form's type-conditional `visibleOn` section (joined blocks) automatically
|
|
13
|
+
* surfaces the right fields — adding a new report type or prop to
|
|
14
|
+
* `@objectstack/spec` flows through with zero code changes here.
|
|
15
|
+
*
|
|
16
|
+
* ADR-0021 single-form: a 9.0 report is dataset-bound — it binds a
|
|
17
|
+
* semantic-layer `dataset` and selects its `values` (measure names) grouped
|
|
18
|
+
* by `rows` (dimension names). The inspector keeps a thin curated layer for
|
|
19
|
+
* the concerns the spec form can't express well on its own:
|
|
20
|
+
* 1. the REPORT TYPE picker (options sourced from the spec `type` enum),
|
|
21
|
+
* 2. the DATASET binding (drives the measure/dimension catalogs), and
|
|
22
|
+
* 3. the VALUES / ROWS lists — add / remove / reorder from the bound
|
|
23
|
+
* dataset's measures and dimensions.
|
|
24
|
+
* Those fields are pruned from the spec form to avoid double-editing.
|
|
25
|
+
*
|
|
26
|
+
* Unlike a View (a nested document with a variant BODY), a Report is FLAT:
|
|
27
|
+
* label / dataset / type / values / rows all live at the draft top level, so
|
|
28
|
+
* every write is a plain shallow `onPatch`.
|
|
29
|
+
*/
|
|
30
|
+
import * as React from 'react';
|
|
31
|
+
import { Badge, Label } from '@object-ui/components';
|
|
32
|
+
import { InspectorShell, InspectorTextField, InspectorSelectField, appendArray, moveArray, spliceArray, } from './_shared';
|
|
33
|
+
import { AddFieldPopover, FieldListRow } from '../previews/ViewColumnPanes';
|
|
34
|
+
import { SchemaForm } from '../SchemaForm';
|
|
35
|
+
import { useDatasetCatalog, useDatasetSemantics, } from '../previews/useDatasetCatalog';
|
|
36
|
+
import { getReportForm, getReportSchema } from '../report-schema';
|
|
37
|
+
import { mergeServerFields } from '../mergeServerFields';
|
|
38
|
+
import { t } from '../i18n';
|
|
39
|
+
/**
|
|
40
|
+
* Top-level report fields this inspector renders with its own dedicated
|
|
41
|
+
* controls (type / dataset / values / rows + identity), so the spec-form
|
|
42
|
+
* graft never double-renders them. Mirrors the `hiddenFields` passed to
|
|
43
|
+
* SchemaForm.
|
|
44
|
+
*/
|
|
45
|
+
const REPORT_CURATED_FIELDS = new Set([
|
|
46
|
+
'type',
|
|
47
|
+
'label',
|
|
48
|
+
'name',
|
|
49
|
+
'dataset',
|
|
50
|
+
'values',
|
|
51
|
+
'rows',
|
|
52
|
+
'columns', // matrix across-dimensions — dedicated list below
|
|
53
|
+
]);
|
|
54
|
+
/** i18n keys for the spec `type` enum (falls back to the raw value). */
|
|
55
|
+
const TYPE_LABEL_KEYS = {
|
|
56
|
+
tabular: 'engine.inspector.report.type.tabular',
|
|
57
|
+
summary: 'engine.inspector.report.type.summary',
|
|
58
|
+
matrix: 'engine.inspector.report.type.matrix',
|
|
59
|
+
joined: 'engine.inspector.report.type.joined',
|
|
60
|
+
};
|
|
61
|
+
/** Build the Report-type <select> options from the spec `type` enum. */
|
|
62
|
+
function useTypeOptions(currentType, locale) {
|
|
63
|
+
return React.useMemo(() => {
|
|
64
|
+
const schema = getReportSchema();
|
|
65
|
+
const rawEnum = schema?.properties?.type?.enum;
|
|
66
|
+
const values = Array.isArray(rawEnum) && rawEnum.length
|
|
67
|
+
? rawEnum.filter((v) => typeof v === 'string')
|
|
68
|
+
: ['tabular', 'summary', 'matrix', 'joined'];
|
|
69
|
+
const opts = values.map((v) => {
|
|
70
|
+
const key = TYPE_LABEL_KEYS[v];
|
|
71
|
+
// i18n with a raw-value fallback (`t` echoes unknown keys verbatim).
|
|
72
|
+
const label = key ? t(key, locale) : v;
|
|
73
|
+
return { value: v, label: label === key ? v : label };
|
|
74
|
+
});
|
|
75
|
+
if (!opts.some((o) => o.value === currentType) && currentType) {
|
|
76
|
+
opts.push({ value: currentType, label: currentType });
|
|
77
|
+
}
|
|
78
|
+
return opts;
|
|
79
|
+
}, [currentType, locale]);
|
|
80
|
+
}
|
|
81
|
+
/** Read a `string[]` draft field defensively. */
|
|
82
|
+
function readNames(value) {
|
|
83
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === 'string') : [];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A reorderable list of dataset member names (the report's `values` or
|
|
87
|
+
* `rows`) with an add-popover fed by the bound dataset's catalog. Exported so
|
|
88
|
+
* the Dashboard widget inspector can bind the same governed dimensions/measures
|
|
89
|
+
* the same way (single source of truth for dataset-member editing).
|
|
90
|
+
*/
|
|
91
|
+
export function DatasetNamesEditor({ label, emptyText, names, options, loading, error, readOnly, onCommit, }) {
|
|
92
|
+
const [dragIndex, setDragIndex] = React.useState(null);
|
|
93
|
+
const [overIndex, setOverIndex] = React.useState(null);
|
|
94
|
+
const used = React.useMemo(() => new Set(names), [names]);
|
|
95
|
+
const typeByName = React.useMemo(() => {
|
|
96
|
+
const m = new Map();
|
|
97
|
+
for (const o of options)
|
|
98
|
+
m.set(o.name, o.type);
|
|
99
|
+
return m;
|
|
100
|
+
}, [options]);
|
|
101
|
+
return (_jsxs("div", { className: "border-t pt-3 space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsx(Badge, { variant: "outline", className: "text-[10px]", children: names.length })] }), names.length === 0 ? (_jsx("p", { className: "rounded-md border border-dashed bg-muted/30 px-3 py-3 text-center text-[11px] text-muted-foreground", children: emptyText })) : (_jsx("div", { className: "space-y-1", children: names.map((name, i) => (_jsx(FieldListRow, { index: i, label: name, fieldName: name, fieldType: typeByName.get(name) ?? 'number', selected: false, canEdit: !readOnly, dragging: dragIndex !== null, dropBefore: overIndex === i && dragIndex !== null && dragIndex !== i, onSelect: () => { }, onRemove: () => onCommit(spliceArray(names, i, null)), onDragStart: () => setDragIndex(i), onDragEnd: () => {
|
|
102
|
+
setDragIndex(null);
|
|
103
|
+
setOverIndex(null);
|
|
104
|
+
}, onDragOverRow: () => setOverIndex(i), onDropRow: () => {
|
|
105
|
+
if (dragIndex != null && dragIndex !== i)
|
|
106
|
+
onCommit(moveArray(names, dragIndex, i));
|
|
107
|
+
setDragIndex(null);
|
|
108
|
+
setOverIndex(null);
|
|
109
|
+
} }, `${name}-${i}`))) })), !readOnly && (_jsx(AddFieldPopover, { fields: options, usedNames: used, loading: loading, error: error, onAdd: (f) => onCommit(appendArray(names, f.name)) }))] }));
|
|
110
|
+
}
|
|
111
|
+
export function ReportDefaultInspector({ draft, onPatch, readOnly, locale, datasetCatalogOverride, serverSchema, }) {
|
|
112
|
+
const tr = React.useCallback((key) => t(key, locale), [locale]);
|
|
113
|
+
const reportType = typeof draft.type === 'string' ? draft.type : 'tabular';
|
|
114
|
+
const typeOptions = useTypeOptions(reportType, locale);
|
|
115
|
+
const labelValue = typeof draft.label === 'string' ? draft.label : '';
|
|
116
|
+
const datasetName = typeof draft.dataset === 'string' ? draft.dataset : '';
|
|
117
|
+
const values = React.useMemo(() => readNames(draft.values), [draft.values]);
|
|
118
|
+
const rows = React.useMemo(() => readNames(draft.rows), [draft.rows]);
|
|
119
|
+
const columnsAcross = React.useMemo(() => readNames(draft.columns), [draft.columns]);
|
|
120
|
+
// Dataset catalog (binding options) + the bound dataset's semantic layer
|
|
121
|
+
// (measure/dimension picker options).
|
|
122
|
+
const catalog = useDatasetCatalog(datasetCatalogOverride);
|
|
123
|
+
const semantics = useDatasetSemantics(datasetName || undefined, catalog);
|
|
124
|
+
const datasetOptions = React.useMemo(() => {
|
|
125
|
+
const opts = catalog.datasets.map((d) => ({
|
|
126
|
+
value: d.name,
|
|
127
|
+
label: d.label && d.label !== d.name ? `${d.label} (${d.name})` : d.name,
|
|
128
|
+
}));
|
|
129
|
+
if (datasetName && !opts.some((o) => o.value === datasetName)) {
|
|
130
|
+
opts.push({ value: datasetName, label: datasetName });
|
|
131
|
+
}
|
|
132
|
+
return opts;
|
|
133
|
+
}, [catalog.datasets, datasetName]);
|
|
134
|
+
const measureOptions = React.useMemo(() => semantics.measures.map((m) => ({
|
|
135
|
+
name: m.name,
|
|
136
|
+
label: m.aggregate ? `${m.name} · ${m.aggregate}` : m.name,
|
|
137
|
+
type: 'number',
|
|
138
|
+
hidden: false,
|
|
139
|
+
})), [semantics.measures]);
|
|
140
|
+
const dimensionOptions = React.useMemo(() => semantics.dimensions.map((d) => ({
|
|
141
|
+
name: d.name,
|
|
142
|
+
label: d.name,
|
|
143
|
+
type: d.type ?? 'text',
|
|
144
|
+
hidden: false,
|
|
145
|
+
})), [semantics.dimensions]);
|
|
146
|
+
// A `joined` report carries its data on dataset-bound `blocks` (edited via
|
|
147
|
+
// the spec form's repeater) — the top-level binding only applies otherwise.
|
|
148
|
+
const datasetBound = reportType !== 'joined';
|
|
149
|
+
// Graft any server-only top-level fields onto the bundled-spec form so they
|
|
150
|
+
// are directly editable here even when the bundled `@objectstack/spec` lags
|
|
151
|
+
// the running server (skew root-cure).
|
|
152
|
+
const { schema, form } = React.useMemo(() => mergeServerFields({
|
|
153
|
+
bundledSchema: getReportSchema(),
|
|
154
|
+
bundledForm: getReportForm(),
|
|
155
|
+
serverSchema,
|
|
156
|
+
excludeFields: REPORT_CURATED_FIELDS,
|
|
157
|
+
sectionTitle: t('engine.inspector.moreFields', locale),
|
|
158
|
+
}), [serverSchema, locale]);
|
|
159
|
+
return (_jsxs(InspectorShell, { kindLabel: tr('engine.inspector.report.kind'), title: String(labelValue || draft.name || tr('engine.inspector.report.kind')), onClose: () => { }, closeLabel: tr('engine.inspector.report.close'), hideClose: true, children: [_jsx(InspectorTextField, { label: tr('engine.inspector.report.label'), value: labelValue, onCommit: (v) => onPatch({ label: v }), placeholder: tr('engine.inspector.report.labelPlaceholder'), disabled: readOnly }), _jsx(InspectorSelectField, { label: tr('engine.inspector.report.type'), value: reportType, options: typeOptions, onCommit: (v) => onPatch({ type: v }), disabled: readOnly }), datasetBound && (_jsxs(_Fragment, { children: [catalog.datasets.length > 0 || datasetName ? (_jsx(InspectorSelectField, { label: tr('engine.inspector.report.dataset'), value: datasetName, options: datasetOptions, onCommit: (v) => onPatch({ dataset: v }), disabled: readOnly })) : (_jsx(InspectorTextField, { label: tr('engine.inspector.report.dataset'), value: datasetName, onCommit: (v) => onPatch({ dataset: v }), placeholder: tr('engine.inspector.report.datasetPlaceholder'), disabled: readOnly, mono: true })), _jsx(DatasetNamesEditor, { label: tr('engine.inspector.report.values'), emptyText: tr('engine.inspector.report.valuesEmpty'), names: values, options: measureOptions, loading: semantics.loading, error: semantics.error, readOnly: readOnly, onCommit: (next) => onPatch({ values: next }) }), _jsx(DatasetNamesEditor, { label: tr('engine.inspector.report.rows'), emptyText: tr('engine.inspector.report.rowsEmpty'), names: rows, options: dimensionOptions, loading: semantics.loading, error: semantics.error, readOnly: readOnly, onCommit: (next) => onPatch({ rows: next }) }), reportType === 'matrix' && (_jsx(DatasetNamesEditor, { label: tr('engine.inspector.report.columnsAcross'), emptyText: tr('engine.inspector.report.columnsAcrossEmpty'), names: columnsAcross, options: dimensionOptions, loading: semantics.loading, error: semantics.error, readOnly: readOnly, onCommit: (next) => onPatch({ columns: next }) }))] })), _jsx("div", { className: "border-t pt-3", children: schema ? (_jsx(SchemaForm, { schema: schema, form: form, value: draft, hiddenFields: ['type', 'label', 'name', 'dataset', 'values', 'rows', 'columns'], readOnly: readOnly, onChange: (next) => onPatch(next) })) : (_jsx("p", { className: "text-[11px] text-muted-foreground", children: tr('engine.inspector.report.noSchema') })) })] }));
|
|
160
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ViewColumnInspector — scoped editor for the selected View column.
|
|
3
|
+
*
|
|
4
|
+
* Selection shape: { kind: 'column', id: '<variant>.columns[<i>]' }
|
|
5
|
+
*
|
|
6
|
+
* SPEC-DRIVEN: the column's detail properties (width / align / pinned /
|
|
7
|
+
* summary / sortable / …) are rendered from the spec's `ListColumn`
|
|
8
|
+
* JSONSchema via the generic {@link SchemaForm}, NOT a hardcoded field
|
|
9
|
+
* list. New ListColumn props in `@objectstack/spec` appear automatically.
|
|
10
|
+
*
|
|
11
|
+
* A thin curated layer stays on top for the column IDENTITY (field key +
|
|
12
|
+
* label) because those round-trip through two shapes: the ObjectStack
|
|
13
|
+
* canonical `{ field, label }` and the legacy TanStack `{ accessorKey,
|
|
14
|
+
* header }`. A column that is a bare string (e.g. a kanban card field) is
|
|
15
|
+
* kept as a string until the author edits a detail prop.
|
|
16
|
+
*/
|
|
17
|
+
import * as React from 'react';
|
|
18
|
+
import type { MetadataInspectorProps } from '../inspector-registry';
|
|
19
|
+
export declare function ViewColumnInspector({ selection, draft, onPatch, onClearSelection, onSelectionChange, locale, readOnly, }: MetadataInspectorProps): React.JSX.Element;
|