@w6w/embed 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/LICENSE +105 -0
- package/README.md +166 -2
- package/dist/W6WEmbedProvider.d.ts +29 -0
- package/dist/chrome/CallFromCodeButton.d.ts +155 -0
- package/dist/chrome/CallableSettingsModal.d.ts +17 -0
- package/dist/chrome/ConfirmModal.d.ts +20 -0
- package/dist/chrome/DangerZone.d.ts +19 -0
- package/dist/chrome/ExecutionProfileHeader.d.ts +69 -0
- package/dist/chrome/HistoryButton.d.ts +8 -0
- package/dist/chrome/HistoryModal.d.ts +9 -0
- package/dist/chrome/HistoryView.d.ts +15 -0
- package/dist/chrome/ImportSpecModal.d.ts +40 -0
- package/dist/chrome/JsonToggle.d.ts +51 -0
- package/dist/chrome/Modal.d.ts +20 -0
- package/dist/chrome/RightRail.d.ts +24 -0
- package/dist/chrome/TagEditor.d.ts +23 -0
- package/dist/chrome/VersionHistoryModal.d.ts +38 -0
- package/dist/chrome/history-open-run.d.ts +7 -0
- package/dist/chrome/index.d.ts +36 -0
- package/dist/chrome/workspace.d.ts +67 -0
- package/dist/client-context-CX61Bgw-.js +16 -0
- package/dist/client-context-CX61Bgw-.js.map +1 -0
- package/dist/draft/autosave-flush.d.ts +63 -0
- package/dist/draft/autosave.d.ts +68 -0
- package/dist/draft/client-context.d.ts +8 -0
- package/dist/draft/draft-registry.d.ts +14 -0
- package/dist/draft/index.d.ts +15 -0
- package/dist/draft/use-workflow-draft.d.ts +67 -0
- package/dist/draft/workflow-save.d.ts +48 -0
- package/dist/draft-registry-YF0tqNN0.js +49 -0
- package/dist/draft-registry-YF0tqNN0.js.map +1 -0
- package/dist/draft.d.ts +2 -0
- package/dist/draft.mjs +18 -0
- package/dist/draft.mjs.map +1 -0
- package/dist/editor/WorkflowEditor.d.ts +12 -0
- package/dist/editor/WorkflowSettingsModal.d.ts +17 -0
- package/dist/editor/definition.d.ts +31 -0
- package/dist/editor/editor-apps.d.ts +7 -0
- package/dist/editor/types.d.ts +34 -0
- package/dist/editor.d.ts +9 -0
- package/dist/editor.mjs +2170 -0
- package/dist/editor.mjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +67 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/callable-descriptors.d.ts +77 -0
- package/dist/lib/callable-kind.d.ts +13 -0
- package/dist/lib/code-rail.d.ts +45 -0
- package/dist/lib/document-sources.d.ts +26 -0
- package/dist/lib/error-handler-self.d.ts +25 -0
- package/dist/lib/history-query.d.ts +135 -0
- package/dist/lib/import-paste.d.ts +41 -0
- package/dist/lib/index.d.ts +17 -0
- package/dist/lib/new-id.d.ts +10 -0
- package/dist/lib/rail-settings.d.ts +196 -0
- package/dist/lib/save-invalidation.d.ts +24 -0
- package/dist/lib/sdk-snippets.d.ts +96 -0
- package/dist/lib/settings-rail.d.ts +68 -0
- package/dist/lib/slug.d.ts +69 -0
- package/dist/lib/spec-import-invalidation.d.ts +48 -0
- package/dist/lib/tag-editor.d.ts +36 -0
- package/dist/lib/trigger-preview.d.ts +89 -0
- package/dist/lib/workflow-live-run.d.ts +165 -0
- package/dist/lib/workflow-poll.d.ts +8 -0
- package/dist/lib/workflow-route.d.ts +26 -0
- package/dist/lib/workflow-settings.d.ts +72 -0
- package/dist/lib/workflow-validity.d.ts +92 -0
- package/dist/lib/workflow-variables.d.ts +106 -0
- package/dist/lib.d.ts +2 -0
- package/dist/lib.mjs +62 -0
- package/dist/lib.mjs.map +1 -0
- package/dist/project-context-Dbk0Gr1K.js +16 -0
- package/dist/project-context-Dbk0Gr1K.js.map +1 -0
- package/dist/project-context.d.ts +11 -0
- package/dist/rail/CodeTool.d.ts +2 -0
- package/dist/rail/ErrorHandlingTool.d.ts +22 -0
- package/dist/rail/ExpressionScope.d.ts +21 -0
- package/dist/rail/SettingsTool.d.ts +27 -0
- package/dist/rail/editor-tools.d.ts +2 -0
- package/dist/rail/rail-env.d.ts +18 -0
- package/dist/rail/settings-sections.d.ts +93 -0
- package/dist/repos/documents.d.ts +102 -0
- package/dist/repos/history.d.ts +24 -0
- package/dist/repos/index.d.ts +22 -0
- package/dist/repos/spec-import.d.ts +44 -0
- package/dist/repos/step-tests.d.ts +19 -0
- package/dist/repos/vars.d.ts +25 -0
- package/dist/repos/vault.d.ts +24 -0
- package/dist/repos/versions.d.ts +112 -0
- package/dist/repos.d.ts +2 -0
- package/dist/repos.mjs +94 -0
- package/dist/repos.mjs.map +1 -0
- package/dist/slug-ByKQgxrf.js +642 -0
- package/dist/slug-ByKQgxrf.js.map +1 -0
- package/dist/spec-import-HgO7ZkLZ.js +898 -0
- package/dist/spec-import-HgO7ZkLZ.js.map +1 -0
- package/dist/spec-import-invalidation-D3retX4Q.js +18 -0
- package/dist/spec-import-invalidation-D3retX4Q.js.map +1 -0
- package/dist/use-workflow-draft-oI02dsP-.js +314 -0
- package/dist/use-workflow-draft-oI02dsP-.js.map +1 -0
- package/package.json +71 -3
- package/src/styles.css +829 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, ALv2 Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-ALv2
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 w6w-io
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or
|
|
34
|
+
service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software
|
|
39
|
+
that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee
|
|
52
|
+
using the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to
|
|
59
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
+
remove any copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
+
|
|
77
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
+
|
|
81
|
+
### Trademarks
|
|
82
|
+
|
|
83
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
+
trademarks, trade names, service marks or product names.
|
|
86
|
+
|
|
87
|
+
## Grant of Future License
|
|
88
|
+
|
|
89
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
91
|
+
the date we make the Software available. On or after that date, you may use the
|
|
92
|
+
Software under the Apache License, Version 2.0, in which case the following
|
|
93
|
+
will apply:
|
|
94
|
+
|
|
95
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
96
|
+
this file except in compliance with the License.
|
|
97
|
+
|
|
98
|
+
You may obtain a copy of the License at
|
|
99
|
+
|
|
100
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
101
|
+
|
|
102
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
103
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
104
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
105
|
+
specific language governing permissions and limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,167 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @w6w/embed
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Embed w6w in a host React app: one provider that wires the w6w API client, `@w6w/ui`'s components
|
|
4
|
+
and an identity-scoped query cache to your own sign-in, and a managed workflow editor
|
|
5
|
+
(`<WorkflowEditor>`) you mount as a route.
|
|
6
|
+
|
|
7
|
+
License: [FSL-1.1-ALv2](./LICENSE) (Functional Source License). This package is
|
|
8
|
+
**source-available**, not open source: the licence's Competing-Use clause applies, and each version
|
|
9
|
+
converts to Apache-2.0 after two years. `@w6w/sdk`, `@w6w/react` and `@w6w/ui`, which it depends on,
|
|
10
|
+
stay MIT.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm i @w6w/embed react react-dom
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
That is the only w6w package you install. `@w6w/sdk`, `@w6w/react`, `@w6w/ui` and
|
|
19
|
+
`@tanstack/react-query` come with it as dependencies; `react` and `react-dom` (18 or later) are
|
|
20
|
+
yours. Import the one stylesheet once, at your app's root:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import "@w6w/embed/styles.css"; // @w6w/ui's styles, React Flow base included
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## The provider
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { W6WEmbedProvider } from "@w6w/embed";
|
|
30
|
+
|
|
31
|
+
function Host({ user }: { user: { id: string; accountId: string } }) {
|
|
32
|
+
return (
|
|
33
|
+
<W6WEmbedProvider
|
|
34
|
+
apiOrigin="https://api.w6w.io"
|
|
35
|
+
identityKey={`${user.id}:${user.accountId}`}
|
|
36
|
+
getSession={() => fetch("/api/w6w-session", { method: "POST" }).then((r) => r.json())} // -> {token, expiresAt}
|
|
37
|
+
project="proj_123" // optional default project, see "The project rule"
|
|
38
|
+
theme="dark" // optional: follow your host's theme
|
|
39
|
+
>
|
|
40
|
+
{/* @w6w/ui components, @w6w/react hooks and <WorkflowEditor> work here */}
|
|
41
|
+
</W6WEmbedProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`getSession` calls an endpoint on **your** backend that mints an account-scoped session for the
|
|
47
|
+
signed-in user with `createEmbedSessionClient` from `@w6w/sdk/server`; the tenant client secret
|
|
48
|
+
never reaches the browser. The recipe is in the guide at `/guides/embed/`.
|
|
49
|
+
|
|
50
|
+
- `identityKey` names who is signed in. When it changes, the API client **and** the query cache are
|
|
51
|
+
replaced and the subtree re-mounts, so nothing cached for the previous identity is shown to the
|
|
52
|
+
next one.
|
|
53
|
+
- The provider owns its `QueryClient`; it does not use, and does not need, one from your app.
|
|
54
|
+
- `ready={false}` holds every read until you have a user; `project` sets the default project.
|
|
55
|
+
|
|
56
|
+
### Next.js server components
|
|
57
|
+
|
|
58
|
+
A server component cannot pass a plain function to a client component, so a `getSession` written
|
|
59
|
+
inline there does not work. Define it as an inline server action instead:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// app/page.tsx (a server component)
|
|
63
|
+
import { createEmbedSessionClient } from "@w6w/sdk/server";
|
|
64
|
+
import { W6WEmbedProvider } from "@w6w/embed";
|
|
65
|
+
import { currentUser } from "./your-auth"; // YOUR server-side session lookup
|
|
66
|
+
|
|
67
|
+
const sessions = createEmbedSessionClient({
|
|
68
|
+
baseUrl: process.env.W6W_BASE_URL!,
|
|
69
|
+
clientId: process.env.W6W_TENANT_CLIENT_ID!,
|
|
70
|
+
clientSecret: process.env.W6W_TENANT_CLIENT_SECRET!, // stays on the server
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export default async function Page() {
|
|
74
|
+
const user = await currentUser(); // from your own session, on the server
|
|
75
|
+
if (!user) return null;
|
|
76
|
+
|
|
77
|
+
async function getSession() {
|
|
78
|
+
"use server";
|
|
79
|
+
const u = await currentUser(); // no arguments: who is signed in comes from the server
|
|
80
|
+
if (!u) throw new Error("unauthenticated");
|
|
81
|
+
const s = await sessions.create({ subject: u.id, accountRef: u.companyId });
|
|
82
|
+
return { token: s.token, expiresAt: s.expiresAt }; // nothing else leaves the server
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<W6WEmbedProvider
|
|
87
|
+
apiOrigin={process.env.W6W_BASE_URL!}
|
|
88
|
+
identityKey={`${user.id}:${user.companyId}`} // the same server-side user
|
|
89
|
+
getSession={getSession}
|
|
90
|
+
>
|
|
91
|
+
{/* a client component renders <WorkflowEditor> here */}
|
|
92
|
+
</W6WEmbedProvider>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
A server action is a public POST endpoint: anyone can call it with any arguments. So `getSession`
|
|
98
|
+
must **never accept the subject or the account from its caller**, and takes no arguments at all.
|
|
99
|
+
It reads the signed-in user from your own server-side session, mints for that user only, and
|
|
100
|
+
returns only `{ token, expiresAt }`. The tenant client secret stays on the server, and
|
|
101
|
+
`identityKey` is computed from the same server-side user. In a client component, the `fetch` form
|
|
102
|
+
above stays the default.
|
|
103
|
+
|
|
104
|
+
## The editor
|
|
105
|
+
|
|
106
|
+
Mount the managed editor as a route in your app. It is loaded lazily, so it adds nothing to your
|
|
107
|
+
bundle until the route renders:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { WorkflowEditor } from "@w6w/embed/editor";
|
|
111
|
+
|
|
112
|
+
function WorkflowRoute({ workflowId }: { workflowId: string }) {
|
|
113
|
+
return (
|
|
114
|
+
<WorkflowEditor
|
|
115
|
+
workflowId={workflowId}
|
|
116
|
+
project="proj_123" // optional when the provider has one
|
|
117
|
+
onNavigate={(to) => {/* route inside your app */}}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Props: `workflowId` (required), `project`, `initialRunId`, `onNavigate` and `slots`. `onNavigate` is
|
|
124
|
+
optional (default: a no-op) and hands navigation (back to the list, or to another workflow) to your
|
|
125
|
+
router; `slots` lets you place your own elements in the editor chrome; `initialRunId` opens the
|
|
126
|
+
editor on a run. The editor must render inside `<W6WEmbedProvider>`.
|
|
127
|
+
|
|
128
|
+
### The project rule
|
|
129
|
+
|
|
130
|
+
The editor takes its project from its `project` prop, else from the provider's `project`. Saves
|
|
131
|
+
never fall back to the account's default project, because a save without a project would silently
|
|
132
|
+
move the workflow. With neither set (or with `project={null}` or `""`, which refuses even when the
|
|
133
|
+
provider has one), the editor opens with saving and publishing disabled and a "project required"
|
|
134
|
+
message.
|
|
135
|
+
|
|
136
|
+
### Autosave and switching identity
|
|
137
|
+
|
|
138
|
+
Edits autosave. When `identityKey` changes, a pending save is first flushed into the account it
|
|
139
|
+
belongs to, and only then does the provider swap to the new identity. There is no discard path: a
|
|
140
|
+
save that fails or times out does not block the switch, and is never retried into the new account.
|
|
141
|
+
|
|
142
|
+
### Theming
|
|
143
|
+
|
|
144
|
+
The editor's chrome is styled by the same `@w6w/embed/styles.css`. Every rule is scoped under the
|
|
145
|
+
editor's root element, class `w6w-embed-root`, so it does not leak into your page. The palette
|
|
146
|
+
comes from the nearest `[data-theme]` ancestor: the provider's `theme` prop puts one around the
|
|
147
|
+
tree. Omit `theme` and the editor follows `data-theme` on `<html>` if you set it, else the OS
|
|
148
|
+
preference. The editor fills its parent (`width` and `height` 100%), so give its container a height.
|
|
149
|
+
|
|
150
|
+
## Console exclusions
|
|
151
|
+
|
|
152
|
+
Your host code makes no `client.console` call. The package uses a public `@w6w/sdk` operation
|
|
153
|
+
wherever one exists, and every remaining `client.console` or raw `request()` site is listed here
|
|
154
|
+
with its reason.
|
|
155
|
+
|
|
156
|
+
| File | Call | Reason |
|
|
157
|
+
| --- | --- | --- |
|
|
158
|
+
| `src/repos/workflows.ts` | `console.workflows.listRuns`, `console.workflows.getRun` + `pollRunToTerminal` | no public run-list or run-get operation; the run poll is what the Run feature needs |
|
|
159
|
+
| `src/repos/workflows.ts` | `console.workflows.upsert` | creating a workflow in a named project has no public operation |
|
|
160
|
+
| `src/lib/history-query.ts` | `console.workflows.getRun`; raw `GET /history`, `GET /history/stats`, `GET /invocations/:id` | no public history or invocation operation |
|
|
161
|
+
| `src/repos/step-tests.ts` | `console.stepTests.list`, `.save`, `.recordRun` | no public operation |
|
|
162
|
+
| `src/repos/vault.ts` | `console.vault.list`, `.seal`, `.create`, `.update`, `.delete` | vault is outside the public contract; used to add and seal a secret from the expression editor |
|
|
163
|
+
| `src/repos/documents.ts` | raw `POST /documents/:id/sync` | no public operation |
|
|
164
|
+
| `src/repos/spec-import.ts` | raw `POST /spec/import` | no public operation (Settings import) |
|
|
165
|
+
| `src/repos/vars.ts` | raw `GET /vars`, `POST /vars`, `PATCH /vars/:id`, `DELETE /vars/:id` | the SDK's `vars` methods take no options argument, so they cannot send `?project=` |
|
|
166
|
+
| `src/repos/versions.ts` | raw `GET /:c/:id/versions`, `GET /:c/:id/versions/:v`, `POST /:c/:id/publish`, `POST /:c/:id/:x`, `POST /:c/:id/versions/:v/revert`, `POST /:c/:id/versions/:v/:x` | the endpoint arm has no public version operation; the function arm of invoke-version keeps the raw invocation frame, which `functions.runVersion` unwraps |
|
|
167
|
+
| `@w6w/react` `createW6WUiAdapter` (canvas) | `console.apps.*`, saved and step tests, subscriptions | the adapter's own call sites, used by the canvas from `@w6w/ui/flow` |
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { W6WSession } from '@w6w/react';
|
|
2
|
+
import { FetchLike } from '@w6w/sdk';
|
|
3
|
+
import { ThemeMode } from '@w6w/ui';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
export interface W6WEmbedProviderProps {
|
|
6
|
+
/** The w6w API origin, e.g. `"https://api.w6w.io"`. */
|
|
7
|
+
apiOrigin: string;
|
|
8
|
+
/**
|
|
9
|
+
* Mints a session for the CURRENT host user (`{token, expiresAt, expiresIn?}`). Always the
|
|
10
|
+
* latest callback; the provider caches and renews the result.
|
|
11
|
+
*/
|
|
12
|
+
getSession: () => Promise<W6WSession>;
|
|
13
|
+
/**
|
|
14
|
+
* Which signed-in identity this provider speaks for (e.g. `${userId}:${accountId}`). Changing it
|
|
15
|
+
* rebuilds the API client AND replaces the `QueryClient`, so nothing cached for the previous
|
|
16
|
+
* identity is ever shown under the new one.
|
|
17
|
+
*/
|
|
18
|
+
identityKey: string;
|
|
19
|
+
/** Force the `@w6w/ui` theme to follow the host's. Omit to resolve it the library's default way. */
|
|
20
|
+
theme?: ThemeMode;
|
|
21
|
+
/** Gates every read hook while `false` (default `true`) — e.g. until the host has a user. */
|
|
22
|
+
ready?: boolean;
|
|
23
|
+
/** Default project id for project-scoped operations. */
|
|
24
|
+
project?: string;
|
|
25
|
+
/** Transport override (tests, request recording). Defaults to `globalThis.fetch`. */
|
|
26
|
+
fetch?: FetchLike;
|
|
27
|
+
children: ReactNode;
|
|
28
|
+
}
|
|
29
|
+
export declare function W6WEmbedProvider({ apiOrigin, getSession, identityKey, theme, ready, project, fetch, children, }: W6WEmbedProviderProps): ReactNode;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { SnippetCallable, TriggerPreview } from '@w6w/embed/lib';
|
|
2
|
+
/**
|
|
3
|
+
* "Call from code" — the button that shows how to reach the thing you are
|
|
4
|
+
* looking at from the Node SDK (`@w6w/sdk`), the CLI (`w6w`), or the Python
|
|
5
|
+
* SDK (`w6w`, PyPI).
|
|
6
|
+
*
|
|
7
|
+
* Mounted on the pages whose resource the wrapper contract actually covers.
|
|
8
|
+
* Everything shown comes from `../lib/sdk-snippets.ts`, which builds against
|
|
9
|
+
* `packages/wrappers/endpoints.json` — this component owns presentation only
|
|
10
|
+
* and never composes an API call of its own.
|
|
11
|
+
*
|
|
12
|
+
* A modal rather than an inline block: the snippet is reference material a
|
|
13
|
+
* reader wants once and then dismisses, and inlining it would push the page's
|
|
14
|
+
* real content (a function's inputs, a workflow's steps) below the fold for
|
|
15
|
+
* everyone who is not currently writing a client.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Tabs, in the order the contract lists the wrappers — then `curl`, which is
|
|
19
|
+
* not a wrapper at all and therefore comes last.
|
|
20
|
+
*
|
|
21
|
+
* The strip renders only the tabs the BUILT snippet actually carries
|
|
22
|
+
* (`Snippet.curl` is optional): a Function, Endpoint or Workflow shows all
|
|
23
|
+
* four tabs, while a Connection, Var or Document — which have no fixed
|
|
24
|
+
* single-resource route to curl against — still show exactly the three
|
|
25
|
+
* Node/CLI/Python tabs they show today.
|
|
26
|
+
*/
|
|
27
|
+
declare const TABS: readonly [{
|
|
28
|
+
readonly id: "node";
|
|
29
|
+
readonly label: "Node";
|
|
30
|
+
readonly language: "TypeScript";
|
|
31
|
+
readonly grammar: "typescript";
|
|
32
|
+
readonly icon: "lang-node";
|
|
33
|
+
}, {
|
|
34
|
+
readonly id: "cli";
|
|
35
|
+
readonly label: "CLI";
|
|
36
|
+
readonly language: "Shell";
|
|
37
|
+
readonly grammar: "bash";
|
|
38
|
+
readonly icon: "terminal";
|
|
39
|
+
}, {
|
|
40
|
+
readonly id: "python";
|
|
41
|
+
readonly label: "Python";
|
|
42
|
+
readonly language: "Python";
|
|
43
|
+
readonly grammar: "python";
|
|
44
|
+
readonly icon: "lang-python";
|
|
45
|
+
}, {
|
|
46
|
+
readonly id: "curl";
|
|
47
|
+
readonly label: "curl";
|
|
48
|
+
readonly language: "Shell";
|
|
49
|
+
readonly grammar: "bash";
|
|
50
|
+
readonly icon: "lang-curl";
|
|
51
|
+
}];
|
|
52
|
+
/**
|
|
53
|
+
* The tab table, exported so a caller can render its OWN affordance per
|
|
54
|
+
* language without re-deriving the set. `CodeTool`'s rail panel uses it to draw
|
|
55
|
+
* one icon per language and open this component's modal on that language.
|
|
56
|
+
*
|
|
57
|
+
* Exported as the table rather than as a list of ids on purpose: label, grammar
|
|
58
|
+
* and glyph belong to the same row, and a second place that decided "which
|
|
59
|
+
* languages exist" would be a second place to forget `curl`.
|
|
60
|
+
*/
|
|
61
|
+
export declare const SNIPPET_TABS: readonly [{
|
|
62
|
+
readonly id: "node";
|
|
63
|
+
readonly label: "Node";
|
|
64
|
+
readonly language: "TypeScript";
|
|
65
|
+
readonly grammar: "typescript";
|
|
66
|
+
readonly icon: "lang-node";
|
|
67
|
+
}, {
|
|
68
|
+
readonly id: "cli";
|
|
69
|
+
readonly label: "CLI";
|
|
70
|
+
readonly language: "Shell";
|
|
71
|
+
readonly grammar: "bash";
|
|
72
|
+
readonly icon: "terminal";
|
|
73
|
+
}, {
|
|
74
|
+
readonly id: "python";
|
|
75
|
+
readonly label: "Python";
|
|
76
|
+
readonly language: "Python";
|
|
77
|
+
readonly grammar: "python";
|
|
78
|
+
readonly icon: "lang-python";
|
|
79
|
+
}, {
|
|
80
|
+
readonly id: "curl";
|
|
81
|
+
readonly label: "curl";
|
|
82
|
+
readonly language: "Shell";
|
|
83
|
+
readonly grammar: "bash";
|
|
84
|
+
readonly icon: "lang-curl";
|
|
85
|
+
}];
|
|
86
|
+
type TabId = (typeof TABS)[number]["id"];
|
|
87
|
+
export type SnippetTabId = TabId;
|
|
88
|
+
/**
|
|
89
|
+
* Which language tabs a resource actually has — the same filter the strip
|
|
90
|
+
* below applies, hoisted so a caller can ask BEFORE rendering.
|
|
91
|
+
*
|
|
92
|
+
* `curl` is emitted only where a public URL exists and was handed in (today: a
|
|
93
|
+
* Function, a Workflow, or an Endpoint that knows its own server-rendered URL),
|
|
94
|
+
* so a var, document or connection yields exactly Node/CLI/Python. Trigger
|
|
95
|
+
* fields are deliberately not a parameter: they change what the snippet SAYS,
|
|
96
|
+
* never which languages it is available in.
|
|
97
|
+
*
|
|
98
|
+
* Empty when the resource has no snippet at all — the caller should then show
|
|
99
|
+
* {@link unavailableReason} rather than an empty row of icons.
|
|
100
|
+
*/
|
|
101
|
+
export declare function snippetTabsFor(resource: SnippetCallable): readonly (typeof TABS)[number][];
|
|
102
|
+
/**
|
|
103
|
+
* The headless body — everything that renders the snippet itself: the
|
|
104
|
+
* trigger-tab strip, the language-tab strip, the `CodeBlock`, and the per-tab
|
|
105
|
+
* install-hint paragraph. No button, no `Modal`. Split out (T2.1.2) so
|
|
106
|
+
* `CodeTool.Panel` (`../ui/rail/CodeTool.tsx`) can render this INSIDE the
|
|
107
|
+
* right rail's own already-open panel, without a second trigger button or a
|
|
108
|
+
* Modal-on-top-of-a-panel double-wrap — the rail's strip + panel disclosure
|
|
109
|
+
* IS the trigger; this component only needs to draw what's inside it.
|
|
110
|
+
* `CallFromCodeButton` below is unchanged in outward shape: the same button +
|
|
111
|
+
* `Modal`, now rendering this body inside.
|
|
112
|
+
*/
|
|
113
|
+
export declare function CallFromCodeBody({ resource, triggers, wrap, maxHeight, initialTab, }: {
|
|
114
|
+
resource: SnippetCallable;
|
|
115
|
+
/**
|
|
116
|
+
* The workflow's declared manual (`@w6w/trigger`) triggers, one entry per
|
|
117
|
+
* step, in declared order — optional so every other `CallFromCodeBody`
|
|
118
|
+
* caller (function, endpoint, connection, var, document) is unaffected.
|
|
119
|
+
* Both call sites derive this from a workflow definition already in scope
|
|
120
|
+
* (T2.2.1, HITL-2/HITL-4 pinned); nothing here fetches it. The selected
|
|
121
|
+
* trigger's declared fields are passed straight into `buildSnippet` and
|
|
122
|
+
* rendered INSIDE the generated code — required fields as active code with
|
|
123
|
+
* a type-derived placeholder, optional fields commented out (D-3/D-4) — so
|
|
124
|
+
* there is nothing left to duplicate in a panel above it.
|
|
125
|
+
*/
|
|
126
|
+
triggers?: TriggerPreview[];
|
|
127
|
+
/**
|
|
128
|
+
* Soft-wrap the code box instead of scrolling it horizontally. Default OFF
|
|
129
|
+
* — see the `CodeBlock` call below for why off is right wherever there is
|
|
130
|
+
* room, and why the right rail is the place where it is not.
|
|
131
|
+
*/
|
|
132
|
+
wrap?: boolean;
|
|
133
|
+
/** The code box's max height. Default `"420px"`, the modal's size. */
|
|
134
|
+
maxHeight?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Which language to open on. Seeds the selection ONCE, at mount — this is a
|
|
137
|
+
* starting point, not a controlled value, so the strip stays clickable
|
|
138
|
+
* afterwards.
|
|
139
|
+
*
|
|
140
|
+
* That "once" is load-bearing for the rail: `CodeTool` mounts this inside a
|
|
141
|
+
* modal that is conditionally rendered, so picking Python, closing, and
|
|
142
|
+
* picking Node re-mounts and re-seeds. A tab this resource does not carry
|
|
143
|
+
* falls back to the first one it does, via `activeTab` below.
|
|
144
|
+
*/
|
|
145
|
+
initialTab?: TabId;
|
|
146
|
+
}): import("react").JSX.Element;
|
|
147
|
+
export declare function CallFromCodeButton({ resource, label, triggers, initialTab, }: {
|
|
148
|
+
resource: SnippetCallable;
|
|
149
|
+
label?: string;
|
|
150
|
+
/** See {@link CallFromCodeBody}'s own doc — passed straight through. */
|
|
151
|
+
triggers?: TriggerPreview[];
|
|
152
|
+
/** See {@link CallFromCodeBody}'s own doc — passed straight through. */
|
|
153
|
+
initialTab?: TabId;
|
|
154
|
+
}): import("react").JSX.Element;
|
|
155
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface CallableSettingsModalProps {
|
|
2
|
+
kind: "function" | "endpoint" | "workflow";
|
|
3
|
+
id: string;
|
|
4
|
+
initial: {
|
|
5
|
+
displayName: string;
|
|
6
|
+
key: string | null;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
};
|
|
9
|
+
onSave: (data: {
|
|
10
|
+
displayName: string;
|
|
11
|
+
key: string | null;
|
|
12
|
+
tags?: string[];
|
|
13
|
+
}) => Promise<void>;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function CallableSettingsModal(props: CallableSettingsModalProps): import("react").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface ConfirmModalProps {
|
|
2
|
+
title: string;
|
|
3
|
+
message: string;
|
|
4
|
+
/** Fired when the user confirms. The caller clears its pending state via onClose. */
|
|
5
|
+
onConfirm: () => void;
|
|
6
|
+
/** Fired on Cancel, Esc, or outside-click — dismisses without confirming. */
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
confirmLabel?: string;
|
|
9
|
+
cancelLabel?: string;
|
|
10
|
+
/** Style the confirm button as destructive (default true — this dialog gates dangerous actions). */
|
|
11
|
+
destructive?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A reusable confirmation dialog built on our <dialog>-based Modal, so it inherits
|
|
15
|
+
* focus-trap, Esc-dismiss, and outside-click close. Replaces the browser's native
|
|
16
|
+
* confirmation prompt for destructive actions: Confirm fires `onConfirm`;
|
|
17
|
+
* Cancel/Esc/outside-click fires `onClose` only (no confirmation).
|
|
18
|
+
*/
|
|
19
|
+
export declare function ConfirmModal({ title, message, onConfirm, onClose, confirmLabel, cancelLabel, destructive, }: ConfirmModalProps): import("react").JSX.Element;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface DangerZoneProps {
|
|
2
|
+
/** Whether the resource is archived yet. `true` renders Delete; `false`
|
|
3
|
+
* renders Archive. Every kind has an archive-before-delete step as of
|
|
4
|
+
* T4.1.1 (Function/Endpoint newly, Workflow already did). */
|
|
5
|
+
archived: boolean;
|
|
6
|
+
/** Accessible name for the Delete icon button — `title`/`aria-label` only
|
|
7
|
+
* (`IconButton.tsx`), e.g. "Delete this function". */
|
|
8
|
+
deleteLabel: string;
|
|
9
|
+
/** `data-testid` for the Delete control. Kind-specific — page guards key
|
|
10
|
+
* on these directly (e.g. `delete-function`, `wf-settings-delete`). */
|
|
11
|
+
deleteTestId: string;
|
|
12
|
+
/** `data-testid` for the Archive control. Kind-specific. */
|
|
13
|
+
archiveTestId: string;
|
|
14
|
+
onRequestDelete: () => void;
|
|
15
|
+
onRequestArchive: () => void;
|
|
16
|
+
deleteError: string | null;
|
|
17
|
+
archiveError: string | null;
|
|
18
|
+
}
|
|
19
|
+
export declare function DangerZone(props: DangerZoneProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* `ExecutionProfileHeader` — the ONE editor header every execution profile's
|
|
4
|
+
* editor mounts (T3.1.1, `building-blocks.md` §Profile building blocks
|
|
5
|
+
* §Mirror).
|
|
6
|
+
*
|
|
7
|
+
* Extracted verbatim from `WorkflowsPage.tsx`'s full-bleed editor head, which
|
|
8
|
+
* is the presentation of record: back control, title, actions. Two hosts use
|
|
9
|
+
* it with two title CONFIGURATIONS, never two headers:
|
|
10
|
+
* - `WorkflowsPage.tsx` — an inline-editable, controlled name input
|
|
11
|
+
* (`editable: true`); back clears the `?edit=` search param; the action row
|
|
12
|
+
* (run / stop / publish / JSON / settings) stays host-owned and arrives as
|
|
13
|
+
* `actions`.
|
|
14
|
+
* - `CallablePage.tsx`'s `CallableEditorChrome` — a Function/Endpoint
|
|
15
|
+
* read-only heading (`editable: false`) with the `incomplete` badge passed
|
|
16
|
+
* as `titleAdornment`, and the host's own JSON toggle then Save button as
|
|
17
|
+
* `actions`.
|
|
18
|
+
*
|
|
19
|
+
* Presentation only: no query, mutation or navigation logic lives here — every
|
|
20
|
+
* callback (`onBack`, `onChange`, `onBlur`) and every node in the action row is
|
|
21
|
+
* the host's, mirroring the `ConnectionHeader.tsx` action-slot precedent.
|
|
22
|
+
*
|
|
23
|
+
* The rendered DOM of the Workflow editor's header is byte-for-byte what it
|
|
24
|
+
* was before the extraction (`wf-fullbleed-head` / `wf-back-btn` /
|
|
25
|
+
* `wf-title-input` / `wf-head-actions`, every `data-testid`, the `aria-label`
|
|
26
|
+
* and the attribute order), which is what `styles.css`'s
|
|
27
|
+
* `.wf-fullbleed-head input.wf-title-input` ancestor specificity and the
|
|
28
|
+
* workflow header screenshot guard both depend on.
|
|
29
|
+
*/
|
|
30
|
+
/** The editable title variant: the Workflow editor's inline-editable name. */
|
|
31
|
+
export interface EditableProfileTitle {
|
|
32
|
+
/** The controlled value. */
|
|
33
|
+
value: string;
|
|
34
|
+
/** Called with the new text on every keystroke. */
|
|
35
|
+
onChange: (next: string) => void;
|
|
36
|
+
/** Called when the field loses focus — the Workflow host saves here. */
|
|
37
|
+
onBlur: () => void;
|
|
38
|
+
/** Shown while the value is empty; also the field's minimum sizing basis. */
|
|
39
|
+
placeholder: string;
|
|
40
|
+
/** The `maxLength` the input carries. */
|
|
41
|
+
maxLength: number;
|
|
42
|
+
/** The input's accessible name. */
|
|
43
|
+
ariaLabel: string;
|
|
44
|
+
}
|
|
45
|
+
/** The read-only title variant: a Function/Endpoint editor's heading text. */
|
|
46
|
+
export interface ReadOnlyProfileTitle {
|
|
47
|
+
value: string;
|
|
48
|
+
}
|
|
49
|
+
/** Which title the host mounts. The discriminant is `editable`. */
|
|
50
|
+
export type ExecutionProfileTitle = ({
|
|
51
|
+
editable: true;
|
|
52
|
+
} & EditableProfileTitle) | ({
|
|
53
|
+
editable: false;
|
|
54
|
+
} & ReadOnlyProfileTitle);
|
|
55
|
+
export interface ExecutionProfileHeaderProps {
|
|
56
|
+
/** The back control's click handler — host-owned (the Workflow host clears
|
|
57
|
+
* `?edit=`; `CallableEditorChrome` navigates to the kind's listing). */
|
|
58
|
+
onBack: () => void;
|
|
59
|
+
/** The back control's visible text — host-owned copy (`"← Workflows"`,
|
|
60
|
+
* `descriptor.editor.backLabel`). */
|
|
61
|
+
backLabel: string;
|
|
62
|
+
/** Editable (Workflow) or read-only (Function/Endpoint) title. */
|
|
63
|
+
title: ExecutionProfileTitle;
|
|
64
|
+
/** Rendered immediately after a read-only title — the `incomplete` badge. */
|
|
65
|
+
titleAdornment?: ReactNode;
|
|
66
|
+
/** The host's action row (buttons only; this component owns the wrapper). */
|
|
67
|
+
actions: ReactNode;
|
|
68
|
+
}
|
|
69
|
+
export declare function ExecutionProfileHeader({ onBack, backLabel, title, titleAdornment, actions, }: ExecutionProfileHeaderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CallableKind } from '@w6w/embed/repos';
|
|
2
|
+
export interface HistoryButtonProps {
|
|
3
|
+
kind: CallableKind;
|
|
4
|
+
id: string;
|
|
5
|
+
/** Forwarded to the modal; see `HistoryModalProps.onOpenRun`. */
|
|
6
|
+
onOpenRun?: (runId: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function HistoryButton(props: HistoryButtonProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CallableKind } from '@w6w/embed/repos';
|
|
2
|
+
export interface HistoryModalProps {
|
|
3
|
+
kind: CallableKind;
|
|
4
|
+
id: string;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
/** Open a workflow run in the host's editor; absent ⇒ no open-in-editor affordance. */
|
|
7
|
+
onOpenRun?: (runId: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function HistoryModal(props: HistoryModalProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ExecutionSummary, HistoryFilters, HistoryScope } from '@w6w/embed/repos';
|
|
2
|
+
export interface HistoryViewProps {
|
|
3
|
+
/** `null` ⇒ no scope known yet (the project-wide host, before its project
|
|
4
|
+
* resolves) — both queries stay disabled, mirroring `repos/history.ts`'s
|
|
5
|
+
* own `enabled: scope !== null`. */
|
|
6
|
+
scope: HistoryScope | null;
|
|
7
|
+
/** Project-wide chrome: the Kind filter, and the Callable column on every
|
|
8
|
+
* row. A per-callable host (every callable already knows its own kind)
|
|
9
|
+
* passes `false`. */
|
|
10
|
+
showKind: boolean;
|
|
11
|
+
filters: HistoryFilters;
|
|
12
|
+
onFiltersChange: (next: HistoryFilters) => void;
|
|
13
|
+
onOpenInEditor?: (execution: ExecutionSummary) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function HistoryView(props: HistoryViewProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SpecImportKind, SpecImportListKeys } from '@w6w/embed/lib';
|
|
2
|
+
/**
|
|
3
|
+
* Import modal for the Functions, Endpoints and Workflows lists (T1.2.1, generalizing T3.2.1's
|
|
4
|
+
* Functions-only `ImportFunctionModal`): paste a portable spec document (rfcs/function.md), POST
|
|
5
|
+
* it to `/spec/import` and either land in the created resource's editor (every reference resolved)
|
|
6
|
+
* or stay open with the unresolved-reference report (A5).
|
|
7
|
+
*
|
|
8
|
+
* **P1 — one parameterized component, not three.** The Function-specific surface was four strings,
|
|
9
|
+
* one nav target and a testid prefix — forking it into three siblings would duplicate the state
|
|
10
|
+
* machine below for no gain. The `kind` prop drives all of it: `parseImportPaste`'s expected kind,
|
|
11
|
+
* the title/copy, the `goto()` navigation target (`<collection>/<id>`), and every testid (P2 — the
|
|
12
|
+
* four `functions-import-*` ones this file used to hardcode keep matching byte-for-byte; see
|
|
13
|
+
* `TESTIDS` above for why they are spelled out literally per kind rather than interpolated).
|
|
14
|
+
*
|
|
15
|
+
* Mirrors `FunctionIdentityModal.tsx` (note 3 — same studio-local `Modal`,
|
|
16
|
+
* same `ApiError.message` handling, same "the row was created, hand the
|
|
17
|
+
* operator the id" shape as `onCreated`) but is a structurally PARALLEL,
|
|
18
|
+
* distinct trigger — not a second "create a resource and land in its editor"
|
|
19
|
+
* flow built on top of it. It owns its own navigation (unlike the identity
|
|
20
|
+
* modal, which reports back to the list) because A5's "created but
|
|
21
|
+
* partially resolved" outcome has nowhere else to render the report: the
|
|
22
|
+
* modal has to stay mounted to show it, so it is also the one place that can
|
|
23
|
+
* decide whether and when to leave the list route.
|
|
24
|
+
*
|
|
25
|
+
* **A `201` whose `references` carry any `resolved: false` entry is NOT
|
|
26
|
+
* "done" (A5)** — the near-miss this exists to kill is "201 ⇒ close and
|
|
27
|
+
* navigate", which would hide exactly the unresolved-reference report the
|
|
28
|
+
* intake asks for.
|
|
29
|
+
*/
|
|
30
|
+
export interface ImportSpecModalProps {
|
|
31
|
+
kind: SpecImportKind;
|
|
32
|
+
/** The host's current project (only the workflow list key reads it). */
|
|
33
|
+
project: string | undefined;
|
|
34
|
+
/** The three list query keys, injected by the host. */
|
|
35
|
+
listKeys: SpecImportListKeys;
|
|
36
|
+
/** Navigate to the imported row; the modal closes itself first. */
|
|
37
|
+
onOpenImported: (kind: SpecImportKind, id: string) => void;
|
|
38
|
+
onClose: () => void;
|
|
39
|
+
}
|
|
40
|
+
export declare function ImportSpecModal(props: ImportSpecModalProps): import("react").JSX.Element;
|