@w6w/ui 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -2
  4. package/dist/ActionTestForm.d.ts +76 -0
  5. package/dist/AddConnectionModal.d.ts +24 -0
  6. package/dist/AppPicker.d.ts +83 -0
  7. package/dist/CodeBlock-CZu4TFSi.cjs +15 -0
  8. package/dist/CodeBlock-CZu4TFSi.cjs.map +1 -0
  9. package/dist/CodeBlock-Dot3Pd7P.js +2889 -0
  10. package/dist/CodeBlock-Dot3Pd7P.js.map +1 -0
  11. package/dist/CodeBlock.d.ts +65 -0
  12. package/dist/CodeEditor.d.ts +42 -0
  13. package/dist/ConfirmModal-8avl9Nv8.cjs +11 -0
  14. package/dist/ConfirmModal-8avl9Nv8.cjs.map +1 -0
  15. package/dist/ConfirmModal-CD-P8mhN.js +6335 -0
  16. package/dist/ConfirmModal-CD-P8mhN.js.map +1 -0
  17. package/dist/Copyable-1niV9gUa.js +771 -0
  18. package/dist/Copyable-1niV9gUa.js.map +1 -0
  19. package/dist/Copyable-CYZU1o4X.cjs +2 -0
  20. package/dist/Copyable-CYZU1o4X.cjs.map +1 -0
  21. package/dist/JsonEditor.d.ts +60 -0
  22. package/dist/NodeConfigForm.d.ts +70 -0
  23. package/dist/ParamsForm.d.ts +56 -0
  24. package/dist/PropertyEntryForm.d.ts +56 -0
  25. package/dist/RetryPolicyFields.d.ts +18 -0
  26. package/dist/StepBuilderModal.d.ts +375 -0
  27. package/dist/TriggerFillForm.d.ts +52 -0
  28. package/dist/WaitEditor.d.ts +6 -0
  29. package/dist/WorkflowFlowEditor.d.ts +119 -0
  30. package/dist/YamlEditor.d.ts +46 -0
  31. package/dist/app-categories.d.ts +38 -0
  32. package/dist/app-pages.d.ts +111 -0
  33. package/dist/code.cjs +2 -0
  34. package/dist/code.cjs.map +1 -0
  35. package/dist/code.d.ts +29 -0
  36. package/dist/code.mjs +8 -0
  37. package/dist/code.mjs.map +1 -0
  38. package/dist/components/ApiCallsPanel.d.ts +41 -0
  39. package/dist/components/AppIcon.d.ts +25 -0
  40. package/dist/components/AuthFieldsForm.d.ts +22 -0
  41. package/dist/components/Combobox.d.ts +24 -0
  42. package/dist/components/ConfirmModal.d.ts +33 -0
  43. package/dist/components/Copyable.d.ts +51 -0
  44. package/dist/components/CopyableText.d.ts +40 -0
  45. package/dist/components/DeleteButton.d.ts +16 -0
  46. package/dist/components/EditButton.d.ts +10 -0
  47. package/dist/components/ExecutionDetail.d.ts +70 -0
  48. package/dist/components/ExecutionFilters.d.ts +59 -0
  49. package/dist/components/ExecutionList.d.ts +60 -0
  50. package/dist/components/ExecutionLogPanel.d.ts +98 -0
  51. package/dist/components/ExecutionStats.d.ts +47 -0
  52. package/dist/components/ExpressionEditorModal.d.ts +42 -0
  53. package/dist/components/ExpressionInput.d.ts +36 -0
  54. package/dist/components/ExpressionOptions.d.ts +185 -0
  55. package/dist/components/HealthStatusPill.d.ts +25 -0
  56. package/dist/components/HistoryTimeline.d.ts +56 -0
  57. package/dist/components/Icon.d.ts +34 -0
  58. package/dist/components/IconButton.d.ts +60 -0
  59. package/dist/components/InfoTip.d.ts +15 -0
  60. package/dist/components/InternalIcon.d.ts +19 -0
  61. package/dist/components/ListItem.d.ts +25 -0
  62. package/dist/components/Modal.d.ts +29 -0
  63. package/dist/components/RepoSyncIndicator.d.ts +29 -0
  64. package/dist/components/ResolvedParams.d.ts +31 -0
  65. package/dist/components/ServerResources.d.ts +47 -0
  66. package/dist/components/StepStatusPill.d.ts +51 -0
  67. package/dist/components/UptimeStrip.d.ts +56 -0
  68. package/dist/components/execution-format.d.ts +24 -0
  69. package/dist/components/expression-dom.d.ts +154 -0
  70. package/dist/components/expression-template.d.ts +86 -0
  71. package/dist/components/history-scale.d.ts +33 -0
  72. package/dist/components/icons.d.ts +41 -0
  73. package/dist/components/resolved-clip.d.ts +42 -0
  74. package/dist/components/server-resources-format.d.ts +68 -0
  75. package/dist/components/server-resources.fixture.d.ts +9 -0
  76. package/dist/components/use-copy.d.ts +14 -0
  77. package/dist/createW6WApi.d.ts +31 -0
  78. package/dist/flow-connect.d.ts +138 -0
  79. package/dist/flow-fanout.d.ts +15 -0
  80. package/dist/flow-types.d.ts +356 -0
  81. package/dist/flow-utils.d.ts +284 -0
  82. package/dist/flow.cjs +3 -0
  83. package/dist/flow.cjs.map +1 -0
  84. package/dist/flow.d.ts +24 -0
  85. package/dist/flow.mjs +1978 -0
  86. package/dist/flow.mjs.map +1 -0
  87. package/dist/index.cjs +2 -0
  88. package/dist/index.cjs.map +1 -0
  89. package/dist/index.d.ts +94 -0
  90. package/dist/index.mjs +1812 -0
  91. package/dist/index.mjs.map +1 -0
  92. package/dist/oauth-popup.d.ts +17 -0
  93. package/dist/output-shape.d.ts +58 -0
  94. package/dist/provider.d.ts +421 -0
  95. package/dist/resolve-params.d.ts +112 -0
  96. package/dist/resolved-json.d.ts +21 -0
  97. package/dist/run-visuals.d.ts +90 -0
  98. package/dist/step-preview-state.d.ts +143 -0
  99. package/dist/theme.d.ts +32 -0
  100. package/dist/trigger-fields.d.ts +56 -0
  101. package/dist/types.d.ts +413 -0
  102. package/dist/use-app-action-defs.d.ts +7 -0
  103. package/dist/use-enter-submit.d.ts +23 -0
  104. package/dist/use-seed-sources.d.ts +16 -0
  105. package/package.json +112 -3
  106. package/src/code.css +561 -0
  107. package/src/styles/_buttons.scss +38 -0
  108. package/src/styles/_chips.scss +210 -0
  109. package/src/styles/_code.scss +139 -0
  110. package/src/styles/_copyable.scss +147 -0
  111. package/src/styles/_data-vars.scss +38 -0
  112. package/src/styles/_execution-history.scss +282 -0
  113. package/src/styles/_execution-log.scss +178 -0
  114. package/src/styles/_expression-field.scss +65 -0
  115. package/src/styles/_expression-inline.scss +63 -0
  116. package/src/styles/_expression-modal.scss +292 -0
  117. package/src/styles/_fields.scss +161 -0
  118. package/src/styles/_flow.scss +217 -0
  119. package/src/styles/_fx.scss +158 -0
  120. package/src/styles/_health.scss +46 -0
  121. package/src/styles/_history-timeline.scss +156 -0
  122. package/src/styles/_icon-button.scss +22 -0
  123. package/src/styles/_icon.scss +15 -0
  124. package/src/styles/_icons.scss +31 -0
  125. package/src/styles/_incoming-state.scss +46 -0
  126. package/src/styles/_info-tip.scss +9 -0
  127. package/src/styles/_layout.scss +6 -0
  128. package/src/styles/_lists.scss +64 -0
  129. package/src/styles/_modal.scss +125 -0
  130. package/src/styles/_multiselect.scss +69 -0
  131. package/src/styles/_repo-sync-indicator.scss +99 -0
  132. package/src/styles/_scale.scss +70 -0
  133. package/src/styles/_sections.scss +36 -0
  134. package/src/styles/_server-resources.scss +163 -0
  135. package/src/styles/_step-builder.scss +376 -0
  136. package/src/styles/_step-config.scss +195 -0
  137. package/src/styles/_tabs.scss +54 -0
  138. package/src/styles/_tester.scss +111 -0
  139. package/src/styles/_tokens.scss +160 -0
  140. package/src/styles/_uptime.scss +61 -0
  141. package/src/styles.css +4894 -0
  142. package/src/styles.scss +61 -0
@@ -0,0 +1,284 @@
1
+ import { Edge, Node } from '@xyflow/react';
2
+ import { FlowEdge, FlowStep, FlowWorkflow } from './flow-types.ts';
3
+ import { RunStatus, StepVisualState } from './run-visuals.ts';
4
+ export interface StepNodeData extends Record<string, unknown> {
5
+ step: FlowStep;
6
+ /** True for internal pseudo-app nodes (`@w6w/*`) — rendered as pill cards. */
7
+ isInternal: boolean;
8
+ /**
9
+ * This step's status within the run the host is currently showing
10
+ * (T1.1.1). `undefined`/`"no-run"` ⇒ no run, or this canvas isn't showing
11
+ * one. Patched in by `WorkflowFlowEditor.tsx`'s live-run repaint effect —
12
+ * never set here, and never read by {@link flowToWorkflow}, which only
13
+ * ever reads `.step` off a node's `data` (A6 — nothing run-related is
14
+ * persisted).
15
+ */
16
+ stepStatus?: StepVisualState;
17
+ /**
18
+ * The owning run's OWN status, alongside {@link stepStatus} — a node
19
+ * card's visual is a function of BOTH (RunStatus × StepStatus, not
20
+ * StepStatus alone; see `run-visuals.ts`'s `stepNodeVisual`). Same
21
+ * provenance/persistence rules as `stepStatus`.
22
+ */
23
+ runStatus?: RunStatus;
24
+ }
25
+ export type StepNode = Node<StepNodeData>;
26
+ /**
27
+ * The React Flow id for the edge `from → to` in a given lane — **the one place**
28
+ * the id convention lives.
29
+ *
30
+ * A success edge keeps the historic unqualified `from->to` spelling (so no
31
+ * persisted definition changes id when it is reloaded); an error edge is
32
+ * **qualified** with `:error`, because the model permits a success edge AND an
33
+ * error edge between the same pair (core `rfcs/workflow.md` · `Edge.when`
34
+ * amendment; D-T1-8) and two edges sharing one id would be collapsed by React
35
+ * Flow's id-keyed store — silently losing a lane.
36
+ *
37
+ * Every site that mints or rewrites an edge id calls this: {@link workflowToFlow},
38
+ * `applyConnect` (edge creation) and `renameStepInEdges` (the step-rename
39
+ * rewrite) in `flow-connect.ts`. A second hand-rolled copy of the template is
40
+ * exactly how the rename path came to drop the qualifier.
41
+ */
42
+ export declare function flowEdgeId(from: string, to: string, when?: FlowEdge["when"]): string;
43
+ /**
44
+ * Why a step id may not be saved from the editor, or `null` when it may. The one
45
+ * rule here is "no `.`" (a dotted id cannot be addressed by `steps.<id>.output`);
46
+ * duplicates and the edge-time `->` / `:error` checks are NOT this function's job.
47
+ */
48
+ export declare function stepIdError(id: string): string | null;
49
+ /**
50
+ * The one wording for a refused edge id, shared by both routes into the collision —
51
+ * drawing a wire whose minted id is taken (`applyConnect` / `connectConflict`) and
52
+ * re-laning one onto a taken id (`setEdgeWhen` / `edgeWhenConflict`). `lead` names
53
+ * what was refused, `id` is the taken id, and `involved` carries the step ids of the
54
+ * **two edges that mint it**: the new/moving edge's endpoints and the sitting
55
+ * edge's. Rendered inline with `role="alert"`, never in a browser dialog
56
+ * (`.ai/conventions.md`).
57
+ *
58
+ * It lives here, beside {@link flowEdgeId}, for two reasons: the clash *is* a
59
+ * property of that function's non-injectivity over free-text step ids, and this
60
+ * module is JSX-free so `node --test` can pin the wording (it used to sit in
61
+ * `WorkflowFlowEditor.tsx`, where the runner cannot reach it — which is how the
62
+ * wrong advice below shipped uncovered).
63
+ *
64
+ * ⚠️ **The cause is DETERMINED, never asserted.** This message used to hard-code
65
+ * *"because a step id ending in `:error` collides with the error-lane marker.
66
+ * Rename that step"* — and the guard has a second, equally real trigger: a step id
67
+ * containing `->`, the separator itself. With steps `a`, `b->c`, `a->b`, `c` and an
68
+ * edge `a → "b->c"`, drawing `"a->b" → c` is correctly refused (both mint
69
+ * `a->b->c`) while **no step id ends in `:error`** — so the author was told to
70
+ * rename a step that does not exist, and given advice that could not resolve their
71
+ * problem. Inferring the cause from the taken `id` alone does not fix that: an id
72
+ * ending in `:error` may equally be an error-lane edge whose collision came from an
73
+ * embedded `->`. So the culprit is looked up among the ids actually involved, and
74
+ * when none of them is ambiguous the message names **no** cause at all.
75
+ *
76
+ * ## Which of the two triggers it is, is decided by the LANE PAIR
77
+ *
78
+ * Scanning the involved ids for *either* spelling and taking the first match is
79
+ * **not** enough — it names a step whose renaming cannot resolve the clash. Steps
80
+ * `p->q`, `b`, `b:error` with `p->q → b` sitting on the **error** lane and
81
+ * `p->q → "b:error"` drawn on the **success** lane both mint `p->q->b:error`; the
82
+ * first-match scan blames `p->q`, which is the **shared source of both edges**, so
83
+ * renaming it re-mints both and the edge is still refused. The mirror is just as
84
+ * wrong: two **success**-lane edges over steps `x:error`, `y->z`, `x:error->y`, `z`
85
+ * collide with no error lane anywhere, yet get blamed on the error-lane marker.
86
+ *
87
+ * The lane pair decides it, and decides it exactly:
88
+ * - **Same lane on both edges** ⇒ `f1->t1` == `f2->t2` (with the same suffix) forces
89
+ * the two splits to differ, i.e. an **embedded `->`**; it also forces both
90
+ * endpoints to differ (equal sources would force equal targets and vice versa), so
91
+ * renaming *any* involved id re-mints exactly one of the two edges.
92
+ * - **Different lanes** ⇒ `fs->ts` == `fe->te:error`, and since `:error` contains
93
+ * neither `-` nor `>` its 6 characters cannot overlap the separator — so **the
94
+ * success edge's target** ends in `:error`, and that is the step to rename.
95
+ *
96
+ * The lanes are not passed in: they are recovered from `id` itself, which
97
+ * {@link flowEdgeId} is the only minter of, so an endpoint pair spells `id` on at
98
+ * most one lane (`f->t` and `f->t:error` are never equal). A pair that spells it on
99
+ * neither means an already-corrupt edge set — the lane pair then determines nothing
100
+ * and the message names no cause, exactly as when nothing involved is ambiguous. A
101
+ * vague-but-true message beats a confident false one.
102
+ */
103
+ export declare function idClashMessage(lead: string, id: string, involved: readonly (string | null | undefined)[]): string;
104
+ /**
105
+ * Turn a Workflow into (nodes, edges) with an auto-layout when no positions are
106
+ * known.
107
+ *
108
+ * A step's **stored `position` wins** over the computed slot (the amendment's
109
+ * "omitted ⇒ the editor computes a layout" arm, and its converse). A partially
110
+ * positioned graph mixes the two: positioned steps sit where they were left,
111
+ * unpositioned ones take their computed slot.
112
+ *
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.
118
+ */
119
+ export declare function workflowToFlow(wf: FlowWorkflow): {
120
+ nodes: StepNode[];
121
+ edges: Edge[];
122
+ };
123
+ /**
124
+ * Re-flow every node with the same deterministic layering the editor uses on
125
+ * first open — the auto-layout control's whole implementation.
126
+ *
127
+ * Takes React Flow's `(nodes, edges)` rather than a `FlowWorkflow` because the
128
+ * button acts on **what is currently on the canvas**, including steps added and
129
+ * wires drawn since the last save.
130
+ *
131
+ * Same {@link computeLayers} and same {@link slotPosition} as {@link
132
+ * workflowToFlow}, so a graph with no stored positions lays out byte-identically
133
+ * either way (pinned by `flow-utils.test.ts` — "auto-layout agrees with first
134
+ * open"). The **only** difference is that a stored coordinate does not win here:
135
+ * 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.
137
+ *
138
+ * Layering is keyed by **`node.id`**, not `node.data.step.id`: React Flow's
139
+ * `edge.source`/`edge.target` name node ids, so keying by anything else would
140
+ * silently drop every edge from the layering (a `?? 0` fallback puts the whole
141
+ * graph in column 0) if the two ever disagreed.
142
+ *
143
+ * Returns a **new array of new node objects** — React Flow's state handle
144
+ * compares by reference, so a mutated-in-place array does not re-render — with
145
+ * every node's `id`, `type` and `data` carried across untouched (`data` by the
146
+ * same reference, so no node card re-derives its metadata).
147
+ */
148
+ export declare function relayoutNodes(nodes: StepNode[], edges: Edge[]): StepNode[];
149
+ /**
150
+ * Reverse direction: pull the graph state back into a Workflow shape for
151
+ * onChange.
152
+ *
153
+ * Each emitted step carries the **current canvas coordinate** of its node, unless
154
+ * `original.settings.savePosition` is explicitly `false`. The flag is read off
155
+ * the workflow this function already receives — deliberately **not** a new
156
+ * parameter or an options bag, because both exported conversion functions are
157
+ * public `@w6w/ui/flow` API for a partner-facing library and a signature
158
+ * change here would break it for a value the function can already see.
159
+ *
160
+ * ⚠️ **`savePosition` defaults to `true`** (core `rfcs/workflow.md` ·
161
+ * authoring-presentation amendment), so it is read as `!== false`: an absent
162
+ * `settings` object means positions *are* persisted. The practical consequence is
163
+ * intended — **a workflow that has never been saved by this editor starts
164
+ * carrying `position` on every step the first time it is saved.**
165
+ */
166
+ export declare function flowToWorkflow(original: FlowWorkflow, nodes: StepNode[], edges: Edge[]): FlowWorkflow;
167
+ /** The workflow's stored camera, as `settings.viewport` declares it. */
168
+ type StoredViewport = NonNullable<NonNullable<FlowWorkflow["settings"]>["viewport"]>;
169
+ /**
170
+ * The workflow's **stored** camera position, when it has a usable one — the
171
+ * viewport counterpart to {@link storedPosition}, and the single definition of
172
+ * "a viewport this editor will act on". Both the restore-on-open read and
173
+ * {@link withViewport}'s no-op comparison go through it, so they cannot disagree
174
+ * about what counts as stored.
175
+ *
176
+ * All three components are checked with `Number.isFinite` for the same reason
177
+ * `storedPosition` checks two: `settings.viewport` arrives from a persisted JSON
178
+ * document that an author can hand-edit (studio's `</>` raw-JSON modal), and a
179
+ * `null`, a string or a half-written `{ x, y }` would otherwise be handed to
180
+ * React Flow's `defaultViewport` as the initial transform — a `NaN` there blanks
181
+ * the canvas, with no way back except editing the JSON again. Unusable ⇒
182
+ * `undefined`, i.e. "no stored viewport", which falls back to `fitView`.
183
+ *
184
+ * A **fresh object** is returned, never the one hanging off `settings`: React
185
+ * Flow owns the viewport it is given.
186
+ */
187
+ export declare function storedViewport(wf: FlowWorkflow): StoredViewport | undefined;
188
+ /**
189
+ * Record the author's viewport on the workflow (core `rfcs/workflow.md` ·
190
+ * authoring-presentation amendment). Pure, so the two decisions that matter —
191
+ * rounding and no-op detection — are unit-testable without mounting React Flow.
192
+ *
193
+ * Returns `wf` **UNCHANGED (the same reference)** when:
194
+ * - `settings.savePosition` is `false` — read as `!== false`, never `?? false`
195
+ * and never `=== true`: **omitted ⇒ ON**, same as `flowToWorkflow`;
196
+ * - the rounded viewport already equals the stored one;
197
+ * - the incoming viewport is not finite (nothing usable to store).
198
+ *
199
+ * The same-reference return **is** the coalescing guard: the caller emits only
200
+ * when the reference changes, so a pan that lands back where it started emits
201
+ * nothing at all. That matters because the host's auto-save is a trailing
202
+ * debounce over emitted changes — every emission is a candidate network write.
203
+ *
204
+ * Rounding is pinned for that same reason (and mirrors `flowToWorkflow`'s
205
+ * coordinate rounding): `x`/`y` to integers, `zoom` to **3 decimal places**.
206
+ * A trackpad reports the zoom as a long float, so without it two visually
207
+ * identical viewports serialize differently and every idle gesture looks like a
208
+ * change to a payload-comparing auto-save.
209
+ *
210
+ * `settings` is spread, not replaced, so `autoSave` / `savePosition` survive a
211
+ * viewport write — the mirror image of `writeSetting` (studio) deleting a key at
212
+ * its default without disturbing `viewport`. That mirror runs to the **guard on
213
+ * the spread** as well: `settings` is typed as an object here, but it arrives from
214
+ * a `JSON.parse`d document an author can hand-edit (studio's `</>` raw-JSON
215
+ * modal), so `"settings": "hello"` would spread into indexed keys —
216
+ * `{"0":"h","1":"e",…, viewport}` — **on a pan**, and the host's auto-save would
217
+ * re-persist that on a debounce with nobody clicking anything. Anything that is
218
+ * not a plain object therefore reads as "no settings", i.e. the write produces a
219
+ * fresh `{ viewport }`, discarding the unusable value; the predicate is
220
+ * `writeSetting`'s, character for character, so the two really are one rule.
221
+ */
222
+ export declare function withViewport(wf: FlowWorkflow, vp: StoredViewport): FlowWorkflow;
223
+ /**
224
+ * Turn a human-readable label (an action's `label`/`displayName`) into an
225
+ * id-safe slug for {@link suggestStepId}'s `prefix` — human override,
226
+ * 2026-08-30: a step id derived from its OWN action ("data_1",
227
+ * "render_template_1", "manual_trigger_1") orients a reader who never
228
+ * renamed it, unlike the generic "gate_1"/"step_1" every internal/external
229
+ * step used to get regardless of what it actually does. Lowercase,
230
+ * underscore-separated, ASCII word characters only; falls back to `"step"`
231
+ * for a label that slugifies to nothing (empty, or entirely punctuation).
232
+ */
233
+ export declare function slugifyLabel(label: string): string;
234
+ /**
235
+ * The current chain's ROOT: the earliest-added node (array/declaration order)
236
+ * with no incoming edge. `undefined` for an empty graph. Used to give a
237
+ * newly-added TRIGGER a sensible default wire — human override, 2026-08-30 —
238
+ * rather than always landing as a floating node. Array order (not position)
239
+ * is the tie-break because it is deterministic and matches "the node that
240
+ * was here first," not wherever the canvas happens to have placed it.
241
+ */
242
+ export declare function findChainRoot(nodes: StepNode[], edges: Edge[]): StepNode | undefined;
243
+ /**
244
+ * The current chain's TAIL: the most-recently-added node (array/declaration
245
+ * order) with no outgoing edge. `undefined` for an empty graph. Used to give
246
+ * a newly-added non-trigger STEP a sensible default wire — the most recently
247
+ * placed branch is the one a user adding steps one at a time is most likely
248
+ * extending.
249
+ */
250
+ export declare function findChainTail(nodes: StepNode[], edges: Edge[]): StepNode | undefined;
251
+ /** Suggest a unique step id given the current graph. */
252
+ export declare function suggestStepId(existing: string[], prefix?: string): string;
253
+ /**
254
+ * A step, or the add-step hosts' in-progress `BuiltStep` (`StepBuilderModal.tsx`)
255
+ * — structurally `FlowStep` minus `id`, which those hosts legitimately have not
256
+ * minted yet (the editor assigns it once the step first joins the graph). Kept
257
+ * structural rather than importing `BuiltStep` so this module stays the
258
+ * dependency-free base every host already imports from, not the other way
259
+ * round.
260
+ */
261
+ export type StepLike = Omit<FlowStep, "id"> & {
262
+ id?: string;
263
+ };
264
+ /**
265
+ * The full-step `<>` view text — every persisted field, `id` included when the
266
+ * caller has one, no more and no less. Core `rfcs/workflow.md`: "A step **is**
267
+ * an Invocation", so this is the whole step, not a derived projection — no
268
+ * `kind` field is added, and nothing here special-cases a trigger's
269
+ * `with.fields`; it is an ordinary declared param living in the same `with`
270
+ * slot every step uses.
271
+ *
272
+ * **Read-only in v1 (D-3)** — a hand-edited `uses`/`id` has no validation path
273
+ * today, so callers must not wire a write-back path from this text. Write
274
+ * access stays on {@link paramsToJson}'s view and the Form view.
275
+ */
276
+ export declare function stepToJson(step: StepLike): string;
277
+ /**
278
+ * The params-only view text — `step.with`, exactly what the `<>` view showed
279
+ * before this task split "the whole step" out from "just its params". Still
280
+ * writable: the params-only `JsonEditor`'s `onValidChange` feeds straight back
281
+ * into `with`/`withValues`, same as it always has.
282
+ */
283
+ export declare function paramsToJson(step: Pick<StepLike, "with">): string;
284
+ export {};
package/dist/flow.cjs ADDED
@@ -0,0 +1,3 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),R=require("@xyflow/react"),i=require("react"),xt=require("react-dom"),n=require("./ConfirmModal-8avl9Nv8.cjs"),de=require("./Copyable-CYZU1o4X.cjs"),tt=220;function bt(t){return t.length<=tt?{text:t,clipped:!1,length:t.length}:{text:t.slice(0,tt).trimEnd(),clipped:!0,length:t.length}}function jt({params:t,values:s,testStartState:r,view:a="props"}){const{sampleValues:d}=n.useExpressionOptions(),u=i.useMemo(()=>n.buildResolveScope(d,r),[d,r]),f=n.flattenParams(t),S=m=>{var l;return s[m]!==void 0?s[m]:(l=f.find(x=>x.key===m))==null?void 0:l.default},N=f.filter(m=>m.type!=="section"&&n.isParamVisible(m,S));if(a==="code"){const m=vt(N,s,u);return e.jsx("div",{className:"w6w-resolved-params",children:e.jsx(n.JsonEditor,{value:JSON.stringify(m,null,2),onChange:()=>{},readOnly:!0,minHeight:"260px",height:"100%","aria-label":"Resolved test values (JSON)"})})}const v=N.filter(m=>!n.deepEqual(S(m.key),m.default));return N.length===0?e.jsx("div",{className:"w6w-resolved-params",children:e.jsx("p",{className:"w6w-muted w6w-small",children:"This action takes no parameters."})}):v.length===0?e.jsx("div",{className:"w6w-resolved-params",children:e.jsx("p",{className:"w6w-muted w6w-small",children:"Every configured value matches its default — nothing to show here. Switch to JSON to see the full set."})}):e.jsx("div",{className:"w6w-resolved-params w6w-resolved-table",children:v.map(m=>m.type==="vars"?e.jsx(Nt,{param:m,value:s[m.key],scope:u},m.key):e.jsx(St,{label:m.label??m.key,segments:n.resolveParamValue(s[m.key]!==void 0?s[m.key]:m.default,u)},m.key))})}function vt(t,s,r){const a={};for(const d of t)if(d.type==="vars"){const u=Array.isArray(s[d.key])?s[d.key]:Array.isArray(d.default)?d.default:[];a[d.key]=n.resolveVarsJson(u,r)}else a[d.key]=n.resolveParamJson(s[d.key]!==void 0?s[d.key]:d.default,r);return a}function St({label:t,segments:s}){return e.jsxs("div",{className:"w6w-resolved-row",children:[e.jsx("span",{className:"w6w-resolved-label",children:t}),e.jsx("div",{className:"w6w-resolved-value",children:e.jsx(it,{segments:s})})]})}function Nt({param:t,value:s,scope:r}){const a=Array.isArray(s)?s:Array.isArray(t.default)?t.default:[];return e.jsxs("div",{className:"w6w-resolved-row",children:[e.jsx("span",{className:"w6w-resolved-label",children:t.label??t.key}),a.length===0?e.jsx("p",{className:"w6w-muted w6w-small",children:"None configured."}):e.jsx("div",{className:"w6w-stack",children:a.map((d,u)=>e.jsxs("div",{className:"w6w-resolved-value",children:[e.jsx("code",{children:d.key||"(no key)"})," → ",e.jsx(it,{segments:n.resolveParamValue(d.value,r)})]},u))})]})}function it({segments:t}){return e.jsx(e.Fragment,{children:t.map((s,r)=>e.jsx(Ct,{segment:s},r))})}function Ct({segment:t}){switch(t.status){case"resolved":return t.ref?e.jsxs(e.Fragment,{children:[e.jsx(ke,{kind:"var",refName:t.ref}),e.jsx(st,{value:t.value})]}):e.jsx(st,{value:t.value});case"unresolved":return e.jsxs(e.Fragment,{children:[e.jsx(ke,{kind:"var",refName:t.ref}),e.jsx("span",{className:"w6w-param-unresolved",children:"unresolved"})]});case"not-evaluated":return e.jsxs(e.Fragment,{children:[e.jsx(ke,{kind:"expr"}),e.jsx("span",{className:"w6w-param-unevaluated",children:"not evaluated"})]});case"masked":return e.jsx(ke,{kind:"secret",refName:t.ref})}}function st({value:t}){const[s,r]=i.useState(!1),a=kt(t),d=bt(a);return d.clipped?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:s?"w6w-resolved-text-full":void 0,children:s?a:`${d.text}…`}),e.jsx("button",{type:"button",className:"w6w-resolved-more","aria-expanded":s,onClick:()=>r(u=>!u),children:s?"Show less":`Show all (${d.length.toLocaleString()} characters)`})]}):e.jsx("span",{children:a})}const yt={var:"◆",secret:"🔒",expr:"ƒ"};function ke({kind:t,refName:s}){const r=t==="expr"?"expr":n.varLabel(s??"");return e.jsxs("span",{className:`w6w-expr-chip w6w-expr-chip-${t}`,children:[e.jsx("span",{className:"w6w-expr-chip-sigil",children:yt[t]}),e.jsx("span",{className:"w6w-expr-chip-label",children:r})]})}function kt(t){if(t===null)return"null";if(t===void 0)return"(not set)";if(t==="")return'""';if(typeof t=="string"||typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return String(t)}}function Y(t){var s;return((s=t.data)==null?void 0:s.when)==="error"?"error":"success"}function lt(t,s){var r;return((r=t.find(a=>a.id===s))==null?void 0:r.id)??null}function ct(t,s,r,a,d){var v,m;if(!t||!s||t===s||a.some(l=>l.source===t&&l.target===s))return!1;const u=(v=r.find(l=>l.id===t))==null?void 0:v.data.step,f=(m=r.find(l=>l.id===s))==null?void 0:m.data.step;if(!u||!f)return!1;const S=n.nodePortsForStep(u,d),N=n.nodePortsForStep(f,d);return S.out>=1&&N.in>=1}function Le(t,s,r,a,d,u){var T,E;if(!ct(t,s,r,a,u)||!t||!s)return null;const f=(T=r.find(D=>D.id===t))==null?void 0:T.data.step,S=(E=r.find(D=>D.id===s))==null?void 0:E.data.step;if(!f||!S)return null;const N=n.nodePortsForStep(f,u),v=n.nodePortsForStep(S,u);let m=a;if(m.filter(D=>D.source===t&&Y(D)===d).length>=N.out)return{next:a,conflict:null,refusal:{refused:"out_cap",cap:N.out}};const x=m.filter(D=>D.target===s);if(x.length>=v.in){const D=new Set(x.slice(0,x.length-v.in+1).map(p=>p.id));m=m.filter(p=>!D.has(p.id))}const y=n.flowEdgeId(t,s,d);return{next:R.addEdge({source:t,target:s,id:y,sourceHandle:n.sourceHandleForLane(d),data:{when:d},...n.edgeVisuals(d,void 0)},m),conflict:lt(m,y),refusal:null}}function Ee(t,s,r,a,d="success",u){const f=Le(t,s,r,a,d,u);return!f||f.conflict||f.refusal?null:f.next}function Et(t,s,r,a,d="success",u){var f;return((f=Le(t,s,r,a,d,u))==null?void 0:f.conflict)??null}function Pt(t,s,r,a,d="success",u){var f;return((f=Le(t,s,r,a,d,u))==null?void 0:f.refusal)??null}function De(t,s,r,a,d){var T;const u=t.filter(E=>E.id===s);if(u.length!==1)return null;const f=u[0],S=(T=a.find(E=>E.id===f.source))==null?void 0:T.data.step;if(!S)return null;const N=n.nodePortsForStep(S,d).out,v=t.filter(E=>E.id!==s);if((Y(f)===r?[]:v.filter(E=>E.source===f.source&&Y(E)===r)).length>=N)return{next:t,conflict:null,refusal:{refused:"out_cap",cap:N}};const l=n.edgeVisuals(r,void 0),x={...f,id:n.flowEdgeId(f.source,f.target,r),data:{...f.data,when:r},className:l.className,label:l.label,sourceHandle:n.sourceHandleForLane(r)},y=lt(v,x.id);return{next:t.map(E=>E.id===s?x:E),conflict:y,refusal:null}}function At(t,s,r,a,d){const u=De(t,s,r,a,d);return!u||u.conflict||u.refusal?null:u.next}function Tt(t,s,r,a,d){var u;return((u=De(t,s,r,a,d))==null?void 0:u.conflict)??null}function Rt(t,s,r,a,d){var u;return((u=De(t,s,r,a,d))==null?void 0:u.refusal)??null}function It(t,s,r){return t.map(a=>{const d=a.source===s?r:a.source,u=a.target===s?r:a.target;return{...a,source:d,target:u,id:n.flowEdgeId(d,u,Y(a))}})}function Ft(t,s){const r={success:0,error:0};for(const d of s)d.source===t&&r[Y(d)]++;const a=Math.max(r.success,r.error);return{enabled:a>=2,count:a}}function Lt(t,s){const{fanOut:r,...a}=t;return s==="parallel"?{...a,fanOut:"parallel"}:a}function Dt(t,s){return`Runs these ${t} steps in ${s==="parallel"?"parallel":"sequence"}`}const Wt=new Set(["succeeded","failed","canceled"]);function Mt(t,s){var r;return t?((r=t.steps[s])==null?void 0:r.status)??"pending":"no-run"}const nt={borderColor:"var(--w6w-border)",borderStyle:"solid",borderWidth:1,opacity:1};function ut(t,s){const r=s!==void 0&&Wt.has(s);switch(t){case"no-run":return nt;case"pending":return r?{borderColor:"var(--w6w-muted)",borderStyle:"dashed",borderWidth:1,opacity:.5}:{borderColor:"var(--w6w-border)",borderStyle:"dashed",borderWidth:1,opacity:1};case"running":return{borderColor:"var(--w6w-accent)",borderStyle:"solid",borderWidth:2,opacity:1};case"succeeded":return{borderColor:"var(--w6w-success)",borderStyle:"solid",borderWidth:2,opacity:1};case"failed":return{borderColor:"var(--w6w-danger)",borderStyle:"solid",borderWidth:2,opacity:1};case"skipped":return{borderColor:"var(--w6w-muted)",borderStyle:"dashed",borderWidth:1,opacity:.7};default:return nt}}function Vt(t,s,r){if(!t)return;const a=t.steps[s];if(!a)return;const d=r??"success";if(a.status==="succeeded")return d==="success"?"taken":"skipped";if(a.status==="failed")return d==="error"?"taken":"skipped";if(a.status==="skipped")return"skipped"}function Ot(t,s){const[r,a]=i.useState({}),d=i.useRef(new Set),u=JSON.stringify([...new Set(s.map(f=>f.data.step.uses.app))].filter(f=>f&&!n.isInternalApp(f)).sort());return i.useEffect(()=>{const f=JSON.parse(u).filter(S=>!d.current.has(S));if(f.length!==0){for(const S of f)d.current.add(S);Promise.all(f.map(async S=>{try{return[S,await t.getAppActions(S)]}catch{return d.current.delete(S),null}})).then(S=>{const N=S.filter(v=>v!==null);N.length!==0&&a(v=>({...v,...Object.fromEntries(N)}))})}},[t,u]),r}function _t(t){return(s,r)=>{var a,d;return(d=(a=t[s])==null?void 0:a.find(u=>u.key===r))==null?void 0:d.ports}}const Ht="Which outcome of the source step this edge carries. An error edge is drawn by dragging from the step's error exit port; use this control to re-lane an edge already drawn. An error edge overrides the step’s “On error” policy.";function ot(t,s,r,a){const d=t.find(u=>u.id===s);return[r,a,d==null?void 0:d.source,d==null?void 0:d.target]}const We=i.createContext(void 0),Me=i.createContext(new Map);function rt(t){return`Can’t draw that edge: this node allows at most ${t} outgoing edge${t===1?"":"s"} per lane.`}const Ve=i.createContext(new Map),dt=i.createContext(null);function Jt(t){return e.jsx(R.ReactFlowProvider,{children:e.jsx($t,{...t})})}function $t({value:t,onChange:s,readOnly:r,height:a=480,apps:d,exprOptions:u,project:f,runState:S,onTestRun:N,fitViewKey:v}){var Qe,Ze,et;const m=n.useW6WApi(),l=i.useMemo(()=>new Map((d??[]).map(o=>[o.id,o])),[d]),[x,y]=i.useState(null),T=i.useMemo(()=>n.workflowToFlow(t),[t.id]),E=i.useMemo(()=>n.storedViewport(t),[t.id]),D=((Qe=t.settings)==null?void 0:Qe.savePosition)!==!1,[p,I,re]=R.useNodesState(T.nodes),Z=Ot(m,p),M=i.useMemo(()=>_t(Z),[Z]),[b,A,ae]=R.useEdgesState(T.edges);i.useEffect(()=>{I(o=>o.map(c=>{const w=Mt(S,c.id);return c.data.stepStatus===w&&c.data.runStatus===(S==null?void 0:S.status)?c:{...c,data:{...c.data,stepStatus:w,runStatus:S==null?void 0:S.status}}})),A(o=>o.map(c=>{const w=Y(c),g=Vt(S,c.source,w),j=n.edgeVisuals(w,g);return c.className===j.className&&c.label===j.label?c:{...c,className:j.className,label:j.label}}))},[S,I,A]);const[U,q]=i.useState(null),[k,$]=i.useState(null),[V,Q]=i.useState(!1),[O,ee]=i.useState(null),[pe,te]=i.useState("props"),[se,he]=i.useState(null),ie=i.useRef(!1),ve=i.useRef(null),[_,z]=i.useState(null),{screenToFlowPosition:Se,fitView:H}=R.useReactFlow(),Pe=n.useEffectiveTheme();i.useEffect(()=>{I(T.nodes),A(T.edges),q(null),ee(null)},[T,I,A]);const F=i.useCallback((o,c)=>{s(n.flowToWorkflow(t,o,c))},[t,s]),oe=i.useCallback(o=>ct(o.source,o.target,p,b,M),[p,b,M]),ne=i.useCallback(o=>{if(r)return;const c=Ee(o.source,o.target,p,b,n.laneForSourceHandle(o.sourceHandle),M);if(!c){const w=n.laneForSourceHandle(o.sourceHandle),g=Pt(o.source,o.target,p,b,w,M);if(g){const C=b.find(P=>P.source===o.source&&Y(P)===w);C&&(A(b.map(P=>({...P,selected:P.id===C.id}))),$(C.id),W({edgeId:C.id,message:rt(g.cap)}));return}const j=Et(o.source,o.target,p,b,n.laneForSourceHandle(o.sourceHandle));if(!j)return;A(b.map(C=>({...C,selected:C.id===j}))),$(j),W({edgeId:j,message:n.idClashMessage("Can’t draw that edge",j,ot(b,j,o.source,o.target))});return}W(null),A(c),F(p,c)},[b,p,A,F,r,M]),Ae=i.useCallback((o,c)=>{var J,L,G;if(r||c.isValid)return;const w=c.fromNode;if(!w)return;const g=((J=c.fromHandle)==null?void 0:J.type)==="target"?"target":"source",j=(L=p.find(X=>X.id===w.id))==null?void 0:L.data.step;if(j){const X=n.nodePortsForStep(j,M);if((g==="source"?X.out:X.in)<1)return}const C="changedTouches"in o?o.changedTouches[0]:o,P=Se({x:C.clientX,y:C.clientY});z({nodeId:w.id,handleType:g,position:P,lane:n.laneForSourceHandle((G=c.fromHandle)==null?void 0:G.id)}),Q(!0)},[r,Se,p,M]),fe=i.useCallback(o=>{r||he(o)},[r]),Ne=i.useCallback(o=>{if(r)return;const c=p.filter(g=>g.id!==o),w=b.filter(g=>g.source!==o&&g.target!==o);I(c),A(w),U===o&&q(null),O===o&&ee(null),F(c,w)},[p,b,I,A,F,r,U,O]),ge=i.useCallback(()=>{if(r)return;const o=n.relayoutNodes(p,b);I(o),ie.current=!0,F(o,b)},[p,b,I,F,r]),xe=i.useCallback(()=>{r||ge()},[r,ge]);i.useEffect(()=>{ie.current&&(ie.current=!1,H({duration:300}))},[p,H]);const be=i.useRef(v);i.useEffect(()=>{Object.is(be.current,v)||(be.current=v,H({duration:300}))},[v,H]);const[le,W]=i.useState(null),ce=i.useMemo(()=>b.find(o=>o.id===k)??null,[b,k]),Te=i.useCallback(o=>{if(r||!k)return;const c=b.find(P=>P.id===k);if(!c||Y(c)===o)return;const w=Tt(b,k,o,p),g=Rt(b,k,o,p,M),j=w||g?null:At(b,k,o,p,M);if(!j){if(g){W({edgeId:k,message:rt(g.cap)});return}W({edgeId:k,message:w?n.idClashMessage("Can’t switch this edge",w,ot(b,w,c.source,c.target)):"This edge can’t be switched right now."});return}W(null),A(j);const C=j.find(P=>P.source===c.source&&P.target===c.target&&Y(P)===o);$((C==null?void 0:C.id)??null),F(p,j)},[b,p,A,F,r,k,M]),Ce=i.useCallback(o=>{if(r)return;const c=b.filter(w=>w.id!==o);c.length!==b.length&&(A(c),k===o&&$(null),F(p,c))},[p,b,A,F,r,k]),h=i.useCallback(o=>{if(r)return;const c=p.find(P=>P.id===o);if(!c)return;const w=n.suggestStepId(p.map(P=>P.id),`${c.data.step.id}_copy`),g={...structuredClone(c.data.step),id:w},j={id:w,type:c.type,position:{x:c.position.x+40,y:c.position.y+60},data:{step:g,isInternal:c.data.isInternal}},C=[...p,j];I(C),q(w),F(C,b)},[p,b,I,F,r]),B=i.useCallback(o=>{if(r)return;const c=n.isInternalApp(o.uses.app),w=n.suggestStepId(p.map(J=>J.id),n.slugifyLabel(n.internalNodeLabel(o.uses.app,o.uses.action))),g={id:w,uses:o.uses,...o.with&&Object.keys(o.with).length>0?{with:o.with}:{}},j={id:w,type:c?"control":"step",position:(_==null?void 0:_.position)??{x:80,y:80+p.length*24},data:{step:g,isInternal:c}},C=[...p,j];let P=b;if(_){const[J,L]=_.handleType==="target"?[w,_.nodeId]:[_.nodeId,w];P=Ee(J,L,C,b,_.lane,M)??b}else{const J=p.find(L=>n.isTriggerApp(L.data.step.uses.app));if(n.isTriggerApp(o.uses.app)){if(!J){const L=n.findChainRoot(p,b);L&&(P=Ee(w,L.id,C,b,"success",M)??b)}}else{const G=(J&&!b.some(X=>X.source===J.id)?J:void 0)??n.findChainTail(p,b);G&&(P=Ee(G.id,w,C,b,"success",M)??b)}}return I(C),P!==b&&A(P),q(w),F(C,P),w},[p,b,I,A,F,r,_,M]),K=i.useCallback((o,c)=>{const w=c.id!==o;if(w&&p.some(j=>j.id===c.id))return;const g=p.map(j=>j.id===o?{...j,id:c.id,data:{step:c,isInternal:n.isInternalApp(c.uses.app)}}:j);if(w){const j=It(b,o,c.id);I(g),A(j),U===o&&q(c.id),O===o&&ee(c.id),F(g,j);return}I(g),F(g,b)},[p,b,I,A,U,O,F]),ue=i.useCallback((o,c,w)=>{(async()=>{const g=await m.saveStepTest(t.id,o,c).catch(j=>(console.error("step run fixture save failed",j),null));await m.recordStepTestRun(t.id,o,{stepTestId:(g==null?void 0:g.id)??null,status:w.status,input:c.input,output:w.output,error:w.error,...w.meta?{meta:w.meta}:{}})})().catch(g=>{console.error("step run persist failed",g)})},[m,t.id]),je=i.useCallback(o=>{const c=p.find(w=>w.id===o);!c||n.isControlApp(c.data.step.uses.app)||y({stepId:o,status:"collect"})},[p]),mt=i.useCallback(async(o,c,w)=>{N==null||N();const g=p.find(L=>L.id===o);if(!g)return;const j=g.data.step,C=n.isTriggerApp(j.uses.app),P=C?{input:c}:{...j.with??{},...c},J=C?{input:c,with:c}:{input:c,with:P};y({stepId:o,status:"running"});try{const L=await m.invokeAction(j.uses.app,j.uses.action,P,{...j.uses.connection?{connectionId:j.uses.connection}:{},project:f,...w?{state:w}:{}}),G=L.logs,X=L.meta;y({stepId:o,status:"done",value:L.value,logs:G,...X?{meta:X}:{}}),ue(o,J,{status:"succeeded",output:L.value,...X?{meta:X}:{}})}catch(L){const G=L;y({stepId:o,status:"error",error:G.message??String(L),errorCode:G.code}),ue(o,J,{status:"failed",error:G.message??String(L)})}},[p,m,ue,f,N]),Re=i.useMemo(()=>({onEdit:o=>{te("props"),ee(o)},onEditJson:o=>{te("json"),ee(o)},onRun:je,onDuplicate:h,onDelete:fe,readOnly:r}),[je,h,fe,r]);i.useEffect(()=>{const o=ve.current;if(!o)return;const c=w=>{const g=w.target.closest(".react-flow__node");if(!g)return;const j=g.getAttribute("data-id");j&&(w.stopPropagation(),Re.onEdit(j))};return o.addEventListener("dblclick",c,!0),()=>o.removeEventListener("dblclick",c,!0)},[Re]);const _e=((Ze=p.find(o=>o.id===O))==null?void 0:Ze.data.step)??null,Ie=x?((et=p.find(o=>o.id===x.stepId))==null?void 0:et.data.step)??null:null,Fe=(x==null?void 0:x.status)==="collect"&&!!Ie,ht=i.useMemo(()=>x?n.upstreamStateSources(x.stepId,p,b).steps:[],[x,p,b]),He=i.useMemo(()=>{const o=new Map;for(const c of p)o.set(c.id,Ft(c.id,b).count);return o},[p,b]),gt=i.useMemo(()=>({step:Ut,control:qt}),[]),[ye,Je]=i.useState({}),[$e,Be]=i.useState({}),Ue=i.useMemo(()=>({actionDef:(o,c)=>{var w;return(w=Z[o])==null?void 0:w.find(g=>g.key===c)},testOutputs:ye}),[Z,ye]),[qe,ze]=i.useState(null),we=i.useMemo(()=>{const o=n.upstreamStateSources(O,p,b,Ue);return{...o,steps:n.excludeSelfStep(o.steps,O??qe)}},[O,qe,p,b,Ue]),Ke=JSON.stringify(we.steps.map(o=>o.id));i.useEffect(()=>{const o=JSON.parse(Ke);if(!O||o.length===0){Je({}),Be({});return}let c=!1;return Promise.all(o.map(async w=>{try{const g=await m.listStepTests(t.id,w),j=g.length?g[g.length-1]:null;return j?{id:w,output:j.lastRunOutput,meta:j.lastRunMeta}:null}catch{return null}})).then(w=>{if(c)return;const g={},j={};for(const C of w)C!=null&&C.meta&&(j[C.id]=C.meta),!(!C||C.output===void 0||C.output===null)&&(g[C.id]=C.output);Je(g),Be(j)}),()=>{c=!0}},[m,t.id,O,Ke]);const Ge=i.useMemo(()=>{const o={};for(const c of we.steps){Object.assign(o,n.stepMetaSampleValues(c.id,$e[c.id]));const w=ye[c.id];if(w!==void 0){if(o[`steps.${c.id}.output`]=w,typeof w=="object"&&w!==null&&!Array.isArray(w))for(const[g,j]of Object.entries(w))o[`steps.${c.id}.output.${g}`]=j;for(const g of c.outputs??[]){if(!g.path||!g.key.includes("."))continue;const j=n.valueAtPath(w,g.key);j!==void 0&&(o[`steps.${c.id}.output.${g.key}`]=j)}}}return o},[we.steps,ye,$e]),Xe=n.useExpressionOptions(),Ye=i.useMemo(()=>({...u??{},steps:we.steps,hasTrigger:we.hasTrigger,sampleValues:{...Xe.sampleValues??{},...(u==null?void 0:u.sampleValues)??{},...Ge}}),[u,Xe.sampleValues,we,Ge]);return e.jsx(dt.Provider,{value:Re,children:e.jsx(We.Provider,{value:M,children:e.jsx(Me.Provider,{value:He,children:e.jsx(Ve.Provider,{value:l,children:e.jsx(n.WorkflowProjectProvider,{project:f,children:e.jsx(n.ExpressionOptionsProvider,{value:Ye,children:e.jsxs("div",{ref:ve,className:"w6w-flow",style:{width:"100%",height:a,position:"relative"},onKeyDown:o=>{if(o.key!=="Backspace"&&o.key!=="Delete"||O||V||!U&&!k)return;const c=o.target;c.isContentEditable||c.tagName==="INPUT"||c.tagName==="TEXTAREA"||c.tagName==="SELECT"||c.closest("dialog, .w6w-modal")!==null||(o.preventDefault(),U?fe(U):k&&Ce(k))},children:[e.jsxs(R.ReactFlow,{nodes:p,edges:b,defaultEdgeOptions:{type:"smoothstep"},connectionLineType:R.ConnectionLineType.SmoothStep,onNodesChange:re,onEdgesChange:ae,onConnect:ne,onConnectEnd:Ae,isValidConnection:oe,onNodeDragStop:()=>{D&&F(p,b)},onMoveEnd:(o,c)=>{if(!o||r)return;const w=n.flowToWorkflow(t,p,b),g=n.withViewport(w,c);g!==w&&s(g)},onSelectionChange:({nodes:o,edges:c})=>{var w,g;q(((w=o[0])==null?void 0:w.id)??null),$(((g=c[0])==null?void 0:g.id)??null)},nodeTypes:gt,nodesDraggable:!r,nodesConnectable:!r,elementsSelectable:!0,...E?{defaultViewport:E}:{fitView:!0},deleteKeyCode:null,colorMode:Pe,proOptions:{hideAttribution:!0},children:[e.jsx(R.Background,{gap:16}),e.jsx(R.Controls,{showInteractive:!1,children:!r&&e.jsx(R.ControlButton,{onClick:xe,title:"Auto-layout — re-flow the graph into columns","aria-label":"Auto-layout the graph",children:e.jsx(de.Icon,{name:"layout"})})}),e.jsx(R.MiniMap,{pannable:!0,zoomable:!0,style:{background:"var(--w6w-panel-2)"}}),!r&&e.jsx(R.Panel,{position:"top-left",children:e.jsx("button",{type:"button",className:"w6w-btn",onClick:()=>Q(!0),children:"+ Step"})}),!r&&ce&&e.jsx(R.Panel,{position:"top-right",children:e.jsxs("div",{className:"w6w-edge-lane",children:[e.jsx("span",{className:"w6w-muted w6w-small",children:"Run on"}),["success","error"].map(o=>e.jsx("button",{type:"button",className:`w6w-btn w6w-btn-sm w6w-btn-ghost${Y(ce)===o?" active":""}`,"aria-pressed":Y(ce)===o,title:Ht,onClick:()=>Te(o),children:o==="success"?"Success":"Error"},o)),(le==null?void 0:le.edgeId)===ce.id&&e.jsx("span",{className:"w6w-edge-lane-err w6w-small",role:"alert",children:le.message})]})})]}),V&&e.jsx(n.StepBuilderModal,{onClose:()=>{Q(!1),z(null),ze(null)},onAdd:o=>{const c=B(o);return c&&ze(c),c},onDraftChange:(o,c)=>K(o,{id:o,...c}),workflowId:t.id,upstreamSteps:n.stepBuilderUpstreamSteps(_,p,b)}),_e&&O&&e.jsx(zt,{workflowId:t.id,step:_e,upstreamSteps:Ye.steps??[],readOnly:r,fanOutCount:He.get(O)??0,initialView:pe,onChange:o=>K(O,o),onClose:()=>ee(null),onTestRun:N}),x&&e.jsxs(n.Modal,{title:`${Fe?"Run step":"Test run"}: ${x.stepId}`,onClose:()=>y(null),children:[Fe&&Ie&&e.jsx(Bt,{workflowId:t.id,step:Ie,upstreamSteps:ht,onCancel:()=>y(null),onRun:(o,c)=>mt(x.stepId,o,c)},x.stepId),!Fe&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"w6w-modal-body",children:[x.status==="running"&&e.jsx("p",{className:"w6w-muted w6w-small",children:"Running…"}),x.status==="error"&&e.jsxs("div",{className:"w6w-result w6w-error",children:[x.errorCode&&e.jsx("div",{className:"w6w-small",style:{opacity:.75,marginBottom:4},children:e.jsx("code",{children:x.errorCode})}),x.error||"The step failed with no error message."]}),x.status==="done"&&e.jsxs("div",{children:[e.jsx("div",{className:"w6w-muted w6w-small",style:{marginBottom:6},children:"Result"}),e.jsx("pre",{className:"w6w-result",style:{whiteSpace:"pre-wrap",maxHeight:360,overflow:"auto",margin:0},children:JSON.stringify(x.value,null,2)}),x.meta&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"w6w-muted w6w-small",style:{margin:"10px 0 6px"},children:"Metadata"}),e.jsx("pre",{className:"w6w-result",style:{whiteSpace:"pre-wrap",maxHeight:360,overflow:"auto",margin:0},children:JSON.stringify(x.meta,null,2)})]})]}),x.logs&&x.logs.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"w6w-muted w6w-small",style:{margin:"10px 0 6px"},children:"Console output"}),e.jsx("pre",{className:"w6w-result",style:{whiteSpace:"pre-wrap",maxHeight:200,overflow:"auto",margin:0},children:x.logs.join(`
2
+ `)})]})]}),e.jsx("div",{className:"w6w-modal-actions",children:e.jsx("button",{type:"button",className:"w6w-btn",onClick:()=>y(null),children:"Close"})})]})]}),se!==null&&e.jsx(n.ConfirmModal,{title:"Delete step",message:`Delete step "${se}"? Its connections are removed too.`,confirmLabel:"Delete",onConfirm:()=>{Ne(se),he(null)},onClose:()=>he(null)})]})})})})})})})}function Oe(t){try{const s=JSON.parse(t);return s&&typeof s=="object"&&!Array.isArray(s)?s:null}catch{return null}}function pt({text:t,onChange:s,seeds:r,readOnly:a}){const d=Oe(t),u=d?Object.keys(d).length:0,f=u>0,[S,N]=i.useState(f);i.useEffect(()=>{f&&N(!0)},[f]);const v=m=>{s(JSON.stringify(m.lastRunOutput??m.input??{},null,2)),N(!0)};return e.jsxs("div",{className:"w6w-field w6w-incoming-state",children:[e.jsx("span",{children:"Incoming state"}),r.length>0&&e.jsx("div",{className:"w6w-seed-picker",children:e.jsx("div",{className:"w6w-seed-chips",children:r.map(m=>e.jsxs("button",{type:"button",className:"w6w-chip w6w-seed-chip",title:`Use ${m.label}'s saved test as the incoming state`,disabled:a,onClick:()=>v(m.test),children:[e.jsx("code",{children:m.label}),m.test.lastRunStatus?e.jsxs("span",{className:"w6w-muted w6w-small",children:[" · ",m.test.lastRunStatus]}):null]},m.stepId))})}),e.jsxs("details",{className:"w6w-state-override",open:S,onToggle:m=>N(m.currentTarget.open),children:[e.jsxs("summary",{children:["Override the incoming state",u>0?` · ${u} key${u===1?"":"s"} set`:""]}),e.jsx("textarea",{rows:3,value:t,readOnly:a,spellCheck:!1,"aria-label":"Incoming state override (JSON)",onChange:m=>s(m.target.value)}),e.jsxs("span",{className:"w6w-hint",children:["JSON merged into the call (e.g. a script's ",e.jsx("code",{children:"input"}),"). Reach for this to test against a state the flow cannot currently produce — a field no upstream step returns yet, or a case you can't reproduce by running the flow."]})]})]})}function Bt({workflowId:t,step:s,upstreamSteps:r,onRun:a,onCancel:d}){const u=n.useW6WApi(),f=n.isTriggerApp(s.uses.app),S=n.isInternalApp(s.uses.app),N=i.useMemo(()=>{var k;return f?n.asFieldDefs((k=s.with)==null?void 0:k.fields):[]},[f,s.with]),v=i.useMemo(()=>f?n.fieldsToParams(N):S?n.internalNodeParams(s.uses.app,s.uses.action):null,[f,S,N,s.uses.app,s.uses.action]),[m,l]=i.useState(null),x=v??m;i.useEffect(()=>{if(v)return;if(!s.uses.app||!s.uses.action){l([]);return}let k=!1;return l(null),u.getAppActions(s.uses.app).then($=>{var V;k||l(((V=$.find(Q=>Q.key===s.uses.action))==null?void 0:V.params)??[])}).catch(()=>!k&&l([])),()=>{k=!0}},[u,v,s.uses.app,s.uses.action]);const[y,T]=i.useState(()=>{var k;return f?n.seedValues(n.asFieldDefs((k=s.with)==null?void 0:k.fields)):{}}),[E,D]=i.useState("{}"),p=n.useSeedSources(t,r,!f),I=n.startStateFromSeeds(p),[re,Z]=i.useState(!1);i.useEffect(()=>{let k=!1;return u.listStepTests(t,s.id).then($=>{if(k)return;const V=$.length?$[$.length-1]:null;f?V!=null&&V.with&&T(Q=>({...Q,...V.with})):V!=null&&V.input&&Object.keys(V.input).length>0&&D(JSON.stringify(V.input,null,2)),Z(!0)}).catch(()=>{k||Z(!0)}),()=>{k=!0}},[u,t,s.id,f]);const[M,b]=i.useState(!0),A=Oe(E),ae=f?M:A!==null,U=f?y:{...s.with??{},...A??{}},q=!!x&&re&&ae&&n.requiredParamsFilled(x,U);return e.jsxs("div",{className:"w6w-stepconfig",children:[e.jsx("div",{className:"w6w-modal-body",children:e.jsx("div",{className:"w6w-stack",children:x===null||!re?e.jsx("p",{className:"w6w-muted w6w-small",children:x===null?"Loading parameters…":"Loading saved values…"}):f?e.jsxs(e.Fragment,{children:[e.jsx(n.PropertyEntryForm,{params:x,values:y,onChange:T,onValidityChange:b}),x.length===0&&e.jsxs("span",{className:"w6w-hint",children:["This trigger declares no fields — provide a sample payload to run with. It becomes the trigger's output state (",e.jsx("code",{children:"input"}),")."]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"w6w-muted w6w-small",children:["Runs ",e.jsx("code",{children:s.uses.action})," with the configuration saved on this step — only the incoming state changes per run. Edit the step to change how it is configured."]}),e.jsx(pt,{text:E,onChange:D,seeds:p})]})})}),e.jsxs("div",{className:"w6w-modal-actions",children:[e.jsx("button",{type:"button",className:"w6w-btn w6w-btn-ghost",onClick:d,children:"Cancel"}),!q&&x!==null&&re&&e.jsx("span",{className:"w6w-muted w6w-small",children:ae?f?"Fill the required fields to test.":"This step is missing required configuration — set it on the Configure tab.":f?"The payload must be a JSON object to run.":"The incoming state must be a JSON object to run."}),e.jsx("button",{type:"button",className:"w6w-btn",disabled:!q,onClick:()=>a(f?y:A??{},f?void 0:I),children:"▶ Run"})]})]})}function me({type:t,position:s,multiple:r,id:a,variant:d}){return e.jsx(R.Handle,{type:t,position:s,id:a,className:d==="error"?"w6w-handle-error":r?"w6w-handle-multi":void 0,style:r?{height:22,borderRadius:3,width:8}:void 0,title:d==="error"?"On error — drag to route this step's failure separately":r?t==="target"?"Accepts multiple incoming connections":"Multiple outgoing connections":void 0})}function ft({id:t,runnable:s}){const r=i.useContext(dt);return!r||r.readOnly?null:e.jsxs(R.NodeToolbar,{position:R.Position.Top,className:"w6w-node-toolbar",children:[s&&e.jsx("button",{type:"button",className:"w6w-node-toolbar-btn",title:"Test-run this step","aria-label":"Test-run this step",onClick:()=>r.onRun(t),children:e.jsx(de.Icon,{name:"run",size:15})}),e.jsx("button",{type:"button",className:"w6w-node-toolbar-btn",title:"Edit","aria-label":"Edit step",onClick:()=>r.onEdit(t),children:e.jsx(de.Icon,{name:"edit",size:15})}),e.jsx("button",{type:"button",className:"w6w-node-toolbar-btn",title:"Duplicate","aria-label":"Duplicate step",onClick:()=>r.onDuplicate(t),children:e.jsx(de.Icon,{name:"copy",size:15})}),e.jsx("button",{type:"button",className:"w6w-node-toolbar-btn danger",title:"Delete","aria-label":"Delete step",onClick:()=>r.onDelete(t),children:e.jsx(de.Icon,{name:"trash",size:15})})]})}function wt({step:t,count:s}){if(s<2)return null;const r=t.fanOut==="parallel",a=Dt(s,r?"parallel":"sequential");return e.jsxs("div",{className:"w6w-fanout-badge",role:"img","aria-label":a,title:a,children:[e.jsx("span",{"aria-hidden":"true",children:r?"⇉":"→"})," ",s]})}function Ut({id:t,data:s,selected:r}){const a=s.step,u=i.useContext(Ve).get(a.uses.app),f=(u==null?void 0:u.displayName)||a.uses.app||"—",S=n.nodePortsForStep(a,i.useContext(We)),N=ut(s.stepStatus??"no-run",s.runStatus),v=e.jsx(wt,{step:a,count:i.useContext(Me).get(t)??0});return e.jsxs("div",{children:[e.jsx(ft,{id:t,runnable:!0}),e.jsxs("div",{"data-run-status":s.stepStatus??"no-run",style:{position:"relative",border:`${N.borderWidth}px ${N.borderStyle} ${r?"var(--w6w-accent)":N.borderColor}`,opacity:r?1:N.opacity,background:"var(--w6w-panel)",color:"var(--w6w-text)",borderRadius:4,padding:"8px 12px",minWidth:180,fontSize:13,display:"flex",alignItems:"center",gap:10},children:[S.in>0&&e.jsx(me,{type:"target",position:R.Position.Left,multiple:S.in>1}),e.jsx(n.AppIcon,{src:u==null?void 0:u.iconSvg,srcDark:u==null?void 0:u.iconSvgDark,brandColor:u==null?void 0:u.brandColor,name:f,size:28}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("div",{style:{fontWeight:600},children:f}),e.jsx("div",{className:"w6w-muted w6w-small",style:{marginTop:2},children:e.jsx("code",{children:a.uses.action||"—"})})]}),S.out>0&&e.jsxs(e.Fragment,{children:[e.jsx(me,{type:"source",position:R.Position.Right,multiple:S.out>1}),e.jsx(me,{type:"source",position:R.Position.Bottom,multiple:!1,id:n.ERROR_SOURCE_HANDLE,variant:"error"})]})]}),v,e.jsxs("div",{className:"w6w-muted",style:{marginTop:3,fontSize:10,opacity:.75,paddingLeft:2},children:[a.id,u!=null&&u.version?` - v${u.version}`:""]}),a.notes&&e.jsx("div",{className:"w6w-muted w6w-node-notes",title:a.notes,children:a.notes})]})}function qt({id:t,data:s,selected:r}){const a=s.step,d=n.internalNodeLabel(a.uses.app,a.uses.action),u=n.internalNodeIcon(a.uses.app,a.uses.action),f=n.nodePortsForStep(a,i.useContext(We)),S=n.isTriggerApp(a.uses.app),N=ut(s.stepStatus??"no-run",s.runStatus),v=e.jsx(wt,{step:a,count:i.useContext(Me).get(t)??0});return e.jsxs("div",{children:[e.jsx(ft,{id:t,runnable:!n.isControlApp(a.uses.app)}),e.jsxs("div",{"data-run-status":s.stepStatus??"no-run",style:{position:"relative",border:`${N.borderWidth}px ${N.borderStyle} ${r?"var(--w6w-accent)":N.borderColor}`,opacity:r?1:N.opacity,background:"var(--w6w-panel-2)",color:"var(--w6w-text)",borderRadius:4,padding:"6px 14px 6px 8px",minWidth:140,fontSize:13,display:"flex",alignItems:"center",gap:10},children:[f.in>0&&e.jsx(me,{type:"target",position:R.Position.Left,multiple:f.in>1}),u&&e.jsx(n.InternalIcon,{icon:u}),e.jsxs("div",{style:{minWidth:0,textAlign:"left"},children:[e.jsx("div",{style:{fontWeight:600},children:d}),e.jsx("div",{className:"w6w-muted w6w-small",style:{marginTop:2},children:e.jsx("code",{children:a.uses.action||"—"})})]}),f.out>0&&e.jsxs(e.Fragment,{children:[e.jsx(me,{type:"source",position:R.Position.Right,multiple:f.out>1}),!S&&e.jsx(me,{type:"source",position:R.Position.Bottom,multiple:!1,id:n.ERROR_SOURCE_HANDLE,variant:"error"})]})]}),v,e.jsx("div",{className:"w6w-muted",style:{marginTop:3,fontSize:10,opacity:.75,paddingLeft:2},children:a.id}),a.notes&&e.jsx("div",{className:"w6w-muted w6w-node-notes",title:a.notes,children:a.notes})]})}function zt({workflowId:t,step:s,upstreamSteps:r,onChange:a,onClose:d,readOnly:u,initialView:f="props",fanOutCount:S=0,onTestRun:N}){var Ce;const v=n.useW6WApi(),m=i.useContext(Ve),[l,x]=i.useState(s),[y,T]=i.useState("configure"),[E,D]=i.useState(f==="json"?"code":f==="settings"?"config":"props"),[p,I]=i.useState("props"),[re,Z]=i.useState(()=>n.stepToJson(s)),[M,b]=i.useState(()=>n.paramsToJson(s)),[A,ae]=i.useState("{}"),U=i.useRef(null),[q,k]=i.useState(!1),[$,V]=i.useState(!1),[Q,O]=i.useState(l.id),[ee,pe]=i.useState(null),[te,se]=i.useState(null),[he,ie]=i.useState(null),[ve,_]=i.useState(null),z=n.isInternalApp(l.uses.app);i.useEffect(()=>{if(z){se(n.internalNodeParams(l.uses.app,l.uses.action)),ie(null);return}if(!l.uses.app){ie(null),se([]);return}let h=!1;return se(null),v.getAppActions(l.uses.app).then(B=>{var K;h||(ie(B),se(l.uses.action?((K=B.find(ue=>ue.key===l.uses.action))==null?void 0:K.params)??[]:[]))}).catch(()=>!h&&se([])),()=>{h=!0}},[v,l.uses.app,l.uses.action,z]);const Se=i.useCallback(()=>{z||!l.uses.app||v.listConnectionsForApp(l.uses.app).then(h=>_(h)).catch(()=>_([]))},[v,l.uses.app,z]);i.useEffect(()=>{if(z||!l.uses.app)return;let h=!1;return v.listConnectionsForApp(l.uses.app).then(B=>!h&&_(B)).catch(()=>!h&&_([])),()=>{h=!0}},[v,l.uses.app,z]);const H=i.useCallback(h=>{x(h),a(h)},[a]),Pe=h=>{h==="code"?Z(n.stepToJson(l)):h==="params-code"&&b(n.paramsToJson(l)),D(h)},F=()=>{const h=Q.trim(),B=h&&h!==l.id?n.stepIdError(h):null;if(B){pe(B);return}h&&h!==l.id&&H({...l,id:h}),pe(null),V(!1)},oe=!!l.uses.app&&!!l.uses.action&&!n.isControlApp(l.uses.app),ne=n.isTriggerApp(l.uses.app),Ae=y==="test"&&oe&&!ne,fe=n.useSeedSources(t,r,oe&&!ne),Ne=n.startStateFromSeeds(fe);i.useEffect(()=>{if(!oe||ne)return;let h=!1;return v.listStepTests(t,l.id).then(B=>{if(h)return;const K=B.length?B[B.length-1]:null;if(!(K!=null&&K.input)||Object.keys(K.input).length===0)return;const ue=JSON.stringify(K.input,null,2);ae(je=>je.trim()==="{}"?ue:je)}).catch(()=>{}),()=>{h=!0}},[v,t,l.id,oe,ne]);const ge=Oe(A),xe={...l.with??{},...ge??{}},be=ge??{},le=!!te&&n.requiredParamsFilled(te,xe),W=m.get(l.uses.app),ce=z?n.internalNodeIcon(l.uses.app,l.uses.action):null,Te=z?ce?e.jsx(n.InternalIcon,{icon:ce}):null:e.jsx(n.AppIcon,{src:W==null?void 0:W.iconSvg,srcDark:W==null?void 0:W.iconSvgDark,brandColor:W==null?void 0:W.brandColor,name:W==null?void 0:W.displayName});return e.jsx(n.Modal,{ariaLabel:"Edit step",titleIcon:Te,title:e.jsxs("span",{className:"w6w-step-rename",children:[$&&!u?e.jsx("input",{autoFocus:!0,value:Q,onChange:h=>{O(h.target.value),pe(null)},onBlur:F,onKeyDown:h=>{h.key==="Enter"&&F(),h.key==="Escape"&&(O(l.id),pe(null),V(!1))}}):e.jsxs(e.Fragment,{children:[e.jsx("code",{children:l.id}),!u&&e.jsx("button",{type:"button",className:"w6w-icon-btn w6w-btn-sm",title:"Rename step","aria-label":"Rename step",onClick:()=>{O(l.id),V(!0)},children:e.jsx(de.Icon,{name:"edit",size:15})})]}),ee&&e.jsx("span",{className:"w6w-hint",role:"alert",style:{color:"var(--w6w-danger)"},children:ee})]}),onClose:d,size:"wide",children:e.jsxs("div",{className:"w6w-stepconfig",children:[e.jsxs("div",{className:"w6w-tabsbar",children:[e.jsx("div",{className:"w6w-subtabs",children:["setup","configure","test"].map(h=>e.jsx("button",{type:"button",className:`w6w-subtab${y===h?" active":""}`,onClick:()=>T(h),children:h==="setup"?"Setup":h==="configure"?"Configure":"Test"},h))}),Ae?e.jsx(n.ConfigViewToggle,{view:p,views:["props","code"],onChange:h=>I(h)}):e.jsx(n.ConfigViewToggle,{view:E,onChange:Pe,disabled:y!=="configure"})]}),e.jsxs("div",{className:"w6w-stepconfig-body",children:[y==="setup"&&e.jsx(Yt,{step:l,app:W,actions:he,conns:ve,isInternal:z,readOnly:u,onChangeAction:h=>H({...l,uses:{...l.uses,action:h},with:{}}),onChangeConnection:h=>H({...l,uses:{...l.uses,connection:h}}),onConnectionCreated:Se,onChangeApp:h=>H(h===l.uses.app?l:{...l,uses:{app:h,action:"",connection:void 0},with:{}})}),y==="configure"&&e.jsxs(e.Fragment,{children:[l.uses.app===n.WEBHOOK_APP&&v.listSubscriptionsForWorkflow&&v.createSubscription&&e.jsx(Xt,{workflowId:t,step:l,readOnly:u}),te===null?e.jsx("p",{className:"w6w-muted w6w-small",children:"Loading parameters…"}):E==="props"?l.uses.action==="wait"&&n.isControlApp(l.uses.app)?e.jsx(n.WaitEditor,{values:l.with??{},readOnly:u,onChange:h=>H({...l,with:h})}):e.jsx(n.ParamsForm,{params:te,values:l.with??{},readOnly:u,onChange:h=>H({...l,with:h})}):E==="code"?e.jsx(n.JsonEditor,{value:re,onChange:()=>{},readOnly:!0,minHeight:"260px",height:"100%","aria-label":`Step ${l.id} JSON`,copyable:!0}):E==="params-code"?e.jsx(n.JsonEditor,{value:M,onChange:b,readOnly:u,minHeight:"260px",height:"100%","aria-label":`Step ${l.id} params JSON`,copyable:!0,onValidChange:h=>h&&typeof h=="object"&&!Array.isArray(h)&&H({...l,with:h})}):e.jsxs("div",{className:"w6w-stack",children:[e.jsx(n.NodeConfigForm,{config:{retry:l.retry,onError:l.onError,notes:l.notes},onChange:h=>H({...l,...h}),readOnly:u,failureHandling:!ne,retryControls:!n.isControlApp(l.uses.app)&&l.uses.app!==n.CALL_APP}),Kt,e.jsx(Gt,{step:l,count:S,readOnly:u,onChange:H})]})]}),y==="test"&&e.jsx("div",{className:"w6w-stack",children:oe?ne?e.jsx(n.TriggerFillForm,{app:l.uses.app,action:l.uses.action,fields:(Ce=l.with)==null?void 0:Ce.fields,persist:{workflowId:t,stepId:l.id,input:be}}):e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"w6w-muted w6w-small",children:["Tests ",e.jsx("code",{children:l.uses.action})," with the configuration saved on this step — only the incoming state changes per run."]}),e.jsx(pt,{text:A,onChange:ae,seeds:fe,readOnly:u}),te===null?e.jsx("p",{className:"w6w-muted w6w-small",children:"Loading parameters…"}):e.jsx(jt,{params:te,values:xe,testStartState:Ne,view:p}),e.jsx(n.StepTestRun,{ref:U,app:l.uses.app,action:l.uses.action,connectionId:l.uses.connection??void 0,values:xe,state:Ne,canRun:le,hideRunButton:!0,persist:{workflowId:t,stepId:l.id,input:be},onBusyChange:k})]}):e.jsx("p",{className:"w6w-muted w6w-small",children:"Flow-control nodes can't be tested on their own."})})]}),e.jsx("div",{className:"w6w-modal-actions w6w-stepconfig-footer",children:y!=="test"?e.jsx("button",{type:"button",className:"w6w-btn",onClick:()=>T(y==="setup"?"configure":"test"),children:"Next →"}):e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"w6w-btn w6w-btn-ghost",onClick:d,children:"Done"}),oe&&!ne&&e.jsx("button",{type:"button",className:"w6w-btn",disabled:u||!le||q,onClick:()=>{var h;N==null||N(),(h=U.current)==null||h.run()},children:q?"Testing…":"Test"})]})})]})})}const Kt=!1;function Gt({step:t,count:s,readOnly:r,onChange:a}){const d=s>=2,u=t.fanOut==="parallel"?"parallel":"sequential";return e.jsxs("label",{className:"w6w-field",children:[e.jsx("span",{children:"Run next steps"}),e.jsxs("select",{"aria-label":"Run next steps",value:u,disabled:r||!d,onChange:f=>a(Lt(t,f.target.value)),children:[e.jsx("option",{value:"sequential",children:"In sequence"}),e.jsx("option",{value:"parallel",children:"In parallel"})]}),!d&&e.jsx("span",{className:"w6w-muted w6w-small",children:"Connect two or more steps after this one to choose how they run."})]})}function Xt({workflowId:t,step:s,readOnly:r}){const a=n.useW6WApi(),[d,u]=i.useState(void 0),[f,S]=i.useState(null),[N,v]=i.useState(!1);i.useEffect(()=>{const l=a.listSubscriptionsForWorkflow;if(!l)return;let x=!1;return l(t).then(y=>{x||u(y.find(T=>T.appId===n.WEBHOOK_APP)??null)}).catch(y=>!x&&S(y.message)),()=>{x=!0}},[a,t]);const m=()=>{const l=a.createSubscription;l&&(S(null),v(!0),l(n.WEBHOOK_APP,s.uses.action,{workflowId:t,connectionId:null,params:s.with??{}}).then(x=>{v(!1),u(x)}).catch(x=>{v(!1),S(x instanceof Error?x.message:String(x))}))};return e.jsxs("div",{className:"w6w-stack",children:[e.jsxs("p",{className:"w6w-muted w6w-small",children:[e.jsx("strong",{children:"Webhook URL"})," — the address a third party posts to."]}),f&&e.jsx("div",{className:"w6w-result w6w-error",children:f}),d!=null&&d.webhookUrl?e.jsx(de.Copyable,{value:d.webhookUrl,readOnly:!0,children:e.jsx("input",{type:"text",readOnly:!0,value:d.webhookUrl,"aria-label":"Webhook URL"})}):d===void 0?e.jsx("p",{className:"w6w-muted w6w-small",children:"Loading…"}):!r&&e.jsx("button",{type:"button",className:"w6w-btn",disabled:N,onClick:m,children:N?"Creating…":"Create webhook URL"})]})}function at({anchorRef:t,onClose:s,children:r}){const a=i.useRef(null),[d,u]=i.useState(null),[f,S]=i.useState(null);return i.useEffect(()=>{const N=t.current;if(!N)return;const v=N.getBoundingClientRect();u({top:v.bottom+6,left:v.left,width:v.width}),S(N.closest("dialog")??document.body)},[t]),i.useEffect(()=>{function N(m){var x,y;const l=m.target;(x=a.current)!=null&&x.contains(l)||(y=t.current)!=null&&y.contains(l)||s()}function v(m){m.key==="Escape"&&s()}return document.addEventListener("mousedown",N),document.addEventListener("keydown",v),()=>{document.removeEventListener("mousedown",N),document.removeEventListener("keydown",v)}},[s,t]),!d||!f?null:xt.createPortal(e.jsx("div",{ref:a,className:"w6w-flyout",style:{top:d.top,left:d.left,width:d.width},children:r}),f)}function Yt({step:t,app:s,actions:r,conns:a,isInternal:d,readOnly:u,onChangeAction:f,onChangeConnection:S,onChangeApp:N,onConnectionCreated:v}){var D;const[m,l]=i.useState(null),[x,y]=i.useState(!1),T=i.useRef(null),E=t.uses.connection?((D=(a??[]).find(p=>p.id===t.uses.connection))==null?void 0:D.displayName)??t.uses.connection:"No connection";return e.jsxs("div",{className:"w6w-stack",children:[e.jsxs("div",{className:"w6w-field",children:[e.jsx("span",{children:"App"}),e.jsxs("div",{className:"w6w-app-conn-row",ref:T,children:[e.jsxs("button",{type:"button",className:"w6w-app-conn-btn","aria-label":"App","aria-expanded":m==="app",disabled:u,onClick:()=>l(p=>p==="app"?null:"app"),children:[!d&&s&&e.jsx(n.AppIcon,{src:s.iconSvg,srcDark:s.iconSvgDark,brandColor:s.brandColor,name:s.displayName,size:20}),e.jsx("span",{className:"w6w-conn-label-name",children:d?t.uses.app:(s==null?void 0:s.displayName)??t.uses.app})]}),!d&&e.jsx("button",{type:"button",className:"w6w-app-conn-btn","aria-label":"Connection","aria-expanded":m==="conn",disabled:u,onClick:()=>l(p=>p==="conn"?null:"conn"),children:e.jsx("span",{className:"w6w-conn-label-name",children:E})})]}),m==="app"&&e.jsx(at,{anchorRef:T,onClose:()=>l(null),children:e.jsx(n.AppPicker,{onSelectApp:p=>{const I=p.id===t.uses.app;N(p.id),l(I?"conn":null)}})}),m==="conn"&&e.jsx(at,{anchorRef:T,onClose:()=>l(null),children:e.jsxs("div",{className:"w6w-stack",children:[e.jsx("div",{className:"w6w-stepbuilder-list",children:(a??[]).map(p=>e.jsx("button",{type:"button",className:"w6w-stepbuilder-item",onClick:()=>{S(p.id),l(null)},children:e.jsxs("span",{className:"w6w-stepbuilder-item-main",children:[e.jsx("strong",{children:p.displayName||p.id}),p.state&&e.jsx("span",{className:"w6w-muted w6w-small",children:p.state})]})},p.id))}),e.jsx("button",{type:"button",className:"w6w-btn",disabled:u,onClick:()=>{y(!0),l(null)},children:"+ New connection"})]})})]}),!d&&x&&e.jsx(n.AddConnectionModal,{initialAppId:t.uses.app,onClose:()=>y(!1),onCreated:({connectionId:p})=>{y(!1),S(p),v(),l(null)}}),d?e.jsxs("div",{className:"w6w-field",children:[e.jsx("span",{children:"Action"}),e.jsx("div",{className:"w6w-muted w6w-small",children:e.jsx("code",{children:t.uses.action})})]}):e.jsxs("label",{className:"w6w-field",children:[e.jsx("span",{children:"Action"}),e.jsx(n.Combobox,{value:t.uses.action,disabled:u||r===null,onChange:f,options:r===null?[{value:t.uses.action,label:t.uses.action}]:r.map(p=>({value:p.key,label:p.title??p.key}))})]})]})}exports.CALL_APP=n.CALL_APP;exports.CONTROL_APP=n.CONTROL_APP;exports.DATA_APP=n.DATA_APP;exports.ExpressionOptionsProvider=n.ExpressionOptionsProvider;exports.INTERNAL_NODES=n.INTERNAL_NODES;exports.SCHEDULER_APP=n.SCHEDULER_APP;exports.SCRIPT_APP=n.SCRIPT_APP;exports.TRIGGER_APP=n.TRIGGER_APP;exports.WEBHOOK_APP=n.WEBHOOK_APP;exports.asFieldDefs=n.asFieldDefs;exports.coerceDefault=n.coerceDefault;exports.fieldWidget=n.fieldWidget;exports.fieldsToParams=n.fieldsToParams;exports.flowToWorkflow=n.flowToWorkflow;exports.internalNodeDefaults=n.internalNodeDefaults;exports.internalNodeIcon=n.internalNodeIcon;exports.internalNodeLabel=n.internalNodeLabel;exports.internalNodeParams=n.internalNodeParams;exports.isControlApp=n.isControlApp;exports.isInternalApp=n.isInternalApp;exports.isTriggerApp=n.isTriggerApp;exports.seedValues=n.seedValues;exports.workflowToFlow=n.workflowToFlow;exports.WorkflowFlowEditor=Jt;
3
+ //# sourceMappingURL=flow.cjs.map