@open-slot-ui/pixi 0.7.0 → 0.8.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.
package/dist/index.cjs CHANGED
@@ -3985,16 +3985,327 @@ var PanelBodyView = class extends ControlView {
3985
3985
  super.dispose();
3986
3986
  }
3987
3987
  };
3988
+ var esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
3989
+ var rich = (s) => esc(s).replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
3990
+ function renderBlocks(blocks, tr) {
3991
+ const out = [];
3992
+ for (const b of blocks) {
3993
+ switch (b.kind) {
3994
+ case "text":
3995
+ out.push(`<p>${rich(tr(b.text))}</p>`);
3996
+ break;
3997
+ case "heading":
3998
+ out.push(`<div class="ohm-sec"><span>${esc(tr(b.text))}</span></div>`);
3999
+ break;
4000
+ case "subheading":
4001
+ out.push(`<h4 class="ohm-subh">${esc(tr(b.text))}</h4>`);
4002
+ break;
4003
+ case "legal":
4004
+ out.push(`<p class="ohm-legal">${rich(tr(b.text))}</p>`);
4005
+ break;
4006
+ case "divider":
4007
+ out.push('<hr class="ohm-hr">');
4008
+ break;
4009
+ case "image":
4010
+ out.push(`<img class="ohm-feature" alt="${esc(tr(b.alt ?? ""))}" src="${b.src}" loading="lazy">`);
4011
+ break;
4012
+ case "media": {
4013
+ const img = `<img alt="${esc(tr(b.alt ?? ""))}" src="${b.src}" loading="lazy">`;
4014
+ const body = `<div class="ohm-media-body">${b.title ? `<h4>${esc(tr(b.title))}</h4>` : ""}<p>${rich(tr(b.text))}</p></div>`;
4015
+ out.push(`<div class="ohm-media ohm-media--${b.side ?? "left"}">${img}${body}</div>`);
4016
+ break;
4017
+ }
4018
+ case "cards": {
4019
+ const cards = b.items.map((it) => `<div class="ohm-fcard">${it.icon ? `<img src="${it.icon}" alt="" loading="lazy">` : ""}<h5>${esc(tr(it.title))}</h5>${it.text ? `<p>${rich(tr(it.text))}</p>` : ""}</div>`).join("");
4020
+ out.push(`<div class="ohm-cards">${cards}</div>`);
4021
+ break;
4022
+ }
4023
+ case "paytable":
4024
+ out.push(`<div class="ohm-grid">${renderPaytable(b.rows, tr)}</div>`);
4025
+ break;
4026
+ case "table": {
4027
+ const head = b.columns?.length ? `<thead><tr>${b.columns.map((c) => `<th>${esc(tr(c))}</th>`).join("")}</tr></thead>` : "";
4028
+ const body = b.rows.map((r) => `<tr>${r.map((c) => `<td>${esc(tr(c))}</td>`).join("")}</tr>`).join("");
4029
+ out.push(`<table class="ohm-table">${head}<tbody>${body}</tbody></table>`);
4030
+ break;
4031
+ }
4032
+ case "stat-grid": {
4033
+ const rows = b.items.map((it) => `<div><dt>${esc(tr(it.label))}</dt><dd>${esc(tr(it.value))}</dd></div>`).join("");
4034
+ out.push(`<dl class="ohm-stats">${rows}</dl>`);
4035
+ break;
4036
+ }
4037
+ case "steps": {
4038
+ const items = b.items.map((s) => `<li>${rich(tr(s))}</li>`).join("");
4039
+ out.push(b.ordered ? `<ol class="ohm-steps">${items}</ol>` : `<ul class="ohm-steps">${items}</ul>`);
4040
+ break;
4041
+ }
4042
+ case "callout":
4043
+ out.push(`<div class="ohm-callout ohm-callout--${b.tone ?? "info"}">${b.title ? `<b>${esc(tr(b.title))}</b>` : ""}<p>${rich(tr(b.text))}</p></div>`);
4044
+ break;
4045
+ case "group":
4046
+ out.push(`<div class="ohm-group">${b.title ? `<h4 class="ohm-subh">${esc(tr(b.title))}</h4>` : ""}${renderBlocks(b.children, tr)}</div>`);
4047
+ break;
4048
+ }
4049
+ }
4050
+ return out.join("\n");
4051
+ }
4052
+ function renderPaytable(rows, tr) {
4053
+ return rows.map((r) => {
4054
+ const icon = r.icon ? `<img class="ohm-symimg" src="${r.icon}" alt="" loading="lazy">` : `<span class="ohm-emoji">${esc(tr(r.symbol ?? ""))}</span>`;
4055
+ const lines = r.payouts.split("\n").map((line) => {
4056
+ const i = line.indexOf(":");
4057
+ return i >= 0 ? `<div><b>${esc(line.slice(0, i))}</b><span>${esc(line.slice(i + 1))}</span></div>` : `<div><span>${esc(line)}</span></div>`;
4058
+ }).join("");
4059
+ return `<div class="ohm-sym">${icon}<div class="ohm-pay">${lines}</div></div>`;
4060
+ }).join("");
4061
+ }
4062
+ function renderSettingBlock(b, tr) {
4063
+ const hint = "hint" in b && b.hint ? `<div class="ohm-hint">${esc(tr(b.hint))}</div>` : "";
4064
+ const label = "label" in b && b.label ? esc(tr(b.label)) : "";
4065
+ switch (b.kind) {
4066
+ case "toggle":
4067
+ return `<div class="ohm-setting"><label class="ohm-row ohm-check"><span>${label}</span><span class="ohm-ctl"><input data-set="${b.id}" type="checkbox"${b.on ? " checked" : ""}></span></label>${hint}</div>`;
4068
+ case "slider":
4069
+ return `<div class="ohm-setting"><label class="ohm-row"><span>${label}</span><input data-set="${b.id}" type="range" min="0" max="1" step="0.01" value="${b.initial ?? 1}"></label>${hint}</div>`;
4070
+ case "select": {
4071
+ const opts = b.options.map((o, i) => `<option value="${esc(o.value)}"${i === (b.index ?? 0) ? " selected" : ""}>${esc(tr(o.label))}</option>`).join("");
4072
+ return `<div class="ohm-setting"><label class="ohm-row"><span>${label}</span><select data-set="${b.id}">${opts}</select></label>${hint}</div>`;
4073
+ }
4074
+ default:
4075
+ return "";
4076
+ }
4077
+ }
4078
+ function mountInfoMenu(app, ui) {
4079
+ const menu = ui.spec?.menu ?? {};
4080
+ const tr = (k) => ui.t(k);
4081
+ const disposers = [];
4082
+ const host2 = document.createElement("div");
4083
+ host2.className = "ohm-root";
4084
+ const vars = {
4085
+ "--accent": "#d99000",
4086
+ "--accent-text": "#1a1200",
4087
+ "--surface": "#ffffff",
4088
+ "--surface-alt": "#eef1f6",
4089
+ "--text": "#181b20",
4090
+ "--text-dim": "#5b6472",
4091
+ "--card-radius": "8px",
4092
+ "--font": ui.theme.type.family
4093
+ };
4094
+ for (const [k, v] of Object.entries(vars)) host2.style.setProperty(k, v);
4095
+ const locales = ui.spec?.locale ? Array.from(/* @__PURE__ */ new Set([ui.spec.locale.locale, ...Object.keys(ui.spec.locale.messages)])) : [];
4096
+ const langRow = locales.length > 1 ? `<div class="ohm-setting"><label class="ohm-row"><span>${tr("Language")}</span><select id="ohm-lang">${locales.map((c) => `<option value="${c}"${c === ui.locale.get() ? " selected" : ""}>${esc(core.LOCALE_LABELS[c] ?? c)}</option>`).join("")}</select></label></div>` : "";
4097
+ const turbo = ui.turbo;
4098
+ const cap = (m) => m.charAt(0).toUpperCase() + m.slice(1);
4099
+ const turboCtl = turbo.modeCount <= 2 ? `<span class="ohm-ctl"><input id="ohm-turbo" type="checkbox"></span>` : `<span class="ohm-ctl"><div class="ohm-segmented" id="ohm-turbo-seg">${turbo.modes.map((m, i) => `<button class="ohm-seg" data-i="${i}">${esc(tr(cap(m)))}</button>`).join("")}</div></span>`;
4100
+ const customSettings = (menu.settings ?? []).map((b) => renderSettingBlock(b, tr)).join("");
4101
+ const soundMode = menu.sound ?? "sliders";
4102
+ const volRow = (id, label, hint, val) => `<div class="ohm-setting"><label class="ohm-row"><span>${esc(tr(label))}</span><input class="ohm-slider" data-vol="${id}" type="range" min="0" max="1" step="0.01" value="${val}"></label><div class="ohm-hint">${esc(tr(hint))}</div></div>`;
4103
+ const soundSliders = soundMode === "master" ? volRow("master", "Volume", "Adjust the overall game volume.", ui.sfxSlider.value.get()) : soundMode === "sliders" ? volRow("music", "Music", "Adjust the background music volume.", ui.musicSlider.value.get()) + volRow("sfx", "Effects", "Adjust the sound-effects volume.", ui.sfxSlider.value.get()) : "";
4104
+ const paytableHtml = menu.paytable ? renderBlocks(menu.paytable, tr) : "";
4105
+ const rulesHtml = menu.rules ? renderBlocks(menu.rules, tr) : "";
4106
+ const banner = menu.banner ? `<img class="ohm-logo" alt="" src="${menu.banner.src}"${menu.banner.width ? ` width="${menu.banner.width}"` : ""}${menu.banner.height ? ` height="${menu.banner.height}"` : ""}>` : ui.gameInfo.name ? `<h1 class="ohm-logo-text">${esc(ui.gameInfo.name)}</h1>` : "";
4107
+ host2.innerHTML = `
4108
+ <div class="ohm-backdrop" data-close></div>
4109
+ <button class="ohm-x" data-close aria-label="Close">\u2715</button>
4110
+ <div class="ohm-card" role="dialog" aria-modal="true">
4111
+ <div class="ohm-body">
4112
+ ${banner}
4113
+ <div class="ohm-sec"><span>${tr("Settings")}</span></div>
4114
+ <div class="ohm-setting"><label class="ohm-row ohm-check"><span>${tr("Sound")}</span><span class="ohm-ctl"><input id="ohm-sound" type="checkbox" checked></span></label><div class="ohm-hint">${tr("Turn all game sound and music on or off.")}</div></div>
4115
+ ${soundSliders}
4116
+ ${langRow}
4117
+ <div class="ohm-setting"><div class="ohm-row ohm-check"><span>${tr("Quick spin")}</span>${turboCtl}</div><div class="ohm-hint">${tr("Speed up rounds by shortening the animation. The result is identical.")}</div></div>
4118
+ ${customSettings}
4119
+ ${paytableHtml ? `<div class="ohm-sec"><span>${tr("Paytable")}</span></div>${paytableHtml}` : ""}
4120
+ ${rulesHtml ? `<div class="ohm-sec"><span>${tr("Rules")}</span></div><div class="ohm-rules" id="ohm-rules">${rulesHtml}</div>` : ""}
4121
+ </div>
4122
+ </div>`;
4123
+ const style = document.createElement("style");
4124
+ style.textContent = OHM_CSS;
4125
+ host2.appendChild(style);
4126
+ document.body.appendChild(host2);
4127
+ const $ = (sel) => host2.querySelector(sel);
4128
+ const sound = $("#ohm-sound");
4129
+ if (sound) {
4130
+ sound.checked = !ui.muted.get();
4131
+ sound.addEventListener("change", () => ui.setMuted(!sound.checked));
4132
+ disposers.push(ui.muted.subscribe((m) => {
4133
+ sound.checked = !m;
4134
+ }));
4135
+ }
4136
+ host2.querySelectorAll("[data-vol]").forEach((el) => {
4137
+ const which = el.dataset.vol;
4138
+ el.addEventListener("input", () => {
4139
+ const v = Number(el.value);
4140
+ if (which === "music") ui.musicSlider.setNormalized(v);
4141
+ else if (which === "sfx") ui.sfxSlider.setNormalized(v);
4142
+ else {
4143
+ ui.musicSlider.setNormalized(v);
4144
+ ui.sfxSlider.setNormalized(v);
4145
+ }
4146
+ });
4147
+ const src = which === "music" ? ui.musicSlider : ui.sfxSlider;
4148
+ disposers.push(src.value.subscribe((v) => {
4149
+ el.value = String(v);
4150
+ }));
4151
+ });
4152
+ const lang = $("#ohm-lang");
4153
+ if (lang) lang.addEventListener("change", () => ui.setLocale(lang.value));
4154
+ if (turbo.modeCount <= 2) {
4155
+ const tg = $("#ohm-turbo");
4156
+ if (tg) {
4157
+ tg.checked = turbo.isOn;
4158
+ tg.addEventListener("change", () => turbo.set(tg.checked));
4159
+ disposers.push(turbo.index.subscribe(() => {
4160
+ tg.checked = turbo.isOn;
4161
+ }));
4162
+ }
4163
+ } else {
4164
+ const segs = Array.from(host2.querySelectorAll(".ohm-seg"));
4165
+ segs.forEach((b) => b.addEventListener("click", () => turbo.setIndex(Number(b.dataset.i))));
4166
+ const sync = () => segs.forEach((b, i) => b.classList.toggle("active", i === turbo.index.get()));
4167
+ disposers.push(turbo.index.subscribe(sync));
4168
+ sync();
4169
+ }
4170
+ host2.querySelectorAll("[data-set]").forEach((el) => {
4171
+ const id = el.dataset.set;
4172
+ if (el instanceof HTMLInputElement && el.type === "checkbox") el.addEventListener("change", () => ui.bus.emit("toggled", { id, on: el.checked }));
4173
+ else if (el instanceof HTMLInputElement && el.type === "range") el.addEventListener("input", () => ui.bus.emit("valueChanged", { id, value: Number(el.value) }));
4174
+ else if (el instanceof HTMLSelectElement) el.addEventListener("change", () => ui.bus.emit("optionSelected", { id, value: el.value, index: el.selectedIndex }));
4175
+ });
4176
+ host2.querySelectorAll("[data-close]").forEach((b) => b.addEventListener("click", () => ui.settingsPanel.closePanel()));
4177
+ disposers.push(
4178
+ ui.locale.subscribe(() => {
4179
+ const body = host2.querySelector(".ohm-body");
4180
+ if (body) {
4181
+ const rulesEl = host2.querySelector("#ohm-rules");
4182
+ if (rulesEl && menu.rules) rulesEl.innerHTML = renderBlocks(menu.rules, tr);
4183
+ if (lang) lang.value = ui.locale.get();
4184
+ }
4185
+ })
4186
+ );
4187
+ disposers.push(ui.settingsPanel.state.subscribe(() => host2.classList.toggle("open", ui.settingsPanel.isOpen)));
4188
+ return () => {
4189
+ for (const d of disposers.splice(0)) d();
4190
+ host2.remove();
4191
+ };
4192
+ }
4193
+ var OHM_CSS = `
4194
+ .ohm-root { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; font-family: var(--font); opacity: 0; pointer-events: none; transition: opacity .18s ease; }
4195
+ .ohm-root.open { opacity: 1; pointer-events: auto; }
4196
+ .ohm-backdrop { position: absolute; inset: 0; background: rgba(8,6,4,0); backdrop-filter: blur(0px) saturate(1); -webkit-backdrop-filter: blur(0px) saturate(1); transition: background .4s ease, backdrop-filter .4s ease, -webkit-backdrop-filter .4s ease; }
4197
+ .ohm-root.open .ohm-backdrop { background: rgba(8,6,4,.34); backdrop-filter: blur(6px) saturate(1.1); -webkit-backdrop-filter: blur(6px) saturate(1.1); }
4198
+ .ohm-card { position: relative; width: min(92%, 1100px); max-height: 86vh; display: flex; flex-direction: column; background: var(--surface); color: var(--text); border: 1.5px solid #000; border-radius: var(--card-radius); box-shadow: 0 30px 80px rgba(0,0,0,.5); overflow: hidden; transform: translateY(8px) scale(.99); transition: transform .18s ease; }
4199
+ .ohm-root.open .ohm-card { transform: none; }
4200
+ .ohm-x { position: absolute; top: 18px; right: 22px; width: 46px; height: 46px; border-radius: 999px; border: 0; background: rgba(18,14,10,.82); color: #fff; font-size: 18px; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 18px rgba(0,0,0,.45); z-index: 2; transition: transform .12s, background .12s; }
4201
+ .ohm-x:hover { transform: scale(1.08); background: rgba(18,14,10,.95); }
4202
+ .ohm-body { padding: 24px 26px 26px; overflow-y: scroll; }
4203
+ .ohm-body::-webkit-scrollbar { width: 18px; }
4204
+ .ohm-body::-webkit-scrollbar-track { background: transparent; margin: 12px 0; }
4205
+ .ohm-body::-webkit-scrollbar-thumb { background-color: #111; border: 6px solid transparent; background-clip: padding-box; border-radius: 999px; min-height: 44px; }
4206
+ .ohm-body::-webkit-scrollbar-thumb:hover { background-color: #000; }
4207
+ .ohm-logo { display: block; margin: 6px auto 18px; max-width: 64%; height: auto; }
4208
+ .ohm-logo-text { margin: 6px 0 18px; text-align: center; font-size: 30px; font-weight: 900; letter-spacing: 1px; color: var(--text); }
4209
+ .ohm-sec { display: flex; align-items: center; gap: 14px; margin: 26px 0 14px; color: var(--text); font-weight: 800; letter-spacing: 1px; }
4210
+ .ohm-sec::before, .ohm-sec::after { content: ""; flex: 1; height: 2px; background: color-mix(in srgb, var(--text) 80%, transparent); border-radius: 2px; }
4211
+ .ohm-root *, .ohm-root *::before, .ohm-root *::after { box-sizing: border-box; }
4212
+ .ohm-row { display: flex; align-items: center; gap: 16px; margin: 14px 0; font-weight: 700; }
4213
+ .ohm-setting { margin: 14px 0; }
4214
+ .ohm-setting .ohm-row { margin: 0; }
4215
+ .ohm-hint { margin: 3px 0 0; font-size: 12.5px; font-weight: 500; color: var(--text-dim); }
4216
+ .ohm-row > span:first-child { flex: none; min-width: 110px; }
4217
+ .ohm-row input[type=range] { flex: 1; min-width: 0; max-width: min(440px, 60dvw); accent-color: var(--accent); height: 6px; }
4218
+ .ohm-row select { flex: 1; min-width: 0; max-width: min(440px, 60dvw); padding: 11px 14px; border-radius: 4px; border: 2px solid var(--accent); background: var(--surface-alt); color: var(--text); font-weight: 700; font-size: 15px; cursor: pointer; }
4219
+ .ohm-row select option { background: var(--surface); color: var(--text); font-weight: 600; }
4220
+ .ohm-row select option:checked { background: var(--accent); color: var(--accent-text); }
4221
+ .ohm-ctl { flex: 1; min-width: 0; max-width: min(440px, 60dvw); display: flex; align-items: center; justify-content: flex-end; }
4222
+ .ohm-check input[type=checkbox] { appearance: none; -webkit-appearance: none; width: 50px; height: 28px; border-radius: 999px; background: color-mix(in srgb, var(--text-dim) 38%, transparent); position: relative; cursor: pointer; transition: background .15s; flex: none; }
4223
+ .ohm-check input[type=checkbox]:checked { background: var(--accent); }
4224
+ .ohm-check input[type=checkbox]::before { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 999px; background: #fff; transition: left .15s; box-shadow: 0 1px 3px rgba(0,0,0,.3); }
4225
+ .ohm-check input[type=checkbox]:checked::before { left: 25px; }
4226
+ .ohm-segmented { display: inline-flex; gap: 4px; padding: 4px; background: var(--surface-alt); border-radius: 999px; border: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); }
4227
+ .ohm-seg { border: 0; background: transparent; color: var(--text-dim); font-weight: 700; font-size: 14px; padding: 8px 18px; border-radius: 999px; cursor: pointer; transition: background .12s, color .12s; }
4228
+ .ohm-seg.active { background: var(--accent); color: var(--accent-text); }
4229
+ .ohm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
4230
+ .ohm-sym { display: flex; align-items: center; gap: 16px; padding: 6px 4px; }
4231
+ .ohm-emoji { font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,.3)); }
4232
+ .ohm-symimg { width: 56px; height: 56px; object-fit: contain; flex: none; }
4233
+ .ohm-pay { font-size: 13px; line-height: 1.6; }
4234
+ .ohm-pay div { display: flex; gap: 6px; }
4235
+ .ohm-pay b { min-width: 42px; }
4236
+ .ohm-pay span { color: var(--accent); font-weight: 700; }
4237
+ .ohm-body p { color: var(--text-dim); line-height: 1.6; }
4238
+ .ohm-body p b { color: var(--text); }
4239
+ .ohm-feature { display: block; width: 100%; height: auto; margin: 10px 0; }
4240
+ .ohm-stats { margin: 12px 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }
4241
+ .ohm-stats > div { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 20%, transparent); }
4242
+ .ohm-stats dt { color: var(--text-dim); margin: 0; } .ohm-stats dd { margin: 0; font-weight: 700; }
4243
+ .ohm-callout { margin: 16px 0 4px; padding: 14px 16px; border-radius: 12px; border-left: 4px solid var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
4244
+ .ohm-callout b { color: var(--accent); } .ohm-callout p { margin: 4px 0 0; color: var(--text); }
4245
+ .ohm-callout--warning { border-left-color: #e0a106; background: color-mix(in srgb, #e0a106 10%, transparent); }
4246
+ .ohm-callout--warning b { color: #b07d09; }
4247
+ .ohm-subh { margin: 22px 0 8px; font-size: 15px; font-weight: 800; letter-spacing: .5px; color: var(--text); }
4248
+ .ohm-legal { font-size: 12px; line-height: 1.6; color: var(--text-dim); opacity: .85; }
4249
+ .ohm-hr { border: 0; border-top: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); margin: 18px 0; }
4250
+ .ohm-media { display: flex; align-items: center; gap: 18px; margin: 14px 0; }
4251
+ .ohm-media--right { flex-direction: row-reverse; }
4252
+ .ohm-media > img { width: 40%; max-width: 320px; height: auto; flex: none; }
4253
+ .ohm-media-body { flex: 1; }
4254
+ .ohm-media-body h4 { margin: 0 0 6px; font-size: 16px; color: var(--text); }
4255
+ .ohm-media-body p { margin: 0; }
4256
+ .ohm-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 12px 0; }
4257
+ .ohm-fcard { padding: 8px 6px; text-align: center; }
4258
+ .ohm-fcard img { display: block; width: 48px; height: 48px; margin: 0 auto 8px; }
4259
+ .ohm-fcard h5 { margin: 0 0 4px; font-size: 14px; color: var(--text); }
4260
+ .ohm-fcard p { margin: 0; font-size: 12px; line-height: 1.5; }
4261
+ .ohm-table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; }
4262
+ .ohm-table th { text-align: left; padding: 8px 10px; font-weight: 800; color: var(--text); border-bottom: 2px solid color-mix(in srgb, var(--text-dim) 35%, transparent); }
4263
+ .ohm-table td { padding: 8px 10px; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 18%, transparent); }
4264
+ .ohm-table td:first-child { color: var(--text); font-weight: 700; }
4265
+ .ohm-table td:not(:first-child) { color: var(--accent); font-weight: 700; }
4266
+ .ohm-steps { margin: 12px 0; padding-left: 22px; color: var(--text-dim); line-height: 1.7; }
4267
+ .ohm-steps li { margin: 5px 0; }
4268
+ .ohm-steps b { color: var(--text); }
4269
+ .ohm-group { margin: 8px 0; }
4270
+ `;
4271
+
4272
+ // src/mountHud.ts
4273
+ function showReplayModal(ui, info, buttonKey, onSelect) {
4274
+ const cur = info.currency ?? ui.balance.currency.get();
4275
+ const money = (n) => core.formatAmount(n, cur);
4276
+ ui.showNotice(
4277
+ [
4278
+ { kind: "heading", id: "openui-replay-h", text: "openui.replay.title" },
4279
+ {
4280
+ kind: "stat-grid",
4281
+ id: "openui-replay-g",
4282
+ items: [
4283
+ { label: "openui.replay.baseBet", value: money(info.baseBet) },
4284
+ { label: "openui.replay.costMultiplier", value: `${info.costMultiplier}\xD7` },
4285
+ { label: "openui.replay.payoutMultiplier", value: `${info.payoutMultiplier}\xD7` },
4286
+ { label: "openui.replay.amount", value: money(info.amount) }
4287
+ ]
4288
+ }
4289
+ ],
4290
+ [{ label: buttonKey, variant: "primary", onSelect: () => {
4291
+ ui.hideNotice();
4292
+ onSelect();
4293
+ } }],
4294
+ { blocking: true }
4295
+ );
4296
+ }
3988
4297
  function mountHud(app, spec = {}, opts = {}) {
3989
- const { hooks, ...pixiOpts } = opts;
4298
+ const { hooks, infoMenu, ...pixiOpts } = opts;
3990
4299
  const ui = core.createUI(spec, hooks);
4300
+ const useInfoMenu = infoMenu !== false && pixiOpts.menu !== false;
3991
4301
  const locales = spec.locale ? Array.from(/* @__PURE__ */ new Set([spec.locale.locale, ...Object.keys(spec.locale.messages)])) : [];
3992
- const menu = pixiOpts.menu === false ? false : core.composeMenu(spec.menu, { locales, localeSelectId: spec.localeSelectId, rulesFallback: spec.rules });
4302
+ const menu = pixiOpts.menu === false || useInfoMenu ? false : core.composeMenu(spec.menu, { locales, localeSelectId: spec.localeSelectId, rulesFallback: spec.rules });
3993
4303
  if (menu && spec.game && (spec.game.name || spec.game.version)) {
3994
4304
  menu.push({ kind: "legal", id: "openui-game-info", text: [spec.game.name, spec.game.version ? `v${spec.game.version}` : ""].filter(Boolean).join(" \xB7 ") });
3995
4305
  }
3996
4306
  const pixi = new OpenUIPixi(ui, { ...pixiOpts, menu });
3997
4307
  pixi.mount(app);
4308
+ const disposeInfoMenu = useInfoMenu ? mountInfoMenu(app, ui) : void 0;
3998
4309
  const extra = [];
3999
4310
  if (spec.panels?.length) {
4000
4311
  for (const ps of spec.panels) {
@@ -4015,6 +4326,7 @@ function mountHud(app, spec = {}, opts = {}) {
4015
4326
  });
4016
4327
  const teardown = () => {
4017
4328
  offRelayout();
4329
+ disposeInfoMenu?.();
4018
4330
  for (const v of extra) v.dispose();
4019
4331
  extra.length = 0;
4020
4332
  pixi.unmount();
@@ -4050,30 +4362,10 @@ function mountHud(app, spec = {}, opts = {}) {
4050
4362
  setReplay: (on2) => ui.setReplay(on2),
4051
4363
  replayStart: (info, onPlay) => {
4052
4364
  ui.setReplay(true);
4053
- const cur = info.currency ?? ui.balance.currency.get();
4054
- const money = (n) => core.formatAmount(n, cur);
4055
- ui.showNotice(
4056
- [
4057
- { kind: "heading", id: "openui-replay-h", text: "openui.replay.title" },
4058
- {
4059
- kind: "stat-grid",
4060
- id: "openui-replay-g",
4061
- items: [
4062
- { label: "openui.replay.baseBet", value: money(info.baseBet) },
4063
- { label: "openui.replay.costMultiplier", value: `${info.costMultiplier}\xD7` },
4064
- { label: "openui.replay.payoutMultiplier", value: `${info.payoutMultiplier}\xD7` },
4065
- { label: "openui.replay.amount", value: money(info.amount) }
4066
- ]
4067
- }
4068
- ],
4069
- [{ label: "openui.replay.play", variant: "primary", onSelect: onPlay }]
4070
- );
4365
+ showReplayModal(ui, info, "openui.replay.play", () => onPlay?.());
4071
4366
  },
4072
- replayEnd: (onReplay) => {
4073
- ui.showNotice(
4074
- [{ kind: "heading", id: "openui-replay-end", text: "openui.replay.title" }],
4075
- [{ label: "openui.replay.again", variant: "primary", onSelect: onReplay }]
4076
- );
4367
+ replayEnd: (info, onReplay) => {
4368
+ showReplayModal(ui, info, "openui.replay.again", onReplay);
4077
4369
  },
4078
4370
  confirmBuy: (o) => {
4079
4371
  if (ui.isDisabled("buyFeature")) return;
@@ -4122,7 +4414,7 @@ function mountHud(app, spec = {}, opts = {}) {
4122
4414
 
4123
4415
  // src/bootError.ts
4124
4416
  var host = null;
4125
- var esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4417
+ var esc2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4126
4418
  function showBootError(opts = {}) {
4127
4419
  const title = opts.title ?? "Connection lost";
4128
4420
  const message = opts.message ?? "The game could not reach the game server. Please reload to reconnect and continue.";
@@ -4136,10 +4428,10 @@ function showBootError(opts = {}) {
4136
4428
  <div class="openui-be-icon" aria-hidden="true">
4137
4429
  <svg viewBox="0 0 48 48" width="48" height="48"><path d="M24 4 3 42h42L24 4Z" fill="none" stroke="#ffc935" stroke-width="3" stroke-linejoin="round"/><rect x="22" y="18" width="4" height="12" rx="2" fill="#ffc935"/><circle cx="24" cy="35" r="2.4" fill="#ffc935"/></svg>
4138
4430
  </div>
4139
- <h1 class="openui-be-title">${esc(title)}</h1>
4140
- <p class="openui-be-msg">${esc(message)}</p>
4141
- ${opts.detail ? `<p class="openui-be-detail">${esc(opts.detail)}</p>` : ""}
4142
- ${showReload ? `<button class="openui-be-reload" type="button">${esc(opts.reloadLabel ?? "Reload")}</button>` : ""}
4431
+ <h1 class="openui-be-title">${esc2(title)}</h1>
4432
+ <p class="openui-be-msg">${esc2(message)}</p>
4433
+ ${opts.detail ? `<p class="openui-be-detail">${esc2(opts.detail)}</p>` : ""}
4434
+ ${showReload ? `<button class="openui-be-reload" type="button">${esc2(opts.reloadLabel ?? "Reload")}</button>` : ""}
4143
4435
  </div>
4144
4436
  <style>
4145
4437
  .openui-boot-error { position: fixed; inset: 0; z-index: 2147483000; display: grid; place-items: center;
@@ -4220,6 +4512,7 @@ exports.drawSpin = drawSpin;
4220
4512
  exports.hideBootError = hideBootError;
4221
4513
  exports.isDesktop = isDesktop;
4222
4514
  exports.mountHud = mountHud;
4515
+ exports.mountInfoMenu = mountInfoMenu;
4223
4516
  exports.showBootError = showBootError;
4224
4517
  exports.svgSpinSkin = svgSpinSkin;
4225
4518
  //# sourceMappingURL=index.cjs.map