@energy8platform/platform-core 0.25.4 → 0.26.1

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.
@@ -151,6 +151,21 @@ export const SHELL_CSS = SHELL_FONT_CSS + `
151
151
  #${SHELL_ROOT_ID} .ge-gi-version { text-align:center; color:var(--shell-muted); font-size:11px;
152
152
  letter-spacing:.08em; opacity:.7; margin:4px 0 2px; }
153
153
 
154
+ /* hotkeys — keycap chips → localized action label, mirrors controls row layout */
155
+ #${SHELL_ROOT_ID} .ge-gi-hk-block { display:flex; flex-direction:column; }
156
+ #${SHELL_ROOT_ID} .ge-gi-hk { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:9px 0; }
157
+ #${SHELL_ROOT_ID} .ge-gi-hk + .ge-gi-hk { border-top:1px solid var(--shell-plaque-line); }
158
+ #${SHELL_ROOT_ID} .ge-gi-hk-chips { display:flex; align-items:center; flex-wrap:wrap; gap:4px; flex:0 0 auto; }
159
+ #${SHELL_ROOT_ID} .ge-gi-hk-combo { display:inline-flex; align-items:center; gap:4px; }
160
+ #${SHELL_ROOT_ID} .ge-gi-hk-chip { display:inline-flex; align-items:center; justify-content:center;
161
+ padding:2px 7px; border-radius:6px; border:1px solid var(--shell-plaque-line);
162
+ background:var(--shell-plaque-dark); color:#fff;
163
+ font-family:'SFMono-Regular',Consolas,'Liberation Mono',Menlo,monospace; font-size:12px;
164
+ font-weight:600; line-height:1.5; white-space:nowrap; min-width:1.6em; text-align:center; }
165
+ #${SHELL_ROOT_ID} .ge-gi-hk-sep { color:var(--shell-plaque-label); font-size:11px; padding:0 1px; }
166
+ #${SHELL_ROOT_ID} .ge-gi-hk-sep2 { color:var(--shell-plaque-label); font-size:11px; padding:0 4px; }
167
+ #${SHELL_ROOT_ID} .ge-gi-hk-tx { color:rgba(255,255,255,.88); font-size:14px; font-weight:600; text-align:right; flex:1; }
168
+
154
169
  /* controls — two blocks (gameplay / menu & info), icon/name/description per control */
155
170
  #${SHELL_ROOT_ID} .ge-gi-ctl-block + .ge-gi-ctl-block { margin-top:16px; padding-top:4px; border-top:1px solid var(--shell-plaque-line); }
156
171
  #${SHELL_ROOT_ID} .ge-gi-ctl-block-h { color:var(--shell-plaque-label); font-size:11px; letter-spacing:.12em;
@@ -245,20 +260,26 @@ export const SHELL_CSS = SHELL_FONT_CSS + `
245
260
  #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-body { max-width:none; padding:clamp(6px,2.5cqh,16px) clamp(12px,3vw,28px); }
246
261
  #${SHELL_ROOT_ID} .ge-bb-grid { display:flex; gap:14px; justify-content:safe center; overflow-x:auto; overflow-y:hidden; padding-bottom:6px;
247
262
  scroll-snap-type:x proximity; -webkit-overflow-scrolling:touch; }
248
- /* the one knob that scales the whole card cqh measures the overlay (popout frame), not the
249
- browser window, so cards shrink to fit the real container height. The floor is deliberately tiny:
250
- on a 400×225 popout the whole card (incl. the CTA) only fits below ~5px, and a fully visible,
251
- single-axis-scrolling card beats a bigger one whose button is clipped or needs a 2nd scrollbar. */
263
+ /* the one knob that scales the whole card (its whole layout is em-relative). It is the SMALLER of two
264
+ fits, so the card is always fully visible:
265
+ 3.4cqh height: the card stays inside the band between the header and the bet footer (cqh
266
+ measures the overlay popout frame, not the browser window);
267
+ • 84cqw / (N*18) — width: the N cards (each 18em) fit the frame width side-by-side instead of
268
+ overflowing into an X-scroll. --ge-bb-n is the live card count, set in BuyBonus.ts.
269
+ Floor is deliberately tiny: on a 400×225 popout a fully visible card beats a bigger clipped one. */
252
270
  #${SHELL_ROOT_ID} .ge-bb-grid .ge-bonus-card { flex:0 0 18em; scroll-snap-align:start;
253
- font-size:clamp(4px, 3.4cqh, 12px); }
254
- /* mobile: vertical stack at a fixed, readable size — scroll the list, don't shrink the cards */
271
+ font-size:clamp(4px, min(3.4cqh, calc(84cqw / (var(--ge-bb-n,3) * 18))), 12px); }
272
+ /* mobile: vertical stack at a fixed, readable size — scroll the list; only shrink if the card would
273
+ be wider than the frame (very narrow viewport), so it never overflows horizontally. */
255
274
  #${SHELL_ROOT_ID}.ge-mobile .ge-bb-grid { display:flex; flex-direction:column; gap:14px; overflow:visible; }
256
- #${SHELL_ROOT_ID}.ge-mobile .ge-bb-grid .ge-bonus-card { flex:0 0 auto; font-size:12px; }
275
+ #${SHELL_ROOT_ID}.ge-mobile .ge-bb-grid .ge-bonus-card { flex:0 0 auto; font-size:min(12px, calc(92cqw / 18)); }
257
276
  #${SHELL_ROOT_ID} .ge-bonus-card { display:flex; flex-direction:column; border-radius:1.4em; overflow:hidden;
258
277
  background:var(--shell-plaque-glass); border:1px solid var(--shell-plaque-line); color:#fff; text-align:center;
259
278
  pointer-events:auto; cursor:pointer; transition:box-shadow .12s ease, background .12s ease; }
260
279
  #${SHELL_ROOT_ID} .ge-bonus-card:hover:not(.ge-bonus-off) {
261
280
  box-shadow:0 0 0 1px var(--card-acc), 0 12px 34px -12px var(--card-acc); }
281
+ #${SHELL_ROOT_ID} .ge-bonus-card--kbd-focus:not(.ge-bonus-off) {
282
+ box-shadow:0 0 0 1px var(--card-acc), 0 12px 34px -12px var(--card-acc); }
262
283
  /* custom card (BonusOption.custom): keep grid sizing + accent vars, drop the default chrome so the game owns the UI */
263
284
  #${SHELL_ROOT_ID} .ge-bonus-card--custom { background:none; border:none; cursor:default; }
264
285
  #${SHELL_ROOT_ID} .ge-bonus-body { display:flex; flex-direction:column; align-items:center; flex:1; padding:1.25em 1.1em .9em; }
@@ -314,13 +335,15 @@ export const SHELL_CSS = SHELL_FONT_CSS + `
314
335
  #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-spacer { width:clamp(24px,7cqh,32px); }
315
336
  #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-ov-nav { width:clamp(24px,7cqh,32px); height:clamp(24px,7cqh,32px);
316
337
  font-size:clamp(14px,4cqh,18px); border-radius:clamp(7px,2cqh,9px); }
317
- #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betbar { padding:clamp(2px,.9cqh,4px); }
318
- #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betpill { padding:clamp(2px,.67cqh,3px) clamp(4px,1.1cqh,5px); }
319
- #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betstep { width:clamp(24px,7cqh,32px); height:clamp(24px,7cqh,32px);
320
- font-size:clamp(15px,4.4cqh,20px); }
321
- #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval { min-width:clamp(62px,17.5cqh,80px); }
322
- #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval b { font-size:clamp(11px,3.1cqh,14px); }
323
- #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval span { font-size:clamp(6px,1.55cqh,7px); }
338
+ /* the bet pill read too large next to the shrunk cards — size it ~0. across the board (the floors
339
+ stay readable; the maxima are what dominate on Popout L / wide frames). */
340
+ #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betbar { padding:clamp(2px,.75cqh,3px); }
341
+ #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betpill { padding:clamp(2px,.55cqh,3px) clamp(3px,.9cqh,4px); }
342
+ #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betstep { width:clamp(20px,5.7cqh,26px); height:clamp(20px,5.7cqh,26px);
343
+ font-size:clamp(12px,3.5cqh,16px); }
344
+ #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval { min-width:clamp(50px,14cqh,66px); }
345
+ #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval b { font-size:clamp(9px,2.5cqh,11px); }
346
+ #${SHELL_ROOT_ID} [data-ge="buybonus-overlay"] .ge-bb-betval span { font-size:clamp(5px,1.25cqh,6px); }
324
347
 
325
348
  /* ═══ base/wide plaque bar — grouped dark + glass panels (reference-style) ═══ */
326
349
  #${SHELL_ROOT_ID} .ge-zone-plaques { gap:0; } /* panels connect; buttons overlap */
@@ -117,6 +117,7 @@ export interface GameMode {
117
117
  export type GameInfoSection =
118
118
  | { type: 'modes'; title?: string; order?: number; modes: GameMode[] }
119
119
  | { type: 'controls'; title?: string; order?: number }
120
+ | { type: 'hotkeys'; title?: string; order?: number }
120
121
  | { type: 'paytable'; title?: string; order?: number; rows: PaytableRow[] }
121
122
  | WinSection
122
123
  | { type: 'custom'; title?: string; order?: number; node?: HTMLElement; html?: string };
@@ -135,6 +136,9 @@ export interface AutoplayConfig {
135
136
 
136
137
  export interface ShellFeatures {
137
138
  turbo: 0 | 1 | 2 | 3;
139
+ /** Master keyboard-shortcut switch. Defaults to `true`; set `false` to disable ALL hotkeys
140
+ * (overrides `spacebar` and any future hotkey). */
141
+ hotkeys?: boolean;
138
142
  /** Spacebar starts a spin in base mode. Defaults to `true`; set `false` to disable the
139
143
  * keyboard shortcut (e.g. jurisdictions that forbid quick-spin keys). */
140
144
  spacebar?: boolean;
@@ -187,6 +191,10 @@ export interface ModalOptions {
187
191
  actions?: ModalAction[];
188
192
  /** Backdrop blur in px (defaults to the shell's standard blur). */
189
193
  blurLevel?: number;
194
+ /** Optional keyboard handler — called by the shell keyboard controller while this modal is
195
+ * open. Return true to consume the key (prevents bar actions + Escape close); false to let
196
+ * the controller handle it (Escape → closeModal). */
197
+ onKey?: (e: KeyboardEvent) => boolean;
190
198
  }
191
199
 
192
200
  export interface ShellConfig {
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED by scripts/gen-version.mjs — do not edit. Mirrors package.json "version".
2
2
  /** The @energy8platform/platform-core package version, stamped at build time. */
3
- export const PACKAGE_VERSION = '0.25.4';
3
+ export const PACKAGE_VERSION = '0.26.1';
package/src/types.ts CHANGED
@@ -3,6 +3,8 @@
3
3
  // Phaser/Three/custom-engine consumers import these from
4
4
  // `@energy8platform/platform-core` instead of pulling in game-engine.
5
5
 
6
+ import type { PreloaderVariantName } from './loading/variants';
7
+
6
8
  // SDK types
7
9
  export type {
8
10
  InitData,
@@ -43,6 +45,12 @@ export interface AssetManifest {
43
45
  // engine-specific loading scenes (in @energy8platform/game-engine etc.).
44
46
 
45
47
  export interface LoadingScreenConfig {
48
+ /**
49
+ * Which visual identity the CSS preloader renders. Defaults to `'energy8'`;
50
+ * an unknown value falls back to the default. Ignored when `cssPreloaderHTML`
51
+ * is set (custom HTML bypasses the variant).
52
+ */
53
+ preloaderVariant?: PreloaderVariantName;
46
54
  /** Background color (hex number or CSS string) */
47
55
  backgroundColor?: number | string;
48
56
  /** Background gradient (CSS string applied to the CSS preloader) */