@yodaos-pkg/ink 0.3.0 → 0.6.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/{dist/env.js → env.js} +12 -14
- package/index.d.ts +365 -0
- package/{dist/index.js → index.js} +9 -0
- package/package.json +11 -15
- package/{dist/pkg → pkg}/ink_web.d.ts +9 -5
- package/{dist/pkg → pkg}/ink_web.js +29 -16
- package/{dist/pkg → pkg}/ink_web_bg.wasm +0 -0
- package/{dist/pkg → pkg}/ink_web_bg.wasm.d.ts +7 -5
- package/dist/README.md +0 -724
- package/dist/index.d.ts +0 -166
- package/dist/package.json +0 -20
- package/dist/pkg/README.md +0 -34
- package/dist/pkg/package.json +0 -3
package/dist/README.md
DELETED
|
@@ -1,724 +0,0 @@
|
|
|
1
|
-
# `@yodaos-pkg/ink`
|
|
2
|
-
|
|
3
|
-
`@yodaos-pkg/ink` is the browser-facing Ink SDK for third-party frontend
|
|
4
|
-
projects.
|
|
5
|
-
|
|
6
|
-
It wraps the low-level wasm runtime and `InkWebView` into a stable JavaScript
|
|
7
|
-
and TypeScript API so you can:
|
|
8
|
-
|
|
9
|
-
- initialize the Ink wasm runtime
|
|
10
|
-
- create and destroy an `InkView`
|
|
11
|
-
- bind a `canvas` and forward DOM events such as keyboard and pointer input
|
|
12
|
-
- open an Ink bundle directly from memory
|
|
13
|
-
- fetch and render an Ink bundle from an HTTP VFS service
|
|
14
|
-
|
|
15
|
-
## Use Cases
|
|
16
|
-
|
|
17
|
-
This package is designed for:
|
|
18
|
-
|
|
19
|
-
- plain browser-based frontend applications
|
|
20
|
-
- React applications embedding Ink inside a component
|
|
21
|
-
- Vue applications embedding Ink inside a page or component
|
|
22
|
-
- frontend apps that fetch Ink resources from a backend VFS service
|
|
23
|
-
|
|
24
|
-
## What You Need Before Starting
|
|
25
|
-
|
|
26
|
-
Before integrating the SDK, make sure you have one of these two inputs:
|
|
27
|
-
|
|
28
|
-
1. An in-memory bundle
|
|
29
|
-
- You already have the contents of `app.json`, page scripts, styles, images,
|
|
30
|
-
and other files.
|
|
31
|
-
- This is a good fit when your build pipeline or backend has already prepared
|
|
32
|
-
the bundle.
|
|
33
|
-
|
|
34
|
-
2. A VFS service URL
|
|
35
|
-
- The frontend only knows an `appId` and an HTTP VFS endpoint.
|
|
36
|
-
- This is a good fit when assets live on the server and the browser fetches
|
|
37
|
-
them on demand.
|
|
38
|
-
|
|
39
|
-
If you use the VFS flow, provide your own HTTP VFS endpoint on the server side.
|
|
40
|
-
|
|
41
|
-
## Installation
|
|
42
|
-
|
|
43
|
-
### Step 1: Install the SDK
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
npm install @yodaos-pkg/ink
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
If you also want to use the VFS flow, prepare an HTTP endpoint that exposes:
|
|
50
|
-
|
|
51
|
-
```text
|
|
52
|
-
GET /apps/:appId/manifest
|
|
53
|
-
GET /apps/:appId/files/:path
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Core API
|
|
57
|
-
|
|
58
|
-
These are the most commonly used APIs:
|
|
59
|
-
|
|
60
|
-
### `createInkView(options)`
|
|
61
|
-
|
|
62
|
-
Creates an `InkView` instance and initializes the wasm runtime internally.
|
|
63
|
-
|
|
64
|
-
**Parameters**
|
|
65
|
-
|
|
66
|
-
- `options.width: number`
|
|
67
|
-
- Required
|
|
68
|
-
- The logical width of the Ink view
|
|
69
|
-
- `options.height: number`
|
|
70
|
-
- Required
|
|
71
|
-
- The logical height of the Ink view
|
|
72
|
-
- `options.scaleFactor?: number`
|
|
73
|
-
- Optional
|
|
74
|
-
- The device pixel ratio, defaulting to `window.devicePixelRatio`
|
|
75
|
-
- `options.canvas?: HTMLCanvasElement`
|
|
76
|
-
- Optional
|
|
77
|
-
- If provided, the view is automatically bound to this canvas
|
|
78
|
-
- `options.wasm?: InitInkOptions`
|
|
79
|
-
- Optional
|
|
80
|
-
- Lets you customize wasm initialization
|
|
81
|
-
- `wasmUrl?: string | URL | Request`
|
|
82
|
-
- `moduleOrPath?: RequestInfo | URL | Response | BufferSource | WebAssembly.Module`
|
|
83
|
-
|
|
84
|
-
**What it does**
|
|
85
|
-
|
|
86
|
-
- Initializes the Ink wasm runtime
|
|
87
|
-
- Creates the underlying `InkWebView`
|
|
88
|
-
- Returns the higher-level `InkView` wrapper
|
|
89
|
-
- Automatically calls `bindCanvas()` if a `canvas` is provided
|
|
90
|
-
|
|
91
|
-
**Returns**
|
|
92
|
-
|
|
93
|
-
- `Promise<InkView>`
|
|
94
|
-
- Resolves to an `InkView` instance that can then call
|
|
95
|
-
`bindDomEvents()`, `openBundle()`, and `openFromVfs()`
|
|
96
|
-
|
|
97
|
-
### `configureNetwork(options)`
|
|
98
|
-
|
|
99
|
-
Configures host-controlled request interception for Ink network traffic.
|
|
100
|
-
|
|
101
|
-
**Parameters**
|
|
102
|
-
|
|
103
|
-
- `options.interceptor`
|
|
104
|
-
- Optional
|
|
105
|
-
- A function that receives the outgoing request and returns an action
|
|
106
|
-
- `options.proxyUrl`
|
|
107
|
-
- Optional
|
|
108
|
-
- A convenience option for rewriting requests through a proxy endpoint
|
|
109
|
-
- `options.targetSearchParam`
|
|
110
|
-
- Optional
|
|
111
|
-
- The query parameter name used when `proxyUrl` is provided
|
|
112
|
-
- `options.clear`
|
|
113
|
-
- Optional
|
|
114
|
-
- Clears the previously registered interceptor
|
|
115
|
-
|
|
116
|
-
**What it does**
|
|
117
|
-
|
|
118
|
-
- Registers a global Ink request interceptor
|
|
119
|
-
- Lets hosts continue, rewrite, or block outgoing requests
|
|
120
|
-
- Mirrors the shape of a WebView-style request interception hook
|
|
121
|
-
|
|
122
|
-
**Returns**
|
|
123
|
-
|
|
124
|
-
- `void`
|
|
125
|
-
|
|
126
|
-
### `createProxyUrlResolver(options)`
|
|
127
|
-
|
|
128
|
-
Creates a request interceptor that rewrites outgoing requests to a host-managed
|
|
129
|
-
proxy endpoint such as `'/__proxy?url=...'`.
|
|
130
|
-
|
|
131
|
-
**Parameters**
|
|
132
|
-
|
|
133
|
-
- `options.proxyUrl`
|
|
134
|
-
- Required
|
|
135
|
-
- The proxy endpoint to call
|
|
136
|
-
- `options.targetSearchParam`
|
|
137
|
-
- Optional
|
|
138
|
-
- The query parameter name that receives the original target URL
|
|
139
|
-
|
|
140
|
-
**Returns**
|
|
141
|
-
|
|
142
|
-
- `InkRequestInterceptor`
|
|
143
|
-
- A reusable interceptor for `configureNetwork()` or `initInk()`
|
|
144
|
-
|
|
145
|
-
### `view.bindDomEvents(options?)`
|
|
146
|
-
|
|
147
|
-
Binds common DOM events to the current `InkView`.
|
|
148
|
-
|
|
149
|
-
**Parameters**
|
|
150
|
-
|
|
151
|
-
- `options.canvas?: HTMLCanvasElement`
|
|
152
|
-
- Optional
|
|
153
|
-
- Overrides the currently bound canvas
|
|
154
|
-
- `options.keyboardTarget?: EventTarget | null`
|
|
155
|
-
- Optional
|
|
156
|
-
- The keyboard event target, defaulting to `window` when available
|
|
157
|
-
- `options.focusTarget?: HTMLElement | HTMLCanvasElement | null`
|
|
158
|
-
- Optional
|
|
159
|
-
- The target used for focus and blur events, defaulting to the canvas
|
|
160
|
-
- `options.preventWheelDefault?: boolean`
|
|
161
|
-
- Optional
|
|
162
|
-
- Controls whether wheel default behavior is prevented
|
|
163
|
-
- Defaults to `true`
|
|
164
|
-
|
|
165
|
-
**What it does**
|
|
166
|
-
|
|
167
|
-
- Binds `pointerdown` / `pointermove` / `pointerup` / `pointercancel`
|
|
168
|
-
- Binds `wheel`
|
|
169
|
-
- Binds `keydown` / `keyup`
|
|
170
|
-
- Binds `focus` / `blur`
|
|
171
|
-
- Automatically forwards these browser events into the Ink runtime
|
|
172
|
-
|
|
173
|
-
**Returns**
|
|
174
|
-
|
|
175
|
-
- `() => void`
|
|
176
|
-
- Returns a cleanup function
|
|
177
|
-
- Calling it removes every listener created by this binding call
|
|
178
|
-
|
|
179
|
-
### `view.openBundle(options)`
|
|
180
|
-
|
|
181
|
-
Opens an Ink bundle that already exists in memory.
|
|
182
|
-
|
|
183
|
-
**Parameters**
|
|
184
|
-
|
|
185
|
-
- `options.appId: string`
|
|
186
|
-
- Required
|
|
187
|
-
- The application ID of the Ink app to open
|
|
188
|
-
- `options.files: BundleFiles`
|
|
189
|
-
- Required
|
|
190
|
-
- Supports three formats:
|
|
191
|
-
- `Map<string, BundleFileInput>`
|
|
192
|
-
- `Array<[string, BundleFileInput]>`
|
|
193
|
-
- `Record<string, BundleFileInput>`
|
|
194
|
-
- `BundleFileInput`
|
|
195
|
-
- Supported input types:
|
|
196
|
-
- `string`
|
|
197
|
-
- `Uint8Array`
|
|
198
|
-
- `ArrayBuffer`
|
|
199
|
-
- `ArrayBufferView`
|
|
200
|
-
- `options.initialPage?: string | null`
|
|
201
|
-
- Optional
|
|
202
|
-
- Sets the first page to open
|
|
203
|
-
- `options.query?: string | Record<string, unknown> | null`
|
|
204
|
-
- Optional
|
|
205
|
-
- Initial query payload
|
|
206
|
-
- If an object is provided, the SDK serializes it into JSON
|
|
207
|
-
|
|
208
|
-
**What it does**
|
|
209
|
-
|
|
210
|
-
- Normalizes the file set into the bundle shape expected by the runtime
|
|
211
|
-
- Calls the underlying `openBundle`
|
|
212
|
-
- Opens the requested Ink app
|
|
213
|
-
- Automatically triggers a render request
|
|
214
|
-
|
|
215
|
-
**Returns**
|
|
216
|
-
|
|
217
|
-
- `InkView`
|
|
218
|
-
- Returns the current instance so it can be chained
|
|
219
|
-
|
|
220
|
-
### `view.openFromVfs(options)`
|
|
221
|
-
|
|
222
|
-
Fetches an Ink bundle from a remote HTTP VFS service and opens it.
|
|
223
|
-
|
|
224
|
-
**Parameters**
|
|
225
|
-
|
|
226
|
-
- `options.appId: string`
|
|
227
|
-
- Required
|
|
228
|
-
- The application ID to open
|
|
229
|
-
- `options.baseUrl: string`
|
|
230
|
-
- Required
|
|
231
|
-
- The VFS service base URL, for example
|
|
232
|
-
`https://example.com/ink-vfs`
|
|
233
|
-
- `options.fetch?: typeof globalThis.fetch`
|
|
234
|
-
- Optional
|
|
235
|
-
- Lets you provide a custom `fetch` implementation
|
|
236
|
-
- `options.signal?: AbortSignal`
|
|
237
|
-
- Optional
|
|
238
|
-
- Used to cancel the request flow
|
|
239
|
-
- `options.headers?: HeadersInit`
|
|
240
|
-
- Optional
|
|
241
|
-
- Extra request headers
|
|
242
|
-
- `options.requestInterceptor?: InkRequestInterceptor`
|
|
243
|
-
- Optional
|
|
244
|
-
- Overrides the global interceptor for this VFS load only
|
|
245
|
-
- `options.initialPage?: string | null`
|
|
246
|
-
- Optional
|
|
247
|
-
- Sets the first page to open
|
|
248
|
-
- `options.query?: string | Record<string, unknown> | null`
|
|
249
|
-
- Optional
|
|
250
|
-
- Initial query payload
|
|
251
|
-
|
|
252
|
-
**What it does**
|
|
253
|
-
|
|
254
|
-
- Fetches the VFS manifest first
|
|
255
|
-
- Fetches each file listed in the manifest
|
|
256
|
-
- Reconstructs the bundle in the browser
|
|
257
|
-
- Applies the request interceptor when one is configured
|
|
258
|
-
- Calls `openBundle()` automatically
|
|
259
|
-
|
|
260
|
-
**Returns**
|
|
261
|
-
|
|
262
|
-
- `Promise<LoadedVfsBundle>`
|
|
263
|
-
- Resolves to the fetched bundle data:
|
|
264
|
-
- `appId: string`
|
|
265
|
-
- `manifest: VfsManifest`
|
|
266
|
-
- `files: Map<string, Uint8Array>`
|
|
267
|
-
|
|
268
|
-
### `initInk(options)`
|
|
269
|
-
|
|
270
|
-
Initializes the wasm runtime and optionally installs a host networking policy.
|
|
271
|
-
|
|
272
|
-
**Parameters**
|
|
273
|
-
|
|
274
|
-
- `options.wasmUrl?: string | URL | Request`
|
|
275
|
-
- Optional
|
|
276
|
-
- Custom URL for the wasm binary
|
|
277
|
-
- `options.moduleOrPath?: RequestInfo | URL | Response | BufferSource | WebAssembly.Module`
|
|
278
|
-
- Optional
|
|
279
|
-
- Custom wasm module input supported by `wasm-bindgen`
|
|
280
|
-
- `options.requestInterceptor?: InkRequestInterceptor`
|
|
281
|
-
- Optional
|
|
282
|
-
- Installs a host request interceptor before Ink networking starts
|
|
283
|
-
- `options.proxyUrl?: string`
|
|
284
|
-
- Optional
|
|
285
|
-
- Shorthand for a proxy-based interceptor
|
|
286
|
-
|
|
287
|
-
**Returns**
|
|
288
|
-
|
|
289
|
-
- `Promise<{ InkWebView, getInkVersion }>`
|
|
290
|
-
- Resolves to the wasm bindings
|
|
291
|
-
|
|
292
|
-
### `view.startRendering()`
|
|
293
|
-
|
|
294
|
-
Starts the continuous render loop.
|
|
295
|
-
|
|
296
|
-
**Parameters**
|
|
297
|
-
|
|
298
|
-
- None
|
|
299
|
-
|
|
300
|
-
**What it does**
|
|
301
|
-
|
|
302
|
-
- Enables automatic rendering mode
|
|
303
|
-
- Uses `requestAnimationFrame` internally to keep rendering
|
|
304
|
-
- Works well for animations, interaction-heavy apps, and continuously updating
|
|
305
|
-
UIs
|
|
306
|
-
|
|
307
|
-
**Returns**
|
|
308
|
-
|
|
309
|
-
- `InkView`
|
|
310
|
-
- Returns the current instance so it can be chained
|
|
311
|
-
|
|
312
|
-
### `view.destroy()`
|
|
313
|
-
|
|
314
|
-
Destroys the current `InkView` and releases its resources.
|
|
315
|
-
|
|
316
|
-
**Parameters**
|
|
317
|
-
|
|
318
|
-
- None
|
|
319
|
-
|
|
320
|
-
**What it does**
|
|
321
|
-
|
|
322
|
-
- Stops the render loop
|
|
323
|
-
- Removes event listeners created by `bindDomEvents()`
|
|
324
|
-
- Calls the underlying `InkWebView.destroy()`
|
|
325
|
-
- Releases runtime resources held by the current view
|
|
326
|
-
|
|
327
|
-
**Returns**
|
|
328
|
-
|
|
329
|
-
- `void`
|
|
330
|
-
|
|
331
|
-
## Plain JavaScript Integration
|
|
332
|
-
|
|
333
|
-
This is the most direct way to integrate Ink into a plain JavaScript app.
|
|
334
|
-
|
|
335
|
-
### Step 1: Prepare a container element
|
|
336
|
-
|
|
337
|
-
Start with a `canvas` element:
|
|
338
|
-
|
|
339
|
-
```html
|
|
340
|
-
<canvas id="ink-root" style="width: 375px; height: 667px;"></canvas>
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### Step 2: Import the SDK
|
|
344
|
-
|
|
345
|
-
```js
|
|
346
|
-
import { createInkView } from '@yodaos-pkg/ink';
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### Step 3: Prepare the bundle files
|
|
350
|
-
|
|
351
|
-
If your assets are already available in memory, organize them as an object or a
|
|
352
|
-
`Map`:
|
|
353
|
-
|
|
354
|
-
```js
|
|
355
|
-
const files = {
|
|
356
|
-
'app.json': JSON.stringify({
|
|
357
|
-
pages: ['pages/index/index'],
|
|
358
|
-
}),
|
|
359
|
-
'pages/index/index.js': `
|
|
360
|
-
export default {
|
|
361
|
-
data: {
|
|
362
|
-
title: 'Hello Ink'
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
`,
|
|
366
|
-
};
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### Step 4: Create the view and bind the canvas
|
|
370
|
-
|
|
371
|
-
```js
|
|
372
|
-
const canvas = document.getElementById('ink-root');
|
|
373
|
-
|
|
374
|
-
const view = await createInkView({
|
|
375
|
-
width: canvas.clientWidth,
|
|
376
|
-
height: canvas.clientHeight,
|
|
377
|
-
scaleFactor: window.devicePixelRatio,
|
|
378
|
-
canvas,
|
|
379
|
-
});
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
### Step 5: Bind DOM events
|
|
383
|
-
|
|
384
|
-
This wires common pointer, keyboard, focus, and blur events automatically:
|
|
385
|
-
|
|
386
|
-
```js
|
|
387
|
-
view.bindDomEvents();
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Step 6: Open the Ink bundle
|
|
391
|
-
|
|
392
|
-
```js
|
|
393
|
-
view.openBundle({
|
|
394
|
-
appId: 'demo-app',
|
|
395
|
-
files,
|
|
396
|
-
});
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### Step 7: Start the render loop
|
|
400
|
-
|
|
401
|
-
```js
|
|
402
|
-
view.startRendering();
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
### Step 8: Clean up when the page is destroyed
|
|
406
|
-
|
|
407
|
-
```js
|
|
408
|
-
window.addEventListener('beforeunload', () => {
|
|
409
|
-
view.destroy();
|
|
410
|
-
});
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
### Full Plain JavaScript Example
|
|
414
|
-
|
|
415
|
-
```js
|
|
416
|
-
import { createInkView } from '@yodaos-pkg/ink';
|
|
417
|
-
|
|
418
|
-
const files = {
|
|
419
|
-
'app.json': JSON.stringify({
|
|
420
|
-
pages: ['pages/index/index'],
|
|
421
|
-
}),
|
|
422
|
-
'pages/index/index.js': `
|
|
423
|
-
export default {
|
|
424
|
-
data: {
|
|
425
|
-
title: 'Hello Ink'
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
`,
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
const canvas = document.getElementById('ink-root');
|
|
432
|
-
|
|
433
|
-
const view = await createInkView({
|
|
434
|
-
width: canvas.clientWidth,
|
|
435
|
-
height: canvas.clientHeight,
|
|
436
|
-
scaleFactor: window.devicePixelRatio,
|
|
437
|
-
canvas,
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
view.bindDomEvents();
|
|
441
|
-
view.openBundle({
|
|
442
|
-
appId: 'demo-app',
|
|
443
|
-
files,
|
|
444
|
-
});
|
|
445
|
-
view.startRendering();
|
|
446
|
-
|
|
447
|
-
window.addEventListener('beforeunload', () => {
|
|
448
|
-
view.destroy();
|
|
449
|
-
});
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
## Opening an App Through VFS
|
|
453
|
-
|
|
454
|
-
If you do not want to embed the full bundle in the browser and instead prefer
|
|
455
|
-
to fetch resources from the server, use `openFromVfs()`.
|
|
456
|
-
|
|
457
|
-
### Step 1: Prepare an accessible VFS service
|
|
458
|
-
|
|
459
|
-
For example, the server may expose:
|
|
460
|
-
|
|
461
|
-
- `https://example.com/ink-vfs/apps/demo-app/manifest`
|
|
462
|
-
- `https://example.com/ink-vfs/apps/demo-app/files/...`
|
|
463
|
-
|
|
464
|
-
### Step 2: Create the view
|
|
465
|
-
|
|
466
|
-
```js
|
|
467
|
-
import { createInkView } from '@yodaos-pkg/ink';
|
|
468
|
-
|
|
469
|
-
const canvas = document.getElementById('ink-root');
|
|
470
|
-
|
|
471
|
-
const view = await createInkView({
|
|
472
|
-
width: canvas.clientWidth,
|
|
473
|
-
height: canvas.clientHeight,
|
|
474
|
-
scaleFactor: window.devicePixelRatio,
|
|
475
|
-
canvas,
|
|
476
|
-
});
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
### Step 3: Open the remote app
|
|
480
|
-
|
|
481
|
-
```js
|
|
482
|
-
view.bindDomEvents();
|
|
483
|
-
|
|
484
|
-
await view.openFromVfs({
|
|
485
|
-
appId: 'demo-app',
|
|
486
|
-
baseUrl: 'https://example.com/ink-vfs',
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
view.startRendering();
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
### Step 4: Release resources when done
|
|
493
|
-
|
|
494
|
-
```js
|
|
495
|
-
view.destroy();
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
## Vue.js Integration
|
|
499
|
-
|
|
500
|
-
The recommended approach is to wrap Ink inside a Vue component and manage it
|
|
501
|
-
through `onMounted` and `onBeforeUnmount`.
|
|
502
|
-
|
|
503
|
-
### Step 1: Install the dependency
|
|
504
|
-
|
|
505
|
-
```bash
|
|
506
|
-
npm install @yodaos-pkg/ink
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Step 2: Create a Vue component
|
|
510
|
-
|
|
511
|
-
Below is a minimal `InkCanvas.vue` example.
|
|
512
|
-
|
|
513
|
-
### Step 3: Initialize in `onMounted`
|
|
514
|
-
|
|
515
|
-
- Get the `canvas`
|
|
516
|
-
- Create the `InkView`
|
|
517
|
-
- Bind DOM events
|
|
518
|
-
- Open the bundle
|
|
519
|
-
- Start rendering
|
|
520
|
-
|
|
521
|
-
### Step 4: Clean up in `onBeforeUnmount`
|
|
522
|
-
|
|
523
|
-
- Call `view.destroy()`
|
|
524
|
-
|
|
525
|
-
### Full Vue Example
|
|
526
|
-
|
|
527
|
-
```vue
|
|
528
|
-
<script setup lang="ts">
|
|
529
|
-
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
|
530
|
-
import { createInkView } from '@yodaos-pkg/ink';
|
|
531
|
-
|
|
532
|
-
const props = defineProps<{
|
|
533
|
-
appId: string;
|
|
534
|
-
files: Record<string, string | Uint8Array>;
|
|
535
|
-
}>();
|
|
536
|
-
|
|
537
|
-
const canvasRef = ref<HTMLCanvasElement | null>(null);
|
|
538
|
-
let cleanup = () => {};
|
|
539
|
-
|
|
540
|
-
onMounted(async () => {
|
|
541
|
-
const canvas = canvasRef.value;
|
|
542
|
-
if (!canvas) {
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
const view = await createInkView({
|
|
547
|
-
width: canvas.clientWidth,
|
|
548
|
-
height: canvas.clientHeight,
|
|
549
|
-
scaleFactor: window.devicePixelRatio,
|
|
550
|
-
canvas,
|
|
551
|
-
});
|
|
552
|
-
|
|
553
|
-
view.bindDomEvents();
|
|
554
|
-
view.openBundle({
|
|
555
|
-
appId: props.appId,
|
|
556
|
-
files: props.files,
|
|
557
|
-
});
|
|
558
|
-
view.startRendering();
|
|
559
|
-
|
|
560
|
-
cleanup = () => view.destroy();
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
onBeforeUnmount(() => {
|
|
564
|
-
cleanup();
|
|
565
|
-
});
|
|
566
|
-
</script>
|
|
567
|
-
|
|
568
|
-
<template>
|
|
569
|
-
<canvas ref="canvasRef" style="width: 375px; height: 667px;" />
|
|
570
|
-
</template>
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
### Vue Integration Tips
|
|
574
|
-
|
|
575
|
-
- Treat `files` and `appId` as component inputs
|
|
576
|
-
- If the bundle changes, destroy the old view before creating a new one
|
|
577
|
-
- If the component size changes, call `view.resize()` from the host layer
|
|
578
|
-
|
|
579
|
-
## React.js Integration
|
|
580
|
-
|
|
581
|
-
The recommended approach is to wrap Ink in a React component and manage its
|
|
582
|
-
lifecycle inside `useEffect`.
|
|
583
|
-
|
|
584
|
-
### Step 1: Install the dependency
|
|
585
|
-
|
|
586
|
-
```bash
|
|
587
|
-
npm install @yodaos-pkg/ink
|
|
588
|
-
```
|
|
589
|
-
|
|
590
|
-
### Step 2: Create a React component
|
|
591
|
-
|
|
592
|
-
The component keeps a `canvas ref` and creates or destroys the Ink view inside
|
|
593
|
-
`useEffect`.
|
|
594
|
-
|
|
595
|
-
### Step 3: Initialize inside `useEffect`
|
|
596
|
-
|
|
597
|
-
- Get the `canvas`
|
|
598
|
-
- Create the `InkView`
|
|
599
|
-
- Bind DOM events
|
|
600
|
-
- Open the bundle
|
|
601
|
-
- Start rendering
|
|
602
|
-
|
|
603
|
-
### Step 4: Destroy it in the effect cleanup
|
|
604
|
-
|
|
605
|
-
- Call `view.destroy()`
|
|
606
|
-
|
|
607
|
-
### Full React Example
|
|
608
|
-
|
|
609
|
-
```tsx
|
|
610
|
-
import { useEffect, useRef } from 'react';
|
|
611
|
-
import { createInkView } from '@yodaos-pkg/ink';
|
|
612
|
-
|
|
613
|
-
type InkCanvasProps = {
|
|
614
|
-
appId: string;
|
|
615
|
-
files: Record<string, string | Uint8Array>;
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
export function InkCanvas({ appId, files }: InkCanvasProps) {
|
|
619
|
-
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
|
620
|
-
|
|
621
|
-
useEffect(() => {
|
|
622
|
-
let disposed = false;
|
|
623
|
-
let cleanup = () => {};
|
|
624
|
-
|
|
625
|
-
async function mount() {
|
|
626
|
-
const canvas = canvasRef.current;
|
|
627
|
-
if (!canvas) {
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
const view = await createInkView({
|
|
632
|
-
width: canvas.clientWidth,
|
|
633
|
-
height: canvas.clientHeight,
|
|
634
|
-
scaleFactor: window.devicePixelRatio,
|
|
635
|
-
canvas,
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
view.bindDomEvents();
|
|
639
|
-
view.openBundle({
|
|
640
|
-
appId,
|
|
641
|
-
files,
|
|
642
|
-
});
|
|
643
|
-
view.startRendering();
|
|
644
|
-
|
|
645
|
-
cleanup = () => view.destroy();
|
|
646
|
-
if (disposed) {
|
|
647
|
-
cleanup();
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
mount();
|
|
652
|
-
|
|
653
|
-
return () => {
|
|
654
|
-
disposed = true;
|
|
655
|
-
cleanup();
|
|
656
|
-
};
|
|
657
|
-
}, [appId, files]);
|
|
658
|
-
|
|
659
|
-
return <canvas ref={canvasRef} style={{ width: 375, height: 667 }} />;
|
|
660
|
-
}
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
### React Integration Tips
|
|
664
|
-
|
|
665
|
-
- Keep `files` as a stable reference when possible, so the view is not rebuilt
|
|
666
|
-
on every render
|
|
667
|
-
- If you need to switch apps, reinitialize when `appId` or a wrapping `key`
|
|
668
|
-
changes
|
|
669
|
-
- If the host size changes significantly, use `ResizeObserver` and call
|
|
670
|
-
`view.resize()`
|
|
671
|
-
|
|
672
|
-
## Frequently Asked Questions
|
|
673
|
-
|
|
674
|
-
### 1. The page renders, but input does not work
|
|
675
|
-
|
|
676
|
-
The usual cause is missing this step:
|
|
677
|
-
|
|
678
|
-
```js
|
|
679
|
-
view.bindDomEvents();
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
### 2. Resources are still retained after the page is destroyed
|
|
683
|
-
|
|
684
|
-
Make sure you call this when the component unmounts or the page exits:
|
|
685
|
-
|
|
686
|
-
```js
|
|
687
|
-
view.destroy();
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
### 3. Should bundle files be strings or binary?
|
|
691
|
-
|
|
692
|
-
Both are supported:
|
|
693
|
-
|
|
694
|
-
- `string`
|
|
695
|
-
- `Uint8Array`
|
|
696
|
-
- `ArrayBuffer`
|
|
697
|
-
|
|
698
|
-
### 4. When should I use `openBundle()` vs `openFromVfs()`?
|
|
699
|
-
|
|
700
|
-
- If you already have the full resource contents, use `openBundle()`
|
|
701
|
-
- If you only know the `appId` and a server endpoint, use `openFromVfs()`
|
|
702
|
-
|
|
703
|
-
## Local Development
|
|
704
|
-
|
|
705
|
-
### Build
|
|
706
|
-
|
|
707
|
-
```bash
|
|
708
|
-
npm run build
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
### Test
|
|
712
|
-
|
|
713
|
-
```bash
|
|
714
|
-
npm test
|
|
715
|
-
```
|
|
716
|
-
|
|
717
|
-
## Package Shape
|
|
718
|
-
|
|
719
|
-
- `dist/index.js`
|
|
720
|
-
- SDK entry point
|
|
721
|
-
- `dist/pkg/*`
|
|
722
|
-
- wasm-bindgen output
|
|
723
|
-
- `dist/env.js`
|
|
724
|
-
- runtime import shim
|