@energy8platform/platform-core 0.23.2 → 0.24.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/README.md +4 -3
- package/dist/index.cjs.js +33 -21
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +11 -7
- package/dist/index.esm.js +33 -21
- package/dist/index.esm.js.map +1 -1
- package/dist/shell.cjs.js +33 -21
- package/dist/shell.cjs.js.map +1 -1
- package/dist/shell.d.ts +11 -7
- package/dist/shell.esm.js +33 -21
- package/dist/shell.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/shell/GameShell.ts +2 -1
- package/src/shell/components/BottomBar.ts +15 -4
- package/src/shell/components/ReplayModal.ts +2 -1
- package/src/shell/format.ts +14 -11
- package/src/shell/shell.css.ts +1 -1
- package/src/shell/theme.ts +1 -3
- package/src/shell/types.ts +11 -7
package/dist/index.d.ts
CHANGED
|
@@ -501,11 +501,12 @@ type ShellMode = 'base' | 'freeSpins' | 'replay';
|
|
|
501
501
|
interface CurrencyConfig {
|
|
502
502
|
symbol: string;
|
|
503
503
|
position: 'left' | 'right';
|
|
504
|
-
/** Maximum fraction digits (default 2).
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
*
|
|
504
|
+
/** Maximum fraction digits (default 2). Win / total-win readouts are rounded to this precision;
|
|
505
|
+
* balance / bet / prices stay fixed at `minDecimals`. */
|
|
506
|
+
maxDecimals?: number;
|
|
507
|
+
/** Minimum fraction digits (defaults to `maxDecimals`). For win / total-win, trailing zeros are
|
|
508
|
+
* trimmed down to this many places so small wins keep their significant digits (e.g. 0.0673)
|
|
509
|
+
* while round amounts stay compact (e.g. 0.30). Everything else is shown at exactly this many. */
|
|
509
510
|
minDecimals?: number;
|
|
510
511
|
separator?: {
|
|
511
512
|
thousands?: string;
|
|
@@ -552,8 +553,9 @@ interface BonusCardContext {
|
|
|
552
553
|
interface ThemeConfig {
|
|
553
554
|
/** Palette scheme: 'dark' (default) for dark games, 'light' for light backgrounds. */
|
|
554
555
|
scheme?: 'dark' | 'light';
|
|
556
|
+
/** Brand accent — active states, the SPIN hover glow, and the BUY BONUS button.
|
|
557
|
+
* (Per-bonus card accents are set on each `BonusOption.accentColor`.) */
|
|
555
558
|
accent?: string;
|
|
556
|
-
buyBonusColor?: string;
|
|
557
559
|
}
|
|
558
560
|
/** One paytable entry: a symbol (text/image) and its win tiers, rendered "<count> x<multiplier>". */
|
|
559
561
|
interface PaytableRow {
|
|
@@ -658,7 +660,9 @@ interface AutoplayOptions {
|
|
|
658
660
|
remaining: number;
|
|
659
661
|
}
|
|
660
662
|
interface FreeSpinsState {
|
|
661
|
-
current
|
|
663
|
+
/** Spin index for the `current / total` counter. Set to `null` (or omit) to instead show just
|
|
664
|
+
* `total` as a single number — drive a countdown by decrementing `total` each spin. */
|
|
665
|
+
current?: number | null;
|
|
662
666
|
total: number;
|
|
663
667
|
totalWin: number;
|
|
664
668
|
}
|
package/dist/index.esm.js
CHANGED
|
@@ -1026,7 +1026,7 @@ const PALETTE = {
|
|
|
1026
1026
|
},
|
|
1027
1027
|
};
|
|
1028
1028
|
/** CSS custom-property block for the shell root. `scheme` picks the palette;
|
|
1029
|
-
* only accent
|
|
1029
|
+
* only the accent is additionally game-overridable. */
|
|
1030
1030
|
function buildThemeVars(theme = {}) {
|
|
1031
1031
|
const p = PALETTE[theme.scheme === 'light' ? 'light' : 'dark'];
|
|
1032
1032
|
return [
|
|
@@ -1055,8 +1055,6 @@ function buildThemeVars(theme = {}) {
|
|
|
1055
1055
|
`--shell-plaque-line: rgba(255,255,255,.22)`,
|
|
1056
1056
|
`--shell-plaque-label: rgba(255,255,255,.6)`,
|
|
1057
1057
|
`--shell-accent: ${theme.accent ?? DEFAULT_ACCENT}`,
|
|
1058
|
-
// buy-bonus tint follows the accent by default; only overridden when set explicitly
|
|
1059
|
-
`--shell-buybonus: ${theme.buyBonusColor ?? theme.accent ?? DEFAULT_ACCENT}`,
|
|
1060
1058
|
].join('; ') + ';';
|
|
1061
1059
|
}
|
|
1062
1060
|
|
|
@@ -1120,7 +1118,7 @@ const SHELL_CSS = SHELL_FONT_CSS + `
|
|
|
1120
1118
|
|
|
1121
1119
|
/* BUY BONUS — round accent badge, 2-line label, text pulses + accent glow on hover */
|
|
1122
1120
|
#${SHELL_ROOT_ID} .ge-shell-buybonus { pointer-events:auto; cursor:pointer; box-sizing:border-box;
|
|
1123
|
-
width:80px; height:80px; border-radius:50%; border:3px solid #000; background:var(--shell-
|
|
1121
|
+
width:80px; height:80px; border-radius:50%; border:3px solid #000; background:var(--shell-accent);
|
|
1124
1122
|
color:#fff; font-weight:800; letter-spacing:.02em; font-size:13px; line-height:1.08; text-align:center;
|
|
1125
1123
|
display:flex; align-items:center; justify-content:center; transition:transform .08s ease, box-shadow .12s ease; }
|
|
1126
1124
|
#${SHELL_ROOT_ID} .ge-shell-buybonus span { display:inline-block; will-change:transform; }
|
|
@@ -1452,22 +1450,25 @@ const SHELL_CSS = SHELL_FONT_CSS + `
|
|
|
1452
1450
|
|
|
1453
1451
|
/** The shared money formatter for every shell readout (balance, win, total win, bet, prices).
|
|
1454
1452
|
*
|
|
1455
|
-
* `
|
|
1456
|
-
* is the MINIMUM.
|
|
1457
|
-
* —
|
|
1458
|
-
*
|
|
1453
|
+
* `maxDecimals` is the MAXIMUM fraction digits (default 2); `minDecimals` (defaults to
|
|
1454
|
+
* `maxDecimals`) is the MINIMUM. By default the value is shown at exactly `minDecimals` places.
|
|
1455
|
+
* With `variableDecimals` — used only for win / total-win — it is rounded to `maxDecimals`, then
|
|
1456
|
+
* trailing zeros are trimmed down to (but never past) `minDecimals`, so small wins keep their
|
|
1457
|
+
* significant digits. Balance / bet / prices stay fixed at `minDecimals`.
|
|
1459
1458
|
*
|
|
1460
|
-
* Example with `
|
|
1461
|
-
*
|
|
1462
|
-
* 0.
|
|
1459
|
+
* Example with `maxDecimals: 4, minDecimals: 2`:
|
|
1460
|
+
* fixed → 0.0673 → 0,07 0.3 → 0,30
|
|
1461
|
+
* variable → 0.0673 → 0,0673 0.067 → 0,067 0.3 → 0,30 0 → 0,00
|
|
1463
1462
|
*/
|
|
1464
|
-
function formatCurrency(value, currency) {
|
|
1465
|
-
const
|
|
1466
|
-
const minDecimals = Math.max(0, Math.min(
|
|
1463
|
+
function formatCurrency(value, currency, variableDecimals = false) {
|
|
1464
|
+
const maxDecimals = currency.maxDecimals ?? 2;
|
|
1465
|
+
const minDecimals = Math.max(0, Math.min(maxDecimals, currency.minDecimals ?? maxDecimals));
|
|
1467
1466
|
const thousands = currency.separator?.thousands ?? '.';
|
|
1468
1467
|
const decimal = currency.separator?.decimal ?? ',';
|
|
1469
1468
|
const safe = Number.isFinite(value) ? value : 0;
|
|
1470
|
-
|
|
1469
|
+
// fixed callers round at minDecimals; variable callers round at maxDecimals then trim back down.
|
|
1470
|
+
const places = variableDecimals ? maxDecimals : minDecimals;
|
|
1471
|
+
const fixed = safe.toFixed(places);
|
|
1471
1472
|
const [intPart, rawFrac = ''] = fixed.split('.');
|
|
1472
1473
|
// trim trailing zeros, but keep at least `minDecimals` fraction digits
|
|
1473
1474
|
let fracPart = rawFrac;
|
|
@@ -1628,6 +1629,7 @@ function iconBtn(ge, name, onClick, active = false) {
|
|
|
1628
1629
|
function renderBottomBar(shell) {
|
|
1629
1630
|
const { state, config } = shell;
|
|
1630
1631
|
const fmt = (n) => formatCurrency(n, config.currency);
|
|
1632
|
+
const fmtWin = (n) => formatCurrency(n, config.currency, true); // win / total-win: variable decimals
|
|
1631
1633
|
const mobile = shell.layout === 'mobile';
|
|
1632
1634
|
const bar = document.createElement('div');
|
|
1633
1635
|
bar.className = 'ge-shell-bottom';
|
|
@@ -1648,8 +1650,13 @@ function renderBottomBar(shell) {
|
|
|
1648
1650
|
const betShown = feature ? state.bet * feature.priceMultiplier : state.bet;
|
|
1649
1651
|
const betValue = readout('bet-value', shell.t('Bet'), fmt(betShown));
|
|
1650
1652
|
if (feature) {
|
|
1653
|
+
const accent = effectiveAccent(feature);
|
|
1651
1654
|
betValue.classList.add('ge-bet-feature');
|
|
1652
|
-
betValue.style.color =
|
|
1655
|
+
betValue.style.color = accent;
|
|
1656
|
+
// tint the "BET" label too (its .ge-lbl colour is set in CSS, so override inline)
|
|
1657
|
+
const lbl = betValue.querySelector('.ge-lbl');
|
|
1658
|
+
if (lbl)
|
|
1659
|
+
lbl.style.color = accent;
|
|
1653
1660
|
}
|
|
1654
1661
|
const turbo = config.features.turbo > 0
|
|
1655
1662
|
? iconBtn('turbo', turboIcon(state.turbo), () => onTurbo(shell), state.turbo > 0) : null;
|
|
@@ -1666,10 +1673,13 @@ function renderBottomBar(shell) {
|
|
|
1666
1673
|
auto = config.features.autoplay ? autoButton(shell) : null;
|
|
1667
1674
|
buy = (config.features.buyBonus !== false || config.onBonusBuy) ? buyBtn(shell) : null;
|
|
1668
1675
|
}
|
|
1669
|
-
const winEl = state.win > 0 ? readout('win', shell.t('Win'),
|
|
1676
|
+
const winEl = state.win > 0 ? readout('win', shell.t('Win'), fmtWin(state.win)) : null;
|
|
1670
1677
|
// FS/replay left blocks: spins counter + accumulated Total Win (shown even at €0).
|
|
1671
|
-
|
|
1672
|
-
const
|
|
1678
|
+
// current = number → "current / total"; current = null/undefined → just the (game-driven) total.
|
|
1679
|
+
const fs = state.freeSpins;
|
|
1680
|
+
const fsText = fs.current == null ? `${fs.total}` : `${fs.current} / ${fs.total}`;
|
|
1681
|
+
const fsCounter = showFsBlocks ? readout('fs-counter', shell.t('Free spins'), fsText) : null;
|
|
1682
|
+
const fsTotalWin = showFsBlocks ? readout('fs-totalwin', shell.t('Total win'), fmtWin(fs.totalWin)) : null;
|
|
1673
1683
|
if (mobile) {
|
|
1674
1684
|
// rows: [balance · win] · [menu · auto · spin · FS counter · Total Win · turbo · buy] · [− bet +]
|
|
1675
1685
|
// FS counter + Total Win live in the controls row (alongside menu/turbo), not the top readouts.
|
|
@@ -2485,6 +2495,7 @@ function buildModal(opts) {
|
|
|
2485
2495
|
function buildReplayModal(shell, opts) {
|
|
2486
2496
|
const { bonusId, bet, payoutMultiplier } = opts;
|
|
2487
2497
|
const fmt = (n) => formatCurrency(n, shell.config.currency);
|
|
2498
|
+
const fmtWin = (n) => formatCurrency(n, shell.config.currency, true); // total win: variable decimals
|
|
2488
2499
|
const bonus = Array.isArray(shell.config.features.buyBonus)
|
|
2489
2500
|
? shell.config.features.buyBonus.find((b) => b.id === bonusId)
|
|
2490
2501
|
: undefined;
|
|
@@ -2513,7 +2524,7 @@ function buildReplayModal(shell, opts) {
|
|
|
2513
2524
|
row('Cost multiplier', `${costMultiplier}×`);
|
|
2514
2525
|
row('Total cost bet', fmt(bet * costMultiplier));
|
|
2515
2526
|
row('Payout multiplier', `${payoutMultiplier}×`);
|
|
2516
|
-
row('Total win',
|
|
2527
|
+
row('Total win', fmtWin(payoutMultiplier * bet), true);
|
|
2517
2528
|
ui.body.appendChild(rows);
|
|
2518
2529
|
const actions = document.createElement('div');
|
|
2519
2530
|
actions.className = 'ge-modal-actions';
|
|
@@ -2802,12 +2813,13 @@ class GameShell extends EventEmitter {
|
|
|
2802
2813
|
}
|
|
2803
2814
|
animateMoney() {
|
|
2804
2815
|
const fmt = (n) => formatCurrency(n, this.config.currency);
|
|
2816
|
+
const fmtWin = (n) => formatCurrency(n, this.config.currency, true); // win: variable decimals
|
|
2805
2817
|
const bal = this.barHost.querySelector('[data-ge="balance"]');
|
|
2806
2818
|
const win = this.barHost.querySelector('[data-ge="win"]');
|
|
2807
2819
|
if (bal && this.state.balance !== this.prevBalance)
|
|
2808
2820
|
this.moneyAnims.push(animateReadout(bal, this.prevBalance, this.state.balance, fmt));
|
|
2809
2821
|
if (win && this.state.win !== this.prevWin)
|
|
2810
|
-
this.moneyAnims.push(animateReadout(win, this.prevWin, this.state.win,
|
|
2822
|
+
this.moneyAnims.push(animateReadout(win, this.prevWin, this.state.win, fmtWin));
|
|
2811
2823
|
this.prevBalance = this.state.balance;
|
|
2812
2824
|
this.prevWin = this.state.win;
|
|
2813
2825
|
}
|