@caperjs/core 0.2.3 → 0.3.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.
Files changed (175) hide show
  1. package/build/index.mjs +3 -1
  2. package/build/internal/discovery.mjs +1 -1
  3. package/build/internal/manifest.mjs +8 -3
  4. package/build/internal/validate.mjs +3 -1
  5. package/build/plugins/assetTypes.mjs +4 -4
  6. package/build/plugins/caperConfig.mjs +12 -5
  7. package/build/plugins/lists.mjs +29 -9
  8. package/cli/create.mjs +57 -6
  9. package/cli/create.test.mjs +36 -0
  10. package/cli/update.mjs +1 -1
  11. package/lib/{CaptionsPlugin-WPAcfAkx.js → CaptionsPlugin-BLbLl3WB.js} +3 -3
  12. package/lib/{CaptionsPlugin-WPAcfAkx.js.map → CaptionsPlugin-BLbLl3WB.js.map} +1 -1
  13. package/lib/{DataAdapter-DS-twowe.js → DataAdapter-aHSNM_26.js} +12 -7
  14. package/lib/DataAdapter-aHSNM_26.js.map +1 -0
  15. package/lib/{DebugRenderer-D1ryrRYx.js → DebugRenderer-8LjHtBzA.js} +2 -2
  16. package/lib/{DebugRenderer-D1ryrRYx.js.map → DebugRenderer-8LjHtBzA.js.map} +1 -1
  17. package/lib/{DevToolsPlugin-DH7zX7HU.js → DevToolsPlugin-Vrk6aOtS.js} +2 -2
  18. package/lib/{DevToolsPlugin-DH7zX7HU.js.map → DevToolsPlugin-Vrk6aOtS.js.map} +1 -1
  19. package/lib/{GSAPPlugin-BBtRjUqe.js → GSAPPlugin-Hm3F4zdg.js} +3 -3
  20. package/lib/{GSAPPlugin-BBtRjUqe.js.map → GSAPPlugin-Hm3F4zdg.js.map} +1 -1
  21. package/lib/{LayoutPlugin-Co6vcoV4.js → LayoutPlugin-Dpgeawfw.js} +4 -4
  22. package/lib/{LayoutPlugin-Co6vcoV4.js.map → LayoutPlugin-Dpgeawfw.js.map} +1 -1
  23. package/lib/{SpinePlugin-uN641Hmk.js → SpinePlugin-B08yAw1S.js} +690 -793
  24. package/lib/SpinePlugin-B08yAw1S.js.map +1 -0
  25. package/lib/{StatsPlugin-vZQRm6wh.js → StatsPlugin-D2Xa5j97.js} +5 -2
  26. package/lib/StatsPlugin-D2Xa5j97.js.map +1 -0
  27. package/lib/{VoiceOverPlugin-KlZdGj1G.js → VoiceOverPlugin-qtFlqpRn.js} +6 -5
  28. package/lib/VoiceOverPlugin-qtFlqpRn.js.map +1 -0
  29. package/lib/caper.mjs +37 -19
  30. package/lib/caper.mjs.map +1 -1
  31. package/lib/core/Application.d.ts +8 -3
  32. package/lib/core/Application.d.ts.map +1 -1
  33. package/lib/core/Application.test.d.ts +2 -0
  34. package/lib/core/Application.test.d.ts.map +1 -0
  35. package/lib/core/config.d.ts +6 -1
  36. package/lib/core/config.d.ts.map +1 -1
  37. package/lib/core/config.test.d.ts +2 -0
  38. package/lib/core/config.test.d.ts.map +1 -0
  39. package/lib/core/interfaces/IApplication.d.ts +6 -6
  40. package/lib/core/interfaces/IApplication.d.ts.map +1 -1
  41. package/lib/core/interfaces/ICoreSignals.d.ts +2 -1
  42. package/lib/core/interfaces/ICoreSignals.d.ts.map +1 -1
  43. package/lib/display/Camera.test.d.ts +2 -0
  44. package/lib/display/Camera.test.d.ts.map +1 -0
  45. package/lib/display/Entity.d.ts +2 -2
  46. package/lib/display/SceneTransition.test.d.ts +1 -0
  47. package/lib/display/SceneTransition.test.d.ts.map +1 -0
  48. package/lib/display/SpineAnimation.d.ts +3 -3
  49. package/lib/mixins/factory/methods.d.ts.map +1 -1
  50. package/lib/plugins/AssetsPlugin.d.ts.map +1 -1
  51. package/lib/plugins/AssetsPlugin.test.d.ts +2 -0
  52. package/lib/plugins/AssetsPlugin.test.d.ts.map +1 -0
  53. package/lib/plugins/DataAdapter.d.ts.map +1 -1
  54. package/lib/plugins/DataAdapter.test.d.ts +2 -0
  55. package/lib/plugins/DataAdapter.test.d.ts.map +1 -0
  56. package/lib/plugins/FullScreenPlugin.d.ts.map +1 -1
  57. package/lib/plugins/FullScreenPlugin.test.d.ts +2 -0
  58. package/lib/plugins/FullScreenPlugin.test.d.ts.map +1 -0
  59. package/lib/plugins/GSAPPlugin.d.ts +0 -2
  60. package/lib/plugins/GSAPPlugin.d.ts.map +1 -1
  61. package/lib/plugins/GSAPPlugin.test.d.ts +2 -0
  62. package/lib/plugins/GSAPPlugin.test.d.ts.map +1 -0
  63. package/lib/plugins/LookupPlugin.d.ts +6 -1
  64. package/lib/plugins/LookupPlugin.d.ts.map +1 -1
  65. package/lib/plugins/LookupPlugin.test.d.ts +2 -0
  66. package/lib/plugins/LookupPlugin.test.d.ts.map +1 -0
  67. package/lib/plugins/PopupManagerPlugin.d.ts.map +1 -1
  68. package/lib/plugins/PopupManagerPlugin.test.d.ts +1 -0
  69. package/lib/plugins/PopupManagerPlugin.test.d.ts.map +1 -0
  70. package/lib/plugins/SceneManagerPlugin.d.ts +1 -0
  71. package/lib/plugins/SceneManagerPlugin.d.ts.map +1 -1
  72. package/lib/plugins/SceneManagerPlugin.test.d.ts +2 -0
  73. package/lib/plugins/SceneManagerPlugin.test.d.ts.map +1 -0
  74. package/lib/plugins/StatsPlugin.d.ts +1 -0
  75. package/lib/plugins/StatsPlugin.d.ts.map +1 -1
  76. package/lib/plugins/WebEventsPlugin.d.ts.map +1 -1
  77. package/lib/plugins/actions/ActionsPlugin.test.d.ts +2 -0
  78. package/lib/plugins/actions/ActionsPlugin.test.d.ts.map +1 -0
  79. package/lib/plugins/audio/AudioChannel.d.ts.map +1 -1
  80. package/lib/plugins/audio/AudioManagerPlugin.d.ts.map +1 -1
  81. package/lib/plugins/audio/AudioManagerPlugin.test.d.ts +2 -0
  82. package/lib/plugins/audio/AudioManagerPlugin.test.d.ts.map +1 -0
  83. package/lib/plugins/audio/VoiceOverPlugin.d.ts.map +1 -1
  84. package/lib/plugins/captions/CaptionsPlugin.test.d.ts +2 -0
  85. package/lib/plugins/captions/CaptionsPlugin.test.d.ts.map +1 -0
  86. package/lib/plugins/focus/FocusManagerPlugin.d.ts.map +1 -1
  87. package/lib/plugins/focus/FocusManagerPlugin.test.d.ts +2 -0
  88. package/lib/plugins/focus/FocusManagerPlugin.test.d.ts.map +1 -0
  89. package/lib/plugins/input/AbstractControls.d.ts +5 -0
  90. package/lib/plugins/input/AbstractControls.d.ts.map +1 -1
  91. package/lib/plugins/input/Controls.test.d.ts +2 -0
  92. package/lib/plugins/input/Controls.test.d.ts.map +1 -0
  93. package/lib/plugins/input/keyboard/KeyboardContols.d.ts +5 -0
  94. package/lib/plugins/input/keyboard/KeyboardContols.d.ts.map +1 -1
  95. package/lib/plugins/input/touch/VirtualControls.d.ts +6 -0
  96. package/lib/plugins/input/touch/VirtualControls.d.ts.map +1 -1
  97. package/lib/plugins/input/touch/VirtualControls.test.d.ts +2 -0
  98. package/lib/plugins/input/touch/VirtualControls.test.d.ts.map +1 -0
  99. package/lib/{registries-BLrxALZ0.js → registries-m2vKTIih.js} +156 -101
  100. package/lib/registries-m2vKTIih.js.map +1 -0
  101. package/lib/store/Store.d.ts.map +1 -1
  102. package/lib/ui/Button.d.ts +8 -1
  103. package/lib/ui/Button.d.ts.map +1 -1
  104. package/lib/ui/Button.test.d.ts +2 -0
  105. package/lib/ui/Button.test.d.ts.map +1 -0
  106. package/lib/ui/UICanvas.d.ts +10 -1
  107. package/lib/ui/UICanvas.d.ts.map +1 -1
  108. package/lib/ui/UICanvas.test.d.ts +0 -1
  109. package/lib/ui/UICanvas.test.d.ts.map +1 -1
  110. package/lib/utils/color.d.ts.map +1 -1
  111. package/lib/utils/color.test.d.ts +2 -0
  112. package/lib/utils/color.test.d.ts.map +1 -0
  113. package/package.json +1 -1
  114. package/src/core/Application.test.ts +168 -0
  115. package/src/core/Application.ts +37 -27
  116. package/src/core/config.test.ts +79 -0
  117. package/src/core/config.ts +28 -6
  118. package/src/core/interfaces/IApplication.ts +6 -6
  119. package/src/core/interfaces/ICoreSignals.ts +2 -0
  120. package/src/display/Camera.test.ts +40 -0
  121. package/src/display/Camera.ts +3 -3
  122. package/src/display/Entity.ts +2 -2
  123. package/src/display/SceneTransition.test.ts +58 -0
  124. package/src/display/SceneTransition.ts +1 -1
  125. package/src/display/SpineAnimation.ts +4 -4
  126. package/src/mixins/factory/methods.ts +0 -1
  127. package/src/plugins/AssetsPlugin.test.ts +48 -0
  128. package/src/plugins/AssetsPlugin.ts +3 -1
  129. package/src/plugins/DataAdapter.test.ts +32 -0
  130. package/src/plugins/DataAdapter.ts +5 -1
  131. package/src/plugins/FullScreenPlugin.test.ts +48 -0
  132. package/src/plugins/FullScreenPlugin.ts +5 -1
  133. package/src/plugins/GSAPPlugin.test.ts +31 -0
  134. package/src/plugins/GSAPPlugin.ts +1 -4
  135. package/src/plugins/LookupPlugin.test.ts +42 -0
  136. package/src/plugins/LookupPlugin.ts +15 -3
  137. package/src/plugins/PopupManagerPlugin.test.ts +53 -0
  138. package/src/plugins/PopupManagerPlugin.ts +5 -3
  139. package/src/plugins/SceneManagerPlugin.test.ts +76 -0
  140. package/src/plugins/SceneManagerPlugin.ts +21 -11
  141. package/src/plugins/StatsPlugin.ts +8 -0
  142. package/src/plugins/WebEventsPlugin.test.ts +32 -0
  143. package/src/plugins/WebEventsPlugin.ts +2 -0
  144. package/src/plugins/actions/ActionsPlugin.test.ts +68 -0
  145. package/src/plugins/actions/ActionsPlugin.ts +5 -5
  146. package/src/plugins/audio/AudioChannel.test.ts +19 -0
  147. package/src/plugins/audio/AudioChannel.ts +8 -1
  148. package/src/plugins/audio/AudioManagerPlugin.test.ts +41 -0
  149. package/src/plugins/audio/AudioManagerPlugin.ts +3 -2
  150. package/src/plugins/audio/VoiceOverPlugin.ts +1 -0
  151. package/src/plugins/captions/CaptionsPlugin.test.ts +40 -0
  152. package/src/plugins/captions/CaptionsPlugin.ts +1 -1
  153. package/src/plugins/focus/FocusManagerPlugin.test.ts +71 -0
  154. package/src/plugins/focus/FocusManagerPlugin.ts +7 -0
  155. package/src/plugins/input/AbstractControls.ts +6 -0
  156. package/src/plugins/input/Controls.test.ts +149 -0
  157. package/src/plugins/input/keyboard/KeyboardContols.ts +29 -5
  158. package/src/plugins/input/touch/VirtualControls.test.ts +38 -0
  159. package/src/plugins/input/touch/VirtualControls.ts +44 -10
  160. package/src/plugins/spine/SpinePlugin.ts +2 -2
  161. package/src/store/Store.test.ts +15 -0
  162. package/src/store/Store.ts +4 -1
  163. package/src/ui/Button.test.ts +248 -0
  164. package/src/ui/Button.ts +42 -10
  165. package/src/ui/UICanvas.test.ts +109 -6
  166. package/src/ui/UICanvas.ts +41 -3
  167. package/src/utils/color.test.ts +16 -0
  168. package/src/utils/color.ts +2 -1
  169. package/src/utils/platform.ts +1 -1
  170. package/src/version.ts +1 -1
  171. package/lib/DataAdapter-DS-twowe.js.map +0 -1
  172. package/lib/SpinePlugin-uN641Hmk.js.map +0 -1
  173. package/lib/StatsPlugin-vZQRm6wh.js.map +0 -1
  174. package/lib/VoiceOverPlugin-KlZdGj1G.js.map +0 -1
  175. package/lib/registries-BLrxALZ0.js.map +0 -1
package/build/index.mjs CHANGED
@@ -76,7 +76,9 @@ function caperPluginList({ assets = {}, pwa } = {}) {
76
76
  entityListPlugin(),
77
77
  uiListPlugin(),
78
78
  ...assetPlugins,
79
- caperConfigPlugin(),
79
+ // The manifest name reaches build-time validation this way — it is the only
80
+ // place that knows a project overrode it.
81
+ caperConfigPlugin(true, manifestUrl),
80
82
  caperDevHelperPlugin(),
81
83
  ...(pwa ? caperPwaPlugins(pwa) : []),
82
84
  ];
@@ -37,7 +37,7 @@ export async function findTypeScriptFiles(dir) {
37
37
 
38
38
  if (entry.isDirectory()) {
39
39
  await scan(fullPath);
40
- } else if (entry.isFile() && /\.ts?$/.test(entry.name)) {
40
+ } else if (entry.isFile() && /\.tsx?$/.test(entry.name)) {
41
41
  files.push(fullPath);
42
42
  }
43
43
  }
@@ -8,10 +8,15 @@
8
8
  */
9
9
  import fs from 'node:fs';
10
10
  import path from 'node:path';
11
- import { cwd, logger } from './util.mjs';
11
+ import { logger } from './util.mjs';
12
12
 
13
- export function loadManifestBundleNames(manifestUrl = 'assets.json') {
14
- const manifestPath = path.join(process.cwd(), 'public', 'assets', manifestUrl);
13
+ /**
14
+ * `root` is vite's resolved project root — not `process.cwd()`, which is
15
+ * whatever directory the build was launched from. See `internal/discovery.mjs`
16
+ * for the same contract.
17
+ */
18
+ export function loadManifestBundleNames(root, manifestUrl = 'assets.json') {
19
+ const manifestPath = path.join(root, 'public', 'assets', manifestUrl);
15
20
  if (!fs.existsSync(manifestPath)) return null;
16
21
  try {
17
22
  const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
@@ -12,6 +12,8 @@ import { logger } from './util.mjs';
12
12
 
13
13
  export function runBuildTimeValidation({
14
14
  server,
15
+ root,
16
+ manifestUrl,
15
17
  configPath,
16
18
  configObject,
17
19
  scenes,
@@ -21,7 +23,7 @@ export function runBuildTimeValidation({
21
23
  breakpointsName,
22
24
  }) {
23
25
  const warnings = [];
24
- const bundleNames = loadManifestBundleNames();
26
+ const bundleNames = loadManifestBundleNames(root, manifestUrl);
25
27
 
26
28
  // 1. Scene bundle references
27
29
  if (bundleNames && bundleNames.size > 0) {
@@ -9,7 +9,7 @@
9
9
  import fs from 'node:fs';
10
10
  import path from 'node:path';
11
11
  import { loadManifestBundleNames } from '../internal/manifest.mjs';
12
- import { ASSET_DTS_FILE_NAME, debounce, delay, logger } from '../internal/util.mjs';
12
+ import { ASSET_DTS_FILE_NAME, debounce, delay, env, logger } from '../internal/util.mjs';
13
13
 
14
14
  export { loadManifestBundleNames };
15
15
 
@@ -399,12 +399,12 @@ export function assetTypesPlugin(manifestUrl = 'assets.json') {
399
399
 
400
400
  return {
401
401
  name: 'vite-plugin-asset-types',
402
- config(config) {
403
- ispPwaEnabled = config.plugins.some((p) => p.name === 'vite-plugin-pwa');
404
- },
405
402
  configResolved(config) {
406
403
  publicDir = config.publicDir;
407
404
  root = config.root;
405
+ // Resolved, so the list is flat: in the `config` hook `caper()` is still
406
+ // one nested array and vite-plugin-pwa is never found at the top level.
407
+ ispPwaEnabled = config.plugins.some((p) => p.name === 'vite-plugin-pwa');
408
408
  },
409
409
  async buildStart() {
410
410
  // a short delay to allow assetpack to generate the manifest
@@ -93,7 +93,7 @@ async function validateCaperConfig(server, root) {
93
93
 
94
94
  // write a debounce function
95
95
 
96
- export function caperConfigPlugin(isProject = true) {
96
+ export function caperConfigPlugin(isProject = true, manifestUrl = 'assets.json') {
97
97
  // vite's resolved project root. Everything below resolves against this rather
98
98
  // than process.cwd(), so `vite --root elsewhere` and monorepo invocations from
99
99
  // a parent directory find the right caper.config.ts and src/ tree.
@@ -228,6 +228,8 @@ export function caperConfigPlugin(isProject = true) {
228
228
  // defaultScene pointing at a non-existent scene, duplicate IDs).
229
229
  runBuildTimeValidation({
230
230
  server,
231
+ root,
232
+ manifestUrl,
231
233
  configPath,
232
234
  configObject,
233
235
  scenes,
@@ -444,6 +446,7 @@ declare module '@caperjs/core' {
444
446
  const pluginsDir = path.resolve(root, 'src/plugins');
445
447
  const popupsDir = path.resolve(root, 'src/popups');
446
448
  const entitiesDir = path.resolve(root, 'src/entities');
449
+ const uisDir = path.resolve(root, 'src/ui');
447
450
  const localesDir = path.resolve(root, 'src/locales');
448
451
 
449
452
  const handleFileChange = async (file) => {
@@ -451,10 +454,11 @@ declare module '@caperjs/core' {
451
454
  const isPlugin = file.startsWith(pluginsDir);
452
455
  const isPopup = file.startsWith(popupsDir);
453
456
  const isEntity = file.startsWith(entitiesDir);
457
+ const isUI = file.startsWith(uisDir);
454
458
  const isLocale = file.startsWith(localesDir);
455
459
  const isConfig = file === configPath;
456
460
 
457
- if (!isScene && !isPlugin && !isPopup && !isEntity && !isLocale && !isConfig) return;
461
+ if (!isScene && !isPlugin && !isPopup && !isEntity && !isUI && !isLocale && !isConfig) return;
458
462
 
459
463
  const msg = isScene
460
464
  ? 'Scene file changed'
@@ -464,9 +468,11 @@ declare module '@caperjs/core' {
464
468
  ? 'Popup file changed'
465
469
  : isEntity
466
470
  ? 'Entity file changed'
467
- : isLocale
468
- ? 'Locale file changed'
469
- : 'Config file changed';
471
+ : isUI
472
+ ? 'UI file changed'
473
+ : isLocale
474
+ ? 'Locale file changed'
475
+ : 'Config file changed';
470
476
  await build(`${msg}, regenerating types...`, server);
471
477
  };
472
478
 
@@ -475,6 +481,7 @@ declare module '@caperjs/core' {
475
481
  server.watcher.add(pluginsDir);
476
482
  server.watcher.add(popupsDir);
477
483
  server.watcher.add(entitiesDir);
484
+ server.watcher.add(uisDir);
478
485
  server.watcher.add(localesDir);
479
486
 
480
487
  server.watcher.on('change', handleFileChange);
@@ -9,14 +9,11 @@
9
9
  import path from 'node:path';
10
10
  import {
11
11
  discoverEntities,
12
- discoverLocaleKeys,
13
12
  discoverPlugins,
14
13
  discoverPopups,
15
14
  discoverScenes,
16
15
  discoverUIs,
17
16
  } from '../internal/discovery.mjs';
18
- import { logger } from '../internal/util.mjs';
19
- import { loadManifestBundleNames } from '../internal/manifest.mjs';
20
17
 
21
18
  export function createClassListPlugin({ virtualModuleId, discoverFn, exportName, pluginName }) {
22
19
  // vite's resolved project root, captured for the discovery pass. See
@@ -32,7 +29,15 @@ export function createClassListPlugin({ virtualModuleId, discoverFn, exportName,
32
29
 
33
30
  const generate = (items) => {
34
31
  const staticItems = items.filter((i) => i.module && !i.module.isFunction);
35
- const imports = staticItems.map((i) => `import ${extractClassName(i)} from '${i.module}';`);
32
+ // Basenames alone collide when two files share a name in different
33
+ // directories (e.g. src/entities/a/Foo.ts and src/entities/b/Foo.ts),
34
+ // producing two `import Foo from '...'` lines — a duplicate-binding
35
+ // syntax error. Suffix with the item's index in the static-import list
36
+ // to keep identifiers unique while staying stable and readable, and
37
+ // look them up from the same map when emitting the object literal so
38
+ // the import and its `module:` reference always agree.
39
+ const importNames = new Map(staticItems.map((i, index) => [i, `${extractClassName(i)}_${index}`]));
40
+ const imports = staticItems.map((i) => `import ${importNames.get(i)} from '${i.module}';`);
36
41
 
37
42
  return `
38
43
  ${imports.join('\n')}
@@ -41,7 +46,7 @@ export function createClassListPlugin({ virtualModuleId, discoverFn, exportName,
41
46
  .map((item) => {
42
47
  const moduleExpr =
43
48
  item.module && !item.module.isFunction
44
- ? extractClassName(item)
49
+ ? importNames.get(item)
45
50
  : (item.module?.toString?.() ?? `() => import('${item.importPath}')`);
46
51
  return `{
47
52
  id: '${item.id}',
@@ -157,7 +162,15 @@ export function pluginListPlugin(isProject = true) {
157
162
  // npm static imports would collide on class-name derivation from the pkg
158
163
  // path, so only local plugins support `dynamic = false`. npm packages are
159
164
  // always dynamic.
160
- const imports = staticPlugins.map((p) => `import ${extractClassName(p)} from '${p.module}';`);
165
+ //
166
+ // Basenames alone collide when two files share a name in different
167
+ // directories, producing two `import Foo from '...'` lines — a
168
+ // duplicate-binding syntax error. Suffix with the item's index in the
169
+ // static-import list to keep identifiers unique while staying stable
170
+ // and readable, and look them up from the same map when emitting the
171
+ // object literal so the import and its `module:` reference always agree.
172
+ const importNames = new Map(staticPlugins.map((p, index) => [p, `${extractClassName(p)}_${index}`]));
173
+ const imports = staticPlugins.map((p) => `import ${importNames.get(p)} from '${p.module}';`);
161
174
 
162
175
  return `
163
176
  ${imports.join('\n')}
@@ -166,7 +179,7 @@ export function pluginListPlugin(isProject = true) {
166
179
  .map((plugin) => {
167
180
  const moduleExpr =
168
181
  plugin.module && !plugin.module.isFunction && plugin.isLocal
169
- ? extractClassName(plugin)
182
+ ? importNames.get(plugin)
170
183
  : (plugin.module?.toString?.() ?? `() => import('${plugin.importPath}')`);
171
184
  return `{
172
185
  name: '${plugin.name}',
@@ -223,7 +236,14 @@ export function sceneListPlugin(isProject = true) {
223
236
  // extract non function scenes from the list
224
237
  const nonFunctionScenes = scenes.filter((scene) => !scene.module.isFunction);
225
238
 
226
- const imports = nonFunctionScenes.map((scene) => `import ${extractClassName(scene)} from '${scene.module}';`);
239
+ // Basenames alone collide when two files share a name in different
240
+ // directories, producing two `import Foo from '...'` lines — a
241
+ // duplicate-binding syntax error. Suffix with the item's index in the
242
+ // static-import list to keep identifiers unique while staying stable
243
+ // and readable, and look them up from the same map when emitting the
244
+ // object literal so the import and its `module:` reference always agree.
245
+ const importNames = new Map(nonFunctionScenes.map((scene, index) => [scene, `${extractClassName(scene)}_${index}`]));
246
+ const imports = nonFunctionScenes.map((scene) => `import ${importNames.get(scene)} from '${scene.module}';`);
227
247
 
228
248
  const result = `
229
249
  ${imports.join('\n')}
@@ -233,7 +253,7 @@ export function sceneListPlugin(isProject = true) {
233
253
  (scene) => `{
234
254
  id: '${scene.id}',
235
255
  active: ${scene.active},
236
- module: ${scene.module.isFunction ? scene.module.toString() : extractClassName(scene)},
256
+ module: ${scene.module.isFunction ? scene.module.toString() : importNames.get(scene)},
237
257
  debugLabel: ${JSON.stringify(scene.debugLabel)},
238
258
  debugGroup: ${JSON.stringify(scene.debugGroup)},
239
259
  debugOrder: ${scene.debugOrder},
package/cli/create.mjs CHANGED
@@ -88,6 +88,60 @@ function getFiles(dirPath) {
88
88
  return files;
89
89
  }
90
90
 
91
+ /**
92
+ * Injects wizard-selected plugin config entries into a caper.config.ts file's
93
+ * `plugins:` array, whether that array is currently empty or already has entries.
94
+ *
95
+ * @param {string} configContents
96
+ * @param {string[]} pluginConfigs
97
+ * @returns {string}
98
+ */
99
+ export function injectPluginsIntoConfig(configContents, pluginConfigs) {
100
+ // Empty array: replace it wholesale with the new entries.
101
+ if (/plugins:\s*\[\s*\]/.test(configContents)) {
102
+ return configContents.replace(
103
+ /plugins:\s*\[\s*\]/,
104
+ `plugins: [\n ${pluginConfigs.join(',\n ')}\n ]`,
105
+ );
106
+ }
107
+
108
+ // Non-empty array: find the `plugins:` array's matching brackets (which may
109
+ // contain nested arrays, e.g. `['name', {...}]` entries) and append the new
110
+ // entries alongside the existing ones.
111
+ const keyMatch = configContents.match(/plugins:\s*\[/);
112
+ if (!keyMatch) {
113
+ return configContents;
114
+ }
115
+
116
+ const openBracketIndex = keyMatch.index + keyMatch[0].length - 1;
117
+ let depth = 0;
118
+ let closeBracketIndex = -1;
119
+ for (let i = openBracketIndex; i < configContents.length; i++) {
120
+ if (configContents[i] === '[') depth++;
121
+ else if (configContents[i] === ']') {
122
+ depth--;
123
+ if (depth === 0) {
124
+ closeBracketIndex = i;
125
+ break;
126
+ }
127
+ }
128
+ }
129
+ if (closeBracketIndex === -1) {
130
+ return configContents;
131
+ }
132
+
133
+ const existingEntries = configContents.slice(openBracketIndex + 1, closeBracketIndex).trim();
134
+ const allEntries = existingEntries
135
+ ? `${existingEntries},\n ${pluginConfigs.join(',\n ')}`
136
+ : pluginConfigs.join(',\n ');
137
+
138
+ return (
139
+ configContents.slice(0, openBracketIndex) +
140
+ `[\n ${allEntries}\n ]` +
141
+ configContents.slice(closeBracketIndex + 1)
142
+ );
143
+ }
144
+
91
145
  /**
92
146
  * @param {string} template
93
147
  * @param {string} applicationNameForPkg
@@ -180,11 +234,8 @@ function write_template_files(cwd, template, applicationNameForPkg, applicationN
180
234
  return `['${shortName}', { autoLoad: false }]`;
181
235
  });
182
236
 
183
- // Replace empty plugins array with configured plugins
184
- configContents = configContents.replace(
185
- /plugins:\s*\[\s*\]/,
186
- `plugins: [\n ${pluginConfigs.join(',\n ')}\n ]`,
187
- );
237
+ // Inject the configured plugins into the plugins array
238
+ configContents = injectPluginsIntoConfig(configContents, pluginConfigs);
188
239
  }
189
240
 
190
241
  fs.writeFileSync(configPath, configContents.replace(/__APPLICATION_NAME__/g, applicationName), 'utf-8');
@@ -304,7 +355,7 @@ export async function create(cwd = '.', packageManagerOverride) {
304
355
  });
305
356
 
306
357
  if (!appName) {
307
- appName = name;
358
+ appName = defaultName;
308
359
  }
309
360
 
310
361
  // derive an application name from the project name by camel casing it
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { injectPluginsIntoConfig } from './create.mjs';
3
+
4
+ describe('injectPluginsIntoConfig', () => {
5
+ it('inserts plugins into an empty array', () => {
6
+ const configContents = `export default {\n plugins: [],\n};\n`;
7
+ const pluginConfigs = [`['rollbar', { autoLoad: false }]`];
8
+
9
+ const result = injectPluginsIntoConfig(configContents, pluginConfigs);
10
+
11
+ expect(result).toContain(`plugins: [\n ['rollbar', { autoLoad: false }]\n ]`);
12
+ });
13
+
14
+ it('appends plugins alongside an existing non-empty array', () => {
15
+ const configContents = `export default {\n plugins: [['existing', { autoLoad: false }]],\n};\n`;
16
+ const pluginConfigs = [`['rollbar', { autoLoad: false }]`];
17
+
18
+ const result = injectPluginsIntoConfig(configContents, pluginConfigs);
19
+
20
+ expect(result).toContain(`['existing', { autoLoad: false }]`);
21
+ expect(result).toContain(`['rollbar', { autoLoad: false }]`);
22
+ // both entries should end up inside a single well-formed array
23
+ expect(result).toMatch(/plugins: \[[\s\S]*existing[\s\S]*rollbar[\s\S]*\]/);
24
+ });
25
+
26
+ it('appends plugins alongside an existing multiline array', () => {
27
+ const configContents = `export default {\n plugins: [\n ['existing', { autoLoad: false }],\n ],\n};\n`;
28
+ const pluginConfigs = [`['rollbar', { autoLoad: false }]`, `['rive', { autoLoad: false }]`];
29
+
30
+ const result = injectPluginsIntoConfig(configContents, pluginConfigs);
31
+
32
+ expect(result).toContain(`['existing', { autoLoad: false }]`);
33
+ expect(result).toContain(`['rollbar', { autoLoad: false }]`);
34
+ expect(result).toContain(`['rive', { autoLoad: false }]`);
35
+ });
36
+ });
package/cli/update.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {execSync} from 'node:child_process';
3
3
  import {package_manager} from './utils.mjs';
4
4
 
5
- const install_path = 'github:anthonysapp/caper';
5
+ const install_path = '@caperjs/core@latest';
6
6
 
7
7
  export async function update() {
8
8
  return execSync(`${package_manager} install ${install_path}`);
@@ -1,4 +1,4 @@
1
- import { Dt as e, H as t, bt as n, f as r, jt as i } from "./registries-BLrxALZ0.js";
1
+ import { Dt as e, H as t, bt as n, f as r, jt as i } from "./registries-m2vKTIih.js";
2
2
  import { ensurePadding as a } from "./caper.mjs";
3
3
  import { Assets as o, Container as s, Texture as c } from "pixi.js";
4
4
  import { gsap as l } from "gsap";
@@ -200,7 +200,7 @@ var m = class extends t {
200
200
  return this._locale === e ? this._locale : (this._activeCaptionId && this.stopCaption(this._activeCaptionId), this._activeCaptionId = void 0, await this._loadAndSetLocale(e), this._locale = e, this._locale);
201
201
  }
202
202
  async loadLocale(t) {
203
- if (this._locale === "localeId") return;
203
+ if (this._dicts[t]) return;
204
204
  let r = this._options.files.find((e) => t === e.id);
205
205
  if (!r) {
206
206
  e.error(`i18n:: Could not find locale file for ${t}`);
@@ -275,4 +275,4 @@ var m = class extends t {
275
275
  //#endregion
276
276
  export { m as CaptionsPlugin };
277
277
 
278
- //# sourceMappingURL=CaptionsPlugin-WPAcfAkx.js.map
278
+ //# sourceMappingURL=CaptionsPlugin-BLbLl3WB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CaptionsPlugin-WPAcfAkx.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/Container';\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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"}
1
+ {"version":3,"file":"CaptionsPlugin-BLbLl3WB.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/Container';\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._dicts[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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"}
@@ -1,4 +1,4 @@
1
- import { H as e, K as t, Ut as n, lt as r } from "./registries-BLrxALZ0.js";
1
+ import { H as e, K as t, Ut as n, lt as r } from "./registries-m2vKTIih.js";
2
2
  //#region src/plugins/DataAdapter.ts
3
3
  var i = /* @__PURE__ */ n({
4
4
  DataAdapter: () => o,
@@ -15,7 +15,7 @@ var o = class extends e {
15
15
  return ["onDataChange"];
16
16
  }
17
17
  destroy() {
18
- this.data = {};
18
+ this.data = {}, super.destroy();
19
19
  }
20
20
  initialize(e) {
21
21
  this.namespace = e?.namespace || this.app.appName, this.data = e?.initial || {}, this.backupKeys = e?.backupKeys || [], this.backupAll = e?.backupAll || !1, this.overrideWithLocalStorage = e?.overrideWithLocalStorage !== !1, (this.backupAll || this.backupKeys.length > 0) && (this.overrideWithLocalStorage && this.restoreFromLocalStorage(this.backupKeys), this.backupToLocalStorage(this.backupKeys));
@@ -50,10 +50,15 @@ var o = class extends e {
50
50
  return r?.length > 0 && (i = r + n + t), this.set({ [e]: i }), i;
51
51
  }
52
52
  clear(e) {
53
- e === void 0 ? (this.data = {}, localStorage.clear(), this.onDataChange.emit({
54
- key: e,
55
- clear: !0
56
- })) : (delete this.data[e], localStorage.removeItem(`${this.namespace}-${e}`), this.onDataChange.emit({ clear: !0 }));
53
+ if (e === void 0) {
54
+ this.data = {};
55
+ let t = `${this.namespace}-`;
56
+ for (let e of Object.keys(localStorage).filter((e) => e.startsWith(t))) localStorage.removeItem(e);
57
+ this.onDataChange.emit({
58
+ key: e,
59
+ clear: !0
60
+ });
61
+ } else delete this.data[e], localStorage.removeItem(`${this.namespace}-${e}`), this.onDataChange.emit({ clear: !0 });
57
62
  }
58
63
  snapshot(e) {
59
64
  return JSON.parse(JSON.stringify(e === void 0 ? this.data : this.data[e]));
@@ -81,4 +86,4 @@ var o = class extends e {
81
86
  //#endregion
82
87
  export { i as n, a as r, o as t };
83
88
 
84
- //# sourceMappingURL=DataAdapter-DS-twowe.js.map
89
+ //# sourceMappingURL=DataAdapter-aHSNM_26.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataAdapter-aHSNM_26.js","names":[],"sources":["../src/plugins/DataAdapter.ts"],"sourcesContent":["import { Signal } from '../signals';\nimport { AppTypeOverrides, deepMerge, DeepPartial } from '../utils';\nimport { Plugin } from './Plugin';\n\nexport type DataSchema = {\n [key: string]: any;\n};\n\n/**\n * Interface for the options of the DataAdapter.\n */\nexport interface IDataAdapterOptions {\n initial: Partial<AppTypeOverrides['Data']>;\n /**\n * The namespace to use for the keys in local storage.\n */\n namespace: string;\n /**\n * Whether to override the data with the data from local storage.\n */\n overrideWithLocalStorage: boolean;\n /**\n * Whether to backup all data to local storage.\n */\n backupAll: boolean;\n /**\n * The keys to backup to local storage.\n */\n backupKeys: Array<keyof AppTypeOverrides['Data']>;\n}\n\nexport interface DataChangeSignalDetail {\n key?: any;\n value?: any;\n restore?: boolean;\n clear?: boolean;\n}\n\ntype DataAdapterType = AppTypeOverrides['Data'];\n\nexport interface IDataAdapter {\n get(): DataAdapterType;\n get<K extends keyof DataAdapterType>(key: K): DataAdapterType[K] | undefined;\n set<K extends keyof DataAdapterType>(key: K, data: DataAdapterType[K]): DataAdapterType;\n set(data: DeepPartial<DataAdapterType>, merge?: boolean): DataAdapterType;\n clear(): void;\n clear<K extends keyof DataAdapterType>(key: K): void;\n increment<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends number ? P : never }[keyof DataAdapterType],\n >(\n key: K,\n amount?: number,\n ): DataAdapterType[K];\n concat<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends any[] ? P : never }[keyof DataAdapterType],\n >(\n key: K,\n value: DataAdapterType[K] extends (infer E)[] ? E | E[] : never,\n ): DataAdapterType[K];\n append<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends string ? P : never }[keyof DataAdapterType],\n >(\n key: K,\n value: string,\n separator?: string,\n ): DataAdapterType[K];\n snapshot(): DataAdapterType;\n snapshot<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K];\n onDataChange: Signal<(detail: DataChangeSignalDetail) => void>;\n clearOnResume?: boolean;\n}\n\nexport function defineData<T extends DataSchema>(data: T): T {\n return data;\n}\n\n/**\n * An in-memory game-data plugin with optional localStorage backup.\n *\n * Not `IStorageCapability` — its API (`get`/`set`/`increment`/...) is richer\n * than the generic save/load contract. Accessed directly via `app.data`.\n */\nexport class DataAdapter extends Plugin<Partial<IDataAdapterOptions>> implements IDataAdapter {\n public data: DataAdapterType;\n\n public onDataChange: Signal<(detail: DataChangeSignalDetail) => void> = new Signal();\n\n private backupKeys: Array<keyof DataAdapterType> = [];\n private backupAll: boolean = false;\n private namespace: string = '';\n private overrideWithLocalStorage: boolean = true;\n\n constructor(id: string = 'data') {\n super(id);\n }\n\n public getCoreSignals(): string[] {\n return ['onDataChange'];\n }\n\n destroy() {\n this.data = {} as DataAdapterType;\n super.destroy();\n }\n\n public initialize(options?: Partial<IDataAdapterOptions>): void {\n this.namespace = options?.namespace || this.app.appName;\n this.data = (options?.initial as DataAdapterType) || ({} as DataAdapterType);\n this.backupKeys = options?.backupKeys || [];\n this.backupAll = options?.backupAll || false;\n this.overrideWithLocalStorage = options?.overrideWithLocalStorage === false ? false : true;\n\n if (this.backupAll || this.backupKeys.length > 0) {\n if (this.overrideWithLocalStorage) {\n this.restoreFromLocalStorage(this.backupKeys);\n }\n this.backupToLocalStorage(this.backupKeys);\n }\n }\n\n set<K extends keyof DataAdapterType>(key: K, data: DataAdapterType[K]): DataAdapterType;\n set(data: DeepPartial<DataAdapterType>, merge?: boolean): DataAdapterType;\n set<K extends keyof DataAdapterType>(\n keyOrData: K | DeepPartial<DataAdapterType>,\n dataOrMerge?: DataAdapterType[K] | boolean,\n ): DataAdapterType {\n if (typeof keyOrData === 'string' || typeof keyOrData === 'number' || typeof keyOrData === 'symbol') {\n const key = keyOrData;\n const data = dataOrMerge as DataAdapterType[K];\n\n this.data[key] = data;\n if (this.backupAll || this.backupKeys.includes(key)) {\n this.backupToLocalStorage([key]);\n }\n this.onDataChange.emit({ key, value: data });\n return this.data;\n }\n\n const data = keyOrData as DeepPartial<DataAdapterType>;\n const merge = (dataOrMerge as boolean) ?? true;\n\n if (merge) {\n this.data = deepMerge({ ...this.data }, data);\n } else {\n this.data = data as DataAdapterType;\n }\n\n if (this.backupAll || this.backupKeys.length > 0) {\n this.backupToLocalStorage(this.backupKeys);\n }\n\n this.onDataChange.emit({\n key: Object.keys(data)?.length === 1 ? Object.keys(data)[0] : Object.keys(data),\n value: data[Object.keys(data)[0]] as DataAdapterType[keyof DataAdapterType],\n });\n\n return this.data;\n }\n\n get(): DataAdapterType;\n get<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K] | undefined;\n get<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K] | DataAdapterType | undefined {\n if (key === undefined) {\n return this.data;\n }\n return this.data[key];\n }\n\n increment<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends number ? P : never }[keyof DataAdapterType],\n >(key: K, amount: number = 1): DataAdapterType[K] {\n const currentValue = this.data[key] || 0;\n const newValue = currentValue + amount;\n this.set({ [key]: newValue } as DeepPartial<DataAdapterType>);\n return newValue as DataAdapterType[K];\n }\n\n concat<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends any[] ? P : never }[keyof DataAdapterType],\n >(key: K, value: DataAdapterType[K] extends (infer E)[] ? E | E[] : never): DataAdapterType[K] {\n const currentValue = this.data[key];\n const newValue = [...currentValue, ...(Array.isArray(value) ? value : [value])];\n this.set({ [key]: newValue } as DeepPartial<DataAdapterType>);\n return newValue as DataAdapterType[K];\n }\n\n append<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends string ? P : never }[keyof DataAdapterType],\n >(key: K, value: string, separator: string = ''): DataAdapterType[K] {\n const currentValue = this.data[key];\n let newValue = value;\n if ((currentValue as string)?.length > 0) {\n newValue = currentValue + separator + value;\n }\n this.set({ [key]: newValue } as DeepPartial<DataAdapterType>);\n return newValue as DataAdapterType[K];\n }\n\n clear(): void;\n clear<K extends keyof DataAdapterType>(key?: K): void {\n if (key === undefined) {\n this.data = {} as DataAdapterType;\n const prefix = `${this.namespace}-`;\n for (const storageKey of Object.keys(localStorage).filter((k) => k.startsWith(prefix))) {\n localStorage.removeItem(storageKey);\n }\n this.onDataChange.emit({ key, clear: true });\n } else {\n delete this.data[key];\n localStorage.removeItem(`${this.namespace}-${key as string}`);\n this.onDataChange.emit({ clear: true });\n }\n }\n\n snapshot(): DataAdapterType;\n snapshot<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K];\n snapshot<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K] | DataAdapterType {\n if (key === undefined) {\n return JSON.parse(JSON.stringify(this.data));\n }\n return JSON.parse(JSON.stringify(this.data[key]));\n }\n\n private backupToLocalStorage(keys?: Array<keyof DataAdapterType>): void {\n const dataToBackup =\n keys && keys?.length > 0 ? Object.fromEntries(keys.map((key) => [key, this.data[key]])) : this.data;\n\n for (const key in dataToBackup) {\n localStorage.setItem(`${this.namespace}-${key}`, JSON.stringify(dataToBackup[key]));\n }\n }\n\n private restoreFromLocalStorage(keys?: Array<keyof DataAdapterType>): void {\n const keysToRestore = keys && keys?.length > 0 ? keys : (Object.keys(this.data) as Array<keyof DataAdapterType>);\n keysToRestore.forEach((key) => {\n try {\n const loadedData = localStorage.getItem(`${this.namespace}-${String(key)}`);\n if (loadedData !== null) {\n try {\n const parsedData = JSON.parse(loadedData);\n this.data[key] = parsedData;\n } catch (parseError) {\n console.warn(\n `Failed to parse data for key \"${String(key)}\" in namespace \"${this.namespace}\". Using default value.`,\n );\n }\n }\n } catch (storageError) {\n console.error(\n `Error accessing localStorage for key \"${String(key)}\" in namespace \"${this.namespace}\":`,\n storageError,\n );\n }\n });\n this.onDataChange.emit({ restore: true });\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Ut as e } from "./registries-BLrxALZ0.js";
1
+ import { Ut as e } from "./registries-m2vKTIih.js";
2
2
  import { BigPool as t, Bounds as n, Container as r, Graphics as i, Rectangle as a } from "pixi.js";
3
3
  //#region ../../node_modules/.pnpm/yoga-layout@3.2.1/node_modules/yoga-layout/dist/binaries/yoga-wasm-base64-esm.js
4
4
  var o = (() => {
@@ -1382,4 +1382,4 @@ var se = class extends r {
1382
1382
  //#endregion
1383
1383
  export { s as a, d as c, g as d, _ as f, C as h, re as i, f as l, x as m, w as n, c as o, b as p, E as r, u as s, ce as t, h as u };
1384
1384
 
1385
- //# sourceMappingURL=DebugRenderer-D1ryrRYx.js.map
1385
+ //# sourceMappingURL=DebugRenderer-8LjHtBzA.js.map