@w6w/ui 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/LICENSE +21 -0
- package/README.md +260 -2
- package/dist/ActionTestForm.d.ts +76 -0
- package/dist/AddConnectionModal.d.ts +24 -0
- package/dist/AppPicker.d.ts +83 -0
- package/dist/CodeBlock-CZu4TFSi.cjs +15 -0
- package/dist/CodeBlock-CZu4TFSi.cjs.map +1 -0
- package/dist/CodeBlock-Dot3Pd7P.js +2889 -0
- package/dist/CodeBlock-Dot3Pd7P.js.map +1 -0
- package/dist/CodeBlock.d.ts +65 -0
- package/dist/CodeEditor.d.ts +42 -0
- package/dist/ConfirmModal-DJPYXE9t.cjs +11 -0
- package/dist/ConfirmModal-DJPYXE9t.cjs.map +1 -0
- package/dist/ConfirmModal-sY1tzkBO.js +6335 -0
- package/dist/ConfirmModal-sY1tzkBO.js.map +1 -0
- package/dist/Copyable-1niV9gUa.js +771 -0
- package/dist/Copyable-1niV9gUa.js.map +1 -0
- package/dist/Copyable-CYZU1o4X.cjs +2 -0
- package/dist/Copyable-CYZU1o4X.cjs.map +1 -0
- package/dist/JsonEditor.d.ts +60 -0
- package/dist/NodeConfigForm.d.ts +70 -0
- package/dist/ParamsForm.d.ts +56 -0
- package/dist/PropertyEntryForm.d.ts +56 -0
- package/dist/RetryPolicyFields.d.ts +18 -0
- package/dist/StepBuilderModal.d.ts +375 -0
- package/dist/TriggerFillForm.d.ts +52 -0
- package/dist/WaitEditor.d.ts +6 -0
- package/dist/WorkflowFlowEditor.d.ts +119 -0
- package/dist/YamlEditor.d.ts +46 -0
- package/dist/app-categories.d.ts +38 -0
- package/dist/app-pages.d.ts +111 -0
- package/dist/code.cjs +2 -0
- package/dist/code.cjs.map +1 -0
- package/dist/code.d.ts +29 -0
- package/dist/code.mjs +7 -0
- package/dist/code.mjs.map +1 -0
- package/dist/components/ApiCallsPanel.d.ts +41 -0
- package/dist/components/AppIcon.d.ts +25 -0
- package/dist/components/AuthFieldsForm.d.ts +22 -0
- package/dist/components/Combobox.d.ts +24 -0
- package/dist/components/ConfirmModal.d.ts +33 -0
- package/dist/components/Copyable.d.ts +51 -0
- package/dist/components/CopyableText.d.ts +40 -0
- package/dist/components/DeleteButton.d.ts +16 -0
- package/dist/components/EditButton.d.ts +10 -0
- package/dist/components/ExecutionDetail.d.ts +70 -0
- package/dist/components/ExecutionFilters.d.ts +59 -0
- package/dist/components/ExecutionList.d.ts +60 -0
- package/dist/components/ExecutionLogPanel.d.ts +98 -0
- package/dist/components/ExecutionStats.d.ts +47 -0
- package/dist/components/ExpressionEditorModal.d.ts +42 -0
- package/dist/components/ExpressionInput.d.ts +36 -0
- package/dist/components/ExpressionOptions.d.ts +185 -0
- package/dist/components/HealthStatusPill.d.ts +25 -0
- package/dist/components/HistoryTimeline.d.ts +56 -0
- package/dist/components/Icon.d.ts +34 -0
- package/dist/components/IconButton.d.ts +60 -0
- package/dist/components/InfoTip.d.ts +15 -0
- package/dist/components/InternalIcon.d.ts +19 -0
- package/dist/components/ListItem.d.ts +25 -0
- package/dist/components/Modal.d.ts +29 -0
- package/dist/components/RepoSyncIndicator.d.ts +29 -0
- package/dist/components/ResolvedParams.d.ts +31 -0
- package/dist/components/ServerResources.d.ts +47 -0
- package/dist/components/StepStatusPill.d.ts +51 -0
- package/dist/components/UptimeStrip.d.ts +56 -0
- package/dist/components/execution-format.d.ts +24 -0
- package/dist/components/expression-dom.d.ts +154 -0
- package/dist/components/expression-template.d.ts +86 -0
- package/dist/components/history-scale.d.ts +33 -0
- package/dist/components/icons.d.ts +41 -0
- package/dist/components/resolved-clip.d.ts +42 -0
- package/dist/components/server-resources-format.d.ts +68 -0
- package/dist/components/server-resources.fixture.d.ts +9 -0
- package/dist/components/use-copy.d.ts +14 -0
- package/dist/createW6WApi.d.ts +31 -0
- package/dist/flow-connect.d.ts +138 -0
- package/dist/flow-fanout.d.ts +15 -0
- package/dist/flow-types.d.ts +356 -0
- package/dist/flow-utils.d.ts +284 -0
- package/dist/flow.cjs +3 -0
- package/dist/flow.cjs.map +1 -0
- package/dist/flow.d.ts +22 -0
- package/dist/flow.mjs +1977 -0
- package/dist/flow.mjs.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +94 -0
- package/dist/index.mjs +1811 -0
- package/dist/index.mjs.map +1 -0
- package/dist/oauth-popup.d.ts +17 -0
- package/dist/output-shape.d.ts +58 -0
- package/dist/provider.d.ts +420 -0
- package/dist/resolve-params.d.ts +112 -0
- package/dist/resolved-json.d.ts +21 -0
- package/dist/run-visuals.d.ts +90 -0
- package/dist/step-preview-state.d.ts +143 -0
- package/dist/theme.d.ts +32 -0
- package/dist/trigger-fields.d.ts +56 -0
- package/dist/types.d.ts +413 -0
- package/dist/ui.css +1 -0
- package/dist/use-app-action-defs.d.ts +7 -0
- package/dist/use-enter-submit.d.ts +23 -0
- package/dist/use-seed-sources.d.ts +16 -0
- package/package.json +111 -3
- package/src/code.css +542 -0
- package/src/styles/_buttons.scss +38 -0
- package/src/styles/_chips.scss +210 -0
- package/src/styles/_code.scss +139 -0
- package/src/styles/_copyable.scss +147 -0
- package/src/styles/_data-vars.scss +38 -0
- package/src/styles/_execution-history.scss +282 -0
- package/src/styles/_execution-log.scss +178 -0
- package/src/styles/_expression-field.scss +65 -0
- package/src/styles/_expression-inline.scss +63 -0
- package/src/styles/_expression-modal.scss +292 -0
- package/src/styles/_fields.scss +161 -0
- package/src/styles/_flow.scss +217 -0
- package/src/styles/_fx.scss +158 -0
- package/src/styles/_health.scss +46 -0
- package/src/styles/_history-timeline.scss +156 -0
- package/src/styles/_icon-button.scss +22 -0
- package/src/styles/_icon.scss +15 -0
- package/src/styles/_icons.scss +31 -0
- package/src/styles/_incoming-state.scss +46 -0
- package/src/styles/_info-tip.scss +9 -0
- package/src/styles/_layout.scss +6 -0
- package/src/styles/_lists.scss +64 -0
- package/src/styles/_modal.scss +125 -0
- package/src/styles/_multiselect.scss +69 -0
- package/src/styles/_repo-sync-indicator.scss +99 -0
- package/src/styles/_scale.scss +70 -0
- package/src/styles/_sections.scss +36 -0
- package/src/styles/_server-resources.scss +163 -0
- package/src/styles/_step-builder.scss +376 -0
- package/src/styles/_step-config.scss +195 -0
- package/src/styles/_tabs.scss +54 -0
- package/src/styles/_tester.scss +111 -0
- package/src/styles/_tokens.scss +141 -0
- package/src/styles/_uptime.scss +61 -0
- package/src/styles.css +4208 -0
- package/src/styles.scss +61 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FlowStep } from './flow-types.ts';
|
|
2
|
+
/** Who this retry policy applies to — picks the helper line's wording. */
|
|
3
|
+
export type RetryTarget = "step" | "function" | "endpoint" | "workflow";
|
|
4
|
+
/** The persisted retry shape (core `rfcs/node-types.md`), minus the `undefined` case. */
|
|
5
|
+
export type RetryPolicyValue = NonNullable<FlowStep["retry"]>;
|
|
6
|
+
/**
|
|
7
|
+
* The "Retry on failure" checkbox + helper line + Attempts/Delay (ms)/Backoff
|
|
8
|
+
* row — the one retry shape shared by every host that can offer a retry
|
|
9
|
+
* policy (core rfcs/R-2 "one retry shape everywhere"). `value` is the
|
|
10
|
+
* persisted policy or `undefined` for "no retry"; `target` only changes the
|
|
11
|
+
* helper line's wording, never the behavior.
|
|
12
|
+
*/
|
|
13
|
+
export declare function RetryPolicyFields({ value, onChange, readOnly, target, }: {
|
|
14
|
+
value: RetryPolicyValue | undefined;
|
|
15
|
+
onChange: (next: RetryPolicyValue | undefined) => void;
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
target?: RetryTarget;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { NodeConfig } from './NodeConfigForm.tsx';
|
|
2
|
+
import { ExpressionStepSource } from './components/ExpressionOptions.tsx';
|
|
3
|
+
import { InternalNodeDef } from './flow-types.ts';
|
|
4
|
+
import { StepStartState } from './provider.tsx';
|
|
5
|
+
import { ActionParam, AppSummary, FunctionSummary, ThemeMode, WorkflowSummary } from './types.ts';
|
|
6
|
+
/** The step the builder emits — the editor assigns the final `id`. `NodeConfig`
|
|
7
|
+
* carries the base settings (retry / onError / notes) set on the Config view. */
|
|
8
|
+
export interface BuiltStep extends NodeConfig {
|
|
9
|
+
uses: {
|
|
10
|
+
app: string;
|
|
11
|
+
action: string;
|
|
12
|
+
connection?: string | null;
|
|
13
|
+
};
|
|
14
|
+
with?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export interface StepBuilderModalProps {
|
|
17
|
+
onClose: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* Fired once per session, the moment the step first has identity — for an
|
|
20
|
+
* app step, when Setup completes (action + connection, if needed); for a
|
|
21
|
+
* control node, on mount. Returns the minted step id so subsequent edits can
|
|
22
|
+
* target it via {@link StepBuilderModalProps.onDraftChange}.
|
|
23
|
+
*/
|
|
24
|
+
onAdd: (step: BuiltStep) => string | undefined | void;
|
|
25
|
+
/**
|
|
26
|
+
* Fired for every field change **after** the step has been committed via
|
|
27
|
+
* `onAdd` — keeps the already-added node current without minting a second
|
|
28
|
+
* one. `id` is the id `onAdd` returned. Progressive commit (mint-then-update)
|
|
29
|
+
* only engages when this is supplied; omitted callers (the Functions/
|
|
30
|
+
* Endpoints pickers) keep the original one-shot "Add step" behavior.
|
|
31
|
+
*/
|
|
32
|
+
onDraftChange?: (id: string, step: BuiltStep) => void;
|
|
33
|
+
theme?: ThemeMode;
|
|
34
|
+
/**
|
|
35
|
+
* Hide the GRAPH-ONLY tabs — Triggers / Controls / Utilities / Data, the
|
|
36
|
+
* flow-control and internal `@w6w/*` node kinds that only mean something
|
|
37
|
+
* inside a workflow canvas. Used by every picker that binds a *target*
|
|
38
|
+
* rather than adding a node to a graph.
|
|
39
|
+
*
|
|
40
|
+
* ⚠️ It does NOT hide Functions and Workflows, and did not always behave
|
|
41
|
+
* that way: it used to, which is why the Implementation card's picker
|
|
42
|
+
* showed only `Connected apps / Apps / AI` and F-2.0's tabs were
|
|
43
|
+
* unreachable outside the canvas. A Function and a Workflow are *callable
|
|
44
|
+
* targets*, not graph-only node kinds — they belong in every picker.
|
|
45
|
+
* {@link StepBuilderModalProps.callables} is the knob for those two.
|
|
46
|
+
*/
|
|
47
|
+
appsOnly?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Which callable families the Functions/Workflows tabs offer. Defaults to
|
|
50
|
+
* BOTH, so a caller that says nothing keeps the full F-2.0 homepage
|
|
51
|
+
* (`Connected apps | Functions | Workflows`). Pass a narrower array — or
|
|
52
|
+
* `[]` — where the surrounding contract cannot accept one of them.
|
|
53
|
+
*/
|
|
54
|
+
callables?: readonly ("function" | "workflow")[];
|
|
55
|
+
/**
|
|
56
|
+
* Which homepage tab opens first. Defaults to `"connected"` — F-2.0's
|
|
57
|
+
* homepage. A caller re-opening the picker for an already-bound target
|
|
58
|
+
* passes that target's own family, so "Change" lands where the current
|
|
59
|
+
* value lives instead of making the author re-find the tab.
|
|
60
|
+
*/
|
|
61
|
+
initialTab?: "connected" | "functions" | "workflows";
|
|
62
|
+
/** Modal heading. Defaults to "Add a step". */
|
|
63
|
+
title?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Workflow-step context, when the builder is opened for a step that already
|
|
66
|
+
* lives in a workflow. When present the `testRequired` save-gate can discover a
|
|
67
|
+
* previously-saved **passing** test for the step via {@link W6WApi.listStepTests}.
|
|
68
|
+
* Absent in the plain add-step flow (the step has no id yet) — there the gate is
|
|
69
|
+
* satisfied by running a passing test in-session.
|
|
70
|
+
*/
|
|
71
|
+
workflowId?: string;
|
|
72
|
+
/** Step id paired with {@link StepBuilderModalProps.workflowId}. */
|
|
73
|
+
stepId?: string;
|
|
74
|
+
/**
|
|
75
|
+
* The new step's known graph ancestors, when the builder is opened from the
|
|
76
|
+
* workflow canvas (`stepBuilderUpstreamSteps`, derived from the connection
|
|
77
|
+
* drag that opened it). Threaded into the Test tab's `<StepTestRun>` the same
|
|
78
|
+
* way `StepEditModal` seeds an existing step's Test tab, so a `with` block
|
|
79
|
+
* written as `{{ steps.<id>.output.<field> }}` resolves instead of coming
|
|
80
|
+
* back empty. Absent (defaults to `[]`) for the Functions/Endpoints pickers,
|
|
81
|
+
* which have no graph to draw ancestors from.
|
|
82
|
+
*/
|
|
83
|
+
upstreamSteps?: ExpressionStepSource[];
|
|
84
|
+
/**
|
|
85
|
+
* Pre-select an app when the modal opens. When provided along with
|
|
86
|
+
* initialAction/initialConnection/initialWith, the modal opens directly
|
|
87
|
+
* to the action configuration view instead of the app picker.
|
|
88
|
+
* Used when editing an existing action (e.g., clicking "Change" on an
|
|
89
|
+
* Endpoint's already-configured target).
|
|
90
|
+
*/
|
|
91
|
+
initialApp?: AppSummary;
|
|
92
|
+
/**
|
|
93
|
+
* Pre-select an action key. Requires initialApp to be set.
|
|
94
|
+
*/
|
|
95
|
+
initialAction?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Pre-select a connection. Requires initialApp and initialAction.
|
|
98
|
+
*/
|
|
99
|
+
initialConnection?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Pre-fill the action's parameter values. Requires initialApp and initialAction.
|
|
102
|
+
*/
|
|
103
|
+
initialWith?: Record<string, unknown>;
|
|
104
|
+
/**
|
|
105
|
+
* Narrow which apps a scoped caller may pick, everywhere an app list is
|
|
106
|
+
* computed — the "Apps" tab's grid, the "AI" tab's composed filter, and
|
|
107
|
+
* {@link StepBuilderModalProps.callables}'s "Ready to use" tab. An
|
|
108
|
+
* `undefined` filter is a no-op; every existing caller (none of which sets
|
|
109
|
+
* this) is unaffected.
|
|
110
|
+
*
|
|
111
|
+
* On "Ready to use", an app built from a connection's inline `app` meta
|
|
112
|
+
* carries only `id` plus those meta keys (`displayName`, icons, brand
|
|
113
|
+
* colours) — no `version` or `categories` — so the filter sees just those,
|
|
114
|
+
* and the selected-app header omits the ` · v<version>` suffix for it.
|
|
115
|
+
*/
|
|
116
|
+
appsFilter?: (app: AppSummary) => boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Stop at "a connection is chosen" — no Action, no Configure/Test. Renders
|
|
119
|
+
* {@link AppConnectionOnlyConfig} in place of the usual `AppStepConfig`
|
|
120
|
+
* once an app is picked. Used by a caller that only needs a connection
|
|
121
|
+
* (e.g. binding a repository), not a runnable step.
|
|
122
|
+
*/
|
|
123
|
+
connectionOnly?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Fired once, on {@link AppConnectionOnlyConfig}'s footer button — never on
|
|
126
|
+
* selection alone. Only meaningful with {@link StepBuilderModalProps.connectionOnly}.
|
|
127
|
+
*/
|
|
128
|
+
onConnected?: (connectionId: string, app: AppSummary) => void;
|
|
129
|
+
}
|
|
130
|
+
/** The four representations of the Configure tab: form, full-step JSON,
|
|
131
|
+
* params-only JSON, node settings. */
|
|
132
|
+
export type ConfigView = "props" | "code" | "params-code" | "config";
|
|
133
|
+
/**
|
|
134
|
+
* The props / code / params-code / config view toggle, right-aligned in the
|
|
135
|
+
* tabs bar. Disabled off the Configure tab (all four views represent the
|
|
136
|
+
* action's config).
|
|
137
|
+
*
|
|
138
|
+
* `views` narrows it to a subset, in the order given — a fields ⇄ raw-JSON
|
|
139
|
+
* property form (see `PropertyEntryForm`) passes `["props", "code"]`. There is
|
|
140
|
+
* deliberately no second toggle component: one glyph set, one styling, one
|
|
141
|
+
* pressed-state behaviour, however many views a host offers.
|
|
142
|
+
*/
|
|
143
|
+
export declare function ConfigViewToggle({ view, onChange, disabled, views, }: {
|
|
144
|
+
view: ConfigView;
|
|
145
|
+
onChange: (v: ConfigView) => void;
|
|
146
|
+
disabled?: boolean;
|
|
147
|
+
/** Which views to offer, in order. Defaults to all four. */
|
|
148
|
+
views?: ConfigView[];
|
|
149
|
+
}): import("react").JSX.Element;
|
|
150
|
+
/**
|
|
151
|
+
* Guided "add a step" flow. A sidebar toggles between **Apps** (pick app →
|
|
152
|
+
* ensure a connection → pick action → fill params) and **Controls** — the
|
|
153
|
+
* internal nodes: triggers, flow control (if/foreach/parallel/wait), and compute
|
|
154
|
+
* (script/data). Emits a `BuiltStep` via `onAdd`.
|
|
155
|
+
*
|
|
156
|
+
* Data + IO come from `useW6WApi()`, so mount it under `<W6WUIProvider>`.
|
|
157
|
+
*/
|
|
158
|
+
export declare function StepBuilderModal({ onClose, onAdd, onDraftChange, theme, appsOnly, callables, initialTab, title, workflowId, stepId, upstreamSteps, initialApp, initialAction, initialConnection, initialWith, appsFilter, connectionOnly, onConnected, }: StepBuilderModalProps): import("react").JSX.Element;
|
|
159
|
+
/**
|
|
160
|
+
* Config form for a chosen internal node — its schema rendered through the same
|
|
161
|
+
* `ParamsForm` as app actions, seeded with the node's defaults. Emits the built
|
|
162
|
+
* step on Add.
|
|
163
|
+
*/
|
|
164
|
+
export declare function ControlStepConfig({ node, onAdd, onClose, onDraftChange, workflowId, upstreamSteps, }: {
|
|
165
|
+
node: InternalNodeDef;
|
|
166
|
+
onAdd: (s: BuiltStep) => string | undefined | void;
|
|
167
|
+
onClose: () => void;
|
|
168
|
+
/** See {@link StepBuilderModalProps.onDraftChange}. */
|
|
169
|
+
onDraftChange?: (id: string, step: BuiltStep) => void;
|
|
170
|
+
workflowId?: string;
|
|
171
|
+
/** The new step's known graph ancestors — see {@link StepBuilderModalProps.upstreamSteps}. */
|
|
172
|
+
upstreamSteps?: ExpressionStepSource[];
|
|
173
|
+
}): import("react").JSX.Element;
|
|
174
|
+
/**
|
|
175
|
+
* Config → test → add flow for a picked Function/Workflow target (D-12,
|
|
176
|
+
* D-15). Mints a single `@w6w/call` step — `family` only decides which
|
|
177
|
+
* summary/detail/invoke endpoints are called and what `with.targetKind` is
|
|
178
|
+
* stamped; it is never two near-copies. Mirrors `ControlStepConfig`'s
|
|
179
|
+
* progressive-commit shape (mint via `onAdd` the instant the target is
|
|
180
|
+
* picked, then `onDraftChange` on every later change) — unlike `AppStepConfig`
|
|
181
|
+
* there is no Setup tab (the target picked in `CallableList` IS the identity)
|
|
182
|
+
* and no `NodeConfigForm` here: a second onError/retry form is out of scope —
|
|
183
|
+
* `NodeConfigForm` is reached once the `@w6w/call` step already lives on a
|
|
184
|
+
* canvas, not at add-time.
|
|
185
|
+
*/
|
|
186
|
+
export declare function CallableStepConfig({ family, targetId, targetLabel, onAdd, onClose, onDraftChange, }: {
|
|
187
|
+
family: "function" | "workflow";
|
|
188
|
+
targetId: string;
|
|
189
|
+
targetLabel: string;
|
|
190
|
+
onAdd: (s: BuiltStep) => string | undefined | void;
|
|
191
|
+
onClose: () => void;
|
|
192
|
+
/** See {@link StepBuilderModalProps.onDraftChange}. */
|
|
193
|
+
onDraftChange?: (id: string, step: BuiltStep) => void;
|
|
194
|
+
}): import("react").JSX.Element;
|
|
195
|
+
/**
|
|
196
|
+
* Whether every required param has a usable value — gates the inline "Test run".
|
|
197
|
+
* A required array (e.g. a `vars` table) may be empty (see the Data node); other
|
|
198
|
+
* required fields must be non-empty.
|
|
199
|
+
*
|
|
200
|
+
* A param hidden by its own `showIf` is skipped, matching `ParamsForm`'s render
|
|
201
|
+
* visibility — this is what lets `required` and `showIf` combine at all (e.g.
|
|
202
|
+
* SendGrid's `contentValue`, required only when NOT using a dynamic template):
|
|
203
|
+
* without it, a conditionally-required field would either block the gate in the
|
|
204
|
+
* branch where it's moot, or (if left non-required to dodge that) never be
|
|
205
|
+
* caught here and only surface as a raw runtime error from the app's own
|
|
206
|
+
* `execute()` — the app was previously written the second way for exactly this
|
|
207
|
+
* reason; that workaround was fixed alongside this once the gate learned `showIf`.
|
|
208
|
+
*/
|
|
209
|
+
export declare function requiredParamsFilled(params: ActionParam[], values: Record<string, unknown>): boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Whether adding this step is gated on a **passing** saved test — the per-app
|
|
212
|
+
* `testRequired` save-gate. Defaults to **required**; an app/node surface may
|
|
213
|
+
* opt out by carrying `testRequired: false`.
|
|
214
|
+
*
|
|
215
|
+
* The flag is read defensively off the app/node surface because the core app
|
|
216
|
+
* manifest does not carry a `testRequired` field yet (a recorded follow-up); an
|
|
217
|
+
* absent flag therefore means **required**, so today every app step must pass a
|
|
218
|
+
* test before it can be added.
|
|
219
|
+
*/
|
|
220
|
+
export declare function isTestRequired(surface: unknown): boolean;
|
|
221
|
+
/**
|
|
222
|
+
* Where a test run should be persisted. When present, `StepTestRun` saves the
|
|
223
|
+
* fixture (`saveStepTest`) and records the run's outcome (`recordStepTestRun`)
|
|
224
|
+
* against the given workflow step after each invoke. `input` is the resolved
|
|
225
|
+
* incoming state captured alongside the params (`values` → `with`). Absent in
|
|
226
|
+
* the add-step builder (the step isn't in a workflow yet).
|
|
227
|
+
*/
|
|
228
|
+
export interface StepTestPersist {
|
|
229
|
+
workflowId: string;
|
|
230
|
+
stepId: string;
|
|
231
|
+
input: Record<string, unknown>;
|
|
232
|
+
}
|
|
233
|
+
/** Imperative handle so a host (e.g. the step modal footer) can trigger the run. */
|
|
234
|
+
export interface StepTestRunHandle {
|
|
235
|
+
run: () => void;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Inline "Test run" — invokes the action/node with the current params (and, for
|
|
239
|
+
* app actions, the chosen connection) so the user can try a step from inside the
|
|
240
|
+
* builder before adding it. Pressable only once required fields are filled.
|
|
241
|
+
*
|
|
242
|
+
* When `persist` is supplied (the node editor's Test tab), each run also saves
|
|
243
|
+
* the fixture and records the outcome server-side, so a step test becomes saved
|
|
244
|
+
* and re-runnable. `hideRunButton` suppresses the inline button when the host
|
|
245
|
+
* drives the run from elsewhere (the modal footer) via the imperative handle.
|
|
246
|
+
*/
|
|
247
|
+
export declare const StepTestRun: import('react').ForwardRefExoticComponent<{
|
|
248
|
+
app: string;
|
|
249
|
+
action: string;
|
|
250
|
+
connectionId?: string;
|
|
251
|
+
values: Record<string, unknown>;
|
|
252
|
+
canRun: boolean;
|
|
253
|
+
hideRunButton?: boolean;
|
|
254
|
+
persist?: StepTestPersist;
|
|
255
|
+
/**
|
|
256
|
+
* The run's start state — what the upstream steps last produced — so a
|
|
257
|
+
* `values` entry written as `{{ steps.<id>.output.<field> }}` resolves
|
|
258
|
+
* server-side instead of coming back empty. The host builds it (both the
|
|
259
|
+
* node editor's Test tab and, since T1.1.1, the add-step builder's Test
|
|
260
|
+
* tab seed it from the upstream fixtures, via `useSeedSources` +
|
|
261
|
+
* `startStateFromSeeds`); absent only when the host itself has no upstream
|
|
262
|
+
* steps to offer — the Functions/Endpoints pickers, which have no graph.
|
|
263
|
+
*/
|
|
264
|
+
state?: StepStartState;
|
|
265
|
+
/** Notified when the run starts/finishes so a host button can reflect it. */
|
|
266
|
+
onBusyChange?: (busy: boolean) => void;
|
|
267
|
+
/**
|
|
268
|
+
* Notified with the outcome of each finished run (`true` = passed). Lets a
|
|
269
|
+
* host satisfy the `testRequired` save-gate from an in-session test run.
|
|
270
|
+
*/
|
|
271
|
+
onResult?: (passed: boolean) => void;
|
|
272
|
+
} & import('react').RefAttributes<StepTestRunHandle>>;
|
|
273
|
+
/**
|
|
274
|
+
* What the home tab has to show. Lifted out of the tab's own component because
|
|
275
|
+
* the MODAL needs the answer too: a home tab with nothing in it is not
|
|
276
|
+
* rendered at all (no connected apps, no Functions, no Workflows ⇒ no tab),
|
|
277
|
+
* and that decision belongs to whoever draws the sidebar.
|
|
278
|
+
*
|
|
279
|
+
* `state` is deliberately four-valued. "Empty" and "not loaded yet" must not
|
|
280
|
+
* collapse into one: hiding the tab while its fetches are in flight would make
|
|
281
|
+
* it appear a beat later, moving the sidebar under the cursor.
|
|
282
|
+
*/
|
|
283
|
+
interface ReadyToUse {
|
|
284
|
+
state: "loading" | "error" | "empty" | "ready";
|
|
285
|
+
error?: string;
|
|
286
|
+
apps: AppSummary[];
|
|
287
|
+
fns: FunctionSummary[];
|
|
288
|
+
wfs: WorkflowSummary[];
|
|
289
|
+
/** More connected-app ids remain unresolved — draw an explicit "load more" affordance. */
|
|
290
|
+
moreApps: boolean;
|
|
291
|
+
/** Resolve the next bounded batch of connected-app ids. No-op off the bounded path or with nothing left. */
|
|
292
|
+
loadMoreApps: () => void;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Clamp the poll-interval text to an integer number of minutes ≥ `min`. Blank,
|
|
296
|
+
* non-numeric or below-minimum input yields `min`; fractions round to nearest.
|
|
297
|
+
*/
|
|
298
|
+
export declare function clampMinutes(raw: string, min: number): number;
|
|
299
|
+
/**
|
|
300
|
+
* "Ready to use"'s data: distinct connected app ids (A3) resolved in bounded
|
|
301
|
+
* batches via the optional `listAppsByIds`, plus Functions/Workflows.
|
|
302
|
+
*
|
|
303
|
+
* `/connections` already includes a synthetic zero-credential row per
|
|
304
|
+
* zero-credential-flagged app the caller's tenant can use with no connection
|
|
305
|
+
* step (`admin/connections.ts`) — so the DISTINCT connection app ids alone are
|
|
306
|
+
* the full "ready" membership; unlike the old full-catalog scan, no separate
|
|
307
|
+
* `AppSummary.zeroCredential` check is needed on this path.
|
|
308
|
+
*
|
|
309
|
+
* `listAppsByIds` is optional (older/imported providers implement only
|
|
310
|
+
* `listApps`): capability is `typeof api.listAppsByIds === "function"`
|
|
311
|
+
* ALONE — never inferred from a runtime result. A first batch that resolves
|
|
312
|
+
* to an empty array is a LEGITIMATE answer from a fully-working
|
|
313
|
+
* `listAppsByIds` (every connected app was since deleted from the catalog,
|
|
314
|
+
* an ordinary case) and must be shown as such, not treated as evidence the
|
|
315
|
+
* optional method "isn't really implemented" (T2.1.1 ROUND 2 — that
|
|
316
|
+
* conflation previously made a correct, well-typed empty result permanently
|
|
317
|
+
* fall back to the unbounded `listApps()` for the rest of the component's
|
|
318
|
+
* lifetime, the exact "one request per entire catalog at open" A3 forbids).
|
|
319
|
+
* When the method is genuinely absent, this hook falls back to the ORIGINAL
|
|
320
|
+
* full-catalog scan (`listApps()` + the zero-credential check), unchanged —
|
|
321
|
+
* and with `listApps` itself also absent (now optional, like this member),
|
|
322
|
+
* settles on the empty catalog instead of calling an undefined function.
|
|
323
|
+
*
|
|
324
|
+
* On the bounded path each connection's inline `app` meta is read FIRST: an
|
|
325
|
+
* app id with a non-null `app` on any of its rows is built as
|
|
326
|
+
* `{ ...c.app, id: c.appId }` and seeded as resolved + requested, so
|
|
327
|
+
* `listAppsByIds` is called only for ids whose rows all lack it (`app` absent
|
|
328
|
+
* or `null`) — and not at all when none do. Such inline apps have no
|
|
329
|
+
* `version`/`categories`: the selected-app header drops its ` · v<version>`
|
|
330
|
+
* suffix and `appsFilter` sees only `id` and the meta keys.
|
|
331
|
+
*
|
|
332
|
+
* Exported for tests only (not re-exported from the package index).
|
|
333
|
+
*/
|
|
334
|
+
export declare function useReadyToUse(callables: readonly ("function" | "workflow")[], appsFilter?: (app: AppSummary) => boolean): ReadyToUse;
|
|
335
|
+
export declare function AppStepConfig({ appId, app, onAdd, onClose, onDraftChange, onChangeApp, theme, workflowId, stepId, upstreamSteps, initialAction, initialConnection, initialWith, }: {
|
|
336
|
+
appId: string;
|
|
337
|
+
app?: AppSummary;
|
|
338
|
+
onAdd: (s: BuiltStep) => string | undefined | void;
|
|
339
|
+
onClose: () => void;
|
|
340
|
+
/** See {@link StepBuilderModalProps.onDraftChange}. */
|
|
341
|
+
onDraftChange?: (id: string, step: BuiltStep) => void;
|
|
342
|
+
onChangeApp?: () => void;
|
|
343
|
+
theme?: ThemeMode;
|
|
344
|
+
workflowId?: string;
|
|
345
|
+
stepId?: string;
|
|
346
|
+
/** The new step's known graph ancestors — see {@link StepBuilderModalProps.upstreamSteps}. */
|
|
347
|
+
upstreamSteps?: ExpressionStepSource[];
|
|
348
|
+
/** Pre-selected action key, opens directly to Configure tab when provided with initialWith */
|
|
349
|
+
initialAction?: string;
|
|
350
|
+
/** Pre-selected connection id */
|
|
351
|
+
initialConnection?: string;
|
|
352
|
+
/** Pre-filled parameter values */
|
|
353
|
+
initialWith?: Record<string, unknown>;
|
|
354
|
+
}): import("react").JSX.Element;
|
|
355
|
+
/**
|
|
356
|
+
* {@link AppStepConfig}'s Setup tab, minus the Action and Configure/Test
|
|
357
|
+
* gate — for a caller that only needs "a connection is chosen" (e.g. binding
|
|
358
|
+
* a repository), not a runnable step. Copies its App section and all three
|
|
359
|
+
* Connection-section branches verbatim, same CSS classes; fetches only
|
|
360
|
+
* {@link W6WApi.getAppAuth} + {@link W6WApi.listConnectionsForApp} (never
|
|
361
|
+
* `getAppActions`). Ends in one footer button, gated on `connectionSatisfied`
|
|
362
|
+
* alone, that fires {@link onConnected} once — never on selection (D-sbm-2).
|
|
363
|
+
*/
|
|
364
|
+
export declare function AppConnectionOnlyConfig({ appId, app, onClose, onChangeApp, theme, initialConnection, onConnected, }: {
|
|
365
|
+
appId: string;
|
|
366
|
+
app?: AppSummary;
|
|
367
|
+
onClose: () => void;
|
|
368
|
+
onChangeApp?: () => void;
|
|
369
|
+
theme?: ThemeMode;
|
|
370
|
+
/** Pre-selected connection id */
|
|
371
|
+
initialConnection?: string;
|
|
372
|
+
/** Fired once, on the footer button — never on a state change (D-sbm-2). */
|
|
373
|
+
onConnected: (connectionId: string, app: AppSummary) => void;
|
|
374
|
+
}): import("react").JSX.Element;
|
|
375
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { StepTestPersist } from './StepBuilderModal.tsx';
|
|
2
|
+
/**
|
|
3
|
+
* The Test-tab widget for a manual/webhook trigger. A trigger's configured
|
|
4
|
+
* `fields` ARE the run's starting state, so testing it means **filling those
|
|
5
|
+
* fields**, not running the raw config (which is why the trigger's output used to
|
|
6
|
+
* come back `{}` — the invoke never carried an `input`).
|
|
7
|
+
*
|
|
8
|
+
* It projects the trigger's `fields` into params (see `./trigger-fields.ts`) and
|
|
9
|
+
* hands them to {@link PropertyEntryForm} — the one property-entry surface, which
|
|
10
|
+
* gives it the per-field widgets, per-field `ƒx`, and the fields ⇄ raw-JSON
|
|
11
|
+
* toggle. This component keeps only the *run*: it enforces each field's
|
|
12
|
+
* `required` via {@link requiredParamsFilled} before enabling Test, and invokes
|
|
13
|
+
* with `{ input: {…filled} }` so the handler (which passes `params.input`
|
|
14
|
+
* through) returns the populated values as the trigger's output state.
|
|
15
|
+
*
|
|
16
|
+
* A trigger with no declared fields (e.g. a webhook, whose payload is arbitrary)
|
|
17
|
+
* gets the raw JSON payload editor — that is the entry form's own empty-params
|
|
18
|
+
* path, not a second code path here — so the operator can still supply a
|
|
19
|
+
* starting state, and the same `{ input }` projection applies.
|
|
20
|
+
*
|
|
21
|
+
* **Remembered values (T4.1.3).** With `persist` supplied, the values are not
|
|
22
|
+
* just used for the invoke: they are saved as the step's latest `step_tests`
|
|
23
|
+
* fixture (`with`) and the run is recorded **against that fixture's id**, and the
|
|
24
|
+
* form seeds itself from the latest fixture next time it opens. The store is
|
|
25
|
+
* project-owned and shared per workflow — any editor of the workflow sees the
|
|
26
|
+
* same saved values, which is the answer to HITL-2. The canvas ▶ Run collect
|
|
27
|
+
* form reads and writes the same fixture, so values entered on either surface
|
|
28
|
+
* come back on the other.
|
|
29
|
+
*
|
|
30
|
+
* That persistence is **local to testing** — `TriggerFillForm` itself never
|
|
31
|
+
* calls `POST /workflows/:id/run`. It does not by itself reach a production
|
|
32
|
+
* workflow run: that route does accept an `input` body field, and the server
|
|
33
|
+
* lands it as the entry trigger's output (`run-workflow.ts`,
|
|
34
|
+
* `EnqueueRunInput.input`), but a CALLER has to fetch the saved fixture and
|
|
35
|
+
* pass it in. Studio's header ▶ Run is that caller (`WorkflowsPage.tsx`'s
|
|
36
|
+
* `onRunClick` → `resolveHeaderRunInput`,
|
|
37
|
+
* `packages/studio/src/lib/workflow-live-run.ts`): it fetches the manual
|
|
38
|
+
* trigger's latest `step_tests` row and sends its `with` verbatim as `input`.
|
|
39
|
+
* This form is not in that path; it only writes the fixture that call reads.
|
|
40
|
+
*/
|
|
41
|
+
export declare function TriggerFillForm({ app, action, fields, persist, }: {
|
|
42
|
+
app: string;
|
|
43
|
+
action: string;
|
|
44
|
+
/** The trigger's `fields` param value (an array of field definitions). */
|
|
45
|
+
fields: unknown;
|
|
46
|
+
/**
|
|
47
|
+
* Where to remember the entered values. Absent in the add-step builder — that
|
|
48
|
+
* step is not in a workflow yet, so there is no `(workflowId, stepId)` to key
|
|
49
|
+
* a fixture by and this form neither reads nor writes one.
|
|
50
|
+
*/
|
|
51
|
+
persist?: StepTestPersist;
|
|
52
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Both input modes write the same duration field; switching never discards a compound value. */
|
|
2
|
+
export declare function WaitEditor({ values, onChange, readOnly, }: {
|
|
3
|
+
values: Record<string, unknown>;
|
|
4
|
+
onChange: (values: Record<string, unknown>) => void;
|
|
5
|
+
readOnly?: boolean;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ExpressionOptions, ExpressionStepSource } from './components/ExpressionOptions.tsx';
|
|
2
|
+
import { FlowStep, FlowWorkflow } from './flow-types.ts';
|
|
3
|
+
import { RunState } from './run-visuals.ts';
|
|
4
|
+
import { AppSummary } from './types.ts';
|
|
5
|
+
export interface WorkflowFlowEditorProps {
|
|
6
|
+
/** The workflow being edited. The editor re-derives layout when this changes identity. */
|
|
7
|
+
value: FlowWorkflow;
|
|
8
|
+
/** Fired whenever the user changes the graph — new nodes, edges, or step edits. */
|
|
9
|
+
onChange: (next: FlowWorkflow) => void;
|
|
10
|
+
/** Disable all interactions — pans/zooms are still enabled. */
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
/** Height of the editor viewport. Defaults to 480px. */
|
|
13
|
+
height?: string | number;
|
|
14
|
+
/**
|
|
15
|
+
* Registered apps, used to render each action node with its owning app's icon,
|
|
16
|
+
* display name, and version. A step only carries `uses.app` (an id), so the
|
|
17
|
+
* card joins that id against this list. Optional — unknown/absent apps degrade
|
|
18
|
+
* to an initials tile with no version. Metadata is looked up at render time and
|
|
19
|
+
* never stored on nodes, so it can't corrupt round-tripping back to a workflow.
|
|
20
|
+
*/
|
|
21
|
+
apps?: AppSummary[];
|
|
22
|
+
/**
|
|
23
|
+
* EXTRA scope for each step field's expression picker, on top of whatever
|
|
24
|
+
* this editor is already mounted under.
|
|
25
|
+
*
|
|
26
|
+
* Optional, and normally omitted: `ExpressionOptionsProvider` layers, so a
|
|
27
|
+
* host that provides the project's vars/secrets/documents above this editor
|
|
28
|
+
* (studio does, once, in its app shell) needs to pass nothing here. Use it
|
|
29
|
+
* only to add or override something at this level.
|
|
30
|
+
*
|
|
31
|
+
* Names only — secret plaintext never reaches the client.
|
|
32
|
+
*/
|
|
33
|
+
exprOptions?: ExpressionOptions;
|
|
34
|
+
/**
|
|
35
|
+
* The workflow's currently-selected project id. Threaded into ad-hoc
|
|
36
|
+
* test-invokes so document expressions resolve against that project's docs
|
|
37
|
+
* (not the scope's default/starter project). The host (studio) passes the
|
|
38
|
+
* active project here; omitted → server default-project behavior. See T2.1.2 /
|
|
39
|
+
* HITL-4(b): the invoke path's ambient scope is already project-aware.
|
|
40
|
+
*/
|
|
41
|
+
project?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The live run's per-step state, when the canvas is showing one (T1.1.1).
|
|
44
|
+
* Omitted ⇒ the canvas renders exactly as it does today: every node in its
|
|
45
|
+
* default look, every edge unstyled beyond its own `when` lane. This
|
|
46
|
+
* editor does no fetching of its own — the host (`studio`) owns polling
|
|
47
|
+
* `GET /runs/:id` and passes each successive result here, the same
|
|
48
|
+
* "host owns the query, editor is presentational" split `apps`/`readOnly`
|
|
49
|
+
* already establish for every other external data source.
|
|
50
|
+
*
|
|
51
|
+
* A structural subset of `RunState` in `@w6w/workflow-types` (mirrors this
|
|
52
|
+
* file's own `FlowWorkflow`/`FlowStep` — see `flow-types.ts`'s header
|
|
53
|
+
* note): `packages/ui` takes no dependency on the engine's types, so a
|
|
54
|
+
* caller who already has the real `RunState` is compatible for free.
|
|
55
|
+
*
|
|
56
|
+
* Never persisted: {@link flowToWorkflow} never reads it — a run is not
|
|
57
|
+
* part of the workflow that ran, and `data.stepStatus`/`data.runStatus`
|
|
58
|
+
* (where this ends up on the canvas) are never among the fields it reads
|
|
59
|
+
* back off a node.
|
|
60
|
+
*/
|
|
61
|
+
runState?: RunState;
|
|
62
|
+
/**
|
|
63
|
+
* Fired the instant a step test starts — the ▶ collect form's Run button, or
|
|
64
|
+
* `StepEditModal`'s footer Test button — before the invoke goes out, so a host
|
|
65
|
+
* can drop whatever run its canvas was showing (T1.1.1) instead of leaving a
|
|
66
|
+
* test to run underneath a stale run's highlighting.
|
|
67
|
+
*
|
|
68
|
+
* On the click, never on the result: only one of those two surfaces has a
|
|
69
|
+
* completion to report at all, and the click is the one moment both share.
|
|
70
|
+
*/
|
|
71
|
+
onTestRun?: () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Re-frames the canvas when the host changes the space around it. When this
|
|
74
|
+
* value changes after mount (compared with `Object.is`), the editor calls
|
|
75
|
+
* `fitView({ duration: 300 })` once. It never fires on mount, and omitting it
|
|
76
|
+
* or passing the same value again adds no fit.
|
|
77
|
+
*
|
|
78
|
+
* For a host whose page layout resizes the canvas without the graph changing,
|
|
79
|
+
* e.g. a side panel docking beside it (pass the panel's open state). React Flow
|
|
80
|
+
* keeps its pan/zoom transform when its pane narrows, so nodes near the edge
|
|
81
|
+
* would otherwise end up behind the panel. The editor does not watch its own
|
|
82
|
+
* size, so the host decides which layout changes deserve a re-frame.
|
|
83
|
+
*
|
|
84
|
+
* A fit replaces whatever camera is showing, including a saved viewport the
|
|
85
|
+
* editor restored on open. The fit is not user-initiated, so it never emits
|
|
86
|
+
* `onChange` and never overwrites the stored viewport.
|
|
87
|
+
*/
|
|
88
|
+
fitViewKey?: string | number | boolean;
|
|
89
|
+
}
|
|
90
|
+
/** Which view the step edit modal opens in: the tabbed form, raw JSON, or node settings. */
|
|
91
|
+
type EditView = "props" | "json" | "settings";
|
|
92
|
+
/**
|
|
93
|
+
* Visual workflow editor. Renders a Workflow's DAG as a React Flow graph:
|
|
94
|
+
*
|
|
95
|
+
* - Auto-layouted on load (topological columns + sibling rows).
|
|
96
|
+
* - Nodes render differently for action steps vs. control steps
|
|
97
|
+
* (`uses.app === "@w6w/control"`).
|
|
98
|
+
* - `+ Step` opens a guided builder (pick app → connection → action → params,
|
|
99
|
+
* or a flow control). Drag nodes to reposition; connect handles to add edges.
|
|
100
|
+
* - Selecting a node reveals a toolbar above it: Edit / Duplicate / Delete.
|
|
101
|
+
* - Edit opens a modal with a Form ⇄ JSON toggle for that step.
|
|
102
|
+
* - Every meaningful change fires `onChange` with an updated Workflow.
|
|
103
|
+
*/
|
|
104
|
+
export declare function WorkflowFlowEditor(props: WorkflowFlowEditorProps): import("react").JSX.Element;
|
|
105
|
+
export declare function StepEditModal({ workflowId, step: initialStep, upstreamSteps, onChange, onClose, readOnly, initialView, fanOutCount, onTestRun, }: {
|
|
106
|
+
workflowId: string;
|
|
107
|
+
step: FlowStep;
|
|
108
|
+
/** Graph ancestors of this step (from `upstreamStateSources`); the incoming-state picker seeds from their saved tests. */
|
|
109
|
+
upstreamSteps: ExpressionStepSource[];
|
|
110
|
+
onChange: (next: FlowStep) => void;
|
|
111
|
+
onClose: () => void;
|
|
112
|
+
readOnly?: boolean;
|
|
113
|
+
initialView?: EditView;
|
|
114
|
+
/** Most outgoing edges this step has in one lane; "Run next steps" needs >= 2. */
|
|
115
|
+
fanOutCount?: number;
|
|
116
|
+
/** Fired the instant the footer Test button is clicked, before the test runs (T1.1.1). */
|
|
117
|
+
onTestRun?: () => void;
|
|
118
|
+
}): import("react").JSX.Element;
|
|
119
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ThemeMode } from './types.ts';
|
|
2
|
+
export interface YamlEditorProps {
|
|
3
|
+
value: string;
|
|
4
|
+
onChange: (value: string) => void;
|
|
5
|
+
/** Placeholder text shown when value is empty. */
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
/** Minimum editor height. Defaults to "240px". */
|
|
8
|
+
minHeight?: string;
|
|
9
|
+
/** Maximum editor height before scrolling. Defaults to no cap. */
|
|
10
|
+
maxHeight?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Explicit editor height. Pass `"100%"` to fill a flex parent (the whole-config
|
|
13
|
+
* "code" view). Omit to let the editor grow with its content between
|
|
14
|
+
* `minHeight` and `maxHeight` — an inline YAML/group field wants this.
|
|
15
|
+
*/
|
|
16
|
+
height?: string;
|
|
17
|
+
/** Read-only mode — useful for previewing a stored definition. */
|
|
18
|
+
readOnly?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Explicit theme. If omitted, the editor auto-detects `data-theme` on
|
|
21
|
+
* `<html>` and falls back to `prefers-color-scheme` — same behavior as
|
|
22
|
+
* `<AppIcon>`. Uses CodeMirror's built-in one-dark for dark mode.
|
|
23
|
+
*/
|
|
24
|
+
theme?: ThemeMode;
|
|
25
|
+
/** Accessible label for the editor. */
|
|
26
|
+
"aria-label"?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Render an in-box copy-to-clipboard button, a direct child of this
|
|
29
|
+
* component's own `.w6w-yaml-editor` wrapper (sibling to the CodeMirror
|
|
30
|
+
* mount — no extra DOM node). Copies the current `value` verbatim.
|
|
31
|
+
*
|
|
32
|
+
* Off by default: the other mounts of this component must render byte-
|
|
33
|
+
* identically to before this prop existed.
|
|
34
|
+
*/
|
|
35
|
+
copyable?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* YAML editor built on CodeMirror 6. Syntax highlighting, folding, gutter,
|
|
39
|
+
* and line numbers. Themed with the `--w6w-*` custom properties so it
|
|
40
|
+
* inherits from the consumer's palette.
|
|
41
|
+
*
|
|
42
|
+
* ```tsx
|
|
43
|
+
* <YamlEditor value={text} onChange={setText} minHeight="320px" />
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function YamlEditor(props: YamlEditorProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AppSummary } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Display label for a category slug. A known override wins; otherwise the
|
|
4
|
+
* slug is split on `-`/`_`/whitespace and each word is capitalized. Never
|
|
5
|
+
* throws — an empty/non-string slug renders as `""`, and any out-of-
|
|
6
|
+
* vocabulary slug still gets a readable (title-cased) label.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* categoryLabel("crm"); // "CRM" (override)
|
|
10
|
+
* categoryLabel("project-management"); // "Project Management"
|
|
11
|
+
* categoryLabel("sales"); // "Sales" (out-of-vocabulary, still safe)
|
|
12
|
+
*/
|
|
13
|
+
export declare function categoryLabel(slug: string): string;
|
|
14
|
+
/** One category chip's derived data — a slug, its display label, and how
|
|
15
|
+
* many of the supplied apps carry it. */
|
|
16
|
+
export interface CategoryChip {
|
|
17
|
+
slug: string;
|
|
18
|
+
label: string;
|
|
19
|
+
count: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Distinct category slugs present across `apps`, each with its app count.
|
|
23
|
+
* Ordered by count DESCENDING; ties break on the derived LABEL, ascending
|
|
24
|
+
* (a deterministic order — never insertion/slug order, which would vary with
|
|
25
|
+
* the catalog's own listing order).
|
|
26
|
+
*
|
|
27
|
+
* Derive from the caller's already-visible catalog (post any `filter` prop),
|
|
28
|
+
* never from the full RFC vocabulary — a category with nothing behind it in
|
|
29
|
+
* the current list is a dead end (D-1a).
|
|
30
|
+
*/
|
|
31
|
+
export declare function deriveCategories(apps: readonly AppSummary[]): CategoryChip[];
|
|
32
|
+
/**
|
|
33
|
+
* Whether `app` matches a set of selected category slugs. An EMPTY selection
|
|
34
|
+
* means "all" (every app matches); a non-empty selection is OR-across-
|
|
35
|
+
* selected — the app matches if it carries ANY of the selected slugs. Mirrors
|
|
36
|
+
* `AppsPage.tsx`'s `cats.size === 0 ? … : appCats.some((c) => cats.has(c))`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function matchesCategories(app: AppSummary, selected: readonly string[]): boolean;
|