@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,6 +1,14 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { StepMeta } from '../provider.tsx';
3
- import { StepStatus } from './StepStatusPill.tsx';
3
+ import { SkipReason, StepStatus } from './StepStatusPill.tsx';
4
+ /** What a step is: the app and action it uses, and whether it is a trigger (`uses.trigger`). */
5
+ export interface ExecutionLogNode {
6
+ app: string;
7
+ action: string;
8
+ trigger?: boolean;
9
+ appName?: string;
10
+ actionName?: string;
11
+ }
4
12
  /**
5
13
  * A step's or run's failure, already normalised by the HOST from the workflow
6
14
  * spec's `StepError` (`code`/`message`/`phase`/`retryable`). The panel never
@@ -43,6 +51,12 @@ export interface ExecutionLogStep {
43
51
  /** Human-readable step name. Falls back to `id` when omitted. */
44
52
  label?: string;
45
53
  status: StepStatus;
54
+ /**
55
+ * Why a `skipped` step did not run (`StepExecution.skipReason`). `not_on_path` rows leave the
56
+ * list for the "other paths" footer; the rest show a short reason beside the Skipped pill.
57
+ * Absent (a run recorded before reasons existed) ⇒ a plain Skipped row, as before.
58
+ */
59
+ skipReason?: SkipReason;
46
60
  /** ISO-8601 timestamp the step started, once it has. */
47
61
  startedAt?: string;
48
62
  /** ISO-8601 timestamp the step finished, once it has. */
@@ -51,20 +65,64 @@ export interface ExecutionLogStep {
51
65
  input?: unknown;
52
66
  /** The step's output, once it has one. */
53
67
  output?: unknown;
68
+ /** Captured console output (also present when a script throws). */
69
+ logs?: string[];
54
70
  /**
55
71
  * What ran (`StepExecution.meta`): app, version, action and connection id. Shown as a
56
72
  * Metadata block after Output. Absent or `null` ⇒ no block at all (R-12: no filler).
57
73
  */
58
74
  meta?: StepMeta | null;
75
+ /**
76
+ * What this step IS, from the workflow definition — shown on the row itself so a run reads as
77
+ * "Trigger · Cohost · Order Placed" rather than a bare node id. `appName`/`actionName` are the
78
+ * host's display names for a registered app; a built-in `@w6w/*` node is named here from its
79
+ * own definition, and anything unnamed falls back to the raw id. Absent ⇒ the row shows its
80
+ * label alone, as before.
81
+ */
82
+ node?: ExecutionLogNode;
59
83
  /**
60
84
  * Why the step failed (`StepExecution.error`, "present on failed"). Rendered
61
85
  * below the row's box and outside its lazy `<details>` body, so the reason
62
86
  * reads without expanding the row.
63
87
  */
64
88
  error?: ExecutionLogError;
89
+ /** For each only (I4): the per-iteration body-step records, index ascending. */
90
+ iterations?: ExecutionLogIteration[];
91
+ /** Distinct iteration indices the run recorded (may exceed `iterations.length`). */
92
+ iterationsTotal?: number;
93
+ /** How many of those iterations failed. */
94
+ iterationsFailed?: number;
95
+ /** `true` when `iterations` holds fewer than `iterationsTotal`. */
96
+ iterationsTruncated?: boolean;
97
+ /**
98
+ * The step's state writes (`stateWrites`, the run's state log rows for this step), in write
99
+ * order: `state.<path>: old → new`, or a warning when `warning` is set (a `StateWarningCode`).
100
+ * `item` is the For each item a hoisted body write came from. Absent, `null` or `[]` ⇒ no rows.
101
+ */
102
+ stateWrites?: Array<{
103
+ path: string[];
104
+ item?: number;
105
+ old?: unknown;
106
+ new?: unknown;
107
+ warning?: string;
108
+ }> | null;
109
+ /**
110
+ * The run's state tree after this step, shown as "State after this step" in the State block.
111
+ * Absent or `null` ⇒ not shown; `{}` shows only alongside writes.
112
+ */
113
+ stateAfter?: Record<string, unknown> | null;
114
+ }
115
+ /** One For each iteration: its status and the body-step records, in execution order. */
116
+ export interface ExecutionLogIteration {
117
+ /** 0-based; the same number as `foreach.index` in that iteration's expressions. */
118
+ index: number;
119
+ status: "succeeded" | "failed" | "running";
120
+ /** The body step that failed, when one did. */
121
+ failedNodeId?: string;
122
+ steps: ExecutionLogStep[];
65
123
  }
66
124
  export interface ExecutionLogPanelProps {
67
- /** The run's steps, rendered in exactly this order — never re-sorted. */
125
+ /** Rendered earliest first by start time (finish time as fallback), then untimed steps. */
68
126
  steps: ExecutionLogStep[];
69
127
  /** Shown instead of the list when `steps` is empty. */
70
128
  emptyLabel?: ReactNode;
@@ -88,7 +146,7 @@ export interface ExecutionLogPanelProps {
88
146
  stepErrors?: ExecutionLogRecordedError[];
89
147
  }
90
148
  /**
91
- * Read-only log of a workflow run's steps, in the order given: each row is
149
+ * Read-only log of a workflow run's steps, in ascending execution time: each row is
92
150
  * the step's status pill, its timing, and its resolved input/output.
93
151
  *
94
152
  * A pure display leaf — no data fetching, no polling, no layout media
@@ -24,19 +24,42 @@ export interface ExpressionEditorModalProps {
24
24
  options: ExpressionOptions;
25
25
  /** Field name shown in the modal title. */
26
26
  fieldLabel?: string;
27
- /** Expression mode's commit. Not used in `mode="json-binding"` (see `onBind`). */
27
+ /** Expression mode's commit. Not used in `mode="json-binding"` (see `onSaveJson`). */
28
28
  onSave?: (next: ExprValue | string) => void;
29
29
  onClose: () => void;
30
30
  /**
31
- * `"json-binding"`: pick ONE upstream step output for a whole `json`/`group`
32
- * param. The rail shows only the Workflow state slot, each step gets an
33
- * "Entire output" leaf, and a click calls `onBind({ $: ref })` (the plain
34
- * one-key object, never an `ExprValue`) and closes. No chips editor, no
35
- * Save, no template/Result panes. Absent ⇒ expression mode, unchanged.
31
+ * `"json-binding"`: the value of a whole `json`/`group` param, composed as JSON. The rail
32
+ * shows Previous steps (each step's "Entire output", its fields and, for an app step, its
33
+ * Metadata), Inputs and Variables — no Secrets or Documents. A click on a source into an empty
34
+ * draft (or one holding only a reference) binds it: `onSaveJson("{{ ref }}")` and close. Into a
35
+ * draft being composed it ADDS the reference (`addRefToDraft`, `json-compose.ts`): at the caret
36
+ * where a value or property fits, else as a new property/element at the end — never replacing
37
+ * the draft. Save calls `onSaveJson` with the parsed JSON.
38
+ * Absent ⇒ expression mode, unchanged.
36
39
  */
37
40
  mode?: "json-binding";
38
- onBind?: (next: {
39
- $: string;
40
- }) => void;
41
+ /** json-binding mode: the field's current value, seeding the compose pane. */
42
+ jsonValue?: unknown;
43
+ /** json-binding mode: Save from the compose pane, with the parsed JSON. */
44
+ onSaveJson?: (next: unknown) => void;
45
+ /**
46
+ * json-binding mode only: the field takes one whole value (`ActionParam.whole`). A source click
47
+ * into an empty draft, or one parsing to exactly `[]` / `{}`, binds the bare ref. Any other
48
+ * draft composes as usual.
49
+ */
50
+ whole?: boolean;
51
+ /**
52
+ * json-binding mode only: a workflow's starting state (`Workflow.initialState`), evaluated once
53
+ * at run start. The rail has no Previous steps or State section (the state is blank then) and
54
+ * no Secrets (a secret never enters state), but does list Documents. A toggle above it picks
55
+ * what a source click inserts: its reference (default), or its current sample value as a
56
+ * literal. A click always composes into the object, never binds the whole field. An empty
57
+ * draft saves `undefined`; Save is refused while `jsonProblem` names a problem.
58
+ */
59
+ startingState?: boolean;
60
+ /** Starting-state mode: why the draft text cannot be saved (`null` when it can). */
61
+ jsonProblem?: (text: string) => string | null;
62
+ /** The modal's title, in place of "Edit JSON value" / "Edit expression". */
63
+ title?: string;
41
64
  }
42
- export declare function ExpressionEditorModal({ value, masked, multiline, options, fieldLabel, onSave, onClose, mode, onBind, }: ExpressionEditorModalProps): import("react").JSX.Element;
65
+ export declare function ExpressionEditorModal({ value, masked, multiline, options, fieldLabel, onSave, onClose, mode, jsonValue, onSaveJson, whole: wholeField, startingState: startingStateProp, jsonProblem, title, }: ExpressionEditorModalProps): import("react").JSX.Element;
@@ -5,7 +5,18 @@ import { SecretValue } from '../types.ts';
5
5
  * sources — a step cannot reference its own output.
6
6
  */
7
7
  export declare function excludeSelfStep(steps: ExpressionStepSource[], selfId: string | null | undefined): ExpressionStepSource[];
8
- /** An upstream step whose output this field can reference (`steps.<id>.output`). */
8
+ /** One pickable output field of a step / trigger event, as the rail lists it. */
9
+ export interface ExpressionFieldSource {
10
+ key: string;
11
+ label?: string;
12
+ path?: boolean;
13
+ /**
14
+ * `true` for a key the app DECLARES but the step's real (fresh/persisted) shape lacks:
15
+ * offered muted, "declared by the app".
16
+ */
17
+ declaredOnly?: true;
18
+ }
19
+ /** An upstream step whose output this field can reference (`nodes.<id>.output`). */
9
20
  export interface ExpressionStepSource {
10
21
  /** Step id — the key under `steps` in the run scope. */
11
22
  id: string;
@@ -15,7 +26,7 @@ export interface ExpressionStepSource {
15
26
  * The step's output field keys, when any are known (a manual trigger's
16
27
  * configured `fields`, a built-in node's static output, or an app action's
17
28
  * shape — see `outputsFrom`). Each entry feeds exactly one ref —
18
- * `steps.<id>.output.<key>` — which is the canonical form the engine resolves
29
+ * `nodes.<id>.output.<key>` — which is the canonical form the engine resolves (`steps.<id>…` is its compat alias)
19
30
  * (`RunScope.steps`; `core/rfcs/workflow.md` §"Expressions", `core/rfcs/node-types.md`
20
31
  * "Executing a trigger node yields the run's start payload … which downstream
21
32
  * nodes read as `steps.<triggerId>.output`").
@@ -27,18 +38,14 @@ export interface ExpressionStepSource {
27
38
  * **Omitted** (not `[]`) when the step declares no outputs, so a consumer can
28
39
  * tell "nothing declared" from "declared none" without a special case.
29
40
  */
30
- outputs?: {
31
- key: string;
32
- label?: string;
33
- path?: boolean;
34
- }[];
41
+ outputs?: ExpressionFieldSource[];
35
42
  /**
36
- * Where `outputs` came from, for an app-action step: the action's declared
37
- * `output`, its `sample`, or the step's last test run (`output-shape.ts`).
43
+ * Where `outputs` came from, for an app-action step: a fresh test output, the persisted
44
+ * test shape, the action's declared `output`, or its `sample` (`output-shape.ts`).
38
45
  * An entry with `path: true` is a dot path into nested output (`start.utc`),
39
46
  * checked segment by segment; without it the key is one literal key.
40
47
  */
41
- outputsFrom?: "declared" | "sample" | "test";
48
+ outputsFrom?: "fresh" | "persisted" | "declared" | "sample";
42
49
  /**
43
50
  * `true` when the step is an app action that declares no output shape and has
44
51
  * no test run yet — the picker tells the author to run a test to see fields.
@@ -46,12 +53,35 @@ export interface ExpressionStepSource {
46
53
  needsTest?: boolean;
47
54
  /**
48
55
  * `true` for an EXTERNAL app-action step only (R-7): the picker then offers a fixed
49
- * Metadata group (`steps.<id>.meta.app|version|action|connectionId`). **Omitted, not
50
- * `false`**, for triggers and every `@w6w/*` node. Carries no metadata VALUE: the group
51
- * is just labels, and the value exists only at run time.
56
+ * Metadata group (`nodes.<id>.meta.app|version|action|connectionId`). **Omitted, not
57
+ * `false`**, for triggers and every `@w6w/*` node. Carries no metadata VALUE: the static
58
+ * values come from {@link ExpressionOptions.nodeMeta}.
52
59
  */
53
60
  hasMeta?: boolean;
54
61
  }
62
+ /**
63
+ * One field of the merged workflow STATE a step reads (`state-shape.ts`), offered as
64
+ * `state.<key>` in the picker's "State" section. `paths` says whether every entry path into the
65
+ * step sets it (`all`) or only some (`some` — e.g. one of two converging triggers writes it).
66
+ */
67
+ export interface ExpressionStateField extends ExpressionFieldSource {
68
+ paths: "all" | "some";
69
+ }
70
+ /**
71
+ * The For each a step sits in the body of: offered as the rail's "Loop" group (Current item,
72
+ * Index, one row per item field). Present only for a loop-body step.
73
+ */
74
+ export interface ExpressionLoopSource {
75
+ foreachId: string;
76
+ /** Element [0] of the For each's resolved `items`. OMITTED (key absent) when unresolvable. */
77
+ itemSample?: unknown;
78
+ /** `inferOutputFields(itemSample)`. OMITTED when none. */
79
+ itemOutputs?: {
80
+ key: string;
81
+ label?: string;
82
+ path?: boolean;
83
+ }[];
84
+ }
55
85
  /**
56
86
  * A document contributing pickable refs (`documents.<key>`, and one
57
87
  * `documents.<key>.<field>` per top-level field when it qualifies).
@@ -97,6 +127,12 @@ export interface ExpressionDocumentSource {
97
127
  /** Known variable/secret names offered in an ExpressionInput's insert menu. */
98
128
  export interface ExpressionOptions {
99
129
  vars?: string[];
130
+ /**
131
+ * Account-level constants (`const.<name>`): read-only, set by an
132
+ * administrator, ordinary data (not secret). Offered as insertable chips
133
+ * only — there is deliberately no create callback.
134
+ */
135
+ constants?: string[];
100
136
  secrets?: string[];
101
137
  /**
102
138
  * Function/run input keys in scope (`inputs.<name>`). Present when the field
@@ -113,15 +149,65 @@ export interface ExpressionOptions {
113
149
  documents?: ExpressionDocumentSource[];
114
150
  /**
115
151
  * The workflow state leading to this step: upstream steps whose output is in
116
- * scope (`steps.<id>.output`). Present only in a workflow context; omitted for
152
+ * scope (`nodes.<id>.output`). Present only in a workflow context; omitted for
117
153
  * a standalone field.
118
154
  */
119
155
  steps?: ExpressionStepSource[];
156
+ /** The enclosing For each, when the field belongs to a loop-body step (`foreach.item` / `foreach.index`). */
157
+ loop?: ExpressionLoopSource;
158
+ /**
159
+ * The merged workflow state this step reads (starting data, variables and upstream writers;
160
+ * `state-shape.ts`). The picker lists it as the "State" section, only when non-empty.
161
+ */
162
+ stateShape?: {
163
+ fields: ExpressionStateField[];
164
+ };
120
165
  /** Whether a trigger event is in scope (`trigger.event`). */
121
166
  hasTrigger?: boolean;
167
+ /**
168
+ * The trigger event's fields, offered as `trigger.event.<key>` under the `trigger.event`
169
+ * chip: the payload the entry trigger last ran with, else an app trigger's declared event
170
+ * fields. Omitted when none are known.
171
+ */
172
+ eventOutputs?: ExpressionFieldSource[];
173
+ /**
174
+ * Where {@link eventOutputs} came from: a test this session (`fresh`), the server's remembered
175
+ * sample (`persisted`), the trigger's declared `output`, or its `sample`.
176
+ */
177
+ eventOutputsFrom?: ExpressionStepSource["outputsFrom"];
178
+ /**
179
+ * Which tier each value in {@link sampleValues} came from, keyed by the same full ref:
180
+ * a fresh test output, the persisted test (`from last test`) or the app's declared
181
+ * `sample` (`example from the app`). A ref absent here is not a step/event value.
182
+ */
183
+ valueSources?: Record<string, "fresh" | "persisted" | "sample">;
184
+ /**
185
+ * Every node's configuration keys, read as `nodes.<id>.config.<key>` on any run whether or not
186
+ * the node runs — its literal settings, and a webhook trigger's `url`. Offered as the rail's
187
+ * "Node settings" group, for every node, not only upstream ones. Workflow context only.
188
+ */
189
+ nodeConfigs?: {
190
+ id: string;
191
+ keys: string[];
192
+ }[];
193
+ /**
194
+ * Each node's configuration VALUES, keyed by node id — what a run reads at
195
+ * `nodes.<id>.meta.config` (`nodeConfigOf`): authored literal params (never a secret, never a
196
+ * binding) plus a webhook trigger's `url` from its subscription. The Test tab and the Result
197
+ * preview resolve config refs against it. Workflow context only.
198
+ */
199
+ nodeConfig?: Record<string, Record<string, unknown>>;
200
+ /**
201
+ * Each node's static metadata VALUES, keyed by node id — what a run reads at
202
+ * `nodes.<id>.meta.<key>` whether or not the node ran (`nodeMetaOf`): `app`, `action`,
203
+ * `connectionId`, the `version` the canvas labels it with, and a webhook trigger's
204
+ * `subscriptionId` / `url`. Offered as Metadata leaves
205
+ * in the picker and resolved by the previews. Workflow context only.
206
+ */
207
+ nodeMeta?: Record<string, Record<string, unknown>>;
122
208
  /**
123
209
  * Design-time sample values the Result preview substitutes for known refs,
124
- * keyed by FULL ref (`"vars.from_email"`, `"documents.test"`). Seeded by the
210
+ * keyed by FULL ref (`"var.from_email"`, `"documents.test"`). Seeded by the
125
211
  * host from the project's real vars/documents so the preview shows actual
126
212
  * values instead of the raw `{{ ref }}` template. Optional — a user-typed
127
213
  * Sample value still overrides, and unknown refs keep the raw fallback.
@@ -0,0 +1,7 @@
1
+ /** Vendor HTML is hostile. NEVER dangerouslySetInnerHTML it; this is the only render path. */
2
+ export declare const HTML_PREVIEW_CSP = "default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'";
3
+ /** The CSP meta is FIRST so it is parsed into <head> before any payload byte. */
4
+ export declare function htmlPreviewSrcDoc(html: string): string;
5
+ export declare function HtmlPreview({ html }: {
6
+ html: string;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A read-only, dependency-free tree for a parsed JSON value.
3
+ *
4
+ * Deliberately NOT exported from `src/index.ts` (`T0.1.1` pin 2): the public
5
+ * way to show a result is `ResultViewer`, which owns the format decision and
6
+ * the toolbar. `JsonTree` is the piece `ResultViewer` composes for
7
+ * `format: "json"`, so it stays private until a consumer needs a bare tree.
8
+ *
9
+ * Two properties everything here is built around:
10
+ *
11
+ * - **Nothing is injected.** Every key, every scalar and every brace reaches
12
+ * the DOM as a React text child — there is no `dangerouslySetInnerHTML`
13
+ * anywhere in this file. A property key such as `"<img onerror=…>"` is just
14
+ * text, which is the whole point: the value came from a vendor API.
15
+ * - **Collapsing is a native `<details>`.** The children are always rendered
16
+ * and the browser hides them, so collapsed text stays in the DOM: it is
17
+ * selectable, findable by the browser's find-in-page, and readable by a
18
+ * test. Re-rendering the subtree "only when open" would silently make the
19
+ * collapsed content unreachable.
20
+ */
21
+ export interface JsonTreeProps {
22
+ /** Any value; objects and arrays become collapsible nodes, the rest leaves. */
23
+ value: unknown;
24
+ /**
25
+ * How many levels start open. A node at depth `d` (root `d = 0`) is open iff
26
+ * `d < expandDepth`, so the default `2` opens the root and its children —
27
+ * enough to see the shape of a response without scrolling. `Infinity` opens
28
+ * everything; `1` leaves only the root open.
29
+ */
30
+ expandDepth?: number;
31
+ }
32
+ export declare function JsonTree({ value, expandDepth }: JsonTreeProps): import("react").JSX.Element;
@@ -15,6 +15,11 @@ export interface ResolvedParamsProps {
15
15
  * the trigger arm, and two side by side is a defect, not a feature).
16
16
  */
17
17
  view?: "props" | "code";
18
+ /**
19
+ * Param keys the host sends as SOURCE TEXT, never resolved (`@w6w/script`'s `code`, the
20
+ * engine's `LITERAL_PARAMS`): shown verbatim, so a `{{ }}` in them never reads as a value.
21
+ */
22
+ literalKeys?: readonly string[];
18
23
  }
19
24
  /**
20
25
  * Read-only sibling of `ParamsForm`: for every configured param, shows the
@@ -28,4 +33,4 @@ export interface ResolvedParamsProps {
28
33
  * the static chip vocabulary (`varLabel`, `.w6w-expr-chip-*`) rather than
29
34
  * `expression-dom.ts`'s DOM-painting, which is for the editable field.
30
35
  */
31
- export declare function ResolvedParams({ params, values, testStartState, view, }: ResolvedParamsProps): import("react").JSX.Element;
36
+ export declare function ResolvedParams({ params, values, testStartState, view, literalKeys, }: ResolvedParamsProps): import("react").JSX.Element;
@@ -0,0 +1,46 @@
1
+ export interface ResultViewerProps {
2
+ /** The result as the host received it: an already-parsed value, or a raw
3
+ * response body string. The format is sniffed from this ROOT value only
4
+ * (`detectResultFormat`); string leaves inside a JSON tree stay text. */
5
+ value: unknown;
6
+ /** Keep an already-parsed payload as JSON, including strings; default sniffs the format. */
7
+ format?: "auto" | "json";
8
+ /** Height cap of the scrolling body, in px. Default 320. */
9
+ maxHeight?: number;
10
+ /** Extra class on the root, for spacing in the consuming pane. */
11
+ className?: string;
12
+ }
13
+ /**
14
+ * Read-only display of one result value, chosen by its format:
15
+ *
16
+ * | format | body |
17
+ * | ---------- | ---------------------------------------------------------- |
18
+ * | `json` | a collapsible `JsonTree`, with Expand all / Collapse all |
19
+ * | `xml` | source (`CodeBlock`, `markup`, when small enough) |
20
+ * | `html` | `HtmlPreview` — an empty-sandbox iframe — or source |
21
+ * | `markdown` | `Markdown` — or source |
22
+ * | `text` | a plain `<pre>` |
23
+ *
24
+ * Read-only means read-only: nothing here takes an `onChange`, and the one
25
+ * interactive affordance besides the collapsers and the Rendered/Source
26
+ * toggle is `Copyable`'s button, overlaying the top-right corner and revealed
27
+ * on hover (`w6w-copyable--hover`).
28
+ *
29
+ * **Vendor HTML never touches this document.** The `html` format renders only
30
+ * through `HtmlPreview` — an `<iframe sandbox="">` whose `srcdoc` opens with a
31
+ * restrictive CSP meta as its first element — so a hostile payload cannot run
32
+ * script and cannot reach this page's origin or its data. Nothing in this
33
+ * component is ever passed to `dangerouslySetInnerHTML`. Accepted residual: a
34
+ * reader's CLICK on a link inside the preview navigates the frame itself (a
35
+ * page load in a sandboxed, scriptless, cookie-less document) — nothing more.
36
+ * Above `RESULT_RENDER_MAX_CHARS` even that path is skipped: an oversized
37
+ * document is shown as source, with a note saying so. Source views are handed
38
+ * to `renderSource`, which drops Prism above `RESULT_HIGHLIGHT_MAX_CHARS`.
39
+ *
40
+ * The copy button always writes `resultCopyText(detected)` — pretty-printed
41
+ * JSON for a tree, the raw string for every other format — so what lands on
42
+ * the clipboard is what the reader means by "the result", not the on-screen
43
+ * rendering. If that computation throws (circular value, `BigInt`), the view
44
+ * still renders and the button writes a best-effort string instead.
45
+ */
46
+ export declare function ResultViewer(props: ResultViewerProps): import("react").JSX.Element;
@@ -0,0 +1,31 @@
1
+ export interface ScriptConversion {
2
+ /** What the open-time conversion did, until Undo. */
3
+ converted: number;
4
+ undo: () => void;
5
+ }
6
+ /**
7
+ * A Run script's `{{ }}` markers, converted when the step opens. The host never substitutes
8
+ * inside code (see `script-bindings.ts`), so a marker there is literal text at run time. When
9
+ * the step opens, each convertible marker is rewritten to the code read it names
10
+ * (`$.get(root, ...keys)` in JavaScript/TypeScript); {@link ScriptBindingsNotice} says so,
11
+ * with Undo. Runs once per mount of the step editor, so after Undo the code stays as it was
12
+ * until the step is opened again. Read-only (or not a script), nothing is rewritten.
13
+ */
14
+ export declare function useScriptConversion({ enabled, values, onChange, }: {
15
+ /** A writable `@w6w/script` step. */
16
+ enabled: boolean;
17
+ /** The step's `with`: `code`, `language`, `input`. */
18
+ values: Record<string, unknown>;
19
+ onChange: (next: Record<string, unknown>) => void;
20
+ }): ScriptConversion | null;
21
+ /**
22
+ * The quiet line under a Run script's Configure tab: "Converted 2 references to code reads ·
23
+ * Undo" after the open-time conversion, and, for any marker still in the code, that it stays
24
+ * literal text. Renders nothing otherwise.
25
+ */
26
+ export declare function ScriptBindingsNotice({ values, conversion, readOnly, }: {
27
+ /** The step's `with`: `code`, `language`. */
28
+ values: Record<string, unknown>;
29
+ conversion: ScriptConversion | null;
30
+ readOnly?: boolean;
31
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ import { ScriptLanguage } from '../script-bindings.ts';
3
+ import { ActionParam } from '../types.ts';
4
+ /** Script picker and node chips insert literal-key reads for every script language. */
5
+ export declare function ScriptCodeField({ param, value, language, label, req, readOnly, onChange, }: {
6
+ param: ActionParam;
7
+ value: string;
8
+ language: ScriptLanguage;
9
+ label: string;
10
+ req: ReactNode;
11
+ readOnly?: boolean;
12
+ onChange: (next: string) => void;
13
+ }): import("react").JSX.Element;
@@ -8,6 +8,13 @@ import { ReactNode } from 'react';
8
8
  * the same precedent `HealthStatusPill`'s `HealthPillState` establishes.
9
9
  */
10
10
  export type StepStatus = "pending" | "running" | "succeeded" | "failed" | "skipped";
11
+ /**
12
+ * Why a `skipped` step did not run — the engine's `NodeExecution.skipReason`, again a thin
13
+ * LOCAL literal. `not_on_path`: the step is not downstream of the fired trigger (or outside a
14
+ * run-from-node scope), so it was never part of the run; the other three are real skips. A
15
+ * record from before the engine stamped reasons has none.
16
+ */
17
+ export type SkipReason = "not_on_path" | "condition" | "stopped" | "disabled";
11
18
  /**
12
19
  * The five states a whole EXECUTION (an invocation, an endpoint call, a
13
20
  * workflow run) can be in — the run-level sibling of `StepStatus`, and again a
@@ -0,0 +1,13 @@
1
+ import { ExprPart } from '../types.ts';
2
+ import { ExpressionOptions } from './ExpressionOptions.tsx';
3
+ /** Compile an entire condition, including picker chips followed by typed operators. Plain
4
+ * text/templates stay unchanged. The persisted value uses the existing JSONLogic wire format. */
5
+ export declare function compileAuthoredParts(original: ExprPart[], options: ExpressionOptions): {
6
+ parts: ExprPart[];
7
+ error: string | null;
8
+ };
9
+ /** Sample fields include those inside comparisons, not just standalone reference chips. */
10
+ export declare function authoredReferences(parts: ExprPart[]): string[];
11
+ /** Evaluate supported conditions with the same evaluator as workflow execution. Other legacy
12
+ * expression forms keep their existing template preview. Explicit samples preserve JSON types. */
13
+ export declare function previewAuthoredParts(parts: ExprPart[], seeds?: Record<string, unknown>, overrides?: Record<string, string>): string;
@@ -3,14 +3,14 @@ import { ExprPart } from '../types.ts';
3
3
  * The name a source or chip DISPLAYS. Never the ref it SAVES.
4
4
  *
5
5
  * A saved ref is always canonical and engine-resolvable — the run scope offers
6
- * exactly `vars.* · steps.<id>.output.* · steps.<id>.meta.* · trigger.* · secrets.* · documents.* ·
6
+ * exactly `var.* · steps.<id>.output.* · steps.<id>.meta.* · trigger.* · secrets.* · documents.* · const.* ·
7
7
  * inputs.* · foreach.* · output.*` (`core/rfcs/workflow.md` §Expressions, built
8
8
  * in `w6w-workflow/packages/engine/src/run.ts`). Those read long in a field, so
9
9
  * the label drops the root the chip's sigil and colour already imply:
10
10
  *
11
11
  * | ref | label |
12
12
  * |-----------------------------|----------------|
13
- * | `vars.from_email` | `from_email` |
13
+ * | `var.from_email` | `from_email` |
14
14
  * | `steps.gate_1.output` | `gate_1` |
15
15
  * | `steps.gate_1.output.email` | `gate_1.email` |
16
16
  * | `steps.gate_1.meta.version` | `gate_1 meta · version` |
@@ -41,6 +41,21 @@ export declare function isRefSafeKey(key: string): boolean;
41
41
  * {@link isRefSafeKey} on its own.
42
42
  */
43
43
  export declare function isRefSafePath(path: string): boolean;
44
+ /**
45
+ * Lay a step's flat output fields out as a tree for the picker: each row shows only its OWN
46
+ * name, nested under the nearest listed ancestor. `event`, `event.tz`, `event.start.utc` read as
47
+ * `event` › `tz`, `start.utc` — the step id and the shared prefix are what truncated every row to
48
+ * the same `eventbrite_to_cohost_1.event.…`. A literal key (no `path`) is one name at depth 0.
49
+ * Display only: the ref is still built from the verbatim `key`.
50
+ */
51
+ export declare function outputFieldTree<F extends {
52
+ key: string;
53
+ path?: boolean;
54
+ }>(fields: F[]): {
55
+ field: F;
56
+ depth: number;
57
+ name: string;
58
+ }[];
44
59
  /**
45
60
  * Build the non-editable inline chip (tag) DOM node for a part.
46
61
  *
@@ -19,13 +19,23 @@ import { ExprPart, ExprValue, SecretValue } from '../types.ts';
19
19
  */
20
20
  export { parseTemplate, serializeTemplate };
21
21
  /**
22
- * Serialize parts to the leanest faithful VALUE: prune empty text, collapse a
23
- * lone text segment to a plain string (backward-compat), else an `ExprValue`.
24
- * Shared by the inline field and the expression editor modal.
22
+ * Serialize parts to the value that is saved: the `{{ }}` template STRING — exactly what the
23
+ * author sees (core Workflow RFC amendment, 2026-10-29). Text parts are source text, kept
24
+ * verbatim (an escaped `\{{ var.x }}` stays escaped). The one exception is a `render` part,
25
+ * which has no `{{ }}` spelling by design (RFC, *The `render` part kind*): a value holding one
26
+ * is saved as an `ExprValue` envelope. Shared by the inline field and the expression editor
27
+ * modal.
25
28
  */
26
29
  export declare function partsToValue(parts: ExprPart[]): ExprValue | string;
27
30
  /** Every root name, for tests that pin the derived set without reaching into the type. */
28
31
  export declare const RUN_SCOPE_ROOT_NAMES: readonly string[];
32
+ /**
33
+ * THE alias rule for the state tree: `state`, `var` and `vars` are one object. For a ref whose
34
+ * root is one of them (followed by `.` or end of string) this gives the lookup spellings in order:
35
+ * the ref exactly as written, then `state.<rest>`, `var.<rest>`, `vars.<rest>` (deduplicated).
36
+ * Any other root gives only the ref itself (`steps`/`nodes` are NOT aliased here).
37
+ */
38
+ export declare function stateAliasSpellings(ref: string): string[];
29
39
  /**
30
40
  * Root-anchored parse (CONDUCTOR AMENDMENT 2026-08-14): builds every marker in
31
41
  * `s` via `parseTemplate` (never a second `{{ }}` scanner), then requires:
@@ -49,6 +59,18 @@ export declare const RUN_SCOPE_ROOT_NAMES: readonly string[];
49
59
  * vendor placeholders with no root of their own).
50
60
  */
51
61
  export declare function parseRootAnchoredTemplate(s: string): ExprPart[];
62
+ /**
63
+ * True when `v` holds a reference the run resolves — an `ExprValue` envelope, or a string with
64
+ * at least one live marker of ours. Since the editor saves template STRINGS, this (not
65
+ * `isExprValue`) is the test for "this field is an expression".
66
+ */
67
+ export declare function holdsExpression(v: unknown): boolean;
68
+ /**
69
+ * Parse a string the way the engine resolves a `with` string (`parseResolvableTemplate`):
70
+ * parts with escapes consumed, or `null` when the engine would pass it through untouched (no
71
+ * marker of ours, or one marker that is not ours). For previews.
72
+ */
73
+ export declare function parseResolvableText(s: string): ExprPart[] | null;
52
74
  /**
53
75
  * Parse an incoming value into editable parts (+ any sealed secret to display).
54
76
  * The inverse of {@link partsToValue} for the editable forms; a sealed
@@ -4,7 +4,7 @@ import { ReactNode } from 'react';
4
4
  * never for the studio component that happened to draw it, so a caller asks for
5
5
  * `icon="history"` rather than `icon="history-icon-tsx"`.
6
6
  */
7
- export type IconName = "edit" | "edit-2" | "delete" | "copy" | "check" | "close" | "history" | "info" | "clock" | "json" | "code" | "sync" | "cloud-download" | "eye" | "play" | "stop" | "warning" | "file-text" | "settings" | "github" | "user" | "users" | "logout" | "id-card" | "dashboard" | "pulse" | "workflow" | "globe" | "lambda" | "sliders" | "file" | "plug" | "grid" | "folder" | "git-branch" | "coin" | "building" | "server" | "price-tag" | "lang-node" | "terminal" | "lang-python" | "lang-curl" | "sun" | "moon" | "circle-half" | "layout" | "run" | "trash" | "maximize" | "form" | "braces" | "settings-2";
7
+ export type IconName = "edit" | "edit-2" | "delete" | "copy" | "check" | "close" | "history" | "info" | "clock" | "json" | "code" | "sync" | "cloud-download" | "eye" | "play" | "stop" | "warning" | "file-text" | "settings" | "github" | "user" | "bot" | "users" | "logout" | "id-card" | "dashboard" | "pulse" | "workflow" | "globe" | "lambda" | "sliders" | "file" | "plug" | "grid" | "folder" | "git-branch" | "coin" | "building" | "server" | "price-tag" | "lang-node" | "terminal" | "lang-python" | "lang-curl" | "sun" | "moon" | "circle-half" | "layout" | "run" | "pause" | "ban" | "trash" | "maximize" | "form" | "braces" | "settings-2" | "sticky-note" | "frame" | "bold" | "grip" | "chevron-down" | "database";
8
8
  /**
9
9
  * Which attributes the shared `<svg>` root carries — i.e. how the glyph is
10
10
  * painted. The sources are not uniform, and forcing them into one shape would