@w6w/ui 0.1.1 → 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 +27 -0
- package/README.md +7 -5
- package/dist/AppPicker.d.ts +48 -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/ConnectionHeader.d.ts +19 -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 +26 -0
- 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 +5 -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 +19 -1
- package/dist/components/BudgetMeter.d.ts +15 -0
- package/dist/components/CallableList.d.ts +58 -0
- package/dist/components/Combobox.d.ts +8 -1
- package/dist/components/ConnectionList.d.ts +43 -0
- 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/ListItem.d.ts +16 -6
- package/dist/components/ReliabilityChart.d.ts +10 -0
- package/dist/components/ReliabilityList.d.ts +47 -0
- package/dist/components/icons.d.ts +1 -1
- package/dist/connection-app-meta.d.ts +32 -0
- 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 +30 -2
- package/dist/index.mjs +2053 -1005
- package/dist/index.mjs.map +1 -1
- package/dist/note-markdown.d.ts +22 -0
- package/dist/provider.d.ts +73 -5
- package/dist/reliability-board-layout.d.ts +121 -0
- 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 +117 -3
- package/dist/use-dynamic-fields.d.ts +23 -0
- package/package.json +5 -3
- package/src/styles/_budget-meter.scss +46 -0
- package/src/styles/_callable-list.scss +69 -0
- package/src/styles/_canvas.scss +318 -0
- package/src/styles/_connections.scss +88 -0
- 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/_lists.scss +4 -0
- package/src/styles/_markdown.scss +20 -0
- package/src/styles/_reliability.scss +339 -0
- package/src/styles/_tester.scss +1 -14
- package/src/styles.css +1142 -17
- package/src/styles.scss +8 -0
- package/dist/ConfirmModal-8avl9Nv8.cjs +0 -11
- package/dist/ConfirmModal-8avl9Nv8.cjs.map +0 -1
- package/dist/ConfirmModal-CD-P8mhN.js +0 -6335
- package/dist/ConfirmModal-CD-P8mhN.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,26 @@
|
|
|
1
|
+
import { ConnectionSummary, ThemeMode } from './types.ts';
|
|
2
|
+
export interface EditConnectionModalProps {
|
|
3
|
+
/** The row being edited. `builtIn` rows have nothing to edit: the modal shows a notice only. */
|
|
4
|
+
connection: Pick<ConnectionSummary, "id" | "appId" | "authKey" | "displayName" | "builtIn" | "credentialId" | "lastTestOk">;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
/** Fired with the server's updated row. The typed credential is cleared before this runs. */
|
|
7
|
+
onSaved: (updated: ConnectionSummary) => void;
|
|
8
|
+
/** Reserved for icon variants, like the other modals. */
|
|
9
|
+
theme?: ThemeMode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Edit an existing connection: rename it and/or replace some of its credential fields. Runs on
|
|
13
|
+
* the {@link useW6WApi} adapter alone. The server never returns the stored secret, so credential
|
|
14
|
+
* fields start empty and blank means "keep what is stored" — only the fields the user filled are
|
|
15
|
+
* sent, and the server merges them over the stored credential. OAuth connections can be renamed
|
|
16
|
+
* here; re-authorizing is not part of this modal.
|
|
17
|
+
*
|
|
18
|
+
* A connection that uses a stored credential (`connection.credentialId`), when the host supplies
|
|
19
|
+
* `api.rotateCredential`, is split in two: Save only renames it and changes its binding (never the
|
|
20
|
+
* credential, which other connections may share), and "Rotate credential" is a separate explicit
|
|
21
|
+
* action that replaces the stored secret for every connection using it.
|
|
22
|
+
*
|
|
23
|
+
* Needs `api.updateConnection`. Without it (or for a `builtIn` row) there is no Save button, a
|
|
24
|
+
* one-line notice shows instead, and nothing is called. Hosts should not offer Edit in that case.
|
|
25
|
+
*/
|
|
26
|
+
export declare function EditConnectionModal({ connection, onClose, onSaved }: EditConnectionModalProps): import("react").JSX.Element;
|
package/dist/JsonEditor.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
import { ThemeMode } from './types.ts';
|
|
2
3
|
export interface JsonEditorProps {
|
|
3
4
|
value: string;
|
|
@@ -45,6 +46,13 @@ export interface JsonEditorProps {
|
|
|
45
46
|
* this prop existed.
|
|
46
47
|
*/
|
|
47
48
|
copyable?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Content overlaid inside the editor box at its top-right corner, a direct
|
|
51
|
+
* child of `.w6w-json-editor` (same overlay mechanism as `copyable`). The
|
|
52
|
+
* `ParamsForm` json field puts its `ƒx` here. Text keeps right padding so
|
|
53
|
+
* line 1 is not covered.
|
|
54
|
+
*/
|
|
55
|
+
overlay?: ReactNode;
|
|
48
56
|
}
|
|
49
57
|
/**
|
|
50
58
|
* JSON editor built on CodeMirror 6. Syntax highlighting, folding, gutter with
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface MarkdownProps {
|
|
2
|
+
content: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Pass a URL through only when its *parsed* protocol is allowlisted; relative,
|
|
7
|
+
* unparseable and every other scheme (javascript:, data:, vbscript:, any casing
|
|
8
|
+
* or whitespace trick the URL parser normalises) collapse to "".
|
|
9
|
+
*/
|
|
10
|
+
export declare function safeUrl(url: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* A leading `---` YAML block and the Markdown after it. Rendered as Markdown the block would
|
|
13
|
+
* come out as a rule plus a heading; it is metadata, so `Markdown` shows it in a collapsed
|
|
14
|
+
* section instead. Kept as text, not parsed — this package carries no YAML parser.
|
|
15
|
+
*/
|
|
16
|
+
export declare function splitFrontmatter(text: string): {
|
|
17
|
+
frontmatter: string | null;
|
|
18
|
+
body: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Renders imported, attacker-controllable note content. No `rehype-raw`: raw HTML
|
|
22
|
+
* is dropped (`skipHtml`), images are not rendered, and links are protocol-allowlisted.
|
|
23
|
+
* A leading YAML frontmatter block becomes a collapsed section above the body.
|
|
24
|
+
*/
|
|
25
|
+
export declare function Markdown({ content, className }: MarkdownProps): import("react").JSX.Element;
|
package/dist/ParamsForm.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DynamicContext } from './dynamic-fields.ts';
|
|
1
2
|
import { ActionParam } from './types.ts';
|
|
2
3
|
/**
|
|
3
4
|
* Evaluate a param's `showIf` predicate. `getValue` resolves a sibling field's
|
|
@@ -29,6 +30,11 @@ export interface ParamsFormProps {
|
|
|
29
30
|
/** Fired with the next values object on every edit. */
|
|
30
31
|
onChange: (values: Record<string, unknown>) => void;
|
|
31
32
|
readOnly?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Opt-in context for `options: { source: "resolveFields" }` params. Absent (or
|
|
35
|
+
* the host has no `resolveActionFields`) = those params render as plain inputs.
|
|
36
|
+
*/
|
|
37
|
+
dynamic?: DynamicContext;
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
34
40
|
* Renders an action's declared params as a form. Required params are always
|
|
@@ -40,7 +46,7 @@ export interface ParamsFormProps {
|
|
|
40
46
|
* expression bindings (`{ $: "steps.x.output.y" }`) authors drop to the JSON
|
|
41
47
|
* view; this form deals in literals.
|
|
42
48
|
*/
|
|
43
|
-
export declare function ParamsForm({ params, values, onChange, readOnly }: ParamsFormProps): import("react").JSX.Element;
|
|
49
|
+
export declare function ParamsForm({ params, values, onChange, readOnly, dynamic }: ParamsFormProps): import("react").JSX.Element;
|
|
44
50
|
/**
|
|
45
51
|
* One typed key/value entry in a `vars` param. `type` is a real value type only:
|
|
46
52
|
* `expression` is a binding *mode* (see {@link FxField}/`ExprValue`), not a value
|
|
@@ -2,7 +2,7 @@ import { NodeConfig } from './NodeConfigForm.tsx';
|
|
|
2
2
|
import { ExpressionStepSource } from './components/ExpressionOptions.tsx';
|
|
3
3
|
import { InternalNodeDef } from './flow-types.ts';
|
|
4
4
|
import { StepStartState } from './provider.tsx';
|
|
5
|
-
import { ActionParam, AppSummary, FunctionSummary, ThemeMode, WorkflowSummary } from './types.ts';
|
|
5
|
+
import { ActionParam, AppSummary, FunctionSummary, ThemeMode, WorkflowDetail, WorkflowSummary } from './types.ts';
|
|
6
6
|
/** The step the builder emits — the editor assigns the final `id`. `NodeConfig`
|
|
7
7
|
* carries the base settings (retry / onError / notes) set on the Config view. */
|
|
8
8
|
export interface BuiltStep extends NodeConfig {
|
|
@@ -27,7 +27,7 @@ export interface StepBuilderModalProps {
|
|
|
27
27
|
* `onAdd` — keeps the already-added node current without minting a second
|
|
28
28
|
* one. `id` is the id `onAdd` returned. Progressive commit (mint-then-update)
|
|
29
29
|
* only engages when this is supplied; omitted callers (the Functions/
|
|
30
|
-
* Endpoints pickers) keep the original one-shot "Add
|
|
30
|
+
* Endpoints pickers) keep the original one-shot "Add node" behavior.
|
|
31
31
|
*/
|
|
32
32
|
onDraftChange?: (id: string, step: BuiltStep) => void;
|
|
33
33
|
theme?: ThemeMode;
|
|
@@ -59,7 +59,7 @@ export interface StepBuilderModalProps {
|
|
|
59
59
|
* value lives instead of making the author re-find the tab.
|
|
60
60
|
*/
|
|
61
61
|
initialTab?: "connected" | "functions" | "workflows";
|
|
62
|
-
/** Modal heading. Defaults to "Add a
|
|
62
|
+
/** Modal heading. Defaults to "Add a node". */
|
|
63
63
|
title?: string;
|
|
64
64
|
/**
|
|
65
65
|
* Workflow-step context, when the builder is opened for a step that already
|
|
@@ -114,6 +114,11 @@ export interface StepBuilderModalProps {
|
|
|
114
114
|
* and the selected-app header omits the ` · v<version>` suffix for it.
|
|
115
115
|
*/
|
|
116
116
|
appsFilter?: (app: AppSummary) => boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Server-side id allow-list for the Apps-tab picker (forwarded as `ids` to the
|
|
119
|
+
* paged fetch), so the footer total equals the cards shown.
|
|
120
|
+
*/
|
|
121
|
+
appsIds?: string[];
|
|
117
122
|
/**
|
|
118
123
|
* Stop at "a connection is chosen" — no Action, no Configure/Test. Renders
|
|
119
124
|
* {@link AppConnectionOnlyConfig} in place of the usual `AppStepConfig`
|
|
@@ -126,6 +131,13 @@ export interface StepBuilderModalProps {
|
|
|
126
131
|
* selection alone. Only meaningful with {@link StepBuilderModalProps.connectionOnly}.
|
|
127
132
|
*/
|
|
128
133
|
onConnected?: (connectionId: string, app: AppSummary) => void;
|
|
134
|
+
/**
|
|
135
|
+
* Callable ids (`fn_…` / `wf_…`) the Functions and Workflows tabs, and the
|
|
136
|
+
* "Ready to use" tab, never offer — matched by id equality only. A Function
|
|
137
|
+
* editor passes its own id: a Function bound to itself has no state change,
|
|
138
|
+
* so the only outcome is an infinite loop. Absent ⇒ nothing is excluded.
|
|
139
|
+
*/
|
|
140
|
+
excludeCallableIds?: readonly string[];
|
|
129
141
|
}
|
|
130
142
|
/** The four representations of the Configure tab: form, full-step JSON,
|
|
131
143
|
* params-only JSON, node settings. */
|
|
@@ -155,7 +167,7 @@ export declare function ConfigViewToggle({ view, onChange, disabled, views, }: {
|
|
|
155
167
|
*
|
|
156
168
|
* Data + IO come from `useW6WApi()`, so mount it under `<W6WUIProvider>`.
|
|
157
169
|
*/
|
|
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;
|
|
170
|
+
export declare function StepBuilderModal({ onClose, onAdd, onDraftChange, theme, appsOnly, callables, initialTab, title, workflowId, stepId, upstreamSteps, initialApp, initialAction, initialConnection, initialWith, appsFilter, appsIds, connectionOnly, onConnected, excludeCallableIds, }: StepBuilderModalProps): import("react").JSX.Element;
|
|
159
171
|
/**
|
|
160
172
|
* Config form for a chosen internal node — its schema rendered through the same
|
|
161
173
|
* `ParamsForm` as app actions, seeded with the node's defaults. Emits the built
|
|
@@ -171,6 +183,7 @@ export declare function ControlStepConfig({ node, onAdd, onClose, onDraftChange,
|
|
|
171
183
|
/** The new step's known graph ancestors — see {@link StepBuilderModalProps.upstreamSteps}. */
|
|
172
184
|
upstreamSteps?: ExpressionStepSource[];
|
|
173
185
|
}): import("react").JSX.Element;
|
|
186
|
+
export declare function triggerFieldsOf(wf: WorkflowDetail): ActionParam[];
|
|
174
187
|
/**
|
|
175
188
|
* Config → test → add flow for a picked Function/Workflow target (D-12,
|
|
176
189
|
* D-15). Mints a single `@w6w/call` step — `family` only decides which
|
|
@@ -331,7 +344,12 @@ export declare function clampMinutes(raw: string, min: number): number;
|
|
|
331
344
|
*
|
|
332
345
|
* Exported for tests only (not re-exported from the package index).
|
|
333
346
|
*/
|
|
334
|
-
export declare function useReadyToUse(callables: readonly ("function" | "workflow")[], appsFilter?: (app: AppSummary) => boolean): ReadyToUse;
|
|
347
|
+
export declare function useReadyToUse(callables: readonly ("function" | "workflow")[], appsFilter?: (app: AppSummary) => boolean, excludeIds?: readonly string[], appsIds?: readonly string[]): ReadyToUse;
|
|
348
|
+
/** A copy of `items` without any entry whose `id` equals one of `ids` (id
|
|
349
|
+
* equality only — never name or position). No `ids` ⇒ an unchanged copy. */
|
|
350
|
+
export declare function withoutIds<T extends {
|
|
351
|
+
id: string;
|
|
352
|
+
}>(items: readonly T[], ids?: readonly string[]): T[];
|
|
335
353
|
export declare function AppStepConfig({ appId, app, onAdd, onClose, onDraftChange, onChangeApp, theme, workflowId, stepId, upstreamSteps, initialAction, initialConnection, initialWith, }: {
|
|
336
354
|
appId: string;
|
|
337
355
|
app?: AppSummary;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ExpressionOptions, ExpressionStepSource } from './components/ExpressionOptions.tsx';
|
|
2
2
|
import { FlowStep, FlowWorkflow } from './flow-types.ts';
|
|
3
3
|
import { RunState } from './run-visuals.ts';
|
|
4
|
+
import { StepProblem, StepProblems } from './step-problems.ts';
|
|
4
5
|
import { AppSummary } from './types.ts';
|
|
5
6
|
export interface WorkflowFlowEditorProps {
|
|
6
7
|
/** The workflow being edited. The editor re-derives layout when this changes identity. */
|
|
@@ -59,6 +60,14 @@ export interface WorkflowFlowEditorProps {
|
|
|
59
60
|
* back off a node.
|
|
60
61
|
*/
|
|
61
62
|
runState?: RunState;
|
|
63
|
+
/**
|
|
64
|
+
* Host-detected per-step problems, keyed by step id — an app step whose bound
|
|
65
|
+
* connection no longer exists gets an error ring + tooltip. Omitted ⇒ the
|
|
66
|
+
* canvas renders exactly as today. The host owns detection; this editor never
|
|
67
|
+
* infers a problem itself. Repaints live (same `value.id`) and is never
|
|
68
|
+
* persisted: `flowToWorkflow` never reads `data.stepProblem`.
|
|
69
|
+
*/
|
|
70
|
+
stepProblems?: StepProblems;
|
|
62
71
|
/**
|
|
63
72
|
* Fired the instant a step test starts — the ▶ collect form's Run button, or
|
|
64
73
|
* `StepEditModal`'s footer Test button — before the invoke goes out, so a host
|
|
@@ -95,14 +104,14 @@ type EditView = "props" | "json" | "settings";
|
|
|
95
104
|
* - Auto-layouted on load (topological columns + sibling rows).
|
|
96
105
|
* - Nodes render differently for action steps vs. control steps
|
|
97
106
|
* (`uses.app === "@w6w/control"`).
|
|
98
|
-
* - `+
|
|
107
|
+
* - `+ Node` opens a guided builder (pick app → connection → action → params,
|
|
99
108
|
* or a flow control). Drag nodes to reposition; connect handles to add edges.
|
|
100
109
|
* - Selecting a node reveals a toolbar above it: Edit / Duplicate / Delete.
|
|
101
110
|
* - Edit opens a modal with a Form ⇄ JSON toggle for that step.
|
|
102
111
|
* - Every meaningful change fires `onChange` with an updated Workflow.
|
|
103
112
|
*/
|
|
104
113
|
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, }: {
|
|
114
|
+
export declare function StepEditModal({ workflowId, step: initialStep, upstreamSteps, onChange, onClose, readOnly, initialView, fanOutCount, onTestRun, stepProblem, }: {
|
|
106
115
|
workflowId: string;
|
|
107
116
|
step: FlowStep;
|
|
108
117
|
/** Graph ancestors of this step (from `upstreamStateSources`); the incoming-state picker seeds from their saved tests. */
|
|
@@ -111,9 +120,11 @@ export declare function StepEditModal({ workflowId, step: initialStep, upstreamS
|
|
|
111
120
|
onClose: () => void;
|
|
112
121
|
readOnly?: boolean;
|
|
113
122
|
initialView?: EditView;
|
|
114
|
-
/** Most outgoing edges this
|
|
123
|
+
/** Most outgoing edges this node has in one lane; "Run next nodes" needs >= 2. */
|
|
115
124
|
fanOutCount?: number;
|
|
116
125
|
/** Fired the instant the footer Test button is clicked, before the test runs (T1.1.1). */
|
|
117
126
|
onTestRun?: () => void;
|
|
127
|
+
/** Host-supplied problem for this step; a dangling connection locks Configure/Test. */
|
|
128
|
+
stepProblem?: StepProblem;
|
|
118
129
|
}): import("react").JSX.Element;
|
|
119
130
|
export {};
|
package/dist/app-pages.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface AppsPageQuery {
|
|
|
5
5
|
q: string;
|
|
6
6
|
/** Server-side category filter (e.g. `"ai"` for the AI tab), or absent. */
|
|
7
7
|
category?: string;
|
|
8
|
+
/** Server-side id allow-list, or absent. */
|
|
9
|
+
ids?: string[];
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Two queries are the same fetch target when both fields match exactly
|
|
@@ -29,6 +31,8 @@ export interface AppsPageState {
|
|
|
29
31
|
/** Cursor to send on the NEXT "load more"; absent once the server has no more pages. */
|
|
30
32
|
cursor?: string;
|
|
31
33
|
hasMore: boolean;
|
|
34
|
+
/** The server's total for the current query, once a page has carried it. */
|
|
35
|
+
total?: number;
|
|
32
36
|
error?: string;
|
|
33
37
|
}
|
|
34
38
|
export declare function initialAppsPageState(query: AppsPageQuery, generation?: number): AppsPageState;
|
|
@@ -65,6 +69,7 @@ export type AppsPageAction =
|
|
|
65
69
|
apps: AppSummary[];
|
|
66
70
|
nextCursor?: string;
|
|
67
71
|
requestedCursor?: string;
|
|
72
|
+
total?: number;
|
|
68
73
|
} | {
|
|
69
74
|
type: "page-failed";
|
|
70
75
|
generation: number;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Workflow canvas (notes + sections); hand-mirror of core's `Workflow.canvas`. */
|
|
2
|
+
export interface CanvasNote {
|
|
3
|
+
id: string;
|
|
4
|
+
color: string;
|
|
5
|
+
position: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
size: {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
};
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CanvasSection {
|
|
16
|
+
id: string;
|
|
17
|
+
title: string;
|
|
18
|
+
color: string;
|
|
19
|
+
position: {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
};
|
|
23
|
+
size: {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
};
|
|
27
|
+
/** Member node ids; a node belongs to at most one section. */
|
|
28
|
+
nodes: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface FlowCanvas {
|
|
31
|
+
notes?: CanvasNote[];
|
|
32
|
+
sections?: CanvasSection[];
|
|
33
|
+
}
|
|
34
|
+
export declare const MAX_NOTES = 200;
|
|
35
|
+
export declare const MAX_SECTIONS = 200;
|
|
36
|
+
export declare const MAX_NOTE_BYTES = 10240;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
2
|
+
/** Live geometry keyed by note/section id. */
|
|
3
|
+
export interface LiveGeometry {
|
|
4
|
+
[id: string]: {
|
|
5
|
+
position?: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
size?: {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Round every stored number to an integer. */
|
|
16
|
+
export declare function roundGeometry<T extends {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
} | {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}>(g: T): T;
|
|
23
|
+
/**
|
|
24
|
+
* Stamp live geometry onto the stored canvas, rounded to integers. When
|
|
25
|
+
* `savePosition === false` the stored canvas is returned untouched (mirrors
|
|
26
|
+
* `flowToWorkflow`'s `withPosition`): not written is not erased.
|
|
27
|
+
*/
|
|
28
|
+
export declare function withCanvasGeometry(canvas: FlowCanvas, savePosition: boolean, live?: LiveGeometry): FlowCanvas;
|
|
29
|
+
/** Remove a deleted node id from every section. */
|
|
30
|
+
export declare function pruneSectionMembers(canvas: FlowCanvas, deletedNodeId: string): FlowCanvas;
|
|
31
|
+
/** Map a renamed node id in every section. */
|
|
32
|
+
export declare function renameSectionMember(canvas: FlowCanvas, from: string, to: string): FlowCanvas;
|
|
33
|
+
/** Put `nodeIds` into `sectionId`, removing them from any other section (at most one each). */
|
|
34
|
+
export declare function assignMembership(canvas: FlowCanvas, sectionId: string, nodeIds: string[]): FlowCanvas;
|
|
35
|
+
/** Ids of every section containing the node. */
|
|
36
|
+
export declare function sectionsContaining(canvas: FlowCanvas, nodeId: string): string[];
|
|
37
|
+
/** Enforce the caps: 200 notes, 200 sections, 10240 UTF-8 bytes per note content. */
|
|
38
|
+
export declare function clampCanvas(canvas: FlowCanvas): FlowCanvas;
|
|
39
|
+
/**
|
|
40
|
+
* The canvas to emit. Geometry is stamped (rounded) from the live canvas when `savePosition` is
|
|
41
|
+
* on; when off, every item already in `stored` keeps its STORED position/size (live edits render
|
|
42
|
+
* but are not written — mirrors node positions). Items new this session keep their live geometry.
|
|
43
|
+
*/
|
|
44
|
+
export declare function persistCanvas(canvas: FlowCanvas, stored: FlowCanvas | undefined, savePosition: boolean): FlowCanvas;
|
package/dist/code.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./CodeBlock-
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./CodeBlock-CulfbnZD.cjs"),o=require("./Copyable-DA6eiU7w.cjs");exports.CodeBlock=e.CodeBlock;exports.Copyable=o.Copyable;
|
|
2
2
|
//# sourceMappingURL=code.cjs.map
|
package/dist/code.mjs
CHANGED
|
@@ -13,10 +13,28 @@ interface Props {
|
|
|
13
13
|
enterSubmitProps?: {
|
|
14
14
|
onKeyDown: KeyboardEventHandler<HTMLElement>;
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* `"create"` (default) seeds each field from its manifest `default`. `"edit"` is for replacing
|
|
18
|
+
* part of a stored credential: it never seeds `default`, gives secret inputs the placeholder
|
|
19
|
+
* `•••••• (unchanged)`, and reports an emptied number input as `""` (not `0`) so the caller can
|
|
20
|
+
* treat blank as "keep what is stored".
|
|
21
|
+
*/
|
|
22
|
+
mode?: "create" | "edit";
|
|
16
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Parses every filled `json` field of `values` (they are held as raw text while typing). Returns
|
|
26
|
+
* the values with those fields parsed, or an `error` naming the offending field by label. The
|
|
27
|
+
* error NEVER contains the typed text or the parser's message (which can quote it): a pasted key
|
|
28
|
+
* file that is almost valid must not be echoed back into the page.
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseJsonFields(fields: AuthField[], values: Record<string, unknown>): {
|
|
31
|
+
values: Record<string, unknown>;
|
|
32
|
+
} | {
|
|
33
|
+
error: string;
|
|
34
|
+
};
|
|
17
35
|
/**
|
|
18
36
|
* Renders the form for an Auth method's `fields` declaration. Field shape
|
|
19
37
|
* comes from the app's manifest so no app-specific knowledge is needed here.
|
|
20
38
|
*/
|
|
21
|
-
export declare function AuthFieldsForm({ fields, values, onChange, enterSubmitProps }: Props): import("react").JSX.Element;
|
|
39
|
+
export declare function AuthFieldsForm({ fields, values, onChange, enterSubmitProps, mode, }: Props): import("react").JSX.Element;
|
|
22
40
|
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BudgetMeterProps {
|
|
2
|
+
/** Accessible name and the visible caption. */
|
|
3
|
+
label: string;
|
|
4
|
+
/** Amount already consumed. */
|
|
5
|
+
used: number;
|
|
6
|
+
/** Upper bound `used` is measured against. */
|
|
7
|
+
limit: number;
|
|
8
|
+
/** Amount held back but not yet spent. The segment renders only when > 0. */
|
|
9
|
+
reserved?: number;
|
|
10
|
+
/** Formats every number the meter prints (visible text and aria-valuetext). */
|
|
11
|
+
format?: (n: number) => string;
|
|
12
|
+
className?: string;
|
|
13
|
+
testId?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function BudgetMeter({ label, used, limit, reserved, format, className, testId, }: BudgetMeterProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { MouseEvent, ReactNode } from 'react';
|
|
2
|
+
/** One row of a {@link CallableList}. The host decides `archived`; the list never learns a kind. */
|
|
3
|
+
export interface CallableListRow {
|
|
4
|
+
id: string;
|
|
5
|
+
title: ReactNode;
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
archived: boolean;
|
|
8
|
+
/** Extra badges, rendered before the archived badge in the trailing slot. */
|
|
9
|
+
badges?: ReactNode;
|
|
10
|
+
/** Trailing content; sits inside the row's anchor when `getHref` is set, so keep it non-interactive. */
|
|
11
|
+
trailing?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export interface CallableListProps {
|
|
14
|
+
rows: readonly CallableListRow[];
|
|
15
|
+
title: ReactNode;
|
|
16
|
+
description?: ReactNode;
|
|
17
|
+
/** Shown (inside an EmptyState) when no rows exist at all and not `loading`. */
|
|
18
|
+
emptyCopy?: ReactNode;
|
|
19
|
+
/** Label of the New button. Defaults to "New". */
|
|
20
|
+
newLabel?: string;
|
|
21
|
+
/** Tooltip (`title` attribute) on each openable row. */
|
|
22
|
+
openRowTitle?: string;
|
|
23
|
+
testIds?: {
|
|
24
|
+
showArchived?: string;
|
|
25
|
+
importOpen?: string;
|
|
26
|
+
archivedBadge?: string;
|
|
27
|
+
};
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
error?: string | null;
|
|
30
|
+
/** The New button renders only when this is set. */
|
|
31
|
+
onCreate?: () => void;
|
|
32
|
+
/** New button is disabled and reads "Creating…" while true. */
|
|
33
|
+
creating?: boolean;
|
|
34
|
+
/** The Import button renders only when this is set. */
|
|
35
|
+
onImport?: () => void;
|
|
36
|
+
/** Row click. The event is passed through untouched; the host may `preventDefault`. */
|
|
37
|
+
onOpen?: (id: string, event: MouseEvent<Element>) => void;
|
|
38
|
+
/** When set, each row is a real `<a href>`. */
|
|
39
|
+
getHref?: (id: string) => string;
|
|
40
|
+
/** Controlled "Show archived". Omit for an uncontrolled toggle that starts off. */
|
|
41
|
+
showArchived?: boolean;
|
|
42
|
+
onShowArchivedChange?: (next: boolean) => void;
|
|
43
|
+
slots?: {
|
|
44
|
+
/** Replaces the default title/description block (the Show-archived toggle stays). */
|
|
45
|
+
header?: ReactNode;
|
|
46
|
+
/** Rendered before Import/New. */
|
|
47
|
+
actions?: ReactNode;
|
|
48
|
+
/** Replaces `emptyCopy`. */
|
|
49
|
+
empty?: ReactNode;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A presentational list of callables (Functions, Endpoints, Workflows): rows in, callbacks out.
|
|
54
|
+
* Owns only the archived filter and its toggle; it knows no router, query, modal or kind.
|
|
55
|
+
* Rows render through {@link DataTable}: a click handler with `onOpen`, anchors with `getHref`.
|
|
56
|
+
* No visible rows renders an {@link EmptyState}; when only archived rows exist it offers "Show archived".
|
|
57
|
+
*/
|
|
58
|
+
export declare function CallableList({ rows, title, description, emptyCopy, newLabel, openRowTitle, testIds, loading, error, onCreate, creating, onImport, onOpen, getHref, showArchived: showArchivedProp, onShowArchivedChange, slots, }: CallableListProps): import("react").JSX.Element;
|
|
@@ -15,10 +15,17 @@ export interface ComboboxProps {
|
|
|
15
15
|
forceSelection?: boolean;
|
|
16
16
|
/** Estimated option height in px, used by `auto` mode. Default 32. */
|
|
17
17
|
optionHeight?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Cap for the open list, in px — the list scrolls past it instead of growing.
|
|
20
|
+
* Default 240 (the shared value). A host inside an already-scrolling container
|
|
21
|
+
* (a modal body) passes a smaller one so the popup cannot add a second scroller.
|
|
22
|
+
*/
|
|
23
|
+
listMaxHeight?: number;
|
|
18
24
|
className?: string;
|
|
19
25
|
}
|
|
20
26
|
/** Combobox is chosen when the list would take more than 60% of the viewport. */
|
|
21
27
|
export declare function shouldUseCombobox(count: number, optionHeight: number, viewportHeight: number): boolean;
|
|
22
28
|
/** Case-insensitive substring match on label and value. */
|
|
23
29
|
export declare function filterOptions(options: ComboboxOption[], query: string): ComboboxOption[];
|
|
24
|
-
export declare
|
|
30
|
+
export declare const DEFAULT_LIST_MAX_HEIGHT = 240;
|
|
31
|
+
export declare function Combobox({ options, value, onChange, placeholder, disabled, "aria-label": ariaLabel, mode, forceSelection, optionHeight, listMaxHeight, className, }: ComboboxProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { MouseEvent, ReactNode } from 'react';
|
|
2
|
+
import { InlineAppMeta } from '../connection-app-meta.ts';
|
|
3
|
+
import { ConnectionSummary } from '../types.ts';
|
|
4
|
+
export interface ConnectionListProps {
|
|
5
|
+
connections: readonly ConnectionSummary[];
|
|
6
|
+
/**
|
|
7
|
+
* App meta by id, used for rows whose own inline `app` is `undefined` (an older server).
|
|
8
|
+
* Rows with an inline `app` object, or `null`, never consult it.
|
|
9
|
+
*/
|
|
10
|
+
appsById?: ReadonlyMap<string, InlineAppMeta>;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
error?: string | null;
|
|
13
|
+
/** Row click. The event is passed through untouched; the host may `preventDefault`. */
|
|
14
|
+
onOpen?: (id: string, event: MouseEvent<Element>) => void;
|
|
15
|
+
/** When set, each openable row is a real `<a href>`. */
|
|
16
|
+
getHref?: (id: string) => string;
|
|
17
|
+
/**
|
|
18
|
+
* Renders an Edit button per row. Pass it only when the host's adapter has `updateConnection`
|
|
19
|
+
* (otherwise the modal it opens has nothing to save with).
|
|
20
|
+
*/
|
|
21
|
+
onEdit?: (connection: ConnectionSummary) => void;
|
|
22
|
+
/** Renders a Delete button per row. Confirmation and the delete call are the host's. */
|
|
23
|
+
onDelete?: (connection: ConnectionSummary) => void;
|
|
24
|
+
/** Disables every Delete button while a delete is in flight. */
|
|
25
|
+
busy?: boolean;
|
|
26
|
+
slots?: {
|
|
27
|
+
/** Heading block above the rows. */
|
|
28
|
+
header?: ReactNode;
|
|
29
|
+
/** Trailing action(s) next to the header (e.g. an "Add" button). */
|
|
30
|
+
actions?: ReactNode;
|
|
31
|
+
/** Shown when there are no connections and the list is not `loading`. */
|
|
32
|
+
empty?: ReactNode;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A presentational list of connections: rows in, callbacks out; it needs no provider. Rows render
|
|
37
|
+
* through {@link DataTable} (name/app, status, and an Edit/Delete column that is never a link).
|
|
38
|
+
*
|
|
39
|
+
* A `builtIn` row (the server's synthetic "no credential" entry) is a plain non-interactive item:
|
|
40
|
+
* no link, no `onOpen`, no Edit, no Delete, because the server 404s get/test/delete on its id.
|
|
41
|
+
* Detection is `row.builtIn === true`, never an id prefix.
|
|
42
|
+
*/
|
|
43
|
+
export declare function ConnectionList({ connections, appsById, loading, error, onOpen, getHref, onEdit, onDelete, busy, slots, }: ConnectionListProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AuthField, ConnectionBinding, CredentialSummary, ServiceAccountConfig } from '../types.ts';
|
|
2
|
+
export interface CredentialPickerProps {
|
|
3
|
+
/** Credentials to offer. Pass them already filtered; this component renders them as given. */
|
|
4
|
+
credentials: CredentialSummary[];
|
|
5
|
+
/** `"existing"` picks one of `credentials`; `"new"` is for the caller's create form. */
|
|
6
|
+
mode: "existing" | "new";
|
|
7
|
+
onModeChange: (mode: "existing" | "new") => void;
|
|
8
|
+
/** The chosen credential id (`""` for none). Only used in `"existing"` mode. */
|
|
9
|
+
selectedId: string;
|
|
10
|
+
onSelect: (id: string) => void;
|
|
11
|
+
/** False hides the "Use existing" choice (nothing to choose from). Default true. */
|
|
12
|
+
canUseExisting?: boolean;
|
|
13
|
+
/** The contract the credential must satisfy, shown as a hint. */
|
|
14
|
+
contract?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The Use existing / Create new switch of a connection's Credential step, plus the list of stored
|
|
18
|
+
* credentials. Presentational: no API access, no state of its own. Each option shows the
|
|
19
|
+
* credential's name and its non-secret `display` values, never a payload. The "Create new" form
|
|
20
|
+
* itself (name + fields) is the caller's, rendered beneath this.
|
|
21
|
+
*/
|
|
22
|
+
export declare function CredentialPicker({ credentials, mode, onModeChange, selectedId, onSelect, canUseExisting, contract, }: CredentialPickerProps): import("react").JSX.Element;
|
|
23
|
+
/**
|
|
24
|
+
* The binding fields a `serviceAccount` auth asks for on a connection. `delegatedUser` is always
|
|
25
|
+
* labelled "Impersonated user" (the person the credential acts as, never the connection's owner),
|
|
26
|
+
* is absent when impersonation is `"none"` even if declared, and is synthesised when impersonation
|
|
27
|
+
* is allowed but the auth declares no such field.
|
|
28
|
+
*/
|
|
29
|
+
export declare function bindingFieldsFor(sa: ServiceAccountConfig): AuthField[];
|
|
30
|
+
/**
|
|
31
|
+
* Maps typed binding values to the wire `binding`: `delegatedUser` stays top-level, every other key
|
|
32
|
+
* goes under `settings`, blank values are dropped, and an empty result is `undefined`. `scopes` is
|
|
33
|
+
* never sent (the server applies the auth's declared scopes).
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildBinding(fields: AuthField[], values: Record<string, unknown>): ConnectionBinding | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MouseEvent, ReactNode } from 'react';
|
|
2
|
+
export interface DataTableColumn<Row> {
|
|
3
|
+
key: string;
|
|
4
|
+
header: ReactNode;
|
|
5
|
+
/** Omitted ⇒ the cell shows `String(row[key] ?? "")`. */
|
|
6
|
+
render?: (row: Row) => ReactNode;
|
|
7
|
+
width?: string;
|
|
8
|
+
align?: "left" | "right" | "center";
|
|
9
|
+
/** With `getRowHref`, wrap this column's cells in an anchor. Default true. */
|
|
10
|
+
link?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface DataTableProps<Row> {
|
|
13
|
+
columns: readonly DataTableColumn<Row>[];
|
|
14
|
+
rows: readonly Row[];
|
|
15
|
+
rowKey: (row: Row) => string;
|
|
16
|
+
/** Row click. The event is passed through untouched; the host may `preventDefault`. */
|
|
17
|
+
onRowClick?: (row: Row, e: MouseEvent<Element>) => void;
|
|
18
|
+
/** When set, every cell of a `link !== false` column wraps its content in `<a href>`. */
|
|
19
|
+
getRowHref?: (row: Row) => string | undefined;
|
|
20
|
+
/** Rendered in place of the body when there are no rows and not `loading`. */
|
|
21
|
+
empty?: ReactNode;
|
|
22
|
+
loading?: boolean;
|
|
23
|
+
className?: string;
|
|
24
|
+
testId?: string;
|
|
25
|
+
rowTestId?: (row: Row) => string | undefined;
|
|
26
|
+
}
|
|
27
|
+
export declare function DataTable<Row>(props: DataTableProps<Row>): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface EmptyStateProps {
|
|
3
|
+
title?: ReactNode;
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
action?: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
testId?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function EmptyState({ title, children, action, className, testId }: EmptyStateProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { MouseEvent, ReactNode } from 'react';
|
|
2
2
|
export interface ListItemProps {
|
|
3
3
|
/** Primary label — prominent, single-line with ellipsis overflow. */
|
|
4
4
|
title: ReactNode;
|
|
@@ -6,12 +6,21 @@ export interface ListItemProps {
|
|
|
6
6
|
subtitle?: ReactNode;
|
|
7
7
|
/** Leading slot (e.g. an `<AppIcon />` or status glyph). */
|
|
8
8
|
icon?: ReactNode;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Trailing slot pushed to the right (e.g. a badge or chevron). With `href` it sits INSIDE the
|
|
11
|
+
* anchor, so it must stay non-interactive (no buttons or links).
|
|
12
|
+
*/
|
|
10
13
|
trailing?: ReactNode;
|
|
11
14
|
/** Highlights the row as selected/current. Reflected as `aria-pressed` when clickable. */
|
|
12
15
|
active?: boolean;
|
|
13
|
-
/**
|
|
14
|
-
|
|
16
|
+
/**
|
|
17
|
+
* When provided, the row renders as a focusable, keyboard-activatable button — or, with `href`,
|
|
18
|
+
* still fires on a click of the anchor. Receives the click event; ListItem never calls
|
|
19
|
+
* `preventDefault`, so the host decides whether the browser navigates.
|
|
20
|
+
*/
|
|
21
|
+
onClick?: (event: MouseEvent<HTMLElement>) => void;
|
|
22
|
+
/** When provided, the row renders as a real `<a href>` (middle-click, copy link, new tab). */
|
|
23
|
+
href?: string;
|
|
15
24
|
/** Accessible label for the clickable row (falls back to the `title` DOM text). */
|
|
16
25
|
ariaLabel?: string;
|
|
17
26
|
}
|
|
@@ -20,6 +29,7 @@ export interface ListItemProps {
|
|
|
20
29
|
*
|
|
21
30
|
* Mirrors the look/behaviour of the saved-test button rows it replaces. When
|
|
22
31
|
* `onClick` is given it renders a `<button type="button">` (focusable, Enter/Space
|
|
23
|
-
* activatable) with `aria-pressed={active}`;
|
|
32
|
+
* activatable) with `aria-pressed={active}`; with `href` an `<a href>` (the click still reaches
|
|
33
|
+
* `onClick`); otherwise a plain, non-interactive row.
|
|
24
34
|
*/
|
|
25
|
-
export declare function ListItem({ title, subtitle, icon, trailing, active, onClick, ariaLabel, }: ListItemProps): import("react").JSX.Element;
|
|
35
|
+
export declare function ListItem({ title, subtitle, icon, trailing, active, onClick, href, ariaLabel, }: ListItemProps): import("react").JSX.Element;
|