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