@statelyai/sdk 0.1.1 → 0.3.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/README.md +145 -25
- package/dist/embed.d.mts +43 -0
- package/dist/embed.mjs +175 -0
- package/dist/graph-C-7ZK_nK.d.mts +393 -0
- package/dist/graph.d.mts +2 -0
- package/dist/graph.mjs +344 -0
- package/dist/index.d.mts +34 -107
- package/dist/index.mjs +7 -200
- package/dist/inspect.d.mts +45 -0
- package/dist/inspect.mjs +122 -0
- package/dist/protocol-BC-_s3if.d.mts +172 -0
- package/dist/studio.d.mts +54 -0
- package/dist/studio.mjs +62 -0
- package/dist/sync-CzEOizjx.mjs +558 -0
- package/dist/sync.d.mts +43 -0
- package/dist/sync.mjs +5 -0
- package/dist/transport-D352iKKa.mjs +250 -0
- package/package.json +36 -8
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @statelyai/sdk
|
|
2
2
|
|
|
3
|
-
Embed the [Stately editor](https://stately.ai) in your app. Zero dependencies, fully typed.
|
|
3
|
+
Embed the [Stately editor](https://stately.ai) in your app and talk to the Stately Studio API. Zero dependencies, fully typed.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,9 +8,13 @@ Embed the [Stately editor](https://stately.ai) in your app. Zero dependencies, f
|
|
|
8
8
|
npm install @statelyai/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Authentication
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The editor uses a pluggable authentication system. How you configure it depends on whether you're using the hosted Stately platform or self-hosting.
|
|
14
|
+
|
|
15
|
+
### With Stately (default)
|
|
16
|
+
|
|
17
|
+
An API key is required. To get one:
|
|
14
18
|
|
|
15
19
|
1. Go to your [Stately settings](https://stately.ai/settings)
|
|
16
20
|
2. Select the **API Key** tab
|
|
@@ -19,8 +23,68 @@ An API key is required to use the embed SDK. To get one:
|
|
|
19
23
|
|
|
20
24
|
See the [Studio API docs](https://stately.ai/docs/studio-api) for more details.
|
|
21
25
|
|
|
26
|
+
Pass the key to the SDK:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
const embed = createStatelyEmbed({
|
|
30
|
+
baseUrl: 'https://stately.ai',
|
|
31
|
+
apiKey: 'your-api-key',
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The server validates the key against the Stately registry API.
|
|
36
|
+
|
|
37
|
+
### Self-hosting
|
|
38
|
+
|
|
39
|
+
When self-hosting the editor, authentication is controlled by the `AUTH_PROVIDER` environment variable on the server:
|
|
40
|
+
|
|
41
|
+
| Value | Behavior |
|
|
42
|
+
| ---------- | ----------------------------------------------------------- |
|
|
43
|
+
| `stately` | Validates tokens against the Stately registry API |
|
|
44
|
+
| `none` | Allows all requests (no authentication) |
|
|
45
|
+
| _(unset)_ | `none` in development, `stately` in production |
|
|
46
|
+
|
|
47
|
+
For a fully self-contained deployment with no Stately dependency:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
AUTH_PROVIDER=none
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Custom authentication
|
|
54
|
+
|
|
55
|
+
You can implement your own auth by writing a custom `AuthValidator` — an async function that receives a token and returns whether it's valid:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import type { AuthValidator } from '@/lib/auth';
|
|
59
|
+
|
|
60
|
+
const myValidator: AuthValidator = async (token) => {
|
|
61
|
+
const res = await fetch('https://my-auth-server.com/verify', {
|
|
62
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
63
|
+
});
|
|
64
|
+
return res.ok;
|
|
65
|
+
};
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The built-in adapters are:
|
|
69
|
+
|
|
70
|
+
- **`createStatelyValidator(baseUrl?)`** — verifies against the Stately registry API (`/registry/api/v1/verify`)
|
|
71
|
+
- **`allowAllValidator`** — always returns `true`
|
|
72
|
+
|
|
73
|
+
To use a custom validator, call `getAuthValidator()` from `src/lib/auth` in the server-side page code, or replace the resolver logic in `src/lib/auth/index.tsx` to return your implementation.
|
|
74
|
+
|
|
75
|
+
### Environment variables
|
|
76
|
+
|
|
77
|
+
| Variable | Purpose |
|
|
78
|
+
| ----------------------- | -------------------------------------------- |
|
|
79
|
+
| `AUTH_PROVIDER` | Auth strategy: `stately`, `none`, or unset |
|
|
80
|
+
| `STATELY_API_KEY` | Server-side API key for Stately data fetching |
|
|
81
|
+
| `STATELY_API_URL` | Stately API base URL (server-side override) |
|
|
82
|
+
| `NEXT_PUBLIC_BASE_URL` | Public-facing base URL |
|
|
83
|
+
|
|
22
84
|
## Quick start
|
|
23
85
|
|
|
86
|
+
### Third-party embed (with API key)
|
|
87
|
+
|
|
24
88
|
```ts
|
|
25
89
|
import { createStatelyEmbed } from '@statelyai/sdk';
|
|
26
90
|
|
|
@@ -29,10 +93,8 @@ const embed = createStatelyEmbed({
|
|
|
29
93
|
apiKey: 'your-api-key',
|
|
30
94
|
});
|
|
31
95
|
|
|
32
|
-
// Mount into a container
|
|
33
96
|
embed.mount(document.getElementById('editor')!);
|
|
34
97
|
|
|
35
|
-
// Initialize with a machine
|
|
36
98
|
embed.init({
|
|
37
99
|
machine: myMachineConfig,
|
|
38
100
|
mode: 'editing',
|
|
@@ -40,26 +102,84 @@ embed.init({
|
|
|
40
102
|
});
|
|
41
103
|
```
|
|
42
104
|
|
|
105
|
+
### Same-origin embed (cookie auth)
|
|
106
|
+
|
|
107
|
+
When the embed host and the editor share a domain (e.g. Stately Studio embedding the beta editor), Supabase session cookies handle auth automatically — no API key needed:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const embed = createStatelyEmbed({
|
|
111
|
+
baseUrl: process.env.NEXT_PUBLIC_BETA_EDITOR_URL ?? window.location.origin,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
embed.mount(container);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Self-hosted (no auth)
|
|
118
|
+
|
|
119
|
+
When self-hosting with `AUTH_PROVIDER=none`, no token is required:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
const embed = createStatelyEmbed({
|
|
123
|
+
baseUrl: 'https://your-editor.example.com',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
embed.mount(container);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Module layout
|
|
130
|
+
|
|
131
|
+
The SDK ships direct root exports for the common entry points:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import {
|
|
135
|
+
createStatelyInspector,
|
|
136
|
+
createStatelyEmbed,
|
|
137
|
+
createStatelyClient,
|
|
138
|
+
} from '@statelyai/sdk';
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
It also supports subpath imports when you want a narrower surface:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { createStatelyClient } from '@statelyai/sdk/studio';
|
|
145
|
+
import { createStatelyInspector } from '@statelyai/sdk/inspect';
|
|
146
|
+
import { createStatelyEmbed } from '@statelyai/sdk/embed';
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Studio API client
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { createStatelyClient } from '@statelyai/sdk';
|
|
153
|
+
|
|
154
|
+
const studio = createStatelyClient({
|
|
155
|
+
apiKey: process.env.STATELY_API_KEY,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const project = await studio.projects.get('project-id');
|
|
159
|
+
const machine = await studio.machines.get('machine-id', { version: '42' });
|
|
160
|
+
const extracted = await studio.code.extractMachines(sourceCode);
|
|
161
|
+
```
|
|
162
|
+
|
|
43
163
|
## API
|
|
44
164
|
|
|
45
165
|
### `createStatelyEmbed(options)`
|
|
46
166
|
|
|
47
167
|
Creates an embed instance.
|
|
48
168
|
|
|
49
|
-
| Option
|
|
50
|
-
|
|
51
|
-
| `baseUrl`
|
|
52
|
-
| `apiKey`
|
|
53
|
-
| `origin`
|
|
54
|
-
| `onReady`
|
|
55
|
-
| `onLoaded` | `(graph) => void`
|
|
56
|
-
| `onChange` | `(graph, machineConfig) => void` | Called on every change
|
|
57
|
-
| `onSave`
|
|
58
|
-
| `onError`
|
|
169
|
+
| Option | Type | Description |
|
|
170
|
+
| ---------- | -------------------------------- | ----------------------------------------- |
|
|
171
|
+
| `baseUrl` | `string` | **Required.** Base URL of the Stately app |
|
|
172
|
+
| `apiKey` | `string` | API key for authentication (see [Authentication](#authentication)) |
|
|
173
|
+
| `origin` | `string` | Custom target origin for postMessage |
|
|
174
|
+
| `onReady` | `() => void` | Called when embed is ready |
|
|
175
|
+
| `onLoaded` | `(graph) => void` | Called when machine is loaded |
|
|
176
|
+
| `onChange` | `(graph, machineConfig) => void` | Called on every change |
|
|
177
|
+
| `onSave` | `(graph, machineConfig) => void` | Called on save |
|
|
178
|
+
| `onError` | `({ code, message }) => void` | Called on error |
|
|
59
179
|
|
|
60
180
|
### Embed methods
|
|
61
181
|
|
|
62
|
-
#### `mount(container)` / `attach(iframe)`
|
|
182
|
+
#### `embed.mount(container)` / `embed.attach(iframe)`
|
|
63
183
|
|
|
64
184
|
Mount creates an iframe inside a container element. Attach connects to an existing iframe.
|
|
65
185
|
|
|
@@ -71,7 +191,7 @@ const iframe = embed.mount(document.getElementById('editor')!);
|
|
|
71
191
|
embed.attach(document.querySelector('iframe')!);
|
|
72
192
|
```
|
|
73
193
|
|
|
74
|
-
#### `init(options)`
|
|
194
|
+
#### `embed.init(options)`
|
|
75
195
|
|
|
76
196
|
Initialize the embed with a machine and display options.
|
|
77
197
|
|
|
@@ -79,8 +199,8 @@ Initialize the embed with a machine and display options.
|
|
|
79
199
|
embed.init({
|
|
80
200
|
machine: machineConfig,
|
|
81
201
|
format: 'xstate', // optional
|
|
82
|
-
mode: 'editing',
|
|
83
|
-
theme: 'dark',
|
|
202
|
+
mode: 'editing', // 'editing' | 'viewing' | 'simulating'
|
|
203
|
+
theme: 'dark', // 'light' | 'dark'
|
|
84
204
|
readOnly: false,
|
|
85
205
|
depth: 3,
|
|
86
206
|
panels: {
|
|
@@ -91,15 +211,15 @@ embed.init({
|
|
|
91
211
|
});
|
|
92
212
|
```
|
|
93
213
|
|
|
94
|
-
#### `updateMachine(machine, format?)`
|
|
214
|
+
#### `embed.updateMachine(machine, format?)`
|
|
95
215
|
|
|
96
216
|
Update the displayed machine.
|
|
97
217
|
|
|
98
|
-
#### `setMode(mode)` / `setTheme(theme)`
|
|
218
|
+
#### `embed.setMode(mode)` / `embed.setTheme(theme)`
|
|
99
219
|
|
|
100
220
|
Change the embed mode or theme at runtime.
|
|
101
221
|
|
|
102
|
-
#### `export(format, options?)`
|
|
222
|
+
#### `embed.export(format, options?)`
|
|
103
223
|
|
|
104
224
|
Export the current machine. Returns a promise.
|
|
105
225
|
|
|
@@ -111,7 +231,7 @@ const mermaid = await embed.export('mermaid');
|
|
|
111
231
|
|
|
112
232
|
Supported formats: `xstate`, `json`, `digraph`, `mermaid`, `scxml`
|
|
113
233
|
|
|
114
|
-
#### `on(event, handler)` / `off(event, handler)`
|
|
234
|
+
#### `embed.on(event, handler)` / `embed.off(event, handler)`
|
|
115
235
|
|
|
116
236
|
Subscribe/unsubscribe to embed events: `ready`, `loaded`, `change`, `save`, `error`.
|
|
117
237
|
|
|
@@ -121,10 +241,10 @@ embed.on('change', ({ graph, machineConfig }) => {
|
|
|
121
241
|
});
|
|
122
242
|
```
|
|
123
243
|
|
|
124
|
-
#### `toast(message, type?)`
|
|
244
|
+
#### `embed.toast(message, type?)`
|
|
125
245
|
|
|
126
246
|
Show a toast notification in the embed. Type: `'success' | 'error' | 'info' | 'warning'`
|
|
127
247
|
|
|
128
|
-
#### `destroy()`
|
|
248
|
+
#### `embed.destroy()`
|
|
129
249
|
|
|
130
250
|
Tear down the embed. Removes listeners, rejects pending promises, and removes the iframe if it was created via `mount()`.
|
package/dist/embed.d.mts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { a as ExportCallOptions, c as InitOptions, i as EmbedMode, n as EmbedEventMap, o as ExportFormat, r as EmbedEventName, s as ExportFormatMap, t as EmbedEventHandler } from "./protocol-BC-_s3if.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/embed.d.ts
|
|
4
|
+
interface StatelyEmbedOptions {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
origin?: string;
|
|
8
|
+
onReady?: () => void;
|
|
9
|
+
onLoaded?: (graph: unknown) => void;
|
|
10
|
+
onChange?: (graph: unknown, machineConfig: unknown) => void;
|
|
11
|
+
onSave?: (graph: unknown, machineConfig: unknown) => void;
|
|
12
|
+
onError?: (error: {
|
|
13
|
+
code: string;
|
|
14
|
+
message: string;
|
|
15
|
+
}) => void;
|
|
16
|
+
}
|
|
17
|
+
interface StatelyEmbed {
|
|
18
|
+
/** Attach to an existing iframe element. Sets src and begins handshake. */
|
|
19
|
+
attach(iframe: HTMLIFrameElement): void;
|
|
20
|
+
/** Create an iframe and mount it into a container element. */
|
|
21
|
+
mount(container: HTMLElement): HTMLIFrameElement;
|
|
22
|
+
/** Send init message (queued if iframe not ready yet). */
|
|
23
|
+
init(options: InitOptions): void;
|
|
24
|
+
/** Update the machine (shorthand for update message). */
|
|
25
|
+
updateMachine(machine: unknown, format?: string): void;
|
|
26
|
+
/** Change the embed mode. */
|
|
27
|
+
setMode(mode: EmbedMode): void;
|
|
28
|
+
/** Change the embed theme. */
|
|
29
|
+
setTheme(theme: 'light' | 'dark'): void;
|
|
30
|
+
/** Export the current machine in a given format. Returns a promise. */
|
|
31
|
+
export<F extends ExportFormat>(format: F, options?: ExportCallOptions<F>): Promise<ExportFormatMap[F]['result']>;
|
|
32
|
+
/** Subscribe to an embed event. */
|
|
33
|
+
on<K extends EmbedEventName>(event: K, handler: EmbedEventHandler<K>): void;
|
|
34
|
+
/** Unsubscribe from an embed event. */
|
|
35
|
+
off<K extends EmbedEventName>(event: K, handler: EmbedEventHandler<K>): void;
|
|
36
|
+
/** Show a toast message in the embed. */
|
|
37
|
+
toast(message: string, toastType?: 'success' | 'error' | 'info' | 'warning'): void;
|
|
38
|
+
/** Tear down: remove listener, reject pending promises, optionally remove iframe. */
|
|
39
|
+
destroy(): void;
|
|
40
|
+
}
|
|
41
|
+
declare function createStatelyEmbed(options: StatelyEmbedOptions): StatelyEmbed;
|
|
42
|
+
//#endregion
|
|
43
|
+
export { type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type InitOptions, StatelyEmbed, StatelyEmbedOptions, createStatelyEmbed };
|
package/dist/embed.mjs
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { i as createPendingExportManager, o as toInitMessage, r as createEventRegistry, t as createPostMessageTransport } from "./transport-D352iKKa.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/embed.ts
|
|
4
|
+
function createStatelyEmbed(options) {
|
|
5
|
+
const base = options.baseUrl.replace(/\/+$/, "") + "/embed";
|
|
6
|
+
const embedUrl = options.apiKey ? `${base}?api_key=${encodeURIComponent(options.apiKey)}` : base;
|
|
7
|
+
const targetOrigin = options.origin ?? new URL(embedUrl).origin;
|
|
8
|
+
let iframe = null;
|
|
9
|
+
let transport = null;
|
|
10
|
+
let ownedIframe = false;
|
|
11
|
+
let destroyed = false;
|
|
12
|
+
const pendingMessages = [];
|
|
13
|
+
const events = createEventRegistry();
|
|
14
|
+
const exportManager = createPendingExportManager((message) => send(message));
|
|
15
|
+
function send(msg) {
|
|
16
|
+
if (!transport?.ready) {
|
|
17
|
+
pendingMessages.push(msg);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
transport.send(msg);
|
|
21
|
+
}
|
|
22
|
+
function flush() {
|
|
23
|
+
if (!transport) return;
|
|
24
|
+
while (pendingMessages.length > 0) {
|
|
25
|
+
const msg = pendingMessages.shift();
|
|
26
|
+
transport.send(msg);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function handleMessage(data) {
|
|
30
|
+
if (destroyed) return;
|
|
31
|
+
switch (data.type) {
|
|
32
|
+
case "@statelyai.ready": {
|
|
33
|
+
const ready = data;
|
|
34
|
+
flush();
|
|
35
|
+
options.onReady?.();
|
|
36
|
+
events.emit("ready", { version: ready.version });
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case "@statelyai.loaded": {
|
|
40
|
+
const loaded = data;
|
|
41
|
+
options.onLoaded?.(loaded.graph);
|
|
42
|
+
events.emit("loaded", { graph: loaded.graph });
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case "@statelyai.change": {
|
|
46
|
+
const change = data;
|
|
47
|
+
options.onChange?.(change.graph, change.machineConfig);
|
|
48
|
+
events.emit("change", {
|
|
49
|
+
graph: change.graph,
|
|
50
|
+
machineConfig: change.machineConfig
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case "@statelyai.save": {
|
|
55
|
+
const save = data;
|
|
56
|
+
options.onSave?.(save.graph, save.machineConfig);
|
|
57
|
+
events.emit("save", {
|
|
58
|
+
graph: save.graph,
|
|
59
|
+
machineConfig: save.machineConfig
|
|
60
|
+
});
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case "@statelyai.retrieved": {
|
|
64
|
+
const retrieved = data;
|
|
65
|
+
exportManager.resolve(retrieved.requestId, retrieved.data);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case "@statelyai.error": {
|
|
69
|
+
const error = data;
|
|
70
|
+
const err = {
|
|
71
|
+
code: error.code,
|
|
72
|
+
message: error.message
|
|
73
|
+
};
|
|
74
|
+
exportManager.reject(new Error(err.message), error.requestId);
|
|
75
|
+
options.onError?.(err);
|
|
76
|
+
events.emit("error", err);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function replaceTransport(nextTransport) {
|
|
82
|
+
transport?.destroy();
|
|
83
|
+
transport = nextTransport;
|
|
84
|
+
}
|
|
85
|
+
function setupTransport(el) {
|
|
86
|
+
const nextTransport = createPostMessageTransport({
|
|
87
|
+
iframe: el,
|
|
88
|
+
targetOrigin
|
|
89
|
+
});
|
|
90
|
+
replaceTransport(nextTransport);
|
|
91
|
+
nextTransport.onMessage(handleMessage);
|
|
92
|
+
nextTransport.onReady(flush);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
attach(el) {
|
|
96
|
+
if (destroyed) return;
|
|
97
|
+
const currentSrc = el.getAttribute("src");
|
|
98
|
+
if (currentSrc && currentSrc !== "about:blank" && el.src !== embedUrl) console.warn("Replacing existing iframe src during attach()", {
|
|
99
|
+
currentSrc,
|
|
100
|
+
nextSrc: embedUrl
|
|
101
|
+
});
|
|
102
|
+
iframe = el;
|
|
103
|
+
ownedIframe = false;
|
|
104
|
+
el.src = embedUrl;
|
|
105
|
+
setupTransport(el);
|
|
106
|
+
},
|
|
107
|
+
mount(container) {
|
|
108
|
+
if (destroyed) throw new Error("Embed is destroyed");
|
|
109
|
+
const el = document.createElement("iframe");
|
|
110
|
+
el.src = embedUrl;
|
|
111
|
+
el.style.border = "none";
|
|
112
|
+
el.style.width = "100%";
|
|
113
|
+
el.style.height = "100%";
|
|
114
|
+
el.setAttribute("sandbox", "allow-scripts allow-same-origin");
|
|
115
|
+
el.setAttribute("allow", "clipboard-read; clipboard-write");
|
|
116
|
+
container.appendChild(el);
|
|
117
|
+
iframe = el;
|
|
118
|
+
ownedIframe = true;
|
|
119
|
+
setupTransport(el);
|
|
120
|
+
return el;
|
|
121
|
+
},
|
|
122
|
+
init(opts) {
|
|
123
|
+
send(toInitMessage(opts));
|
|
124
|
+
},
|
|
125
|
+
updateMachine(machine, format) {
|
|
126
|
+
send({
|
|
127
|
+
type: "@statelyai.update",
|
|
128
|
+
machine,
|
|
129
|
+
format
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
setMode(mode) {
|
|
133
|
+
send({
|
|
134
|
+
type: "@statelyai.setMode",
|
|
135
|
+
mode
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
setTheme(theme) {
|
|
139
|
+
send({
|
|
140
|
+
type: "@statelyai.setTheme",
|
|
141
|
+
theme
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
toast(message, toastType) {
|
|
145
|
+
send({
|
|
146
|
+
type: "@statelyai.toast",
|
|
147
|
+
message,
|
|
148
|
+
toastType
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
export(format, callOptions) {
|
|
152
|
+
return exportManager.start(format, callOptions, "Embed is destroyed", () => destroyed);
|
|
153
|
+
},
|
|
154
|
+
on(event, handler) {
|
|
155
|
+
events.on(event, handler);
|
|
156
|
+
},
|
|
157
|
+
off(event, handler) {
|
|
158
|
+
events.off(event, handler);
|
|
159
|
+
},
|
|
160
|
+
destroy() {
|
|
161
|
+
if (destroyed) return;
|
|
162
|
+
destroyed = true;
|
|
163
|
+
transport?.destroy();
|
|
164
|
+
transport = null;
|
|
165
|
+
exportManager.clear("Embed destroyed");
|
|
166
|
+
events.clear();
|
|
167
|
+
pendingMessages.length = 0;
|
|
168
|
+
if (ownedIframe && iframe) iframe.remove();
|
|
169
|
+
iframe = null;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//#endregion
|
|
175
|
+
export { createStatelyEmbed };
|