@mindlogic-ai/logician-ui 3.1.0 → 3.2.0-alpha.1
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/dist/components/Icon/_constants/iconList.d.ts +1 -1
- package/dist/components/Icon/_constants/iconList.d.ts.map +1 -1
- package/dist/components/Icon/_constants/iconList.js +18 -0
- package/dist/components/Icon/_constants/iconList.js.map +1 -1
- package/dist/components/Icon/_constants/iconList.mjs +20 -2
- package/dist/components/Icon/_constants/iconList.mjs.map +1 -1
- package/dist/components/Icon/index.d.ts +2 -1
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.js +20 -1
- package/dist/components/Icon/index.js.map +1 -1
- package/dist/components/Icon/index.mjs +4 -2
- package/dist/components/Icon/index.mjs.map +1 -1
- package/dist/components/Tree/Tree.d.ts +20 -0
- package/dist/components/Tree/Tree.d.ts.map +1 -0
- package/dist/components/Tree/Tree.js +43 -0
- package/dist/components/Tree/Tree.js.map +1 -0
- package/dist/components/Tree/Tree.mjs +41 -0
- package/dist/components/Tree/Tree.mjs.map +1 -0
- package/dist/components/Tree/Tree.types.d.ts +21 -0
- package/dist/components/Tree/Tree.types.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranch.d.ts +3 -0
- package/dist/components/Tree/TreeBranch.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranch.js +14 -0
- package/dist/components/Tree/TreeBranch.js.map +1 -0
- package/dist/components/Tree/TreeBranch.mjs +12 -0
- package/dist/components/Tree/TreeBranch.mjs.map +1 -0
- package/dist/components/Tree/TreeBranchContent.d.ts +3 -0
- package/dist/components/Tree/TreeBranchContent.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranchContent.js +14 -0
- package/dist/components/Tree/TreeBranchContent.js.map +1 -0
- package/dist/components/Tree/TreeBranchContent.mjs +12 -0
- package/dist/components/Tree/TreeBranchContent.mjs.map +1 -0
- package/dist/components/Tree/TreeBranchControl.d.ts +3 -0
- package/dist/components/Tree/TreeBranchControl.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranchControl.js +19 -0
- package/dist/components/Tree/TreeBranchControl.js.map +1 -0
- package/dist/components/Tree/TreeBranchControl.mjs +17 -0
- package/dist/components/Tree/TreeBranchControl.mjs.map +1 -0
- package/dist/components/Tree/TreeBranchIndentGuide.d.ts +3 -0
- package/dist/components/Tree/TreeBranchIndentGuide.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranchIndentGuide.js +20 -0
- package/dist/components/Tree/TreeBranchIndentGuide.js.map +1 -0
- package/dist/components/Tree/TreeBranchIndentGuide.mjs +18 -0
- package/dist/components/Tree/TreeBranchIndentGuide.mjs.map +1 -0
- package/dist/components/Tree/TreeBranchIndicator.d.ts +3 -0
- package/dist/components/Tree/TreeBranchIndicator.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranchIndicator.js +15 -0
- package/dist/components/Tree/TreeBranchIndicator.js.map +1 -0
- package/dist/components/Tree/TreeBranchIndicator.mjs +13 -0
- package/dist/components/Tree/TreeBranchIndicator.mjs.map +1 -0
- package/dist/components/Tree/TreeBranchText.d.ts +3 -0
- package/dist/components/Tree/TreeBranchText.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranchText.js +14 -0
- package/dist/components/Tree/TreeBranchText.js.map +1 -0
- package/dist/components/Tree/TreeBranchText.mjs +12 -0
- package/dist/components/Tree/TreeBranchText.mjs.map +1 -0
- package/dist/components/Tree/TreeBranchTrigger.d.ts +3 -0
- package/dist/components/Tree/TreeBranchTrigger.d.ts.map +1 -0
- package/dist/components/Tree/TreeBranchTrigger.js +15 -0
- package/dist/components/Tree/TreeBranchTrigger.js.map +1 -0
- package/dist/components/Tree/TreeBranchTrigger.mjs +13 -0
- package/dist/components/Tree/TreeBranchTrigger.mjs.map +1 -0
- package/dist/components/Tree/TreeItem.d.ts +3 -0
- package/dist/components/Tree/TreeItem.d.ts.map +1 -0
- package/dist/components/Tree/TreeItem.js +25 -0
- package/dist/components/Tree/TreeItem.js.map +1 -0
- package/dist/components/Tree/TreeItem.mjs +23 -0
- package/dist/components/Tree/TreeItem.mjs.map +1 -0
- package/dist/components/Tree/TreeItemIndicator.d.ts +3 -0
- package/dist/components/Tree/TreeItemIndicator.d.ts.map +1 -0
- package/dist/components/Tree/TreeItemIndicator.js +14 -0
- package/dist/components/Tree/TreeItemIndicator.js.map +1 -0
- package/dist/components/Tree/TreeItemIndicator.mjs +12 -0
- package/dist/components/Tree/TreeItemIndicator.mjs.map +1 -0
- package/dist/components/Tree/TreeItemText.d.ts +3 -0
- package/dist/components/Tree/TreeItemText.d.ts.map +1 -0
- package/dist/components/Tree/TreeItemText.js +14 -0
- package/dist/components/Tree/TreeItemText.js.map +1 -0
- package/dist/components/Tree/TreeItemText.mjs +12 -0
- package/dist/components/Tree/TreeItemText.mjs.map +1 -0
- package/dist/components/Tree/TreeLabel.d.ts +3 -0
- package/dist/components/Tree/TreeLabel.d.ts.map +1 -0
- package/dist/components/Tree/TreeLabel.js +14 -0
- package/dist/components/Tree/TreeLabel.js.map +1 -0
- package/dist/components/Tree/TreeLabel.mjs +12 -0
- package/dist/components/Tree/TreeLabel.mjs.map +1 -0
- package/dist/components/Tree/TreeNode.d.ts +5 -0
- package/dist/components/Tree/TreeNode.d.ts.map +1 -0
- package/dist/components/Tree/TreeNode.js +9 -0
- package/dist/components/Tree/TreeNode.js.map +1 -0
- package/dist/components/Tree/TreeNode.mjs +7 -0
- package/dist/components/Tree/TreeNode.mjs.map +1 -0
- package/dist/components/Tree/TreeNodeCheckbox.d.ts +3 -0
- package/dist/components/Tree/TreeNodeCheckbox.d.ts.map +1 -0
- package/dist/components/Tree/TreeNodeCheckbox.js +14 -0
- package/dist/components/Tree/TreeNodeCheckbox.js.map +1 -0
- package/dist/components/Tree/TreeNodeCheckbox.mjs +12 -0
- package/dist/components/Tree/TreeNodeCheckbox.mjs.map +1 -0
- package/dist/components/Tree/TreeNodeContext.d.ts +2 -0
- package/dist/components/Tree/TreeNodeContext.d.ts.map +1 -0
- package/dist/components/Tree/TreeNodeContext.js +9 -0
- package/dist/components/Tree/TreeNodeContext.js.map +1 -0
- package/dist/components/Tree/TreeNodeContext.mjs +7 -0
- package/dist/components/Tree/TreeNodeContext.mjs.map +1 -0
- package/dist/components/Tree/TreeNodeProvider.d.ts +5 -0
- package/dist/components/Tree/TreeNodeProvider.d.ts.map +1 -0
- package/dist/components/Tree/TreeNodeProvider.js +9 -0
- package/dist/components/Tree/TreeNodeProvider.js.map +1 -0
- package/dist/components/Tree/TreeNodeProvider.mjs +7 -0
- package/dist/components/Tree/TreeNodeProvider.mjs.map +1 -0
- package/dist/components/Tree/TreeRoot.d.ts +3 -0
- package/dist/components/Tree/TreeRoot.d.ts.map +1 -0
- package/dist/components/Tree/TreeRoot.js +14 -0
- package/dist/components/Tree/TreeRoot.js.map +1 -0
- package/dist/components/Tree/TreeRoot.mjs +12 -0
- package/dist/components/Tree/TreeRoot.mjs.map +1 -0
- package/dist/components/Tree/TreeTree.d.ts +3 -0
- package/dist/components/Tree/TreeTree.d.ts.map +1 -0
- package/dist/components/Tree/TreeTree.js +14 -0
- package/dist/components/Tree/TreeTree.js.map +1 -0
- package/dist/components/Tree/TreeTree.mjs +12 -0
- package/dist/components/Tree/TreeTree.mjs.map +1 -0
- package/dist/components/Tree/index.d.ts +23 -0
- package/dist/components/Tree/index.d.ts.map +1 -0
- package/dist/components/Workflow/Workflow.d.ts +3 -0
- package/dist/components/Workflow/Workflow.d.ts.map +1 -0
- package/dist/components/Workflow/Workflow.js +109 -0
- package/dist/components/Workflow/Workflow.js.map +1 -0
- package/dist/components/Workflow/Workflow.mjs +107 -0
- package/dist/components/Workflow/Workflow.mjs.map +1 -0
- package/dist/components/Workflow/Workflow.translations.json.js +164 -0
- package/dist/components/Workflow/Workflow.translations.json.js.map +1 -0
- package/dist/components/Workflow/Workflow.translations.json.mjs +138 -0
- package/dist/components/Workflow/Workflow.translations.json.mjs.map +1 -0
- package/dist/components/Workflow/Workflow.types.d.ts +435 -0
- package/dist/components/Workflow/Workflow.types.d.ts.map +1 -0
- package/dist/components/Workflow/Workflow.types.js +19 -0
- package/dist/components/Workflow/Workflow.types.js.map +1 -0
- package/dist/components/Workflow/Workflow.types.mjs +16 -0
- package/dist/components/Workflow/Workflow.types.mjs.map +1 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.d.ts +10 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.d.ts.map +1 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.js +163 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.js.map +1 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.mjs +159 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.mjs.map +1 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.types.d.ts +117 -0
- package/dist/components/Workflow/WorkflowContext/WorkflowContext.types.d.ts.map +1 -0
- package/dist/components/Workflow/WorkflowContext/index.d.ts +3 -0
- package/dist/components/Workflow/WorkflowContext/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.d.ts +19 -0
- package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.js +44 -0
- package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.js.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.mjs +42 -0
- package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.mjs.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.d.ts +10 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.js +531 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.js.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.mjs +529 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.mjs.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.styles.d.ts +53 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.styles.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.styles.js +96 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.styles.js.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.styles.mjs +93 -0
- package/dist/components/Workflow/canvas/Canvas/Canvas.styles.mjs.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/CanvasControls.d.ts +27 -0
- package/dist/components/Workflow/canvas/Canvas/CanvasControls.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/CanvasControls.js +70 -0
- package/dist/components/Workflow/canvas/Canvas/CanvasControls.js.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/CanvasControls.mjs +68 -0
- package/dist/components/Workflow/canvas/Canvas/CanvasControls.mjs.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/LabeledEdge.d.ts +10 -0
- package/dist/components/Workflow/canvas/Canvas/LabeledEdge.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/LabeledEdge.js +106 -0
- package/dist/components/Workflow/canvas/Canvas/LabeledEdge.js.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/LabeledEdge.mjs +104 -0
- package/dist/components/Workflow/canvas/Canvas/LabeledEdge.mjs.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.d.ts +13 -0
- package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.js +18 -0
- package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.js.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.mjs +16 -0
- package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.mjs.map +1 -0
- package/dist/components/Workflow/canvas/Canvas/index.d.ts +2 -0
- package/dist/components/Workflow/canvas/Canvas/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.d.ts +30 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.js +34 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.js.map +1 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.mjs +32 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.mjs.map +1 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/index.d.ts +2 -0
- package/dist/components/Workflow/canvas/CollapsibleSection/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.d.ts +37 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.js +33 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.js.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.mjs +31 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.mjs.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.d.ts +16 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.js +54 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.js.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.mjs +52 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.mjs.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.d.ts +27 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.js +178 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.js.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.mjs +176 -0
- package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.mjs.map +1 -0
- package/dist/components/Workflow/canvas/DrawerShell/index.d.ts +3 -0
- package/dist/components/Workflow/canvas/DrawerShell/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.d.ts +12 -0
- package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.js +68 -0
- package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.js.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.mjs +66 -0
- package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.mjs.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.d.ts +19 -0
- package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.js +35 -0
- package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.js.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.mjs +32 -0
- package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.mjs.map +1 -0
- package/dist/components/Workflow/canvas/EdgeInspector/index.d.ts +3 -0
- package/dist/components/Workflow/canvas/EdgeInspector/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.d.ts +54 -0
- package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.js +56 -0
- package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.js.map +1 -0
- package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.mjs +54 -0
- package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.mjs.map +1 -0
- package/dist/components/Workflow/canvas/FieldWrapper/index.d.ts +3 -0
- package/dist/components/Workflow/canvas/FieldWrapper/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.d.ts +16 -0
- package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.js +25 -0
- package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.js.map +1 -0
- package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.mjs +22 -0
- package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.mjs.map +1 -0
- package/dist/components/Workflow/canvas/FloatingCard/index.d.ts +2 -0
- package/dist/components/Workflow/canvas/FloatingCard/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.d.ts +14 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.js +61 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.js.map +1 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.mjs +59 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.mjs.map +1 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.types.d.ts +11 -0
- package/dist/components/Workflow/canvas/GenericNode/GenericNode.types.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/GenericNode/index.d.ts +3 -0
- package/dist/components/Workflow/canvas/GenericNode/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.d.ts +15 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.js +145 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.js.map +1 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.mjs +143 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.mjs.map +1 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/index.d.ts +2 -0
- package/dist/components/Workflow/canvas/GraphErrorBanner/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.d.ts +10 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.js +21 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.js.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.mjs +19 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.mjs.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.styles.d.ts +18 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.styles.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.styles.js +40 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.styles.js.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.styles.mjs +37 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.styles.mjs.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.types.d.ts +15 -0
- package/dist/components/Workflow/canvas/IconTile/IconTile.types.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/IconTile/index.d.ts +4 -0
- package/dist/components/Workflow/canvas/IconTile/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/IssueList/IssueList.d.ts +24 -0
- package/dist/components/Workflow/canvas/IssueList/IssueList.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/IssueList/IssueList.js +34 -0
- package/dist/components/Workflow/canvas/IssueList/IssueList.js.map +1 -0
- package/dist/components/Workflow/canvas/IssueList/IssueList.mjs +32 -0
- package/dist/components/Workflow/canvas/IssueList/IssueList.mjs.map +1 -0
- package/dist/components/Workflow/canvas/IssueList/index.d.ts +2 -0
- package/dist/components/Workflow/canvas/IssueList/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.d.ts +9 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.js +94 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.js.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.mjs +92 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.mjs.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.d.ts +7 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.js +13 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.js.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.mjs +10 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.mjs.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.d.ts +10 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.js +28 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.js.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.mjs +26 -0
- package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.mjs.map +1 -0
- package/dist/components/Workflow/canvas/NodePalette/index.d.ts +4 -0
- package/dist/components/Workflow/canvas/NodePalette/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.d.ts +3 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.js +137 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.js.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.mjs +135 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.mjs.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.d.ts +66 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.js +87 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.js.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.mjs +77 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.mjs.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.types.d.ts +35 -0
- package/dist/components/Workflow/canvas/NodeShell/NodeShell.types.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/NodeShell/index.d.ts +4 -0
- package/dist/components/Workflow/canvas/NodeShell/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.d.ts +15 -0
- package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.js +14 -0
- package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.js.map +1 -0
- package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.mjs +12 -0
- package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.mjs.map +1 -0
- package/dist/components/Workflow/canvas/SeverityDot/index.d.ts +2 -0
- package/dist/components/Workflow/canvas/SeverityDot/index.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/issueSeverity.d.ts +23 -0
- package/dist/components/Workflow/canvas/issueSeverity.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/issueSeverity.js +51 -0
- package/dist/components/Workflow/canvas/issueSeverity.js.map +1 -0
- package/dist/components/Workflow/canvas/issueSeverity.mjs +47 -0
- package/dist/components/Workflow/canvas/issueSeverity.mjs.map +1 -0
- package/dist/components/Workflow/canvas/useFieldFocusRequest.d.ts +14 -0
- package/dist/components/Workflow/canvas/useFieldFocusRequest.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/useFieldFocusRequest.js +48 -0
- package/dist/components/Workflow/canvas/useFieldFocusRequest.js.map +1 -0
- package/dist/components/Workflow/canvas/useFieldFocusRequest.mjs +46 -0
- package/dist/components/Workflow/canvas/useFieldFocusRequest.mjs.map +1 -0
- package/dist/components/Workflow/canvas/workflowLabelProps.d.ts +12 -0
- package/dist/components/Workflow/canvas/workflowLabelProps.d.ts.map +1 -0
- package/dist/components/Workflow/canvas/workflowLabelProps.js +17 -0
- package/dist/components/Workflow/canvas/workflowLabelProps.js.map +1 -0
- package/dist/components/Workflow/canvas/workflowLabelProps.mjs +15 -0
- package/dist/components/Workflow/canvas/workflowLabelProps.mjs.map +1 -0
- package/dist/components/Workflow/connectionRules.d.ts +59 -0
- package/dist/components/Workflow/connectionRules.d.ts.map +1 -0
- package/dist/components/Workflow/connectionRules.js +150 -0
- package/dist/components/Workflow/connectionRules.js.map +1 -0
- package/dist/components/Workflow/connectionRules.mjs +145 -0
- package/dist/components/Workflow/connectionRules.mjs.map +1 -0
- package/dist/components/Workflow/createNode.d.ts +27 -0
- package/dist/components/Workflow/createNode.d.ts.map +1 -0
- package/dist/components/Workflow/createNode.js +66 -0
- package/dist/components/Workflow/createNode.js.map +1 -0
- package/dist/components/Workflow/createNode.mjs +62 -0
- package/dist/components/Workflow/createNode.mjs.map +1 -0
- package/dist/components/Workflow/graphHistory.d.ts +23 -0
- package/dist/components/Workflow/graphHistory.d.ts.map +1 -0
- package/dist/components/Workflow/graphHistory.js +73 -0
- package/dist/components/Workflow/graphHistory.js.map +1 -0
- package/dist/components/Workflow/graphHistory.mjs +70 -0
- package/dist/components/Workflow/graphHistory.mjs.map +1 -0
- package/dist/components/Workflow/graphObserver.d.ts +13 -0
- package/dist/components/Workflow/graphObserver.d.ts.map +1 -0
- package/dist/components/Workflow/graphObserver.js +11 -0
- package/dist/components/Workflow/graphObserver.js.map +1 -0
- package/dist/components/Workflow/graphObserver.mjs +8 -0
- package/dist/components/Workflow/graphObserver.mjs.map +1 -0
- package/dist/components/Workflow/graphReducer.d.ts +75 -0
- package/dist/components/Workflow/graphReducer.d.ts.map +1 -0
- package/dist/components/Workflow/graphReducer.js +122 -0
- package/dist/components/Workflow/graphReducer.js.map +1 -0
- package/dist/components/Workflow/graphReducer.mjs +119 -0
- package/dist/components/Workflow/graphReducer.mjs.map +1 -0
- package/dist/components/Workflow/index.d.ts +22 -0
- package/dist/components/Workflow/index.d.ts.map +1 -0
- package/dist/components/Workflow/layout/autoLayout.d.ts +49 -0
- package/dist/components/Workflow/layout/autoLayout.d.ts.map +1 -0
- package/dist/components/Workflow/layout/autoLayout.js +149 -0
- package/dist/components/Workflow/layout/autoLayout.js.map +1 -0
- package/dist/components/Workflow/layout/autoLayout.mjs +146 -0
- package/dist/components/Workflow/layout/autoLayout.mjs.map +1 -0
- package/dist/components/Workflow/stories/toyNodeTypes.d.ts +40 -0
- package/dist/components/Workflow/stories/toyNodeTypes.d.ts.map +1 -0
- package/dist/components/Workflow/useWorkflowIssueMessage.d.ts +15 -0
- package/dist/components/Workflow/useWorkflowIssueMessage.d.ts.map +1 -0
- package/dist/components/Workflow/useWorkflowIssueMessage.js +45 -0
- package/dist/components/Workflow/useWorkflowIssueMessage.js.map +1 -0
- package/dist/components/Workflow/useWorkflowIssueMessage.mjs +43 -0
- package/dist/components/Workflow/useWorkflowIssueMessage.mjs.map +1 -0
- package/dist/components/Workflow/useWorkflowKeyboard.d.ts +10 -0
- package/dist/components/Workflow/useWorkflowKeyboard.d.ts.map +1 -0
- package/dist/components/Workflow/useWorkflowKeyboard.js +116 -0
- package/dist/components/Workflow/useWorkflowKeyboard.js.map +1 -0
- package/dist/components/Workflow/useWorkflowKeyboard.mjs +114 -0
- package/dist/components/Workflow/useWorkflowKeyboard.mjs.map +1 -0
- package/dist/icons.js +17 -0
- package/dist/icons.js.map +1 -1
- package/dist/icons.mjs +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -1
- package/dist/index.mjs.map +1 -1
- package/dist/test-support/setup.d.ts +5 -0
- package/dist/test-support/setup.d.ts.map +1 -0
- package/package.json +10 -2
- package/src/components/Icon/_constants/iconList.ts +35 -0
- package/src/components/Icon/index.tsx +20 -0
- package/src/components/Tree/Tree.stories.tsx +564 -0
- package/src/components/Tree/Tree.tsx +37 -0
- package/src/components/Tree/Tree.types.ts +51 -0
- package/src/components/Tree/TreeBranch.tsx +11 -0
- package/src/components/Tree/TreeBranchContent.tsx +21 -0
- package/src/components/Tree/TreeBranchControl.tsx +28 -0
- package/src/components/Tree/TreeBranchIndentGuide.tsx +20 -0
- package/src/components/Tree/TreeBranchIndicator.tsx +27 -0
- package/src/components/Tree/TreeBranchText.tsx +19 -0
- package/src/components/Tree/TreeBranchTrigger.tsx +25 -0
- package/src/components/Tree/TreeItem.tsx +33 -0
- package/src/components/Tree/TreeItemIndicator.tsx +20 -0
- package/src/components/Tree/TreeItemText.tsx +19 -0
- package/src/components/Tree/TreeLabel.tsx +19 -0
- package/src/components/Tree/TreeNode.tsx +6 -0
- package/src/components/Tree/TreeNodeCheckbox.tsx +12 -0
- package/src/components/Tree/TreeNodeContext.tsx +3 -0
- package/src/components/Tree/TreeNodeProvider.tsx +6 -0
- package/src/components/Tree/TreeRoot.tsx +11 -0
- package/src/components/Tree/TreeTree.tsx +11 -0
- package/src/components/Tree/index.ts +42 -0
- package/src/components/Workflow/README.md +362 -0
- package/src/components/Workflow/Workflow.translations.json +112 -0
- package/src/components/Workflow/Workflow.tsx +189 -0
- package/src/components/Workflow/Workflow.types.ts +496 -0
- package/src/components/Workflow/WorkflowContext/WorkflowContext.tsx +215 -0
- package/src/components/Workflow/WorkflowContext/WorkflowContext.types.ts +122 -0
- package/src/components/Workflow/WorkflowContext/index.ts +10 -0
- package/src/components/Workflow/WorkflowContext/workflowSelection.test.tsx +93 -0
- package/src/components/Workflow/canvas/Canvas/BranchLabelBadge.tsx +69 -0
- package/src/components/Workflow/canvas/Canvas/Canvas.styles.ts +91 -0
- package/src/components/Workflow/canvas/Canvas/Canvas.tsx +773 -0
- package/src/components/Workflow/canvas/Canvas/CanvasControls.tsx +178 -0
- package/src/components/Workflow/canvas/Canvas/LabeledEdge.tsx +198 -0
- package/src/components/Workflow/canvas/Canvas/edgeLabelVariant.test.ts +26 -0
- package/src/components/Workflow/canvas/Canvas/edgeLabelVariant.ts +23 -0
- package/src/components/Workflow/canvas/Canvas/index.ts +1 -0
- package/src/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.tsx +96 -0
- package/src/components/Workflow/canvas/CollapsibleSection/index.ts +4 -0
- package/src/components/Workflow/canvas/DrawerShell/DrawerHeader.tsx +104 -0
- package/src/components/Workflow/canvas/DrawerShell/DrawerIssues.tsx +115 -0
- package/src/components/Workflow/canvas/DrawerShell/DrawerShell.tsx +408 -0
- package/src/components/Workflow/canvas/DrawerShell/index.ts +2 -0
- package/src/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.tsx +135 -0
- package/src/components/Workflow/canvas/EdgeInspector/endpointTitle.ts +38 -0
- package/src/components/Workflow/canvas/EdgeInspector/index.ts +2 -0
- package/src/components/Workflow/canvas/FieldWrapper/FieldWrapper.tsx +118 -0
- package/src/components/Workflow/canvas/FieldWrapper/index.ts +6 -0
- package/src/components/Workflow/canvas/FloatingCard/FloatingCard.tsx +37 -0
- package/src/components/Workflow/canvas/FloatingCard/index.ts +1 -0
- package/src/components/Workflow/canvas/GenericNode/GenericNode.tsx +114 -0
- package/src/components/Workflow/canvas/GenericNode/GenericNode.types.ts +10 -0
- package/src/components/Workflow/canvas/GenericNode/index.ts +5 -0
- package/src/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.tsx +284 -0
- package/src/components/Workflow/canvas/GraphErrorBanner/index.ts +1 -0
- package/src/components/Workflow/canvas/IconTile/IconTile.styles.ts +40 -0
- package/src/components/Workflow/canvas/IconTile/IconTile.tsx +36 -0
- package/src/components/Workflow/canvas/IconTile/IconTile.types.ts +13 -0
- package/src/components/Workflow/canvas/IconTile/index.ts +7 -0
- package/src/components/Workflow/canvas/IssueList/IssueList.tsx +84 -0
- package/src/components/Workflow/canvas/IssueList/index.ts +1 -0
- package/src/components/Workflow/canvas/NodePalette/NodePalette.styles.ts +7 -0
- package/src/components/Workflow/canvas/NodePalette/NodePalette.tsx +180 -0
- package/src/components/Workflow/canvas/NodePalette/NodePaletteToggle.tsx +39 -0
- package/src/components/Workflow/canvas/NodePalette/index.ts +3 -0
- package/src/components/Workflow/canvas/NodeShell/NodeShell.styles.ts +84 -0
- package/src/components/Workflow/canvas/NodeShell/NodeShell.tsx +321 -0
- package/src/components/Workflow/canvas/NodeShell/NodeShell.types.ts +45 -0
- package/src/components/Workflow/canvas/NodeShell/index.ts +8 -0
- package/src/components/Workflow/canvas/SeverityDot/SeverityDot.tsx +33 -0
- package/src/components/Workflow/canvas/SeverityDot/index.ts +1 -0
- package/src/components/Workflow/canvas/issueSeverity.ts +48 -0
- package/src/components/Workflow/canvas/useFieldFocusRequest.ts +54 -0
- package/src/components/Workflow/canvas/workflowLabelProps.ts +11 -0
- package/src/components/Workflow/connectionRules.test.ts +326 -0
- package/src/components/Workflow/connectionRules.ts +190 -0
- package/src/components/Workflow/createNode.test.ts +61 -0
- package/src/components/Workflow/createNode.ts +67 -0
- package/src/components/Workflow/graphHistory.test.ts +178 -0
- package/src/components/Workflow/graphHistory.ts +91 -0
- package/src/components/Workflow/graphObserver.ts +21 -0
- package/src/components/Workflow/graphReducer.test.ts +314 -0
- package/src/components/Workflow/graphReducer.ts +196 -0
- package/src/components/Workflow/index.ts +74 -0
- package/src/components/Workflow/layout/autoLayout.test.ts +170 -0
- package/src/components/Workflow/layout/autoLayout.ts +200 -0
- package/src/components/Workflow/stories/Workflow.stories.tsx +111 -0
- package/src/components/Workflow/stories/toyNodeTypes.tsx +146 -0
- package/src/components/Workflow/useWorkflowIssueMessage.test.ts +101 -0
- package/src/components/Workflow/useWorkflowIssueMessage.ts +49 -0
- package/src/components/Workflow/useWorkflowKeyboard.ts +126 -0
- package/src/index.ts +2 -0
- package/src/test-support/setup.ts +11 -0
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DragEvent,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
useCallback,
|
|
7
|
+
useEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
useState,
|
|
10
|
+
} from 'react';
|
|
11
|
+
import { Box } from '@chakra-ui/react';
|
|
12
|
+
import type { OnConnectEnd, OnConnectStart, OnReconnect } from '@xyflow/react';
|
|
13
|
+
import {
|
|
14
|
+
applyEdgeChanges,
|
|
15
|
+
applyNodeChanges,
|
|
16
|
+
Background,
|
|
17
|
+
Connection,
|
|
18
|
+
ConnectionLineType,
|
|
19
|
+
Edge,
|
|
20
|
+
EdgeChange,
|
|
21
|
+
IsValidConnection,
|
|
22
|
+
MiniMap,
|
|
23
|
+
NodeChange,
|
|
24
|
+
NodeTypes,
|
|
25
|
+
ReactFlow,
|
|
26
|
+
ReactFlowProvider,
|
|
27
|
+
useReactFlow,
|
|
28
|
+
} from '@xyflow/react';
|
|
29
|
+
|
|
30
|
+
import '@xyflow/react/dist/style.css';
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
existingEdgeFromHandle,
|
|
34
|
+
isValidConnection as isValidWorkflowConnection,
|
|
35
|
+
soleEdgeToHandle,
|
|
36
|
+
} from '../../connectionRules';
|
|
37
|
+
import { genId } from '../../createNode';
|
|
38
|
+
import {
|
|
39
|
+
autoLayout,
|
|
40
|
+
estimateLabelOverhang,
|
|
41
|
+
type NodeDimensions,
|
|
42
|
+
} from '../../layout/autoLayout';
|
|
43
|
+
import { useWorkflowKeyboard } from '../../useWorkflowKeyboard';
|
|
44
|
+
import type {
|
|
45
|
+
Graph,
|
|
46
|
+
GraphEdge,
|
|
47
|
+
GraphNode,
|
|
48
|
+
Position,
|
|
49
|
+
} from '../../Workflow.types';
|
|
50
|
+
import { resolveDefaultConfig } from '../../Workflow.types';
|
|
51
|
+
import { useWorkflow, useWorkflowTranslate } from '../../WorkflowContext';
|
|
52
|
+
import type { WorkflowReactFlowNode } from '../GenericNode';
|
|
53
|
+
import { GenericNode } from '../GenericNode';
|
|
54
|
+
import { GraphErrorBanner } from '../GraphErrorBanner';
|
|
55
|
+
import { DRAG_MIME, NodePalette, NodePaletteToggle } from '../NodePalette';
|
|
56
|
+
import { canvasSelectionCss, defaultEdgeOptions } from './Canvas.styles';
|
|
57
|
+
import { CanvasControls } from './CanvasControls';
|
|
58
|
+
import { LabeledEdge } from './LabeledEdge';
|
|
59
|
+
|
|
60
|
+
// React Flow's `nodeTypes` prop — distinct from our domain "node type registry".
|
|
61
|
+
// We use a unique key here ('workflow') rather than 'default' to avoid React
|
|
62
|
+
// Flow's built-in default-node CSS (.react-flow__node-default: padding +
|
|
63
|
+
// border + 150px width) rendering as a black box behind our NodeShell.
|
|
64
|
+
const rfNodeTypes: NodeTypes = { workflow: GenericNode };
|
|
65
|
+
|
|
66
|
+
// React Flow edge type registry — `labeled` swaps the SVG `labelStyle`
|
|
67
|
+
// path for a Chakra `Subtext` so the label inherits semantic typography.
|
|
68
|
+
const rfEdgeTypes = { labeled: LabeledEdge };
|
|
69
|
+
|
|
70
|
+
// Cap zoom so a tiny graph doesn't balloon, and pad so nodes don't touch the
|
|
71
|
+
// edges. Shared between the initial `fitView` prop, the read-only re-fit, and
|
|
72
|
+
// the post-auto-arrange re-fit so every framing settles the same way.
|
|
73
|
+
const FIT_VIEW_OPTIONS = { maxZoom: 1.2, padding: 0.15 };
|
|
74
|
+
|
|
75
|
+
// User-triggered re-fits (the fit-view button, the post-arrange reframe) glide
|
|
76
|
+
// instead of teleporting, matching the error-banner jump's duration. The
|
|
77
|
+
// initial mount and the read-only layout-settling re-fits stay instant — there
|
|
78
|
+
// the viewport has no meaningful prior position to animate from.
|
|
79
|
+
const ANIMATED_FIT_VIEW_OPTIONS = { ...FIT_VIEW_OPTIONS, duration: 400 };
|
|
80
|
+
|
|
81
|
+
function graphToReactFlow(
|
|
82
|
+
graph: Graph,
|
|
83
|
+
isPinned: (kind: string) => boolean,
|
|
84
|
+
readOnly: boolean,
|
|
85
|
+
selection: { nodeId: string | null; edgeId: string | null }
|
|
86
|
+
): { nodes: WorkflowReactFlowNode[]; edges: Edge[] } {
|
|
87
|
+
return {
|
|
88
|
+
nodes: graph.nodes.map<WorkflowReactFlowNode>((n) => ({
|
|
89
|
+
id: n.id,
|
|
90
|
+
type: 'workflow',
|
|
91
|
+
position: n.position,
|
|
92
|
+
data: { nodeId: n.id },
|
|
93
|
+
selected: n.id === selection.nodeId,
|
|
94
|
+
deletable: !readOnly && !isPinned(n.kind),
|
|
95
|
+
})),
|
|
96
|
+
edges: graph.edges.map((e) => ({
|
|
97
|
+
id: e.id,
|
|
98
|
+
source: e.source,
|
|
99
|
+
target: e.target,
|
|
100
|
+
sourceHandle: e.sourceHandle,
|
|
101
|
+
targetHandle: e.targetHandle,
|
|
102
|
+
label: e.label,
|
|
103
|
+
animated: false,
|
|
104
|
+
selected: e.id === selection.edgeId,
|
|
105
|
+
deletable: !readOnly,
|
|
106
|
+
})),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function CanvasInner({
|
|
111
|
+
showPalette,
|
|
112
|
+
onNodeClick: onNodeClickHost,
|
|
113
|
+
onEdgeClick: onEdgeClickHost,
|
|
114
|
+
children,
|
|
115
|
+
}: {
|
|
116
|
+
showPalette: boolean;
|
|
117
|
+
onNodeClick?: (node: GraphNode) => void;
|
|
118
|
+
onEdgeClick?: (edge: GraphEdge) => void;
|
|
119
|
+
children?: ReactNode;
|
|
120
|
+
}) {
|
|
121
|
+
const {
|
|
122
|
+
graph,
|
|
123
|
+
dispatch,
|
|
124
|
+
editor: { selectedNodeId, selectedEdgeId, runStates, drawerTarget },
|
|
125
|
+
setSelectedNodeId,
|
|
126
|
+
setSelectedEdgeId,
|
|
127
|
+
setDrawerTarget,
|
|
128
|
+
revealInspector,
|
|
129
|
+
getNodeType,
|
|
130
|
+
onArrange,
|
|
131
|
+
readOnly,
|
|
132
|
+
issues,
|
|
133
|
+
hostBridge,
|
|
134
|
+
} = useWorkflow();
|
|
135
|
+
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
|
136
|
+
// When a drag starts from an already-connected entry (input) handle, we grab
|
|
137
|
+
// that edge and re-route its source instead of laying down a duplicate. The
|
|
138
|
+
// ref carries the grabbed edge id from `onConnectStart` to `onConnect`.
|
|
139
|
+
const grabbedEntryEdgeRef = useRef<string | null>(null);
|
|
140
|
+
const { screenToFlowPosition, getNodes, fitView } = useReactFlow();
|
|
141
|
+
|
|
142
|
+
// The palette is open by default; the floating `+` toggle (top-left) reopens
|
|
143
|
+
// it after the author collapses it via its header.
|
|
144
|
+
const [isPaletteOpen, setIsPaletteOpen] = useState(true);
|
|
145
|
+
|
|
146
|
+
const translate = useWorkflowTranslate();
|
|
147
|
+
// Tear off only the string lookup so `localizeDefaults` doesn't depend
|
|
148
|
+
// on the React-fragment interpolation path.
|
|
149
|
+
const t = useCallback(
|
|
150
|
+
(key: string, params?: Record<string, string>) =>
|
|
151
|
+
translate(key, params) as string,
|
|
152
|
+
[translate]
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
useWorkflowKeyboard();
|
|
156
|
+
|
|
157
|
+
const isPinned = useCallback(
|
|
158
|
+
(kind: string) => Boolean(getNodeType(kind)?.placement?.pinned),
|
|
159
|
+
[getNodeType]
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Local mirror of nodes/edges so React Flow can hold transient state —
|
|
163
|
+
// drag positions and selection — without our graph -> elements derivation
|
|
164
|
+
// snapping them back. We reseed when the graph reference changes.
|
|
165
|
+
const [displayNodes, setDisplayNodes] = useState<WorkflowReactFlowNode[]>(
|
|
166
|
+
() =>
|
|
167
|
+
graphToReactFlow(graph, isPinned, readOnly, {
|
|
168
|
+
nodeId: selectedNodeId,
|
|
169
|
+
edgeId: selectedEdgeId,
|
|
170
|
+
}).nodes
|
|
171
|
+
);
|
|
172
|
+
const [displayEdges, setDisplayEdges] = useState<Edge[]>(
|
|
173
|
+
() =>
|
|
174
|
+
graphToReactFlow(graph, isPinned, readOnly, {
|
|
175
|
+
nodeId: selectedNodeId,
|
|
176
|
+
edgeId: selectedEdgeId,
|
|
177
|
+
}).edges
|
|
178
|
+
);
|
|
179
|
+
const lastSyncedGraphRef = useRef(graph);
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (graph === lastSyncedGraphRef.current) return;
|
|
182
|
+
lastSyncedGraphRef.current = graph;
|
|
183
|
+
const next = graphToReactFlow(graph, isPinned, readOnly, {
|
|
184
|
+
nodeId: selectedNodeId,
|
|
185
|
+
edgeId: selectedEdgeId,
|
|
186
|
+
});
|
|
187
|
+
setDisplayNodes(next.nodes);
|
|
188
|
+
setDisplayEdges(next.edges);
|
|
189
|
+
}, [graph, isPinned, readOnly, selectedNodeId, selectedEdgeId]);
|
|
190
|
+
|
|
191
|
+
// Mirror context selection (driven by node/edge clicks AND the edges sidebar)
|
|
192
|
+
// into React Flow's display state so a selection made outside the canvas —
|
|
193
|
+
// e.g. clicking an edge in the sidebar — highlights on the canvas too. Each
|
|
194
|
+
// updater is a no-op (returns `prev`) when nothing needs to change, so this
|
|
195
|
+
// can't loop with the `select` changes that flow back through onNodesChange.
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
setDisplayNodes((prev) =>
|
|
198
|
+
prev.some((n) => Boolean(n.selected) !== (n.id === selectedNodeId))
|
|
199
|
+
? prev.map((n) =>
|
|
200
|
+
Boolean(n.selected) === (n.id === selectedNodeId)
|
|
201
|
+
? n
|
|
202
|
+
: { ...n, selected: n.id === selectedNodeId }
|
|
203
|
+
)
|
|
204
|
+
: prev
|
|
205
|
+
);
|
|
206
|
+
}, [selectedNodeId]);
|
|
207
|
+
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
setDisplayEdges((prev) =>
|
|
210
|
+
prev.some((e) => Boolean(e.selected) !== (e.id === selectedEdgeId))
|
|
211
|
+
? prev.map((e) =>
|
|
212
|
+
Boolean(e.selected) === (e.id === selectedEdgeId)
|
|
213
|
+
? e
|
|
214
|
+
: { ...e, selected: e.id === selectedEdgeId }
|
|
215
|
+
)
|
|
216
|
+
: prev
|
|
217
|
+
);
|
|
218
|
+
}, [selectedEdgeId]);
|
|
219
|
+
|
|
220
|
+
// Animate the edges along the active path during a test run: an edge flows
|
|
221
|
+
// once its source node has produced output (`done`) and its target is engaged
|
|
222
|
+
// (`running`/`done`). Mirrors run state into the local edge state — which is
|
|
223
|
+
// only reseeded on graph changes — without disturbing positions or selection.
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
setDisplayEdges((prev) => {
|
|
226
|
+
let changed = false;
|
|
227
|
+
const next = prev.map((e) => {
|
|
228
|
+
const active =
|
|
229
|
+
runStates[e.source] === 'done' &&
|
|
230
|
+
(runStates[e.target] === 'running' || runStates[e.target] === 'done');
|
|
231
|
+
if (Boolean(e.animated) === active) return e;
|
|
232
|
+
changed = true;
|
|
233
|
+
return { ...e, animated: active };
|
|
234
|
+
});
|
|
235
|
+
return changed ? next : prev;
|
|
236
|
+
});
|
|
237
|
+
}, [runStates]);
|
|
238
|
+
|
|
239
|
+
// React Flow's one-shot `fitView` prop only fits on first mount. In the
|
|
240
|
+
// read-only preview the container settles its size late (panel layout) and
|
|
241
|
+
// the graph can change underneath us — either one leaves the graph
|
|
242
|
+
// off-centre. Re-fit (deferred a frame so the new size is measured) on graph
|
|
243
|
+
// change and on container resize. Skipped while editing: it would fight the
|
|
244
|
+
// author's own panning and zooming.
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
if (!readOnly) return;
|
|
247
|
+
const raf = requestAnimationFrame(() => fitView(FIT_VIEW_OPTIONS));
|
|
248
|
+
return () => cancelAnimationFrame(raf);
|
|
249
|
+
}, [readOnly, fitView, displayNodes]);
|
|
250
|
+
|
|
251
|
+
useEffect(() => {
|
|
252
|
+
if (!readOnly) return;
|
|
253
|
+
const el = wrapperRef.current;
|
|
254
|
+
if (!el) return;
|
|
255
|
+
let raf = 0;
|
|
256
|
+
const observer = new ResizeObserver(() => {
|
|
257
|
+
cancelAnimationFrame(raf);
|
|
258
|
+
raf = requestAnimationFrame(() => fitView(FIT_VIEW_OPTIONS));
|
|
259
|
+
});
|
|
260
|
+
observer.observe(el);
|
|
261
|
+
return () => {
|
|
262
|
+
cancelAnimationFrame(raf);
|
|
263
|
+
observer.disconnect();
|
|
264
|
+
};
|
|
265
|
+
}, [readOnly, fitView]);
|
|
266
|
+
|
|
267
|
+
const onNodesChange = useCallback(
|
|
268
|
+
(changes: NodeChange<WorkflowReactFlowNode>[]) => {
|
|
269
|
+
// Keep React Flow's transient state (positions during drag, selection) local.
|
|
270
|
+
setDisplayNodes((prev) => applyNodeChanges(changes, prev));
|
|
271
|
+
|
|
272
|
+
for (const change of changes) {
|
|
273
|
+
// Only persist position on drag end — avoids 60fps validator churn.
|
|
274
|
+
if (change.type === 'position' && change.position && !change.dragging) {
|
|
275
|
+
dispatch({
|
|
276
|
+
type: 'updateNodePosition',
|
|
277
|
+
id: change.id,
|
|
278
|
+
position: change.position,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
if (change.type === 'remove') {
|
|
282
|
+
// Pinned nodes are not deletable in React Flow, but defense-in-depth:
|
|
283
|
+
// if a remove change for a pinned node ever leaks through, skip it
|
|
284
|
+
// AND skip the edge-removes for its endpoints to avoid orphaning.
|
|
285
|
+
const node = graph.nodes.find((n) => n.id === change.id);
|
|
286
|
+
const def = node ? getNodeType(node.kind) : undefined;
|
|
287
|
+
if (def?.placement?.pinned) continue;
|
|
288
|
+
dispatch({ type: 'deleteNode', id: change.id });
|
|
289
|
+
}
|
|
290
|
+
if (change.type === 'select') {
|
|
291
|
+
if (change.selected) {
|
|
292
|
+
// Selecting a node clears any edge selection (single active target).
|
|
293
|
+
setSelectedNodeId(change.id);
|
|
294
|
+
setSelectedEdgeId(null);
|
|
295
|
+
// Drag-select is the one selection path that doesn't go through a
|
|
296
|
+
// click handler: keep an already-open inspector following the
|
|
297
|
+
// selection (same invariant clicks maintain) instead of leaving it
|
|
298
|
+
// on a now-deselected element. A closed drawer stays closed.
|
|
299
|
+
if (
|
|
300
|
+
drawerTarget &&
|
|
301
|
+
(drawerTarget.type !== 'node' || drawerTarget.id !== change.id)
|
|
302
|
+
) {
|
|
303
|
+
setDrawerTarget({ type: 'node', id: change.id });
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
setSelectedNodeId(null);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
[
|
|
312
|
+
graph.nodes,
|
|
313
|
+
dispatch,
|
|
314
|
+
getNodeType,
|
|
315
|
+
setSelectedNodeId,
|
|
316
|
+
setSelectedEdgeId,
|
|
317
|
+
drawerTarget,
|
|
318
|
+
setDrawerTarget,
|
|
319
|
+
]
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
const onEdgesChange = useCallback(
|
|
323
|
+
(changes: EdgeChange[]) => {
|
|
324
|
+
// Apply every change locally — crucially `select`, so an edge can enter
|
|
325
|
+
// the selected state that the Delete key binding acts on. Persist removals.
|
|
326
|
+
setDisplayEdges((prev) => applyEdgeChanges(changes, prev));
|
|
327
|
+
for (const change of changes) {
|
|
328
|
+
if (change.type === 'remove') {
|
|
329
|
+
dispatch({ type: 'deleteEdge', id: change.id });
|
|
330
|
+
}
|
|
331
|
+
if (change.type === 'select') {
|
|
332
|
+
if (change.selected) {
|
|
333
|
+
// Selecting an edge clears node selection + opens it in the drawer.
|
|
334
|
+
setSelectedEdgeId(change.id);
|
|
335
|
+
setSelectedNodeId(null);
|
|
336
|
+
setDrawerTarget({ type: 'edge', id: change.id });
|
|
337
|
+
} else {
|
|
338
|
+
setSelectedEdgeId(null);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
[dispatch, setSelectedEdgeId, setSelectedNodeId, setDrawerTarget]
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
const isValidConnection = useCallback<IsValidConnection<Edge>>(
|
|
347
|
+
// React Flow may hand either a `Connection` or an existing `Edge`; both
|
|
348
|
+
// expose the same source/target/handle fields the validator reads.
|
|
349
|
+
(connection) =>
|
|
350
|
+
isValidWorkflowConnection(
|
|
351
|
+
{
|
|
352
|
+
source: connection.source,
|
|
353
|
+
target: connection.target,
|
|
354
|
+
sourceHandle: connection.sourceHandle ?? null,
|
|
355
|
+
targetHandle: connection.targetHandle ?? null,
|
|
356
|
+
},
|
|
357
|
+
graph,
|
|
358
|
+
getNodeType
|
|
359
|
+
),
|
|
360
|
+
[graph, getNodeType]
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
// Dragging from a handle that already has an edge should move that edge, not
|
|
364
|
+
// stack a new one. React Flow grabs the *edge endpoint* this way already, but
|
|
365
|
+
// a drag from the handle port itself starts a fresh connection. For entries
|
|
366
|
+
// (which permit fan-in) we bridge that gap: if the drag begins on an input
|
|
367
|
+
// handle that holds exactly one edge, remember it so `onConnect` re-routes its
|
|
368
|
+
// source rather than adding a parallel edge. With zero or 2+ edges there's no
|
|
369
|
+
// single edge to grab, so we leave it to the normal add path.
|
|
370
|
+
const onConnectStart = useCallback<OnConnectStart>(
|
|
371
|
+
(_event, { nodeId, handleId, handleType }) => {
|
|
372
|
+
grabbedEntryEdgeRef.current =
|
|
373
|
+
handleType === 'target' && nodeId
|
|
374
|
+
? (soleEdgeToHandle(graph, getNodeType, nodeId, handleId ?? undefined)
|
|
375
|
+
?.id ?? null)
|
|
376
|
+
: null;
|
|
377
|
+
},
|
|
378
|
+
[graph, getNodeType]
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const onConnectEnd = useCallback<OnConnectEnd>(() => {
|
|
382
|
+
grabbedEntryEdgeRef.current = null;
|
|
383
|
+
}, []);
|
|
384
|
+
|
|
385
|
+
const onConnect = useCallback(
|
|
386
|
+
(connection: Connection) => {
|
|
387
|
+
if (!connection.source || !connection.target) return;
|
|
388
|
+
// Defense-in-depth: enforce node-type rules even though React Flow also
|
|
389
|
+
// gates drags through `isValidConnection`.
|
|
390
|
+
if (!isValidWorkflowConnection(connection, graph, getNodeType)) return;
|
|
391
|
+
const sourceHandle = connection.sourceHandle ?? undefined;
|
|
392
|
+
const targetHandle = connection.targetHandle ?? undefined;
|
|
393
|
+
// Drag started on an occupied entry: re-route that edge's source endpoint
|
|
394
|
+
// to the newly chosen source instead of adding a parallel edge. Apply the
|
|
395
|
+
// same single-edge-per-exit guard as a reconnect — if the new source exit
|
|
396
|
+
// already holds a different edge, bail so React Flow snaps back.
|
|
397
|
+
const grabbedId = grabbedEntryEdgeRef.current;
|
|
398
|
+
if (grabbedId) {
|
|
399
|
+
const occupant = existingEdgeFromHandle(
|
|
400
|
+
graph,
|
|
401
|
+
getNodeType,
|
|
402
|
+
connection.source,
|
|
403
|
+
sourceHandle
|
|
404
|
+
);
|
|
405
|
+
if (!occupant || occupant.id === grabbedId) {
|
|
406
|
+
dispatch({
|
|
407
|
+
type: 'reconnectEdge',
|
|
408
|
+
id: grabbedId,
|
|
409
|
+
source: connection.source,
|
|
410
|
+
target: connection.target,
|
|
411
|
+
sourceHandle,
|
|
412
|
+
targetHandle,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
// An exit point holds at most one edge. Dragging a fresh connection from
|
|
418
|
+
// an exit that already has one MOVES that edge to the new target (keeping
|
|
419
|
+
// its id + label) rather than creating a second edge from the same point.
|
|
420
|
+
const existing = existingEdgeFromHandle(
|
|
421
|
+
graph,
|
|
422
|
+
getNodeType,
|
|
423
|
+
connection.source,
|
|
424
|
+
sourceHandle
|
|
425
|
+
);
|
|
426
|
+
if (existing) {
|
|
427
|
+
dispatch({
|
|
428
|
+
type: 'reconnectEdge',
|
|
429
|
+
id: existing.id,
|
|
430
|
+
source: connection.source,
|
|
431
|
+
target: connection.target,
|
|
432
|
+
sourceHandle,
|
|
433
|
+
targetHandle,
|
|
434
|
+
});
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
dispatch({
|
|
438
|
+
type: 'addEdge',
|
|
439
|
+
edge: {
|
|
440
|
+
id: genId('e'),
|
|
441
|
+
source: connection.source,
|
|
442
|
+
target: connection.target,
|
|
443
|
+
sourceHandle,
|
|
444
|
+
targetHandle,
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
},
|
|
448
|
+
[dispatch, graph, getNodeType]
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
// React Flow reconnect lifecycle. `onReconnect` only mutates the edge on a
|
|
452
|
+
// valid commit; an invalid or empty drop is a no-op, so React Flow snaps the
|
|
453
|
+
// dragged endpoint back to its original handle and the edge stays intact.
|
|
454
|
+
// There's no success ref to track because we never tear down and recreate the
|
|
455
|
+
// edge — an unmutated edge needs nothing restored.
|
|
456
|
+
const onReconnect = useCallback<OnReconnect<Edge>>(
|
|
457
|
+
(oldEdge, connection) => {
|
|
458
|
+
if (!connection.source || !connection.target) return;
|
|
459
|
+
// Validate the new endpoints with the same rules as manual connect; an
|
|
460
|
+
// invalid drop is ignored so the original edge snaps back. `connection`
|
|
461
|
+
// here is React Flow's `Connection`, so narrow to the validator's shape.
|
|
462
|
+
const proposed = {
|
|
463
|
+
source: connection.source,
|
|
464
|
+
target: connection.target,
|
|
465
|
+
sourceHandle: connection.sourceHandle ?? null,
|
|
466
|
+
targetHandle: connection.targetHandle ?? null,
|
|
467
|
+
};
|
|
468
|
+
if (!isValidWorkflowConnection(proposed, graph, getNodeType)) return;
|
|
469
|
+
// Keep the single-edge-per-exit invariant (same as `onConnect`): if the
|
|
470
|
+
// dragged source endpoint lands on an exit that already holds a different
|
|
471
|
+
// edge, reject so React Flow snaps back rather than stacking two edges on
|
|
472
|
+
// one handle. The edge being moved is excluded (a target-endpoint drag
|
|
473
|
+
// keeps the same source handle and would otherwise match itself).
|
|
474
|
+
const occupant = existingEdgeFromHandle(
|
|
475
|
+
graph,
|
|
476
|
+
getNodeType,
|
|
477
|
+
connection.source,
|
|
478
|
+
connection.sourceHandle ?? undefined
|
|
479
|
+
);
|
|
480
|
+
if (occupant && occupant.id !== oldEdge.id) return;
|
|
481
|
+
dispatch({
|
|
482
|
+
type: 'reconnectEdge',
|
|
483
|
+
id: oldEdge.id,
|
|
484
|
+
source: connection.source,
|
|
485
|
+
target: connection.target,
|
|
486
|
+
sourceHandle: connection.sourceHandle ?? undefined,
|
|
487
|
+
targetHandle: connection.targetHandle ?? undefined,
|
|
488
|
+
});
|
|
489
|
+
},
|
|
490
|
+
[dispatch, graph, getNodeType]
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
// Single click selects the node AND opens its inspector drawer (no
|
|
494
|
+
// double-click needed). React Flow's own `select` change still fires and
|
|
495
|
+
// syncs `selectedNodeId`, but we set it here too so selection + drawer open
|
|
496
|
+
// atomically on the very first click.
|
|
497
|
+
const onNodeClick = useCallback(
|
|
498
|
+
(_: unknown, node: WorkflowReactFlowNode) => {
|
|
499
|
+
setSelectedNodeId(node.id);
|
|
500
|
+
setSelectedEdgeId(null);
|
|
501
|
+
// revealInspector sets the drawer target (read by a mounted
|
|
502
|
+
// <NodeInspector>, and surfaced to the host via onSelectionChange).
|
|
503
|
+
revealInspector({ type: 'node', id: node.id });
|
|
504
|
+
// Convenience click hook for hosts driving UI outside the canvas.
|
|
505
|
+
const graphNode = graph.nodes.find((n) => n.id === node.id);
|
|
506
|
+
if (graphNode) onNodeClickHost?.(graphNode);
|
|
507
|
+
},
|
|
508
|
+
[
|
|
509
|
+
setSelectedNodeId,
|
|
510
|
+
setSelectedEdgeId,
|
|
511
|
+
revealInspector,
|
|
512
|
+
graph,
|
|
513
|
+
onNodeClickHost,
|
|
514
|
+
]
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
// Single click selects the edge AND targets the inspector at it — the same
|
|
518
|
+
// surface nodes use — replacing the old left-sidebar edge list.
|
|
519
|
+
const onEdgeClick = useCallback(
|
|
520
|
+
(_: unknown, edge: Edge) => {
|
|
521
|
+
setSelectedEdgeId(edge.id);
|
|
522
|
+
setSelectedNodeId(null);
|
|
523
|
+
revealInspector({ type: 'edge', id: edge.id });
|
|
524
|
+
const graphEdge = graph.edges.find((e) => e.id === edge.id);
|
|
525
|
+
if (graphEdge) onEdgeClickHost?.(graphEdge);
|
|
526
|
+
},
|
|
527
|
+
[
|
|
528
|
+
setSelectedEdgeId,
|
|
529
|
+
setSelectedNodeId,
|
|
530
|
+
revealInspector,
|
|
531
|
+
graph,
|
|
532
|
+
onEdgeClickHost,
|
|
533
|
+
]
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
const onPaneClick = useCallback(() => {
|
|
537
|
+
setSelectedNodeId(null);
|
|
538
|
+
setSelectedEdgeId(null);
|
|
539
|
+
setDrawerTarget(null);
|
|
540
|
+
}, [setSelectedNodeId, setSelectedEdgeId, setDrawerTarget]);
|
|
541
|
+
|
|
542
|
+
// One-click tidy: lay the graph out left-to-right and dispatch the new
|
|
543
|
+
// positions as a single (undoable) reposition. We feed dagre the REAL
|
|
544
|
+
// rendered node sizes from React Flow so variable-height cards pack tightly,
|
|
545
|
+
// falling back to card defaults for any node not yet measured — plus the
|
|
546
|
+
// trailing room a node's exit labels (e.g. Classify categories) need, since
|
|
547
|
+
// those overflow the measured card and would otherwise sit under the next
|
|
548
|
+
// rank's edges.
|
|
549
|
+
const onAutoArrange = useCallback(() => {
|
|
550
|
+
const nodesById = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
551
|
+
const dimensions: Record<string, NodeDimensions> = {};
|
|
552
|
+
for (const n of getNodes()) {
|
|
553
|
+
const { width, height } = n.measured ?? {};
|
|
554
|
+
if (!width || !height) continue;
|
|
555
|
+
const node = nodesById.get(n.id);
|
|
556
|
+
const def = node ? getNodeType(node.kind) : undefined;
|
|
557
|
+
const outputs = node && def ? def.handles(node.config).outputs : [];
|
|
558
|
+
const labels = outputs
|
|
559
|
+
.map((o) => o.label)
|
|
560
|
+
.filter((label): label is string => Boolean(label));
|
|
561
|
+
dimensions[n.id] = {
|
|
562
|
+
width,
|
|
563
|
+
height,
|
|
564
|
+
trailing: estimateLabelOverhang(labels),
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
// The order each node paints its exits, so the layout can lay a fan-out's
|
|
568
|
+
// children out in exit order rather than wiring order (see `outputOrder`).
|
|
569
|
+
const outputOrder: Record<string, string[]> = {};
|
|
570
|
+
for (const node of graph.nodes) {
|
|
571
|
+
const def = getNodeType(node.kind);
|
|
572
|
+
if (!def) continue;
|
|
573
|
+
outputOrder[node.id] = def.handles(node.config).outputs.map((o) => o.id);
|
|
574
|
+
}
|
|
575
|
+
const arranged = autoLayout(graph, dimensions, { outputOrder });
|
|
576
|
+
const positions: Record<string, Position> = {};
|
|
577
|
+
let moved = false;
|
|
578
|
+
for (const n of arranged.nodes) {
|
|
579
|
+
positions[n.id] = n.position;
|
|
580
|
+
const current = nodesById.get(n.id)?.position;
|
|
581
|
+
if (current?.x !== n.position.x || current?.y !== n.position.y) {
|
|
582
|
+
moved = true;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
// Already tidy — skip the dispatch AND the forced save so re-clicking a
|
|
586
|
+
// settled layout doesn't issue a redundant PUT or flip the draft to dirty.
|
|
587
|
+
if (!moved) return;
|
|
588
|
+
dispatch({ type: 'arrangeNodes', positions });
|
|
589
|
+
// A pure reposition wouldn't autosave on its own; let the host persist the
|
|
590
|
+
// tidied layout so it survives a reload (see WorkflowProps.onArrange).
|
|
591
|
+
onArrange?.(arranged);
|
|
592
|
+
// Reframe once the moved nodes have painted.
|
|
593
|
+
window.requestAnimationFrame(() => fitView(ANIMATED_FIT_VIEW_OPTIONS));
|
|
594
|
+
}, [getNodes, graph, getNodeType, dispatch, onArrange, fitView]);
|
|
595
|
+
|
|
596
|
+
const onDragOver = useCallback((e: DragEvent) => {
|
|
597
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME)) return;
|
|
598
|
+
e.preventDefault();
|
|
599
|
+
e.dataTransfer.dropEffect = 'move';
|
|
600
|
+
}, []);
|
|
601
|
+
|
|
602
|
+
const onDrop = useCallback(
|
|
603
|
+
(e: DragEvent) => {
|
|
604
|
+
e.preventDefault();
|
|
605
|
+
const kind = e.dataTransfer.getData(DRAG_MIME);
|
|
606
|
+
if (!kind) return;
|
|
607
|
+
const def = getNodeType(kind);
|
|
608
|
+
if (!def) return;
|
|
609
|
+
const position = screenToFlowPosition({ x: e.clientX, y: e.clientY });
|
|
610
|
+
const base = resolveDefaultConfig(def) as Record<string, unknown>;
|
|
611
|
+
const overlay = def.localizeDefaults?.(t) as
|
|
612
|
+
| Record<string, unknown>
|
|
613
|
+
| undefined;
|
|
614
|
+
// Host-data overlay (e.g. a starting LLM picked from the tenant's live
|
|
615
|
+
// model list) — applied last so it wins over any static placeholder in
|
|
616
|
+
// `defaultConfig`. Keyed on the opaque `hostBridge`; the node type narrows
|
|
617
|
+
// it. Absent on a generic host, leaving the static defaults in place.
|
|
618
|
+
const bridged = def.hostDefaults?.(hostBridge) as
|
|
619
|
+
| Record<string, unknown>
|
|
620
|
+
| undefined;
|
|
621
|
+
const node = {
|
|
622
|
+
id: genId(kind),
|
|
623
|
+
kind,
|
|
624
|
+
position,
|
|
625
|
+
config: { ...base, ...overlay, ...bridged },
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
// Dropped nodes land unconnected — authors wire edges explicitly by
|
|
629
|
+
// dragging from an exit point.
|
|
630
|
+
dispatch({ type: 'addNode', node });
|
|
631
|
+
},
|
|
632
|
+
[dispatch, getNodeType, screenToFlowPosition, t, hostBridge]
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
// Does the canvas top-left corner actually hold overlay chrome the zoom
|
|
636
|
+
// controls should tuck under? The palette toggle docks there when the palette
|
|
637
|
+
// is collapsed, and the error banner when the (editable) graph has issues. If
|
|
638
|
+
// neither is present the controls sit at the corner rather than floating below
|
|
639
|
+
// an empty gap. Read-only preview shows no chrome, so it's always corner-tight.
|
|
640
|
+
const topLeftChromePresent =
|
|
641
|
+
!readOnly && ((showPalette && !isPaletteOpen) || issues.length > 0);
|
|
642
|
+
|
|
643
|
+
return (
|
|
644
|
+
<Box
|
|
645
|
+
display="flex"
|
|
646
|
+
flex="1"
|
|
647
|
+
minHeight={0}
|
|
648
|
+
height="100%"
|
|
649
|
+
// Tint the whole canvas region — not just the React Flow column — so the
|
|
650
|
+
// floating palette (left) and inspector (right) read as cards over a tinted
|
|
651
|
+
// surface instead of white sidebars. Read-only (version preview) drops to a
|
|
652
|
+
// neutral gray so the mode reads as "not your live workspace".
|
|
653
|
+
// Dark mode uses bg.canvas for both: primary.lightest's _dark is blue.900
|
|
654
|
+
// (#04102A), a saturated navy that overpowers the desaturated dark palette
|
|
655
|
+
// as a full-canvas fill, and slate.100's _dark sits ABOVE bg.surface, which
|
|
656
|
+
// would invert the node cards' lift. bg.canvas keeps the cards lifted in
|
|
657
|
+
// both modes; read-only is still cued by the absent editor chrome.
|
|
658
|
+
bgColor={{
|
|
659
|
+
base: readOnly ? 'slate.100' : 'primary.lightest',
|
|
660
|
+
_dark: 'bg.canvas',
|
|
661
|
+
}}
|
|
662
|
+
>
|
|
663
|
+
{showPalette && isPaletteOpen ? (
|
|
664
|
+
<NodePalette onClose={() => setIsPaletteOpen(false)} />
|
|
665
|
+
) : null}
|
|
666
|
+
<Box
|
|
667
|
+
flex="1"
|
|
668
|
+
minWidth={0}
|
|
669
|
+
position="relative"
|
|
670
|
+
ref={wrapperRef}
|
|
671
|
+
onDragOver={onDragOver}
|
|
672
|
+
onDrop={onDrop}
|
|
673
|
+
css={canvasSelectionCss}
|
|
674
|
+
>
|
|
675
|
+
<ReactFlow
|
|
676
|
+
nodes={displayNodes}
|
|
677
|
+
edges={displayEdges}
|
|
678
|
+
nodeTypes={rfNodeTypes}
|
|
679
|
+
edgeTypes={rfEdgeTypes}
|
|
680
|
+
defaultEdgeOptions={defaultEdgeOptions}
|
|
681
|
+
onNodesChange={onNodesChange}
|
|
682
|
+
onEdgesChange={onEdgesChange}
|
|
683
|
+
// Match the live connection preview to the committed edge shape:
|
|
684
|
+
// both render as angled (smooth-step) paths so releasing a drag
|
|
685
|
+
// doesn't snap a curved preview into an angled edge.
|
|
686
|
+
connectionLineType={ConnectionLineType.SmoothStep}
|
|
687
|
+
onConnect={onConnect}
|
|
688
|
+
onConnectStart={readOnly ? undefined : onConnectStart}
|
|
689
|
+
onConnectEnd={readOnly ? undefined : onConnectEnd}
|
|
690
|
+
onReconnect={readOnly ? undefined : onReconnect}
|
|
691
|
+
onNodeClick={onNodeClick}
|
|
692
|
+
onEdgeClick={onEdgeClick}
|
|
693
|
+
onPaneClick={onPaneClick}
|
|
694
|
+
isValidConnection={isValidConnection}
|
|
695
|
+
nodesDraggable={!readOnly}
|
|
696
|
+
nodesConnectable={!readOnly}
|
|
697
|
+
elementsSelectable
|
|
698
|
+
// The editor's selection model is a single node/edge (see
|
|
699
|
+
// selectedNodeId / selectedEdgeId): disable React Flow's marquee and
|
|
700
|
+
// modifier-click multi-select, which would visually select a group
|
|
701
|
+
// only for the sync effects above to collapse it to one element.
|
|
702
|
+
selectionKeyCode={null}
|
|
703
|
+
multiSelectionKeyCode={null}
|
|
704
|
+
edgesFocusable={!readOnly}
|
|
705
|
+
// Belt-and-suspenders on top of per-node `deletable: false`: also
|
|
706
|
+
// disable the delete keyboard binding entirely in read-only mode.
|
|
707
|
+
deleteKeyCode={readOnly ? null : ['Backspace', 'Delete']}
|
|
708
|
+
// Pan on scroll/trackpad (Figma-style) in addition to click-and-drag;
|
|
709
|
+
// ⌘/Ctrl+scroll zooms. Enabled in read-only too: scroll is a viewing
|
|
710
|
+
// action, and drag-to-pan is already allowed there — this just makes
|
|
711
|
+
// the scroll gesture pan instead of zoom (whether the canvas captures
|
|
712
|
+
// scroll at all is governed separately by `preventScrolling`).
|
|
713
|
+
panOnScroll
|
|
714
|
+
fitView
|
|
715
|
+
fitViewOptions={FIT_VIEW_OPTIONS}
|
|
716
|
+
proOptions={{ hideAttribution: true }}
|
|
717
|
+
>
|
|
718
|
+
<Background />
|
|
719
|
+
<CanvasControls
|
|
720
|
+
readOnly={readOnly}
|
|
721
|
+
onAutoArrange={onAutoArrange}
|
|
722
|
+
fitViewOptions={ANIMATED_FIT_VIEW_OPTIONS}
|
|
723
|
+
topLeftChromePresent={topLeftChromePresent}
|
|
724
|
+
/>
|
|
725
|
+
{/* React Flow's stock minimap is a fixed white panel — resolve its
|
|
726
|
+
colors through theme CSS vars so it follows the color mode
|
|
727
|
+
(light values match the stock look). */}
|
|
728
|
+
<MiniMap
|
|
729
|
+
pannable
|
|
730
|
+
zoomable
|
|
731
|
+
bgColor="var(--chakra-colors-bg-surface)"
|
|
732
|
+
nodeColor="var(--chakra-colors-slate-200)"
|
|
733
|
+
maskColor="color-mix(in srgb, var(--chakra-colors-slate-100) 60%, transparent)"
|
|
734
|
+
/>
|
|
735
|
+
</ReactFlow>
|
|
736
|
+
{showPalette && !isPaletteOpen ? (
|
|
737
|
+
<NodePaletteToggle onOpen={() => setIsPaletteOpen(true)} />
|
|
738
|
+
) : null}
|
|
739
|
+
<GraphErrorBanner
|
|
740
|
+
paletteToggleVisible={showPalette && !isPaletteOpen}
|
|
741
|
+
/>
|
|
742
|
+
</Box>
|
|
743
|
+
{/* Canvas-anchored overlay slot (React-Flow-style children): the host
|
|
744
|
+
mounts <NodeInspector> here for the built-in drawer, or its own
|
|
745
|
+
surfaces. A left-docked inspector orders itself before the canvas. */}
|
|
746
|
+
{children}
|
|
747
|
+
</Box>
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
export function Canvas({
|
|
752
|
+
showPalette = true,
|
|
753
|
+
onNodeClick,
|
|
754
|
+
onEdgeClick,
|
|
755
|
+
children,
|
|
756
|
+
}: {
|
|
757
|
+
showPalette?: boolean;
|
|
758
|
+
onNodeClick?: (node: GraphNode) => void;
|
|
759
|
+
onEdgeClick?: (edge: GraphEdge) => void;
|
|
760
|
+
children?: ReactNode;
|
|
761
|
+
}) {
|
|
762
|
+
return (
|
|
763
|
+
<ReactFlowProvider>
|
|
764
|
+
<CanvasInner
|
|
765
|
+
showPalette={showPalette}
|
|
766
|
+
onNodeClick={onNodeClick}
|
|
767
|
+
onEdgeClick={onEdgeClick}
|
|
768
|
+
>
|
|
769
|
+
{children}
|
|
770
|
+
</CanvasInner>
|
|
771
|
+
</ReactFlowProvider>
|
|
772
|
+
);
|
|
773
|
+
}
|