@caperjs/core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/lib/{CaptionsPlugin-Dc8fIrjy.js → CaptionsPlugin-DKhbmJvH.js} +15 -15
  2. package/lib/{CaptionsPlugin-Dc8fIrjy.js.map → CaptionsPlugin-DKhbmJvH.js.map} +1 -1
  3. package/lib/{DataAdapter-BY2114sp.js → DataAdapter-BZFTkFQ4.js} +4 -4
  4. package/lib/{DataAdapter-BY2114sp.js.map → DataAdapter-BZFTkFQ4.js.map} +1 -1
  5. package/lib/{DebugRenderer-BJMLILqI.js → DebugRenderer-C7X-nlXE.js} +2 -2
  6. package/lib/{DebugRenderer-BJMLILqI.js.map → DebugRenderer-C7X-nlXE.js.map} +1 -1
  7. package/lib/{DevToolsPlugin-wQ5rOkn0.js → DevToolsPlugin-P-atJ-5U.js} +2 -2
  8. package/lib/{DevToolsPlugin-wQ5rOkn0.js.map → DevToolsPlugin-P-atJ-5U.js.map} +1 -1
  9. package/lib/{GSAPPlugin-DHhSZKv8.js → GSAPPlugin-CeH9275z.js} +2 -2
  10. package/lib/{GSAPPlugin-DHhSZKv8.js.map → GSAPPlugin-CeH9275z.js.map} +1 -1
  11. package/lib/{LayoutPlugin-B-DF9SYM.js → LayoutPlugin-iZ3k6RsK.js} +4 -4
  12. package/lib/{LayoutPlugin-B-DF9SYM.js.map → LayoutPlugin-iZ3k6RsK.js.map} +1 -1
  13. package/lib/{SpinePlugin-Dz_3dljz.js → SpinePlugin-BWiavCpO.js} +2 -2
  14. package/lib/{SpinePlugin-Dz_3dljz.js.map → SpinePlugin-BWiavCpO.js.map} +1 -1
  15. package/lib/{StatsPlugin-Cg82JMBD.js → StatsPlugin-CBpzDJL0.js} +4 -4
  16. package/lib/{StatsPlugin-Cg82JMBD.js.map → StatsPlugin-CBpzDJL0.js.map} +1 -1
  17. package/lib/{VoiceOverPlugin-BR3ImT8C.js → VoiceOverPlugin-YaiKJtJ6.js} +26 -26
  18. package/lib/{VoiceOverPlugin-BR3ImT8C.js.map → VoiceOverPlugin-YaiKJtJ6.js.map} +1 -1
  19. package/lib/caper.mjs +95 -95
  20. package/lib/caper.mjs.map +1 -1
  21. package/lib/core/Application.d.ts +1 -1
  22. package/lib/core/Application.d.ts.map +1 -1
  23. package/lib/core/interfaces/IApplicationOptions.d.ts +2 -1
  24. package/lib/core/interfaces/IApplicationOptions.d.ts.map +1 -1
  25. package/lib/core/interfaces/ICoreSignals.d.ts +5 -1
  26. package/lib/core/interfaces/ICoreSignals.d.ts.map +1 -1
  27. package/lib/display/Container.d.ts +1 -1
  28. package/lib/display/Container.d.ts.map +1 -1
  29. package/lib/display/ParticleContainer.d.ts +1 -1
  30. package/lib/display/ParticleContainer.d.ts.map +1 -1
  31. package/lib/plugins/Plugin.d.ts +1 -1
  32. package/lib/plugins/Plugin.d.ts.map +1 -1
  33. package/lib/plugins/defaults.d.ts.map +1 -1
  34. package/lib/plugins/gesture/GesturePlugin.d.ts +58 -0
  35. package/lib/plugins/gesture/GesturePlugin.d.ts.map +1 -0
  36. package/lib/plugins/gesture/gestureMath.d.ts +32 -0
  37. package/lib/plugins/gesture/gestureMath.d.ts.map +1 -0
  38. package/lib/plugins/gesture/gestureMath.test.d.ts +2 -0
  39. package/lib/plugins/gesture/gestureMath.test.d.ts.map +1 -0
  40. package/lib/plugins/gesture/index.d.ts +3 -0
  41. package/lib/plugins/gesture/index.d.ts.map +1 -0
  42. package/lib/plugins/gesture/types.d.ts +45 -0
  43. package/lib/plugins/gesture/types.d.ts.map +1 -0
  44. package/lib/plugins/index.d.ts +1 -0
  45. package/lib/plugins/index.d.ts.map +1 -1
  46. package/lib/plugins/input/Controls.d.ts +5 -2
  47. package/lib/plugins/input/Controls.d.ts.map +1 -1
  48. package/lib/plugins/input/InputPlugin.d.ts +9 -2
  49. package/lib/plugins/input/InputPlugin.d.ts.map +1 -1
  50. package/lib/plugins/input/interfaces.d.ts +5 -3
  51. package/lib/plugins/input/interfaces.d.ts.map +1 -1
  52. package/lib/plugins/input/touch/{TouchControls.d.ts → VirtualControls.d.ts} +5 -4
  53. package/lib/plugins/input/touch/VirtualControls.d.ts.map +1 -0
  54. package/lib/plugins/input/touch/index.d.ts +1 -1
  55. package/lib/plugins/input/touch/index.d.ts.map +1 -1
  56. package/lib/{registries-CYCaYKZI.js → registries-qQmLeN0b.js} +505 -354
  57. package/lib/registries-qQmLeN0b.js.map +1 -0
  58. package/lib/utils/bind.test.d.ts +2 -0
  59. package/lib/utils/bind.test.d.ts.map +1 -0
  60. package/package.json +24 -23
  61. package/src/core/Application.ts +1 -1
  62. package/src/core/interfaces/IApplicationOptions.ts +2 -0
  63. package/src/core/interfaces/ICoreSignals.ts +9 -0
  64. package/src/display/Container.ts +1 -1
  65. package/src/display/ParticleContainer.ts +1 -1
  66. package/src/plugins/Plugin.ts +1 -1
  67. package/src/plugins/defaults.ts +6 -0
  68. package/src/plugins/gesture/GesturePlugin.ts +215 -0
  69. package/src/plugins/gesture/gestureMath.test.ts +75 -0
  70. package/src/plugins/gesture/gestureMath.ts +59 -0
  71. package/src/plugins/gesture/index.ts +2 -0
  72. package/src/plugins/gesture/types.ts +54 -0
  73. package/src/plugins/index.ts +1 -0
  74. package/src/plugins/input/Controls.ts +9 -3
  75. package/src/plugins/input/InputPlugin.ts +61 -14
  76. package/src/plugins/input/interfaces.ts +5 -3
  77. package/src/plugins/input/touch/{TouchControls.ts → VirtualControls.ts} +4 -1
  78. package/src/plugins/input/touch/index.ts +1 -1
  79. package/src/utils/bind.test.ts +99 -0
  80. package/src/version.ts +1 -1
  81. package/LICENSE +0 -22
  82. package/lib/plugins/input/touch/TouchControls.d.ts.map +0 -1
  83. package/lib/registries-CYCaYKZI.js.map +0 -1
@@ -16,6 +16,7 @@ export type InputManagerOptions = {
16
16
 
17
17
  export interface IInputPlugin extends IPlugin<InputManagerOptions> {
18
18
  readonly controls: Controls;
19
+ readonly lastUsedController: InputController | null;
19
20
  activeGamepads: Map<string, Gamepad>;
20
21
  activeControllers: Set<string>;
21
22
  options: InputManagerOptions;
@@ -23,6 +24,7 @@ export interface IInputPlugin extends IPlugin<InputManagerOptions> {
23
24
  onGamepadDisconnected: Signal<(gamepad: Gamepad) => void>;
24
25
  onControllerActivated: Signal<(controller: string) => void>;
25
26
  onControllerDeactivated: Signal<(controller: string) => void>;
27
+ onControllerChanged: Signal<(controller: InputController) => void>;
26
28
 
27
29
  isControllerActive(controller: InputController): boolean;
28
30
 
@@ -44,11 +46,20 @@ export class InputPlugin extends Plugin<InputManagerOptions> implements IInputPl
44
46
  // properties
45
47
  public activeGamepads = new Map<string, Gamepad>();
46
48
  public activeControllers = new Set<string>([]);
49
+ private _lastUsedController: InputController | null = null;
50
+ private _canvas: HTMLCanvasElement | null = null;
47
51
  // signals
48
52
  public onGamepadConnected: Signal<(gamepad: Gamepad) => void> = new Signal<(gamepad: Gamepad) => void>();
49
53
  public onGamepadDisconnected: Signal<(gamepad: Gamepad) => void> = new Signal<(gamepad: Gamepad) => void>();
50
54
  public onControllerActivated: Signal<(controller: string) => void> = new Signal<(controller: string) => void>();
51
55
  public onControllerDeactivated: Signal<(controller: string) => void> = new Signal<(controller: string) => void>();
56
+ public onControllerChanged: Signal<(controller: InputController) => void> = new Signal<
57
+ (controller: InputController) => void
58
+ >();
59
+
60
+ get lastUsedController(): InputController | null {
61
+ return this._lastUsedController;
62
+ }
52
63
 
53
64
  isActionActive(action: Action): boolean {
54
65
  return this.controls.isActionActive(action);
@@ -58,8 +69,9 @@ export class InputPlugin extends Plugin<InputManagerOptions> implements IInputPl
58
69
  this._options = { ...defaultOptions, ...options };
59
70
 
60
71
  app.stage.eventMode = 'static';
61
- app.stage.on('touchstart', this._onTouchStart);
62
- app.stage.on('globalmousemove', this._onMouseMove);
72
+ this._canvas = app.canvas as HTMLCanvasElement;
73
+ this._canvas.addEventListener('pointerdown', this._onPointerDown);
74
+ this._canvas.addEventListener('pointermove', this._onPointerMove);
63
75
  window.addEventListener('keydown', this._onKeyDown);
64
76
  window.addEventListener('gamepadconnected', this._onGamepadConnected);
65
77
  window.addEventListener('gamepaddisconnected', this._onGamepadDisconnected);
@@ -77,12 +89,23 @@ export class InputPlugin extends Plugin<InputManagerOptions> implements IInputPl
77
89
 
78
90
  destroy(): void {
79
91
  // unregister all event listeners
80
- this.app.stage.off('touchstart', this._onTouchStart);
81
- this.app.stage.off('globalmousemove', this._onMouseMove);
92
+ if (this._canvas) {
93
+ this._canvas.removeEventListener('pointerdown', this._onPointerDown);
94
+ this._canvas.removeEventListener('pointermove', this._onPointerMove);
95
+ this._canvas = null;
96
+ }
82
97
  window.removeEventListener('keydown', this._onKeyDown);
83
98
  window.removeEventListener('gamepadconnected', this._onGamepadConnected);
84
99
  window.removeEventListener('gamepaddisconnected', this._onGamepadDisconnected);
85
100
 
101
+ this.controls.destroy();
102
+
103
+ this.onGamepadConnected.disconnectAll();
104
+ this.onGamepadDisconnected.disconnectAll();
105
+ this.onControllerActivated.disconnectAll();
106
+ this.onControllerDeactivated.disconnectAll();
107
+ this.onControllerChanged.disconnectAll();
108
+
86
109
  super.destroy();
87
110
  }
88
111
 
@@ -95,16 +118,36 @@ export class InputPlugin extends Plugin<InputManagerOptions> implements IInputPl
95
118
  }
96
119
 
97
120
  protected getCoreSignals(): string[] {
98
- return ['onGamepadConnected', 'onGamepadDisconnected', 'onControllerActivated', 'onControllerDeactivated'];
121
+ return [
122
+ 'onGamepadConnected',
123
+ 'onGamepadDisconnected',
124
+ 'onControllerActivated',
125
+ 'onControllerDeactivated',
126
+ 'onControllerChanged',
127
+ ];
128
+ }
129
+
130
+ private _isInputControllerType(value: string): value is InputController {
131
+ return (Object.values(InputControllerTypes) as string[]).includes(value);
99
132
  }
100
133
 
101
134
  private _activateController(inputController: string): void {
102
- if (this.activeControllers.has(inputController)) {
103
- return;
135
+ const isNewController = !this.activeControllers.has(inputController);
136
+ if (isNewController) {
137
+ this.activeControllers.add(inputController);
138
+ }
139
+
140
+ // only the four InputControllerTypes values are valid "last used" values —
141
+ // a raw gamepad device id (see _onGamepadConnected) must never land here
142
+ if (this._isInputControllerType(inputController) && inputController !== this._lastUsedController) {
143
+ this._lastUsedController = inputController;
144
+ this.onControllerChanged.emit(inputController);
145
+ }
146
+
147
+ if (isNewController) {
148
+ // emit the controller activated signal
149
+ this.onControllerActivated.emit(inputController);
104
150
  }
105
- this.activeControllers.add(inputController);
106
- // emit the controller activated signal
107
- this.onControllerActivated.emit(inputController);
108
151
  }
109
152
 
110
153
  private _deactivateController(inputController: InputController): void {
@@ -125,12 +168,16 @@ export class InputPlugin extends Plugin<InputManagerOptions> implements IInputPl
125
168
  this.activeGamepads.delete(gamepadId);
126
169
  }
127
170
 
128
- private _onTouchStart(): void {
129
- this._activateController(InputControllerTypes.Touch);
171
+ private _onPointerDown(event: PointerEvent): void {
172
+ if (event.pointerType === 'touch') {
173
+ this._activateController(InputControllerTypes.Touch);
174
+ }
130
175
  }
131
176
 
132
- private _onMouseMove(): void {
133
- this._activateController(InputControllerTypes.Mouse);
177
+ private _onPointerMove(event: PointerEvent): void {
178
+ if (event.pointerType === 'mouse') {
179
+ this._activateController(InputControllerTypes.Mouse);
180
+ }
134
181
  }
135
182
 
136
183
  private _onKeyDown(): void {
@@ -1,6 +1,6 @@
1
1
  import { ActionContext, ActionMap, UserActions, UserButtons } from '../actions';
2
2
  import { IKeyboardControlScheme, KeyboardControls } from './keyboard';
3
- import { ITouchControlScheme, TouchControls } from './touch';
3
+ import { ITouchControlScheme, VirtualControls } from './touch';
4
4
  import { AbstractControlScheme, ControlsActionMap, KeyboardControlsMap, TouchControlsMap } from './types';
5
5
 
6
6
  export interface ControlsAction {
@@ -17,12 +17,13 @@ export interface IGamepadControlScheme extends AbstractControlScheme<'buttonDown
17
17
  export interface ControlScheme {
18
18
  keyboard?: IKeyboardControlScheme;
19
19
  touch?: ITouchControlScheme;
20
- gamepad?: IGamepadControlScheme;
21
20
  }
22
21
 
23
22
  export interface IControls {
24
23
  readonly keyboard: KeyboardControls;
25
- readonly touch: TouchControls;
24
+ /** @deprecated Use {@link IControls.virtual} instead. */
25
+ readonly touch: VirtualControls;
26
+ readonly virtual: VirtualControls;
26
27
 
27
28
  isActionActive(action: string): boolean;
28
29
 
@@ -33,5 +34,6 @@ export interface IControls {
33
34
 
34
35
  export interface UserControls<U extends UserActions = UserActions, B extends UserButtons = UserButtons> {
35
36
  keyboard: Partial<KeyboardControlsMap<U>>;
37
+ /** Virtual on-screen buttons (joystick/buttons) — despite the key name, this is not touchscreen input. */
36
38
  touch: Partial<TouchControlsMap<U, B>>;
37
39
  }
@@ -8,7 +8,7 @@ import { type IButton, type IJoystick } from '../../../ui';
8
8
  import type { Action } from '../../actions';
9
9
  import { AbstractControls } from '../AbstractControls';
10
10
 
11
- export class TouchControls extends WithSignals(AbstractControls) {
11
+ export class VirtualControls extends WithSignals(AbstractControls) {
12
12
  protected scheme: Partial<TouchControlsMap>;
13
13
  private _buttons: Set<IButton> = new Set();
14
14
  private _joystickMap: Partial<JoystickControlsScheme>;
@@ -235,3 +235,6 @@ export class TouchControls extends WithSignals(AbstractControls) {
235
235
  }
236
236
  }
237
237
  }
238
+
239
+ /** @deprecated Use {@link VirtualControls} instead. */
240
+ export { VirtualControls as TouchControls };
@@ -1,3 +1,3 @@
1
1
  export * from './constants';
2
2
  export * from './interfaces';
3
- export * from './TouchControls';
3
+ export * from './VirtualControls';
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { bindAllMethods } from './bind';
3
+
4
+ /**
5
+ * `bindAllMethods` walks up the prototype chain binding every method, and stops
6
+ * at the first class marked with `__caper_method_binding_root`. The marker MUST
7
+ * be `static`: the walk tests it with
8
+ * `hasOwnProperty(prototype.constructor, ...)`, and an instance field never
9
+ * lands on the constructor — so declaring it non-static silently disables the
10
+ * guard and the walk runs all the way to `Object.prototype`, binding (and
11
+ * copying onto every instance) every method of the base class. For a caper
12
+ * `Container` that base is PixiJS's `Container`: ~70 extra bound closures and
13
+ * own properties per display object.
14
+ */
15
+
16
+ /** Stands in for the foreign base we must NOT bind into (i.e. PixiJS). */
17
+ class Foreign {
18
+ foreignMethod(): unknown {
19
+ return this;
20
+ }
21
+ }
22
+
23
+ class Root extends Foreign {
24
+ private static readonly __caper_method_binding_root = true;
25
+
26
+ rootMethod(): unknown {
27
+ return this;
28
+ }
29
+ }
30
+
31
+ class Leaf extends Root {
32
+ constructor() {
33
+ super();
34
+ bindAllMethods(this);
35
+ }
36
+
37
+ leafMethod(): unknown {
38
+ return this;
39
+ }
40
+ }
41
+
42
+ /** The pre-fix declaration: an instance field, which the guard cannot see. */
43
+ class BrokenRoot extends Foreign {
44
+ private readonly __caper_method_binding_root = true;
45
+
46
+ rootMethod(): unknown {
47
+ return this;
48
+ }
49
+ }
50
+
51
+ class BrokenLeaf extends BrokenRoot {
52
+ constructor() {
53
+ super();
54
+ bindAllMethods(this);
55
+ }
56
+ }
57
+
58
+ describe('bindAllMethods', () => {
59
+ it('binds methods declared at and below the leaf', () => {
60
+ const leaf = new Leaf();
61
+ const { leafMethod, rootMethod } = leaf;
62
+
63
+ expect(leafMethod()).toBe(leaf);
64
+ expect(rootMethod()).toBe(leaf);
65
+ });
66
+
67
+ it('stops at the static root marker, leaving the foreign base unbound', () => {
68
+ const leaf = new Leaf();
69
+ const { foreignMethod } = leaf;
70
+
71
+ // Detached and never bound — strict-mode `this` is undefined.
72
+ expect(foreignMethod()).toBeUndefined();
73
+ expect(Object.prototype.hasOwnProperty.call(leaf, 'foreignMethod')).toBe(false);
74
+ });
75
+
76
+ it('does not copy the foreign base onto the instance', () => {
77
+ const leaf = new Leaf();
78
+ const own = Object.getOwnPropertyNames(leaf).filter((k) => typeof (leaf as never)[k] === 'function');
79
+
80
+ expect(own).toContain('leafMethod');
81
+ expect(own).toContain('rootMethod');
82
+ expect(own).not.toContain('foreignMethod');
83
+ });
84
+
85
+ it('a NON-static marker fails to stop the walk (the bug this guards)', () => {
86
+ const broken = new BrokenLeaf();
87
+
88
+ // The guard never fires, so the foreign base gets bound and copied on.
89
+ expect(Object.prototype.hasOwnProperty.call(broken, 'foreignMethod')).toBe(true);
90
+ expect(broken.foreignMethod()).toBe(broken);
91
+ });
92
+
93
+ it('subclasses do not re-trigger the guard via an inherited static', () => {
94
+ // `hasOwnProperty` is own-only, so `Leaf` inheriting Root's static does not
95
+ // stop the walk before Leaf's own methods are collected.
96
+ expect(Object.prototype.hasOwnProperty.call(Leaf, '__caper_method_binding_root')).toBe(false);
97
+ expect(Object.prototype.hasOwnProperty.call(Root, '__caper_method_binding_root')).toBe(true);
98
+ });
99
+ });
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated during the build process.
2
- export const version: string = '0.1.0';
2
+ export const version: string = '0.1.2';
3
3
  export const pixiVersion: string = '8.19.0';
package/LICENSE DELETED
@@ -1,22 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) Relish Interactive
4
- Copyright (c) 2026 Anthony Sapp
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.
@@ -1 +0,0 @@
1
- {"version":3,"file":"TouchControls.d.ts","sourceRoot":"","sources":["../../../../src/plugins/input/touch/TouchControls.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA6C,gBAAgB,EAAuB,MAAM,UAAU,CAAC;AAGjH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;;AAEvD,qBAAa,aAAc,SAAQ,kBAA6B;IAC9D,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,yBAAyB,CAA6C;IAC9E,OAAO,CAAC,oBAAoB,CAAkC;IAC9D,OAAO,CAAC,kBAAkB,CAAkC;IAC5D,OAAO,CAAC,gBAAgB,CAAoC;;IAO5D,OAAO,CAAC,SAAS,CAAY;IAE7B,IAAI,QAAQ,IAAI,SAAS,CAExB;IAED,IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,EAE5B;IAED,IAAI,GAAG,gBAEN;IAED,SAAS,CAAC,MAAM,EAAE,OAAO;IAazB,YAAY,CAAC,MAAM,EAAE,OAAO;IAWrB,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IASnD,OAAO;IAId,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAqBvC,OAAO,CAAC,YAAY;IAoEpB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,OAAO;CAoDhB"}