@object-ui/app-shell 6.2.3 → 7.1.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 +1229 -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 +184 -39
- 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 +747 -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 +28 -0
- package/dist/console/ai/LiveCanvas.js +80 -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 +137 -4
- package/dist/hooks/useChatConversation.js +316 -25
- package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
- package/dist/hooks/useConsoleActionRuntime.js +564 -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 +18 -8
- package/dist/index.js +17 -5
- 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 +34 -2
- package/dist/layout/ConsoleFloatingChatbot.js +391 -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 +242 -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/layout/agentPicker.d.ts +56 -0
- package/dist/layout/agentPicker.js +40 -0
- 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/CommitTimeline.d.ts +15 -0
- package/dist/preview/CommitTimeline.js +82 -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 +83 -0
- package/dist/preview/commitHistory.d.ts +28 -0
- package/dist/preview/commitHistory.js +48 -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 +192 -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 +31 -0
- package/dist/views/FlowRunner.js +121 -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/ScreenView.d.ts +70 -0
- package/dist/views/ScreenView.js +73 -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 +101 -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 +39 -0
- package/dist/views/metadata-admin/JsonSourceEditor.js +196 -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 +403 -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 +1250 -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 +258 -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 +205 -0
- package/dist/views/metadata-admin/anchors.js +255 -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 +1252 -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 +221 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +126 -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 +205 -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 +55 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +365 -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 +218 -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 +128 -0
- package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
- package/dist/views/metadata-admin/inspectors/datasetFilterCondition.d.ts +24 -0
- package/dist/views/metadata-admin/inspectors/datasetFilterCondition.js +97 -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 +506 -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/issuePath.d.ts +22 -0
- package/dist/views/metadata-admin/issuePath.js +65 -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/package-scope.d.ts +26 -0
- package/dist/views/metadata-admin/package-scope.js +43 -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 +105 -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 +49 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.js +416 -0
- package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/FlowPreview.js +120 -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 +204 -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 +200 -5
- 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/ScreenPreview.d.ts +38 -0
- package/dist/views/metadata-admin/previews/ScreenPreview.js +61 -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 +102 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.js +227 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +96 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.js +373 -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 +130 -0
- package/dist/views/metadata-admin/previews/object-fields-io.js +243 -0
- package/dist/views/metadata-admin/previews/screen-spec.d.ts +43 -0
- package/dist/views/metadata-admin/previews/screen-spec.js +108 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +102 -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 +15 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +185 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +73 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +426 -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,97 @@
|
|
|
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
|
+
* FieldsListEditor — the right-panel column manager (mainstream low-code
|
|
5
|
+
* pattern: a vertical, drag-reorderable list of fields with an inline
|
|
6
|
+
* "+ Add field" picker).
|
|
7
|
+
*
|
|
8
|
+
* This is the SINGLE owner of column read / write / reorder / remove / select
|
|
9
|
+
* logic for a View variant. It is rendered in two places so the fields list is
|
|
10
|
+
* always visible:
|
|
11
|
+
* • {@link ViewVariantInspector} (the home / variant panel) — no row is
|
|
12
|
+
* highlighted; clicking a row drills into the scoped column inspector.
|
|
13
|
+
* • {@link ViewColumnInspector} (the scoped column panel) — the selected row
|
|
14
|
+
* is highlighted and the column's detail props render below it.
|
|
15
|
+
*
|
|
16
|
+
* Columns round-trip in their original shape: string variants (e.g. kanban
|
|
17
|
+
* card fields) stay strings; object variants keep `{ field, label, … }`. The
|
|
18
|
+
* raw `columns` array is reordered / spliced directly — never normalised — so
|
|
19
|
+
* round-trips stay lossless.
|
|
20
|
+
*/
|
|
21
|
+
import * as React from 'react';
|
|
22
|
+
import { Badge, Label } from '@object-ui/components';
|
|
23
|
+
import { appendArray, moveArray, spliceArray } from '../inspectors/_shared';
|
|
24
|
+
import { useObjectFields } from './useObjectFields';
|
|
25
|
+
import { AddFieldPopover, FieldListRow } from './ViewColumnPanes';
|
|
26
|
+
import { colFieldName, colLabel, makeColumn, remapIndexAfterMove, remapIndexAfterRemove, usedFieldNames, } from './view-column-io';
|
|
27
|
+
export function FieldsListEditor({ variantKey, schema, columns, allStrings, objectName, objectFieldsOverride, selectedIndex, readOnly, onPatch, onSelectionChange, }) {
|
|
28
|
+
const canEdit = !readOnly;
|
|
29
|
+
const { fields, loading, error } = useObjectFields(objectName || undefined, objectFieldsOverride);
|
|
30
|
+
const fieldTypeByName = React.useMemo(() => {
|
|
31
|
+
const m = new Map();
|
|
32
|
+
for (const f of fields)
|
|
33
|
+
m.set(f.name, f.type);
|
|
34
|
+
return m;
|
|
35
|
+
}, [fields]);
|
|
36
|
+
const [dragIndex, setDragIndex] = React.useState(null);
|
|
37
|
+
const [overIndex, setOverIndex] = React.useState(null);
|
|
38
|
+
const writeColumns = React.useCallback((next) => {
|
|
39
|
+
onPatch({ [variantKey]: { ...schema, columns: next } });
|
|
40
|
+
}, [onPatch, variantKey, schema]);
|
|
41
|
+
const addField = React.useCallback((field) => {
|
|
42
|
+
const col = makeColumn(allStrings, field.name, field.label);
|
|
43
|
+
const next = appendArray(columns, col);
|
|
44
|
+
writeColumns(next);
|
|
45
|
+
onSelectionChange?.({
|
|
46
|
+
kind: 'column',
|
|
47
|
+
id: `${variantKey}.columns[${next.length - 1}]`,
|
|
48
|
+
label: field.label,
|
|
49
|
+
});
|
|
50
|
+
}, [allStrings, columns, writeColumns, variantKey, onSelectionChange]);
|
|
51
|
+
const removeColumn = React.useCallback((index) => {
|
|
52
|
+
const next = spliceArray(columns, index, null);
|
|
53
|
+
writeColumns(next);
|
|
54
|
+
if (selectedIndex != null) {
|
|
55
|
+
const remapped = remapIndexAfterRemove(selectedIndex, index);
|
|
56
|
+
if (remapped == null)
|
|
57
|
+
onSelectionChange?.(null);
|
|
58
|
+
else
|
|
59
|
+
onSelectionChange?.({
|
|
60
|
+
kind: 'column',
|
|
61
|
+
id: `${variantKey}.columns[${remapped}]`,
|
|
62
|
+
label: colLabel(next[remapped], remapped),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}, [columns, writeColumns, selectedIndex, variantKey, onSelectionChange]);
|
|
66
|
+
const moveColumn = React.useCallback((from, to) => {
|
|
67
|
+
if (from === to)
|
|
68
|
+
return;
|
|
69
|
+
const next = moveArray(columns, from, to);
|
|
70
|
+
writeColumns(next);
|
|
71
|
+
if (selectedIndex != null) {
|
|
72
|
+
const remapped = remapIndexAfterMove(selectedIndex, from, to);
|
|
73
|
+
onSelectionChange?.({
|
|
74
|
+
kind: 'column',
|
|
75
|
+
id: `${variantKey}.columns[${remapped}]`,
|
|
76
|
+
label: colLabel(next[remapped], remapped),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}, [columns, writeColumns, selectedIndex, variantKey, onSelectionChange]);
|
|
80
|
+
const selectColumn = React.useCallback((index) => {
|
|
81
|
+
onSelectionChange?.({
|
|
82
|
+
kind: 'column',
|
|
83
|
+
id: `${variantKey}.columns[${index}]`,
|
|
84
|
+
label: colLabel(columns[index], index),
|
|
85
|
+
});
|
|
86
|
+
}, [columns, variantKey, onSelectionChange]);
|
|
87
|
+
const usedNames = usedFieldNames(columns);
|
|
88
|
+
return (_jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { className: "text-xs text-muted-foreground", children: "Columns" }), _jsx(Badge, { variant: "outline", className: "text-[10px]", children: columns.length })] }), columns.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: "No columns yet. Add a field below." })) : (_jsx("div", { className: "space-y-1", children: columns.map((c, i) => (_jsx(FieldListRow, { index: i, label: colLabel(c, i), fieldName: colFieldName(c), fieldType: fieldTypeByName.get(colFieldName(c) ?? '') ?? 'text', selected: selectedIndex === i, canEdit: canEdit, dragging: dragIndex !== null, dropBefore: overIndex === i && dragIndex !== null && dragIndex !== i, onSelect: () => selectColumn(i), onRemove: () => removeColumn(i), onDragStart: () => setDragIndex(i), onDragEnd: () => {
|
|
89
|
+
setDragIndex(null);
|
|
90
|
+
setOverIndex(null);
|
|
91
|
+
}, onDragOverRow: () => setOverIndex(i), onDropRow: () => {
|
|
92
|
+
if (dragIndex != null && dragIndex !== i)
|
|
93
|
+
moveColumn(dragIndex, i);
|
|
94
|
+
setDragIndex(null);
|
|
95
|
+
setOverIndex(null);
|
|
96
|
+
} }, i))) })), canEdit && (_jsx(AddFieldPopover, { fields: fields, usedNames: usedNames, loading: loading, error: error, onAdd: addField }))] }));
|
|
97
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowCanvas — an industry-standard visual flowchart designer for flow
|
|
3
|
+
* automation metadata (mirrors Power Automate / Salesforce Flow Builder).
|
|
4
|
+
*
|
|
5
|
+
* Dependency-free: no reactflow/@xyflow. Nodes are absolutely-positioned
|
|
6
|
+
* Shadcn cards over an SVG edge layer, laid out top-to-bottom by a
|
|
7
|
+
* deterministic layered algorithm (`flow-canvas-layout`). Authors can:
|
|
8
|
+
*
|
|
9
|
+
* - drag to reposition nodes (committed to `node.ui = {x,y}` on drop),
|
|
10
|
+
* - add nodes from a palette (toolbar or a node's bottom "+" handle),
|
|
11
|
+
* - insert a node on an edge ("+" at the edge midpoint splits A→B),
|
|
12
|
+
* - delete the selected node (Delete/Backspace) with full edge cleanup,
|
|
13
|
+
* - pan (background drag) and zoom / fit-to-view.
|
|
14
|
+
*
|
|
15
|
+
* Selection is delegated to the existing FlowNodeInspector via
|
|
16
|
+
* onSelectionChange — the canvas never duplicates the inspector.
|
|
17
|
+
*
|
|
18
|
+
* The component is a pure renderer of `draft`; all mutations go through
|
|
19
|
+
* `onPatch(partial)` and the host merges + persists.
|
|
20
|
+
*/
|
|
21
|
+
import * as React from 'react';
|
|
22
|
+
import { type FlowNode, type FlowEdge } from './flow-canvas-layout';
|
|
23
|
+
export interface FlowCanvasProps {
|
|
24
|
+
nodes: FlowNode[];
|
|
25
|
+
edges: FlowEdge[];
|
|
26
|
+
editable: boolean;
|
|
27
|
+
designMode: boolean;
|
|
28
|
+
selectedId: string | null;
|
|
29
|
+
/** Stable key (see `edgeKey`) of the currently-selected edge, or null. */
|
|
30
|
+
selectedEdgeId?: string | null;
|
|
31
|
+
locale?: string;
|
|
32
|
+
/** Simulation overlay: currently-executing node. */
|
|
33
|
+
activeNodeId?: string | null;
|
|
34
|
+
/** Simulation overlay: nodes already executed. */
|
|
35
|
+
visitedNodeIds?: string[];
|
|
36
|
+
/** Simulation overlay: ids of edges that were traversed. */
|
|
37
|
+
traversedEdgeIds?: string[];
|
|
38
|
+
/** Structural-validation: node ids to paint with a red error ring. */
|
|
39
|
+
invalidNodeIds?: string[];
|
|
40
|
+
/** Structural-validation: edges (keyed `${source}->${target}`) to paint red. */
|
|
41
|
+
invalidEdges?: ReadonlySet<string>;
|
|
42
|
+
/** Structural-validation error messages shown in an inline canvas banner. */
|
|
43
|
+
validationErrors?: string[];
|
|
44
|
+
onSelect: (node: FlowNode | null) => void;
|
|
45
|
+
/** Select an edge (its `edgeKey`), or clear selection with `null`. */
|
|
46
|
+
onSelectEdge?: (edge: FlowEdge | null, key: string) => void;
|
|
47
|
+
onPatch?: (partial: Record<string, unknown>) => void;
|
|
48
|
+
}
|
|
49
|
+
export declare function FlowCanvas({ nodes, edges, editable, designMode, selectedId, selectedEdgeId, locale, activeNodeId, visitedNodeIds, traversedEdgeIds, invalidNodeIds, invalidEdges, validationErrors, onSelect, onSelectEdge, onPatch, }: FlowCanvasProps): React.JSX.Element;
|
|
@@ -0,0 +1,416 @@
|
|
|
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
|
+
* FlowCanvas — an industry-standard visual flowchart designer for flow
|
|
5
|
+
* automation metadata (mirrors Power Automate / Salesforce Flow Builder).
|
|
6
|
+
*
|
|
7
|
+
* Dependency-free: no reactflow/@xyflow. Nodes are absolutely-positioned
|
|
8
|
+
* Shadcn cards over an SVG edge layer, laid out top-to-bottom by a
|
|
9
|
+
* deterministic layered algorithm (`flow-canvas-layout`). Authors can:
|
|
10
|
+
*
|
|
11
|
+
* - drag to reposition nodes (committed to `node.ui = {x,y}` on drop),
|
|
12
|
+
* - add nodes from a palette (toolbar or a node's bottom "+" handle),
|
|
13
|
+
* - insert a node on an edge ("+" at the edge midpoint splits A→B),
|
|
14
|
+
* - delete the selected node (Delete/Backspace) with full edge cleanup,
|
|
15
|
+
* - pan (background drag) and zoom / fit-to-view.
|
|
16
|
+
*
|
|
17
|
+
* Selection is delegated to the existing FlowNodeInspector via
|
|
18
|
+
* onSelectionChange — the canvas never duplicates the inspector.
|
|
19
|
+
*
|
|
20
|
+
* The component is a pure renderer of `draft`; all mutations go through
|
|
21
|
+
* `onPatch(partial)` and the host merges + persists.
|
|
22
|
+
*/
|
|
23
|
+
import * as React from 'react';
|
|
24
|
+
import { AlertTriangle, Maximize2, Plus, ZoomIn, ZoomOut } from 'lucide-react';
|
|
25
|
+
import { cn } from '@object-ui/components';
|
|
26
|
+
import { uniqueId, appendArray, spliceArray } from '../inspectors/_shared';
|
|
27
|
+
import { t as tr } from '../i18n';
|
|
28
|
+
import { computeLayout, diagramSize, bottomAnchor, topAnchor, rightAnchor, edgePath, edgeMidpoint, backEdgePath, backEdgeLabelAnchor, isBackEdge, edgeKey, conditionText, } from './flow-canvas-layout';
|
|
29
|
+
import { NodeCard, NodePalette, defaultNodeLabel, defaultNodeExtras } from './flow-canvas-parts';
|
|
30
|
+
import { useFlowNodePalette } from './useFlowNodePalette';
|
|
31
|
+
const MIN_ZOOM = 0.4;
|
|
32
|
+
const MAX_ZOOM = 1.6;
|
|
33
|
+
const DRAG_THRESHOLD = 4;
|
|
34
|
+
export function FlowCanvas({ nodes, edges, editable, designMode, selectedId, selectedEdgeId, locale, activeNodeId, visitedNodeIds, traversedEdgeIds, invalidNodeIds, invalidEdges, validationErrors, onSelect, onSelectEdge, onPatch, }) {
|
|
35
|
+
const viewportRef = React.useRef(null);
|
|
36
|
+
const [zoom, setZoom] = React.useState(1);
|
|
37
|
+
const [pan, setPan] = React.useState({ x: 0, y: 0 });
|
|
38
|
+
const [paletteOpen, setPaletteOpen] = React.useState(false);
|
|
39
|
+
// Node types offered by the add-node palette, driven by the engine's
|
|
40
|
+
// published descriptors (`GET /api/v1/automation/actions`) merged with the
|
|
41
|
+
// hardcoded base — so the palette reflects what the backend actually supports
|
|
42
|
+
// (e.g. the `approval` node, third-party connector actions).
|
|
43
|
+
const paletteItems = useFlowNodePalette();
|
|
44
|
+
// Transient drag position override (commit-on-drop) so rapid pointer moves
|
|
45
|
+
// never spam onPatch and never diverge from the persisted draft.
|
|
46
|
+
const [dragPos, setDragPos] = React.useState(null);
|
|
47
|
+
const dragRef = React.useRef(null);
|
|
48
|
+
const panRef = React.useRef(null);
|
|
49
|
+
const layout = React.useMemo(() => computeLayout(nodes, edges), [nodes, edges]);
|
|
50
|
+
const size = React.useMemo(() => diagramSize(layout), [layout]);
|
|
51
|
+
// Simulation overlay sets (display-only; never drives engine behavior).
|
|
52
|
+
const visitedSet = React.useMemo(() => new Set(visitedNodeIds ?? []), [visitedNodeIds]);
|
|
53
|
+
const traversedSet = React.useMemo(() => new Set(traversedEdgeIds ?? []), [traversedEdgeIds]);
|
|
54
|
+
const invalidNodeSet = React.useMemo(() => new Set(invalidNodeIds ?? []), [invalidNodeIds]);
|
|
55
|
+
const simRunning = (visitedNodeIds?.length ?? 0) > 0 || !!activeNodeId;
|
|
56
|
+
const positionOf = React.useCallback((id) => {
|
|
57
|
+
if (dragPos && dragPos.id === id)
|
|
58
|
+
return { x: dragPos.x, y: dragPos.y };
|
|
59
|
+
return layout.get(id) ?? { x: 0, y: 0 };
|
|
60
|
+
}, [dragPos, layout]);
|
|
61
|
+
// ── Mutations ────────────────────────────────────────────────────────────
|
|
62
|
+
const persistPosition = React.useCallback((id, x, y) => {
|
|
63
|
+
if (!onPatch)
|
|
64
|
+
return;
|
|
65
|
+
const idx = nodes.findIndex((n) => n.id === id);
|
|
66
|
+
if (idx < 0)
|
|
67
|
+
return;
|
|
68
|
+
const node = nodes[idx];
|
|
69
|
+
const nextNode = { ...node, ui: { ...(node.ui ?? {}), x, y } };
|
|
70
|
+
onPatch({ nodes: spliceArray(nodes, idx, nextNode) });
|
|
71
|
+
}, [nodes, onPatch]);
|
|
72
|
+
const addNode = React.useCallback((type, opts) => {
|
|
73
|
+
if (!onPatch)
|
|
74
|
+
return;
|
|
75
|
+
const existing = nodes.map((n) => n.id).filter(Boolean);
|
|
76
|
+
const id = uniqueId('node', existing);
|
|
77
|
+
const label = type === 'end' ? 'End' : defaultNodeLabel(type);
|
|
78
|
+
// Only an explicit `at` pins a manual position. A `from`-append is left
|
|
79
|
+
// unpinned so the layered auto-layout slots it below its parent and
|
|
80
|
+
// spaces it horizontally among siblings — pinning it directly under the
|
|
81
|
+
// parent (the old behavior) made every sibling stack on the same spot.
|
|
82
|
+
const at = opts?.at;
|
|
83
|
+
const newNode = { id, type, label, ...defaultNodeExtras(type), ...(at ? { ui: { x: at.x, y: at.y } } : {}) };
|
|
84
|
+
const nextNodes = appendArray(nodes, newNode);
|
|
85
|
+
const patch = { nodes: nextNodes };
|
|
86
|
+
if (opts?.from) {
|
|
87
|
+
const newEdge = {
|
|
88
|
+
id: uniqueId('edge', edges.map((e) => e.id).filter(Boolean)),
|
|
89
|
+
source: opts.from,
|
|
90
|
+
target: id,
|
|
91
|
+
};
|
|
92
|
+
// When the source is a decision, carry its matching branch (by order:
|
|
93
|
+
// the k-th out-edge takes the k-th branch) onto the new edge so it
|
|
94
|
+
// actually routes. The decision's config.conditions are otherwise
|
|
95
|
+
// disconnected from the edges, leaving every branch unconditional.
|
|
96
|
+
const fromNode = nodes.find((n) => n.id === opts.from);
|
|
97
|
+
if (fromNode?.type === 'decision') {
|
|
98
|
+
const branches = Array.isArray(fromNode.config?.conditions)
|
|
99
|
+
? fromNode.config.conditions
|
|
100
|
+
: [];
|
|
101
|
+
const outCount = edges.filter((e) => e.source === opts.from).length;
|
|
102
|
+
const branch = branches[outCount];
|
|
103
|
+
if (branch && typeof branch === 'object') {
|
|
104
|
+
const expr = typeof branch.expression === 'string' ? branch.expression.trim() : '';
|
|
105
|
+
const label = typeof branch.label === 'string' ? branch.label.trim() : '';
|
|
106
|
+
if (label)
|
|
107
|
+
newEdge.label = label;
|
|
108
|
+
if (expr === 'true')
|
|
109
|
+
newEdge.isDefault = true;
|
|
110
|
+
else if (expr)
|
|
111
|
+
newEdge.condition = expr;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
patch.edges = appendArray(edges, newEdge);
|
|
115
|
+
}
|
|
116
|
+
onPatch(patch);
|
|
117
|
+
onSelect(newNode);
|
|
118
|
+
setPaletteOpen(false);
|
|
119
|
+
}, [edges, nodes, onPatch, onSelect, positionOf]);
|
|
120
|
+
/** Split edge A→B by inserting a new node N: A→N (keeps guard) + N→B. */
|
|
121
|
+
const insertOnEdge = React.useCallback((edge, type = 'create_record') => {
|
|
122
|
+
if (!onPatch)
|
|
123
|
+
return;
|
|
124
|
+
const edgeIdx = edges.findIndex((e) => e === edge);
|
|
125
|
+
if (edgeIdx < 0)
|
|
126
|
+
return;
|
|
127
|
+
const existing = nodes.map((n) => n.id).filter(Boolean);
|
|
128
|
+
const id = uniqueId('node', existing);
|
|
129
|
+
const from = positionOf(edge.source);
|
|
130
|
+
const to = positionOf(edge.target);
|
|
131
|
+
const at = { x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 };
|
|
132
|
+
const newNode = {
|
|
133
|
+
id,
|
|
134
|
+
type,
|
|
135
|
+
label: defaultNodeLabel(type),
|
|
136
|
+
...defaultNodeExtras(type),
|
|
137
|
+
ui: { x: at.x, y: at.y },
|
|
138
|
+
};
|
|
139
|
+
// A→N inherits the original edge's branch semantics; N→B is plain.
|
|
140
|
+
const firstSegment = { ...edge, target: id };
|
|
141
|
+
const secondSegment = {
|
|
142
|
+
id: uniqueId('edge', [...edges.map((e) => e.id).filter(Boolean), 'edge']),
|
|
143
|
+
source: id,
|
|
144
|
+
target: edge.target,
|
|
145
|
+
};
|
|
146
|
+
const nextEdges = spliceArray(edges, edgeIdx, firstSegment);
|
|
147
|
+
onPatch({ nodes: appendArray(nodes, newNode), edges: appendArray(nextEdges, secondSegment) });
|
|
148
|
+
onSelect(newNode);
|
|
149
|
+
}, [edges, nodes, onPatch, onSelect, positionOf]);
|
|
150
|
+
/**
|
|
151
|
+
* ADR-0044 one-click "add revision loop": drop a signal `wait` node plus the
|
|
152
|
+
* two edges that form a send-back-for-revision loop on an approval node —
|
|
153
|
+
* a `revise` out-edge to the wait point, and a declared `back`-edge closing
|
|
154
|
+
* the loop (resubmit re-enters the approval node as round N+1). Reproduces the
|
|
155
|
+
* canonical `showcase_budget_approval` shape in a single gesture. The wait
|
|
156
|
+
* node is left unpinned so the layered auto-layout slots it among the
|
|
157
|
+
* approval node's other branches.
|
|
158
|
+
*/
|
|
159
|
+
const addReviseLoop = React.useCallback((approvalId) => {
|
|
160
|
+
if (!onPatch)
|
|
161
|
+
return;
|
|
162
|
+
if (!nodes.some((n) => n.id === approvalId))
|
|
163
|
+
return;
|
|
164
|
+
const waitId = uniqueId('node', nodes.map((n) => n.id).filter(Boolean));
|
|
165
|
+
const waitNode = {
|
|
166
|
+
id: waitId,
|
|
167
|
+
type: 'wait',
|
|
168
|
+
label: 'Awaiting Revision',
|
|
169
|
+
// Signal-flavored wait: the submitter's resubmit signal resumes the run.
|
|
170
|
+
waitEventConfig: { eventType: 'signal', signalName: 'revision', onTimeout: 'fail' },
|
|
171
|
+
};
|
|
172
|
+
const existingEdgeIds = edges.map((e) => e.id).filter(Boolean);
|
|
173
|
+
const reviseId = uniqueId('edge', existingEdgeIds);
|
|
174
|
+
const backId = uniqueId('edge', [...existingEdgeIds, reviseId]);
|
|
175
|
+
const reviseEdge = { id: reviseId, source: approvalId, target: waitId, label: 'revise' };
|
|
176
|
+
const backEdge = { id: backId, source: waitId, target: approvalId, label: 'resubmit', type: 'back' };
|
|
177
|
+
onPatch({
|
|
178
|
+
nodes: appendArray(nodes, waitNode),
|
|
179
|
+
edges: appendArray(appendArray(edges, reviseEdge), backEdge),
|
|
180
|
+
});
|
|
181
|
+
onSelect(waitNode);
|
|
182
|
+
}, [edges, nodes, onPatch, onSelect]);
|
|
183
|
+
// Approval nodes that already declare a `revise` out-edge — used to hide the
|
|
184
|
+
// "add revision loop" affordance once a loop exists (avoid duplicates).
|
|
185
|
+
const reviseLoopSources = React.useMemo(() => {
|
|
186
|
+
const s = new Set();
|
|
187
|
+
for (const e of edges) {
|
|
188
|
+
if (typeof e.label === 'string' && e.label.trim().toLowerCase() === 'revise')
|
|
189
|
+
s.add(e.source);
|
|
190
|
+
}
|
|
191
|
+
return s;
|
|
192
|
+
}, [edges]);
|
|
193
|
+
const deleteNode = React.useCallback((id) => {
|
|
194
|
+
if (!onPatch)
|
|
195
|
+
return;
|
|
196
|
+
const nextNodes = nodes.filter((n) => n.id !== id);
|
|
197
|
+
const nextEdges = edges.filter((e) => e.source !== id && e.target !== id);
|
|
198
|
+
onPatch({ nodes: nextNodes, edges: nextEdges });
|
|
199
|
+
onSelect(null);
|
|
200
|
+
}, [edges, nodes, onPatch, onSelect]);
|
|
201
|
+
// ── Drag (reposition) — pointer capture, commit on pointer-up ──────────────
|
|
202
|
+
const onNodePointerDown = React.useCallback((id) => (e) => {
|
|
203
|
+
if (!editable || e.button !== 0)
|
|
204
|
+
return;
|
|
205
|
+
e.stopPropagation();
|
|
206
|
+
const origin = positionOf(id);
|
|
207
|
+
dragRef.current = {
|
|
208
|
+
nodeId: id,
|
|
209
|
+
startX: e.clientX,
|
|
210
|
+
startY: e.clientY,
|
|
211
|
+
originX: origin.x,
|
|
212
|
+
originY: origin.y,
|
|
213
|
+
moved: false,
|
|
214
|
+
};
|
|
215
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
216
|
+
}, [editable, positionOf]);
|
|
217
|
+
const onNodePointerMove = React.useCallback((e) => {
|
|
218
|
+
const d = dragRef.current;
|
|
219
|
+
if (!d)
|
|
220
|
+
return;
|
|
221
|
+
const dx = (e.clientX - d.startX) / zoom;
|
|
222
|
+
const dy = (e.clientY - d.startY) / zoom;
|
|
223
|
+
if (!d.moved && Math.hypot(e.clientX - d.startX, e.clientY - d.startY) < DRAG_THRESHOLD) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
d.moved = true;
|
|
227
|
+
setDragPos({ id: d.nodeId, x: Math.max(0, d.originX + dx), y: Math.max(0, d.originY + dy) });
|
|
228
|
+
}, [zoom]);
|
|
229
|
+
const onNodePointerUp = React.useCallback((e) => {
|
|
230
|
+
const d = dragRef.current;
|
|
231
|
+
dragRef.current = null;
|
|
232
|
+
if (!d)
|
|
233
|
+
return;
|
|
234
|
+
e.currentTarget.releasePointerCapture?.(e.pointerId);
|
|
235
|
+
if (d.moved && dragPos) {
|
|
236
|
+
persistPosition(d.nodeId, Math.round(dragPos.x), Math.round(dragPos.y));
|
|
237
|
+
}
|
|
238
|
+
setDragPos(null);
|
|
239
|
+
}, [dragPos, persistPosition]);
|
|
240
|
+
// ── Pan (background drag) ──────────────────────────────────────────────────
|
|
241
|
+
const onBgPointerDown = React.useCallback((e) => {
|
|
242
|
+
if (e.button !== 0)
|
|
243
|
+
return;
|
|
244
|
+
onSelect(null);
|
|
245
|
+
panRef.current = { startX: e.clientX, startY: e.clientY, originX: pan.x, originY: pan.y };
|
|
246
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
247
|
+
}, [onSelect, pan.x, pan.y]);
|
|
248
|
+
const onBgPointerMove = React.useCallback((e) => {
|
|
249
|
+
const p = panRef.current;
|
|
250
|
+
if (!p)
|
|
251
|
+
return;
|
|
252
|
+
setPan({ x: p.originX + (e.clientX - p.startX), y: p.originY + (e.clientY - p.startY) });
|
|
253
|
+
}, []);
|
|
254
|
+
const onBgPointerUp = React.useCallback((e) => {
|
|
255
|
+
if (panRef.current)
|
|
256
|
+
e.currentTarget.releasePointerCapture?.(e.pointerId);
|
|
257
|
+
panRef.current = null;
|
|
258
|
+
}, []);
|
|
259
|
+
// ── Zoom / fit ─────────────────────────────────────────────────────────────
|
|
260
|
+
const clampZoom = (z) => Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, z));
|
|
261
|
+
const fitToView = React.useCallback(() => {
|
|
262
|
+
const vp = viewportRef.current;
|
|
263
|
+
if (!vp)
|
|
264
|
+
return;
|
|
265
|
+
const pad = 32;
|
|
266
|
+
const zx = (vp.clientWidth - pad) / size.width;
|
|
267
|
+
const zy = (vp.clientHeight - pad) / size.height;
|
|
268
|
+
const z = clampZoom(Math.min(zx, zy, 1));
|
|
269
|
+
setZoom(z);
|
|
270
|
+
setPan({
|
|
271
|
+
x: (vp.clientWidth - size.width * z) / 2,
|
|
272
|
+
y: Math.max(16, (vp.clientHeight - size.height * z) / 2),
|
|
273
|
+
});
|
|
274
|
+
}, [size.height, size.width]);
|
|
275
|
+
// ── Keyboard: delete selected node ─────────────────────────────────────────
|
|
276
|
+
const onKeyDown = React.useCallback((e) => {
|
|
277
|
+
if (!editable || !selectedId)
|
|
278
|
+
return;
|
|
279
|
+
if (e.key === 'Delete' || e.key === 'Backspace') {
|
|
280
|
+
const target = e.target;
|
|
281
|
+
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
e.preventDefault();
|
|
285
|
+
deleteNode(selectedId);
|
|
286
|
+
}
|
|
287
|
+
}, [deleteNode, editable, selectedId]);
|
|
288
|
+
// ── Render ─────────────────────────────────────────────────────────────────
|
|
289
|
+
return (_jsxs("div", { className: "relative h-full min-h-[320px] w-full overflow-hidden", children: [validationErrors && validationErrors.length > 0 && (_jsxs("div", { className: "absolute left-2 top-2 z-30 max-w-[min(60%,420px)] space-y-1", children: [validationErrors.slice(0, 3).map((msg, i) => (_jsxs("div", { role: "alert", className: "flex items-start gap-1.5 rounded-lg border border-destructive/40 bg-destructive/10 px-2.5 py-1.5 text-[11px] leading-snug text-destructive shadow-sm backdrop-blur-sm", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: msg })] }, i))), validationErrors.length > 3 && (_jsxs("div", { className: "px-2.5 text-[10px] text-destructive/80", children: ["+", validationErrors.length - 3, " more\u2026"] }))] })), _jsxs("div", { className: "absolute right-2 top-2 z-30 flex items-center gap-1.5", children: [editable && (_jsxs("div", { className: "relative", children: [_jsxs("button", { type: "button", onClick: () => setPaletteOpen((v) => !v), className: "inline-flex items-center gap-1.5 rounded-lg border bg-background/90 px-2.5 py-1.5 text-xs font-medium shadow-sm backdrop-blur-sm transition-colors hover:border-primary/50 hover:bg-accent hover:text-foreground", children: [_jsx(Plus, { className: "h-3.5 w-3.5" }), tr('engine.inspector.add.node', locale)] }), paletteOpen && (_jsx(NodePalette, { locale: locale, items: paletteItems, onClose: () => setPaletteOpen(false), onPick: (type) => addNode(type, { from: selectedId ?? undefined }) }))] })), _jsxs("div", { className: "flex items-center rounded-lg border bg-background/90 shadow-sm backdrop-blur-sm", children: [_jsx("button", { type: "button", title: "Zoom out", "aria-label": "Zoom out", onClick: () => setZoom((z) => clampZoom(z - 0.15)), className: "inline-flex h-7 w-7 items-center justify-center text-muted-foreground hover:text-foreground", children: _jsx(ZoomOut, { className: "h-3.5 w-3.5" }) }), _jsxs("span", { className: "w-10 text-center text-[11px] tabular-nums text-muted-foreground", children: [Math.round(zoom * 100), "%"] }), _jsx("button", { type: "button", title: "Zoom in", "aria-label": "Zoom in", onClick: () => setZoom((z) => clampZoom(z + 0.15)), className: "inline-flex h-7 w-7 items-center justify-center text-muted-foreground hover:text-foreground", children: _jsx(ZoomIn, { className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", title: "Fit to view", "aria-label": "Fit to view", onClick: fitToView, className: "inline-flex h-7 w-7 items-center justify-center border-l text-muted-foreground hover:text-foreground", children: _jsx(Maximize2, { className: "h-3.5 w-3.5" }) })] })] }), _jsx("div", { ref: viewportRef, tabIndex: 0, role: "application", "aria-label": "Flow canvas", onKeyDown: onKeyDown, onPointerDown: onBgPointerDown, onPointerMove: (e) => {
|
|
290
|
+
onBgPointerMove(e);
|
|
291
|
+
onNodePointerMove(e);
|
|
292
|
+
}, onPointerUp: (e) => {
|
|
293
|
+
onBgPointerUp(e);
|
|
294
|
+
onNodePointerUp(e);
|
|
295
|
+
}, className: cn('h-full w-full cursor-grab outline-none active:cursor-grabbing', 'bg-muted/15 dark:bg-background/30',
|
|
296
|
+
// Subtle inset vignette gives the canvas surface depth.
|
|
297
|
+
'shadow-[inset_0_0_90px_rgba(0,0,0,0.05)]'), style: {
|
|
298
|
+
// Dot grid tied to pan + zoom so the surface tracks the diagram
|
|
299
|
+
// (rather than floating behind a static texture).
|
|
300
|
+
backgroundImage: 'radial-gradient(circle at 1px 1px, hsl(var(--border)) 1px, transparent 0)',
|
|
301
|
+
backgroundSize: `${18 * zoom}px ${18 * zoom}px`,
|
|
302
|
+
backgroundPosition: `${pan.x}px ${pan.y}px`,
|
|
303
|
+
}, children: _jsxs("div", { className: "relative origin-top-left", style: {
|
|
304
|
+
width: size.width,
|
|
305
|
+
height: size.height,
|
|
306
|
+
transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
|
|
307
|
+
}, children: [_jsxs("svg", { className: "pointer-events-none absolute left-0 top-0 overflow-visible", width: size.width, height: size.height, children: [_jsxs("defs", { children: [_jsx("marker", { id: "flow-arrow", viewBox: "0 0 10 10", refX: "8", refY: "5", markerWidth: "7", markerHeight: "7", orient: "auto-start-reverse", children: _jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", className: "fill-muted-foreground/55" }) }), _jsx("marker", { id: "flow-arrow-back", viewBox: "0 0 10 10", refX: "8", refY: "5", markerWidth: "7", markerHeight: "7", orient: "auto-start-reverse", children: _jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", className: "fill-amber-500/80" }) }), _jsx("marker", { id: "flow-arrow-error", viewBox: "0 0 10 10", refX: "8", refY: "5", markerWidth: "7", markerHeight: "7", orient: "auto-start-reverse", children: _jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", className: "fill-destructive" }) })] }), edges.map((edge, i) => {
|
|
308
|
+
const sp = layout.get(edge.source);
|
|
309
|
+
const tp = layout.get(edge.target);
|
|
310
|
+
if (!sp || !tp)
|
|
311
|
+
return null;
|
|
312
|
+
// ADR-0044 back-edges (revise loop) re-enter an earlier node, so
|
|
313
|
+
// they attach to the right side of both endpoints and render as a
|
|
314
|
+
// dashed amber return arc — visually distinct from the forward
|
|
315
|
+
// top-to-bottom flow.
|
|
316
|
+
const back = isBackEdge(edge);
|
|
317
|
+
// Structural-validation error (e.g. part of an un-declared cycle).
|
|
318
|
+
// Back-edges are excluded from cycle detection, so they're never invalid.
|
|
319
|
+
const invalid = !back && !!invalidEdges?.has(`${edge.source}->${edge.target}`);
|
|
320
|
+
const sPos = dragPos?.id === edge.source ? positionOf(edge.source) : sp;
|
|
321
|
+
const tPos = dragPos?.id === edge.target ? positionOf(edge.target) : tp;
|
|
322
|
+
const from = back ? rightAnchor(sPos) : bottomAnchor(sPos);
|
|
323
|
+
const to = back ? rightAnchor(tPos) : topAnchor(tPos);
|
|
324
|
+
const labelPos = back ? backEdgeLabelAnchor(from, to) : edgeMidpoint(from, to);
|
|
325
|
+
const cond = conditionText(edge.condition);
|
|
326
|
+
const branchLabel = edge.isDefault ? 'else' : cond ? `if ${cond}` : edge.label;
|
|
327
|
+
const eid = edgeKey(edge, i);
|
|
328
|
+
const traversed = traversedSet.has(eid);
|
|
329
|
+
const selected = selectedEdgeId === eid;
|
|
330
|
+
const d = back ? backEdgePath(from, to) : edgePath(from, to);
|
|
331
|
+
// Edges are selectable in design mode; the host opens the edge
|
|
332
|
+
// inspector. A wide transparent hit-path widens the click target
|
|
333
|
+
// beyond the 1.5px visible stroke without altering the visuals.
|
|
334
|
+
const selectable = designMode && !!onSelectEdge;
|
|
335
|
+
return (_jsxs("g", { "data-invalid": invalid || undefined, children: [_jsx("path", { d: d, strokeLinecap: "round", strokeDasharray: back ? '5 4' : undefined, className: cn('fill-none transition-[stroke] duration-150', traversed
|
|
336
|
+
? 'stroke-sky-500'
|
|
337
|
+
: selected
|
|
338
|
+
? 'stroke-primary'
|
|
339
|
+
: invalid
|
|
340
|
+
? 'stroke-destructive'
|
|
341
|
+
: back
|
|
342
|
+
? 'stroke-amber-500/70'
|
|
343
|
+
: simRunning
|
|
344
|
+
? 'stroke-muted-foreground/20'
|
|
345
|
+
: 'stroke-muted-foreground/40'), strokeWidth: traversed || selected || invalid ? 2.5 : 1.75, markerEnd: invalid ? 'url(#flow-arrow-error)' : back ? 'url(#flow-arrow-back)' : 'url(#flow-arrow)' }), selectable && (_jsx("path", { d: d, className: "pointer-events-auto cursor-pointer fill-none stroke-transparent", strokeWidth: 14, onPointerDown: (e) => e.stopPropagation(), onClick: (e) => {
|
|
346
|
+
e.stopPropagation();
|
|
347
|
+
onSelectEdge(edge, eid);
|
|
348
|
+
}, children: _jsx("title", { children: invalid ? `${edge.source} → ${edge.target} — part of an un-declared cycle; mark the edge that closes the loop as a back-edge` : back ? `${edge.source} ↩ ${edge.target} (back-edge)` : `${edge.source} → ${edge.target}` }) })), branchLabel && (_jsx("foreignObject", { x: labelPos.x - 60, y: labelPos.y - 11, width: 120, height: 22, className: cn(selectable && 'pointer-events-auto'), children: _jsx("div", { className: "flex justify-center", children: _jsx("span", { onPointerDown: selectable ? (e) => e.stopPropagation() : undefined, onClick: selectable ? (e) => { e.stopPropagation(); onSelectEdge(edge, eid); } : undefined, className: cn('max-w-full truncate rounded-full border bg-background/95 px-2 py-0.5 text-[10px] font-medium shadow-sm backdrop-blur-sm transition-colors', selectable && 'cursor-pointer hover:border-primary/60', selected
|
|
349
|
+
? 'border-primary text-primary'
|
|
350
|
+
: invalid
|
|
351
|
+
? 'border-destructive/60 text-destructive'
|
|
352
|
+
: back
|
|
353
|
+
? 'border-amber-500/50 text-amber-600 dark:text-amber-400'
|
|
354
|
+
: 'border-border text-muted-foreground'), children: branchLabel }) }) })), editable && !back && (_jsx("foreignObject", {
|
|
355
|
+
// Sit the insert handle at the edge midpoint, but slide it
|
|
356
|
+
// to the right of the branch-label pill when one is present
|
|
357
|
+
// so the two don't stack on the same spot.
|
|
358
|
+
x: branchLabel ? labelPos.x + 66 : labelPos.x - 11, y: labelPos.y - 11, width: 22, height: 22, className: "pointer-events-auto", children: _jsx("button", { type: "button", title: "Insert node here", "aria-label": "Insert node here", onPointerDown: (e) => e.stopPropagation(), onClick: (e) => {
|
|
359
|
+
e.stopPropagation();
|
|
360
|
+
insertOnEdge(edge);
|
|
361
|
+
}, className: "inline-flex h-[22px] w-[22px] items-center justify-center rounded-full border bg-background/90 text-muted-foreground opacity-50 shadow-sm backdrop-blur-sm transition-all hover:scale-110 hover:border-primary hover:bg-background hover:text-primary hover:opacity-100 focus-visible:opacity-100", children: _jsx(Plus, { className: "h-3 w-3" }) }) }))] }, edge.id || `${edge.source}-${edge.target}-${i}`));
|
|
362
|
+
})] }), nodes.map((node) => {
|
|
363
|
+
const runState = activeNodeId === node.id ? 'active' : visitedSet.has(node.id) ? 'visited' : undefined;
|
|
364
|
+
return (_jsx(NodeCard, { id: node.id, type: node.type, label: node.label || node.id, summary: nodeSummary(node), position: positionOf(node.id), selected: selectedId === node.id, editable: editable, runState: runState, dimmed: simRunning && !runState, onPointerDown: onNodePointerDown(node.id), onSelect: () => designMode && onSelect(node), onAppend: () => addNode('create_record', { from: node.id }), onAddReviseLoop: editable && node.type === 'approval' && !reviseLoopSources.has(node.id)
|
|
365
|
+
? () => addReviseLoop(node.id)
|
|
366
|
+
: undefined, invalid: invalidNodeSet.has(node.id) }, node.id));
|
|
367
|
+
})] }) })] }));
|
|
368
|
+
}
|
|
369
|
+
/** One-line config summary shown on the node card (best-effort, type-aware). */
|
|
370
|
+
function nodeSummary(node) {
|
|
371
|
+
const c = node.config;
|
|
372
|
+
const str = (v) => (typeof v === 'string' && v ? v : undefined);
|
|
373
|
+
const block = (key, inner) => {
|
|
374
|
+
const b = node[key];
|
|
375
|
+
return b && typeof b === 'object' ? str(b[inner]) : undefined;
|
|
376
|
+
};
|
|
377
|
+
const pick = (k) => (c ? str(c[k]) : undefined);
|
|
378
|
+
if (node.type === 'start') {
|
|
379
|
+
return pick('condition') || pick('criteria') || pick('objectName') || pick('cron') || pick('schedule') || pick('triggerType');
|
|
380
|
+
}
|
|
381
|
+
if (node.type === 'decision') {
|
|
382
|
+
const conds = c?.conditions;
|
|
383
|
+
if (Array.isArray(conds) && conds.length) {
|
|
384
|
+
const labels = conds
|
|
385
|
+
.map((x) => (x && typeof x === 'object' ? str(x.label) : undefined))
|
|
386
|
+
.filter(Boolean);
|
|
387
|
+
return labels.length ? labels.join(' / ') : `${conds.length} branches`;
|
|
388
|
+
}
|
|
389
|
+
return pick('condition');
|
|
390
|
+
}
|
|
391
|
+
if (node.type === 'script') {
|
|
392
|
+
return pick('actionType') || pick('template') || (c && c.script ? 'code' : undefined);
|
|
393
|
+
}
|
|
394
|
+
if (node.type === 'approval') {
|
|
395
|
+
const approvers = c?.approvers;
|
|
396
|
+
const n = Array.isArray(approvers) ? approvers.length : 0;
|
|
397
|
+
const behavior = pick('behavior');
|
|
398
|
+
if (n > 0)
|
|
399
|
+
return `${n} approver${n === 1 ? '' : 's'}${behavior === 'unanimous' ? ' · all' : ''}`;
|
|
400
|
+
return behavior || undefined;
|
|
401
|
+
}
|
|
402
|
+
return (pick('objectName') ||
|
|
403
|
+
block('connectorConfig', 'actionId') ||
|
|
404
|
+
block('waitEventConfig', 'timerDuration') ||
|
|
405
|
+
block('waitEventConfig', 'eventType') ||
|
|
406
|
+
block('boundaryConfig', 'eventType') ||
|
|
407
|
+
pick('condition') ||
|
|
408
|
+
pick('flowName') ||
|
|
409
|
+
pick('url') ||
|
|
410
|
+
pick('collection') ||
|
|
411
|
+
pick('action') ||
|
|
412
|
+
pick('flow') ||
|
|
413
|
+
pick('event') ||
|
|
414
|
+
pick('duration') ||
|
|
415
|
+
undefined);
|
|
416
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowPreview — read-only summary of a Flow metadata draft.
|
|
3
|
+
*
|
|
4
|
+
* A full DAG canvas lives in `@object-ui/plugin-designer` and would
|
|
5
|
+
* pull in ReactFlow + its deps every time the metadata-admin loads,
|
|
6
|
+
* which is too heavy for a glance-preview. Instead we render:
|
|
7
|
+
*
|
|
8
|
+
* 1. A header strip with type / status / runAs / version.
|
|
9
|
+
* 2. A topologically ordered step list inferred from `nodes` +
|
|
10
|
+
* `edges`. Each step shows label, action type, branch markers,
|
|
11
|
+
* and outgoing edge conditions so authors can sanity-check the
|
|
12
|
+
* logic without launching the designer.
|
|
13
|
+
* 3. A variables side panel listing declared flow variables.
|
|
14
|
+
*
|
|
15
|
+
* The renderer is defensive — drafts may be mid-edit with dangling
|
|
16
|
+
* edges or duplicate node ids; we never throw, we just degrade.
|
|
17
|
+
*/
|
|
18
|
+
import * as React from 'react';
|
|
19
|
+
import type { MetadataPreviewProps } from '../preview-registry';
|
|
20
|
+
export declare function FlowPreview({ draft, editing, selection, onSelectionChange, onPatch, locale }: MetadataPreviewProps): React.JSX.Element;
|