@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.
Files changed (160) hide show
  1. package/CHANGELOG.md +146 -2
  2. package/README.md +28 -10
  3. package/dist/AppPicker.d.ts +58 -2
  4. package/dist/CanvasContextMenu.d.ts +19 -0
  5. package/dist/CanvasLayer.d.ts +38 -0
  6. package/dist/{CodeBlock-Dot3Pd7P.js → CodeBlock-C-oIIYfC.js} +1436 -555
  7. package/dist/CodeBlock-C-oIIYfC.js.map +1 -0
  8. package/dist/CodeBlock-CymlfyeA.cjs +15 -0
  9. package/dist/CodeBlock-CymlfyeA.cjs.map +1 -0
  10. package/dist/CodeEditor.d.ts +4 -1
  11. package/dist/ConditionEditor.d.ts +11 -0
  12. package/dist/EditConnectionModal.d.ts +6 -1
  13. package/dist/JsonEditor.d.ts +20 -0
  14. package/dist/Markdown.d.ts +25 -0
  15. package/dist/ParamCustomization.d.ts +5 -0
  16. package/dist/ParamsForm.d.ts +18 -4
  17. package/dist/RouterEditor.d.ts +5 -0
  18. package/dist/StepBuilderModal.d.ts +103 -15
  19. package/dist/StepNameEditor.d.ts +11 -0
  20. package/dist/StopEditor.d.ts +5 -0
  21. package/dist/TriggerFillForm.d.ts +14 -1
  22. package/dist/WebhookListenPanel.d.ts +28 -0
  23. package/dist/WorkflowConnections.d.ts +29 -0
  24. package/dist/WorkflowFlowEditor.d.ts +74 -7
  25. package/dist/app-pages.d.ts +2 -0
  26. package/dist/assets/script-completion.worker-DDJKkj5M.js +8290 -0
  27. package/dist/assets/script-completion.worker-DDJKkj5M.js.map +1 -0
  28. package/dist/canvas-context-menu.d.ts +27 -0
  29. package/dist/canvas-types.d.ts +36 -0
  30. package/dist/canvas-utils.d.ts +44 -0
  31. package/dist/code.cjs +1 -1
  32. package/dist/code.mjs +3 -4
  33. package/dist/code.mjs.map +1 -1
  34. package/dist/components/AnchoredFlyout.d.ts +7 -0
  35. package/dist/components/AuthFieldsForm.d.ts +11 -0
  36. package/dist/components/BudgetMeter.d.ts +15 -0
  37. package/dist/components/CallableList.d.ts +3 -2
  38. package/dist/components/ColumnsEditor.d.ts +27 -0
  39. package/dist/components/Combobox.d.ts +19 -1
  40. package/dist/components/ConnectionList.d.ts +2 -3
  41. package/dist/components/CredentialPicker.d.ts +35 -0
  42. package/dist/components/CsvPanel.d.ts +21 -0
  43. package/dist/components/DataEntryEditor.d.ts +38 -0
  44. package/dist/components/DataEntryList.d.ts +33 -0
  45. package/dist/components/DataStoreList.d.ts +33 -0
  46. package/dist/components/DataTable.d.ts +27 -0
  47. package/dist/components/DataTableGrid.d.ts +46 -0
  48. package/dist/components/EmptyState.d.ts +9 -0
  49. package/dist/components/EventbriteTriggerPicker.d.ts +7 -0
  50. package/dist/components/ExecutionDetail.d.ts +17 -1
  51. package/dist/components/ExecutionList.d.ts +19 -1
  52. package/dist/components/ExecutionLogPanel.d.ts +61 -3
  53. package/dist/components/ExpressionEditorModal.d.ts +33 -10
  54. package/dist/components/ExpressionOptions.d.ts +101 -15
  55. package/dist/components/HtmlPreview.d.ts +7 -0
  56. package/dist/components/JsonTree.d.ts +32 -0
  57. package/dist/components/ResolvedParams.d.ts +6 -1
  58. package/dist/components/ResultViewer.d.ts +46 -0
  59. package/dist/components/ScriptBindingsNotice.d.ts +31 -0
  60. package/dist/components/ScriptCodeField.d.ts +13 -0
  61. package/dist/components/StepStatusPill.d.ts +7 -0
  62. package/dist/components/expression-authoring.d.ts +13 -0
  63. package/dist/components/expression-dom.d.ts +17 -2
  64. package/dist/components/expression-template.d.ts +25 -3
  65. package/dist/components/icons.d.ts +1 -1
  66. package/dist/components/json-compose.d.ts +53 -0
  67. package/dist/components/result-format.d.ts +13 -0
  68. package/dist/condition-editor.d.ts +44 -0
  69. package/dist/data-stores/data-store-view.d.ts +371 -0
  70. package/dist/dynamic-fields.d.ts +60 -0
  71. package/dist/editor-theme.d.ts +24 -0
  72. package/dist/eventbrite-trigger-selection.d.ts +13 -0
  73. package/dist/flow-connect.d.ts +22 -16
  74. package/dist/flow-delete.d.ts +16 -0
  75. package/dist/flow-fanout.d.ts +2 -2
  76. package/dist/flow-history.d.ts +75 -0
  77. package/dist/flow-layout.d.ts +13 -0
  78. package/dist/flow-loop-colors.d.ts +39 -0
  79. package/dist/flow-loop.d.ts +98 -0
  80. package/dist/flow-node-flags.d.ts +14 -0
  81. package/dist/flow-problems.d.ts +69 -0
  82. package/dist/flow-state.d.ts +20 -0
  83. package/dist/flow-types.d.ts +155 -10
  84. package/dist/flow-utils.d.ts +33 -12
  85. package/dist/flow.cjs +4 -2
  86. package/dist/flow.cjs.map +1 -1
  87. package/dist/flow.d.ts +15 -2
  88. package/dist/flow.mjs +3737 -1350
  89. package/dist/flow.mjs.map +1 -1
  90. package/dist/index.cjs +2 -1
  91. package/dist/index.cjs.map +1 -1
  92. package/dist/index.d.ts +43 -5
  93. package/dist/index.mjs +2855 -1333
  94. package/dist/index.mjs.map +1 -1
  95. package/dist/node-samples-ChdyMBnJ.cjs +22 -0
  96. package/dist/node-samples-ChdyMBnJ.cjs.map +1 -0
  97. package/dist/node-samples-DkJL07EX.js +12302 -0
  98. package/dist/node-samples-DkJL07EX.js.map +1 -0
  99. package/dist/node-samples.d.ts +80 -0
  100. package/dist/note-markdown.d.ts +22 -0
  101. package/dist/output-shape.d.ts +30 -14
  102. package/dist/param-customization.d.ts +7 -0
  103. package/dist/provider.d.ts +174 -13
  104. package/dist/resolve-params.d.ts +50 -11
  105. package/dist/run-visuals.d.ts +18 -22
  106. package/dist/script-bindings.d.ts +63 -0
  107. package/dist/script-completion-service.d.ts +9 -0
  108. package/dist/script-completion.worker.d.ts +1 -0
  109. package/dist/script-completions.d.ts +2 -0
  110. package/dist/state-shape.d.ts +38 -0
  111. package/dist/step-preview-state.d.ts +155 -6
  112. package/dist/step-problems.d.ts +64 -0
  113. package/dist/test-inputs.d.ts +25 -0
  114. package/dist/trigger-registration.d.ts +28 -0
  115. package/dist/types.d.ts +179 -11
  116. package/dist/use-app-action-defs.d.ts +9 -1
  117. package/dist/use-dynamic-fields.d.ts +23 -0
  118. package/dist/use-test-input.d.ts +18 -0
  119. package/dist/workflow-connections.d.ts +30 -0
  120. package/package.json +18 -7
  121. package/src/code.css +60 -6
  122. package/src/styles/_budget-meter.scss +46 -0
  123. package/src/styles/_callable-list.scss +15 -6
  124. package/src/styles/_canvas.scss +353 -0
  125. package/src/styles/_code-editor.scss +35 -0
  126. package/src/styles/_code.scss +6 -5
  127. package/src/styles/_connections.scss +2 -14
  128. package/src/styles/_copyable.scss +24 -0
  129. package/src/styles/_data-stores.scss +138 -0
  130. package/src/styles/_data-table.scss +55 -0
  131. package/src/styles/_data-vars.scss +17 -6
  132. package/src/styles/_empty-state.scss +21 -0
  133. package/src/styles/_execution-history.scss +73 -0
  134. package/src/styles/_execution-log.scss +145 -1
  135. package/src/styles/_expression-modal.scss +106 -16
  136. package/src/styles/_fields.scss +11 -0
  137. package/src/styles/_flow.scss +171 -0
  138. package/src/styles/_fx.scss +26 -1
  139. package/src/styles/_incoming-state.scss +33 -0
  140. package/src/styles/_layout.scss +10 -0
  141. package/src/styles/_markdown.scss +20 -0
  142. package/src/styles/_modal.scss +12 -0
  143. package/src/styles/_multiselect.scss +35 -0
  144. package/src/styles/_sections.scss +36 -0
  145. package/src/styles/_step-builder.scss +145 -0
  146. package/src/styles/_tester.scss +57 -14
  147. package/src/styles/_tokens.scss +27 -1
  148. package/src/styles.css +1861 -115
  149. package/src/styles.scss +7 -0
  150. package/dist/CodeBlock-CZu4TFSi.cjs +0 -15
  151. package/dist/CodeBlock-CZu4TFSi.cjs.map +0 -1
  152. package/dist/CodeBlock-Dot3Pd7P.js.map +0 -1
  153. package/dist/ConfirmModal-ChoiGy2K.cjs +0 -11
  154. package/dist/ConfirmModal-ChoiGy2K.cjs.map +0 -1
  155. package/dist/ConfirmModal-Wx3i8F1n.js +0 -6359
  156. package/dist/ConfirmModal-Wx3i8F1n.js.map +0 -1
  157. package/dist/Copyable-1niV9gUa.js +0 -771
  158. package/dist/Copyable-1niV9gUa.js.map +0 -1
  159. package/dist/Copyable-CYZU1o4X.cjs +0 -2
  160. package/dist/Copyable-CYZU1o4X.cjs.map +0 -1
@@ -1,3 +1,5 @@
1
+ import { StateWriteConfig } from '@w6w/expr';
2
+ import { FlowCanvas } from './canvas-types.ts';
1
3
  import { EdgeRunState } from './run-visuals.ts';
2
4
  import { ActionParam } from './types.ts';
3
5
  export interface FlowStep {
@@ -6,13 +8,16 @@ export interface FlowStep {
6
8
  app: string;
7
9
  action: string;
8
10
  connection?: string | null;
11
+ connectionRef?: string;
12
+ /** An app TRIGGER node (`action` is the trigger key): behaves like a built-in trigger on the canvas. */
13
+ trigger?: true;
9
14
  };
10
15
  /**
11
16
  * Declared connection-port cardinality for this step (see core
12
17
  * `rfcs/node-types.md` · Ports & cardinality). Omitted fields fall through field-wise to the catalog action, the internal def, then `{ in: 1, out: "many" }`.
13
- * A persisted value wins over the node's default — `in > 1` opts the step into
14
- * accepting multiple inbound edges (e.g. a flow-control aggregator joining
15
- * several upstream branches).
18
+ * A persisted value wins over the node's default. Only `in: 0` binds (no entry
19
+ * port); any `in >= 1` accepts any number of inbound edges (core node-types ·
20
+ * Alternate entries).
16
21
  */
17
22
  ports?: PortsDecl;
18
23
  with?: Record<string, unknown>;
@@ -36,6 +41,8 @@ export interface FlowStep {
36
41
  * runs them one after another.
37
42
  */
38
43
  fanOut?: "sequential" | "parallel";
44
+ /** Write to state (`Node.state`, core/rfcs/workflow.md). Absent = the default: Off, or Merge at root for `@w6w/data` set. */
45
+ state?: StateWriteConfig;
39
46
  /**
40
47
  * Authoring-time canvas coordinate for this step, in this editor's own
41
48
  * coordinate space (core `rfcs/workflow.md` · "Amendment — 2026-07-29:
@@ -59,10 +66,26 @@ export interface FlowStep {
59
66
  x: number;
60
67
  y: number;
61
68
  };
69
+ /**
70
+ * Disabled: skipped in EVERY run, published and triggered included — the node does not
71
+ * execute and its outgoing edges are skipped, so a node that depends only on it does not run
72
+ * either. An engine semantic (mirrors `Node.disabled` in `@w6w/workflow-types`). Written as
73
+ * `true` or absent, never `false`.
74
+ */
75
+ disabled?: true;
76
+ /**
77
+ * Editor-only metadata; the engine ignores it. `paused`: a test run started from a node's ▶
78
+ * stops BEFORE this node (it does not execute). Never affects a published or triggered run.
79
+ * Absent when empty, never `{}`.
80
+ */
81
+ ui?: {
82
+ paused?: true;
83
+ };
62
84
  }
63
85
  export interface FlowEdge {
64
86
  from: string;
65
87
  to: string;
88
+ route?: string;
66
89
  /**
67
90
  * Which outcome of the `from` step this edge carries (core
68
91
  * `rfcs/workflow.md` · "Amendment — 2026-07-29: failure-conditioned edges
@@ -110,7 +133,7 @@ export interface FlowEdge {
110
133
  * leaves the class in place, so `setEdgeWhen` assigns both keys explicitly
111
134
  * rather than spreading.
112
135
  */
113
- export declare function edgeVisuals(when: "success" | "error" | undefined, runState?: EdgeRunState): {
136
+ export declare function edgeVisuals(when: CanvasLane | undefined, runState?: EdgeRunState): {
114
137
  className?: string;
115
138
  label?: string;
116
139
  };
@@ -120,6 +143,25 @@ export declare function edgeVisuals(when: "success" | "error" | undefined, runSt
120
143
  * (D-P2), since no consumer outside this package needs it.
121
144
  */
122
145
  export declare const ERROR_SOURCE_HANDLE = "out-error";
146
+ /**
147
+ * The handle id of a For each's **Each item** exit port. The `each` lane derives
148
+ * `with.body` on save; its link to the first body step is also saved as a
149
+ * {@link FOREACH_EACH_ROUTE} edge so a reader sees which port it leaves.
150
+ */
151
+ export declare const EACH_SOURCE_HANDLE = "out-each";
152
+ /**
153
+ * `Edge.route` of a For each's **Done** port (the engine's `FOREACH_DONE_ROUTE`): the
154
+ * success edge that runs once, after every iteration. An unrouted For each success
155
+ * edge — the shape saved before the port had an id — is read as Done.
156
+ */
157
+ export declare const FOREACH_DONE_ROUTE = "done";
158
+ /** `Edge.route` of a For each's Each item link to `with.body[0]` (engine `FOREACH_EACH_ROUTE`). */
159
+ export declare const FOREACH_EACH_ROUTE = "each";
160
+ /**
161
+ * A lane on the CANVAS. `"each"` is canvas-only (a For each → body-step edge);
162
+ * the persisted {@link FlowEdge}`["when"]` deliberately stays `"success" | "error"`.
163
+ */
164
+ export type CanvasLane = "success" | "error" | "each";
123
165
  /**
124
166
  * The `sourceHandle` a minted/re-laned/loaded edge carries for a given lane —
125
167
  * the inverse of {@link laneForSourceHandle}. `undefined` for `"success"`/
@@ -128,7 +170,7 @@ export declare const ERROR_SOURCE_HANDLE = "out-error";
128
170
  * already-saved workflow's edges implicitly use. An empty string would not do
129
171
  * this — an empty string is a real, if degenerate, handle id.
130
172
  */
131
- export declare function sourceHandleForLane(when: "success" | "error" | undefined): string | undefined;
173
+ export declare function sourceHandleForLane(when: CanvasLane | undefined): string | undefined;
132
174
  /**
133
175
  * The lane a drag started from, read off the handle id React Flow reports.
134
176
  * **The one canonicalisation point** every minting/re-laning site calls
@@ -138,7 +180,7 @@ export declare function sourceHandleForLane(when: "success" | "error" | undefine
138
180
  * `"error"`; everything else — a near-miss id, `null`, `undefined` — is
139
181
  * `"success"`.
140
182
  */
141
- export declare function laneForSourceHandle(handleId: string | null | undefined): "success" | "error";
183
+ export declare function laneForSourceHandle(handleId: string | null | undefined): CanvasLane;
142
184
  export interface FlowWorkflow {
143
185
  manifestVersion: string;
144
186
  id: string;
@@ -151,8 +193,15 @@ export interface FlowWorkflow {
151
193
  required?: boolean;
152
194
  default?: unknown;
153
195
  }>;
154
- steps: FlowStep[];
196
+ /** Starting data (`Workflow.initialState`): a literal JSON object that seeds the run's state tree. */
197
+ initialState?: Record<string, unknown>;
198
+ nodes: FlowStep[];
199
+ connections?: Record<string, {
200
+ app: string;
201
+ connection: string | null;
202
+ }>;
155
203
  edges?: FlowEdge[];
204
+ canvas?: FlowCanvas;
156
205
  /**
157
206
  * Authoring-time presentation and preferences for this workflow (core
158
207
  * `rfcs/workflow.md` · "Amendment — 2026-07-29: authoring presentation
@@ -209,6 +258,15 @@ export interface FlowWorkflow {
209
258
  };
210
259
  };
211
260
  }
261
+ /**
262
+ * What `workflowToFlow` accepts: a definition in either shape — the canonical
263
+ * `nodes[]` or the legacy `steps[]`. Both present is refused at read time.
264
+ */
265
+ export type FlowWorkflowInput = Omit<FlowWorkflow, "nodes"> & ({
266
+ nodes: FlowStep[];
267
+ } | {
268
+ steps: FlowStep[];
269
+ });
212
270
  /** Reserved namespace for internal pseudo-apps. */
213
271
  export declare const INTERNAL_APP_PREFIX = "@w6w/";
214
272
  /** Engine-native flow control (if/foreach/parallel/wait). */
@@ -242,7 +300,13 @@ export declare const CALL_APP = "@w6w/call";
242
300
  */
243
301
  export declare const DOCUMENT_APP = "@w6w/document";
244
302
  /**
245
- * Compile a Handlebars `template` string against a resolved `values` object
303
+ * Call a model through a named route / read a connection's models and
304
+ * allowance. Host node, like {@link DOCUMENT_APP}; the params mirror the
305
+ * `@w6w/model` internal-app manifest (pinned by `model-node-parity.test.ts`).
306
+ */
307
+ export declare const MODEL_APP = "@w6w/model";
308
+ /**
309
+ * Render Handlebars text or JSON string values against a resolved `values` object
246
310
  * (core rfcs/node-types.md · F-3 amendment, "the `@w6w/template` host node").
247
311
  * Host node: `runInternalNode` short-circuits this id before the registry
248
312
  * loads a module — it needs no privileged host resource (no DB, no
@@ -250,6 +314,74 @@ export declare const DOCUMENT_APP = "@w6w/document";
250
314
  * compiles to a JS function, the same risk shape `@w6w/script` has.
251
315
  */
252
316
  export declare const TEMPLATE_APP = "@w6w/template";
317
+ /** Host-run regular-expression operations. */
318
+ export declare const REGEX_APP = "@w6w/regex";
319
+ /**
320
+ * Read, write, count, list and query the entries of a named data store (core
321
+ * rfcs/node-types.md, the `@w6w/store` amendment). Host node, like
322
+ * {@link DOCUMENT_APP}: the run's own account and project are bound host-side, so
323
+ * there is no scope param — a store is addressed by NAME. The params mirror the
324
+ * `@w6w/store` internal-app manifest (pinned by `store-node-parity.test.ts`).
325
+ */
326
+ export declare const STORE_APP = "@w6w/store";
327
+ /** End the whole workflow successfully when its optional condition matches. */
328
+ export declare const STOP_APP = "@w6w/stop";
329
+ export declare const ROUTER_APP = "@w6w/router";
330
+ export declare const RACE_APP = "@w6w/race";
331
+ export declare const RACE_DESCRIPTION = "Continue once with the first arriving path\u2019s output. Later arrivals are ignored for this run. Other paths keep running.";
332
+ export interface RouterRoute {
333
+ id: string;
334
+ label?: string;
335
+ condition?: unknown;
336
+ default?: boolean;
337
+ }
338
+ export declare function routesForStep(step: FlowStep): RouterRoute[];
339
+ export declare const routeHandle: (id: string) => string;
340
+ export declare const routeFromHandle: (handle: string | null | undefined) => string | undefined;
341
+ /** Route ports the Router card's right edge holds at its natural height. */
342
+ export declare const ROUTER_PORTS_AT_BASE_HEIGHT = 3;
343
+ /** Card height (px, border-box) added per route port past the third. */
344
+ export declare const ROUTER_PORT_STEP = 16;
345
+ export interface RouterPort {
346
+ id: string;
347
+ /** Absent for an If's True port: the unnamed handle a route-less edge anchors to. */
348
+ handleId?: string;
349
+ label: string;
350
+ /** Handle position along its edge, as a CSS `top` (right-edge ports only). */
351
+ top?: string;
352
+ }
353
+ /**
354
+ * Where a Router's ports sit (human report, 2026-10-31: "they need to be
355
+ * attached to the router"). Condition routes go on the card's right edge,
356
+ * evenly spaced; the fallback route takes the bottom edge, the slot every
357
+ * other node gives its error port. Up to three right-edge ports fit the
358
+ * card's natural height; each one past that adds a fixed step, so five
359
+ * routes make a slightly taller card. Handle ids stay `route:<id>`, so
360
+ * saved edges keep resolving.
361
+ */
362
+ export interface PortLayout {
363
+ right: RouterPort[];
364
+ bottom?: RouterPort;
365
+ minHeight?: number;
366
+ }
367
+ export declare function routerPortLayout(routes: RouterRoute[]): PortLayout;
368
+ /**
369
+ * `Edge.route` of an If's false branch (the engine's `IF_FALSE_ROUTE`). The true
370
+ * branch is an edge with no route, which is what every If edge saved before the
371
+ * False port existed already is.
372
+ */
373
+ export declare const IF_FALSE_ROUTE = "false";
374
+ export declare function isIfStep(step: FlowStep): boolean;
375
+ /**
376
+ * An If's ports, laid out the way {@link routerPortLayout} lays out a Router's
377
+ * (human report, 2026-10-31: "should not have error, it should have: true port
378
+ * and false port"). True takes the right edge; False takes the bottom edge, the
379
+ * slot every other node gives its error port, so an If has no error port. True
380
+ * keeps the unnamed handle, so saved If edges stay on it; False is `route:false`.
381
+ */
382
+ export declare function ifPortLayout(): PortLayout & {
383
+ bottom: RouterPort;
384
+ };
253
385
  /** True when `app` is a reserved internal pseudo-app id (`@w6w/*`). */
254
386
  export declare function isInternalApp(app: string): boolean;
255
387
  /** True when a node is an engine-native flow-control node (can't run standalone). */
@@ -261,6 +393,16 @@ export declare function isControlApp(app: string): boolean;
261
393
  * and send the filled values as `{ input }` rather than running the raw config.
262
394
  */
263
395
  export declare function isTriggerApp(app: string): boolean;
396
+ /**
397
+ * Whether a step is a trigger NODE: one of the built-in triggers, or an app
398
+ * trigger node (`uses.trigger === true`). Canvas chrome, wiring and editing key
399
+ * on this; {@link isTriggerApp} stays for readers that mean the built-in
400
+ * `@w6w/*` triggers only (a callable workflow's input fields).
401
+ */
402
+ export declare function isTriggerStep(uses: {
403
+ app: string;
404
+ trigger?: true;
405
+ }): boolean;
264
406
  /** A palette entry for an internal node: its id, label, group, and config schema. */
265
407
  export interface InternalNodeDef {
266
408
  app: string;
@@ -272,6 +414,8 @@ export interface InternalNodeDef {
272
414
  * does. Shown wherever an app's name would be.
273
415
  */
274
416
  displayName: string;
417
+ /** Show one app entry in the palette and choose its action in configuration. */
418
+ groupActions?: boolean;
275
419
  group: "trigger" | "control" | "compute" | "request";
276
420
  /**
277
421
  * Inline SVG *inner* markup (paths / circles / polylines) for this primitive's
@@ -286,8 +430,9 @@ export interface InternalNodeDef {
286
430
  */
287
431
  hidden?: boolean;
288
432
  /**
289
- * Connection ports: how many inbound (entry) and outbound (exit) connections
290
- * this node accepts. A port is the ability to receive/emit a connection —
433
+ * Connection ports: whether this node has an entry (`in >= 1` takes any number
434
+ * of inbound edges; `in: 0` takes none) and how many outbound (exit) connections
435
+ * it allows. A port is the ability to receive/emit a connection —
291
436
  * rendered as a React Flow Handle. Defaults to one of each (`{ in: 1, out: 1 }`)
292
437
  * when omitted; a trigger overrides to `{ in: 0, out: 1 }` (nothing flows into
293
438
  * the entry node). Fixed for now — not user-editable.
@@ -1,6 +1,7 @@
1
1
  import { Edge, Node } from '@xyflow/react';
2
- import { FlowEdge, FlowStep, FlowWorkflow } from './flow-types.ts';
2
+ import { CanvasLane, FlowStep, FlowWorkflow, FlowWorkflowInput } from './flow-types.ts';
3
3
  import { RunStatus, StepVisualState } from './run-visuals.ts';
4
+ import { StepProblem } from './step-problems.ts';
4
5
  export interface StepNodeData extends Record<string, unknown> {
5
6
  step: FlowStep;
6
7
  /** True for internal pseudo-app nodes (`@w6w/*`) — rendered as pill cards. */
@@ -21,6 +22,19 @@ export interface StepNodeData extends Record<string, unknown> {
21
22
  * provenance/persistence rules as `stepStatus`.
22
23
  */
23
24
  runStatus?: RunStatus;
25
+ /**
26
+ * Host-supplied problems with this step (a dangling connection, loop problems).
27
+ * Patched in by `WorkflowFlowEditor.tsx`'s `stepProblems` effect — never set
28
+ * here, absent (never `[]`) when there are none, and never read by {@link flowToWorkflow} (not persisted).
29
+ */
30
+ stepProblems?: StepProblem[];
31
+ /**
32
+ * The For each this step is a loop-body member of (canvas-only; derived on load
33
+ * and by the editor, never read by {@link flowToWorkflow}).
34
+ */
35
+ loopOf?: string;
36
+ /** This For each was converted from a legacy (no-`body`) loop on load. Canvas-only. */
37
+ legacyLoop?: boolean;
24
38
  }
25
39
  export type StepNode = Node<StepNodeData>;
26
40
  /**
@@ -39,13 +53,19 @@ export type StepNode = Node<StepNodeData>;
39
53
  * rewrite) in `flow-connect.ts`. A second hand-rolled copy of the template is
40
54
  * exactly how the rename path came to drop the qualifier.
41
55
  */
42
- export declare function flowEdgeId(from: string, to: string, when?: FlowEdge["when"]): string;
56
+ export declare function flowEdgeId(from: string, to: string, when?: CanvasLane, route?: string): string;
43
57
  /**
44
58
  * Why a step id may not be saved from the editor, or `null` when it may. The one
45
59
  * rule here is "no `.`" (a dotted id cannot be addressed by `steps.<id>.output`);
46
60
  * duplicates and the edge-time `->` / `:error` checks are NOT this function's job.
47
61
  */
48
62
  export declare function stepIdError(id: string): string | null;
63
+ /**
64
+ * {@link stepIdError} plus uniqueness: why `id` may not name a node of a graph whose other
65
+ * nodes are `taken`, or `null`. The rename in the step editor and the name in the add flow
66
+ * both validate through this.
67
+ */
68
+ export declare function stepNameError(id: string, taken: Iterable<string>): string | null;
49
69
  /**
50
70
  * The one wording for a refused edge id, shared by both routes into the collision —
51
71
  * drawing a wire whose minted id is taken (`applyConnect` / `connectConflict`) and
@@ -101,6 +121,8 @@ export declare function stepIdError(id: string): string | null;
101
121
  * vague-but-true message beats a confident false one.
102
122
  */
103
123
  export declare function idClashMessage(lead: string, id: string, involved: readonly (string | null | undefined)[]): string;
124
+ /** Read a definition in either shape into the canonical `nodes[]` form. */
125
+ export declare function normalizeInput(input: FlowWorkflowInput): FlowWorkflow;
104
126
  /**
105
127
  * Turn a Workflow into (nodes, edges) with an auto-layout when no positions are
106
128
  * known.
@@ -110,13 +132,10 @@ export declare function idClashMessage(lead: string, id: string, involved: reado
110
132
  * positioned graph mixes the two: positioned steps sit where they were left,
111
133
  * unpositioned ones take their computed slot.
112
134
  *
113
- * `computeLayers` runs over the **whole** graph either way, and the per-column
114
- * row counter advances for every step including positioned ones — so an
115
- * unpositioned step's computed coordinate is a pure function of the graph and
116
- * does not shift depending on which of its neighbours happen to carry a
117
- * coordinate.
135
+ * Layout runs over the whole graph, including positioned steps, so a fallback
136
+ * coordinate does not depend on which neighbours already have saved positions.
118
137
  */
119
- export declare function workflowToFlow(wf: FlowWorkflow): {
138
+ export declare function workflowToFlow(input: FlowWorkflowInput): {
120
139
  nodes: StepNode[];
121
140
  edges: Edge[];
122
141
  };
@@ -128,12 +147,12 @@ export declare function workflowToFlow(wf: FlowWorkflow): {
128
147
  * button acts on **what is currently on the canvas**, including steps added and
129
148
  * wires drawn since the last save.
130
149
  *
131
- * Same {@link computeLayers} and same {@link slotPosition} as {@link
150
+ * Same {@link computePositions} as {@link
132
151
  * workflowToFlow}, so a graph with no stored positions lays out byte-identically
133
152
  * either way (pinned by `flow-utils.test.ts` — "auto-layout agrees with first
134
153
  * open"). The **only** difference is that a stored coordinate does not win here:
135
154
  * overriding hand placement is precisely what the author asked for by clicking.
136
- * That is also why the caller confirms first — there is no undo in studio.
155
+ * The editor records this as one undoable layout change.
137
156
  *
138
157
  * Layering is keyed by **`node.id`**, not `node.data.step.id`: React Flow's
139
158
  * `edge.source`/`edge.target` name node ids, so keying by anything else would
@@ -163,7 +182,7 @@ export declare function relayoutNodes(nodes: StepNode[], edges: Edge[]): StepNod
163
182
  * intended — **a workflow that has never been saved by this editor starts
164
183
  * carrying `position` on every step the first time it is saved.**
165
184
  */
166
- export declare function flowToWorkflow(original: FlowWorkflow, nodes: StepNode[], edges: Edge[]): FlowWorkflow;
185
+ export declare function flowToWorkflow(originalInput: FlowWorkflowInput, nodes: StepNode[], edges: Edge[]): FlowWorkflow;
167
186
  /** The workflow's stored camera, as `settings.viewport` declares it. */
168
187
  type StoredViewport = NonNullable<NonNullable<FlowWorkflow["settings"]>["viewport"]>;
169
188
  /**
@@ -280,5 +299,7 @@ export declare function stepToJson(step: StepLike): string;
280
299
  * writable: the params-only `JsonEditor`'s `onValidChange` feeds straight back
281
300
  * into `with`/`withValues`, same as it always has.
282
301
  */
283
- export declare function paramsToJson(step: Pick<StepLike, "with">): string;
302
+ export declare function paramsToJson(step: Pick<StepLike, "with"> & {
303
+ uses?: StepLike["uses"];
304
+ }): string;
284
305
  export {};