@w6w/ui 0.2.0 → 0.2.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +146 -2
- package/README.md +28 -10
- package/dist/AppPicker.d.ts +58 -2
- package/dist/CanvasContextMenu.d.ts +19 -0
- package/dist/CanvasLayer.d.ts +38 -0
- package/dist/{CodeBlock-Dot3Pd7P.js → CodeBlock-C-oIIYfC.js} +1436 -555
- package/dist/CodeBlock-C-oIIYfC.js.map +1 -0
- package/dist/CodeBlock-CymlfyeA.cjs +15 -0
- package/dist/CodeBlock-CymlfyeA.cjs.map +1 -0
- package/dist/CodeEditor.d.ts +4 -1
- package/dist/ConditionEditor.d.ts +11 -0
- package/dist/EditConnectionModal.d.ts +6 -1
- package/dist/JsonEditor.d.ts +20 -0
- package/dist/Markdown.d.ts +25 -0
- package/dist/ParamCustomization.d.ts +5 -0
- package/dist/ParamsForm.d.ts +18 -4
- package/dist/RouterEditor.d.ts +5 -0
- package/dist/StepBuilderModal.d.ts +103 -15
- package/dist/StepNameEditor.d.ts +11 -0
- package/dist/StopEditor.d.ts +5 -0
- package/dist/TriggerFillForm.d.ts +14 -1
- package/dist/WebhookListenPanel.d.ts +28 -0
- package/dist/WorkflowConnections.d.ts +29 -0
- package/dist/WorkflowFlowEditor.d.ts +74 -7
- package/dist/app-pages.d.ts +2 -0
- package/dist/assets/script-completion.worker-DDJKkj5M.js +8290 -0
- package/dist/assets/script-completion.worker-DDJKkj5M.js.map +1 -0
- package/dist/canvas-context-menu.d.ts +27 -0
- package/dist/canvas-types.d.ts +36 -0
- package/dist/canvas-utils.d.ts +44 -0
- package/dist/code.cjs +1 -1
- package/dist/code.mjs +3 -4
- package/dist/code.mjs.map +1 -1
- package/dist/components/AnchoredFlyout.d.ts +7 -0
- package/dist/components/AuthFieldsForm.d.ts +11 -0
- package/dist/components/BudgetMeter.d.ts +15 -0
- package/dist/components/CallableList.d.ts +3 -2
- package/dist/components/ColumnsEditor.d.ts +27 -0
- package/dist/components/Combobox.d.ts +19 -1
- package/dist/components/ConnectionList.d.ts +2 -3
- package/dist/components/CredentialPicker.d.ts +35 -0
- package/dist/components/CsvPanel.d.ts +21 -0
- package/dist/components/DataEntryEditor.d.ts +38 -0
- package/dist/components/DataEntryList.d.ts +33 -0
- package/dist/components/DataStoreList.d.ts +33 -0
- package/dist/components/DataTable.d.ts +27 -0
- package/dist/components/DataTableGrid.d.ts +46 -0
- package/dist/components/EmptyState.d.ts +9 -0
- package/dist/components/EventbriteTriggerPicker.d.ts +7 -0
- package/dist/components/ExecutionDetail.d.ts +17 -1
- package/dist/components/ExecutionList.d.ts +19 -1
- package/dist/components/ExecutionLogPanel.d.ts +61 -3
- package/dist/components/ExpressionEditorModal.d.ts +33 -10
- package/dist/components/ExpressionOptions.d.ts +101 -15
- package/dist/components/HtmlPreview.d.ts +7 -0
- package/dist/components/JsonTree.d.ts +32 -0
- package/dist/components/ResolvedParams.d.ts +6 -1
- package/dist/components/ResultViewer.d.ts +46 -0
- package/dist/components/ScriptBindingsNotice.d.ts +31 -0
- package/dist/components/ScriptCodeField.d.ts +13 -0
- package/dist/components/StepStatusPill.d.ts +7 -0
- package/dist/components/expression-authoring.d.ts +13 -0
- package/dist/components/expression-dom.d.ts +17 -2
- package/dist/components/expression-template.d.ts +25 -3
- package/dist/components/icons.d.ts +1 -1
- package/dist/components/json-compose.d.ts +53 -0
- package/dist/components/result-format.d.ts +13 -0
- package/dist/condition-editor.d.ts +44 -0
- package/dist/data-stores/data-store-view.d.ts +371 -0
- package/dist/dynamic-fields.d.ts +60 -0
- package/dist/editor-theme.d.ts +24 -0
- package/dist/eventbrite-trigger-selection.d.ts +13 -0
- package/dist/flow-connect.d.ts +22 -16
- package/dist/flow-delete.d.ts +16 -0
- package/dist/flow-fanout.d.ts +2 -2
- package/dist/flow-history.d.ts +75 -0
- package/dist/flow-layout.d.ts +13 -0
- package/dist/flow-loop-colors.d.ts +39 -0
- package/dist/flow-loop.d.ts +98 -0
- package/dist/flow-node-flags.d.ts +14 -0
- package/dist/flow-problems.d.ts +69 -0
- package/dist/flow-state.d.ts +20 -0
- package/dist/flow-types.d.ts +155 -10
- package/dist/flow-utils.d.ts +33 -12
- package/dist/flow.cjs +4 -2
- package/dist/flow.cjs.map +1 -1
- package/dist/flow.d.ts +15 -2
- package/dist/flow.mjs +3737 -1350
- package/dist/flow.mjs.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +43 -5
- package/dist/index.mjs +2855 -1333
- package/dist/index.mjs.map +1 -1
- package/dist/node-samples-ChdyMBnJ.cjs +22 -0
- package/dist/node-samples-ChdyMBnJ.cjs.map +1 -0
- package/dist/node-samples-DkJL07EX.js +12302 -0
- package/dist/node-samples-DkJL07EX.js.map +1 -0
- package/dist/node-samples.d.ts +80 -0
- package/dist/note-markdown.d.ts +22 -0
- package/dist/output-shape.d.ts +30 -14
- package/dist/param-customization.d.ts +7 -0
- package/dist/provider.d.ts +174 -13
- package/dist/resolve-params.d.ts +50 -11
- package/dist/run-visuals.d.ts +18 -22
- package/dist/script-bindings.d.ts +63 -0
- package/dist/script-completion-service.d.ts +9 -0
- package/dist/script-completion.worker.d.ts +1 -0
- package/dist/script-completions.d.ts +2 -0
- package/dist/state-shape.d.ts +38 -0
- package/dist/step-preview-state.d.ts +155 -6
- package/dist/step-problems.d.ts +64 -0
- package/dist/test-inputs.d.ts +25 -0
- package/dist/trigger-registration.d.ts +28 -0
- package/dist/types.d.ts +179 -11
- package/dist/use-app-action-defs.d.ts +9 -1
- package/dist/use-dynamic-fields.d.ts +23 -0
- package/dist/use-test-input.d.ts +18 -0
- package/dist/workflow-connections.d.ts +30 -0
- package/package.json +18 -7
- package/src/code.css +60 -6
- package/src/styles/_budget-meter.scss +46 -0
- package/src/styles/_callable-list.scss +15 -6
- package/src/styles/_canvas.scss +353 -0
- package/src/styles/_code-editor.scss +35 -0
- package/src/styles/_code.scss +6 -5
- package/src/styles/_connections.scss +2 -14
- package/src/styles/_copyable.scss +24 -0
- package/src/styles/_data-stores.scss +138 -0
- package/src/styles/_data-table.scss +55 -0
- package/src/styles/_data-vars.scss +17 -6
- package/src/styles/_empty-state.scss +21 -0
- package/src/styles/_execution-history.scss +73 -0
- package/src/styles/_execution-log.scss +145 -1
- package/src/styles/_expression-modal.scss +106 -16
- package/src/styles/_fields.scss +11 -0
- package/src/styles/_flow.scss +171 -0
- package/src/styles/_fx.scss +26 -1
- package/src/styles/_incoming-state.scss +33 -0
- package/src/styles/_layout.scss +10 -0
- package/src/styles/_markdown.scss +20 -0
- package/src/styles/_modal.scss +12 -0
- package/src/styles/_multiselect.scss +35 -0
- package/src/styles/_sections.scss +36 -0
- package/src/styles/_step-builder.scss +145 -0
- package/src/styles/_tester.scss +57 -14
- package/src/styles/_tokens.scss +27 -1
- package/src/styles.css +1861 -115
- package/src/styles.scss +7 -0
- package/dist/CodeBlock-CZu4TFSi.cjs +0 -15
- package/dist/CodeBlock-CZu4TFSi.cjs.map +0 -1
- package/dist/CodeBlock-Dot3Pd7P.js.map +0 -1
- package/dist/ConfirmModal-ChoiGy2K.cjs +0 -11
- package/dist/ConfirmModal-ChoiGy2K.cjs.map +0 -1
- package/dist/ConfirmModal-Wx3i8F1n.js +0 -6359
- package/dist/ConfirmModal-Wx3i8F1n.js.map +0 -1
- package/dist/Copyable-1niV9gUa.js +0 -771
- package/dist/Copyable-1niV9gUa.js.map +0 -1
- package/dist/Copyable-CYZU1o4X.cjs +0 -2
- package/dist/Copyable-CYZU1o4X.cjs.map +0 -1
package/dist/flow-connect.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Edge } from '@xyflow/react';
|
|
2
|
-
import {
|
|
2
|
+
import { LoopRefusalReason } from './flow-loop.ts';
|
|
3
|
+
import { CanvasLane, PortsLookup } from './flow-types.ts';
|
|
3
4
|
import { StepNode } from './flow-utils.ts';
|
|
4
5
|
/**
|
|
5
6
|
* Which lane a React Flow edge belongs to (core `rfcs/workflow.md` · `Edge.when`
|
|
@@ -8,7 +9,7 @@ import { StepNode } from './flow-utils.ts';
|
|
|
8
9
|
* `data` at all. The single accessor: every consumer calls this rather than
|
|
9
10
|
* re-deriving the fallback, so "absent means success" is decided once.
|
|
10
11
|
*/
|
|
11
|
-
export declare function edgeLane(e: Edge):
|
|
12
|
+
export declare function edgeLane(e: Edge): CanvasLane;
|
|
12
13
|
/**
|
|
13
14
|
* A refused connection: the source's exit port is full **in this lane** and the cap
|
|
14
15
|
* is finite. Drawing past a finite `out` cap is refused, never satisfied by evicting
|
|
@@ -18,14 +19,22 @@ export type OutCapRefusal = {
|
|
|
18
19
|
refused: "out_cap";
|
|
19
20
|
cap: number;
|
|
20
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* A refused connection that would break the v1 linear-body rule of a For each
|
|
24
|
+
* (see {@link loopRefusal}). Raised before the out-cap census and before any
|
|
25
|
+
* inbound eviction, always against the INPUT edges.
|
|
26
|
+
*/
|
|
27
|
+
export type LoopRefusal = {
|
|
28
|
+
refused: "loop";
|
|
29
|
+
reason: LoopRefusalReason;
|
|
30
|
+
};
|
|
21
31
|
/**
|
|
22
32
|
* The hard rules for an edge `source → target` — the ones no amount of
|
|
23
33
|
* replacement can satisfy: a real, *distinct* pair (no self-loops), no duplicate
|
|
24
34
|
* edge, the target accepts an entry port (blocks connecting *into* a trigger,
|
|
25
35
|
* which declares `in: 0`), and the source has an exit port. Port **capacity** is
|
|
26
|
-
* deliberately NOT checked here:
|
|
27
|
-
*
|
|
28
|
-
* re-points it rather than being rejected. Used as the live `isValidConnection`.
|
|
36
|
+
* deliberately NOT checked here: an input accepts any number of edges, and the exit
|
|
37
|
+
* cap is refused in `applyConnect`. Used as the live `isValidConnection`.
|
|
29
38
|
*
|
|
30
39
|
* The duplicate-pair check is **lane-blind by design**, and that is a v1 *editor*
|
|
31
40
|
* limit, not a model limit: the model permits a success edge and an error edge
|
|
@@ -41,13 +50,13 @@ export type OutCapRefusal = {
|
|
|
41
50
|
* Letting the drop through and refusing in `applyConnect` is what lets the reason
|
|
42
51
|
* paint — see {@link connectConflict}.
|
|
43
52
|
*/
|
|
44
|
-
export declare function canConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], lookup?: PortsLookup): boolean;
|
|
53
|
+
export declare function canConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], lookup?: PortsLookup, route?: string): boolean;
|
|
45
54
|
/**
|
|
46
55
|
* Build the next edge set for a new `source → target` connection. **Additive at the
|
|
47
56
|
* source**: a source under its `out` cap (or unbounded) keeps every existing edge and
|
|
48
57
|
* gains one; at a finite cap the connection is **refused** (see {@link connectRefusal}),
|
|
49
|
-
* never satisfied by evicting. The target's entry port
|
|
50
|
-
*
|
|
58
|
+
* never satisfied by evicting. The target's entry port accepts any number of
|
|
59
|
+
* inbound edges, so nothing is ever evicted there. Returns `null` when the
|
|
51
60
|
* connection is disallowed by {@link canConnect}, refused at the out cap — **or when the minted id would
|
|
52
61
|
* duplicate a surviving edge's id**, the same refusal {@link setEdgeWhen} performs
|
|
53
62
|
* through the same {@link collidingEdgeId} test.
|
|
@@ -68,13 +77,10 @@ export declare function canConnect(source: string | null | undefined, target: st
|
|
|
68
77
|
* `send → (error) → fallback` shape authorable at all. No `ports.out` bump is
|
|
69
78
|
* needed, so every persisted definition and palette entry stays valid.
|
|
70
79
|
*
|
|
71
|
-
* The target's entry capacity
|
|
72
|
-
*
|
|
73
|
-
* governed by `ports.in` alone. Partitioning the target rule by lane too — the
|
|
74
|
-
* plausible "symmetry" cleanup — would let a `ports.in: 1` node silently accept
|
|
75
|
-
* two inbound edges.
|
|
80
|
+
* The target's entry has no capacity: any number of edges, from any number of
|
|
81
|
+
* sources (several triggers may feed one node), converge on it.
|
|
76
82
|
*/
|
|
77
|
-
export declare function applyConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?:
|
|
83
|
+
export declare function applyConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?: CanvasLane, lookup?: PortsLookup, route?: string): Edge[] | null;
|
|
78
84
|
/**
|
|
79
85
|
* The id of the existing edge that drawing `source → target` would collide with, or
|
|
80
86
|
* `null` when the connection is safe (or refused for an ordinary reason — a
|
|
@@ -85,13 +91,13 @@ export declare function applyConnect(source: string | null | undefined, target:
|
|
|
85
91
|
* selects that edge and renders the message in the edge-lane panel (never a browser
|
|
86
92
|
* dialog; see `.ai/conventions.md`).
|
|
87
93
|
*/
|
|
88
|
-
export declare function connectConflict(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?:
|
|
94
|
+
export declare function connectConflict(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?: CanvasLane, lookup?: PortsLookup, route?: string): string | null;
|
|
89
95
|
/**
|
|
90
96
|
* The out-cap refusal for drawing `source → target`, or `null` when the source has
|
|
91
97
|
* room (or is unbounded). The editor renders `cap` in an inline message on the same
|
|
92
98
|
* channel as {@link connectConflict}; {@link applyConnect} returns `null` for it.
|
|
93
99
|
*/
|
|
94
|
-
export declare function connectRefusal(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?:
|
|
100
|
+
export declare function connectRefusal(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?: CanvasLane, lookup?: PortsLookup, route?: string): OutCapRefusal | LoopRefusal | null;
|
|
95
101
|
/**
|
|
96
102
|
* Re-lane one edge. Updates its `data.when`, its visuals and its id, and frees
|
|
97
103
|
* nothing: when the destination lane is at a finite out cap the switch is refused
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
export interface FlowDeleteSelection {
|
|
5
|
+
nodeIds: string[];
|
|
6
|
+
edgeIds: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Capture the full selection, independently of the first item shown in the side panel. */
|
|
9
|
+
export declare function selectedFlowElements(nodes: StepNode[], edges: Edge[]): FlowDeleteSelection;
|
|
10
|
+
/** Apply the entire confirmed selection before the editor emits one change/history entry. */
|
|
11
|
+
export declare function deleteFlowSelection(selection: FlowDeleteSelection, nodes: StepNode[], edges: Edge[], canvas: FlowCanvas): {
|
|
12
|
+
nodes: StepNode[];
|
|
13
|
+
edges: Edge[];
|
|
14
|
+
canvas: FlowCanvas;
|
|
15
|
+
};
|
|
16
|
+
export declare function flowDeleteMessage(selection: FlowDeleteSelection, nodes: StepNode[], edges: Edge[]): string;
|
package/dist/flow-fanout.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Edge } from '@xyflow/react';
|
|
|
2
2
|
import { FlowStep } from './flow-types.ts';
|
|
3
3
|
export type FanOutMode = "sequential" | "parallel";
|
|
4
4
|
/**
|
|
5
|
-
* `count` is the largest number of outgoing edges the
|
|
5
|
+
* `count` is the largest number of outgoing edges the node has in any ONE lane
|
|
6
6
|
* (success / error); fan-out only means something at `count >= 2`.
|
|
7
7
|
*/
|
|
8
8
|
export declare function fanOutState(stepId: string, edges: readonly Edge[]): {
|
|
@@ -11,5 +11,5 @@ export declare function fanOutState(stepId: string, edges: readonly Edge[]): {
|
|
|
11
11
|
};
|
|
12
12
|
/** Sequential is the default, so it is expressed by the key's ABSENCE. */
|
|
13
13
|
export declare function setFanOut(step: FlowStep, mode: FanOutMode): FlowStep;
|
|
14
|
-
/** Card-badge wording: how many next
|
|
14
|
+
/** Card-badge wording: how many next nodes run, and in which mode. */
|
|
15
15
|
export declare function fanOutLabel(count: number, mode: FanOutMode): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
3
|
+
import { FlowStep, FlowWorkflow } from './flow-types.ts';
|
|
4
|
+
import { StepNode } from './flow-utils.ts';
|
|
5
|
+
/** Only authored graph data. Tests, samples, run paint, selection and viewport never enter history. */
|
|
6
|
+
export interface FlowEditSnapshot {
|
|
7
|
+
nodes: FlowStep[];
|
|
8
|
+
edges: NonNullable<FlowWorkflow["edges"]>;
|
|
9
|
+
connections: NonNullable<FlowWorkflow["connections"]>;
|
|
10
|
+
canvas: FlowCanvas;
|
|
11
|
+
/** Keep the live layout even when saving positions is switched off. */
|
|
12
|
+
positions: Record<string, {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export declare function captureFlowEdit(base: FlowWorkflow, nodes: StepNode[], edges: Edge[], connections: FlowEditSnapshot["connections"], canvas: FlowCanvas): FlowEditSnapshot;
|
|
18
|
+
export declare function restoreFlowEdit(base: FlowWorkflow, snapshot: FlowEditSnapshot): {
|
|
19
|
+
nodes: {
|
|
20
|
+
position: {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
};
|
|
24
|
+
id: string;
|
|
25
|
+
data: import('./flow-utils.ts').StepNodeData;
|
|
26
|
+
sourcePosition?: import('@xyflow/react').Position;
|
|
27
|
+
targetPosition?: import('@xyflow/react').Position;
|
|
28
|
+
hidden?: boolean;
|
|
29
|
+
selected?: boolean;
|
|
30
|
+
dragging?: boolean;
|
|
31
|
+
draggable?: boolean;
|
|
32
|
+
selectable?: boolean;
|
|
33
|
+
connectable?: boolean;
|
|
34
|
+
deletable?: boolean;
|
|
35
|
+
dragHandle?: string;
|
|
36
|
+
width?: number;
|
|
37
|
+
height?: number;
|
|
38
|
+
initialWidth?: number;
|
|
39
|
+
initialHeight?: number;
|
|
40
|
+
parentId?: string;
|
|
41
|
+
zIndex?: number;
|
|
42
|
+
extent?: "parent" | import('@xyflow/react').CoordinateExtent | null;
|
|
43
|
+
expandParent?: boolean;
|
|
44
|
+
ariaLabel?: string;
|
|
45
|
+
origin?: import('@xyflow/react').NodeOrigin;
|
|
46
|
+
handles?: import('@xyflow/react').NodeHandle[];
|
|
47
|
+
measured?: {
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
50
|
+
};
|
|
51
|
+
type?: string | undefined;
|
|
52
|
+
style?: import('react').CSSProperties;
|
|
53
|
+
className?: string;
|
|
54
|
+
resizing?: boolean;
|
|
55
|
+
focusable?: boolean;
|
|
56
|
+
ariaRole?: import('react').AriaRole;
|
|
57
|
+
domAttributes?: Omit<import('react').HTMLAttributes<HTMLDivElement>, "id" | "style" | "className" | "draggable" | "role" | "aria-label" | "defaultValue" | "dangerouslySetInnerHTML" | keyof import('react').DOMAttributes<HTMLDivElement>>;
|
|
58
|
+
}[];
|
|
59
|
+
edges: Edge[];
|
|
60
|
+
};
|
|
61
|
+
/** Bounded, editor-session history. One text-field focus session is one undoable edit. */
|
|
62
|
+
export declare class FlowEditHistory {
|
|
63
|
+
private past;
|
|
64
|
+
private future;
|
|
65
|
+
private present;
|
|
66
|
+
private group;
|
|
67
|
+
private readonly limit;
|
|
68
|
+
constructor(initial: FlowEditSnapshot, limit?: number);
|
|
69
|
+
reset(initial: FlowEditSnapshot): void;
|
|
70
|
+
record(snapshot: FlowEditSnapshot, group?: object): void;
|
|
71
|
+
undo(): FlowEditSnapshot | undefined;
|
|
72
|
+
redo(): FlowEditSnapshot | undefined;
|
|
73
|
+
}
|
|
74
|
+
/** Leave native text undo and CodeMirror's own history alone. */
|
|
75
|
+
export declare function isFlowTextTarget(target: EventTarget | null): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Arrange paths and their section frames together. Membership is authored data:
|
|
6
|
+
* fit each frame to its members, never infer new membership from moved geometry.
|
|
7
|
+
* A section spanning non-members is moved with its members below the obstruction.
|
|
8
|
+
* Notes and empty sections retain their authored geometry.
|
|
9
|
+
*/
|
|
10
|
+
export declare function relayoutFlow(nodes: StepNode[], edges: Edge[], canvas: FlowCanvas): {
|
|
11
|
+
nodes: StepNode[];
|
|
12
|
+
canvas: FlowCanvas;
|
|
13
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
/** How many `--w6w-loop-N` tokens `_tokens.scss` defines. */
|
|
5
|
+
export declare const LOOP_TONES = 6;
|
|
6
|
+
/**
|
|
7
|
+
* Tone index (1-based) per For each id. Ids are visited in sorted order so the result
|
|
8
|
+
* does not depend on node order; each takes its hashed tone, or the next free one.
|
|
9
|
+
*/
|
|
10
|
+
export declare function assignLoopTones(foreachIds: Iterable<string>): Map<string, number>;
|
|
11
|
+
/** The CSS colour for a tone index. */
|
|
12
|
+
export declare function loopToneVar(tone: number): string;
|
|
13
|
+
/** The loops enclosing `id`, outermost first, following each For each's own `loopOf`. */
|
|
14
|
+
export declare function enclosingLoops(id: string, loopOfById: ReadonlyMap<string, string | undefined>): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Paint each-lane edges with the colour of the loop they belong to: the For each itself
|
|
17
|
+
* for its Each item link, else the loop the edge's source step runs in. Sets the
|
|
18
|
+
* `--w6w-loop-color` custom property the `.w6w-edge-each` rule reads, so run-state
|
|
19
|
+
* classes still compose over it. Same array when nothing needs painting.
|
|
20
|
+
*/
|
|
21
|
+
export declare function paintLoopEdges(edges: Edge[], tones: ReadonlyMap<string, number>, loopOfById: ReadonlyMap<string, string | undefined>): Edge[];
|
|
22
|
+
/**
|
|
23
|
+
* The colour custom property a card's root carries: a For each's own tone, read by its
|
|
24
|
+
* Each item port. A loop-body step gets none — it looks exactly like a step outside a
|
|
25
|
+
* loop; its dots are what mark it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function loopCardStyle(id: string, tones: ReadonlyMap<string, number>): CSSProperties | undefined;
|
|
28
|
+
/** What the canvas paints loops from: each For each's tone, and each step's own loop. */
|
|
29
|
+
export type LoopPaint = {
|
|
30
|
+
tones: ReadonlyMap<string, number>;
|
|
31
|
+
loopOf: ReadonlyMap<string, string | undefined>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A string that changes only when a loop's membership does — the memo key for
|
|
35
|
+
* {@link loopPaint}, so dragging a node does not hand every card a new context value.
|
|
36
|
+
*/
|
|
37
|
+
export declare function loopPaintKey(nodes: readonly StepNode[]): string;
|
|
38
|
+
/** Rebuild the {@link LoopPaint} a {@link loopPaintKey} describes. */
|
|
39
|
+
export declare function loopPaint(key: string): LoopPaint;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowEdge, FlowStep, FlowWorkflow } from './flow-types.ts';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
type UsesLike = {
|
|
5
|
+
uses?: {
|
|
6
|
+
app?: string;
|
|
7
|
+
action?: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
/** A step is a foreach iff it is `@w6w/control` · `foreach` (P1). */
|
|
11
|
+
export declare function isForeachStep(step: UsesLike | undefined): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The step ids a control step owns — engine `controlOwnedIds`, arm for arm
|
|
14
|
+
* (foreach `body`, parallel `branches`, if `then`/`else`; strings at any array depth).
|
|
15
|
+
*/
|
|
16
|
+
export declare function controlOwnedIds(step: FlowStep): string[];
|
|
17
|
+
/** Every step id owned by some control step (engine `ownedByControl`). */
|
|
18
|
+
export declare function ownedStepIds(steps: readonly FlowStep[]): Set<string>;
|
|
19
|
+
/** A canvas each-lane edge in the ONE shape load, bridge and `applyConnect` share (P3). */
|
|
20
|
+
export declare function eachLaneEdge(from: string, to: string, fromIsForeach: boolean, route?: string): Edge;
|
|
21
|
+
/**
|
|
22
|
+
* The body drawn from `foreachId`: every step reachable from its Each-item port
|
|
23
|
+
* over each-lane edges, as a topological order (Kahn over the body's own each-lane
|
|
24
|
+
* edges, ties broken by discovery order) so the Each-item target is first and every
|
|
25
|
+
* edge goes from an earlier id to a later one. A plain chain comes out exactly as
|
|
26
|
+
* the chain. Never includes `foreachId` or a repeat — so it terminates on a cycle
|
|
27
|
+
* (steps stuck in one are appended in discovery order). `claimed` (internal) stops
|
|
28
|
+
* the walk BEFORE a step an earlier foreach already owns.
|
|
29
|
+
*/
|
|
30
|
+
export declare function loopBody(foreachId: string, nodes: readonly StepNode[], edges: readonly Edge[], claimed?: ReadonlySet<string>): string[];
|
|
31
|
+
/** The each-lane edges with both ends inside `body` (the For each → body[0] link is not one). */
|
|
32
|
+
export declare function bodyInternalEdges(body: readonly string[], edges: readonly Edge[]): Edge[];
|
|
33
|
+
/**
|
|
34
|
+
* A body is plain iff it is a chain the ordered `with.body` list already says: every
|
|
35
|
+
* body node has at most one outgoing each-lane edge and none carries a route. Plain
|
|
36
|
+
* bodies serialize as the list alone; anything else also emits its body edges.
|
|
37
|
+
*/
|
|
38
|
+
export declare function isPlainBody(body: readonly string[], edges: readonly Edge[]): boolean;
|
|
39
|
+
/** The definition edges a canvas's non-plain loop bodies need (empty for plain chains). */
|
|
40
|
+
export declare function loopBodyDefinitionEdges(nodes: readonly StepNode[], edges: readonly Edge[]): FlowEdge[];
|
|
41
|
+
/** Every foreach's body, handled in `nodes` order so emitted bodies are disjoint (P6). */
|
|
42
|
+
export declare function loopBodies(nodes: readonly StepNode[], edges: readonly Edge[]): Map<string, string[]>;
|
|
43
|
+
/** `bodyStepId → foreachId` over the whole canvas. */
|
|
44
|
+
export declare function loopMembership(nodes: readonly StepNode[], edges: readonly Edge[]): Record<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* The edge set after deleting step `id` (D-A4). A body step with exactly one inbound
|
|
47
|
+
* and one outbound each-lane edge is bridged (`prev → next`, each lane, keeping the
|
|
48
|
+
* inbound edge's route when `prev` is an If/Router, `out-each` iff `prev` is the
|
|
49
|
+
* foreach); any other body step just loses its incident edges; deleting the foreach
|
|
50
|
+
* also removes the each-lane edges of its whole body (the body steps stay, as
|
|
51
|
+
* ordinary unconnected nodes). A non-body step is the plain incident-edge filter.
|
|
52
|
+
*/
|
|
53
|
+
export declare function bridgeDeletedBodyStep(id: string, nodes: readonly StepNode[], edges: readonly Edge[]): Edge[];
|
|
54
|
+
/** `with.body` is the derived view of the each lane — drop it from a foreach (P1); other steps untouched. */
|
|
55
|
+
export declare function stripBody<T extends UsesLike & {
|
|
56
|
+
with?: Record<string, unknown>;
|
|
57
|
+
}>(step: T): T;
|
|
58
|
+
/** Why a connection would break the v1 linear-body rule (exhaustive; see {@link loopRefusal}). */
|
|
59
|
+
export type LoopRefusalReason = "error_lane_in_body" | "outside_inbound" | "loop_cycle" | "already_in_loop" | "control_in_body" | "body_branch" | "body_exit";
|
|
60
|
+
/**
|
|
61
|
+
* The loop rule for drawing `source → target` in `lane` (already promoted: a success
|
|
62
|
+
* connect from a body node arrives as `"each"`). First match wins. Pure; run on the
|
|
63
|
+
* INPUT edges, never a post-eviction set.
|
|
64
|
+
*/
|
|
65
|
+
export declare function loopRefusal(source: string, target: string, lane: "success" | "error" | "each", nodes: StepNode[], edges: Edge[]): LoopRefusalReason | null;
|
|
66
|
+
export declare function loopRefusalMessage(reason: LoopRefusalReason): string;
|
|
67
|
+
/**
|
|
68
|
+
* Set or clear `data.loopOf` from {@link loopMembership}. Same array reference when
|
|
69
|
+
* nothing changed, and the same node object for every unchanged node.
|
|
70
|
+
*/
|
|
71
|
+
export declare function stampLoopOf(nodes: StepNode[], edges: Edge[]): StepNode[];
|
|
72
|
+
/** The delete-confirm text. Byte-identical to the plain message unless a For each owns a body. */
|
|
73
|
+
export declare function deleteStepMessage(id: string, nodes: StepNode[], edges: Edge[]): string;
|
|
74
|
+
export type LoopInvalidReason = "body_not_literal" | "body_unknown_step" | "body_self" | "body_duplicate" | "body_claimed_twice" | "body_contains_control" | "body_step_has_edges" | "legacy_not_linear";
|
|
75
|
+
export type LoopInvalid = {
|
|
76
|
+
reason: LoopInvalidReason;
|
|
77
|
+
stepId?: string;
|
|
78
|
+
};
|
|
79
|
+
export type LoopResult = {
|
|
80
|
+
body: string[];
|
|
81
|
+
source: "body" | "legacy";
|
|
82
|
+
edges?: FlowEdge[];
|
|
83
|
+
} | {
|
|
84
|
+
invalid: LoopInvalid;
|
|
85
|
+
};
|
|
86
|
+
/** The edges the engine would run: declared, else the implicit chain over main-graph (non-owned) steps. */
|
|
87
|
+
export declare function effectiveEdges(wf: FlowWorkflow): FlowEdge[];
|
|
88
|
+
/** A saved For each → `body[0]` link ({@link FOREACH_EACH_ROUTE}); the canvas draws it from `with.body`. */
|
|
89
|
+
export declare const isEachLink: (e: FlowEdge) => boolean;
|
|
90
|
+
/**
|
|
91
|
+
* What each foreach's loop is, in a stored definition — the ONE place that knows
|
|
92
|
+
* the legacy-chain rule (D-A3). A foreach carrying a `body` key is judged on it;
|
|
93
|
+
* one without is a legacy loop iff its success-lane successors form a valid linear
|
|
94
|
+
* chain (every node a non-control step owned by no control, whose only inbound edge
|
|
95
|
+
* is from its predecessor and whose only outbound edge is a success edge onward).
|
|
96
|
+
*/
|
|
97
|
+
export declare function definitionLoops(wf: FlowWorkflow): Record<string, LoopResult>;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FlowStep } from './flow-types.ts';
|
|
2
|
+
export declare const PAUSED_LABEL = "Paused \u2014 test runs stop before this node";
|
|
3
|
+
export declare const DISABLED_LABEL = "Disabled \u2014 skipped in every run";
|
|
4
|
+
export declare function isPausedStep(step: FlowStep): boolean;
|
|
5
|
+
export declare function isDisabledStep(step: FlowStep): boolean;
|
|
6
|
+
/** `step` with `ui.paused` set (on) or removed (off); an emptied `ui` is dropped. */
|
|
7
|
+
export declare function withPaused(step: FlowStep, on: boolean): FlowStep;
|
|
8
|
+
/** `step` with `disabled: true` (on) or without the key (off). */
|
|
9
|
+
export declare function withDisabled(step: FlowStep, on: boolean): FlowStep;
|
|
10
|
+
/**
|
|
11
|
+
* The `stopAt` of a run started from `startId`'s ▶: every paused node except the start itself
|
|
12
|
+
* (pressing ▶ on a paused node runs it — the pause stops runs that ARRIVE at it).
|
|
13
|
+
*/
|
|
14
|
+
export declare function pausedStopAt(steps: readonly FlowStep[], startId: string): string[];
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { LoopRefusalReason } from './flow-loop.ts';
|
|
3
|
+
import { CanvasLane, FlowStep, FlowWorkflowInput } from './flow-types.ts';
|
|
4
|
+
import { StepNode } from './flow-utils.ts';
|
|
5
|
+
import { StepProblem, StepProblems } from './step-problems.ts';
|
|
6
|
+
/**
|
|
7
|
+
* THE matcher: is `ref` a reference to foreach `foreachId`'s output, and what
|
|
8
|
+
* does it become inside the loop. `R.F.output` → `foreach.item`, `R.F.output.<rest>`
|
|
9
|
+
* → `foreach.item.<rest>`, `R.F.output[<rest>` → `foreach.item[<rest>`. Segment
|
|
10
|
+
* boundary only: `…outputs` and `for_each_10` never match.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loopOutputRef(ref: string, foreachId: string): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* The loop problems of a stored definition, keyed by step id. Never throws and
|
|
15
|
+
* never mutates: any input `workflowToFlow` would reject gives `{}` (it runs in a
|
|
16
|
+
* host memo with no error boundary).
|
|
17
|
+
*/
|
|
18
|
+
export declare function findLoopProblems(input: FlowWorkflowInput): StepProblems;
|
|
19
|
+
/** One editor-side parallel-write warning — the engine's `StateWriteWarning`, this code only. */
|
|
20
|
+
export interface StateParallelWrite {
|
|
21
|
+
code: "state_parallel_write";
|
|
22
|
+
nodes: string[];
|
|
23
|
+
path: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The editor mirror of the engine's plan-time parallel-write warning (R16, plan
|
|
27
|
+
* §2.3; proven equal on `core/packages/expr/tests/fixtures/state-write-conflicts.json`).
|
|
28
|
+
* Two writers are concurrent iff they sit in different branches of one
|
|
29
|
+
* `@w6w/control` `parallel`; else never when they share an anchor (outermost
|
|
30
|
+
* owning control, else the step) or one anchor reaches the other; else iff one
|
|
31
|
+
* `fanOut: "parallel"` step has two distinct outgoing edges in the SAME lane
|
|
32
|
+
* whose targets reach the two anchors. Each overlapping pair of static write
|
|
33
|
+
* paths gives one warning on the shorter path; deduped, sorted by the engine's
|
|
34
|
+
* order (`code`, then `nodes`, then `path`). Never throws (→ `[]`), never mutates.
|
|
35
|
+
*/
|
|
36
|
+
export declare function stateWriteConflicts(input: FlowWorkflowInput): StateParallelWrite[];
|
|
37
|
+
/**
|
|
38
|
+
* `stateWriteConflicts` as canvas problems: each warning lands on both of its
|
|
39
|
+
* steps, naming the other one (`with`). Never throws (→ `{}`), never mutates.
|
|
40
|
+
*/
|
|
41
|
+
export declare function findStateWriteProblems(input: FlowWorkflowInput): StepProblems;
|
|
42
|
+
/**
|
|
43
|
+
* Apply a problem's fix to `step`, returning a new step. Re-scans the step it is
|
|
44
|
+
* given (never trusts the problem's `refs` snapshot); the SAME reference comes
|
|
45
|
+
* back for a problem with no fix or nothing left to fix. Never mutates.
|
|
46
|
+
*/
|
|
47
|
+
export declare function applyStepProblemFix(step: FlowStep, problem: StepProblem): FlowStep;
|
|
48
|
+
/**
|
|
49
|
+
* The lane of a drag, read from the handle the pointer went down on. xyflow's
|
|
50
|
+
* `connectionState.fromHandle` resolves an id-less handle (the Done port) to the
|
|
51
|
+
* node's FIRST handle (`out-each`), so it cannot tell Done from Each item;
|
|
52
|
+
* `onConnectStart` reports the real `handleId` (null for Done). Falls back to
|
|
53
|
+
* `fromHandle.id` when no matching start was recorded.
|
|
54
|
+
*/
|
|
55
|
+
export declare function dragLane(start: {
|
|
56
|
+
nodeId: string | null;
|
|
57
|
+
handleId: string | null;
|
|
58
|
+
handleType: string | null;
|
|
59
|
+
} | null, fromNodeId: string, fromHandle: {
|
|
60
|
+
id?: string | null;
|
|
61
|
+
type?: string;
|
|
62
|
+
} | null | undefined): CanvasLane;
|
|
63
|
+
/**
|
|
64
|
+
* The loop reason a source-handle drag dropped ON an existing node is refused for
|
|
65
|
+
* (`null` when the loop rule has nothing to say). `onConnectEnd` shows it as the
|
|
66
|
+
* node-anchored notice instead of opening the step builder. The lane is promoted the
|
|
67
|
+
* way `planConnect` does: a success drag from a body node extends the body.
|
|
68
|
+
*/
|
|
69
|
+
export declare function connectDropRefusal(source: string, target: string, lane: "success" | "error" | "each", nodes: StepNode[], edges: Edge[]): LoopRefusalReason | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StateWriteConfig } from '@w6w/expr';
|
|
2
|
+
import { FlowStep } from './flow-types.ts';
|
|
3
|
+
export type StateMode = StateWriteConfig["mode"];
|
|
4
|
+
/** The five modes, in the order the control lists them. */
|
|
5
|
+
export declare const STATE_MODES: readonly StateMode[];
|
|
6
|
+
export declare const STATE_MODE_LABELS: Record<StateMode, string>;
|
|
7
|
+
type StepLike = Pick<FlowStep, "id" | "uses" | "state">;
|
|
8
|
+
/** What the step writes, the default applied (R14: Set data merges at root, every other step is Off). */
|
|
9
|
+
export declare function stateWriteFor(step: StepLike): StateWriteConfig;
|
|
10
|
+
/**
|
|
11
|
+
* The step with `config` as its state write. The default is the key's ABSENCE
|
|
12
|
+
* (Off on an ordinary step, Merge at root on Set data), so writing the default
|
|
13
|
+
* removes `state`. Never mutates; every other key passes through.
|
|
14
|
+
*/
|
|
15
|
+
export declare function setStateWrite<S extends StepLike>(step: S, config: StateWriteConfig): S;
|
|
16
|
+
/** The config written when the author picks `mode`: named after the step so it is valid at once. */
|
|
17
|
+
export declare function seedStateWrite(step: Pick<FlowStep, "id">, mode: StateMode): StateWriteConfig;
|
|
18
|
+
/** The control shows for app steps and triggers; every control-flow step (If, For each, Parallel, Race) hides it. */
|
|
19
|
+
export declare function stateWriteVisible(step: Pick<FlowStep, "uses">): boolean;
|
|
20
|
+
export {};
|