@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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowEdgeInspector — scoped editor for the selected flow connection (edge).
|
|
3
|
+
*
|
|
4
|
+
* Selection shape: { kind: 'edge', id: <edgeKey> }
|
|
5
|
+
* Patches: draft.edges[i] = {...edge, ...updates}
|
|
6
|
+
*
|
|
7
|
+
* An edge carries the flow's routing semantics between two nodes: an optional
|
|
8
|
+
* branch `label` (e.g. an Approval node's `approve` / `reject` out-edge, a
|
|
9
|
+
* Decision branch name), a guard `condition` (a CEL expression the engine
|
|
10
|
+
* evaluates to pick the branch), and an `isDefault` flag marking the fallback
|
|
11
|
+
* ("else") branch. Source / target are shown read-only — rewiring is done on
|
|
12
|
+
* the canvas, not here — so the edge's identity key stays stable across edits.
|
|
13
|
+
*/
|
|
14
|
+
import * as React from 'react';
|
|
15
|
+
import type { MetadataInspectorProps } from '../inspector-registry';
|
|
16
|
+
export declare function FlowEdgeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }: MetadataInspectorProps): React.JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { t } from '../i18n';
|
|
3
|
+
import { InspectorShell, InspectorTextField, InspectorCheckboxField, InspectorRemoveButton, InspectorEmptyState, spliceArray, } from './_shared';
|
|
4
|
+
import { Label } from '@object-ui/components';
|
|
5
|
+
import { edgeKey, conditionText } from '../previews/flow-canvas-layout';
|
|
6
|
+
import { validateExpressionClient } from './expression-validate';
|
|
7
|
+
/** Read-only display of an edge endpoint (source / target node id). */
|
|
8
|
+
function EndpointRow({ label, value }) {
|
|
9
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsx("div", { className: "flex h-8 items-center rounded border bg-muted/30 px-2 font-mono text-sm text-muted-foreground", children: value })] }));
|
|
10
|
+
}
|
|
11
|
+
export function FlowEdgeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }) {
|
|
12
|
+
const edges = Array.isArray(draft.edges) ? draft.edges : [];
|
|
13
|
+
const index = edges.findIndex((e, i) => edgeKey(e, i) === selection.id);
|
|
14
|
+
const edge = index >= 0 ? edges[index] : null;
|
|
15
|
+
if (!edge) {
|
|
16
|
+
return (_jsx(InspectorShell, { kindLabel: t('engine.inspector.flowEdge.kind', locale), title: selection.label ?? selection.id, onClose: onClearSelection, closeLabel: t('engine.inspector.flowEdge.close', locale), children: _jsx(InspectorEmptyState, { message: t('engine.inspector.flowEdge.missing', locale) }) }));
|
|
17
|
+
}
|
|
18
|
+
// Splice an updated edge in place. A field edit never moves the edge in the
|
|
19
|
+
// array, so the row index is stable; but an edge without an explicit `id`
|
|
20
|
+
// keys off `source->target#index`, so we re-point the selection to the fresh
|
|
21
|
+
// key after the patch to keep the panel attached to the same edge.
|
|
22
|
+
const patchEdge = (updates) => {
|
|
23
|
+
const next = { ...edge, ...updates };
|
|
24
|
+
// Prune empty optional keys so a cleared field doesn't linger in the draft.
|
|
25
|
+
for (const k of ['label', 'condition', 'isDefault']) {
|
|
26
|
+
const v = next[k];
|
|
27
|
+
if (v === undefined || v === '' || v === false)
|
|
28
|
+
delete next[k];
|
|
29
|
+
}
|
|
30
|
+
onPatch({ edges: spliceArray(edges, index, next) });
|
|
31
|
+
};
|
|
32
|
+
const isDefault = edge.isDefault === true;
|
|
33
|
+
return (_jsxs(InspectorShell, { kindLabel: t('engine.inspector.flowEdge.kind', locale), title: selection.label ?? `${edge.source} → ${edge.target}`, onClose: onClearSelection, closeLabel: t('engine.inspector.flowEdge.close', locale), footer: _jsx(InspectorRemoveButton, { label: t('engine.inspector.flowEdge.remove', locale), onClick: () => {
|
|
34
|
+
onPatch({ edges: spliceArray(edges, index, null) });
|
|
35
|
+
onClearSelection();
|
|
36
|
+
}, disabled: readOnly }), children: [_jsx(EndpointRow, { label: t('engine.inspector.flowEdge.source', locale), value: edge.source }), _jsx(EndpointRow, { label: t('engine.inspector.flowEdge.target', locale), value: edge.target }), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t('engine.inspector.flowEdge.routing', locale) }), _jsx("span", { className: "h-px flex-1 bg-border", "aria-hidden": true })] }), _jsx(InspectorTextField, { label: t('engine.inspector.flowEdge.label', locale), value: edge.label ?? '', onCommit: (v) => patchEdge({ label: v }), placeholder: t('engine.inspector.flowEdge.labelHint', locale), disabled: readOnly || isDefault }), _jsx(InspectorTextField, { label: t('engine.inspector.flowEdge.condition', locale), value: conditionText(edge.condition) ?? '', onCommit: (v) => patchEdge({ condition: v || undefined }), placeholder: t('engine.inspector.flowEdge.conditionHint', locale), disabled: readOnly || isDefault, mono: true }), (() => {
|
|
37
|
+
// ADR-0032 — flag a malformed edge guard (e.g. `{record.x}` brace-in-CEL)
|
|
38
|
+
// inline, with the same corrective message as build/agent validation.
|
|
39
|
+
const issue = isDefault ? null : validateExpressionClient('predicate', edge.condition);
|
|
40
|
+
return issue ? (_jsx("p", { className: "text-[11px] leading-snug text-destructive", role: "alert", children: issue.message })) : null;
|
|
41
|
+
})(), _jsx(InspectorCheckboxField, { label: t('engine.inspector.flowEdge.isDefault', locale), value: isDefault,
|
|
42
|
+
// The default ("else") branch is taken when no other guard matches, so
|
|
43
|
+
// it carries neither a condition nor a branch label — clear both.
|
|
44
|
+
onCommit: (v) => patchEdge(v ? { isDefault: true, condition: undefined, label: undefined } : { isDefault: false }), disabled: readOnly }), _jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: t('engine.inspector.flowEdge.hint', locale) })] }));
|
|
45
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowInspector — the single inspector registered for the `flow` metadata type.
|
|
3
|
+
*
|
|
4
|
+
* The flow canvas emits two kinds of selection (see `FlowPreview` /
|
|
5
|
+
* `FlowCanvas`): a node (`{ kind: 'node' }`) or a connection edge
|
|
6
|
+
* (`{ kind: 'edge' }`). This thin router forwards each to its focused editor so
|
|
7
|
+
* neither component has to know about the other. Anything else falls through to
|
|
8
|
+
* the node inspector (which renders an empty-state for an unknown id).
|
|
9
|
+
*/
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import type { MetadataInspectorProps } from '../inspector-registry';
|
|
12
|
+
export declare function FlowInspector(props: MetadataInspectorProps): React.JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { FlowNodeInspector } from './FlowNodeInspector';
|
|
3
|
+
import { FlowEdgeInspector } from './FlowEdgeInspector';
|
|
4
|
+
export function FlowInspector(props) {
|
|
5
|
+
if (props.selection.kind === 'edge') {
|
|
6
|
+
return _jsx(FlowEdgeInspector, { ...props });
|
|
7
|
+
}
|
|
8
|
+
return _jsx(FlowNodeInspector, { ...props });
|
|
9
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowKeyValueField — a small repeatable key/value editor for object-map
|
|
3
|
+
* config (e.g. an action's `params`, a subflow's `input`, request `headers`).
|
|
4
|
+
*
|
|
5
|
+
* Design notes (why local draft state instead of commit-on-keystroke):
|
|
6
|
+
* - The host inspector owns the draft and re-renders from the top on every
|
|
7
|
+
* `onPatch`. Committing each keystroke would rehydrate rows mid-edit and
|
|
8
|
+
* drop focus / collapse half-typed keys. So rows live in LOCAL state and
|
|
9
|
+
* only flush to `onCommit` on blur, Enter, add, or remove.
|
|
10
|
+
* - Rows carry a STABLE `id` (not the editable key) so renaming a key never
|
|
11
|
+
* remounts the row — caret and focus are preserved.
|
|
12
|
+
* - Values are smart-parsed on commit (number / boolean / else string) so an
|
|
13
|
+
* author can type `3` or `true` without writing JSON. Empty and duplicate
|
|
14
|
+
* keys are skipped when flushing (last non-empty wins is avoided — earlier
|
|
15
|
+
* rows take precedence).
|
|
16
|
+
*/
|
|
17
|
+
import * as React from 'react';
|
|
18
|
+
export interface FlowKeyValueFieldProps {
|
|
19
|
+
label: string;
|
|
20
|
+
value: unknown;
|
|
21
|
+
onCommit: (value: Record<string, unknown> | undefined) => void;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
help?: string;
|
|
24
|
+
addLabel: string;
|
|
25
|
+
keyLabel: string;
|
|
26
|
+
valueLabel: string;
|
|
27
|
+
removeLabel: string;
|
|
28
|
+
emptyLabel: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function FlowKeyValueField({ label, value, onCommit, disabled, help, addLabel, keyLabel, valueLabel, removeLabel, emptyLabel, }: FlowKeyValueFieldProps): React.JSX.Element;
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
* FlowKeyValueField — a small repeatable key/value editor for object-map
|
|
5
|
+
* config (e.g. an action's `params`, a subflow's `input`, request `headers`).
|
|
6
|
+
*
|
|
7
|
+
* Design notes (why local draft state instead of commit-on-keystroke):
|
|
8
|
+
* - The host inspector owns the draft and re-renders from the top on every
|
|
9
|
+
* `onPatch`. Committing each keystroke would rehydrate rows mid-edit and
|
|
10
|
+
* drop focus / collapse half-typed keys. So rows live in LOCAL state and
|
|
11
|
+
* only flush to `onCommit` on blur, Enter, add, or remove.
|
|
12
|
+
* - Rows carry a STABLE `id` (not the editable key) so renaming a key never
|
|
13
|
+
* remounts the row — caret and focus are preserved.
|
|
14
|
+
* - Values are smart-parsed on commit (number / boolean / else string) so an
|
|
15
|
+
* author can type `3` or `true` without writing JSON. Empty and duplicate
|
|
16
|
+
* keys are skipped when flushing (last non-empty wins is avoided — earlier
|
|
17
|
+
* rows take precedence).
|
|
18
|
+
*/
|
|
19
|
+
import * as React from 'react';
|
|
20
|
+
import { Plus, X } from 'lucide-react';
|
|
21
|
+
import { Button, Input, Label } from '@object-ui/components';
|
|
22
|
+
import { uniqueId } from './_shared';
|
|
23
|
+
function isPlainObject(v) {
|
|
24
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
25
|
+
}
|
|
26
|
+
/** Render a stored value as an editable string. */
|
|
27
|
+
function toRaw(v) {
|
|
28
|
+
if (v == null)
|
|
29
|
+
return '';
|
|
30
|
+
if (typeof v === 'string')
|
|
31
|
+
return v;
|
|
32
|
+
if (typeof v === 'number' || typeof v === 'boolean')
|
|
33
|
+
return String(v);
|
|
34
|
+
return JSON.stringify(v);
|
|
35
|
+
}
|
|
36
|
+
/** Smart-parse an edited value string back to a scalar (no hand-written JSON). */
|
|
37
|
+
function parseValue(raw) {
|
|
38
|
+
const s = raw.trim();
|
|
39
|
+
if (s === '')
|
|
40
|
+
return '';
|
|
41
|
+
if (s === 'true')
|
|
42
|
+
return true;
|
|
43
|
+
if (s === 'false')
|
|
44
|
+
return false;
|
|
45
|
+
if (/^-?\d+(\.\d+)?$/.test(s))
|
|
46
|
+
return Number(s);
|
|
47
|
+
// Round-trip non-scalar values losslessly: a filter operator like
|
|
48
|
+
// `{"$ne": null}` or an array must parse back to its object/array form, not
|
|
49
|
+
// be flattened to a string. Template refs like `{leadId}` are not valid JSON
|
|
50
|
+
// and correctly fall through to a plain string.
|
|
51
|
+
if ((s.startsWith('{') && s.endsWith('}')) || (s.startsWith('[') && s.endsWith(']'))) {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(s);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return raw;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return raw;
|
|
60
|
+
}
|
|
61
|
+
function toRows(obj, existingIds) {
|
|
62
|
+
const ids = [...existingIds];
|
|
63
|
+
return Object.entries(obj).map(([key, value]) => {
|
|
64
|
+
const id = uniqueId('kv', ids);
|
|
65
|
+
ids.push(id);
|
|
66
|
+
return { id, key, raw: toRaw(value) };
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Flush rows to an object, skipping empty/duplicate keys (first wins). */
|
|
70
|
+
function rowsToObject(rows) {
|
|
71
|
+
const out = {};
|
|
72
|
+
for (const r of rows) {
|
|
73
|
+
const k = r.key.trim();
|
|
74
|
+
if (!k || k in out)
|
|
75
|
+
continue;
|
|
76
|
+
out[k] = parseValue(r.raw);
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
function serialize(obj) {
|
|
81
|
+
const sorted = Object.keys(obj).sort().reduce((acc, k) => {
|
|
82
|
+
acc[k] = obj[k];
|
|
83
|
+
return acc;
|
|
84
|
+
}, {});
|
|
85
|
+
return JSON.stringify(sorted);
|
|
86
|
+
}
|
|
87
|
+
export function FlowKeyValueField({ label, value, onCommit, disabled, help, addLabel, keyLabel, valueLabel, removeLabel, emptyLabel, }) {
|
|
88
|
+
const external = isPlainObject(value) ? value : {};
|
|
89
|
+
const [rows, setRows] = React.useState(() => toRows(external, []));
|
|
90
|
+
// Track the last value we committed so an external change (node switch) can
|
|
91
|
+
// resync rows without clobbering an in-progress edit of the same node.
|
|
92
|
+
const lastCommitted = React.useRef(serialize(external));
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
const next = serialize(external);
|
|
95
|
+
if (next !== lastCommitted.current) {
|
|
96
|
+
setRows(toRows(external, []));
|
|
97
|
+
lastCommitted.current = next;
|
|
98
|
+
}
|
|
99
|
+
}, [external]);
|
|
100
|
+
const flush = (nextRows) => {
|
|
101
|
+
const obj = rowsToObject(nextRows);
|
|
102
|
+
lastCommitted.current = serialize(obj);
|
|
103
|
+
onCommit(Object.keys(obj).length ? obj : undefined);
|
|
104
|
+
};
|
|
105
|
+
const setRowField = (id, patch) => {
|
|
106
|
+
setRows((rs) => rs.map((r) => (r.id === id ? { ...r, ...patch } : r)));
|
|
107
|
+
};
|
|
108
|
+
const addRow = () => {
|
|
109
|
+
setRows((rs) => [...rs, { id: uniqueId('kv', rs.map((r) => r.id)), key: '', raw: '' }]);
|
|
110
|
+
};
|
|
111
|
+
const removeRow = (id) => {
|
|
112
|
+
setRows((rs) => {
|
|
113
|
+
const next = rs.filter((r) => r.id !== id);
|
|
114
|
+
flush(next);
|
|
115
|
+
return next;
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsxs("div", { className: "space-y-1.5", children: [rows.length === 0 && (_jsx("p", { className: "text-[11px] italic text-muted-foreground", children: emptyLabel })), rows.map((row) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Input, { value: row.key, onChange: (e) => setRowField(row.id, { key: e.target.value }), onBlur: () => flush(rows), onKeyDown: (e) => {
|
|
119
|
+
if (e.key === 'Enter')
|
|
120
|
+
e.target.blur();
|
|
121
|
+
}, placeholder: keyLabel, disabled: disabled, className: "h-8 flex-1 font-mono text-xs" }), _jsx(Input, { value: row.raw, onChange: (e) => setRowField(row.id, { raw: e.target.value }), onBlur: () => flush(rows), onKeyDown: (e) => {
|
|
122
|
+
if (e.key === 'Enter')
|
|
123
|
+
e.target.blur();
|
|
124
|
+
}, placeholder: valueLabel, disabled: disabled, className: "h-8 flex-1 text-xs" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-8 w-8 shrink-0 p-0 text-muted-foreground", onClick: () => removeRow(row.id), disabled: disabled, "aria-label": removeLabel, title: removeLabel, children: _jsx(X, { className: "h-3.5 w-3.5" }) })] }, row.id)))] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "h-7 w-full text-xs", onClick: addRow, disabled: disabled, children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), addLabel] }), help && _jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: help })] }));
|
|
125
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowNodeConfigField — renders one scalar config control for a flow node,
|
|
3
|
+
* driven by a `FlowConfigField` descriptor. Bridges descriptor "kind" to the
|
|
4
|
+
* shared inspector field primitives and writes back to `node.config[key]`.
|
|
5
|
+
*/
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import type { FlowConfigField } from './flow-node-config';
|
|
8
|
+
import { type FlowReferenceContext } from './FlowReferenceField';
|
|
9
|
+
export interface FlowNodeConfigFieldProps {
|
|
10
|
+
field: FlowConfigField;
|
|
11
|
+
value: unknown;
|
|
12
|
+
onCommit: (value: unknown) => void;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
locale?: string;
|
|
15
|
+
/** Draft + node context so `reference` fields can resolve their options. */
|
|
16
|
+
context?: FlowReferenceContext;
|
|
17
|
+
}
|
|
18
|
+
export declare function FlowNodeConfigField({ field, value, onCommit, disabled, locale, context }: FlowNodeConfigFieldProps): React.JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { t } from '../i18n';
|
|
3
|
+
import { InspectorTextField, InspectorNumberField, InspectorSelectField, InspectorCheckboxField, } from './_shared';
|
|
4
|
+
import { Label } from '@object-ui/components';
|
|
5
|
+
import { FlowKeyValueField } from './FlowKeyValueField';
|
|
6
|
+
import { FlowStringListField } from './FlowStringListField';
|
|
7
|
+
import { FlowObjectListField } from './FlowObjectListField';
|
|
8
|
+
import { FlowReferenceField } from './FlowReferenceField';
|
|
9
|
+
import { validateExpressionClient } from './expression-validate';
|
|
10
|
+
export function FlowNodeConfigField({ field, value, onCommit, disabled, locale, context }) {
|
|
11
|
+
const control = (() => {
|
|
12
|
+
switch (field.kind) {
|
|
13
|
+
case 'reference':
|
|
14
|
+
return (_jsx(FlowReferenceField, { field: field, value: value, onCommit: (v) => onCommit(v), disabled: disabled, context: context }));
|
|
15
|
+
case 'keyValue':
|
|
16
|
+
return (_jsx(FlowKeyValueField, { label: field.label, value: value, onCommit: (v) => onCommit(v), disabled: disabled, addLabel: t('engine.inspector.flowNode.kv.add', locale), keyLabel: t('engine.inspector.flowNode.kv.key', locale), valueLabel: t('engine.inspector.flowNode.kv.value', locale), removeLabel: t('engine.inspector.flowNode.kv.remove', locale), emptyLabel: t('engine.inspector.flowNode.kv.empty', locale) }));
|
|
17
|
+
case 'stringList':
|
|
18
|
+
return (_jsx(FlowStringListField, { label: field.label, value: value, onCommit: (v) => onCommit(v), disabled: disabled, addLabel: t('engine.inspector.flowNode.list.add', locale), itemLabel: t('engine.inspector.flowNode.list.item', locale), removeLabel: t('engine.inspector.flowNode.list.remove', locale), emptyLabel: t('engine.inspector.flowNode.list.empty', locale) }));
|
|
19
|
+
case 'objectList':
|
|
20
|
+
return (_jsx(FlowObjectListField, { label: field.label, columns: field.columns ?? [], value: value, onCommit: (v) => onCommit(v), disabled: disabled, addLabel: t('engine.inspector.flowNode.list.add', locale), removeLabel: t('engine.inspector.flowNode.list.remove', locale), emptyLabel: t('engine.inspector.flowNode.list.empty', locale), context: context }));
|
|
21
|
+
case 'number':
|
|
22
|
+
return (_jsx(InspectorNumberField, { label: field.label, value: typeof value === 'number' ? value : value != null && value !== '' ? Number(value) : undefined, placeholder: field.placeholder, onCommit: (v) => onCommit(v), disabled: disabled }));
|
|
23
|
+
case 'boolean':
|
|
24
|
+
return (_jsx(InspectorCheckboxField, { label: field.label, value: value === true, onCommit: (v) => onCommit(v), disabled: disabled }));
|
|
25
|
+
case 'select':
|
|
26
|
+
return (_jsx(InspectorSelectField, { label: field.label, value: value != null ? String(value) : '', options: field.options ?? [], onCommit: (v) => onCommit(v), disabled: disabled }));
|
|
27
|
+
case 'textarea':
|
|
28
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: field.label }), _jsx("textarea", { value: value != null ? String(value) : '', onChange: (e) => onCommit(e.target.value), placeholder: field.placeholder, disabled: disabled, rows: 4, className: "w-full rounded border bg-background px-2 py-1.5 font-mono text-xs" })] }));
|
|
29
|
+
case 'expression':
|
|
30
|
+
case 'text':
|
|
31
|
+
default:
|
|
32
|
+
return (_jsx(InspectorTextField, { label: field.label, value: value != null ? String(value) : '', placeholder: field.placeholder, onCommit: (v) => onCommit(v), disabled: disabled, mono: field.kind === 'expression' }));
|
|
33
|
+
}
|
|
34
|
+
})();
|
|
35
|
+
// ADR-0032 — surface a malformed condition (e.g. the `{record.x}` brace-in-CEL
|
|
36
|
+
// mistake) inline, as the author types, with the same corrective message the
|
|
37
|
+
// build and the agent tool emit. Only checked for expression-bearing fields.
|
|
38
|
+
const exprIssue = field.kind === 'expression' ? validateExpressionClient('predicate', value) : null;
|
|
39
|
+
return (_jsxs("div", { className: "space-y-1", children: [control, exprIssue && (_jsx("p", { className: "text-[11px] leading-snug text-destructive", role: "alert", children: exprIssue.message })), field.help && !exprIssue && (_jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: field.help }))] }));
|
|
40
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowNodeInspector — scoped editor for the selected flow node.
|
|
3
|
+
*
|
|
4
|
+
* Selection shape: { kind: 'node', id: <nodeId> }
|
|
5
|
+
* Patches: draft.nodes[i] = {...node, ...updates}
|
|
6
|
+
*
|
|
7
|
+
* Beyond id / label / type / description, each node type exposes a set of
|
|
8
|
+
* typed form fields (see `flow-node-config`) that edit scalar keys on
|
|
9
|
+
* `node.config`. Any remaining config keys (objects, arrays, bespoke flags)
|
|
10
|
+
* are surfaced in an "Advanced (JSON)" block so authors are never locked out.
|
|
11
|
+
*/
|
|
12
|
+
import * as React from 'react';
|
|
13
|
+
import type { MetadataInspectorProps } from '../inspector-registry';
|
|
14
|
+
export declare function FlowNodeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }: MetadataInspectorProps): React.JSX.Element;
|
|
@@ -0,0 +1,140 @@
|
|
|
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
|
+
* FlowNodeInspector — scoped editor for the selected flow node.
|
|
5
|
+
*
|
|
6
|
+
* Selection shape: { kind: 'node', id: <nodeId> }
|
|
7
|
+
* Patches: draft.nodes[i] = {...node, ...updates}
|
|
8
|
+
*
|
|
9
|
+
* Beyond id / label / type / description, each node type exposes a set of
|
|
10
|
+
* typed form fields (see `flow-node-config`) that edit scalar keys on
|
|
11
|
+
* `node.config`. Any remaining config keys (objects, arrays, bespoke flags)
|
|
12
|
+
* are surfaced in an "Advanced (JSON)" block so authors are never locked out.
|
|
13
|
+
*/
|
|
14
|
+
import * as React from 'react';
|
|
15
|
+
import { Plus } from 'lucide-react';
|
|
16
|
+
import { t } from '../i18n';
|
|
17
|
+
import { InspectorShell, InspectorTextField, InspectorSelectField, InspectorRemoveButton, InspectorEmptyState, spliceArray, } from './_shared';
|
|
18
|
+
import { fieldsForNodeType, isFieldVisible, getFieldValue, configKeyOf, FLOW_NODE_TYPE_OPTIONS, } from './flow-node-config';
|
|
19
|
+
import { jsonSchemaToFlowFields } from './json-schema-to-fields';
|
|
20
|
+
import { useActionConfigSchemas } from '../previews/useFlowNodePalette';
|
|
21
|
+
import { FlowNodeConfigField } from './FlowNodeConfigField';
|
|
22
|
+
function asConfig(node) {
|
|
23
|
+
const c = node?.config;
|
|
24
|
+
return c && typeof c === 'object' && !Array.isArray(c) ? c : {};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Immutably set `value` at `path` on a plain object, pruning any intermediate
|
|
28
|
+
* object that becomes empty (so e.g. clearing the last `waitEventConfig` key
|
|
29
|
+
* removes the whole block). Empty string / null / undefined deletes the leaf.
|
|
30
|
+
*/
|
|
31
|
+
function setAtPath(obj, path, value) {
|
|
32
|
+
const [head, ...rest] = path;
|
|
33
|
+
const next = { ...obj };
|
|
34
|
+
if (rest.length === 0) {
|
|
35
|
+
if (value === undefined || value === null || value === '')
|
|
36
|
+
delete next[head];
|
|
37
|
+
else
|
|
38
|
+
next[head] = value;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const cur = next[head];
|
|
42
|
+
const base = cur && typeof cur === 'object' && !Array.isArray(cur) ? cur : {};
|
|
43
|
+
const child = setAtPath(base, rest, value);
|
|
44
|
+
if (Object.keys(child).length === 0)
|
|
45
|
+
delete next[head];
|
|
46
|
+
else
|
|
47
|
+
next[head] = child;
|
|
48
|
+
}
|
|
49
|
+
return next;
|
|
50
|
+
}
|
|
51
|
+
export function FlowNodeInspector({ selection, draft, onPatch, onClearSelection, locale, readOnly }) {
|
|
52
|
+
const nodes = Array.isArray(draft.nodes) ? draft.nodes : [];
|
|
53
|
+
const index = nodes.findIndex((n) => n?.id === selection.id);
|
|
54
|
+
const node = index >= 0 ? nodes[index] : null;
|
|
55
|
+
// Server-driven property form: when the running engine publishes a config
|
|
56
|
+
// JSON Schema for this node type (ADR-0018 §configSchema — e.g. the ADR-0019
|
|
57
|
+
// approval node), derive the form from it so the designer stays in lock-step
|
|
58
|
+
// with the backend. Falls back to the hardcoded field group when no schema is
|
|
59
|
+
// published (offline / plugin absent / older backend).
|
|
60
|
+
const configSchemas = useActionConfigSchemas();
|
|
61
|
+
const fields = React.useMemo(() => {
|
|
62
|
+
const schema = node?.type ? configSchemas[node.type] : undefined;
|
|
63
|
+
const serverFields = schema !== undefined ? jsonSchemaToFlowFields(schema) : null;
|
|
64
|
+
return serverFields ?? fieldsForNodeType(node?.type);
|
|
65
|
+
}, [configSchemas, node?.type]);
|
|
66
|
+
const config = asConfig(node);
|
|
67
|
+
const visibleFields = fields.filter((f) => isFieldVisible(f, node, fields));
|
|
68
|
+
// Only fields stored under `config` "own" a config key; spec-structured
|
|
69
|
+
// blocks (waitEventConfig, etc.) and top-level timeoutMs never suppress an
|
|
70
|
+
// Advanced key.
|
|
71
|
+
const ownedConfigKeys = React.useMemo(() => {
|
|
72
|
+
const s = new Set();
|
|
73
|
+
for (const f of fields) {
|
|
74
|
+
const k = configKeyOf(f);
|
|
75
|
+
if (k)
|
|
76
|
+
s.add(k);
|
|
77
|
+
}
|
|
78
|
+
return s;
|
|
79
|
+
}, [fields]);
|
|
80
|
+
const extraJson = React.useMemo(() => {
|
|
81
|
+
const extra = Object.fromEntries(Object.entries(config).filter(([k]) => !ownedConfigKeys.has(k)));
|
|
82
|
+
return Object.keys(extra).length ? JSON.stringify(extra, null, 2) : '';
|
|
83
|
+
// Recompute when the node identity changes (patch) or the known keys change.
|
|
84
|
+
}, [node, ownedConfigKeys]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
85
|
+
const [advText, setAdvText] = React.useState(extraJson);
|
|
86
|
+
const [advError, setAdvError] = React.useState(null);
|
|
87
|
+
const [advOpen, setAdvOpen] = React.useState(extraJson.trim() !== '');
|
|
88
|
+
// Reveals the optional custom-keys editor on nodes that currently have none.
|
|
89
|
+
const [advReveal, setAdvReveal] = React.useState(false);
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
setAdvText(extraJson);
|
|
92
|
+
setAdvError(null);
|
|
93
|
+
setAdvOpen(extraJson.trim() !== '');
|
|
94
|
+
setAdvReveal(false);
|
|
95
|
+
}, [extraJson]);
|
|
96
|
+
if (!node) {
|
|
97
|
+
return (_jsx(InspectorShell, { kindLabel: t('engine.inspector.flowNode.kind', locale), title: selection.label ?? selection.id, onClose: onClearSelection, closeLabel: t('engine.inspector.flowNode.close', locale), children: _jsx(InspectorEmptyState, { message: selection.id }) }));
|
|
98
|
+
}
|
|
99
|
+
const patchNode = (updates) => {
|
|
100
|
+
onPatch({ nodes: spliceArray(nodes, index, { ...node, ...updates }) });
|
|
101
|
+
};
|
|
102
|
+
const hasExtras = extraJson.trim() !== '';
|
|
103
|
+
const setField = (path, value) => {
|
|
104
|
+
const nextNode = setAtPath(node, path, value);
|
|
105
|
+
onPatch({ nodes: spliceArray(nodes, index, nextNode) });
|
|
106
|
+
};
|
|
107
|
+
const commitAdvanced = () => {
|
|
108
|
+
try {
|
|
109
|
+
const parsed = advText.trim() === '' ? {} : JSON.parse(advText);
|
|
110
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
111
|
+
throw new Error('Must be a JSON object');
|
|
112
|
+
// Form-owned config keys always win: the Advanced block may only set keys
|
|
113
|
+
// that no form field owns, so it can never overwrite or resurrect one.
|
|
114
|
+
const knownPart = Object.fromEntries(Object.entries(config).filter(([k]) => ownedConfigKeys.has(k)));
|
|
115
|
+
const extrasPart = Object.fromEntries(Object.entries(parsed).filter(([k]) => !ownedConfigKeys.has(k)));
|
|
116
|
+
const merged = { ...knownPart, ...extrasPart };
|
|
117
|
+
setAdvError(null);
|
|
118
|
+
const nextNode = { ...node };
|
|
119
|
+
if (Object.keys(merged).length === 0)
|
|
120
|
+
delete nextNode.config;
|
|
121
|
+
else
|
|
122
|
+
nextNode.config = merged;
|
|
123
|
+
onPatch({ nodes: spliceArray(nodes, index, nextNode) });
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
setAdvError(String(e.message));
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const remove = () => {
|
|
130
|
+
onPatch({ nodes: spliceArray(nodes, index, null) });
|
|
131
|
+
onClearSelection();
|
|
132
|
+
};
|
|
133
|
+
const typeOptions = FLOW_NODE_TYPE_OPTIONS.includes(node.type)
|
|
134
|
+
? [...FLOW_NODE_TYPE_OPTIONS]
|
|
135
|
+
: [...FLOW_NODE_TYPE_OPTIONS, node.type ?? ''].filter(Boolean);
|
|
136
|
+
return (_jsxs(InspectorShell, { kindLabel: t('engine.inspector.flowNode.kind', locale), title: node.label || node.id, onClose: onClearSelection, closeLabel: t('engine.inspector.flowNode.close', locale), footer: _jsx(InspectorRemoveButton, { label: t('engine.inspector.flowNode.remove', locale), onClick: remove, disabled: readOnly }), children: [_jsx(InspectorTextField, { label: t('engine.inspector.flowNode.id', locale), value: node.id, onCommit: (v) => patchNode({ id: v }), disabled: readOnly, mono: true }), _jsx(InspectorTextField, { label: t('engine.inspector.flowNode.label', locale), value: node.label ?? '', onCommit: (v) => patchNode({ label: v }), disabled: readOnly }), _jsx(InspectorSelectField, { label: t('engine.inspector.flowNode.type', locale), value: node.type, options: typeOptions.map((v) => ({ value: v, label: v })), onCommit: (v) => patchNode({ type: v }), disabled: readOnly }), _jsx(InspectorTextField, { label: t('engine.inspector.flowNode.description', locale), value: node.description ?? '', onCommit: (v) => patchNode({ description: v || undefined }), disabled: readOnly }), fields.length === 0 ? (_jsx("p", { className: "pt-1 text-xs italic text-muted-foreground", children: t('engine.inspector.flowNode.noConfig', locale) })) : (visibleFields.length > 0 && (_jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t('engine.inspector.flowNode.configuration', locale) }), _jsx("span", { className: "h-px flex-1 bg-border", "aria-hidden": true })] }))), visibleFields.map((field) => (_jsx(FlowNodeConfigField, { field: field, value: getFieldValue(node, field), onCommit: (v) => setField(field.path, v), disabled: readOnly, locale: locale, context: { draft, node } }, field.id))), hasExtras || advReveal ? (_jsxs("details", { className: "group rounded border bg-muted/20", open: advOpen, onToggle: (e) => setAdvOpen(e.target.open), children: [_jsx("summary", { className: "cursor-pointer select-none px-2 py-1.5 text-xs font-medium text-muted-foreground", children: t('engine.inspector.flowNode.advanced', locale) }), _jsxs("div", { className: "space-y-1 border-t p-2", children: [_jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: t('engine.inspector.flowNode.advancedHint', locale) }), _jsx("textarea", { value: advText, onChange: (e) => setAdvText(e.target.value), onBlur: commitAdvanced, disabled: readOnly, rows: 6, placeholder: "{ }", className: "w-full rounded border bg-background px-2 py-1.5 font-mono text-xs" }), advError && _jsx("div", { className: "text-xs text-destructive", children: advError })] })] })) : (!readOnly && (_jsxs("button", { type: "button", onClick: () => {
|
|
137
|
+
setAdvReveal(true);
|
|
138
|
+
setAdvOpen(true);
|
|
139
|
+
}, className: "inline-flex items-center gap-1 self-start text-[11px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx(Plus, { className: "h-3 w-3" }), t('engine.inspector.flowNode.advanced', locale)] })))] }));
|
|
140
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowObjectListField — a repeatable array-of-objects editor driven by a column
|
|
3
|
+
* schema (e.g. a screen node's `fields`: a list of `{name,label,type,required,
|
|
4
|
+
* visibleWhen}` definitions).
|
|
5
|
+
*
|
|
6
|
+
* Like the sibling key/value and string-list editors, rows are held in LOCAL
|
|
7
|
+
* state with a STABLE id and flushed on blur / Enter / add / remove so a row
|
|
8
|
+
* never remounts mid-keystroke. Empty per-cell values are pruned; a row with no
|
|
9
|
+
* populated cells is dropped on flush; an empty list commits `undefined`.
|
|
10
|
+
*/
|
|
11
|
+
import * as React from 'react';
|
|
12
|
+
import type { FlowConfigColumn } from './flow-node-config';
|
|
13
|
+
import { type FlowReferenceContext } from './FlowReferenceField';
|
|
14
|
+
export interface FlowObjectListFieldProps {
|
|
15
|
+
label: string;
|
|
16
|
+
columns: FlowConfigColumn[];
|
|
17
|
+
value: unknown;
|
|
18
|
+
onCommit: (value: Array<Record<string, unknown>> | undefined) => void;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
addLabel: string;
|
|
21
|
+
removeLabel: string;
|
|
22
|
+
emptyLabel: string;
|
|
23
|
+
/** Draft + node context so `reference` columns can resolve their options. */
|
|
24
|
+
context?: FlowReferenceContext;
|
|
25
|
+
}
|
|
26
|
+
export declare function FlowObjectListField({ label, columns, value, onCommit, disabled, addLabel, removeLabel, emptyLabel, context, }: FlowObjectListFieldProps): React.JSX.Element;
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
* FlowObjectListField — a repeatable array-of-objects editor driven by a column
|
|
5
|
+
* schema (e.g. a screen node's `fields`: a list of `{name,label,type,required,
|
|
6
|
+
* visibleWhen}` definitions).
|
|
7
|
+
*
|
|
8
|
+
* Like the sibling key/value and string-list editors, rows are held in LOCAL
|
|
9
|
+
* state with a STABLE id and flushed on blur / Enter / add / remove so a row
|
|
10
|
+
* never remounts mid-keystroke. Empty per-cell values are pruned; a row with no
|
|
11
|
+
* populated cells is dropped on flush; an empty list commits `undefined`.
|
|
12
|
+
*/
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import { Plus, X } from 'lucide-react';
|
|
15
|
+
import { Button, Input, Label, Checkbox } from '@object-ui/components';
|
|
16
|
+
import { uniqueId } from './_shared';
|
|
17
|
+
import { ReferenceCombobox, resolveRefKind } from './FlowReferenceField';
|
|
18
|
+
function toRows(list, columns) {
|
|
19
|
+
const ids = [];
|
|
20
|
+
return list.map((item) => {
|
|
21
|
+
const id = uniqueId('ol', ids);
|
|
22
|
+
ids.push(id);
|
|
23
|
+
const values = {};
|
|
24
|
+
for (const col of columns) {
|
|
25
|
+
const v = item[col.key];
|
|
26
|
+
if (col.kind === 'boolean')
|
|
27
|
+
values[col.key] = v === true;
|
|
28
|
+
else if (v != null)
|
|
29
|
+
values[col.key] = String(v);
|
|
30
|
+
else
|
|
31
|
+
values[col.key] = '';
|
|
32
|
+
}
|
|
33
|
+
return { id, values };
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function rowsToList(rows, columns) {
|
|
37
|
+
const out = [];
|
|
38
|
+
for (const row of rows) {
|
|
39
|
+
const obj = {};
|
|
40
|
+
let hasValue = false;
|
|
41
|
+
for (const col of columns) {
|
|
42
|
+
const v = row.values[col.key];
|
|
43
|
+
if (col.kind === 'boolean') {
|
|
44
|
+
if (v === true) {
|
|
45
|
+
obj[col.key] = true;
|
|
46
|
+
hasValue = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (typeof v === 'string' && v.trim() !== '') {
|
|
50
|
+
obj[col.key] = v.trim();
|
|
51
|
+
hasValue = true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (hasValue)
|
|
55
|
+
out.push(obj);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
export function FlowObjectListField({ label, columns, value, onCommit, disabled, addLabel, removeLabel, emptyLabel, context, }) {
|
|
60
|
+
const external = React.useMemo(() => Array.isArray(value)
|
|
61
|
+
? value.filter((v) => v && typeof v === 'object')
|
|
62
|
+
: [], [value]);
|
|
63
|
+
const [rows, setRows] = React.useState(() => toRows(external, columns));
|
|
64
|
+
const lastCommitted = React.useRef(JSON.stringify(external));
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
const next = JSON.stringify(external);
|
|
67
|
+
if (next !== lastCommitted.current) {
|
|
68
|
+
setRows(toRows(external, columns));
|
|
69
|
+
lastCommitted.current = next;
|
|
70
|
+
}
|
|
71
|
+
}, [external, columns]);
|
|
72
|
+
const flush = (nextRows) => {
|
|
73
|
+
const list = rowsToList(nextRows, columns);
|
|
74
|
+
lastCommitted.current = JSON.stringify(list);
|
|
75
|
+
onCommit(list.length ? list : undefined);
|
|
76
|
+
};
|
|
77
|
+
const setCell = (id, key, v) => {
|
|
78
|
+
setRows((rs) => rs.map((r) => (r.id === id ? { ...r, values: { ...r.values, [key]: v } } : r)));
|
|
79
|
+
};
|
|
80
|
+
const addRow = () => {
|
|
81
|
+
const values = {};
|
|
82
|
+
for (const col of columns)
|
|
83
|
+
values[col.key] = col.kind === 'boolean' ? false : '';
|
|
84
|
+
setRows((rs) => [...rs, { id: uniqueId('ol', rs.map((r) => r.id)), values }]);
|
|
85
|
+
};
|
|
86
|
+
const removeRow = (id) => {
|
|
87
|
+
setRows((rs) => {
|
|
88
|
+
const next = rs.filter((r) => r.id !== id);
|
|
89
|
+
flush(next);
|
|
90
|
+
return next;
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: label }), _jsxs("div", { className: "space-y-2", children: [rows.length === 0 && (_jsx("p", { className: "text-[11px] italic text-muted-foreground", children: emptyLabel })), rows.map((row) => (_jsxs("div", { className: "rounded border bg-muted/30 p-2", children: [_jsx("div", { className: "mb-1 flex justify-end", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-6 w-6 p-0 text-muted-foreground", onClick: () => removeRow(row.id), disabled: disabled, "aria-label": removeLabel, title: removeLabel, children: _jsx(X, { className: "h-3.5 w-3.5" }) }) }), _jsx("div", { className: "space-y-1.5", children: columns.map((col) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "w-24 shrink-0 text-[11px] text-muted-foreground", children: col.label }), col.kind === 'boolean' ? (_jsx(Checkbox, { checked: row.values[col.key] === true, onCheckedChange: (c) => {
|
|
94
|
+
setRows((rs) => {
|
|
95
|
+
const next = rs.map((r) => r.id === row.id
|
|
96
|
+
? { ...r, values: { ...r.values, [col.key]: c === true } }
|
|
97
|
+
: r);
|
|
98
|
+
flush(next);
|
|
99
|
+
return next;
|
|
100
|
+
});
|
|
101
|
+
}, disabled: disabled })) : col.kind === 'reference' ? (_jsx("div", { className: "flex-1", children: _jsx(ReferenceCombobox, { resolved: resolveRefKind(col.ref, (k) => row.values[k]), value: typeof row.values[col.key] === 'string' ? row.values[col.key] : '', onCommit: (v) => setCell(row.id, col.key, typeof v === 'string' ? v : ''), onBlur: () => flush(rows), placeholder: col.placeholder, disabled: disabled, context: context, showHint: false }) })) : (_jsx(Input, { value: typeof row.values[col.key] === 'string' ? row.values[col.key] : '', onChange: (e) => setCell(row.id, col.key, e.target.value), onBlur: () => flush(rows), onKeyDown: (e) => {
|
|
102
|
+
if (e.key === 'Enter')
|
|
103
|
+
e.target.blur();
|
|
104
|
+
}, placeholder: col.placeholder, disabled: disabled, className: `h-8 flex-1 text-xs${col.kind === 'expression' ? ' font-mono' : ''}` }))] }, col.key))) })] }, row.id)))] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "h-7 w-full text-xs", onClick: addRow, disabled: disabled, children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), addLabel] })] }));
|
|
105
|
+
}
|