@mindlogic-ai/logician-ui 3.1.0-alpha.9 → 3.2.0-alpha.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/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/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.js +20 -4
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.mjs +20 -4
- package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
- 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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -0
- 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/dist/theme/colors.d.ts +196 -44
- package/dist/theme/colors.d.ts.map +1 -1
- package/dist/theme/colors.js +184 -22
- package/dist/theme/colors.js.map +1 -1
- package/dist/theme/colors.mjs +184 -22
- package/dist/theme/colors.mjs.map +1 -1
- package/dist/theme/global.d.ts.map +1 -1
- package/dist/theme/global.js +30 -2
- package/dist/theme/global.js.map +1 -1
- package/dist/theme/global.mjs +30 -2
- package/dist/theme/global.mjs.map +1 -1
- 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/SegmentedControl/SegmentedControl.tsx +21 -4
- 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 +1 -0
- package/src/test-support/setup.ts +11 -0
- package/src/theme/SemanticTokens.mdx +61 -7
- package/src/theme/colors.ts +216 -26
- package/src/theme/global.ts +31 -2
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import type { Graph, GraphEdge, GraphNode, Position } from './Workflow.types';
|
|
2
|
+
|
|
3
|
+
export type GraphAction =
|
|
4
|
+
| { type: 'addNode'; node: GraphNode }
|
|
5
|
+
| {
|
|
6
|
+
/**
|
|
7
|
+
* Adds a node and, when `autoConnectFrom` is supplied, an edge from that
|
|
8
|
+
* source node into the new node — both in a single reducer transition so
|
|
9
|
+
* one undo step reverts the node and the auto-edge together.
|
|
10
|
+
*/
|
|
11
|
+
type: 'addNodeWithEdge';
|
|
12
|
+
node: GraphNode;
|
|
13
|
+
autoConnectFrom: { edge: GraphEdge } | null;
|
|
14
|
+
}
|
|
15
|
+
| { type: 'updateNodePosition'; id: string; position: Position }
|
|
16
|
+
| {
|
|
17
|
+
/**
|
|
18
|
+
* Repositions many nodes in one transition — the one-click auto-arrange.
|
|
19
|
+
* Positions are precomputed by `autoLayout`; a node absent from the map
|
|
20
|
+
* keeps its current position. Unlike `replace` this is an in-place user
|
|
21
|
+
* edit, so it pushes a SINGLE undo step (and leaves the rest of the undo
|
|
22
|
+
* stack intact) rather than resetting history.
|
|
23
|
+
*/
|
|
24
|
+
type: 'arrangeNodes';
|
|
25
|
+
positions: Record<string, Position>;
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
type: 'updateNodeConfig';
|
|
29
|
+
id: string;
|
|
30
|
+
config: unknown;
|
|
31
|
+
/**
|
|
32
|
+
* Renames an output handle id on the node's outbound edges in the SAME
|
|
33
|
+
* transition. Some handle ids derive from mutable config (Classify:
|
|
34
|
+
* `cat_<name>`); moving the edge atomically keeps React Flow from pruning
|
|
35
|
+
* it as an orphan when the id changes.
|
|
36
|
+
*/
|
|
37
|
+
remapEdgeHandle?: { from: string; to: string };
|
|
38
|
+
}
|
|
39
|
+
| { type: 'deleteNode'; id: string }
|
|
40
|
+
| { type: 'addEdge'; edge: GraphEdge }
|
|
41
|
+
| {
|
|
42
|
+
type: 'reconnectEdge';
|
|
43
|
+
id: string;
|
|
44
|
+
source: string;
|
|
45
|
+
target: string;
|
|
46
|
+
sourceHandle?: string;
|
|
47
|
+
targetHandle?: string;
|
|
48
|
+
}
|
|
49
|
+
| { type: 'deleteEdge'; id: string }
|
|
50
|
+
| {
|
|
51
|
+
/**
|
|
52
|
+
* Merges a partial patch into an edge by id (e.g. its `label`). Endpoint
|
|
53
|
+
* moves go through `reconnectEdge`; this is for non-structural fields so
|
|
54
|
+
* label edits stay undoable through `graphHistory`.
|
|
55
|
+
*/
|
|
56
|
+
type: 'updateEdge';
|
|
57
|
+
id: string;
|
|
58
|
+
patch: Partial<Omit<GraphEdge, 'id'>>;
|
|
59
|
+
}
|
|
60
|
+
| { type: 'replace'; graph: Graph };
|
|
61
|
+
|
|
62
|
+
/** Normalize null-vs-undefined for optional handle ids so dedupe works. */
|
|
63
|
+
function normEdge(edge: GraphEdge): GraphEdge {
|
|
64
|
+
return {
|
|
65
|
+
...edge,
|
|
66
|
+
sourceHandle: edge.sourceHandle ?? undefined,
|
|
67
|
+
targetHandle: edge.targetHandle ?? undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function normGraph(graph: Graph): Graph {
|
|
72
|
+
return { ...graph, edges: graph.edges.map(normEdge) };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function graphReducer(state: Graph, action: GraphAction): Graph {
|
|
76
|
+
switch (action.type) {
|
|
77
|
+
case 'addNode':
|
|
78
|
+
if (state.nodes.some((n) => n.id === action.node.id)) return state;
|
|
79
|
+
return { ...state, nodes: [...state.nodes, action.node] };
|
|
80
|
+
|
|
81
|
+
case 'addNodeWithEdge': {
|
|
82
|
+
if (state.nodes.some((n) => n.id === action.node.id)) return state;
|
|
83
|
+
const nodes = [...state.nodes, action.node];
|
|
84
|
+
if (!action.autoConnectFrom) return { ...state, nodes };
|
|
85
|
+
const edge = normEdge(action.autoConnectFrom.edge);
|
|
86
|
+
// The auto-edge is freshly generated and references a brand-new node id,
|
|
87
|
+
// so it can't collide; append it alongside the node.
|
|
88
|
+
return { nodes, edges: [...state.edges, edge] };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
case 'updateNodePosition':
|
|
92
|
+
return {
|
|
93
|
+
...state,
|
|
94
|
+
nodes: state.nodes.map((n) =>
|
|
95
|
+
n.id === action.id ? { ...n, position: action.position } : n
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
case 'arrangeNodes': {
|
|
100
|
+
// Skip nodes that don't move so an arrange producing the current layout
|
|
101
|
+
// collapses to the same reference — `historyReducer` then treats it as a
|
|
102
|
+
// no-op and records no undo step.
|
|
103
|
+
let moved = false;
|
|
104
|
+
const nodes = state.nodes.map((n) => {
|
|
105
|
+
const next = action.positions[n.id];
|
|
106
|
+
if (!next || (next.x === n.position.x && next.y === n.position.y)) {
|
|
107
|
+
return n;
|
|
108
|
+
}
|
|
109
|
+
moved = true;
|
|
110
|
+
return { ...n, position: next };
|
|
111
|
+
});
|
|
112
|
+
return moved ? { ...state, nodes } : state;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
case 'updateNodeConfig': {
|
|
116
|
+
const nodes = state.nodes.map((n) =>
|
|
117
|
+
n.id === action.id ? { ...n, config: action.config } : n
|
|
118
|
+
);
|
|
119
|
+
const remap = action.remapEdgeHandle;
|
|
120
|
+
if (!remap) return { ...state, nodes };
|
|
121
|
+
const edges = state.edges.map((e) =>
|
|
122
|
+
e.source === action.id && (e.sourceHandle ?? undefined) === remap.from
|
|
123
|
+
? { ...e, sourceHandle: remap.to }
|
|
124
|
+
: e
|
|
125
|
+
);
|
|
126
|
+
return { ...state, nodes, edges };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
case 'deleteNode':
|
|
130
|
+
return {
|
|
131
|
+
nodes: state.nodes.filter((n) => n.id !== action.id),
|
|
132
|
+
edges: state.edges.filter(
|
|
133
|
+
(e) => e.source !== action.id && e.target !== action.id
|
|
134
|
+
),
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
case 'addEdge': {
|
|
138
|
+
const edge = normEdge(action.edge);
|
|
139
|
+
if (state.edges.some((e) => e.id === edge.id)) return state;
|
|
140
|
+
const dup = state.edges.some(
|
|
141
|
+
(e) =>
|
|
142
|
+
e.source === edge.source &&
|
|
143
|
+
(e.sourceHandle ?? undefined) === edge.sourceHandle &&
|
|
144
|
+
e.target === edge.target &&
|
|
145
|
+
(e.targetHandle ?? undefined) === edge.targetHandle
|
|
146
|
+
);
|
|
147
|
+
if (dup) return state;
|
|
148
|
+
return { ...state, edges: [...state.edges, edge] };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
case 'reconnectEdge': {
|
|
152
|
+
const existing = state.edges.find((e) => e.id === action.id);
|
|
153
|
+
if (!existing) return state;
|
|
154
|
+
const next = normEdge({
|
|
155
|
+
...existing,
|
|
156
|
+
source: action.source,
|
|
157
|
+
target: action.target,
|
|
158
|
+
sourceHandle: action.sourceHandle,
|
|
159
|
+
targetHandle: action.targetHandle,
|
|
160
|
+
});
|
|
161
|
+
// A reconnect can land on endpoints that already have an identical edge;
|
|
162
|
+
// isValidConnection doesn't dedupe, so guard here and no-op the move.
|
|
163
|
+
const dup = state.edges.some(
|
|
164
|
+
(e) =>
|
|
165
|
+
e.id !== next.id &&
|
|
166
|
+
e.source === next.source &&
|
|
167
|
+
(e.sourceHandle ?? undefined) === next.sourceHandle &&
|
|
168
|
+
e.target === next.target &&
|
|
169
|
+
(e.targetHandle ?? undefined) === next.targetHandle
|
|
170
|
+
);
|
|
171
|
+
if (dup) return state;
|
|
172
|
+
return {
|
|
173
|
+
...state,
|
|
174
|
+
edges: state.edges.map((e) => (e.id === next.id ? next : e)),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
case 'deleteEdge':
|
|
179
|
+
return { ...state, edges: state.edges.filter((e) => e.id !== action.id) };
|
|
180
|
+
|
|
181
|
+
case 'updateEdge': {
|
|
182
|
+
if (!state.edges.some((e) => e.id === action.id)) return state;
|
|
183
|
+
return {
|
|
184
|
+
...state,
|
|
185
|
+
edges: state.edges.map((e) =>
|
|
186
|
+
e.id === action.id ? normEdge({ ...e, ...action.patch }) : e
|
|
187
|
+
),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
case 'replace':
|
|
192
|
+
return normGraph(action.graph);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const emptyGraph: Graph = { nodes: [], edges: [] };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export type { CollapsibleSectionProps } from './canvas/CollapsibleSection';
|
|
2
|
+
export { CollapsibleSection } from './canvas/CollapsibleSection';
|
|
3
|
+
export type { NodeInspectorProps } from './canvas/DrawerShell';
|
|
4
|
+
export { NodeInspector } from './canvas/DrawerShell';
|
|
5
|
+
export type {
|
|
6
|
+
FieldTone,
|
|
7
|
+
FieldToneState,
|
|
8
|
+
FieldWrapperProps,
|
|
9
|
+
} from './canvas/FieldWrapper';
|
|
10
|
+
export { FieldWrapper } from './canvas/FieldWrapper';
|
|
11
|
+
export { FLOATING_CARD_WIDTH, FloatingCard } from './canvas/FloatingCard';
|
|
12
|
+
export type {
|
|
13
|
+
CategoryTokenMap,
|
|
14
|
+
CategoryTokens,
|
|
15
|
+
IconTileProps,
|
|
16
|
+
} from './canvas/IconTile';
|
|
17
|
+
export {
|
|
18
|
+
DEFAULT_CATEGORY_TOKENS,
|
|
19
|
+
getCategoryTokens,
|
|
20
|
+
IconTile,
|
|
21
|
+
} from './canvas/IconTile';
|
|
22
|
+
export type { NodeShellProps, PortStyle, RingChrome } from './canvas/NodeShell';
|
|
23
|
+
export {
|
|
24
|
+
CARD_WIDTH,
|
|
25
|
+
MAX_META_CHIPS,
|
|
26
|
+
metaChipStyles,
|
|
27
|
+
NodeShell,
|
|
28
|
+
PORT_STYLE,
|
|
29
|
+
} from './canvas/NodeShell';
|
|
30
|
+
export { workflowLabelProps } from './canvas/workflowLabelProps';
|
|
31
|
+
export type { WorkflowGraphObserver } from './graphObserver';
|
|
32
|
+
export {
|
|
33
|
+
useWorkflowGraphObserver,
|
|
34
|
+
WorkflowGraphObserverContext,
|
|
35
|
+
} from './graphObserver';
|
|
36
|
+
export type { GraphAction } from './graphReducer';
|
|
37
|
+
export { emptyGraph, graphReducer } from './graphReducer';
|
|
38
|
+
export { Workflow } from './Workflow';
|
|
39
|
+
export type {
|
|
40
|
+
ConnectionCtx,
|
|
41
|
+
DockSide,
|
|
42
|
+
DrawerRenderProps,
|
|
43
|
+
EdgeDrawerRenderProps,
|
|
44
|
+
Graph,
|
|
45
|
+
GraphEdge,
|
|
46
|
+
GraphNode,
|
|
47
|
+
HandleDef,
|
|
48
|
+
Issue,
|
|
49
|
+
IssueSeverity,
|
|
50
|
+
JSONSchema,
|
|
51
|
+
MetaChipSpec,
|
|
52
|
+
MetaChipTone,
|
|
53
|
+
NodeCategory,
|
|
54
|
+
NodeRenderProps,
|
|
55
|
+
NodeTypeDef,
|
|
56
|
+
NodeTypeRegistry,
|
|
57
|
+
PlacementRule,
|
|
58
|
+
Position,
|
|
59
|
+
RunState,
|
|
60
|
+
WorkflowProps,
|
|
61
|
+
WorkflowSelection,
|
|
62
|
+
WorkflowTranslate,
|
|
63
|
+
} from './Workflow.types';
|
|
64
|
+
export { defineNodeType, resolveDefaultConfig } from './Workflow.types';
|
|
65
|
+
export type {
|
|
66
|
+
EditorState,
|
|
67
|
+
WorkflowContextValue,
|
|
68
|
+
WorkflowProviderProps,
|
|
69
|
+
} from './WorkflowContext';
|
|
70
|
+
export {
|
|
71
|
+
useWorkflow,
|
|
72
|
+
useWorkflowTranslate,
|
|
73
|
+
WorkflowProvider,
|
|
74
|
+
} from './WorkflowContext';
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import type { Graph, GraphNode } from '../Workflow.types';
|
|
4
|
+
import { autoLayout, estimateLabelOverhang } from './autoLayout';
|
|
5
|
+
|
|
6
|
+
const node = (id: string): GraphNode => ({
|
|
7
|
+
id,
|
|
8
|
+
kind: 'x',
|
|
9
|
+
position: { x: 0, y: 0 },
|
|
10
|
+
config: {},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('autoLayout', () => {
|
|
14
|
+
it('lays a linear chain out left-to-right by rank', () => {
|
|
15
|
+
const graph: Graph = {
|
|
16
|
+
nodes: [node('a'), node('b'), node('c')],
|
|
17
|
+
edges: [
|
|
18
|
+
{ id: 'e1', source: 'a', target: 'b' },
|
|
19
|
+
{ id: 'e2', source: 'b', target: 'c' },
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
const out = autoLayout(graph);
|
|
23
|
+
const x = (id: string) => out.nodes.find((n) => n.id === id)!.position.x;
|
|
24
|
+
// LR direction: each downstream node sits in a later (greater-x) rank.
|
|
25
|
+
expect(x('a')).toBeLessThan(x('b'));
|
|
26
|
+
expect(x('b')).toBeLessThan(x('c'));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('places top-down when direction is TB', () => {
|
|
30
|
+
const graph: Graph = {
|
|
31
|
+
nodes: [node('a'), node('b')],
|
|
32
|
+
edges: [{ id: 'e1', source: 'a', target: 'b' }],
|
|
33
|
+
};
|
|
34
|
+
const out = autoLayout(graph, {}, { direction: 'TB' });
|
|
35
|
+
const y = (id: string) => out.nodes.find((n) => n.id === id)!.position.y;
|
|
36
|
+
expect(y('a')).toBeLessThan(y('b'));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('is pure and deterministic — leaves the input graph untouched', () => {
|
|
40
|
+
const graph: Graph = {
|
|
41
|
+
nodes: [node('a'), node('b')],
|
|
42
|
+
edges: [{ id: 'e1', source: 'a', target: 'b' }],
|
|
43
|
+
};
|
|
44
|
+
const snapshot = JSON.stringify(graph);
|
|
45
|
+
const first = autoLayout(graph);
|
|
46
|
+
const second = autoLayout(graph);
|
|
47
|
+
expect(JSON.stringify(graph)).toBe(snapshot); // input not mutated
|
|
48
|
+
expect(first.nodes).toEqual(second.nodes); // same in → same out
|
|
49
|
+
expect(first).not.toBe(graph); // returns a fresh graph
|
|
50
|
+
expect(first.edges).toBe(graph.edges); // edges passed through untouched
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('positions disconnected nodes without overlapping them', () => {
|
|
54
|
+
const graph: Graph = {
|
|
55
|
+
nodes: [node('a'), node('b')],
|
|
56
|
+
edges: [],
|
|
57
|
+
};
|
|
58
|
+
const out = autoLayout(graph, {
|
|
59
|
+
a: { width: 100, height: 50 },
|
|
60
|
+
b: { width: 100, height: 50 },
|
|
61
|
+
});
|
|
62
|
+
const a = out.nodes.find((n) => n.id === 'a')!.position;
|
|
63
|
+
const b = out.nodes.find((n) => n.id === 'b')!.position;
|
|
64
|
+
expect(a).not.toEqual(b);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('reserves trailing room so a downstream rank clears overflowing exit labels', () => {
|
|
68
|
+
const graph: Graph = {
|
|
69
|
+
nodes: [node('a'), node('b')],
|
|
70
|
+
edges: [{ id: 'e1', source: 'a', target: 'b' }],
|
|
71
|
+
};
|
|
72
|
+
const x = (g: Graph, id: string) =>
|
|
73
|
+
g.nodes.find((n) => n.id === id)!.position.x;
|
|
74
|
+
|
|
75
|
+
const tight = autoLayout(graph, { a: { width: 100, height: 50 } });
|
|
76
|
+
const padded = autoLayout(graph, {
|
|
77
|
+
a: { width: 100, height: 50, trailing: 120 },
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// The reserved label room sits on a's trailing edge, so its left edge is
|
|
81
|
+
// unchanged but the next rank is pushed right to clear the labels.
|
|
82
|
+
expect(x(padded, 'a')).toBe(x(tight, 'a'));
|
|
83
|
+
expect(x(padded, 'b')).toBeGreaterThan(x(tight, 'b'));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('estimateLabelOverhang', () => {
|
|
87
|
+
it('reserves nothing when there are no labels', () => {
|
|
88
|
+
expect(estimateLabelOverhang([])).toBe(0);
|
|
89
|
+
expect(estimateLabelOverhang(['', ''])).toBe(0);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('grows with the longest label', () => {
|
|
93
|
+
expect(estimateLabelOverhang(['refund'])).toBeLessThan(
|
|
94
|
+
estimateLabelOverhang(['refund', 'a much longer category name'])
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('lays a fan-out node out in exit order — first exit on top, last on the bottom', () => {
|
|
100
|
+
// `outputOrder` says A paints exits h0, h1, h2 top-to-bottom. The edges are
|
|
101
|
+
// wired in a different order (the author connected the last exit first) to
|
|
102
|
+
// prove the layout follows exit order, not wiring order.
|
|
103
|
+
const graph: Graph = {
|
|
104
|
+
nodes: [node('a'), node('c1'), node('c2'), node('c3')],
|
|
105
|
+
edges: [
|
|
106
|
+
{ id: 'e3', source: 'a', target: 'c3', sourceHandle: 'h2' },
|
|
107
|
+
{ id: 'e1', source: 'a', target: 'c1', sourceHandle: 'h0' },
|
|
108
|
+
{ id: 'e2', source: 'a', target: 'c2', sourceHandle: 'h1' },
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
const out = autoLayout(
|
|
112
|
+
graph,
|
|
113
|
+
{},
|
|
114
|
+
{ outputOrder: { a: ['h0', 'h1', 'h2'] } }
|
|
115
|
+
);
|
|
116
|
+
const y = (id: string) => out.nodes.find((n) => n.id === id)!.position.y;
|
|
117
|
+
// First exit's child sits above the second's, which sits above the third's.
|
|
118
|
+
expect(y('c1')).toBeLessThan(y('c2'));
|
|
119
|
+
expect(y('c2')).toBeLessThan(y('c3'));
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('sorts only the source it knows the exit order of, leaving other edges in place', () => {
|
|
123
|
+
// `a` is a fan-out we know the exit order of; `b`'s edges are interleaved
|
|
124
|
+
// among `a`'s and have no exit order. Only `a`'s children should be
|
|
125
|
+
// reordered — `b`'s must keep the slots they held in `graph.edges`, so the
|
|
126
|
+
// fallback path isn't perturbed by `a`'s reordering.
|
|
127
|
+
const graph: Graph = {
|
|
128
|
+
nodes: [node('a'), node('b'), node('a1'), node('a2'), node('b1')],
|
|
129
|
+
edges: [
|
|
130
|
+
{ id: 'ea2', source: 'a', target: 'a2', sourceHandle: 'h1' },
|
|
131
|
+
{ id: 'eb1', source: 'b', target: 'b1' },
|
|
132
|
+
{ id: 'ea1', source: 'a', target: 'a1', sourceHandle: 'h0' },
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
const out = autoLayout(graph, {}, { outputOrder: { a: ['h0', 'h1'] } });
|
|
136
|
+
const y = (id: string) => out.nodes.find((n) => n.id === id)!.position.y;
|
|
137
|
+
// a's first exit sits above its second despite being wired second.
|
|
138
|
+
expect(y('a1')).toBeLessThan(y('a2'));
|
|
139
|
+
// Every node still gets a distinct slot.
|
|
140
|
+
expect(new Set(['a1', 'a2', 'b1'].map(y)).size).toBe(3);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('falls back to edge order when no exit order is given for the source', () => {
|
|
144
|
+
// Without `outputOrder` the layout can only honor wiring order, but it must
|
|
145
|
+
// still place every child and never collapse them onto one another.
|
|
146
|
+
const graph: Graph = {
|
|
147
|
+
nodes: [node('a'), node('c1'), node('c2'), node('c3')],
|
|
148
|
+
edges: [
|
|
149
|
+
{ id: 'e1', source: 'a', target: 'c1', sourceHandle: 'h0' },
|
|
150
|
+
{ id: 'e2', source: 'a', target: 'c2', sourceHandle: 'h1' },
|
|
151
|
+
{ id: 'e3', source: 'a', target: 'c3', sourceHandle: 'h2' },
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
const out = autoLayout(graph);
|
|
155
|
+
const ys = ['c1', 'c2', 'c3'].map(
|
|
156
|
+
(id) => out.nodes.find((n) => n.id === id)!.position.y
|
|
157
|
+
);
|
|
158
|
+
expect(new Set(ys).size).toBe(3);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('ignores edges that reference an unknown node', () => {
|
|
162
|
+
const graph: Graph = {
|
|
163
|
+
nodes: [node('a')],
|
|
164
|
+
edges: [{ id: 'e1', source: 'a', target: 'ghost' }],
|
|
165
|
+
};
|
|
166
|
+
const out = autoLayout(graph);
|
|
167
|
+
expect(out.nodes).toHaveLength(1);
|
|
168
|
+
expect(out.nodes[0].id).toBe('a');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { graphlib, layout } from '@dagrejs/dagre';
|
|
2
|
+
|
|
3
|
+
import { CARD_WIDTH } from '../canvas/NodeShell/NodeShell.styles';
|
|
4
|
+
import type { Graph, Position } from '../Workflow.types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Flow axis of the laid-out graph. `LR` (the default) lays ranks out
|
|
8
|
+
* left-to-right, matching the way a workflow reads: trigger → steps → output.
|
|
9
|
+
*/
|
|
10
|
+
export type LayoutDirection = 'LR' | 'TB';
|
|
11
|
+
|
|
12
|
+
/** Rendered footprint of a node, used so ranks don't overlap. */
|
|
13
|
+
export type NodeDimensions = {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
/**
|
|
17
|
+
* Extra room (px) to reserve on the node's trailing (downstream) edge for
|
|
18
|
+
* content that overflows the card — specifically the exit labels a Classify /
|
|
19
|
+
* If-Else node paints to the right of its handles. These are absolutely
|
|
20
|
+
* positioned, so React Flow's measured `width` excludes them; without this
|
|
21
|
+
* the next rank packs right up against the node and the edges leaving those
|
|
22
|
+
* exits get tucked under the label text. See `estimateLabelOverhang`.
|
|
23
|
+
*/
|
|
24
|
+
trailing?: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Roughly how wide (px) the longest of a node's exit labels renders, so the
|
|
29
|
+
* layout can reserve trailing room for it. The label is absolutely positioned
|
|
30
|
+
* and not in the layout pass, so we approximate from text length rather than
|
|
31
|
+
* measure: a per-glyph width plus the label's inset from the node edge. Korean
|
|
32
|
+
* glyphs are near full-width, so we size for the wider case to stay safe.
|
|
33
|
+
*/
|
|
34
|
+
const LABEL_GLYPH_PX = 8;
|
|
35
|
+
const LABEL_INSET_PX = 18;
|
|
36
|
+
|
|
37
|
+
export function estimateLabelOverhang(labels: string[]): number {
|
|
38
|
+
const longest = labels.reduce((max, label) => Math.max(max, label.length), 0);
|
|
39
|
+
return longest === 0 ? 0 : LABEL_INSET_PX + longest * LABEL_GLYPH_PX;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type AutoLayoutOptions = {
|
|
43
|
+
direction?: LayoutDirection;
|
|
44
|
+
/** Gap between adjacent ranks (along the flow axis). */
|
|
45
|
+
rankGap?: number;
|
|
46
|
+
/** Gap between sibling nodes within a rank (the cross axis). */
|
|
47
|
+
nodeGap?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Per-node order of output handles, keyed by node id — the ordered list of
|
|
50
|
+
* `HandleDef.id`s a node paints top-to-bottom (e.g. a Classify node's
|
|
51
|
+
* categories). Used to lay a node's downstream children out in the same order
|
|
52
|
+
* its exits read, so the child wired to the first exit sits above the one
|
|
53
|
+
* wired to the last (see `orderEdgesForDagre`). Nodes absent from the map (or
|
|
54
|
+
* edges with no `sourceHandle`) keep their order in `graph.edges`.
|
|
55
|
+
*/
|
|
56
|
+
outputOrder?: Record<string, readonly string[]>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Order `edges` for insertion into dagre so a fan-out node's children come out
|
|
61
|
+
* in exit order — first exit on top, last on the bottom.
|
|
62
|
+
*
|
|
63
|
+
* dagre derives a rank's initial vertical order from a DFS that pushes each
|
|
64
|
+
* node's successors in *edge-insertion order*, and the first-pushed sibling
|
|
65
|
+
* lands at the BOTTOM (largest cross-axis coordinate). Left to the raw
|
|
66
|
+
* `graph.edges` order — which is just whenever the author happened to wire each
|
|
67
|
+
* exit — that yields criss-crossed edges: the first exit's child gets sent to
|
|
68
|
+
* the bottom and the last exit's to the top.
|
|
69
|
+
*
|
|
70
|
+
* So for each source we know the exit order of, we reorder ITS edges in REVERSE
|
|
71
|
+
* exit order to cancel dagre's reversal. Every other edge — a source with no
|
|
72
|
+
* known exit order, or fewer than two edges — keeps its exact slot in
|
|
73
|
+
* `graph.edges`, so the documented fallback path doesn't perturb the layout.
|
|
74
|
+
* Stable: ties (e.g. two edges off one exit) preserve input order.
|
|
75
|
+
*/
|
|
76
|
+
function orderEdgesForDagre(
|
|
77
|
+
edges: Graph['edges'],
|
|
78
|
+
outputOrder: Record<string, readonly string[]>
|
|
79
|
+
): Graph['edges'] {
|
|
80
|
+
// Collect, per source we can sort, that source's edges in REVERSE exit order.
|
|
81
|
+
const sortedBySource = new Map<string, Graph['edges']>();
|
|
82
|
+
for (const edge of edges) {
|
|
83
|
+
if (!outputOrder[edge.source]) continue;
|
|
84
|
+
const group = sortedBySource.get(edge.source);
|
|
85
|
+
if (group) group.push(edge);
|
|
86
|
+
else sortedBySource.set(edge.source, [edge]);
|
|
87
|
+
}
|
|
88
|
+
for (const [source, group] of sortedBySource) {
|
|
89
|
+
const order = outputOrder[source];
|
|
90
|
+
if (group.length < 2) {
|
|
91
|
+
sortedBySource.delete(source);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const exitIndex = (handle: string | undefined): number => {
|
|
95
|
+
// An undefined handle denotes the first output (matches the
|
|
96
|
+
// `resolveHandle` convention in connectionRules), so it ranks as exit 0.
|
|
97
|
+
const i = order.indexOf(handle ?? order[0]);
|
|
98
|
+
return i === -1 ? Number.MAX_SAFE_INTEGER : i;
|
|
99
|
+
};
|
|
100
|
+
// Stable sort keeps ties (e.g. two edges off one exit) in input order.
|
|
101
|
+
group.sort((a, b) => exitIndex(b.sourceHandle) - exitIndex(a.sourceHandle));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Nothing to reorder — hand back the original array untouched.
|
|
105
|
+
if (sortedBySource.size === 0) return edges;
|
|
106
|
+
|
|
107
|
+
// Replay `graph.edges` in place, drawing each sortable source's edges from
|
|
108
|
+
// its reordered queue so only those slots change and all others stay put.
|
|
109
|
+
const cursor = new Map<string, number>();
|
|
110
|
+
return edges.map((edge) => {
|
|
111
|
+
const group = sortedBySource.get(edge.source);
|
|
112
|
+
if (!group) return edge;
|
|
113
|
+
const i = cursor.get(edge.source) ?? 0;
|
|
114
|
+
cursor.set(edge.source, i + 1);
|
|
115
|
+
return group[i];
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Footprint assumed for a node we have no measured size for — e.g. one added
|
|
121
|
+
* but not yet rendered. Width tracks the fixed node-card width (`CARD_WIDTH`);
|
|
122
|
+
* height is a typical two-row card. Callers should pass real measured sizes
|
|
123
|
+
* when available so ranks pack tightly.
|
|
124
|
+
*/
|
|
125
|
+
const FALLBACK_WIDTH = parseInt(CARD_WIDTH, 10);
|
|
126
|
+
const FALLBACK_HEIGHT = 76;
|
|
127
|
+
|
|
128
|
+
const DEFAULT_RANK_GAP = 80;
|
|
129
|
+
const DEFAULT_NODE_GAP = 40;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Compute a tidy, hierarchical layout for a workflow graph and return a new
|
|
133
|
+
* `Graph` with every node's `position` recomputed (edges untouched). Pure and
|
|
134
|
+
* deterministic — same graph + dimensions in, same positions out — so it's
|
|
135
|
+
* safe to dispatch through the reducer and to snapshot in tests.
|
|
136
|
+
*
|
|
137
|
+
* `dimensions` maps node id → measured size; missing entries fall back to the
|
|
138
|
+
* node-card defaults. Disconnected nodes are placed by dagre in the first rank
|
|
139
|
+
* (never overlapping, thanks to `nodesep`).
|
|
140
|
+
*/
|
|
141
|
+
export function autoLayout(
|
|
142
|
+
graph: Graph,
|
|
143
|
+
dimensions: Record<string, NodeDimensions> = {},
|
|
144
|
+
options: AutoLayoutOptions = {}
|
|
145
|
+
): Graph {
|
|
146
|
+
const {
|
|
147
|
+
direction = 'LR',
|
|
148
|
+
rankGap = DEFAULT_RANK_GAP,
|
|
149
|
+
nodeGap = DEFAULT_NODE_GAP,
|
|
150
|
+
outputOrder = {},
|
|
151
|
+
} = options;
|
|
152
|
+
|
|
153
|
+
// Footprint dagre lays out with: the real card height, and a width padded by
|
|
154
|
+
// any trailing exit-label overhang so the next rank clears it. We keep the
|
|
155
|
+
// node left-aligned within that padded box (see the offset below) so the
|
|
156
|
+
// reserved space lands on the trailing edge, where the labels actually are.
|
|
157
|
+
const footprintOf = (id: string): NodeDimensions => {
|
|
158
|
+
const d = dimensions[id];
|
|
159
|
+
return {
|
|
160
|
+
width: (d?.width ?? FALLBACK_WIDTH) + (d?.trailing ?? 0),
|
|
161
|
+
height: d?.height ?? FALLBACK_HEIGHT,
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const g = new graphlib.Graph();
|
|
166
|
+
g.setGraph({ rankdir: direction, ranksep: rankGap, nodesep: nodeGap });
|
|
167
|
+
// dagre requires an edge-label factory even when we attach no labels.
|
|
168
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
169
|
+
|
|
170
|
+
for (const node of graph.nodes) {
|
|
171
|
+
g.setNode(node.id, footprintOf(node.id));
|
|
172
|
+
}
|
|
173
|
+
for (const edge of orderEdgesForDagre(graph.edges, outputOrder)) {
|
|
174
|
+
// Guard against edges that reference a pruned node so dagre doesn't
|
|
175
|
+
// implicitly create a zero-size node for the dangling endpoint.
|
|
176
|
+
if (g.hasNode(edge.source) && g.hasNode(edge.target)) {
|
|
177
|
+
g.setEdge(edge.source, edge.target);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
layout(g);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
...graph,
|
|
185
|
+
nodes: graph.nodes.map((node) => {
|
|
186
|
+
const laidOut = g.node(node.id);
|
|
187
|
+
if (!laidOut) return node;
|
|
188
|
+
const { width, height } = footprintOf(node.id);
|
|
189
|
+
// dagre reports the node CENTER; React Flow positions are top-left. The
|
|
190
|
+
// footprint width includes the trailing label pad, so subtracting half of
|
|
191
|
+
// it puts the card's real left edge at the box's left — leaving the pad on
|
|
192
|
+
// the trailing side, under the overflowing exit labels.
|
|
193
|
+
const position: Position = {
|
|
194
|
+
x: laidOut.x - width / 2,
|
|
195
|
+
y: laidOut.y - height / 2,
|
|
196
|
+
};
|
|
197
|
+
return { ...node, position };
|
|
198
|
+
}),
|
|
199
|
+
};
|
|
200
|
+
}
|