@caperjs/core 0.2.2 → 0.2.3

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 (137) hide show
  1. package/build/index.mjs +2 -0
  2. package/build/plugins/viewport.mjs +52 -0
  3. package/lib/{CaptionsPlugin-DeGyPecB.js → CaptionsPlugin-WPAcfAkx.js} +13 -12
  4. package/lib/CaptionsPlugin-WPAcfAkx.js.map +1 -0
  5. package/lib/{DataAdapter-DeI2kIxC.js → DataAdapter-DS-twowe.js} +11 -11
  6. package/lib/{DataAdapter-DeI2kIxC.js.map → DataAdapter-DS-twowe.js.map} +1 -1
  7. package/lib/{DebugRenderer-wjV0tMwL.js → DebugRenderer-D1ryrRYx.js} +2 -2
  8. package/lib/{DebugRenderer-wjV0tMwL.js.map → DebugRenderer-D1ryrRYx.js.map} +1 -1
  9. package/lib/{DevToolsPlugin-D4iWQwkO.js → DevToolsPlugin-DH7zX7HU.js} +2 -2
  10. package/lib/{DevToolsPlugin-D4iWQwkO.js.map → DevToolsPlugin-DH7zX7HU.js.map} +1 -1
  11. package/lib/{GSAPPlugin-DQTyIwcC.js → GSAPPlugin-BBtRjUqe.js} +2 -2
  12. package/lib/{GSAPPlugin-DQTyIwcC.js.map → GSAPPlugin-BBtRjUqe.js.map} +1 -1
  13. package/lib/{LayoutPlugin-vR_h-BaG.js → LayoutPlugin-Co6vcoV4.js} +4 -4
  14. package/lib/{LayoutPlugin-vR_h-BaG.js.map → LayoutPlugin-Co6vcoV4.js.map} +1 -1
  15. package/lib/{SpinePlugin-DJ-PpxFj.js → SpinePlugin-uN641Hmk.js} +2 -2
  16. package/lib/{SpinePlugin-DJ-PpxFj.js.map → SpinePlugin-uN641Hmk.js.map} +1 -1
  17. package/lib/{StatsPlugin-BYNnKYOm.js → StatsPlugin-vZQRm6wh.js} +4 -4
  18. package/lib/{StatsPlugin-BYNnKYOm.js.map → StatsPlugin-vZQRm6wh.js.map} +1 -1
  19. package/lib/{VoiceOverPlugin-BLSbq3DU.js → VoiceOverPlugin-KlZdGj1G.js} +32 -32
  20. package/lib/{VoiceOverPlugin-BLSbq3DU.js.map → VoiceOverPlugin-KlZdGj1G.js.map} +1 -1
  21. package/lib/caper.mjs +2107 -353
  22. package/lib/caper.mjs.map +1 -1
  23. package/lib/core/Application.d.ts +7 -1
  24. package/lib/core/Application.d.ts.map +1 -1
  25. package/lib/core/interfaces/IApplicationOptions.d.ts +1 -1
  26. package/lib/core/interfaces/IApplicationOptions.d.ts.map +1 -1
  27. package/lib/core/interfaces/ICoreFunctions.d.ts +1 -0
  28. package/lib/core/interfaces/ICoreFunctions.d.ts.map +1 -1
  29. package/lib/display/AnimatedSprite.d.ts +1 -1
  30. package/lib/display/AnimatedSprite.d.ts.map +1 -1
  31. package/lib/display/Container.d.ts.map +1 -1
  32. package/lib/display/SpineAnimation.d.ts +1 -1
  33. package/lib/display/SpineAnimation.d.ts.map +1 -1
  34. package/lib/importOrder.containerFirst.test.d.ts +2 -0
  35. package/lib/importOrder.containerFirst.test.d.ts.map +1 -0
  36. package/lib/importOrder.displayFirst.test.d.ts +2 -0
  37. package/lib/importOrder.displayFirst.test.d.ts.map +1 -0
  38. package/lib/importOrder.mixinsFirst.test.d.ts +2 -0
  39. package/lib/importOrder.mixinsFirst.test.d.ts.map +1 -0
  40. package/lib/importOrder.sceneFirst.test.d.ts +2 -0
  41. package/lib/importOrder.sceneFirst.test.d.ts.map +1 -0
  42. package/lib/importOrder.toastFirst.test.d.ts +2 -0
  43. package/lib/importOrder.toastFirst.test.d.ts.map +1 -0
  44. package/lib/importOrder.uiFirst.test.d.ts +2 -0
  45. package/lib/importOrder.uiFirst.test.d.ts.map +1 -0
  46. package/lib/mixins/factory/Factory.d.ts +1 -1
  47. package/lib/mixins/factory/Factory.d.ts.map +1 -1
  48. package/lib/mixins/factory/Factory.test.d.ts +1 -0
  49. package/lib/mixins/factory/Factory.test.d.ts.map +1 -0
  50. package/lib/mixins/factory/const.d.ts +9 -2
  51. package/lib/mixins/factory/const.d.ts.map +1 -1
  52. package/lib/mixins/factory/defaults.d.ts +5 -0
  53. package/lib/mixins/factory/defaults.d.ts.map +1 -0
  54. package/lib/mixins/factory/methods.d.ts +1 -1
  55. package/lib/mixins/factory/methods.d.ts.map +1 -1
  56. package/lib/mixins/factory/props.d.ts +4 -2
  57. package/lib/mixins/factory/props.d.ts.map +1 -1
  58. package/lib/plugins/PopupManagerPlugin.d.ts +1 -1
  59. package/lib/plugins/PopupManagerPlugin.d.ts.map +1 -1
  60. package/lib/plugins/ResizerPlugin.d.ts +29 -0
  61. package/lib/plugins/ResizerPlugin.d.ts.map +1 -1
  62. package/lib/plugins/ResizerPlugin.test.d.ts +2 -0
  63. package/lib/plugins/ResizerPlugin.test.d.ts.map +1 -0
  64. package/lib/plugins/WebEventsPlugin.d.ts +5 -0
  65. package/lib/plugins/WebEventsPlugin.d.ts.map +1 -1
  66. package/lib/plugins/WebEventsPlugin.test.d.ts +2 -0
  67. package/lib/plugins/WebEventsPlugin.test.d.ts.map +1 -0
  68. package/lib/plugins/captions/CaptionsRenderer.d.ts +1 -1
  69. package/lib/plugins/captions/CaptionsRenderer.d.ts.map +1 -1
  70. package/lib/plugins/i18nPlugin.d.ts +29 -3
  71. package/lib/plugins/i18nPlugin.d.ts.map +1 -1
  72. package/lib/plugins/i18nPlugin.test.d.ts +2 -0
  73. package/lib/plugins/i18nPlugin.test.d.ts.map +1 -0
  74. package/lib/plugins/input/touch/VirtualControls.d.ts.map +1 -1
  75. package/lib/plugins/spine/pixi-spine/require-shim.d.ts +0 -1
  76. package/lib/plugins/spine/pixi-spine/require-shim.d.ts.map +1 -1
  77. package/lib/{registries-aN0y0Xha.js → registries-BLrxALZ0.js} +1124 -2801
  78. package/lib/registries-BLrxALZ0.js.map +1 -0
  79. package/lib/ui/Button.d.ts +1 -1
  80. package/lib/ui/Button.d.ts.map +1 -1
  81. package/lib/ui/FlexContainer.d.ts +1 -1
  82. package/lib/ui/FlexContainer.d.ts.map +1 -1
  83. package/lib/ui/Input.d.ts +2 -2
  84. package/lib/ui/Input.d.ts.map +1 -1
  85. package/lib/ui/Joystick.d.ts +1 -1
  86. package/lib/ui/Joystick.d.ts.map +1 -1
  87. package/lib/ui/Toast.d.ts +1 -1
  88. package/lib/ui/Toast.d.ts.map +1 -1
  89. package/lib/ui/UICanvas.d.ts +11 -1
  90. package/lib/ui/UICanvas.d.ts.map +1 -1
  91. package/lib/ui/UICanvas.test.d.ts +2 -0
  92. package/lib/ui/UICanvas.test.d.ts.map +1 -0
  93. package/lib/utils/types.d.ts +1 -2
  94. package/lib/utils/types.d.ts.map +1 -1
  95. package/package.json +1 -1
  96. package/src/core/Application.ts +15 -2
  97. package/src/core/interfaces/IApplicationOptions.ts +1 -1
  98. package/src/core/interfaces/ICoreFunctions.ts +1 -0
  99. package/src/display/AnimatedSprite.ts +2 -1
  100. package/src/display/Container.ts +3 -1
  101. package/src/display/SpineAnimation.ts +3 -2
  102. package/src/importOrder.containerFirst.test.ts +32 -0
  103. package/src/importOrder.displayFirst.test.ts +19 -0
  104. package/src/importOrder.mixinsFirst.test.ts +18 -0
  105. package/src/importOrder.sceneFirst.test.ts +21 -0
  106. package/src/importOrder.toastFirst.test.ts +20 -0
  107. package/src/importOrder.uiFirst.test.ts +24 -0
  108. package/src/mixins/factory/Factory.test.ts +22 -0
  109. package/src/mixins/factory/Factory.ts +9 -2
  110. package/src/mixins/factory/const.ts +18 -11
  111. package/src/mixins/factory/defaults.ts +28 -0
  112. package/src/mixins/factory/methods.ts +1 -1
  113. package/src/mixins/factory/props.ts +5 -3
  114. package/src/plugins/LookupPlugin.ts +1 -1
  115. package/src/plugins/PopupManagerPlugin.ts +1 -1
  116. package/src/plugins/ResizerPlugin.test.ts +84 -0
  117. package/src/plugins/ResizerPlugin.ts +59 -1
  118. package/src/plugins/WebEventsPlugin.test.ts +75 -0
  119. package/src/plugins/WebEventsPlugin.ts +15 -0
  120. package/src/plugins/captions/CaptionsRenderer.ts +1 -1
  121. package/src/plugins/i18nPlugin.test.ts +124 -0
  122. package/src/plugins/i18nPlugin.ts +57 -18
  123. package/src/plugins/input/keyboard/KeyboardContols.ts +1 -1
  124. package/src/plugins/input/touch/VirtualControls.ts +2 -2
  125. package/src/plugins/spine/pixi-spine/require-shim.ts +3 -1
  126. package/src/ui/Button.ts +5 -1
  127. package/src/ui/FlexContainer.ts +3 -2
  128. package/src/ui/Input.ts +5 -2
  129. package/src/ui/Joystick.ts +1 -1
  130. package/src/ui/Toast.ts +2 -1
  131. package/src/ui/Toaster.ts +1 -1
  132. package/src/ui/UICanvas.test.ts +35 -0
  133. package/src/ui/UICanvas.ts +46 -8
  134. package/src/utils/types.ts +1 -1
  135. package/src/version.ts +1 -1
  136. package/lib/CaptionsPlugin-DeGyPecB.js.map +0 -1
  137. package/lib/registries-aN0y0Xha.js.map +0 -1
package/src/ui/Button.ts CHANGED
@@ -12,7 +12,11 @@ import {
12
12
  import { type LayoutOptions } from '@pixi/layout';
13
13
  import type { IApplication } from '../core';
14
14
  import { Application } from '../core/Application';
15
- import { Factory, Focusable, HTMLTextProps, Interactive, type TextProps, WithSignals } from '../mixins';
15
+ import { Factory } from '../mixins/factory/Factory';
16
+ import type { HTMLTextProps, TextProps } from '../mixins/factory/props';
17
+ import { Focusable } from '../mixins/focus';
18
+ import { Interactive } from '../mixins/interaction';
19
+ import { WithSignals } from '../mixins/signals';
16
20
  import { Signal } from '../signals';
17
21
  import { AudioAsset, bindAllMethods, type SpritesheetAsset, type TextureAsset } from '../utils';
18
22
 
@@ -1,8 +1,9 @@
1
1
  import type { LayoutOptions, NumberValue } from '@pixi/layout';
2
2
  import { BitmapText, Graphics, Container as PIXIContainer, Text } from 'pixi.js';
3
3
  import { Application } from '../core/Application';
4
- import { Container } from '../display';
5
- import { Factory, WithSignals } from '../mixins';
4
+ import { Container } from '../display/Container';
5
+ import { Factory } from '../mixins/factory/Factory';
6
+ import { WithSignals } from '../mixins/signals';
6
7
  import { Signal } from '../signals';
7
8
  import {
8
9
  AppTypeOverrides,
package/src/ui/Input.ts CHANGED
@@ -11,7 +11,10 @@ import {
11
11
  Texture,
12
12
  } from 'pixi.js';
13
13
 
14
- import { Focusable, Interactive, TextProps, WithSignals } from '../mixins';
14
+ import type { TextProps } from '../mixins/factory/props';
15
+ import { Focusable } from '../mixins/focus';
16
+ import { Interactive } from '../mixins/interaction';
17
+ import { WithSignals } from '../mixins/signals';
15
18
 
16
19
  import {
17
20
  EaseString,
@@ -27,7 +30,7 @@ import {
27
30
  } from '../utils';
28
31
 
29
32
  import { gsap } from 'gsap';
30
- import { Container } from '../display';
33
+ import { Container } from '../display/Container';
31
34
  import { Signal } from '../signals';
32
35
 
33
36
  /**
@@ -4,7 +4,7 @@
4
4
  * ported to TypeScript and adapted for Caper
5
5
  */
6
6
  import { DestroyOptions, FederatedPointerEvent, Graphics, Point, Sprite } from 'pixi.js';
7
- import { Container } from '../display';
7
+ import { Container } from '../display/Container';
8
8
  import { JoystickDirection } from '../plugins';
9
9
  import { Signal } from '../signals';
10
10
 
package/src/ui/Toast.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { gsap } from 'gsap';
2
2
  import { Graphics, Text } from 'pixi.js';
3
3
  import { Container } from '../display/Container';
4
- import { type TextStyle, WithSignals } from '../mixins';
4
+ import type { TextStyle } from '../mixins/factory/props';
5
+ import { WithSignals } from '../mixins/signals';
5
6
  import { Signal } from '../signals';
6
7
  import { Button } from './Button';
7
8
  import { Toaster } from './Toaster';
package/src/ui/Toaster.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { gsap } from 'gsap';
2
2
  import { Container } from '../display/Container';
3
- import { WithSignals } from '../mixins';
3
+ import { WithSignals } from '../mixins/signals';
4
4
  import { Signal } from '../signals';
5
5
  import { defaultToastConfig, Toast, ToastConfig } from './Toast';
6
6
  import { UICanvasEdge } from './UICanvas';
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+
3
+ // UICanvas transitively imports Application → Pixi display graph. Stub it — the
4
+ // pure padding helper needs none of it.
5
+ vi.mock('../core/Application', () => ({
6
+ Application: { getInstance: () => ({}) },
7
+ }));
8
+
9
+ import { computeEffectivePadding } from './UICanvas';
10
+
11
+ const zero = { top: 0, right: 0, bottom: 0, left: 0 };
12
+
13
+ describe('computeEffectivePadding', () => {
14
+ it('adds the safe area to the configured padding', () => {
15
+ expect(
16
+ computeEffectivePadding({ top: 10, right: 10, bottom: 10, left: 10 }, { ...zero, top: 44, bottom: 34 }),
17
+ ).toEqual({ top: 54, right: 10, bottom: 44, left: 10 });
18
+ });
19
+
20
+ it('returns the configured padding when there is no safe area', () => {
21
+ expect(computeEffectivePadding({ top: 10, right: 20, bottom: 30, left: 40 }, zero)).toEqual({
22
+ top: 10,
23
+ right: 20,
24
+ bottom: 30,
25
+ left: 40,
26
+ });
27
+ });
28
+
29
+ it('does not compound when applied repeatedly to the same base padding', () => {
30
+ const base = { top: 10, right: 10, bottom: 10, left: 10 };
31
+ const safeArea = { ...zero, top: 44 };
32
+ computeEffectivePadding(base, safeArea);
33
+ expect(computeEffectivePadding(base, safeArea).top).toBe(54);
34
+ });
35
+ });
@@ -1,8 +1,9 @@
1
1
  import type { LayoutOptions } from '@pixi/layout';
2
2
  import { ContainerChild, Graphics, RenderLayer, Container as PIXIContainer, Text } from 'pixi.js';
3
3
  import { Application } from '../core/Application';
4
- import { Container } from '../display';
5
- import { Factory, WithSignals } from '../mixins';
4
+ import { Container } from '../display/Container';
5
+ import { Factory } from '../mixins/factory/Factory';
6
+ import { WithSignals } from '../mixins/signals';
6
7
  import type { AppTypeOverrides, Padding, PointLike, Size, SizeLike } from '../utils';
7
8
  import {
8
9
  bindAllMethods,
@@ -72,21 +73,46 @@ export type UICanvasConfig = {
72
73
  padding: Padding;
73
74
  size: Size;
74
75
  useAppSize: boolean;
76
+ useSafeArea: boolean;
75
77
  layout?: Omit<LayoutOptions, 'target'> | null | boolean;
76
78
  autoLayoutChildren?: boolean;
77
79
  };
78
80
 
79
- export const UICanvasConfigKeys: (keyof UICanvasConfig)[] = ['debug', 'padding', 'size', 'useAppSize', 'layout'];
81
+ export const UICanvasConfigKeys: (keyof UICanvasConfig)[] = [
82
+ 'debug',
83
+ 'padding',
84
+ 'size',
85
+ 'useAppSize',
86
+ 'useSafeArea',
87
+ 'layout',
88
+ ];
80
89
 
81
90
  export type UICanvasProps = {
82
91
  debug: boolean;
83
92
  padding: Partial<Padding> | PointLike;
84
93
  size?: SizeLike;
85
94
  useAppSize?: boolean;
95
+ useSafeArea?: boolean;
86
96
  layout?: Omit<LayoutOptions, 'target'> | null | boolean;
87
97
  autoLayoutChildren?: boolean;
88
98
  };
89
99
 
100
+ const zeroPadding: Padding = { top: 0, right: 0, bottom: 0, left: 0 };
101
+
102
+ /**
103
+ * The padding the canvas actually lays out with: the configured padding plus the
104
+ * device's safe-area insets. Kept separate from `config.padding` so it can be
105
+ * re-derived on every resize without compounding.
106
+ */
107
+ export function computeEffectivePadding(padding: Padding, safeArea: Padding): Padding {
108
+ return {
109
+ top: padding.top + safeArea.top,
110
+ right: padding.right + safeArea.right,
111
+ bottom: padding.bottom + safeArea.bottom,
112
+ left: padding.left + safeArea.left,
113
+ };
114
+ }
115
+
90
116
  const defaultLayout = {
91
117
  flexGrow: 0,
92
118
  flexShrink: 0,
@@ -124,6 +150,7 @@ export class UICanvas extends _UICanvas {
124
150
  padding: ensurePadding(config?.padding ?? 0),
125
151
  size: config.size !== undefined ? resolveSizeLike(config.size) : { width: 0, height: 0 },
126
152
  useAppSize: config.useAppSize === true,
153
+ useSafeArea: config.useSafeArea ?? true,
127
154
  autoLayoutChildren: config.autoLayoutChildren ?? true,
128
155
  };
129
156
 
@@ -414,13 +441,22 @@ export class UICanvas extends _UICanvas {
414
441
  set padding(value: Partial<Padding> | PointLike) {
415
442
  this.config.padding = ensurePadding(value);
416
443
  // Update position to account for padding
444
+ this._applyPadding();
445
+ this._updateLayout();
446
+ }
447
+
448
+ /** Writes the effective padding (configured padding + safe-area insets) into the layout. */
449
+ private _applyPadding() {
450
+ const padding = computeEffectivePadding(
451
+ this.config.padding,
452
+ this.config.useSafeArea ? this.app.safeArea : zeroPadding,
453
+ );
417
454
  this.layout = {
418
- paddingLeft: this.config.padding.left,
419
- paddingTop: this.config.padding.top,
420
- paddingRight: this.config.padding.right,
421
- paddingBottom: this.config.padding.bottom,
455
+ paddingLeft: padding.left,
456
+ paddingTop: padding.top,
457
+ paddingRight: padding.right,
458
+ paddingBottom: padding.bottom,
422
459
  };
423
- this._updateLayout();
424
460
  }
425
461
 
426
462
  private static isFlexContainer(child: PIXIContainer): boolean {
@@ -494,6 +530,8 @@ export class UICanvas extends _UICanvas {
494
530
  }
495
531
 
496
532
  public resize() {
533
+ // Re-derived rather than cached: the safe area changes with the viewport.
534
+ this._applyPadding();
497
535
  if (this.config.useAppSize) {
498
536
  this.size = { width: this.app.size.width, height: this.app.size.height };
499
537
  this.position.set(-this.app.size.width * 0.5, -this.app.size.height * 0.5);
@@ -1,7 +1,7 @@
1
1
  import type { AssetInitOptions, AssetsManifest, AssetsPreferences, Texture, UnresolvedAsset } from 'pixi.js';
2
2
  import { Point } from 'pixi.js';
3
3
  import type { Scene } from '../display/Scene';
4
- import { SceneAssets } from '../display';
4
+ import type { SceneAssets } from '../display/Scene';
5
5
  import type { FilterBitmapFontNames, FilterCleanAssetNames, FilterSpineAssetNames } from './typefilters';
6
6
 
7
7
  /**
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.2.2';
2
+ export const version: string = '0.2.3';
3
3
  export const pixiVersion: string = '8.19.0';
@@ -1 +0,0 @@
1
- {"version":3,"file":"CaptionsPlugin-DeGyPecB.js","names":[],"sources":["../src/plugins/captions/CaptionsRenderer.ts","../src/plugins/captions/CaptionsPlugin.ts"],"sourcesContent":["import { gsap } from 'gsap';\nimport { BitmapText, Container as PIXIContainer, Sprite, Texture } from 'pixi.js';\nimport { Container } from '../../display';\nimport { type Size } from '../../utils';\nimport { CaptionsPlugin } from './CaptionsPlugin';\n\nexport type CaptionLine = {\n id: string;\n start: number;\n end: number;\n content: string;\n speaker?: string;\n};\n\nexport interface ICaptionRenderer extends PIXIContainer {\n visible: boolean;\n\n start(): void;\n\n stop(): void;\n\n lineBegin(line: CaptionLine): void;\n\n lineEnd(line: CaptionLine): void;\n\n resize(size?: Size): void;\n\n updateSettings(): void;\n\n destroy(): void;\n}\n\nexport class CaptionsRenderer extends Container implements ICaptionRenderer {\n private readonly _bg: Sprite;\n private readonly _text: BitmapText;\n private readonly _size: Size = { width: 0, height: 0 };\n private readonly fontSize = 48;\n\n constructor(private plugin: CaptionsPlugin) {\n super({ autoResize: false });\n\n this._bg = this.add.sprite({ asset: Texture.WHITE, anchor: [0.5, 0] });\n this._bg.tint = this.plugin.options.backgroundColor;\n this._bg.alpha = 0;\n\n this._text = this.add.bitmapText({\n font: plugin.options.fontName,\n resolution: 2,\n roundPixels: true,\n style: {\n fill: this.plugin.options.textColor,\n fontSize: this.fontSize * this.getSizeMultiplier(),\n fontWeight: 'bold',\n align: 'center',\n wordWrapWidth: this.plugin.maxWidth,\n wordWrap: true,\n lineHeight: this.fontSize * this.getSizeMultiplier() * 2 + 20,\n },\n });\n this._text.style.wordWrap = true;\n this._text.alpha = 0;\n this._text.visible = false;\n this._text.anchor.x = 0.5;\n this._text.anchor.y = 0;\n this.addChild(this._text);\n\n if (this.plugin.debug) {\n let isTapping = false;\n this._bg.eventMode = 'static';\n this._bg.on('pointertap', () => {\n if (isTapping) {\n return;\n }\n isTapping = true;\n setTimeout(() => {\n isTapping = false;\n void this.app.voiceover.stopVO();\n }, 100);\n });\n }\n }\n\n public start(): void {\n this._text.visible = true;\n this._bg.visible = true;\n\n gsap.killTweensOf([this._bg, this._text]);\n this.animate({ alpha: this.plugin.options.backgroundAlpha, visible: true, duration: 0.2 }, this._bg);\n this.animate({ alpha: 1, visible: true, duration: 0.2 }, this._text);\n }\n\n public stop(): void {\n gsap.killTweensOf([this._bg, this._text]);\n this.animate({ alpha: 0, visible: false, duration: 0.2 }, [this._bg, this._text]);\n }\n\n public lineBegin(line: CaptionLine): void {\n let text = line.content\n .replace(/<[^>]*>/gi, '') // remove html tags\n .replace(/\\[.*]\\W*/gi, ''); // remove brackets\n if (line.start === 0) {\n text = text.charAt(0).toUpperCase() + text.slice(1);\n }\n this._text.text = text;\n this.resize();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public lineEnd(_line: CaptionLine): void {}\n\n public resize(): void {\n const size = this.app.size;\n const opts = this.plugin.options;\n\n this._size.width = size.width;\n this._size.height = size.height;\n\n this._text.style.fontSize = this.fontSize * this.getSizeMultiplier();\n this._text.style.wordWrapWidth = opts.maxWidth * 2;\n this._text.scale.set(0.5);\n this._text.position.set(this._size.width * 0.5, 0);\n\n this._bg.position.set(this._size.width * 0.5, 0);\n\n let h = this._text.height;\n if (opts.padding.top) {\n h += opts.padding.top;\n }\n if (opts.padding.bottom) {\n h += opts.padding.bottom;\n }\n this._bg.height = h;\n\n this._text.y += opts.padding.top;\n\n if (opts.floating) {\n let w = this._text.width;\n\n if (opts.padding.left) {\n w += opts.padding.left;\n }\n if (opts.padding.right) {\n w += opts.padding.right;\n }\n\n this._bg.x += opts.padding.right * 0.5 - opts.padding.left * 0.5;\n this._bg.width = w;\n } else {\n this._bg.width = size.width;\n }\n\n if (opts.position === 'top') {\n this.position.set(-size.width * 0.5, Math.round(-size.height * 0.5));\n if (opts.floating) {\n this.position.y += Math.round(opts.distance - this._bg.y);\n }\n } else {\n this.position.set(-size.width * 0.5, Math.round(size.height * 0.5 - this._bg.height));\n if (opts.floating) {\n this.position.y -= Math.round(opts.distance + this._bg.y);\n }\n }\n }\n\n updateSettings() {\n if (this.plugin.options.enabled) {\n this._text.style.fill = this.plugin.options.textColor;\n this._bg.tint = this.plugin.options.backgroundColor;\n if (this._bg.visible) {\n this._bg.alpha = this.plugin.options.backgroundAlpha;\n this.resize();\n }\n } else {\n this.stop();\n this._bg.visible = false;\n this._text.visible = false;\n this._bg.alpha = this._text.alpha = 0;\n }\n }\n\n private getSizeMultiplier(): number {\n return this.plugin.options.fontSizeMultiplier;\n }\n}\n","import { Assets, Container, Ticker } from 'pixi.js';\nimport type { ImportListItem, ImportListItemModule, Padding, PointLike } from '../../utils';\nimport { ensurePadding, getDynamicModuleFromImportListItem, isDev, Logger } from '../../utils';\nimport type { IAudioInstance } from '../audio';\nimport type { IPlugin } from '../Plugin';\nimport { Plugin } from '../Plugin';\nimport type { ICaptionRenderer } from './CaptionsRenderer';\nimport { CaptionsRenderer } from './CaptionsRenderer';\n\nconst isDebug = isDev;\n\n/**\n * Type definition for i18n dictionary.\n */\ntype CaptionsDict = Record<string, any>;\n\n/**\n * Type definition for i18n import list item.\n */\ntype CaptionsImportListItem<T> = {\n id: string;\n namedExport?: string;\n options?: any;\n module?: ImportListItemModule<T>;\n} & {\n json?: string;\n};\n\ntype CaptionRendererConstructor = new (owner: CaptionsPlugin) => ICaptionRenderer;\n\n/**\n * Type definition for i18n options.\n */\nexport type CaptionsOptions = {\n renderer: CaptionRendererConstructor;\n defaultLocale: string;\n files: CaptionsImportListItem<CaptionsDict>[];\n fontFile: string;\n fontName: string;\n fontSizeMultiplier: number;\n maxWidth: number;\n textColor: number;\n backgroundColor: number;\n backgroundAlpha: number;\n enabled: boolean;\n floating: boolean;\n distance: number;\n padding: Padding;\n position: 'top' | 'bottom';\n};\n\n/**\n * Default options for i18n module.\n */\nconst defaultOptions: Partial<CaptionsOptions> = {\n renderer: CaptionsRenderer,\n defaultLocale: 'en',\n fontFile: './caper/font/Sans.fnt',\n fontName: 'Sans',\n fontSizeMultiplier: 1,\n maxWidth: 0.8,\n textColor: 0xffffff,\n backgroundColor: 0x0,\n backgroundAlpha: 0.4,\n enabled: true,\n floating: false,\n distance: 0,\n padding: { top: 20, left: 0, bottom: 20, right: 0 },\n position: 'top',\n};\n\nfunction resolveMaxWidth(value: number, appWidth: number) {\n if (value <= 0) {\n return 0;\n }\n if (value > 0 && value <= 1) {\n return appWidth * value;\n }\n return value;\n}\n\n/**\n * Interface for i18n module.\n */\nexport interface ICaptionsPlugin extends IPlugin {\n readonly locale: string;\n view: Container;\n enabled: boolean;\n floating: boolean;\n distance: number;\n padding: Padding;\n position: 'top' | 'bottom';\n backgroundColor: number;\n textColor: number;\n backgroundAlpha: number;\n fontSizeMultiplier: number;\n maxWidth: number;\n options: Partial<CaptionsOptions>;\n\n setLocale(localeId: string): Promise<string>;\n\n loadLocale(localeId: string): Promise<void>;\n\n render(): void;\n}\n\n/**\n * i18n module class.\n */\nexport class CaptionsPlugin extends Plugin<CaptionsOptions> implements ICaptionsPlugin {\n public readonly id = 'captions';\n public view: Container = new Container();\n public renderer: ICaptionRenderer;\n private _dicts: Record<string, CaptionsDict> = {};\n private _locales: string[];\n private _activeCaptionLine = -1;\n private _activeCaptionTime = 0;\n\n private _locale: string;\n\n /**\n * Getter for locale.\n */\n get locale(): string {\n return this._locale;\n }\n\n private _originalOptions: CaptionsOptions;\n\n get options(): CaptionsOptions {\n return this._options;\n }\n\n set options(value: Partial<CaptionsOptions>) {\n this._options = { ...this._options, ...value };\n\n if (value.padding) {\n this._options.padding = ensurePadding(value.padding);\n }\n }\n\n private _activeCaptionId?: string;\n\n get activeCaptionId() {\n return this._activeCaptionId;\n }\n\n private _paused: boolean = false;\n\n get paused(): boolean {\n return this._paused;\n }\n\n set paused(value: boolean) {\n this._paused = value;\n }\n\n get floating(): boolean {\n return this.options.floating;\n }\n\n set floating(value: boolean) {\n this.options.floating = value;\n this.updateRenderer();\n }\n\n public get enabled(): boolean {\n return this.options.enabled;\n }\n\n set enabled(value: boolean) {\n this.options.enabled = value;\n if (this.enabled) {\n this.view.visible = true;\n } else {\n this.view.visible = false;\n }\n }\n\n public get position(): 'top' | 'bottom' {\n return this.options.position;\n }\n\n public set position(value: 'top' | 'bottom') {\n this.options.position = value;\n this.renderer.updateSettings();\n }\n\n set backgroundColor(value: number) {\n this.options.backgroundColor = value;\n this.updateRenderer();\n }\n\n set textColor(value: number) {\n this.options.textColor = value;\n this.updateRenderer();\n }\n\n set backgroundAlpha(value: number) {\n this.options.backgroundAlpha = value;\n this.updateRenderer();\n }\n\n get padding(): Padding {\n return this.options.padding;\n }\n\n set padding(value: Partial<Padding> | PointLike) {\n this.options.padding = ensurePadding(value);\n this.updateRenderer();\n }\n\n get distance(): number {\n return this.options.distance;\n }\n\n set distance(value: number) {\n this.options.distance = value;\n this.updateRenderer();\n }\n\n public get fontSizeMultiplier(): number {\n return this.options.fontSizeMultiplier;\n }\n\n public set fontSizeMultiplier(value: number) {\n this.options.fontSizeMultiplier = value;\n this.renderer.resize();\n }\n\n public get maxWidth(): number {\n return this.options.maxWidth;\n }\n\n public set maxWidth(value: number) {\n this.options.maxWidth = resolveMaxWidth(value, this.app.size.width);\n this.renderer?.resize();\n }\n\n get list(): CaptionsDict {\n return this._dicts[this._locale];\n }\n\n get debug(): boolean {\n return isDebug;\n }\n\n /**\n * Initializes the i18n module.\n * sets the default locale and loads the locale files.\n * @param _app\n * @param options The i18n options.\n * @returns Promise<void>\n */\n public async initialize(options: Partial<CaptionsOptions>): Promise<void> {\n this._options = {\n ...defaultOptions,\n ...options,\n } as CaptionsOptions;\n\n this._originalOptions = { ...this._options };\n\n if (options?.padding) {\n this._options.padding = ensurePadding(options.padding);\n }\n\n this._locale = this.app.i18n.locale;\n this._locales = this.app.i18n.locales;\n\n if (this._options.fontFile) {\n await Assets.load(this._options.fontFile);\n }\n\n if (this._options?.files?.length > 0) {\n const files = this._options.files.filter((file) => this._locales.includes(file.id));\n for (const file of files) {\n await this.loadLocale(file.id);\n }\n }\n\n this.addSignalConnection(this.app.onResize.connect(this.handleResize, 'highest'));\n }\n\n private handleResize() {\n this.maxWidth = this._originalOptions.maxWidth;\n }\n\n public postInitialize(): void {\n this.app.i18n.onLocaleChanged.connect(this._handleLocaleChange);\n this.app.voiceover.onVoiceOverStart.connect(this._handleVoiceOverStart);\n this.app.voiceover.onVoiceOverPaused.connect(this._handleVoiceOverPaused);\n this.app.voiceover.onVoiceOverResumed.connect(this._handleVoiceOverResumed);\n this.app.voiceover.onVoiceOverComplete.connect(this._handleVoiceoverComplete);\n this.app.voiceover.onVoiceOverStopped.connect(this._handleVoiceoverStopped);\n\n this.app.stage.addChild(this.view);\n this._options.maxWidth = resolveMaxWidth(this._originalOptions.maxWidth, this.app.size.width);\n const RendererClass: CaptionRendererConstructor = this.options.renderer;\n this.renderer = this.view.addChild(new RendererClass(this)) as CaptionsRenderer;\n\n this.app.ticker.add(this.update);\n this.app.scenes.onSceneChangeStart.connect(this.stopAllCaptions);\n }\n\n /**\n * Sets the locale.\n * If the locale is not loaded, it will load it first.\n * @param localeId The locale id to set.\n * @returns Promise<string>\n */\n async setLocale(localeId: string) {\n if (this._locale === localeId) {\n return this._locale;\n }\n if (this._activeCaptionId) {\n this.stopCaption(this._activeCaptionId);\n }\n this._activeCaptionId = undefined;\n await this._loadAndSetLocale(localeId);\n this._locale = localeId;\n return this._locale;\n }\n\n /**\n * Loads a locale.\n * @param localeId The locale id to load.\n * @returns Promise<void>\n */\n async loadLocale(localeId: string) {\n if (this._locale === 'localeId') {\n return;\n }\n const file = this._options.files.find((file) => localeId === file.id);\n if (!file) {\n Logger.error(`i18n:: Could not find locale file for ${localeId}`);\n return;\n }\n this._dicts[localeId] = file.json\n ? await Assets.load(file.json)\n : await getDynamicModuleFromImportListItem(file as ImportListItem<CaptionsDict>);\n }\n\n render() {\n this.renderer.resize();\n }\n\n update(ticker: Ticker): void {\n if (this._paused) {\n return;\n }\n const dt: number = ticker.deltaMS / 1000;\n const id = this._activeCaptionId;\n if (id) {\n this._activeCaptionTime += dt;\n const ms = this._activeCaptionTime * 1000;\n const cc = this.list[id];\n const n = cc.length;\n for (let i = 0; i < n; i++) {\n if (ms >= cc[i].start && ms < cc[i].end) {\n if (this._activeCaptionLine !== i) {\n this.playLine(id, i);\n }\n break;\n }\n }\n if (ms >= cc[n - 1].end) {\n this.playLine(id, -1);\n }\n }\n }\n\n public playCaption(id: string): void {\n // remove extension from id\n id = this._getId(id);\n this.playLine(id, 0);\n }\n\n public stopCaption(id: string): void {\n // remove extension from id\n id = this._getId(id);\n if (this._activeCaptionId === id) {\n this.playLine(id, -1);\n }\n }\n\n public stopAllCaptions(): void {\n this.renderer?.stop();\n this._activeCaptionId = undefined;\n this._activeCaptionLine = -1;\n }\n\n private _getId(id: string) {\n return id.replace(/\\.[^/.]+$/, '');\n }\n\n private updateRenderer() {\n if (!this.enabled) {\n return;\n }\n this.renderer.updateSettings();\n }\n\n private _handleLocaleChange() {\n void this.setLocale(this.app.i18n.locale);\n }\n\n private _handleVoiceOverStart(vo: IAudioInstance) {\n this.playCaption(vo.id);\n }\n\n private _handleVoiceOverPaused() {\n this.paused = true;\n }\n\n private _handleVoiceOverResumed() {\n this.paused = false;\n }\n\n private _handleVoiceoverComplete(vo: IAudioInstance) {\n const id = this._getId(vo?.id || '');\n if (this._activeCaptionId === id) {\n this.stopCaption(id);\n }\n }\n\n private _handleVoiceoverStopped() {\n this.stopAllCaptions();\n }\n\n /**\n * Loads and sets a locale.\n * If the locale is not loaded, it will load it first.\n * @param localeId The locale id to load and set.\n */\n private async _loadAndSetLocale(localeId: string) {\n if (!this._dicts[localeId]) {\n await this.loadLocale(localeId);\n }\n }\n\n private playLine(id: string, index: number) {\n const cc = this.list[id];\n const line = cc ? cc[index] : undefined;\n if (line) {\n if (this._activeCaptionId !== id) {\n this._activeCaptionId = id;\n this._activeCaptionTime = 0;\n this._activeCaptionLine = -1;\n this.renderer?.start();\n }\n if (this._activeCaptionLine !== index) {\n this._activeCaptionLine = index;\n this.renderer?.lineBegin({\n id: this._activeCaptionId,\n ...cc[index],\n });\n }\n } else if (this._activeCaptionId === id && cc) {\n this.renderer?.lineEnd({\n id: this._activeCaptionId,\n ...cc[this._activeCaptionLine],\n });\n this.renderer?.stop();\n this._activeCaptionId = undefined;\n this._activeCaptionLine = -1;\n }\n }\n}\n"],"mappings":"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"}