@yodaos-pkg/ink 0.9.1 → 0.10.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 CHANGED
@@ -76,6 +76,10 @@ Creates an `InkView` instance and initializes the wasm runtime internally.
76
76
  - `options.scaleFactor?: number`
77
77
  - Optional
78
78
  - The device pixel ratio, defaulting to `window.devicePixelRatio`
79
+ - `options.appFps?: number`
80
+ - Optional
81
+ - Per-view app logic frame rate
82
+ - Defaults to `60`
79
83
  - `options.canvas?: HTMLCanvasElement`
80
84
  - Optional
81
85
  - If provided, the view is automatically bound to this canvas
@@ -109,6 +113,7 @@ const view = await createInkView({
109
113
  width: 360,
110
114
  layoutMode: 'width-constrained-auto-height',
111
115
  scaleFactor: window.devicePixelRatio,
116
+ appFps: 30,
112
117
  canvas,
113
118
  });
114
119
  ```
@@ -117,7 +122,8 @@ In this mode:
117
122
 
118
123
  - the host still owns the constrained width
119
124
  - the SDK automatically adopts runtime-reported content height
120
- - browser hosts should call `view.resize()` when width or device pixel ratio changes
125
+ - browser hosts should call `view.setViewport()` when width or device pixel ratio changes
126
+ - pass `{ resetScroll: true }` only when the host explicitly wants to reset the current page scroll position during that viewport update
121
127
  - browser hosts do not need to manually apply HTML canvas height in the common case
122
128
 
123
129
  ### `configureNetwork(options)`
@@ -800,7 +806,7 @@ onBeforeUnmount(() => {
800
806
 
801
807
  - Treat `files` and `appId` as component inputs
802
808
  - If the bundle changes, destroy the old view before creating a new one
803
- - If the component size changes, call `view.resize()` from the host layer
809
+ - If the component size changes, call `view.setViewport()` from the host layer
804
810
 
805
811
  ## React.js Integration
806
812
 
@@ -898,7 +904,7 @@ export function InkCanvas({ appId, files }: InkCanvasProps) {
898
904
  - If you need to switch apps, reinitialize when `appId` or a wrapping `key`
899
905
  changes
900
906
  - If the host size changes significantly, use `ResizeObserver` and call
901
- `view.resize()`
907
+ `view.setViewport()`
902
908
 
903
909
  ## Frequently Asked Questions
904
910
 
package/index.d.ts CHANGED
@@ -44,8 +44,12 @@ export interface CreateInkViewOptions {
44
44
  height?: number;
45
45
  /** Layout behavior used by the host surface. Defaults to `bounded`. */
46
46
  layoutMode?: InkLayoutMode;
47
+ /** Optional built-in Ink host theme name applied when bootstrapping the view. */
48
+ themeName?: string;
47
49
  /** Device pixel ratio override. Defaults to `window.devicePixelRatio` when available. */
48
50
  scaleFactor?: number;
51
+ /** Per-view app logic frame rate. Defaults to `60`. */
52
+ appFps?: number;
49
53
  /** Legacy shortcut for immediately binding an HTML canvas after creation. */
50
54
  canvas?: HTMLCanvasElement;
51
55
  /** Optional surface descriptor bound immediately after creation. */
@@ -63,6 +67,20 @@ export interface CreateInkViewOptions {
63
67
  /** Cross-platform layout mode exposed by browser hosts. */
64
68
  export type InkLayoutMode = 'bounded' | 'width-constrained-auto-height';
65
69
 
70
+ /**
71
+ * Optional resize-time overrides applied atomically with the new viewport size.
72
+ *
73
+ * When `layoutMode` is omitted, the current view mode is preserved. When
74
+ * `scaleFactor` is omitted, the current view scale factor is preserved.
75
+ * `resetScroll` defaults to `false` and only resets the current page scroll
76
+ * position when explicitly enabled.
77
+ */
78
+ export interface InkResizeOptions {
79
+ scaleFactor?: number;
80
+ layoutMode?: InkLayoutMode;
81
+ resetScroll?: boolean;
82
+ }
83
+
66
84
  /** Measured content size reported by the Ink runtime in CSS pixels. */
67
85
  export interface InkContentSize {
68
86
  width: number;
@@ -240,8 +258,18 @@ export interface InkHostMessageStream {
240
258
  close(): void;
241
259
  }
242
260
 
243
- /** Callback invoked after the runtime requests that the host close the current view. */
244
- export type InkCloseRequestedHandler = () => void;
261
+ export interface InkCloseRequestContext {
262
+ source: 'host-close' | 'window-close' | 'exit-mini-program' | 'root-backspace';
263
+ }
264
+
265
+ export interface InkClosedContext {
266
+ source: 'host-close' | 'window-close' | 'exit-mini-program' | 'root-backspace';
267
+ }
268
+
269
+ /** Callback invoked before the runtime closes, allowing the host to allow or deny it. */
270
+ export type InkCloseRequestedHandler = (context: InkCloseRequestContext) => boolean;
271
+ /** Callback invoked after the runtime successfully closes. */
272
+ export type InkClosedHandler = (context: InkClosedContext) => void;
245
273
  /** Callback invoked after the runtime reports a new measured content size. */
246
274
  export type InkContentSizeChangedHandler = (contentSize: InkContentSize) => void;
247
275
 
@@ -388,13 +416,30 @@ export declare class InkView {
388
416
  openFromVfs(options: OpenFromVfsOptions): Promise<LoadedVfsBundle>;
389
417
 
390
418
  /**
391
- * Resizes the logical surface and optionally updates the scale factor.
419
+ * Sets the logical viewport and optionally updates the scale factor.
392
420
  *
393
421
  * Hosts should call this whenever the constrained width or device pixel ratio
394
422
  * changes. In `width-constrained-auto-height` mode, the SDK continues to
395
423
  * adopt the runtime-reported height automatically after width-driven relayout.
396
424
  */
425
+ setViewport(width: number, height: number, scaleFactor?: number): this;
426
+ /**
427
+ * Sets the logical viewport and atomically applies optional viewport-time overrides.
428
+ *
429
+ * Use this overload when the host needs to update `layoutMode` together with
430
+ * the new viewport size in one call, without exposing an intermediate mode or
431
+ * size state to the host surface. Pass `resetScroll: true` to also reset the
432
+ * current page scroll position as part of the same update.
433
+ */
434
+ setViewport(width: number, height: number, options: InkResizeOptions): this;
435
+ /**
436
+ * Legacy alias for `setViewport()`.
437
+ *
438
+ * Prefer `setViewport()` for new integrations.
439
+ */
397
440
  resize(width: number, height: number, scaleFactor?: number): this;
441
+ /** Legacy alias for `setViewport()`. */
442
+ resize(width: number, height: number, options: InkResizeOptions): this;
398
443
 
399
444
  /** Switches the active layout mode and forces the current page to re-layout. */
400
445
  setLayoutMode(layoutMode: InkLayoutMode): this;
@@ -493,19 +538,35 @@ export declare class InkView {
493
538
  isDestroyed(): boolean;
494
539
 
495
540
  /**
496
- * Registers the callback fired after Ink requests that the host close this view.
541
+ * Registers the pre-close interceptor fired when Ink asks the host whether a
542
+ * close request should be allowed.
543
+ *
544
+ * The callback must synchronously return `true` to allow closing or `false`
545
+ * to deny it. When omitted, the SDK preserves the current compatible behavior
546
+ * and allows closing by default.
497
547
  *
498
- * When close is requested, the SDK marks the view as close-requested, stops
499
- * the internal render loop automatically, relies on the runtime to blank the
500
- * currently attached surface, and then invokes this callback.
548
+ * Throwing or returning a non-boolean value is treated as "deny close".
501
549
  * Pass `null` to clear the current callback.
502
550
  */
503
551
  setOnCloseRequested(callback: InkCloseRequestedHandler | null): this;
504
552
 
505
- /** Property-style close callback preferred by the new SDK shape. */
553
+ /** Property-style pre-close interceptor preferred by the new SDK shape. */
506
554
  onCloseRequested: InkCloseRequestedHandler | null;
507
555
 
508
- /** Returns whether Ink has already requested that the host close this view. */
556
+ /**
557
+ * Registers the post-close callback fired only after the host allowed the
558
+ * close request and the runtime reported that closing completed.
559
+ */
560
+ setOnClosed(callback: InkClosedHandler | null): this;
561
+
562
+ /** Property-style post-close notification preferred by the new SDK shape. */
563
+ onClosed: InkClosedHandler | null;
564
+
565
+ /**
566
+ * Returns whether the current app lifetime has already completed closing.
567
+ *
568
+ * This remains `false` when the host denies a close request.
569
+ */
509
570
  isCloseRequested(): boolean;
510
571
 
511
572
  /** Registers the callback fired after Ink reports a new measured content size. */
package/index.js CHANGED
@@ -28,6 +28,14 @@ function normalizeScaleFactor(value) {
28
28
  return 1;
29
29
  }
30
30
 
31
+ function normalizeAppFps(value) {
32
+ const numericValue = Math.trunc(Number(value));
33
+ if (Number.isFinite(numericValue) && numericValue > 0) {
34
+ return numericValue;
35
+ }
36
+ return 60;
37
+ }
38
+
31
39
  function ensureFetch(fetchImpl) {
32
40
  const resolved = fetchImpl || globalThis.fetch;
33
41
  if (typeof resolved !== 'function') {
@@ -392,6 +400,18 @@ function normalizeLayoutMode(value) {
392
400
  throw new TypeError('`layoutMode` must be either `bounded` or `width-constrained-auto-height`.');
393
401
  }
394
402
 
403
+ function normalizeThemeName(value) {
404
+ if (value == null) {
405
+ return null;
406
+ }
407
+ const themeName = String(value).trim();
408
+ return themeName ? themeName : null;
409
+ }
410
+
411
+ function isResizeOptions(value) {
412
+ return value != null && typeof value === 'object' && !Array.isArray(value);
413
+ }
414
+
395
415
  function normalizeHostLanguageModelConfig(config) {
396
416
  if (config == null) {
397
417
  return null;
@@ -475,8 +495,10 @@ export class InkView {
475
495
  const config = options || {};
476
496
  const width = Number(config.width);
477
497
  const layoutMode = normalizeLayoutMode(config.layoutMode);
498
+ const themeName = normalizeThemeName(config.themeName);
478
499
  const height = Number(config.height);
479
500
  const scaleFactor = normalizeScaleFactor(config.scaleFactor);
501
+ const appFps = normalizeAppFps(config.appFps);
480
502
 
481
503
  if (!Number.isFinite(width)) {
482
504
  throw new Error('`width` is a required numeric value.');
@@ -490,7 +512,14 @@ export class InkView {
490
512
  const bindings = await initInk(config.wasm);
491
513
  const physicalWidth = Math.max(1, Math.round(width * scaleFactor));
492
514
  const physicalHeight = Math.max(1, Math.round(initialHeight * scaleFactor));
493
- const rawView = new bindings.InkWebView(physicalWidth, physicalHeight, scaleFactor, layoutMode);
515
+ const rawView = new bindings.InkWebView(
516
+ physicalWidth,
517
+ physicalHeight,
518
+ scaleFactor,
519
+ appFps,
520
+ layoutMode,
521
+ themeName,
522
+ );
494
523
  const view = new InkView(rawView, config);
495
524
  const initialSurface =
496
525
  config.surface || (config.canvas ? { type: 'html-canvas', canvas: config.canvas } : null);
@@ -514,6 +543,7 @@ export class InkView {
514
543
  #destroyed;
515
544
  #domCleanup;
516
545
  #onCloseRequested;
546
+ #onClosed;
517
547
  #clearOnDestroy;
518
548
  #logicalWidth;
519
549
  #logicalHeight;
@@ -535,6 +565,7 @@ export class InkView {
535
565
  this.#destroyed = false;
536
566
  this.#domCleanup = null;
537
567
  this.#onCloseRequested = null;
568
+ this.#onClosed = null;
538
569
  this.#clearOnDestroy = options.clearOnDestroy !== false;
539
570
  this.#logicalWidth = Number(options.width) || 1;
540
571
  this.#logicalHeight = Number(options.height) || 1;
@@ -662,6 +693,38 @@ export class InkView {
662
693
  return true;
663
694
  }
664
695
 
696
+ #syncBoundSurfaceSize() {
697
+ if (this.#surfaceBinding?.type === 'html-canvas') {
698
+ this.#syncHtmlCanvasBindingSize(this.#logicalWidth, this.#logicalHeight, {
699
+ updateStyleWidth: true,
700
+ updateContainerWidth: true,
701
+ });
702
+ return;
703
+ }
704
+ this.#syncSurfaceBindingSize(this.#logicalWidth, this.#logicalHeight);
705
+ }
706
+
707
+ #syncAutoHeightSurfaceSize() {
708
+ if (this.#surfaceBinding?.type === 'html-canvas') {
709
+ this.#syncHtmlCanvasBindingSize(this.#logicalWidth, this.#logicalHeight, {
710
+ updateStyleWidth: true,
711
+ updateStyleHeight: true,
712
+ updateContainerWidth: true,
713
+ updateContainerHeight: true,
714
+ });
715
+ return;
716
+ }
717
+ this.#syncSurfaceBindingSize(this.#logicalWidth, this.#logicalHeight);
718
+ }
719
+
720
+ #syncSurfaceForCurrentLayoutMode() {
721
+ if (this.#layoutMode === 'width-constrained-auto-height') {
722
+ this.#syncAutoHeightSurfaceSize();
723
+ return;
724
+ }
725
+ this.#syncBoundSurfaceSize();
726
+ }
727
+
665
728
  #physicalWidth() {
666
729
  return Math.max(1, Math.round(this.#logicalWidth * this.#scaleFactor));
667
730
  }
@@ -670,15 +733,17 @@ export class InkView {
670
733
  return Math.max(1, Math.round((Number(height) || 1) * this.#scaleFactor));
671
734
  }
672
735
 
673
- #syncRawViewSize(width = this.#logicalWidth, height = this.#logicalHeight) {
674
- if (typeof this.#rawView.resize !== 'function') {
736
+ #syncRawViewSize(width = this.#logicalWidth, height = this.#logicalHeight, resetScroll = false) {
737
+ if (typeof this.#rawView.setViewport !== 'function') {
675
738
  return;
676
739
  }
677
- this.#rawView.resize(
678
- Math.max(1, Math.round((Number(width) || 1) * this.#scaleFactor)),
679
- Math.max(1, Math.round((Number(height) || 1) * this.#scaleFactor)),
680
- this.#scaleFactor,
681
- );
740
+ const physicalWidth = Math.max(1, Math.round((Number(width) || 1) * this.#scaleFactor));
741
+ const physicalHeight = Math.max(1, Math.round((Number(height) || 1) * this.#scaleFactor));
742
+ if (resetScroll) {
743
+ this.#rawView.setViewport(physicalWidth, physicalHeight, this.#scaleFactor, true);
744
+ return;
745
+ }
746
+ this.#rawView.setViewport(physicalWidth, physicalHeight, this.#scaleFactor);
682
747
  }
683
748
 
684
749
  #currentContentSize() {
@@ -762,7 +827,7 @@ export class InkView {
762
827
 
763
828
  #consumeCloseRequested() {
764
829
  if (this.#destroyed || this.#closeRequested) {
765
- return this.#closeRequested;
830
+ return false;
766
831
  }
767
832
  if (typeof this.#rawView.consumeCloseRequested !== 'function') {
768
833
  return false;
@@ -771,10 +836,56 @@ export class InkView {
771
836
  return false;
772
837
  }
773
838
 
839
+ const source =
840
+ typeof this.#rawView.currentCloseRequestSource === 'function'
841
+ ? this.#rawView.currentCloseRequestSource()
842
+ : '';
843
+ const context = { source };
844
+ let allow = true;
845
+ if (typeof this.#onCloseRequested === 'function') {
846
+ try {
847
+ const result = this.#onCloseRequested(context);
848
+ if (typeof result !== 'boolean') {
849
+ console.warn(
850
+ 'InkView onCloseRequested returned a non-boolean value; treating it as allow=true.',
851
+ result,
852
+ );
853
+ } else {
854
+ allow = result;
855
+ }
856
+ } catch (error) {
857
+ allow = false;
858
+ console.error('InkView onCloseRequested failed; denying close request.', error);
859
+ }
860
+ }
861
+ if (typeof this.#rawView.resolveCloseRequested === 'function') {
862
+ this.#rawView.resolveCloseRequested(allow);
863
+ }
864
+ if (allow) {
865
+ this.#consumeClosed();
866
+ }
867
+ return false;
868
+ }
869
+
870
+ #consumeClosed() {
871
+ if (this.#destroyed || this.#closeRequested) {
872
+ return this.#closeRequested;
873
+ }
874
+ if (typeof this.#rawView.consumeClosed !== 'function') {
875
+ return false;
876
+ }
877
+ if (!this.#rawView.consumeClosed()) {
878
+ return false;
879
+ }
880
+
881
+ const source =
882
+ typeof this.#rawView.currentClosedSource === 'function'
883
+ ? this.#rawView.currentClosedSource()
884
+ : '';
774
885
  this.#closeRequested = true;
775
886
  this.stopRendering();
776
- if (typeof this.#onCloseRequested === 'function') {
777
- this.#onCloseRequested();
887
+ if (typeof this.#onClosed === 'function') {
888
+ this.#onClosed({ source });
778
889
  }
779
890
  return true;
780
891
  }
@@ -991,7 +1102,8 @@ export class InkView {
991
1102
  initialPage,
992
1103
  serializeQuery(query),
993
1104
  );
994
- if (!this.#consumeCloseRequested()) {
1105
+ this.#consumeCloseRequested();
1106
+ if (!this.#consumeClosed()) {
995
1107
  this.requestRender();
996
1108
  }
997
1109
  return this;
@@ -1004,7 +1116,8 @@ export class InkView {
1004
1116
 
1005
1117
  this.#resetCloseRequestedState();
1006
1118
  this.#rawView.open(path.trim(), initialPage, serializeQuery(query));
1007
- if (!this.#consumeCloseRequested()) {
1119
+ this.#consumeCloseRequested();
1120
+ if (!this.#consumeClosed()) {
1008
1121
  this.requestRender();
1009
1122
  }
1010
1123
  return this;
@@ -1037,35 +1150,53 @@ export class InkView {
1037
1150
  return bundle;
1038
1151
  }
1039
1152
 
1040
- resize(width, height, scaleFactor = getDefaultScaleFactor()) {
1153
+ setViewport(width, height, scaleFactorOrOptions = getDefaultScaleFactor()) {
1154
+ const hasResizeOptions = isResizeOptions(scaleFactorOrOptions);
1155
+ const shouldResetScroll = hasResizeOptions && scaleFactorOrOptions.resetScroll === true;
1156
+ const nextLayoutMode = hasResizeOptions
1157
+ ? scaleFactorOrOptions.layoutMode == null
1158
+ ? this.#layoutMode
1159
+ : normalizeLayoutMode(scaleFactorOrOptions.layoutMode)
1160
+ : this.#layoutMode;
1161
+ const nextScaleFactor = hasResizeOptions
1162
+ ? Object.prototype.hasOwnProperty.call(scaleFactorOrOptions, 'scaleFactor')
1163
+ ? normalizeScaleFactor(scaleFactorOrOptions.scaleFactor)
1164
+ : this.#scaleFactor
1165
+ : normalizeScaleFactor(scaleFactorOrOptions);
1041
1166
  const nextWidth = Math.max(1, Number(width) || 1);
1042
1167
  const fallbackHeight =
1043
- this.#layoutMode === 'width-constrained-auto-height'
1168
+ nextLayoutMode === 'width-constrained-auto-height'
1044
1169
  ? this.#logicalHeight
1045
1170
  : this.#boundedHeight;
1046
1171
  const nextHeight = Math.max(1, Number(height) || fallbackHeight || 1);
1172
+ const layoutModeChanged = nextLayoutMode !== this.#layoutMode;
1173
+
1047
1174
  this.#logicalWidth = nextWidth;
1048
1175
  this.#logicalHeight = nextHeight;
1049
- if (this.#layoutMode === 'bounded') {
1176
+ this.#scaleFactor = nextScaleFactor;
1177
+ if (nextLayoutMode === 'bounded') {
1050
1178
  this.#boundedHeight = nextHeight;
1051
1179
  }
1052
- this.#scaleFactor = normalizeScaleFactor(scaleFactor);
1053
- this.#syncRawViewSize();
1054
- if (this.#surfaceBinding?.type === 'html-canvas') {
1055
- this.#syncHtmlCanvasBindingSize(this.#logicalWidth, this.#logicalHeight, {
1056
- updateStyleWidth: true,
1057
- updateStyleHeight: this.#layoutMode === 'width-constrained-auto-height',
1058
- updateContainerWidth: true,
1059
- updateContainerHeight: this.#layoutMode === 'width-constrained-auto-height',
1060
- });
1061
- } else {
1062
- this.#syncSurfaceBindingSize(this.#logicalWidth, this.#logicalHeight);
1180
+
1181
+ if (layoutModeChanged) {
1182
+ this.#layoutMode = nextLayoutMode;
1183
+ this.#latestContentSize = null;
1184
+ if (typeof this.#rawView.setLayoutMode === 'function') {
1185
+ this.#rawView.setLayoutMode(nextLayoutMode);
1186
+ }
1063
1187
  }
1188
+
1189
+ this.#syncRawViewSize(this.#logicalWidth, this.#logicalHeight, shouldResetScroll);
1190
+ this.#syncSurfaceForCurrentLayoutMode();
1064
1191
  this.#presentSurface();
1065
1192
  this.requestRender();
1066
1193
  return this;
1067
1194
  }
1068
1195
 
1196
+ resize(width, height, scaleFactorOrOptions = getDefaultScaleFactor()) {
1197
+ return this.setViewport(width, height, scaleFactorOrOptions);
1198
+ }
1199
+
1069
1200
  setLayoutMode(layoutMode) {
1070
1201
  const nextLayoutMode = normalizeLayoutMode(layoutMode);
1071
1202
  if (this.#layoutMode === nextLayoutMode) {
@@ -1080,23 +1211,12 @@ export class InkView {
1080
1211
  if (nextLayoutMode === 'bounded') {
1081
1212
  this.#logicalHeight = this.#boundedHeight;
1082
1213
  this.#syncRawViewSize();
1083
- if (this.#surfaceBinding?.type === 'html-canvas') {
1084
- this.#syncHtmlCanvasBindingSize(this.#logicalWidth, this.#logicalHeight);
1085
- } else {
1086
- this.#syncSurfaceBindingSize(this.#logicalWidth, this.#logicalHeight);
1087
- }
1214
+ this.#syncBoundSurfaceSize();
1088
1215
  } else if (currentContentSize) {
1089
1216
  this.#syncHtmlCanvasAutoHeight(currentContentSize);
1090
1217
  } else {
1091
1218
  this.#syncRawViewSize();
1092
- if (this.#surfaceBinding?.type === 'html-canvas') {
1093
- this.#syncHtmlCanvasBindingSize(this.#logicalWidth, this.#logicalHeight, {
1094
- updateStyleWidth: true,
1095
- updateStyleHeight: true,
1096
- updateContainerWidth: true,
1097
- updateContainerHeight: true,
1098
- });
1099
- }
1219
+ this.#syncAutoHeightSurfaceSize();
1100
1220
  }
1101
1221
 
1102
1222
  this.requestRender();
@@ -1176,7 +1296,8 @@ export class InkView {
1176
1296
  const hasMoreWork = Boolean(this.#rawView.render());
1177
1297
  const contentSizeChanged = this.#consumeContentSizeChanged();
1178
1298
  this.#presentSurface();
1179
- const closeRequested = this.#consumeCloseRequested();
1299
+ this.#consumeCloseRequested();
1300
+ const closeRequested = this.#consumeClosed();
1180
1301
  if (!closeRequested && (hasMoreWork || contentSizeChanged || this.#autoRender)) {
1181
1302
  this.requestRender();
1182
1303
  }
@@ -1247,6 +1368,25 @@ export class InkView {
1247
1368
  this.#onCloseRequested = callback || null;
1248
1369
  }
1249
1370
 
1371
+ setOnClosed(callback) {
1372
+ if (callback != null && typeof callback !== 'function') {
1373
+ throw new TypeError('`callback` must be a function or null.');
1374
+ }
1375
+ this.onClosed = callback || null;
1376
+ return this;
1377
+ }
1378
+
1379
+ get onClosed() {
1380
+ return this.#onClosed;
1381
+ }
1382
+
1383
+ set onClosed(callback) {
1384
+ if (callback != null && typeof callback !== 'function') {
1385
+ throw new TypeError('`callback` must be a function or null.');
1386
+ }
1387
+ this.#onClosed = callback || null;
1388
+ }
1389
+
1250
1390
  setOnContentSizeChanged(callback) {
1251
1391
  if (callback != null && typeof callback !== 'function') {
1252
1392
  throw new TypeError('`callback` must be a function or null.');
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "access": "public",
11
11
  "registry": "https://registry.npmjs.com/"
12
12
  },
13
- "version": "0.9.1",
13
+ "version": "0.10.0",
14
14
  "type": "module",
15
15
  "main": "index.js",
16
16
  "types": "index.d.ts",
package/pkg/ink_web.d.ts CHANGED
@@ -16,8 +16,11 @@ export class InkWebView {
16
16
  blur(): void;
17
17
  clearSurface(): void;
18
18
  consumeCloseRequested(): boolean;
19
+ consumeClosed(): boolean;
19
20
  consumeContentSizeChanged(): boolean;
20
21
  createMessageStream(origin: string, last_event_id: string): InkWebMessageStream;
22
+ currentCloseRequestSource(): string;
23
+ currentClosedSource(): string;
21
24
  currentContentHeight(): number;
22
25
  currentContentWidth(): number;
23
26
  destroy(): void;
@@ -27,15 +30,16 @@ export class InkWebView {
27
30
  focus(): void;
28
31
  isInteractive(): boolean;
29
32
  isRunning(): boolean;
30
- constructor(width: number, height: number, scale_factor: number, layout_mode: string);
33
+ constructor(width: number, height: number, scale_factor: number, app_fps: number, layout_mode: string, theme_name?: string | null);
31
34
  notifyUserInteraction(): void;
32
35
  open(path: string, initial_page?: string | null, query_json?: string | null): void;
33
36
  openBundle(app_id: string, files: Map<any, any>, initial_page?: string | null, query_json?: string | null): void;
34
37
  render(): boolean;
35
- resize(width: number, height: number, scale_factor: number): void;
38
+ resolveCloseRequested(allow: boolean): void;
36
39
  setInteractive(interactive: boolean): void;
37
40
  setLanguageModelConfig(config_json?: string | null): void;
38
41
  setLayoutMode(layout_mode: string): void;
42
+ setViewport(width: number, height: number, scale_factor: number, reset_scroll?: boolean | null): void;
39
43
  }
40
44
 
41
45
  export function get_version(): string;
@@ -55,8 +59,11 @@ export interface InitOutput {
55
59
  readonly inkwebview_blur: (a: number) => void;
56
60
  readonly inkwebview_clearSurface: (a: number) => void;
57
61
  readonly inkwebview_consumeCloseRequested: (a: number) => number;
62
+ readonly inkwebview_consumeClosed: (a: number) => number;
58
63
  readonly inkwebview_consumeContentSizeChanged: (a: number) => number;
59
64
  readonly inkwebview_createMessageStream: (a: number, b: number, c: number, d: number, e: number) => number;
65
+ readonly inkwebview_currentCloseRequestSource: (a: number, b: number) => void;
66
+ readonly inkwebview_currentClosedSource: (a: number, b: number) => void;
60
67
  readonly inkwebview_currentContentHeight: (a: number) => number;
61
68
  readonly inkwebview_currentContentWidth: (a: number) => number;
62
69
  readonly inkwebview_destroy: (a: number) => void;
@@ -66,21 +73,22 @@ export interface InitOutput {
66
73
  readonly inkwebview_focus: (a: number) => void;
67
74
  readonly inkwebview_isInteractive: (a: number) => number;
68
75
  readonly inkwebview_isRunning: (a: number) => number;
69
- readonly inkwebview_new: (a: number, b: number, c: number, d: number, e: number) => number;
76
+ readonly inkwebview_new: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => number;
70
77
  readonly inkwebview_notifyUserInteraction: (a: number) => void;
71
78
  readonly inkwebview_open: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
72
79
  readonly inkwebview_openBundle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
73
80
  readonly inkwebview_render: (a: number, b: number) => void;
74
- readonly inkwebview_resize: (a: number, b: number, c: number, d: number) => void;
81
+ readonly inkwebview_resolveCloseRequested: (a: number, b: number) => void;
75
82
  readonly inkwebview_setInteractive: (a: number, b: number) => void;
76
83
  readonly inkwebview_setLanguageModelConfig: (a: number, b: number, c: number, d: number) => void;
77
84
  readonly inkwebview_setLayoutMode: (a: number, b: number, c: number) => void;
85
+ readonly inkwebview_setViewport: (a: number, b: number, c: number, d: number, e: number) => void;
78
86
  readonly main: () => void;
79
- readonly __wasm_bindgen_func_elem_9470: (a: number, b: number) => void;
80
- readonly __wasm_bindgen_func_elem_13736: (a: number, b: number) => void;
81
- readonly __wasm_bindgen_func_elem_9754: (a: number, b: number, c: number) => void;
82
- readonly __wasm_bindgen_func_elem_13737: (a: number, b: number, c: number) => void;
83
- readonly __wasm_bindgen_func_elem_9755: (a: number, b: number) => void;
87
+ readonly __wasm_bindgen_func_elem_9822: (a: number, b: number) => void;
88
+ readonly __wasm_bindgen_func_elem_14048: (a: number, b: number) => void;
89
+ readonly __wasm_bindgen_func_elem_9965: (a: number, b: number, c: number) => void;
90
+ readonly __wasm_bindgen_func_elem_14049: (a: number, b: number, c: number) => void;
91
+ readonly __wasm_bindgen_func_elem_9963: (a: number, b: number) => void;
84
92
  readonly __wbindgen_export: (a: number, b: number) => number;
85
93
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
86
94
  readonly __wbindgen_export3: (a: number) => void;
package/pkg/ink_web.js CHANGED
@@ -82,6 +82,13 @@ export class InkWebView {
82
82
  const ret = wasm.inkwebview_consumeCloseRequested(this.__wbg_ptr);
83
83
  return ret !== 0;
84
84
  }
85
+ /**
86
+ * @returns {boolean}
87
+ */
88
+ consumeClosed() {
89
+ const ret = wasm.inkwebview_consumeClosed(this.__wbg_ptr);
90
+ return ret !== 0;
91
+ }
85
92
  /**
86
93
  * @returns {boolean}
87
94
  */
@@ -102,6 +109,44 @@ export class InkWebView {
102
109
  const ret = wasm.inkwebview_createMessageStream(this.__wbg_ptr, ptr0, len0, ptr1, len1);
103
110
  return InkWebMessageStream.__wrap(ret);
104
111
  }
112
+ /**
113
+ * @returns {string}
114
+ */
115
+ currentCloseRequestSource() {
116
+ let deferred1_0;
117
+ let deferred1_1;
118
+ try {
119
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
120
+ wasm.inkwebview_currentCloseRequestSource(retptr, this.__wbg_ptr);
121
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
122
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
123
+ deferred1_0 = r0;
124
+ deferred1_1 = r1;
125
+ return getStringFromWasm0(r0, r1);
126
+ } finally {
127
+ wasm.__wbindgen_add_to_stack_pointer(16);
128
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
129
+ }
130
+ }
131
+ /**
132
+ * @returns {string}
133
+ */
134
+ currentClosedSource() {
135
+ let deferred1_0;
136
+ let deferred1_1;
137
+ try {
138
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
139
+ wasm.inkwebview_currentClosedSource(retptr, this.__wbg_ptr);
140
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
141
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
142
+ deferred1_0 = r0;
143
+ deferred1_1 = r1;
144
+ return getStringFromWasm0(r0, r1);
145
+ } finally {
146
+ wasm.__wbindgen_add_to_stack_pointer(16);
147
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
148
+ }
149
+ }
105
150
  /**
106
151
  * @returns {number}
107
152
  */
@@ -210,12 +255,16 @@ export class InkWebView {
210
255
  * @param {number} width
211
256
  * @param {number} height
212
257
  * @param {number} scale_factor
258
+ * @param {number} app_fps
213
259
  * @param {string} layout_mode
260
+ * @param {string | null} [theme_name]
214
261
  */
215
- constructor(width, height, scale_factor, layout_mode) {
262
+ constructor(width, height, scale_factor, app_fps, layout_mode, theme_name) {
216
263
  const ptr0 = passStringToWasm0(layout_mode, wasm.__wbindgen_export, wasm.__wbindgen_export2);
217
264
  const len0 = WASM_VECTOR_LEN;
218
- const ret = wasm.inkwebview_new(width, height, scale_factor, ptr0, len0);
265
+ var ptr1 = isLikeNone(theme_name) ? 0 : passStringToWasm0(theme_name, wasm.__wbindgen_export, wasm.__wbindgen_export2);
266
+ var len1 = WASM_VECTOR_LEN;
267
+ const ret = wasm.inkwebview_new(width, height, scale_factor, app_fps, ptr0, len0, ptr1, len1);
219
268
  this.__wbg_ptr = ret >>> 0;
220
269
  InkWebViewFinalization.register(this, this.__wbg_ptr, this);
221
270
  return this;
@@ -291,12 +340,10 @@ export class InkWebView {
291
340
  }
292
341
  }
293
342
  /**
294
- * @param {number} width
295
- * @param {number} height
296
- * @param {number} scale_factor
343
+ * @param {boolean} allow
297
344
  */
298
- resize(width, height, scale_factor) {
299
- wasm.inkwebview_resize(this.__wbg_ptr, width, height, scale_factor);
345
+ resolveCloseRequested(allow) {
346
+ wasm.inkwebview_resolveCloseRequested(this.__wbg_ptr, allow);
300
347
  }
301
348
  /**
302
349
  * @param {boolean} interactive
@@ -330,6 +377,15 @@ export class InkWebView {
330
377
  const len0 = WASM_VECTOR_LEN;
331
378
  wasm.inkwebview_setLayoutMode(this.__wbg_ptr, ptr0, len0);
332
379
  }
380
+ /**
381
+ * @param {number} width
382
+ * @param {number} height
383
+ * @param {number} scale_factor
384
+ * @param {boolean | null} [reset_scroll]
385
+ */
386
+ setViewport(width, height, scale_factor, reset_scroll) {
387
+ wasm.inkwebview_setViewport(this.__wbg_ptr, width, height, scale_factor, isLikeNone(reset_scroll) ? 0xFFFFFF : reset_scroll ? 1 : 0);
388
+ }
333
389
  }
334
390
  if (Symbol.dispose) InkWebView.prototype[Symbol.dispose] = InkWebView.prototype.free;
335
391
 
@@ -492,6 +548,10 @@ function __wbg_get_imports() {
492
548
  const ret = getObject(arg0).call(getObject(arg1));
493
549
  return addHeapObject(ret);
494
550
  }, arguments); },
551
+ __wbg_call_4708e0c13bdc8e95: function() { return handleError(function (arg0, arg1, arg2) {
552
+ const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
553
+ return addHeapObject(ret);
554
+ }, arguments); },
495
555
  __wbg_call_e8c868596c950cf6: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
496
556
  const ret = getObject(arg0).call(getObject(arg1), getObject(arg2), getObject(arg3), getObject(arg4));
497
557
  return addHeapObject(ret);
@@ -696,6 +756,16 @@ function __wbg_get_imports() {
696
756
  const ret = result;
697
757
  return ret;
698
758
  },
759
+ __wbg_instanceof_Object_1c6af87502b733ed: function(arg0) {
760
+ let result;
761
+ try {
762
+ result = getObject(arg0) instanceof Object;
763
+ } catch (_) {
764
+ result = false;
765
+ }
766
+ const ret = result;
767
+ return ret;
768
+ },
699
769
  __wbg_instanceof_Promise_0094681e3519d6ec: function(arg0) {
700
770
  let result;
701
771
  try {
@@ -1147,28 +1217,28 @@ function __wbg_get_imports() {
1147
1217
  return ret;
1148
1218
  },
1149
1219
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
1150
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2522, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 2526, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1151
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9470, __wasm_bindgen_func_elem_9754);
1220
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 2621, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1221
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9965);
1152
1222
  return addHeapObject(ret);
1153
1223
  },
1154
1224
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
1155
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2522, function: Function { arguments: [NamedExternref("Event")], shim_idx: 2526, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1156
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9470, __wasm_bindgen_func_elem_9754);
1225
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [NamedExternref("Event")], shim_idx: 2621, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1226
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9965);
1157
1227
  return addHeapObject(ret);
1158
1228
  },
1159
1229
  __wbindgen_cast_0000000000000003: function(arg0, arg1) {
1160
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2522, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 2526, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1161
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9470, __wasm_bindgen_func_elem_9754);
1230
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 2621, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1231
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9965);
1162
1232
  return addHeapObject(ret);
1163
1233
  },
1164
1234
  __wbindgen_cast_0000000000000004: function(arg0, arg1) {
1165
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2522, function: Function { arguments: [], shim_idx: 2523, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1166
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9470, __wasm_bindgen_func_elem_9755);
1235
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2633, function: Function { arguments: [], shim_idx: 2634, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1236
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_9822, __wasm_bindgen_func_elem_9963);
1167
1237
  return addHeapObject(ret);
1168
1238
  },
1169
1239
  __wbindgen_cast_0000000000000005: function(arg0, arg1) {
1170
- // Cast intrinsic for `Closure(Closure { dtor_idx: 3491, function: Function { arguments: [Externref], shim_idx: 3492, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1171
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_13736, __wasm_bindgen_func_elem_13737);
1240
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 3529, function: Function { arguments: [Externref], shim_idx: 3530, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1241
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_14048, __wasm_bindgen_func_elem_14049);
1172
1242
  return addHeapObject(ret);
1173
1243
  },
1174
1244
  __wbindgen_cast_0000000000000006: function(arg0) {
@@ -1225,16 +1295,16 @@ function __wbg_get_imports() {
1225
1295
  };
1226
1296
  }
1227
1297
 
1228
- function __wasm_bindgen_func_elem_9755(arg0, arg1) {
1229
- wasm.__wasm_bindgen_func_elem_9755(arg0, arg1);
1298
+ function __wasm_bindgen_func_elem_9963(arg0, arg1) {
1299
+ wasm.__wasm_bindgen_func_elem_9963(arg0, arg1);
1230
1300
  }
1231
1301
 
1232
- function __wasm_bindgen_func_elem_9754(arg0, arg1, arg2) {
1233
- wasm.__wasm_bindgen_func_elem_9754(arg0, arg1, addHeapObject(arg2));
1302
+ function __wasm_bindgen_func_elem_9965(arg0, arg1, arg2) {
1303
+ wasm.__wasm_bindgen_func_elem_9965(arg0, arg1, addHeapObject(arg2));
1234
1304
  }
1235
1305
 
1236
- function __wasm_bindgen_func_elem_13737(arg0, arg1, arg2) {
1237
- wasm.__wasm_bindgen_func_elem_13737(arg0, arg1, addHeapObject(arg2));
1306
+ function __wasm_bindgen_func_elem_14049(arg0, arg1, arg2) {
1307
+ wasm.__wasm_bindgen_func_elem_14049(arg0, arg1, addHeapObject(arg2));
1238
1308
  }
1239
1309
 
1240
1310
 
Binary file
@@ -10,8 +10,11 @@ export const inkwebview_bindCanvas: (a: number, b: number, c: number) => void;
10
10
  export const inkwebview_blur: (a: number) => void;
11
11
  export const inkwebview_clearSurface: (a: number) => void;
12
12
  export const inkwebview_consumeCloseRequested: (a: number) => number;
13
+ export const inkwebview_consumeClosed: (a: number) => number;
13
14
  export const inkwebview_consumeContentSizeChanged: (a: number) => number;
14
15
  export const inkwebview_createMessageStream: (a: number, b: number, c: number, d: number, e: number) => number;
16
+ export const inkwebview_currentCloseRequestSource: (a: number, b: number) => void;
17
+ export const inkwebview_currentClosedSource: (a: number, b: number) => void;
15
18
  export const inkwebview_currentContentHeight: (a: number) => number;
16
19
  export const inkwebview_currentContentWidth: (a: number) => number;
17
20
  export const inkwebview_destroy: (a: number) => void;
@@ -21,21 +24,22 @@ export const inkwebview_dispatchPointer: (a: number, b: number, c: number, d: nu
21
24
  export const inkwebview_focus: (a: number) => void;
22
25
  export const inkwebview_isInteractive: (a: number) => number;
23
26
  export const inkwebview_isRunning: (a: number) => number;
24
- export const inkwebview_new: (a: number, b: number, c: number, d: number, e: number) => number;
27
+ export const inkwebview_new: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => number;
25
28
  export const inkwebview_notifyUserInteraction: (a: number) => void;
26
29
  export const inkwebview_open: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
27
30
  export const inkwebview_openBundle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
28
31
  export const inkwebview_render: (a: number, b: number) => void;
29
- export const inkwebview_resize: (a: number, b: number, c: number, d: number) => void;
32
+ export const inkwebview_resolveCloseRequested: (a: number, b: number) => void;
30
33
  export const inkwebview_setInteractive: (a: number, b: number) => void;
31
34
  export const inkwebview_setLanguageModelConfig: (a: number, b: number, c: number, d: number) => void;
32
35
  export const inkwebview_setLayoutMode: (a: number, b: number, c: number) => void;
36
+ export const inkwebview_setViewport: (a: number, b: number, c: number, d: number, e: number) => void;
33
37
  export const main: () => void;
34
- export const __wasm_bindgen_func_elem_9470: (a: number, b: number) => void;
35
- export const __wasm_bindgen_func_elem_13736: (a: number, b: number) => void;
36
- export const __wasm_bindgen_func_elem_9754: (a: number, b: number, c: number) => void;
37
- export const __wasm_bindgen_func_elem_13737: (a: number, b: number, c: number) => void;
38
- export const __wasm_bindgen_func_elem_9755: (a: number, b: number) => void;
38
+ export const __wasm_bindgen_func_elem_9822: (a: number, b: number) => void;
39
+ export const __wasm_bindgen_func_elem_14048: (a: number, b: number) => void;
40
+ export const __wasm_bindgen_func_elem_9965: (a: number, b: number, c: number) => void;
41
+ export const __wasm_bindgen_func_elem_14049: (a: number, b: number, c: number) => void;
42
+ export const __wasm_bindgen_func_elem_9963: (a: number, b: number) => void;
39
43
  export const __wbindgen_export: (a: number, b: number) => number;
40
44
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
41
45
  export const __wbindgen_export3: (a: number) => void;