@energy8platform/shell 0.4.1 → 0.6.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.
package/dist/index.d.ts CHANGED
@@ -16,7 +16,14 @@ declare class EventEmitter<TEvents extends {}> {
16
16
  removeAllListeners(event?: keyof TEvents): this;
17
17
  }
18
18
 
19
- type ShellMode = 'base' | 'freeSpins' | 'replay';
19
+ /** `freeSpins` and `bonus` are the SAME bar layout (host-driven hero + Total Win); `freeSpins` is
20
+ * kept as a back-compat alias for the common case (its readout is derived current/total), while
21
+ * `bonus` pairs with `setBonus()` to show a game-supplied label + value (adventure, hold-and-spin,
22
+ * respins — anything that isn't a plain free-spins counter). */
23
+ type ShellMode = 'base' | 'bonus' | 'freeSpins' | 'replay';
24
+ /** The three independent volume sliders shown in the Settings overlay. */
25
+ type VolumeKey = 'master' | 'music' | 'sfx';
26
+ type VolumeLevels = Record<VolumeKey, number>;
20
27
  interface CurrencyConfig {
21
28
  symbol: string;
22
29
  position: 'left' | 'right';
@@ -205,6 +212,19 @@ interface FreeSpinsState {
205
212
  total: number;
206
213
  totalWin: number;
207
214
  }
215
+ /** A game-supplied bonus readout for the bar hero, set via `setBonus()`. Generalizes the
216
+ * free-spins counter: the shell renders `label` (localized via the shell translator, so a game
217
+ * i18n entry for it is honoured) + `value` (a pre-formatted string, shown verbatim — "2 / 10",
218
+ * "3", "×5", "7 coins") + the Total Win accumulator. The shell stays free of any per-game bonus
219
+ * concept — the label/value semantics live in the game/host. */
220
+ interface BonusReadout {
221
+ /** Bar label, e.g. 'Free spins' | 'Adventure' | 'Hold & Spin'. Run through the shell translator. */
222
+ label: string;
223
+ /** Pre-formatted counter value shown verbatim (NOT translated). */
224
+ value: string;
225
+ /** Cumulative bonus win for the Total Win readout. */
226
+ totalWin: number;
227
+ }
208
228
  /** One footer button of a generic modal. Clicking it runs `on` (if any), then closes the modal. */
209
229
  interface ModalAction {
210
230
  title: string;
@@ -265,9 +285,13 @@ interface ShellConfig {
265
285
  * opening the built-in buy-bonus overlay (e.g. the game shows its own bonus UI). The button
266
286
  * is shown whenever this OR `features.buyBonus` is set. */
267
287
  onBonusBuy?: () => void;
288
+ /** Initial Settings-overlay volume slider positions (each 0..1, defaults to 1 = 100%). The shell
289
+ * keeps them stateful across opens; read/update at runtime via `shell.getVolume()` /
290
+ * `shell.setVolume()`, and listen to `settingChange` ({ key: 'master'|'music'|'sfx' }) to apply. */
291
+ volumes?: Partial<VolumeLevels>;
268
292
  }
269
293
  /** ShellConfig after the controller applies defaults (version, isSocial, replay, theme). No mount. */
270
- type ResolvedShellConfig = Required<Pick<ShellConfig, 'language' | 'currency' | 'availableBets' | 'defaultBet' | 'balance' | 'win' | 'mode' | 'features' | 'gameInfo' | 'version' | 'isSocial' | 'replay'>> & Pick<ShellConfig, 'currentBet' | 'theme' | 'onBonusBuy'>;
294
+ type ResolvedShellConfig = Required<Pick<ShellConfig, 'language' | 'currency' | 'availableBets' | 'defaultBet' | 'balance' | 'win' | 'mode' | 'features' | 'gameInfo' | 'version' | 'isSocial' | 'replay'>> & Pick<ShellConfig, 'currentBet' | 'theme' | 'onBonusBuy' | 'volumes'>;
271
295
  interface ShellState {
272
296
  mode: ShellMode;
273
297
  /** Sticky replay marker — true for a historical-round replay, regardless of the current
@@ -283,9 +307,18 @@ interface ShellState {
283
307
  turbo: number;
284
308
  buyBonusEnabled: boolean;
285
309
  freeSpins: FreeSpinsState;
310
+ /** Game-supplied bonus label + value override (from `setBonus()`). When null the bar derives the
311
+ * readout from `freeSpins` (label 'Free spins', value current/total) — the back-compat default. */
312
+ bonus: {
313
+ label: string;
314
+ value: string;
315
+ } | null;
286
316
  /** The currently activated `feature` option (e.g. Ante), or null. Drives the
287
317
  * effective-bet readout tint and the BUY BONUS → DISABLE toggle on the bar. */
288
318
  activeFeature: BonusOption | null;
319
+ /** Volume slider positions (0..1) surfaced in the Settings overlay. Stateful across opens so a
320
+ * reopened overlay reflects the last-set positions instead of resetting to 100%. */
321
+ volumes: VolumeLevels;
289
322
  }
290
323
  interface ShellEvents {
291
324
  spin: void;
@@ -408,6 +441,13 @@ interface ShellHost {
408
441
  setSound(on: boolean): void;
409
442
  /** An open Settings overlay registers an icon updater here (null clears it on close). */
410
443
  setSoundRefresh(fn: ((on: boolean) => void) | null): void;
444
+ /** Current volume slider position (0..1) for master/music/sfx. */
445
+ getVolume(key: VolumeKey): number;
446
+ /** Set a volume slider (0..1): clamps, stores, emits `settingChange`, and live-updates an open
447
+ * Settings overlay. Called by the slider control on drag AND by game code as the public API. */
448
+ setVolume(key: VolumeKey, value: number): void;
449
+ /** An open Settings overlay registers a slider updater here (null clears it on close). */
450
+ setVolumeRefresh(fn: ((key: VolumeKey, value: number) => void) | null): void;
411
451
  /** Logic-bearing actions invoked by renderer controls. */
412
452
  readonly actions: ShellActions;
413
453
  }
@@ -471,13 +511,14 @@ declare class ShellController extends EventEmitter<ShellEvents> implements Shell
471
511
  tokens: ShellTokens;
472
512
  layout: ShellLayoutMode;
473
513
  soundOn: boolean;
474
- readonly engineVersion = "0.4.1";
514
+ readonly engineVersion = "0.6.0";
475
515
  readonly actions: ShellActions;
476
516
  private renderer;
477
517
  private i18n;
478
518
  private kbd?;
479
519
  private overlay;
480
520
  private soundRefresh;
521
+ private volumeRefresh;
481
522
  private prevBalance;
482
523
  private prevWin;
483
524
  private destroyed;
@@ -502,6 +543,12 @@ declare class ShellController extends EventEmitter<ShellEvents> implements Shell
502
543
  closeModal(): void;
503
544
  setSound(on: boolean): void;
504
545
  setSoundRefresh(fn: ((on: boolean) => void) | null): void;
546
+ getVolume(key: VolumeKey): number;
547
+ /** Set a volume slider (0..1). Shared by the slider control (drag) and game code (public API):
548
+ * clamps, stores so a reopened Settings overlay reflects it, emits `settingChange`, and
549
+ * live-updates the slider if the overlay is currently open. */
550
+ setVolume(key: VolumeKey, value: number): void;
551
+ setVolumeRefresh(fn: ((key: VolumeKey, value: number) => void) | null): void;
505
552
  activateFeature(bonus: BonusOption): void;
506
553
  deactivateFeature(): void;
507
554
  private money;
@@ -514,6 +561,10 @@ declare class ShellController extends EventEmitter<ShellEvents> implements Shell
514
561
  setTurbo(level: number): void;
515
562
  setBuyBonusEnabled(enabled: boolean): void;
516
563
  setFreeSpins(fs: FreeSpinsState): void;
564
+ /** Generic bonus readout (adventure / hold-and-spin / respins). Sets a game-supplied label+value
565
+ * override for the bar hero and folds `totalWin` into the shared accumulator. Pairs with
566
+ * `setMode('bonus')`. `setFreeSpins()` clears the override back to the derived current/total. */
567
+ setBonus(b: BonusReadout): void;
517
568
  setTheme(theme: ThemeConfig): void;
518
569
  setLanguage(lang: string): void;
519
570
  setSocial(isSocial: boolean): void;
@@ -537,7 +588,7 @@ interface I18n {
537
588
  declare function createI18n(opts: I18nOptions): I18n;
538
589
 
539
590
  /** The @energy8platform/shell package version, stamped into the game-info footer. */
540
- declare const PACKAGE_VERSION = "0.4.1";
591
+ declare const PACKAGE_VERSION = "0.6.0";
541
592
 
542
593
  /** A shell: the renderer-agnostic controller plus the surface facade (safeArea/barHeight/setVisible)
543
594
  * an embedding host reads. `createShell`, `createGameShell` and `createPixiShell` all return this. */
@@ -551,4 +602,4 @@ type Shell = ShellController & ShellSurface;
551
602
  declare function createShell(opts: CreateShellOptions): Shell;
552
603
 
553
604
  export { DEFAULT_ACCENT, PACKAGE_VERSION, SCHEMES, ShellController, createI18n, createShell, normalizeLang, resolveConfig, resolveTheme, socialize };
554
- export type { AutoplayConfig, AutoplayOptions, BonusCardContext, BonusOption, CellRef, CreateShellOptions, CurrencyConfig, FreeSpinsState, GameInfoContent, GameInfoSection, GameMode, I18n, I18nOptions, Lang, ModalAction, ModalOptions, OverlayHandle, OverlayRequest, PaylineDef, PaytableRow, ReplayModalOptions, ResolvedShellConfig, SafeArea, ShapeDef, Shell, ShellActions, ShellConfig, ShellEvents, ShellFeatures, ShellHost, ShellLayoutMode, ShellMode, ShellRenderer, ShellState, ShellSurface, ShellTokens, ThemeConfig, WinSection };
605
+ export type { AutoplayConfig, AutoplayOptions, BonusCardContext, BonusOption, BonusReadout, CellRef, CreateShellOptions, CurrencyConfig, FreeSpinsState, GameInfoContent, GameInfoSection, GameMode, I18n, I18nOptions, Lang, ModalAction, ModalOptions, OverlayHandle, OverlayRequest, PaylineDef, PaytableRow, ReplayModalOptions, ResolvedShellConfig, SafeArea, ShapeDef, Shell, ShellActions, ShellConfig, ShellEvents, ShellFeatures, ShellHost, ShellLayoutMode, ShellMode, ShellRenderer, ShellState, ShellSurface, ShellTokens, ThemeConfig, VolumeKey, VolumeLevels, WinSection };
package/dist/index.esm.js CHANGED
@@ -63,9 +63,19 @@ function createInitialState(config) {
63
63
  turbo: 0,
64
64
  buyBonusEnabled: true,
65
65
  freeSpins: { current: 0, total: 0, totalWin: 0 },
66
+ bonus: null,
66
67
  activeFeature: null,
68
+ volumes: {
69
+ master: clampVolume(config.volumes?.master),
70
+ music: clampVolume(config.volumes?.music),
71
+ sfx: clampVolume(config.volumes?.sfx),
72
+ },
67
73
  };
68
74
  }
75
+ /** Clamp a configured volume to 0..1, defaulting to full (1) when unset/invalid. */
76
+ function clampVolume(v) {
77
+ return typeof v === 'number' && Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 1;
78
+ }
69
79
  /** Step bet up/down within availableBets, clamped at the ends. */
70
80
  function stepBet(state, direction) {
71
81
  const idx = state.availableBets.indexOf(state.bet);
@@ -1410,7 +1420,7 @@ class KeyboardController {
1410
1420
 
1411
1421
  // AUTO-GENERATED by scripts/gen-version.mjs — do not edit. Mirrors package.json "version".
1412
1422
  /** The @energy8platform/shell package version, stamped into the game-info footer. */
1413
- const PACKAGE_VERSION = '0.4.1';
1423
+ const PACKAGE_VERSION = '0.6.0';
1414
1424
 
1415
1425
  /** Apply defaults to the raw config (the mount target lives on the renderer, not here). */
1416
1426
  function resolveConfig(config) {
@@ -1427,6 +1437,7 @@ function resolveConfig(config) {
1427
1437
  features: config.features,
1428
1438
  theme: config.theme,
1429
1439
  onBonusBuy: config.onBonusBuy,
1440
+ volumes: config.volumes,
1430
1441
  version: config.version ?? '1.0.0',
1431
1442
  isSocial: config.isSocial ?? false,
1432
1443
  replay: config.replay ?? config.mode === 'replay',
@@ -1448,6 +1459,7 @@ class ShellController extends EventEmitter {
1448
1459
  kbd;
1449
1460
  overlay = null;
1450
1461
  soundRefresh = null;
1462
+ volumeRefresh = null;
1451
1463
  prevBalance;
1452
1464
  prevWin;
1453
1465
  destroyed = false;
@@ -1471,9 +1483,15 @@ class ShellController extends EventEmitter {
1471
1483
  this.renderer.renderBar();
1472
1484
  }
1473
1485
  // ── ShellHost ──────────────────────────────────────────────────────────────
1474
- t(text) { return this.i18n.t(text); }
1475
- formatCurrency(n, win = false) { return formatCurrency(n, this.config.currency, win); }
1476
- formatWin(value) { return this.formatCurrency(value, true); }
1486
+ t(text) {
1487
+ return this.i18n.t(text);
1488
+ }
1489
+ formatCurrency(n, win = false) {
1490
+ return formatCurrency(n, this.config.currency, win);
1491
+ }
1492
+ formatWin(value) {
1493
+ return this.formatCurrency(value, true);
1494
+ }
1477
1495
  notifyResize(w, h) {
1478
1496
  const layout = w !== 0 && h > w ? 'mobile' : 'wide';
1479
1497
  if (layout !== this.layout) {
@@ -1540,12 +1558,24 @@ class ShellController extends EventEmitter {
1540
1558
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1541
1559
  const self = this;
1542
1560
  const host = {
1543
- get state() { return self.state; },
1544
- get hotkeysEnabled() { return self.config.features.hotkeys !== false; },
1545
- get spacebarEnabled() { return self.config.features.spacebar !== false; },
1546
- get turboLevels() { return self.config.features.turbo; },
1547
- get autoplayEnabled() { return self.config.features.autoplay != null; },
1548
- get buyBonusEnabled() { return self.config.features.buyBonus !== false; },
1561
+ get state() {
1562
+ return self.state;
1563
+ },
1564
+ get hotkeysEnabled() {
1565
+ return self.config.features.hotkeys !== false;
1566
+ },
1567
+ get spacebarEnabled() {
1568
+ return self.config.features.spacebar !== false;
1569
+ },
1570
+ get turboLevels() {
1571
+ return self.config.features.turbo;
1572
+ },
1573
+ get autoplayEnabled() {
1574
+ return self.config.features.autoplay != null;
1575
+ },
1576
+ get buyBonusEnabled() {
1577
+ return self.config.features.buyBonus !== false;
1578
+ },
1549
1579
  hasOpenLayer: () => self.overlay !== null,
1550
1580
  routeToLayer: (e) => self.overlay?.onKey?.(e) ?? false,
1551
1581
  spin: () => self.actions.spin(),
@@ -1561,33 +1591,59 @@ class ShellController extends EventEmitter {
1561
1591
  this.kbd = new KeyboardController(host);
1562
1592
  this.kbd.attach();
1563
1593
  }
1564
- pullFocus = () => { try {
1565
- globalThis.focus?.();
1566
- }
1567
- catch { /* cross-origin */ } };
1594
+ pullFocus = () => {
1595
+ try {
1596
+ globalThis.focus?.();
1597
+ }
1598
+ catch {
1599
+ /* cross-origin */
1600
+ }
1601
+ };
1568
1602
  // ── overlay flow ─────────────────────────────────────────────────────────────
1569
1603
  show(req) {
1570
1604
  this.closeModal();
1571
1605
  this.overlay = this.renderer.openOverlay(req) ?? null;
1572
1606
  }
1573
- openMenu() { this.emit('menuOpen'); this.openSettings(); }
1574
- openSettings() { this.emit('settingsOpen'); this.show({ kind: 'settings' }); }
1575
- openInfo() { this.emit('infoOpen'); this.show({ kind: 'gameInfo' }); }
1576
- openBuyBonus() { if (this.config.onBonusBuy) {
1577
- this.config.onBonusBuy();
1578
- return;
1579
- } this.show({ kind: 'buyBonus' }); }
1580
- openBetPicker() { this.show({ kind: 'betPicker' }); }
1581
- openAutoplayPicker() { this.show({ kind: 'autoplayPicker' }); }
1582
- openReplay(opts) { if (this.destroyed)
1583
- return; this.show({ kind: 'replay', opts }); }
1584
- openModal(opts) { this.show({ kind: 'modal', opts }); }
1607
+ openMenu() {
1608
+ this.emit('menuOpen');
1609
+ this.openSettings();
1610
+ }
1611
+ openSettings() {
1612
+ this.emit('settingsOpen');
1613
+ this.show({ kind: 'settings' });
1614
+ }
1615
+ openInfo() {
1616
+ this.emit('infoOpen');
1617
+ this.show({ kind: 'gameInfo' });
1618
+ }
1619
+ openBuyBonus() {
1620
+ if (this.config.onBonusBuy) {
1621
+ this.config.onBonusBuy();
1622
+ return;
1623
+ }
1624
+ this.show({ kind: 'buyBonus' });
1625
+ }
1626
+ openBetPicker() {
1627
+ this.show({ kind: 'betPicker' });
1628
+ }
1629
+ openAutoplayPicker() {
1630
+ this.show({ kind: 'autoplayPicker' });
1631
+ }
1632
+ openReplay(opts) {
1633
+ if (this.destroyed)
1634
+ return;
1635
+ this.show({ kind: 'replay', opts });
1636
+ }
1637
+ openModal(opts) {
1638
+ this.show({ kind: 'modal', opts });
1639
+ }
1585
1640
  /** Programmatically dismiss whatever overlay/modal is open. No-op when nothing is shown. */
1586
1641
  closeModal() {
1587
1642
  if (!this.overlay)
1588
1643
  return;
1589
1644
  this.overlay = null;
1590
1645
  this.soundRefresh = null;
1646
+ this.volumeRefresh = null;
1591
1647
  this.renderer.closeOverlay();
1592
1648
  }
1593
1649
  // ── sound ──────────────────────────────────────────────────────────────────
@@ -1597,7 +1653,25 @@ class ShellController extends EventEmitter {
1597
1653
  this.soundRefresh?.(on);
1598
1654
  this.renderer.refreshSoundIcon?.(on);
1599
1655
  }
1600
- setSoundRefresh(fn) { this.soundRefresh = fn; }
1656
+ setSoundRefresh(fn) {
1657
+ this.soundRefresh = fn;
1658
+ }
1659
+ // ── volume ─────────────────────────────────────────────────────────────────
1660
+ getVolume(key) {
1661
+ return this.state.volumes[key];
1662
+ }
1663
+ /** Set a volume slider (0..1). Shared by the slider control (drag) and game code (public API):
1664
+ * clamps, stores so a reopened Settings overlay reflects it, emits `settingChange`, and
1665
+ * live-updates the slider if the overlay is currently open. */
1666
+ setVolume(key, value) {
1667
+ const v = Math.max(0, Math.min(1, value));
1668
+ this.state.volumes[key] = v;
1669
+ this.emit('settingChange', { key, value: v });
1670
+ this.volumeRefresh?.(key, v);
1671
+ }
1672
+ setVolumeRefresh(fn) {
1673
+ this.volumeRefresh = fn;
1674
+ }
1601
1675
  // ── features ─────────────────────────────────────────────────────────────────
1602
1676
  activateFeature(bonus) {
1603
1677
  this.state.activeFeature = bonus;
@@ -1618,21 +1692,81 @@ class ShellController extends EventEmitter {
1618
1692
  if (to !== from)
1619
1693
  this.renderer.animateMoney(field, from, to);
1620
1694
  }
1621
- setBalance(n) { const from = this.prevBalance; this.state.balance = n; this.prevBalance = n; this.money('balance', from, n); }
1622
- setWin(n) { const from = this.prevWin; this.state.win = n; this.prevWin = n; this.money('win', from, n); }
1623
- setBet(n) { this.state.bet = n; this.renderer.renderBar(); }
1624
- setMode(mode) { if (mode === 'replay')
1625
- this.state.replay = true; this.state.mode = mode; this.renderer.renderBar(); }
1626
- setBusy(busy) { this.state.busy = busy; this.renderer.renderBar(); this.kbd?.notifyBusyChanged(busy); }
1627
- setAutoplay(a) { this.state.autoplay = a; this.renderer.renderBar(); }
1628
- setTurbo(level) { this.state.turbo = level; this.renderer.renderBar(); }
1629
- setBuyBonusEnabled(enabled) { this.state.buyBonusEnabled = enabled; this.renderer.renderBar(); }
1630
- setFreeSpins(fs) { this.state.freeSpins = fs; this.renderer.renderBar(); }
1631
- setTheme(theme) { this.config.theme = theme; this.tokens = resolveTheme(theme); this.renderer.applyTheme(this.tokens); this.renderer.renderBar(); }
1632
- setLanguage(lang) { this.config.language = lang; this.i18n = createI18n({ language: lang, isSocial: this.config.isSocial }); this.renderer.renderBar(); }
1633
- setSocial(isSocial) { this.config.isSocial = isSocial; this.i18n = createI18n({ language: this.config.language, isSocial }); this.renderer.renderBar(); }
1634
- setLayout(layout) { if (layout === this.layout)
1635
- return; this.layout = layout; this.renderer.setLayout(layout); this.renderer.renderBar(); }
1695
+ setBalance(n) {
1696
+ const from = this.prevBalance;
1697
+ this.state.balance = n;
1698
+ this.prevBalance = n;
1699
+ this.money('balance', from, n);
1700
+ }
1701
+ setWin(n) {
1702
+ const from = this.prevWin;
1703
+ this.state.win = n;
1704
+ this.prevWin = n;
1705
+ this.money('win', from, n);
1706
+ }
1707
+ setBet(n) {
1708
+ this.state.bet = n;
1709
+ this.renderer.renderBar();
1710
+ }
1711
+ setMode(mode) {
1712
+ if (mode === 'replay')
1713
+ this.state.replay = true;
1714
+ this.state.mode = mode;
1715
+ this.renderer.renderBar();
1716
+ }
1717
+ setBusy(busy) {
1718
+ this.state.busy = busy;
1719
+ this.renderer.renderBar();
1720
+ this.kbd?.notifyBusyChanged(busy);
1721
+ }
1722
+ setAutoplay(a) {
1723
+ this.state.autoplay = a;
1724
+ this.renderer.renderBar();
1725
+ }
1726
+ setTurbo(level) {
1727
+ this.state.turbo = level;
1728
+ this.renderer.renderBar();
1729
+ }
1730
+ setBuyBonusEnabled(enabled) {
1731
+ this.state.buyBonusEnabled = enabled;
1732
+ this.renderer.renderBar();
1733
+ }
1734
+ setFreeSpins(fs) {
1735
+ this.state.freeSpins = fs;
1736
+ this.state.bonus = null;
1737
+ this.renderer.renderBar();
1738
+ }
1739
+ /** Generic bonus readout (adventure / hold-and-spin / respins). Sets a game-supplied label+value
1740
+ * override for the bar hero and folds `totalWin` into the shared accumulator. Pairs with
1741
+ * `setMode('bonus')`. `setFreeSpins()` clears the override back to the derived current/total. */
1742
+ setBonus(b) {
1743
+ this.state.bonus = { label: b.label, value: b.value };
1744
+ this.state.freeSpins = { ...this.state.freeSpins, totalWin: b.totalWin };
1745
+ this.renderer.renderBar();
1746
+ }
1747
+ setTheme(theme) {
1748
+ this.config.theme = theme;
1749
+ this.tokens = resolveTheme(theme);
1750
+ this.renderer.applyTheme(this.tokens);
1751
+ this.renderer.renderBar();
1752
+ }
1753
+ setLanguage(lang) {
1754
+ this.config.language = lang;
1755
+ this.i18n = createI18n({ language: lang, isSocial: this.config.isSocial });
1756
+ this.renderer.renderBar();
1757
+ }
1758
+ setSocial(isSocial) {
1759
+ this.config.isSocial = isSocial;
1760
+ this.i18n = createI18n({ language: this.config.language, isSocial });
1761
+ this.renderer.renderBar();
1762
+ }
1763
+ setLayout(layout) {
1764
+ if (layout === this.layout)
1765
+ return;
1766
+ this.layout = layout;
1767
+ this.renderer.setLayout(layout);
1768
+ this.renderer.renderBar();
1769
+ }
1636
1770
  destroy() {
1637
1771
  if (this.destroyed)
1638
1772
  return Promise.resolve();