@energy8platform/platform-core 0.25.0 → 0.25.2
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.cjs.js +71 -16
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +71 -16
- package/dist/index.esm.js.map +1 -1
- package/dist/loading.cjs.js +10 -1
- package/dist/loading.cjs.js.map +1 -1
- package/dist/loading.esm.js +10 -1
- package/dist/loading.esm.js.map +1 -1
- package/dist/shell.cjs.js +61 -15
- package/dist/shell.cjs.js.map +1 -1
- package/dist/shell.d.ts +3 -0
- package/dist/shell.esm.js +61 -15
- package/dist/shell.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/loading/CSSPreloader.ts +14 -1
- package/src/shell/GameShell.ts +22 -8
- package/src/shell/components/ReplayModal.ts +1 -1
- package/src/shell/i18n.ts +1 -0
- package/src/shell/shell.css.ts +36 -3
- package/src/shell/version.ts +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -851,6 +851,10 @@ function createCSSPreloader(container, config) {
|
|
|
851
851
|
50% { opacity: 1; }
|
|
852
852
|
}
|
|
853
853
|
`;
|
|
854
|
+
// The absolute overlay needs a positioned ancestor. Only override a STATIC container, and
|
|
855
|
+
// remember the prior inline value so removeCSSPreloader can restore it (an inline `relative`
|
|
856
|
+
// left behind would beat the game's `#game { position: fixed; inset: 0 }` and collapse it).
|
|
857
|
+
const prevPosition = container.style.position;
|
|
854
858
|
container.style.position = container.style.position || 'relative';
|
|
855
859
|
container.appendChild(styleEl);
|
|
856
860
|
container.appendChild(overlay);
|
|
@@ -861,6 +865,7 @@ function createCSSPreloader(container, config) {
|
|
|
861
865
|
// We still record state so removeCSSPreloader works.
|
|
862
866
|
state = {
|
|
863
867
|
container,
|
|
868
|
+
prevPosition,
|
|
864
869
|
overlay,
|
|
865
870
|
styleEl,
|
|
866
871
|
rectEl: null,
|
|
@@ -879,6 +884,7 @@ function createCSSPreloader(container, config) {
|
|
|
879
884
|
}
|
|
880
885
|
state = {
|
|
881
886
|
container,
|
|
887
|
+
prevPosition,
|
|
882
888
|
overlay,
|
|
883
889
|
styleEl,
|
|
884
890
|
rectEl,
|
|
@@ -957,7 +963,7 @@ function removeCSSPreloader(_container) {
|
|
|
957
963
|
state.tapResolve = null;
|
|
958
964
|
}
|
|
959
965
|
state.removed = true;
|
|
960
|
-
const { overlay, styleEl } = state;
|
|
966
|
+
const { overlay, styleEl, container, prevPosition } = state;
|
|
961
967
|
overlay.classList.add('ge-preloader-hidden');
|
|
962
968
|
return new Promise((resolve) => {
|
|
963
969
|
let settled = false;
|
|
@@ -967,6 +973,9 @@ function removeCSSPreloader(_container) {
|
|
|
967
973
|
settled = true;
|
|
968
974
|
overlay.remove();
|
|
969
975
|
styleEl.remove();
|
|
976
|
+
// Restore the container's original inline position so the game's own layout
|
|
977
|
+
// (e.g. `#game { position: fixed; inset: 0 }`) is no longer defeated by our inline override.
|
|
978
|
+
container.style.position = prevPosition;
|
|
970
979
|
state = null;
|
|
971
980
|
resolve();
|
|
972
981
|
};
|
|
@@ -1320,15 +1329,30 @@ const SHELL_CSS = SHELL_FONT_CSS + `
|
|
|
1320
1329
|
/* the buy-bonus scroll area is a SIZE CONTAINER, so the cards' cqh units measure the overlay
|
|
1321
1330
|
(the popout frame) and not the browser window — cards fit without any vertical scroll. */
|
|
1322
1331
|
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-scroll { container-type:size; }
|
|
1332
|
+
/* Popout / landscape: the horizontal card strip must be the ONLY scroll axis. The cqh-sized cards
|
|
1333
|
+
are meant to fit the overlay height (no vertical scroll), but the old 7px font floor stopped them
|
|
1334
|
+
shrinking on the tiniest popouts — so they spilled past the frame and the overlay grew a SECOND,
|
|
1335
|
+
vertical scrollbar (scrollable in both directions). Two changes keep it single-axis:
|
|
1336
|
+
1. the card font floor drops (below) so cards actually fit the frame height; and
|
|
1337
|
+
2. vertical scrolling is locked off as a belt-and-braces guard, with the strip centred (the body
|
|
1338
|
+
fills the frame and centres the grid) so any sub-pixel slack splits evenly instead of clipping
|
|
1339
|
+
the price/CTA off the bottom.
|
|
1340
|
+
This mirrors the pixi shell, which masks the cards and drag-scrolls on the X axis alone. (Centring
|
|
1341
|
+
lives on the body, not the scroll box, so the grid keeps its width and its own X-scroll.) */
|
|
1342
|
+
#${SHELL_ROOT_ID}:not(.ge-mobile) [data-ge="buybonus-overlay"] .ge-ov-scroll { overflow-y:hidden; }
|
|
1343
|
+
#${SHELL_ROOT_ID}:not(.ge-mobile) [data-ge="buybonus-overlay"] .ge-ov-body {
|
|
1344
|
+
min-height:100%; box-sizing:border-box; display:flex; flex-direction:column; justify-content:center; }
|
|
1323
1345
|
/* buy-bonus uses the FULL overlay width (no 800px centre cap) so the card row isn't cropped at
|
|
1324
1346
|
the sides; small horizontal padding keeps the cards off the screen edges. */
|
|
1325
|
-
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-body { max-width:none; padding:clamp(
|
|
1347
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-body { max-width:none; padding:clamp(6px,2.5cqh,16px) clamp(12px,3vw,28px); }
|
|
1326
1348
|
#${SHELL_ROOT_ID} .ge-bb-grid { display:flex; gap:14px; justify-content:safe center; overflow-x:auto; overflow-y:hidden; padding-bottom:6px;
|
|
1327
1349
|
scroll-snap-type:x proximity; -webkit-overflow-scrolling:touch; }
|
|
1328
1350
|
/* the one knob that scales the whole card — cqh measures the overlay (popout frame), not the
|
|
1329
|
-
browser window, so cards shrink to fit the real container height.
|
|
1351
|
+
browser window, so cards shrink to fit the real container height. The floor is deliberately tiny:
|
|
1352
|
+
on a 400×225 popout the whole card (incl. the CTA) only fits below ~5px, and a fully visible,
|
|
1353
|
+
single-axis-scrolling card beats a bigger one whose button is clipped or needs a 2nd scrollbar. */
|
|
1330
1354
|
#${SHELL_ROOT_ID} .ge-bb-grid .ge-bonus-card { flex:0 0 18em; scroll-snap-align:start;
|
|
1331
|
-
font-size:clamp(
|
|
1355
|
+
font-size:clamp(4px, 3.4cqh, 12px); }
|
|
1332
1356
|
/* mobile: vertical stack at a fixed, readable size — scroll the list, don't shrink the cards */
|
|
1333
1357
|
#${SHELL_ROOT_ID}.ge-mobile .ge-bb-grid { display:flex; flex-direction:column; gap:14px; overflow:visible; }
|
|
1334
1358
|
#${SHELL_ROOT_ID}.ge-mobile .ge-bb-grid .ge-bonus-card { flex:0 0 auto; font-size:12px; }
|
|
@@ -1381,6 +1405,24 @@ const SHELL_CSS = SHELL_FONT_CSS + `
|
|
|
1381
1405
|
#${SHELL_ROOT_ID} .ge-bb-betval span { display:block; font-size:7px; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
|
|
1382
1406
|
color:var(--shell-plaque-label); }
|
|
1383
1407
|
#${SHELL_ROOT_ID} .ge-bb-betval b { font-size:14px; font-weight:800; font-variant-numeric:tabular-nums; color:#fff; }
|
|
1408
|
+
/* Popout S (short landscape): the header (title + ✕) and the bet footer are fixed-px and dwarf the
|
|
1409
|
+
shrunk cards. Scale the buy-bonus chrome down with the FRAME height. Units are cqh (the overlay is a
|
|
1410
|
+
size container below), NOT vh — vh tracks the browser window, which only equals the frame inside the
|
|
1411
|
+
Stake iframe, so it wouldn't shrink in the demo's device-frame view. Coefficients hit the normal cap
|
|
1412
|
+
by ~450px tall (Popout L) and shrink below that, to a readable floor at Popout S (225px). */
|
|
1413
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] { container:ge-bb-frame / size; }
|
|
1414
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-head { padding:clamp(3px,1.33cqh,6px) 10px; }
|
|
1415
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-title { font-size:clamp(11px,3.5cqh,16px); }
|
|
1416
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-spacer { width:clamp(24px,7cqh,32px); }
|
|
1417
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-nav { width:clamp(24px,7cqh,32px); height:clamp(24px,7cqh,32px);
|
|
1418
|
+
font-size:clamp(14px,4cqh,18px); border-radius:clamp(7px,2cqh,9px); }
|
|
1419
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betbar { padding:clamp(2px,.9cqh,4px); }
|
|
1420
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betpill { padding:clamp(2px,.67cqh,3px) clamp(4px,1.1cqh,5px); }
|
|
1421
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betstep { width:clamp(24px,7cqh,32px); height:clamp(24px,7cqh,32px);
|
|
1422
|
+
font-size:clamp(15px,4.4cqh,20px); }
|
|
1423
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval { min-width:clamp(62px,17.5cqh,80px); }
|
|
1424
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval b { font-size:clamp(11px,3.1cqh,14px); }
|
|
1425
|
+
#${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval span { font-size:clamp(6px,1.55cqh,7px); }
|
|
1384
1426
|
|
|
1385
1427
|
/* ═══ base/wide plaque bar — grouped dark + glass panels (reference-style) ═══ */
|
|
1386
1428
|
#${SHELL_ROOT_ID} .ge-zone-plaques { gap:0; } /* panels connect; buttons overlap */
|
|
@@ -1954,7 +1996,7 @@ function openSettingsModal(shell) {
|
|
|
1954
1996
|
|
|
1955
1997
|
// AUTO-GENERATED by scripts/gen-version.mjs — do not edit. Mirrors package.json "version".
|
|
1956
1998
|
/** The @energy8platform/platform-core package version, stamped at build time. */
|
|
1957
|
-
const PACKAGE_VERSION = '0.25.
|
|
1999
|
+
const PACKAGE_VERSION = '0.25.2';
|
|
1958
2000
|
|
|
1959
2001
|
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
1960
2002
|
function openGameInfoModal(shell) {
|
|
@@ -2609,7 +2651,7 @@ function buildReplayModal(shell, opts) {
|
|
|
2609
2651
|
row('Base bet', fmt(bet));
|
|
2610
2652
|
row('Cost multiplier', `${costMultiplier}×`);
|
|
2611
2653
|
row('Total cost', fmt(bet * costMultiplier));
|
|
2612
|
-
row('
|
|
2654
|
+
row('Win multiplier', `${payoutMultiplier}×`);
|
|
2613
2655
|
row('Total win', fmtWin(payoutMultiplier * bet), true);
|
|
2614
2656
|
ui.body.appendChild(rows);
|
|
2615
2657
|
const actions = document.createElement('div');
|
|
@@ -2694,6 +2736,7 @@ const RULES = [
|
|
|
2694
2736
|
['pay out', 'win / won'],
|
|
2695
2737
|
['paid out', 'won'],
|
|
2696
2738
|
['pays out', 'win'],
|
|
2739
|
+
['payout', 'win'], // single word; "pay out" (spaced) is handled above
|
|
2697
2740
|
['paytable', 'win table'],
|
|
2698
2741
|
['paylines', 'winlines'],
|
|
2699
2742
|
['payline', 'winline'],
|
|
@@ -2848,20 +2891,29 @@ class GameShell extends EventEmitter {
|
|
|
2848
2891
|
}
|
|
2849
2892
|
return;
|
|
2850
2893
|
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
//
|
|
2854
|
-
|
|
2894
|
+
// Scale the bar to the SCREEN, not the mode. Two independent limits, whichever bites harder:
|
|
2895
|
+
// • width — the row mustn't exceed the frame (base's wide row hits this); and
|
|
2896
|
+
// • height — the bar mustn't eat more than BAR_MAX_FRACTION of a SHORT frame. Replay's narrow
|
|
2897
|
+
// row never overflows width, so without this it stayed full-size and ate ~47% of a Popout S
|
|
2898
|
+
// frame, overlapping the reels — while base (wide row) shrank to ~27%. Now every mode tracks
|
|
2899
|
+
// the frame size the same way.
|
|
2900
|
+
// Lift the WIN pill onto its own line first when the full-width row overflows (controls stay big).
|
|
2901
|
+
if (pill && bar.scrollWidth > bar.clientWidth + 1) {
|
|
2855
2902
|
host.insertBefore(pill, bar);
|
|
2856
2903
|
pill.classList.add('ge-up');
|
|
2857
2904
|
}
|
|
2858
|
-
|
|
2859
|
-
return; // bar now fits full-width, pill above
|
|
2860
|
-
// still too wide → shrink the whole stack (pill + bar) to fit, anchored bottom-centre
|
|
2905
|
+
// Measure natural CONTENT size — `.ge-fit` makes the bar shrink-to-content (width:max-content).
|
|
2861
2906
|
host.classList.add('ge-fit');
|
|
2862
|
-
const
|
|
2863
|
-
const
|
|
2864
|
-
host.
|
|
2907
|
+
const availW = this.root.clientWidth - 12;
|
|
2908
|
+
const availH = this.root.clientHeight * GameShell.BAR_MAX_FRACTION;
|
|
2909
|
+
const naturalW = host.offsetWidth, naturalH = host.offsetHeight;
|
|
2910
|
+
const s = Math.min(1, naturalW > 0 ? availW / naturalW : 1, naturalH > 0 ? availH / naturalH : 1);
|
|
2911
|
+
if (s < 0.999) {
|
|
2912
|
+
host.style.transform = `translateX(-50%) scale(${s.toFixed(4)})`;
|
|
2913
|
+
}
|
|
2914
|
+
else {
|
|
2915
|
+
host.classList.remove('ge-fit'); // fits full-size → restore the normal full-width bar
|
|
2916
|
+
}
|
|
2865
2917
|
}
|
|
2866
2918
|
/** Spacebar starts a spin — same path as the spin disc. Ignored when `features.spacebar` is
|
|
2867
2919
|
* false, while a spin is running, while autoplay is active, outside base mode, when an
|
|
@@ -2974,6 +3026,9 @@ class GameShell extends EventEmitter {
|
|
|
2974
3026
|
/** Fraction of the frame a card modal may occupy; the rest is breathing-room margin. Keeps
|
|
2975
3027
|
* modals from filling a small popout edge-to-edge (so even short pickers scale down there). */
|
|
2976
3028
|
static MODAL_FIT = 0.86;
|
|
3029
|
+
/** Max fraction of the frame HEIGHT the bottom bar may occupy before it fit-scales down. Keeps the
|
|
3030
|
+
* bar a consistent, small slice on short popouts in EVERY mode (base ≈ this already via width). */
|
|
3031
|
+
static BAR_MAX_FRACTION = 0.27;
|
|
2977
3032
|
fitSheet(root) {
|
|
2978
3033
|
const card = root.querySelector('.ge-modal-card');
|
|
2979
3034
|
if (!card)
|