@energy8platform/shell 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/pixi.d.ts CHANGED
@@ -452,6 +452,11 @@ interface ShellHost {
452
452
  setVolumeRefresh(fn: ((key: VolumeKey, value: number) => void) | null): void;
453
453
  /** Logic-bearing actions invoked by renderer controls. */
454
454
  readonly actions: ShellActions;
455
+ /** Re-show the replay summary modal through the controller (keeps its OverlayHandle in sync).
456
+ * Used as the modal's own reopen callback after START REPLAY, so a renderer never re-pushes a
457
+ * replay modal behind the controller's back (which would strand `overlay` and dead-end the
458
+ * next close). */
459
+ openReplay(opts: ReplayModalOptions): void;
455
460
  }
456
461
  /** Every state-changing thing a control can do. Each runs logic in the controller, emits the
457
462
  * matching event, and triggers a re-render. Renderers MUST route input through these. */
@@ -513,7 +518,7 @@ declare class ShellController extends EventEmitter<ShellEvents> implements Shell
513
518
  tokens: ShellTokens;
514
519
  layout: ShellLayoutMode;
515
520
  soundOn: boolean;
516
- readonly engineVersion = "0.6.3";
521
+ readonly engineVersion = "0.6.5";
517
522
  readonly actions: ShellActions;
518
523
  private renderer;
519
524
  private i18n;
@@ -595,7 +600,7 @@ interface I18n {
595
600
  declare function createI18n(opts: I18nOptions): I18n;
596
601
 
597
602
  /** The @energy8platform/shell package version, stamped into the game-info footer. */
598
- declare const PACKAGE_VERSION = "0.6.3";
603
+ declare const PACKAGE_VERSION = "0.6.5";
599
604
 
600
605
  /** A shell: the renderer-agnostic controller plus the surface facade (safeArea/barHeight/setVisible)
601
606
  * an embedding host reads. `createShell`, `createGameShell` and `createPixiShell` all return this. */
@@ -672,10 +677,6 @@ declare class PixiRenderer implements ShellRenderer {
672
677
  closeLayer(): void;
673
678
  private clearLayer;
674
679
  fitModals(): void;
675
- /** Replay's reopen path: a replay modal can rebuild itself (e.g. after a replay completes). It is
676
- * routed back through the controller-equivalent open flow so the layer stack + backdrop stay in
677
- * sync — mirrors PixiGameShell.openReplay (push a fresh replay modal). */
678
- private openReplayInternal;
679
680
  /** Snapshot the scene behind the modal layer and blur it — the Pixi analogue of the overlay's
680
681
  * `backdrop-filter: blur(20px) saturate(120%)`. Static (captured at open time): the game is paused
681
682
  * under a modal, so a live re-blur each frame isn't worth the cost. */
package/dist/pixi.esm.js CHANGED
@@ -1219,12 +1219,19 @@ function normalizeLang(code) {
1219
1219
  return (LANG_SET.has(base) ? base : 'en');
1220
1220
  }
1221
1221
  function createI18n(opts) {
1222
- // Social is the `en-social` pseudo-locale: it rewrites the English source. Non-English locales are
1223
- // authored social-safe already, so `socialize` only runs on the English source string.
1222
+ // Social is the `en-social` pseudo-locale: it rewrites the English source into social-safe
1223
+ // vocabulary. The replacement dictionary only exists for English, so social mode FORCES English
1224
+ // the requested `language` is ignored, matching the `isSocial` contract ("…derived from English…
1225
+ // regardless of `language`"). Rendering a non-English locale in social mode would leak untranslated
1226
+ // restricted terms, so we never do it.
1227
+ if (opts.isSocial) {
1228
+ const t = (src) => socialize(src);
1229
+ return { lang: 'en', t };
1230
+ }
1224
1231
  const lang = normalizeLang(opts.language);
1225
1232
  const t = (src) => {
1226
1233
  if (lang === 'en')
1227
- return opts.isSocial ? socialize(src) : src;
1234
+ return src;
1228
1235
  return opts.messages?.[lang]?.[src] ?? LOCALES[lang]?.[src] ?? src;
1229
1236
  };
1230
1237
  return { lang, t };
@@ -1447,7 +1454,7 @@ class KeyboardController {
1447
1454
 
1448
1455
  // AUTO-GENERATED by scripts/gen-version.mjs — do not edit. Mirrors package.json "version".
1449
1456
  /** The @energy8platform/shell package version, stamped into the game-info footer. */
1450
- const PACKAGE_VERSION = '0.6.3';
1457
+ const PACKAGE_VERSION = '0.6.5';
1451
1458
 
1452
1459
  /** Apply defaults to the raw config (the mount target lives on the renderer, not here). */
1453
1460
  function resolveConfig(config) {
@@ -1925,6 +1932,11 @@ function makeText(str, opts) {
1925
1932
  if (opts.wrapWidth != null) {
1926
1933
  style.wordWrap = true;
1927
1934
  style.wordWrapWidth = opts.wrapWidth;
1935
+ // CJK (and any long unbroken run) has no spaces to wrap on — without breakWords the line
1936
+ // overflows the wrap width instead of wrapping. This is the single shell text helper (How to
1937
+ // Play, disclaimer, Game Info section titles, mode table, win messages, buy-bonus cards), so
1938
+ // one flag fixes wrapping everywhere.
1939
+ style.breakWords = true;
1928
1940
  }
1929
1941
  if (opts.lineHeight != null)
1930
1942
  style.lineHeight = opts.lineHeight;
@@ -5984,7 +5996,7 @@ class PixiRenderer {
5984
5996
  layer = openAutoplayPicker(this.ctx);
5985
5997
  break;
5986
5998
  case 'replay':
5987
- layer = buildReplayModal(this.ctx, req.opts, () => this.openReplayInternal(req.opts));
5999
+ layer = buildReplayModal(this.ctx, req.opts, () => this.host.openReplay(req.opts));
5988
6000
  break;
5989
6001
  case 'modal':
5990
6002
  layer = buildModal(this.ctx, req.opts);
@@ -6058,15 +6070,6 @@ class PixiRenderer {
6058
6070
  fitModals() {
6059
6071
  this.currentLayer?.fit?.();
6060
6072
  }
6061
- /** Replay's reopen path: a replay modal can rebuild itself (e.g. after a replay completes). It is
6062
- * routed back through the controller-equivalent open flow so the layer stack + backdrop stay in
6063
- * sync — mirrors PixiGameShell.openReplay (push a fresh replay modal). */
6064
- openReplayInternal(opts) {
6065
- if (this.destroyed)
6066
- return;
6067
- const layer = buildReplayModal(this.ctx, opts, () => this.openReplayInternal(opts));
6068
- this.pushLayer(layer);
6069
- }
6070
6073
  // ── frosted backdrop ─────────────────────────────────────────────────────────
6071
6074
  /** Snapshot the scene behind the modal layer and blur it — the Pixi analogue of the overlay's
6072
6075
  * `backdrop-filter: blur(20px) saturate(120%)`. Static (captured at open time): the game is paused
@@ -6163,6 +6166,7 @@ class PixiRenderer {
6163
6166
  get layout() { return host.layout; },
6164
6167
  get soundOn() { return host.soundOn; },
6165
6168
  get actions() { return host.actions; },
6169
+ openReplay: (opts) => host.openReplay(opts),
6166
6170
  t: (s) => host.t(s),
6167
6171
  formatCurrency: (n, win) => host.formatCurrency(n, win),
6168
6172
  emit: host.emit.bind(host),