@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.
Files changed (102) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +166 -2
  3. package/dist/W6WEmbedProvider.d.ts +29 -0
  4. package/dist/chrome/CallFromCodeButton.d.ts +155 -0
  5. package/dist/chrome/CallableSettingsModal.d.ts +17 -0
  6. package/dist/chrome/ConfirmModal.d.ts +20 -0
  7. package/dist/chrome/DangerZone.d.ts +19 -0
  8. package/dist/chrome/ExecutionProfileHeader.d.ts +69 -0
  9. package/dist/chrome/HistoryButton.d.ts +8 -0
  10. package/dist/chrome/HistoryModal.d.ts +9 -0
  11. package/dist/chrome/HistoryView.d.ts +15 -0
  12. package/dist/chrome/ImportSpecModal.d.ts +40 -0
  13. package/dist/chrome/JsonToggle.d.ts +51 -0
  14. package/dist/chrome/Modal.d.ts +20 -0
  15. package/dist/chrome/RightRail.d.ts +24 -0
  16. package/dist/chrome/TagEditor.d.ts +23 -0
  17. package/dist/chrome/VersionHistoryModal.d.ts +38 -0
  18. package/dist/chrome/history-open-run.d.ts +7 -0
  19. package/dist/chrome/index.d.ts +36 -0
  20. package/dist/chrome/workspace.d.ts +67 -0
  21. package/dist/client-context-CX61Bgw-.js +16 -0
  22. package/dist/client-context-CX61Bgw-.js.map +1 -0
  23. package/dist/draft/autosave-flush.d.ts +63 -0
  24. package/dist/draft/autosave.d.ts +68 -0
  25. package/dist/draft/client-context.d.ts +8 -0
  26. package/dist/draft/draft-registry.d.ts +14 -0
  27. package/dist/draft/index.d.ts +15 -0
  28. package/dist/draft/use-workflow-draft.d.ts +67 -0
  29. package/dist/draft/workflow-save.d.ts +48 -0
  30. package/dist/draft-registry-YF0tqNN0.js +49 -0
  31. package/dist/draft-registry-YF0tqNN0.js.map +1 -0
  32. package/dist/draft.d.ts +2 -0
  33. package/dist/draft.mjs +18 -0
  34. package/dist/draft.mjs.map +1 -0
  35. package/dist/editor/WorkflowEditor.d.ts +12 -0
  36. package/dist/editor/WorkflowSettingsModal.d.ts +17 -0
  37. package/dist/editor/definition.d.ts +31 -0
  38. package/dist/editor/editor-apps.d.ts +7 -0
  39. package/dist/editor/types.d.ts +34 -0
  40. package/dist/editor.d.ts +9 -0
  41. package/dist/editor.mjs +2170 -0
  42. package/dist/editor.mjs.map +1 -0
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.mjs +67 -0
  45. package/dist/index.mjs.map +1 -0
  46. package/dist/lib/callable-descriptors.d.ts +77 -0
  47. package/dist/lib/callable-kind.d.ts +13 -0
  48. package/dist/lib/code-rail.d.ts +45 -0
  49. package/dist/lib/document-sources.d.ts +26 -0
  50. package/dist/lib/error-handler-self.d.ts +25 -0
  51. package/dist/lib/history-query.d.ts +135 -0
  52. package/dist/lib/import-paste.d.ts +41 -0
  53. package/dist/lib/index.d.ts +17 -0
  54. package/dist/lib/new-id.d.ts +10 -0
  55. package/dist/lib/rail-settings.d.ts +196 -0
  56. package/dist/lib/save-invalidation.d.ts +24 -0
  57. package/dist/lib/sdk-snippets.d.ts +96 -0
  58. package/dist/lib/settings-rail.d.ts +68 -0
  59. package/dist/lib/slug.d.ts +69 -0
  60. package/dist/lib/spec-import-invalidation.d.ts +48 -0
  61. package/dist/lib/tag-editor.d.ts +36 -0
  62. package/dist/lib/trigger-preview.d.ts +89 -0
  63. package/dist/lib/workflow-live-run.d.ts +165 -0
  64. package/dist/lib/workflow-poll.d.ts +8 -0
  65. package/dist/lib/workflow-route.d.ts +26 -0
  66. package/dist/lib/workflow-settings.d.ts +72 -0
  67. package/dist/lib/workflow-validity.d.ts +92 -0
  68. package/dist/lib/workflow-variables.d.ts +106 -0
  69. package/dist/lib.d.ts +2 -0
  70. package/dist/lib.mjs +62 -0
  71. package/dist/lib.mjs.map +1 -0
  72. package/dist/project-context-Dbk0Gr1K.js +16 -0
  73. package/dist/project-context-Dbk0Gr1K.js.map +1 -0
  74. package/dist/project-context.d.ts +11 -0
  75. package/dist/rail/CodeTool.d.ts +2 -0
  76. package/dist/rail/ErrorHandlingTool.d.ts +22 -0
  77. package/dist/rail/ExpressionScope.d.ts +21 -0
  78. package/dist/rail/SettingsTool.d.ts +27 -0
  79. package/dist/rail/editor-tools.d.ts +2 -0
  80. package/dist/rail/rail-env.d.ts +18 -0
  81. package/dist/rail/settings-sections.d.ts +93 -0
  82. package/dist/repos/documents.d.ts +102 -0
  83. package/dist/repos/history.d.ts +24 -0
  84. package/dist/repos/index.d.ts +22 -0
  85. package/dist/repos/spec-import.d.ts +44 -0
  86. package/dist/repos/step-tests.d.ts +19 -0
  87. package/dist/repos/vars.d.ts +25 -0
  88. package/dist/repos/vault.d.ts +24 -0
  89. package/dist/repos/versions.d.ts +112 -0
  90. package/dist/repos.d.ts +2 -0
  91. package/dist/repos.mjs +94 -0
  92. package/dist/repos.mjs.map +1 -0
  93. package/dist/slug-ByKQgxrf.js +642 -0
  94. package/dist/slug-ByKQgxrf.js.map +1 -0
  95. package/dist/spec-import-HgO7ZkLZ.js +898 -0
  96. package/dist/spec-import-HgO7ZkLZ.js.map +1 -0
  97. package/dist/spec-import-invalidation-D3retX4Q.js +18 -0
  98. package/dist/spec-import-invalidation-D3retX4Q.js.map +1 -0
  99. package/dist/use-workflow-draft-oI02dsP-.js +314 -0
  100. package/dist/use-workflow-draft-oI02dsP-.js.map +1 -0
  101. package/package.json +71 -3
  102. 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
- # Temporary Holding Version
1
+ # @w6w/embed
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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;