@w6w/ui 0.2.0 → 0.2.11
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 +7 -0
- package/dist/AppPicker.d.ts +47 -2
- package/dist/CanvasLayer.d.ts +38 -0
- package/dist/{CodeBlock-Dot3Pd7P.js → CodeBlock-BqXDA35P.js} +2 -2
- package/dist/{CodeBlock-Dot3Pd7P.js.map → CodeBlock-BqXDA35P.js.map} +1 -1
- package/dist/{CodeBlock-CZu4TFSi.cjs → CodeBlock-CulfbnZD.cjs} +2 -2
- package/dist/{CodeBlock-CZu4TFSi.cjs.map → CodeBlock-CulfbnZD.cjs.map} +1 -1
- package/dist/ConfirmModal-Ln99S9NT.js +7919 -0
- package/dist/ConfirmModal-Ln99S9NT.js.map +1 -0
- package/dist/ConfirmModal-fjHW5rN-.cjs +14 -0
- package/dist/ConfirmModal-fjHW5rN-.cjs.map +1 -0
- package/dist/Copyable-DA6eiU7w.cjs +2 -0
- package/dist/Copyable-DA6eiU7w.cjs.map +1 -0
- package/dist/{Copyable-1niV9gUa.js → Copyable-F4NTaG77.js} +91 -15
- package/dist/Copyable-F4NTaG77.js.map +1 -0
- package/dist/EditConnectionModal.d.ts +6 -1
- package/dist/JsonEditor.d.ts +8 -0
- package/dist/Markdown.d.ts +25 -0
- package/dist/ParamsForm.d.ts +7 -1
- package/dist/StepBuilderModal.d.ts +23 -5
- package/dist/WorkflowFlowEditor.d.ts +14 -3
- package/dist/app-pages.d.ts +2 -0
- package/dist/canvas-types.d.ts +36 -0
- package/dist/canvas-utils.d.ts +44 -0
- package/dist/code.cjs +1 -1
- package/dist/code.mjs +2 -2
- package/dist/components/AuthFieldsForm.d.ts +11 -0
- package/dist/components/BudgetMeter.d.ts +15 -0
- package/dist/components/CallableList.d.ts +3 -2
- package/dist/components/Combobox.d.ts +8 -1
- package/dist/components/ConnectionList.d.ts +2 -3
- package/dist/components/CredentialPicker.d.ts +35 -0
- package/dist/components/DataTable.d.ts +27 -0
- package/dist/components/EmptyState.d.ts +9 -0
- package/dist/components/icons.d.ts +1 -1
- package/dist/dynamic-fields.d.ts +60 -0
- package/dist/editor-theme.d.ts +24 -0
- package/dist/flow-fanout.d.ts +2 -2
- package/dist/flow-types.d.ts +18 -1
- package/dist/flow-utils.d.ts +10 -3
- package/dist/flow.cjs +2 -2
- package/dist/flow.cjs.map +1 -1
- package/dist/flow.d.ts +9 -0
- package/dist/flow.mjs +1519 -1138
- package/dist/flow.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -2
- package/dist/index.mjs +1362 -1123
- package/dist/index.mjs.map +1 -1
- package/dist/note-markdown.d.ts +22 -0
- package/dist/provider.d.ts +56 -7
- package/dist/resolve-params.d.ts +5 -0
- package/dist/run-visuals.d.ts +4 -1
- package/dist/step-problems.d.ts +34 -0
- package/dist/types.d.ts +109 -3
- package/dist/use-dynamic-fields.d.ts +23 -0
- package/package.json +4 -2
- package/src/styles/_budget-meter.scss +46 -0
- package/src/styles/_callable-list.scss +15 -6
- package/src/styles/_canvas.scss +318 -0
- package/src/styles/_connections.scss +2 -14
- package/src/styles/_data-table.scss +55 -0
- package/src/styles/_empty-state.scss +21 -0
- package/src/styles/_flow.scss +11 -0
- package/src/styles/_fx.scss +23 -0
- package/src/styles/_layout.scss +10 -0
- package/src/styles/_markdown.scss +20 -0
- package/src/styles/_tester.scss +1 -14
- package/src/styles.css +572 -39
- package/src/styles.scss +5 -0
- package/dist/ConfirmModal-ChoiGy2K.cjs +0 -11
- package/dist/ConfirmModal-ChoiGy2K.cjs.map +0 -1
- package/dist/ConfirmModal-Wx3i8F1n.js +0 -6359
- package/dist/ConfirmModal-Wx3i8F1n.js.map +0 -1
- package/dist/Copyable-1niV9gUa.js.map +0 -1
- package/dist/Copyable-CYZU1o4X.cjs +0 -2
- package/dist/Copyable-CYZU1o4X.cjs.map +0 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The note editor's Markdown round-trip. A note is edited in place as a `contentEditable` block
|
|
3
|
+
* (no textarea); these two functions convert between its stored Markdown and that editable DOM.
|
|
4
|
+
*
|
|
5
|
+
* The editable model is line-based and covers exactly what the note toolbar writes: a heading
|
|
6
|
+
* level per line (`#`…`######`) and `**bold**` runs. Everything else (links, lists, `code`, …) is
|
|
7
|
+
* kept as literal text while editing and rendered by `Markdown` when not, so a line the toolbar
|
|
8
|
+
* never touched round-trips byte-for-byte.
|
|
9
|
+
*
|
|
10
|
+
* The DOM is built with `createElement` + text nodes only — note content is imported,
|
|
11
|
+
* attacker-controllable text and must never reach `innerHTML`.
|
|
12
|
+
*/
|
|
13
|
+
/** Build the editable DOM for `content` into `root` (its children are replaced). */
|
|
14
|
+
export declare function renderEditable(root: HTMLElement, content: string): void;
|
|
15
|
+
/** Serialize the editable DOM under `root` back to Markdown. */
|
|
16
|
+
export declare function editableToMarkdown(root: HTMLElement): string;
|
|
17
|
+
/**
|
|
18
|
+
* The content handed to `Markdown` for display. A note is typed line by line, so a single
|
|
19
|
+
* newline must show as a line break — Markdown would fold it into a space. A soft break between
|
|
20
|
+
* two non-empty lines becomes a hard break (two trailing spaces); the stored content is untouched.
|
|
21
|
+
*/
|
|
22
|
+
export declare function noteDisplayMarkdown(content: string): string;
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { ActionDef, ApiCallRecord, AppSummary, AuthDef, ConnectionSummary, FunctionDetail, FunctionSummary, SavedTest, SubscriptionSummary, ThemeMode, TriggerSummary, WorkflowDetail, WorkflowSummary } from './types.ts';
|
|
2
|
+
import { ActionDef, ApiCallRecord, AppSummary, AuthDef, ConnectionBinding, ConnectionSummary, CreateConnectionBody, CredentialDependents, CredentialSummary, CredentialTestResult, FunctionDetail, FunctionSummary, ResolveFieldsBody, ResolveFieldsResult, SavedTest, SubscriptionSummary, ThemeMode, TriggerSummary, WorkflowDetail, WorkflowSummary } from './types.ts';
|
|
3
3
|
/**
|
|
4
4
|
* A single tester-run summary from the unified `run_log` ledger, keyed to a
|
|
5
5
|
* connection. Thin by design — the full result payload stays server-side in
|
|
@@ -111,6 +111,8 @@ export interface ListAppsPageOptions {
|
|
|
111
111
|
q?: string;
|
|
112
112
|
/** Server-side category filter (e.g. `"ai"`). */
|
|
113
113
|
category?: string;
|
|
114
|
+
/** Server-side id allow-list (`GET /apps?ids=a,b`); `total` is then the filtered total. */
|
|
115
|
+
ids?: string[];
|
|
114
116
|
/** Opaque pagination cursor from a prior {@link AppsPageResult.nextCursor}. */
|
|
115
117
|
cursor?: string;
|
|
116
118
|
/** Page size; a host may clamp this to its own bounds. */
|
|
@@ -174,15 +176,31 @@ export interface W6WApi {
|
|
|
174
176
|
listAppsByIds?(ids: readonly string[], options?: {
|
|
175
177
|
signal?: AbortSignal;
|
|
176
178
|
}): Promise<AppSummary[]>;
|
|
179
|
+
/**
|
|
180
|
+
* OPTIONAL: the tenant's model routes, for the `model-route` step-param
|
|
181
|
+
* picker (`@w6w/model` `complete`). Absent, the param renders as a plain text
|
|
182
|
+
* input and this is never called. A `broken` route is still selectable.
|
|
183
|
+
* `project` is the editor's own project (`WorkflowProjectProvider`) when it
|
|
184
|
+
* has one — a host should list THAT project's routes, not guess one from its
|
|
185
|
+
* URL; `undefined` leaves the choice to the host.
|
|
186
|
+
*/
|
|
187
|
+
listModelRoutes?(project?: string): Promise<{
|
|
188
|
+
name: string;
|
|
189
|
+
model: string;
|
|
190
|
+
status: "active" | "broken";
|
|
191
|
+
}[]>;
|
|
192
|
+
/**
|
|
193
|
+
* OPTIONAL: resolve the choices of `options: { source: "resolveFields" }`
|
|
194
|
+
* params from the current form (`POST` to the host). Absent, those params
|
|
195
|
+
* render as plain inputs and this is never called.
|
|
196
|
+
*/
|
|
197
|
+
resolveActionFields?(appId: string, actionKey: string, body: ResolveFieldsBody, opts?: {
|
|
198
|
+
signal?: AbortSignal;
|
|
199
|
+
}): Promise<ResolveFieldsResult>;
|
|
177
200
|
/** Load auth methods declared by an app's manifest, with availability flags. */
|
|
178
201
|
getAppAuth(appId: string): Promise<AuthDef[]>;
|
|
179
202
|
/** Create a non-OAuth connection with a user-supplied credential. */
|
|
180
|
-
createConnection(appId: string, body:
|
|
181
|
-
authKey: string;
|
|
182
|
-
credential: Record<string, unknown>;
|
|
183
|
-
displayName?: string;
|
|
184
|
-
profile?: Record<string, unknown>;
|
|
185
|
-
}): Promise<ConnectionSummary>;
|
|
203
|
+
createConnection(appId: string, body: CreateConnectionBody): Promise<ConnectionSummary>;
|
|
186
204
|
/**
|
|
187
205
|
* Rename a connection and/or replace some of its credential fields (`PATCH /connections/:id`).
|
|
188
206
|
* Send only the fields being changed: the server merges a partial `credential` over the stored
|
|
@@ -191,8 +209,34 @@ export interface W6WApi {
|
|
|
191
209
|
*/
|
|
192
210
|
updateConnection?(id: string, body: {
|
|
193
211
|
displayName?: string;
|
|
212
|
+
binding?: ConnectionBinding;
|
|
213
|
+
credentialId?: string;
|
|
194
214
|
credential?: Record<string, unknown>;
|
|
195
215
|
}): Promise<ConnectionSummary>;
|
|
216
|
+
/** List stored credentials, optionally narrowed (`GET /credentials`). */
|
|
217
|
+
listCredentials?(filter?: {
|
|
218
|
+
contract?: string;
|
|
219
|
+
appId?: string;
|
|
220
|
+
authKey?: string;
|
|
221
|
+
}): Promise<CredentialSummary[]>;
|
|
222
|
+
/** Store a new credential (`POST /credentials`). `source` is the auth's field-value record. */
|
|
223
|
+
createCredential?(body: {
|
|
224
|
+
name: string;
|
|
225
|
+
contract: string;
|
|
226
|
+
source: Record<string, unknown>;
|
|
227
|
+
}): Promise<CredentialSummary>;
|
|
228
|
+
getCredential?(id: string): Promise<CredentialSummary>;
|
|
229
|
+
/** Replace a credential's secret (`POST /credentials/:id/rotate`). */
|
|
230
|
+
rotateCredential?(id: string, body: {
|
|
231
|
+
source: Record<string, unknown>;
|
|
232
|
+
}): Promise<CredentialSummary>;
|
|
233
|
+
/** Disable (`/disable`) or re-enable (`/enable`) a credential. */
|
|
234
|
+
setCredentialStatus?(id: string, status: "active" | "disabled"): Promise<CredentialSummary>;
|
|
235
|
+
/** Mint-level health check; distinct from a connection's app-access test. */
|
|
236
|
+
testCredential?(id: string): Promise<CredentialTestResult>;
|
|
237
|
+
credentialDependents?(id: string): Promise<CredentialDependents>;
|
|
238
|
+
/** Rejects with `ApiError` code `credential_in_use` (body.error.dependents) when in use. */
|
|
239
|
+
deleteCredential?(id: string): Promise<void>;
|
|
196
240
|
/**
|
|
197
241
|
* Start an OAuth 2.0 flow. Server builds the provider's authorize URL and
|
|
198
242
|
* returns it; the caller opens it in a popup and awaits the server's
|
|
@@ -431,6 +475,11 @@ export declare function W6WUIProvider({ api, theme, children }: W6WUIProviderPro
|
|
|
431
475
|
* `<W6WUIProvider>` — the common mistake is forgetting to wrap the app root.
|
|
432
476
|
*/
|
|
433
477
|
export declare function useW6WApi(): W6WApi;
|
|
478
|
+
/**
|
|
479
|
+
* Like {@link useW6WApi} but returns `undefined` outside a provider instead of
|
|
480
|
+
* throwing — for optional enhancements (e.g. the `model-route` picker).
|
|
481
|
+
*/
|
|
482
|
+
export declare function useOptionalW6WApi(): W6WApi | undefined;
|
|
434
483
|
/** Scopes test-invokes under it to `project`; the editor wraps its body with this. */
|
|
435
484
|
export declare function WorkflowProjectProvider({ project, children, }: {
|
|
436
485
|
project?: string;
|
package/dist/resolve-params.d.ts
CHANGED
|
@@ -38,6 +38,11 @@ export interface ResolveScope {
|
|
|
38
38
|
output?: unknown;
|
|
39
39
|
meta?: StepMeta;
|
|
40
40
|
}>;
|
|
41
|
+
/** `nodes.<id>…` root — the SAME object as `steps` (one state, two roots). */
|
|
42
|
+
nodes?: Record<string, {
|
|
43
|
+
output?: unknown;
|
|
44
|
+
meta?: StepMeta;
|
|
45
|
+
}>;
|
|
41
46
|
trigger: {
|
|
42
47
|
event?: unknown;
|
|
43
48
|
};
|
package/dist/run-visuals.d.ts
CHANGED
|
@@ -28,7 +28,10 @@ export interface StepExecution {
|
|
|
28
28
|
* as the engine's own `RunState.steps`. */
|
|
29
29
|
export interface RunState {
|
|
30
30
|
status: RunStatus;
|
|
31
|
-
|
|
31
|
+
/** Canonical per-node records (D2). */
|
|
32
|
+
nodes?: Record<string, StepExecution>;
|
|
33
|
+
/** Legacy alias of `nodes`; read as `nodes ?? steps` (un-upgraded server). */
|
|
34
|
+
steps?: Record<string, StepExecution>;
|
|
32
35
|
}
|
|
33
36
|
/**
|
|
34
37
|
* A step node's rendered state — exactly the five {@link StepStatus} values
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-supplied per-step problems painted on the canvas. Pure — no React or
|
|
3
|
+
* @xyflow imports. The host owns detection; ui never infers a problem itself.
|
|
4
|
+
*/
|
|
5
|
+
export interface StepProblem {
|
|
6
|
+
code: "unknown_connection";
|
|
7
|
+
connection: string;
|
|
8
|
+
}
|
|
9
|
+
/** Keyed by step id. */
|
|
10
|
+
export type StepProblems = Record<string, StepProblem>;
|
|
11
|
+
interface ProblemNode {
|
|
12
|
+
id: string;
|
|
13
|
+
data: {
|
|
14
|
+
stepProblem?: StepProblem;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Stamp `data.stepProblem` from `problems`, clearing it for steps no longer in
|
|
19
|
+
* the map. Returns the SAME node object when nothing changed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyStepProblems<N extends ProblemNode>(nodes: N[], problems: StepProblems | undefined): N[];
|
|
22
|
+
export declare function stepProblemTooltip(p: StepProblem): string;
|
|
23
|
+
/** True while the step still points at the connection the host reports missing. */
|
|
24
|
+
export declare function isConnectionBlocked(step: {
|
|
25
|
+
uses: {
|
|
26
|
+
connection?: string | null;
|
|
27
|
+
};
|
|
28
|
+
}, problem: StepProblem | undefined): boolean;
|
|
29
|
+
/** The Setup tab's Connection button label — exactly five outcomes. */
|
|
30
|
+
export declare function connectionButtonLabel(connection: string | undefined | null, conns: {
|
|
31
|
+
id: string;
|
|
32
|
+
displayName?: string;
|
|
33
|
+
}[] | null, failed: boolean): string;
|
|
34
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export interface AppSummary {
|
|
|
22
22
|
maturity?: string;
|
|
23
23
|
visibility?: string;
|
|
24
24
|
successor?: string;
|
|
25
|
+
/** Model-provider designation; absent when the app does not declare one. */
|
|
26
|
+
modelProvider?: {
|
|
27
|
+
modelTypes: string[];
|
|
28
|
+
modelFamilies?: string[];
|
|
29
|
+
};
|
|
25
30
|
/**
|
|
26
31
|
* True when the calling tenant has zero-credential access flagged for this
|
|
27
32
|
* app — usable with no connection step at all (server-computed per caller;
|
|
@@ -68,6 +73,8 @@ export interface AuthField {
|
|
|
68
73
|
required?: boolean;
|
|
69
74
|
default?: unknown;
|
|
70
75
|
hint?: string;
|
|
76
|
+
/** Masks the input like a `secret` field whatever its `type` (e.g. a `json` key file). */
|
|
77
|
+
secret?: boolean;
|
|
71
78
|
}
|
|
72
79
|
/**
|
|
73
80
|
* One declared parameter of an action, as returned by GET /apps/:id (the
|
|
@@ -119,7 +126,7 @@ export interface ActionParam {
|
|
|
119
126
|
* Constrained choices. Renders as a single-select dropdown for `select` (or any
|
|
120
127
|
* param with options), and as a multi-select pill picker for `multiselect`.
|
|
121
128
|
*/
|
|
122
|
-
options?: ParamOption[];
|
|
129
|
+
options?: ParamOption[] | DynamicOptions;
|
|
123
130
|
/** Type-specific render/behavior options. */
|
|
124
131
|
config?: ParamConfig;
|
|
125
132
|
/**
|
|
@@ -146,6 +153,34 @@ export interface ActionParam {
|
|
|
146
153
|
export interface ParamOption {
|
|
147
154
|
value: string | number;
|
|
148
155
|
label: string;
|
|
156
|
+
description?: string;
|
|
157
|
+
}
|
|
158
|
+
/** Host-resolved options (mirrors @w6w/types `DynamicOptions`). */
|
|
159
|
+
export interface DynamicOptions {
|
|
160
|
+
source: string;
|
|
161
|
+
searchable?: boolean;
|
|
162
|
+
cache?: "session" | "none";
|
|
163
|
+
refreshOn?: string[];
|
|
164
|
+
}
|
|
165
|
+
/** True for the form-resolved arm: a non-array object with `source === "resolveFields"`. */
|
|
166
|
+
export declare function isFormResolvedOptions(o: unknown): o is DynamicOptions;
|
|
167
|
+
/** Body of `W6WApi.resolveActionFields`. */
|
|
168
|
+
export interface ResolveFieldsBody {
|
|
169
|
+
connectionId: string;
|
|
170
|
+
version?: string;
|
|
171
|
+
reason: "init" | "change";
|
|
172
|
+
form: Record<string, unknown>;
|
|
173
|
+
previous?: Record<string, unknown>;
|
|
174
|
+
changed?: string[];
|
|
175
|
+
fields: string[];
|
|
176
|
+
unresolved: string[];
|
|
177
|
+
}
|
|
178
|
+
/** Result of `W6WApi.resolveActionFields`. */
|
|
179
|
+
export interface ResolveFieldsResult {
|
|
180
|
+
fields: Record<string, {
|
|
181
|
+
options?: ParamOption[];
|
|
182
|
+
error?: string;
|
|
183
|
+
}>;
|
|
149
184
|
}
|
|
150
185
|
/**
|
|
151
186
|
* The element schema for a `type: "array"` param. Either a scalar list
|
|
@@ -184,6 +219,8 @@ export interface ParamCondition {
|
|
|
184
219
|
export interface ParamConfig {
|
|
185
220
|
/** Render as a multi-line textarea. Implied by `type: "text"`. */
|
|
186
221
|
multiline?: boolean;
|
|
222
|
+
/** With options: accept a value not in the list (Combobox `forceSelection` off). */
|
|
223
|
+
allowCustom?: boolean;
|
|
187
224
|
}
|
|
188
225
|
/** Summary of an action an app exposes, as returned by GET /apps/:id. */
|
|
189
226
|
export interface ActionDef {
|
|
@@ -267,16 +304,83 @@ export interface WorkflowDetail {
|
|
|
267
304
|
name: string;
|
|
268
305
|
displayName?: string;
|
|
269
306
|
description?: string;
|
|
270
|
-
|
|
307
|
+
/** The canonical (manifest v2) step list. */
|
|
308
|
+
nodes?: WorkflowStepSummary[];
|
|
309
|
+
/** The legacy (v1) step list; a definition carries one or the other. */
|
|
310
|
+
steps?: WorkflowStepSummary[];
|
|
311
|
+
}
|
|
312
|
+
/** A `serviceAccount` auth's declaration: the credential contract it accepts and its binding. */
|
|
313
|
+
export interface ServiceAccountConfig {
|
|
314
|
+
/** Credential contract ids this auth accepts; the first one is used to list/create. */
|
|
315
|
+
accepts: string[];
|
|
316
|
+
/** Scopes the binding requests by default (shown read-only; the server applies them). */
|
|
317
|
+
scopes: string[];
|
|
318
|
+
/** Whether a connection must/may name an impersonated user (`delegatedUser`). */
|
|
319
|
+
impersonation: "none" | "optional" | "required";
|
|
320
|
+
/** Extra per-connection (binding) fields; each lands in `binding.settings`. */
|
|
321
|
+
bindingFields?: AuthField[];
|
|
322
|
+
}
|
|
323
|
+
export type CredentialStatus = "active" | "disabled" | "revoked";
|
|
324
|
+
/** A stored credential as the API lists it. Never carries the secret payload. */
|
|
325
|
+
export interface CredentialSummary {
|
|
326
|
+
id: string;
|
|
327
|
+
name: string;
|
|
328
|
+
contract: string;
|
|
329
|
+
status: CredentialStatus | string;
|
|
330
|
+
revision: number;
|
|
331
|
+
/** Non-secret display values (e.g. the service account's email). */
|
|
332
|
+
display: Record<string, string>;
|
|
333
|
+
private: boolean;
|
|
334
|
+
connectionCount: number;
|
|
335
|
+
createdAt: string;
|
|
336
|
+
updatedAt: string;
|
|
337
|
+
}
|
|
338
|
+
/** The connections that use a credential. */
|
|
339
|
+
export interface CredentialDependents {
|
|
340
|
+
connections: Array<{
|
|
341
|
+
id: string;
|
|
342
|
+
appId: string;
|
|
343
|
+
authKey: string;
|
|
344
|
+
displayName?: string | null;
|
|
345
|
+
}>;
|
|
346
|
+
}
|
|
347
|
+
export interface CredentialTestResult {
|
|
348
|
+
ok: boolean;
|
|
349
|
+
code?: string;
|
|
350
|
+
message?: string;
|
|
351
|
+
}
|
|
352
|
+
/** Per-connection settings applied on top of a shared credential. */
|
|
353
|
+
export interface ConnectionBinding {
|
|
354
|
+
scopes?: string[];
|
|
355
|
+
/** The user the credential impersonates (Google domain-wide delegation). */
|
|
356
|
+
delegatedUser?: string;
|
|
357
|
+
settings?: Record<string, string | number | boolean>;
|
|
271
358
|
}
|
|
359
|
+
/** Body of `createConnection`: an inline credential XOR a reference to a stored one. */
|
|
360
|
+
export type CreateConnectionBody = {
|
|
361
|
+
authKey: string;
|
|
362
|
+
credential: Record<string, unknown>;
|
|
363
|
+
credentialId?: never;
|
|
364
|
+
displayName?: string;
|
|
365
|
+
profile?: Record<string, unknown>;
|
|
366
|
+
} | {
|
|
367
|
+
authKey: string;
|
|
368
|
+
credentialId: string;
|
|
369
|
+
credential?: never;
|
|
370
|
+
binding?: ConnectionBinding;
|
|
371
|
+
displayName?: string;
|
|
372
|
+
profile?: never;
|
|
373
|
+
};
|
|
272
374
|
/** Auth method declaration as exposed by an app's manifest. */
|
|
273
375
|
export interface AuthDef {
|
|
274
376
|
key: string;
|
|
275
|
-
type: "oauth2" | "apiKey" | "basic" | "bearer" | "custom" | "tenantAuth" | "jit" | string;
|
|
377
|
+
type: "oauth2" | "apiKey" | "basic" | "bearer" | "custom" | "tenantAuth" | "jit" | "serviceAccount" | string;
|
|
276
378
|
displayName?: string;
|
|
277
379
|
description?: string;
|
|
278
380
|
connectionLabel?: string;
|
|
279
381
|
fields?: AuthField[];
|
|
382
|
+
/** Present when `type === "serviceAccount"`: what credential it accepts and how it binds. */
|
|
383
|
+
serviceAccount?: ServiceAccountConfig;
|
|
280
384
|
/** OAuth2 endpoints (only present when type === "oauth2"). */
|
|
281
385
|
oauth2?: Record<string, unknown>;
|
|
282
386
|
/**
|
|
@@ -314,6 +418,8 @@ export interface ConnectionSummary {
|
|
|
314
418
|
id: string;
|
|
315
419
|
appId: string;
|
|
316
420
|
authKey: string;
|
|
421
|
+
/** The stored credential this connection uses, when it has one. */
|
|
422
|
+
credentialId?: string | null;
|
|
317
423
|
/** The owning tenant. The server sends `tenant`/`subject`, never `owner`. */
|
|
318
424
|
tenant?: string;
|
|
319
425
|
/** The owning subject (the partner's user id). */
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DynamicContext } from './dynamic-fields.ts';
|
|
2
|
+
import { ActionParam, ParamOption } from './types.ts';
|
|
3
|
+
/** Per-field state the form renders from. */
|
|
4
|
+
export interface DynamicFieldState {
|
|
5
|
+
options?: ParamOption[];
|
|
6
|
+
loading: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
/** Why the field is free text (no connection / unresolved refreshOn). */
|
|
9
|
+
hint?: string;
|
|
10
|
+
/** Flag for a kept value not in the returned list. */
|
|
11
|
+
notInList?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface UseDynamicFields {
|
|
14
|
+
fields: Record<string, DynamicFieldState>;
|
|
15
|
+
/** A pick committed `value` for `key` (select/Combobox/checkbox): one change call if any field refreshes on it. */
|
|
16
|
+
commit(key: string, value: unknown): void;
|
|
17
|
+
/** Focus entered `key`: remember the pre-edit form (the `previous` of a later blur commit). */
|
|
18
|
+
focus(key: string): void;
|
|
19
|
+
/** Focus left `key`: commit a text edit made since focus (never per keystroke). */
|
|
20
|
+
blur(key: string): void;
|
|
21
|
+
retry(key: string): void;
|
|
22
|
+
}
|
|
23
|
+
export declare function useDynamicFields(params: ActionParam[], values: Record<string, unknown>, dynamic: DynamicContext | undefined, onChange: (next: Record<string, unknown>) => void): UseDynamicFields;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@w6w/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "React components for w6w — central API management. Build plugins, apps and integrations on them.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://w6w.io",
|
|
@@ -73,7 +73,8 @@
|
|
|
73
73
|
"@uiw/react-codemirror": "^4.23.7",
|
|
74
74
|
"@w6w/expr": "^0.1.0",
|
|
75
75
|
"@xyflow/react": "^12.3.6",
|
|
76
|
-
"prism-react-renderer": "^2.4.1"
|
|
76
|
+
"prism-react-renderer": "^2.4.1",
|
|
77
|
+
"react-markdown": "^10.1.0"
|
|
77
78
|
},
|
|
78
79
|
"devDependencies": {
|
|
79
80
|
"@biomejs/biome": "^1.9.4",
|
|
@@ -100,6 +101,7 @@
|
|
|
100
101
|
"typecheck": "tsc -b --noEmit",
|
|
101
102
|
"test": "node --max-old-space-size=2048 --conditions=w6w-source --import ./src/test-jsx-loader.mjs --test --test-concurrency=4 --test-timeout=120000 src/__tests__/*.test.ts src/components/__tests__/*.test.ts",
|
|
102
103
|
"test:picker-layout": "bash test/picker-layout/run.sh",
|
|
104
|
+
"test:canvas-layer": "bash test/canvas-layer/run.sh",
|
|
103
105
|
"test:expr-template": "bash test/expr-template/run.sh",
|
|
104
106
|
"test:action-test-form": "bash test/action-test-form/run.sh",
|
|
105
107
|
"test:host-isolation": "bash test/host-isolation/run.sh",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* BudgetMeter — usage-vs-limit bar with a reserved segment.
|
|
2
|
+
*
|
|
3
|
+
* Token-only: every colour is a --w6w-* custom property, so a host restyles
|
|
4
|
+
* the meter (including the over-limit state) by overriding tokens, never by
|
|
5
|
+
* targeting a hex value here. */
|
|
6
|
+
.w6w-budget-meter {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: var(--w6w-sp-1);
|
|
10
|
+
}
|
|
11
|
+
.w6w-budget-meter-head {
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: baseline;
|
|
14
|
+
justify-content: space-between;
|
|
15
|
+
gap: var(--w6w-sp-2);
|
|
16
|
+
color: var(--w6w-muted);
|
|
17
|
+
}
|
|
18
|
+
.w6w-budget-meter-label {
|
|
19
|
+
color: var(--w6w-text);
|
|
20
|
+
}
|
|
21
|
+
.w6w-budget-meter-value {
|
|
22
|
+
font-variant-numeric: tabular-nums;
|
|
23
|
+
}
|
|
24
|
+
.w6w-budget-meter-track {
|
|
25
|
+
display: flex;
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: 8px;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
background: var(--w6w-panel-2);
|
|
30
|
+
border: 1px solid var(--w6w-border);
|
|
31
|
+
border-radius: var(--w6w-radius);
|
|
32
|
+
}
|
|
33
|
+
.w6w-budget-meter-used {
|
|
34
|
+
height: 100%;
|
|
35
|
+
background: var(--w6w-accent);
|
|
36
|
+
}
|
|
37
|
+
.w6w-budget-meter-reserved {
|
|
38
|
+
height: 100%;
|
|
39
|
+
background: var(--w6w-health-degraded);
|
|
40
|
+
}
|
|
41
|
+
.w6w-budget-meter-over .w6w-budget-meter-used {
|
|
42
|
+
background: var(--w6w-danger);
|
|
43
|
+
}
|
|
44
|
+
.w6w-budget-meter-over .w6w-budget-meter-value {
|
|
45
|
+
color: var(--w6w-danger);
|
|
46
|
+
}
|
|
@@ -36,15 +36,21 @@
|
|
|
36
36
|
.w6w-callable-list-body {
|
|
37
37
|
border: 1px solid var(--w6w-border);
|
|
38
38
|
border-radius: 8px;
|
|
39
|
-
|
|
39
|
+
background: var(--w6w-panel);
|
|
40
|
+
overflow: hidden;
|
|
40
41
|
}
|
|
41
|
-
.w6w-callable-list-
|
|
42
|
-
list-style: none;
|
|
43
|
-
margin: 0;
|
|
44
|
-
padding: 0;
|
|
42
|
+
.w6w-callable-list-main {
|
|
45
43
|
display: flex;
|
|
46
44
|
flex-direction: column;
|
|
47
|
-
gap: var(--w6w-sp-
|
|
45
|
+
gap: var(--w6w-sp-0-5);
|
|
46
|
+
min-width: 0;
|
|
47
|
+
text-align: left;
|
|
48
|
+
}
|
|
49
|
+
.w6w-callable-list-open {
|
|
50
|
+
all: unset;
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
display: block;
|
|
53
|
+
width: 100%;
|
|
48
54
|
}
|
|
49
55
|
.w6w-callable-list-trail {
|
|
50
56
|
display: inline-flex;
|
|
@@ -58,3 +64,6 @@
|
|
|
58
64
|
color: var(--w6w-muted);
|
|
59
65
|
font-size: var(--w6w-fs-xs);
|
|
60
66
|
}
|
|
67
|
+
.w6w-callable-list-row-desc {
|
|
68
|
+
display: block;
|
|
69
|
+
}
|