@bloopjs/bloop 0.0.89 → 0.0.90

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.
@@ -0,0 +1,26 @@
1
+ import type { InputContext, PlayerInputContext, NetContext } from "@bloopjs/engine";
2
+ /**
3
+ * Collection of player input contexts with ergonomic access.
4
+ *
5
+ * - `.get(i)` returns PlayerInputContext without undefined (throws for out-of-bounds 0-11)
6
+ * - Iteration yields only connected players
7
+ * - `.count` returns number of connected players
8
+ */
9
+ export declare class Players implements Iterable<PlayerInputContext> {
10
+ #private;
11
+ constructor(inputs: InputContext, net: NetContext);
12
+ /**
13
+ * Get player input context by index.
14
+ * @param index Player index (0-11)
15
+ * @returns PlayerInputContext for that slot
16
+ * @throws RangeError if index out of bounds
17
+ */
18
+ get(index: number): PlayerInputContext;
19
+ /** Number of connected players (1 in local mode, peerCount in multiplayer) */
20
+ get count(): number;
21
+ /** Iterate over connected players only */
22
+ [Symbol.iterator](): IterableIterator<PlayerInputContext>;
23
+ /** Iterate over connected players with their indices */
24
+ entries(): IterableIterator<[number, PlayerInputContext]>;
25
+ }
26
+ //# sourceMappingURL=players.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"players.d.ts","sourceRoot":"","sources":["../src/players.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACX,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AACH,qBAAa,OAAQ,YAAW,QAAQ,CAAC,kBAAkB,CAAC;;gBAI9C,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU;IAKjD;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB;IAUtC,8EAA8E;IAC9E,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,0CAA0C;IACzC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,kBAAkB,CAAC;IAQ1D,wDAAwD;IACvD,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAO3D"}
package/dist/sim.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type EnginePointer, type Key, type MouseButton, NetContext, type NetEvent, type NetEventType, TimeContext, type WasmEngine } from "@bloopjs/engine";
1
+ import { type EnginePointer, type Key, type MouseButton, NetContext, type NetEvent, type NetEventType, ScreenContext, TimeContext, type WasmEngine } from "@bloopjs/engine";
2
2
  export type LoadTapeOptions = {
3
3
  /** Frames between checkpoints for seek optimization (0 = disabled). Default: 0 */
4
4
  checkpointInterval?: number;
@@ -139,6 +139,7 @@ export declare class Sim {
139
139
  unmount(): void;
140
140
  get time(): TimeContext;
141
141
  get net(): NetContext;
142
+ get screen(): ScreenContext;
142
143
  get buffer(): ArrayBuffer;
143
144
  get isRecording(): boolean;
144
145
  get isReplaying(): boolean;
@@ -150,6 +151,15 @@ export declare class Sim {
150
151
  mousedown: (button: MouseButton, peerId?: number) => void;
151
152
  mouseup: (button: MouseButton, peerId?: number) => void;
152
153
  mousewheel: (x: number, y: number, peerId?: number) => void;
154
+ /**
155
+ * Emit a resize event. Updates screen context and fires resize callback in systems.
156
+ * @param width Logical width in CSS pixels
157
+ * @param height Logical height in CSS pixels
158
+ * @param physicalWidth Physical width in device pixels
159
+ * @param physicalHeight Physical height in device pixels
160
+ * @param pixelRatio Device pixel ratio
161
+ */
162
+ resize: (width: number, height: number, physicalWidth: number, physicalHeight: number, pixelRatio: number) => void;
153
163
  /**
154
164
  * Emit a network event (join:ok, peer:join, etc.)
155
165
  * Events are queued in the engine and processed during the next tick's systemsCallback.
package/dist/sim.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sim.d.ts","sourceRoot":"","sources":["../src/sim.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sim.d.ts","sourceRoot":"","sources":["../src/sim.ts"],"names":[],"mappings":"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"}
package/dist/system.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { NetEvent } from "@bloopjs/engine";
2
2
  import type { Context } from "./context";
3
3
  import type { BloopSchema } from "./data/schema";
4
- import type { KeyEvent, MouseButtonEvent, MouseMoveEvent, MouseWheelEvent } from "./events";
4
+ import type { KeyEvent, MouseButtonEvent, MouseMoveEvent, MouseWheelEvent, ResizeEvent } from "./events";
5
5
  export type System<GS extends BloopSchema = BloopSchema> = {
6
6
  label?: string;
7
7
  update?: (context: Context<GS>) => void;
@@ -27,5 +27,9 @@ export type System<GS extends BloopSchema = BloopSchema> = {
27
27
  netcode?: (context: Context<GS> & {
28
28
  event: NetEvent;
29
29
  }) => void;
30
+ /** Handle screen/viewport resize events */
31
+ resize?: (context: Context<GS> & {
32
+ event: ResizeEvent;
33
+ }) => void;
30
34
  };
31
35
  //# sourceMappingURL=system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,EAChB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,MAAM,CAAC,EAAE,SAAS,WAAW,GAAG,WAAW,IAAI;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAExC,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,KAAK,CAAC,EAAE,CACN,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,gBAAgB,CAAC;KACzB,KACE,IAAI,CAAC;IAEV,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,gBAAgB,CAAC;KACzB,KACE,IAAI,CAAC;IAEV,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,cAAc,CAAC;KACvB,KACE,IAAI,CAAC;IAEV,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,eAAe,CAAC;KACxB,KACE,IAAI,CAAC;IAEV,uDAAuD;IACvD,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;CACX,CAAC"}
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,MAAM,CAAC,EAAE,SAAS,WAAW,GAAG,WAAW,IAAI;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAExC,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,KAAK,CAAC,EAAE,CACN,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,gBAAgB,CAAC;KACzB,KACE,IAAI,CAAC;IAEV,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,gBAAgB,CAAC;KACzB,KACE,IAAI,CAAC;IAEV,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,cAAc,CAAC;KACvB,KACE,IAAI,CAAC;IAEV,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,eAAe,CAAC;KACxB,KACE,IAAI,CAAC;IAEV,uDAAuD;IACvD,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,WAAW,CAAC;KACpB,KACE,IAAI,CAAC;CACX,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloopjs/bloop",
3
- "version": "0.0.89",
3
+ "version": "0.0.90",
4
4
  "author": "Neil Sarkar",
5
5
  "type": "module",
6
6
  "repository": {
@@ -35,7 +35,7 @@
35
35
  "@types/bun": "latest"
36
36
  },
37
37
  "dependencies": {
38
- "@bloopjs/engine": "0.0.89"
38
+ "@bloopjs/engine": "0.0.90"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "typescript": "^5"
package/src/bloop.ts CHANGED
@@ -9,18 +9,22 @@ import {
9
9
  NET_CTX_OFFSET,
10
10
  NetContext,
11
11
  type NetEvent,
12
+ SCREEN_CTX_OFFSET,
13
+ ScreenContext,
12
14
  TIME_CTX_OFFSET,
13
15
  TimeContext,
14
16
  } from "@bloopjs/engine";
17
+ import { Players } from "./players";
15
18
  import type { Context } from "./context";
16
19
  import type { Bag } from "./data/bag";
17
20
  import type { BloopSchema } from "./data/schema";
18
21
  import type {
19
- InputEvent,
22
+ BloopEvent,
20
23
  KeyEvent,
21
24
  MouseButtonEvent,
22
25
  MouseMoveEvent,
23
26
  MouseWheelEvent,
27
+ ResizeEvent,
24
28
  } from "./events";
25
29
  import type { EngineHooks } from "./sim";
26
30
  import type { System } from "./system";
@@ -75,15 +79,16 @@ export class Bloop<GS extends BloopSchema> {
75
79
  }
76
80
 
77
81
  const inputs = new InputContext();
82
+ const net = new NetContext();
83
+ const screen = new ScreenContext();
78
84
  this.#context = {
79
85
  bag: opts.bag ?? {},
80
86
  time: new TimeContext(),
81
87
  inputs,
82
- get players() {
83
- return inputs.players;
84
- },
88
+ players: new Players(inputs, net),
85
89
  rawPointer: -1,
86
- net: new NetContext(),
90
+ net,
91
+ screen,
87
92
  };
88
93
  }
89
94
 
@@ -160,6 +165,7 @@ export class Bloop<GS extends BloopSchema> {
160
165
  const timeCtxPtr = dv.getUint32(TIME_CTX_OFFSET, true);
161
166
  const inputCtxPtr = dv.getUint32(INPUT_CTX_OFFSET, true);
162
167
  const netCtxPtr = dv.getUint32(NET_CTX_OFFSET, true);
168
+ const screenCtxPtr = dv.getUint32(SCREEN_CTX_OFFSET, true);
163
169
 
164
170
  this.#context.rawPointer = ptr;
165
171
 
@@ -193,6 +199,16 @@ export class Bloop<GS extends BloopSchema> {
193
199
  netCtxPtr,
194
200
  );
195
201
  }
202
+
203
+ if (
204
+ this.#context.screen.dataView?.buffer !== this.#engineBuffer ||
205
+ this.#context.screen.dataView?.byteOffset !== screenCtxPtr
206
+ ) {
207
+ this.#context.screen.dataView = new DataView(
208
+ this.#engineBuffer,
209
+ screenCtxPtr,
210
+ );
211
+ }
196
212
  },
197
213
 
198
214
  systemsCallback: (system_handle: number, ptr: EnginePointer) => {
@@ -342,6 +358,18 @@ export class Bloop<GS extends BloopSchema> {
342
358
  this.#context as Context<GS> & { event: NetEvent },
343
359
  );
344
360
  break;
361
+ case Enums.EventType.Resize:
362
+ // Resize event - values are read from screen context (already updated by engine)
363
+ system.resize?.(
364
+ attachEvent<ResizeEvent, GS>(this.#context, {
365
+ width: this.#context.screen.width,
366
+ height: this.#context.screen.height,
367
+ physicalWidth: this.#context.screen.physicalWidth,
368
+ physicalHeight: this.#context.screen.physicalHeight,
369
+ pixelRatio: this.#context.screen.pixelRatio,
370
+ }),
371
+ );
372
+ break;
345
373
  default:
346
374
  // Session lifecycle and other internal events are handled by engine
347
375
  // They don't need to be dispatched to game systems
@@ -356,12 +384,12 @@ export class Bloop<GS extends BloopSchema> {
356
384
  };
357
385
  }
358
386
 
359
- function attachEvent<IE extends InputEvent, GS extends BloopSchema>(
387
+ function attachEvent<E extends BloopEvent, GS extends BloopSchema>(
360
388
  context: Context<GS>,
361
- event: IE,
362
- ): Context<GS> & { event: IE } {
389
+ event: E,
390
+ ): Context<GS> & { event: E } {
363
391
  (context as any).event = event;
364
- return context as Context<GS> & { event: IE };
392
+ return context as Context<GS> & { event: E };
365
393
  }
366
394
 
367
395
  type MakeGS<B extends Bag> = BloopSchema<B>;
package/src/context.ts CHANGED
@@ -2,10 +2,11 @@ import type {
2
2
  EnginePointer,
3
3
  InputContext,
4
4
  NetContext,
5
- PlayerInputContext,
5
+ ScreenContext,
6
6
  TimeContext,
7
7
  } from "@bloopjs/engine";
8
8
  import type { BloopSchema } from "./data/schema";
9
+ import type { Players } from "./players";
9
10
 
10
11
  export type Context<
11
12
  GS extends BloopSchema = BloopSchema,
@@ -27,12 +28,15 @@ export type Context<
27
28
  /** The input snapshot */
28
29
  inputs: InputContext;
29
30
  /**
30
- * Per-player input states. Shorthand for inputs.players.
31
- * Access via: context.players[0].keys.a.held
31
+ * Per-player input states.
32
+ * Access via: context.players.get(0).keys.a.held
33
+ * Iterate connected players: for (const p of context.players) { ... }
32
34
  */
33
- players: readonly PlayerInputContext[];
35
+ players: Players;
34
36
  /** The engine pointer to the injected system arguments (for advanced use cases) */
35
37
  rawPointer: EnginePointer;
36
38
  /** Network context for multiplayer sessions */
37
39
  net: NetContext;
40
+ /** Screen/viewport dimensions and pixel ratio */
41
+ screen: ScreenContext;
38
42
  };
package/src/events.ts CHANGED
@@ -23,3 +23,13 @@ export type MouseWheelEvent = {
23
23
  x: number;
24
24
  y: number;
25
25
  };
26
+
27
+ export type ResizeEvent = {
28
+ width: number;
29
+ height: number;
30
+ physicalWidth: number;
31
+ physicalHeight: number;
32
+ pixelRatio: number;
33
+ };
34
+
35
+ export type BloopEvent = InputEvent | ResizeEvent;
package/src/mod.ts CHANGED
@@ -6,3 +6,4 @@ export { unwrap, assert } from "./util";
6
6
  export { mount, type Mountable, type MountOptions } from "./mount";
7
7
  export { Bloop } from "./bloop";
8
8
  export { Sim, type LoadTapeOptions } from "./sim";
9
+ export { Players } from "./players";
package/src/players.ts ADDED
@@ -0,0 +1,61 @@
1
+ import type {
2
+ InputContext,
3
+ PlayerInputContext,
4
+ NetContext,
5
+ } from "@bloopjs/engine";
6
+
7
+ /**
8
+ * Collection of player input contexts with ergonomic access.
9
+ *
10
+ * - `.get(i)` returns PlayerInputContext without undefined (throws for out-of-bounds 0-11)
11
+ * - Iteration yields only connected players
12
+ * - `.count` returns number of connected players
13
+ */
14
+ export class Players implements Iterable<PlayerInputContext> {
15
+ readonly #inputs: InputContext;
16
+ readonly #net: NetContext;
17
+
18
+ constructor(inputs: InputContext, net: NetContext) {
19
+ this.#inputs = inputs;
20
+ this.#net = net;
21
+ }
22
+
23
+ /**
24
+ * Get player input context by index.
25
+ * @param index Player index (0-11)
26
+ * @returns PlayerInputContext for that slot
27
+ * @throws RangeError if index out of bounds
28
+ */
29
+ get(index: number): PlayerInputContext {
30
+ const players = this.#inputs.players;
31
+ if (index < 0 || index >= players.length) {
32
+ throw new RangeError(
33
+ `Player index ${index} out of bounds (0-${players.length - 1})`,
34
+ );
35
+ }
36
+ return players[index]!;
37
+ }
38
+
39
+ /** Number of connected players (1 in local mode, peerCount in multiplayer) */
40
+ get count(): number {
41
+ return this.#net.isInSession ? this.#net.peerCount : 1;
42
+ }
43
+
44
+ /** Iterate over connected players only */
45
+ *[Symbol.iterator](): IterableIterator<PlayerInputContext> {
46
+ const players = this.#inputs.players;
47
+ const count = this.count;
48
+ for (let i = 0; i < count; i++) {
49
+ yield players[i]!;
50
+ }
51
+ }
52
+
53
+ /** Iterate over connected players with their indices */
54
+ *entries(): IterableIterator<[number, PlayerInputContext]> {
55
+ const players = this.#inputs.players;
56
+ const count = this.count;
57
+ for (let i = 0; i < count; i++) {
58
+ yield [i, players[i]!];
59
+ }
60
+ }
61
+ }
package/src/sim.ts CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  NetContext,
8
8
  type NetEvent,
9
9
  type NetEventType,
10
+ ScreenContext,
10
11
  SNAPSHOT_HEADER_ENGINE_LEN_OFFSET,
11
12
  SNAPSHOT_HEADER_USER_LEN_OFFSET,
12
13
  TimeContext,
@@ -104,6 +105,11 @@ export class Sim {
104
105
  */
105
106
  #net: NetContext;
106
107
 
108
+ /**
109
+ * Screen context - reads viewport dimensions from WASM memory.
110
+ */
111
+ #screen: ScreenContext;
112
+
107
113
  /**
108
114
  * Callback fired when tape buffer fills up and recording stops.
109
115
  * The tape data is passed so you can save it before clearing.
@@ -125,6 +131,7 @@ export class Sim {
125
131
 
126
132
  this.#serialize = opts?.serialize;
127
133
  this.#net = new NetContext();
134
+ this.#screen = new ScreenContext();
128
135
  }
129
136
 
130
137
  /**
@@ -379,6 +386,20 @@ export class Sim {
379
386
  return this.#net;
380
387
  }
381
388
 
389
+ get screen(): ScreenContext {
390
+ if (
391
+ !this.#screen.dataView ||
392
+ this.#screen.dataView.buffer !== this.#memory.buffer
393
+ ) {
394
+ // update the data view to the latest memory buffer
395
+ this.#screen.dataView = new DataView(
396
+ this.#memory.buffer,
397
+ this.wasm.get_screen_ctx(),
398
+ );
399
+ }
400
+ return this.#screen;
401
+ }
402
+
382
403
  get buffer(): ArrayBuffer {
383
404
  return this.#memory.buffer;
384
405
  }
@@ -414,6 +435,23 @@ export class Sim {
414
435
  mousewheel: (x: number, y: number, peerId: number = 0): void => {
415
436
  this.wasm.emit_mousewheel(x, y, peerId);
416
437
  },
438
+ /**
439
+ * Emit a resize event. Updates screen context and fires resize callback in systems.
440
+ * @param width Logical width in CSS pixels
441
+ * @param height Logical height in CSS pixels
442
+ * @param physicalWidth Physical width in device pixels
443
+ * @param physicalHeight Physical height in device pixels
444
+ * @param pixelRatio Device pixel ratio
445
+ */
446
+ resize: (
447
+ width: number,
448
+ height: number,
449
+ physicalWidth: number,
450
+ physicalHeight: number,
451
+ pixelRatio: number,
452
+ ): void => {
453
+ this.wasm.emit_resize(width, height, physicalWidth, physicalHeight, pixelRatio);
454
+ },
417
455
  /**
418
456
  * Emit a network event (join:ok, peer:join, etc.)
419
457
  * Events are queued in the engine and processed during the next tick's systemsCallback.
package/src/system.ts CHANGED
@@ -6,6 +6,7 @@ import type {
6
6
  MouseButtonEvent,
7
7
  MouseMoveEvent,
8
8
  MouseWheelEvent,
9
+ ResizeEvent,
9
10
  } from "./events";
10
11
 
11
12
  export type System<GS extends BloopSchema = BloopSchema> = {
@@ -55,4 +56,11 @@ export type System<GS extends BloopSchema = BloopSchema> = {
55
56
  event: NetEvent;
56
57
  },
57
58
  ) => void;
59
+
60
+ /** Handle screen/viewport resize events */
61
+ resize?: (
62
+ context: Context<GS> & {
63
+ event: ResizeEvent;
64
+ },
65
+ ) => void;
58
66
  };