@open-slot-ui/pixi 0.8.2 → 0.9.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/dist/art.js +1 -1
- package/dist/{chunk-PYXZIGXG.js → chunk-Z7X5JH7H.js} +7 -4
- package/dist/chunk-Z7X5JH7H.js.map +1 -0
- package/dist/index.cjs +170 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +169 -83
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-PYXZIGXG.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -208,6 +208,9 @@ var SpinView = class extends ControlView {
|
|
|
208
208
|
}),
|
|
209
209
|
// re-dim if slam-stop is toggled at runtime (e.g. applyJurisdiction)
|
|
210
210
|
this.spin.allowSlamStop.subscribe(() => this.updateInteractive()),
|
|
211
|
+
// the ref-counted HUD lock (menu / buy modal / blocking notice) gates
|
|
212
|
+
// `spin.interactable` — refresh eventMode/cursor when it flips
|
|
213
|
+
this.ui.locked.subscribe(() => this.updateInteractive()),
|
|
211
214
|
this.spin.onTransition((t) => this.play(t)),
|
|
212
215
|
// free-spins face: switch between the normal skin and the "N FS" counter
|
|
213
216
|
this.spin.freeSpins.subscribe(() => this.updateFaces()),
|
|
@@ -3104,7 +3107,7 @@ var ReadoutView = class extends ControlView {
|
|
|
3104
3107
|
let text;
|
|
3105
3108
|
switch (this.ro.kind) {
|
|
3106
3109
|
case "currency":
|
|
3107
|
-
text = this.ro.currency ? core.
|
|
3110
|
+
text = this.ro.currency ? core.formatAmountPrecise(v, this.ro.currency.get(), { signed: this.ro.signed }) : String(v);
|
|
3108
3111
|
break;
|
|
3109
3112
|
case "percent":
|
|
3110
3113
|
text = `${v.toFixed(this.ro.decimals)}%`;
|
|
@@ -3987,7 +3990,11 @@ var PanelBodyView = class extends ControlView {
|
|
|
3987
3990
|
};
|
|
3988
3991
|
var esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3989
3992
|
var rich = (s) => esc(s).replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
|
|
3990
|
-
function
|
|
3993
|
+
function statGridHtml(items, tr) {
|
|
3994
|
+
const rows = items.map((it) => `<div><dt>${esc(tr(it.label))}</dt><dd>${esc(tr(it.value))}</dd></div>`).join("");
|
|
3995
|
+
return `<dl class="ohm-stats">${rows}</dl>`;
|
|
3996
|
+
}
|
|
3997
|
+
function renderBlocks(blocks, tr, facts) {
|
|
3991
3998
|
const out = [];
|
|
3992
3999
|
for (const b of blocks) {
|
|
3993
4000
|
switch (b.kind) {
|
|
@@ -4029,9 +4036,16 @@ function renderBlocks(blocks, tr) {
|
|
|
4029
4036
|
out.push(`<table class="ohm-table">${head}<tbody>${body}</tbody></table>`);
|
|
4030
4037
|
break;
|
|
4031
4038
|
}
|
|
4032
|
-
case "stat-grid":
|
|
4033
|
-
|
|
4034
|
-
|
|
4039
|
+
case "stat-grid":
|
|
4040
|
+
out.push(statGridHtml(b.items, tr));
|
|
4041
|
+
break;
|
|
4042
|
+
// The AUTO per-mode RTP / Max-win grid — rendered straight from the declared
|
|
4043
|
+
// game facts (+ any host extras), so the table can never drift from the config.
|
|
4044
|
+
// `modeStatsItems` localizes the label PARTS itself ("Max win" · the mode name),
|
|
4045
|
+
// so the grid renderer gets identity-tr — no double translation.
|
|
4046
|
+
case "mode-stats": {
|
|
4047
|
+
const extras = (b.extras ?? []).map((e) => ({ label: tr(e.label), value: tr(e.value) }));
|
|
4048
|
+
out.push(statGridHtml([...core.modeStatsItems(facts, tr), ...extras], (s) => s));
|
|
4035
4049
|
break;
|
|
4036
4050
|
}
|
|
4037
4051
|
case "steps": {
|
|
@@ -4101,8 +4115,30 @@ function mountInfoMenu(app, ui) {
|
|
|
4101
4115
|
const soundMode = menu.sound ?? "sliders";
|
|
4102
4116
|
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
4117
|
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
|
|
4105
|
-
|
|
4118
|
+
const rulesTr = () => {
|
|
4119
|
+
const vars2 = core.factsVars(ui.facts.get(), { "game.name": ui.gameInfo.name ?? "", "game.version": ui.gameInfo.version ?? "" });
|
|
4120
|
+
return (s) => ui.t(s, vars2);
|
|
4121
|
+
};
|
|
4122
|
+
const auditCardHtml = (trr) => {
|
|
4123
|
+
if (!menu.rules?.length) return "";
|
|
4124
|
+
const issues = core.auditRules(ui.facts.get(), menu.rules, { resolve: trr });
|
|
4125
|
+
if (!issues.length) return "";
|
|
4126
|
+
const req = issues.filter((i) => i.level === "required");
|
|
4127
|
+
const rec = issues.filter((i) => i.level === "recommended");
|
|
4128
|
+
const list = (items) => `<ul>${items.map((i) => `<li>${esc(tr(i.message))}</li>`).join("")}</ul>`;
|
|
4129
|
+
return `<div class="ohm-audit" role="alert">
|
|
4130
|
+
<div class="ohm-audit-title">\u26A0 ${esc(tr("openui.rulesAudit.title"))}</div>
|
|
4131
|
+
${req.length ? `<div class="ohm-audit-sub">${esc(tr("openui.rulesAudit.required"))}</div>${list(req)}` : ""}
|
|
4132
|
+
${rec.length ? `<div class="ohm-audit-sub ohm-audit-sub--rec">${esc(tr("openui.rulesAudit.recommended"))}</div><div class="ohm-audit-rec">${list(rec)}</div>` : ""}
|
|
4133
|
+
</div>`;
|
|
4134
|
+
};
|
|
4135
|
+
const rulesInnerHtml = () => {
|
|
4136
|
+
if (!menu.rules) return "";
|
|
4137
|
+
const trr = rulesTr();
|
|
4138
|
+
return auditCardHtml(trr) + renderBlocks(menu.rules, trr, ui.facts.get());
|
|
4139
|
+
};
|
|
4140
|
+
const paytableHtml = menu.paytable ? renderBlocks(menu.paytable, tr, ui.facts.get()) : "";
|
|
4141
|
+
const rulesHtml = rulesInnerHtml();
|
|
4106
4142
|
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
4143
|
host2.innerHTML = `
|
|
4108
4144
|
<div class="ohm-backdrop" data-close></div>
|
|
@@ -4174,19 +4210,40 @@ function mountInfoMenu(app, ui) {
|
|
|
4174
4210
|
else if (el instanceof HTMLSelectElement) el.addEventListener("change", () => ui.bus.emit("optionSelected", { id, value: el.value, index: el.selectedIndex }));
|
|
4175
4211
|
});
|
|
4176
4212
|
host2.querySelectorAll("[data-close]").forEach((b) => b.addEventListener("click", () => ui.settingsPanel.closePanel()));
|
|
4213
|
+
const refreshRules = () => {
|
|
4214
|
+
const rulesEl = host2.querySelector("#ohm-rules");
|
|
4215
|
+
if (rulesEl && menu.rules) rulesEl.innerHTML = rulesInnerHtml();
|
|
4216
|
+
};
|
|
4177
4217
|
disposers.push(
|
|
4178
4218
|
ui.locale.subscribe(() => {
|
|
4179
4219
|
const body = host2.querySelector(".ohm-body");
|
|
4180
4220
|
if (body) {
|
|
4181
|
-
|
|
4182
|
-
if (rulesEl && menu.rules) rulesEl.innerHTML = renderBlocks(menu.rules, tr);
|
|
4221
|
+
refreshRules();
|
|
4183
4222
|
if (lang) lang.value = ui.locale.get();
|
|
4184
4223
|
}
|
|
4224
|
+
}),
|
|
4225
|
+
ui.facts.subscribe(refreshRules)
|
|
4226
|
+
);
|
|
4227
|
+
let menuLocked = false;
|
|
4228
|
+
disposers.push(
|
|
4229
|
+
ui.settingsPanel.state.subscribe(() => {
|
|
4230
|
+
const isOpen = ui.settingsPanel.isOpen;
|
|
4231
|
+
host2.classList.toggle("open", isOpen);
|
|
4232
|
+
if (isOpen && !menuLocked) {
|
|
4233
|
+
ui.lock();
|
|
4234
|
+
menuLocked = true;
|
|
4235
|
+
} else if (!isOpen && menuLocked) {
|
|
4236
|
+
ui.unlock();
|
|
4237
|
+
menuLocked = false;
|
|
4238
|
+
}
|
|
4185
4239
|
})
|
|
4186
4240
|
);
|
|
4187
|
-
disposers.push(ui.settingsPanel.state.subscribe(() => host2.classList.toggle("open", ui.settingsPanel.isOpen)));
|
|
4188
4241
|
return () => {
|
|
4189
4242
|
for (const d of disposers.splice(0)) d();
|
|
4243
|
+
if (menuLocked) {
|
|
4244
|
+
ui.unlock();
|
|
4245
|
+
menuLocked = false;
|
|
4246
|
+
}
|
|
4190
4247
|
host2.remove();
|
|
4191
4248
|
};
|
|
4192
4249
|
}
|
|
@@ -4240,6 +4297,13 @@ var OHM_CSS = `
|
|
|
4240
4297
|
.ohm-stats { margin: 12px 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }
|
|
4241
4298
|
.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
4299
|
.ohm-stats dt { color: var(--text-dim); margin: 0; } .ohm-stats dd { margin: 0; font-weight: 700; }
|
|
4300
|
+
.ohm-audit { margin: 12px 0 18px; padding: 14px 16px; border-radius: 12px; border: 2px solid #d03131; background: color-mix(in srgb, #d03131 8%, transparent); }
|
|
4301
|
+
.ohm-audit-title { font-weight: 900; letter-spacing: .5px; color: #b31d1d; }
|
|
4302
|
+
.ohm-audit-sub { margin-top: 8px; font-size: 13px; font-weight: 800; color: #b31d1d; }
|
|
4303
|
+
.ohm-audit-sub--rec { color: #b07d09; }
|
|
4304
|
+
.ohm-audit ul { margin: 6px 0 0; padding-left: 20px; color: var(--text); font-size: 13.5px; line-height: 1.55; }
|
|
4305
|
+
.ohm-audit li { margin: 3px 0; }
|
|
4306
|
+
.ohm-audit-rec ul { color: var(--text-dim); }
|
|
4243
4307
|
.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
4308
|
.ohm-callout b { color: var(--accent); } .ohm-callout p { margin: 4px 0 0; color: var(--text); }
|
|
4245
4309
|
.ohm-callout--warning { border-left-color: #e0a106; background: color-mix(in srgb, #e0a106 10%, transparent); }
|
|
@@ -4269,10 +4333,67 @@ var OHM_CSS = `
|
|
|
4269
4333
|
.ohm-group { margin: 8px 0; }
|
|
4270
4334
|
`;
|
|
4271
4335
|
|
|
4336
|
+
// src/confirmModal.ts
|
|
4337
|
+
var esc2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4338
|
+
function showConfirm(ui, opts) {
|
|
4339
|
+
return new Promise((resolve) => {
|
|
4340
|
+
const host2 = document.createElement("div");
|
|
4341
|
+
host2.className = "osc-confirm";
|
|
4342
|
+
host2.style.setProperty("--font", ui.theme.type.family);
|
|
4343
|
+
const title = ui.t(opts.title ?? "Buy Feature");
|
|
4344
|
+
const yes = ui.t(opts.confirmLabel ?? "openui.confirm");
|
|
4345
|
+
const no = ui.t(opts.cancelLabel ?? "openui.cancel");
|
|
4346
|
+
host2.innerHTML = `
|
|
4347
|
+
<div class="osc-confirm-backdrop" data-no></div>
|
|
4348
|
+
<div class="osc-confirm-card" role="dialog" aria-modal="true">
|
|
4349
|
+
${title ? `<h3 class="osc-confirm-title">${esc2(title)}</h3>` : ""}
|
|
4350
|
+
<p class="osc-confirm-msg">${esc2(opts.message)}</p>
|
|
4351
|
+
<div class="osc-confirm-row">
|
|
4352
|
+
<button class="osc-confirm-btn osc-confirm-no" data-no>${esc2(no)}</button>
|
|
4353
|
+
<button class="osc-confirm-btn osc-confirm-yes" data-yes>${esc2(yes)}</button>
|
|
4354
|
+
</div>
|
|
4355
|
+
</div>`;
|
|
4356
|
+
const style = document.createElement("style");
|
|
4357
|
+
style.textContent = CONFIRM_CSS;
|
|
4358
|
+
host2.appendChild(style);
|
|
4359
|
+
document.body.appendChild(host2);
|
|
4360
|
+
let settled = false;
|
|
4361
|
+
const close = (val) => {
|
|
4362
|
+
if (settled) return;
|
|
4363
|
+
settled = true;
|
|
4364
|
+
window.removeEventListener("keydown", onKey);
|
|
4365
|
+
host2.remove();
|
|
4366
|
+
resolve(val);
|
|
4367
|
+
};
|
|
4368
|
+
const onKey = (e) => {
|
|
4369
|
+
if (e.key === "Escape") close(false);
|
|
4370
|
+
else if (e.key === "Enter") close(true);
|
|
4371
|
+
};
|
|
4372
|
+
host2.querySelectorAll("[data-no]").forEach((b) => b.addEventListener("click", () => close(false)));
|
|
4373
|
+
host2.querySelector("[data-yes]")?.addEventListener("click", () => close(true));
|
|
4374
|
+
window.addEventListener("keydown", onKey);
|
|
4375
|
+
});
|
|
4376
|
+
}
|
|
4377
|
+
var CONFIRM_CSS = `
|
|
4378
|
+
.osc-confirm { position: fixed; inset: 0; z-index: 12000; display: grid; place-items: center; font-family: var(--font); }
|
|
4379
|
+
.osc-confirm *, .osc-confirm *::before, .osc-confirm *::after { box-sizing: border-box; }
|
|
4380
|
+
.osc-confirm-backdrop { position: absolute; inset: 0; background: rgba(8,6,4,.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
|
|
4381
|
+
.osc-confirm-card { position: relative; width: min(90vw, 420px); background: #ffffff; color: #181b20; border: 3px solid #000; border-radius: 14px; padding: 24px; box-shadow: 0 24px 60px rgba(0,0,0,.55); text-align: center; }
|
|
4382
|
+
.osc-confirm-title { margin: 0 0 12px; font-size: 22px; font-weight: 800; letter-spacing: .3px; }
|
|
4383
|
+
.osc-confirm-msg { margin: 0 0 22px; font-size: 19px; font-weight: 700; line-height: 1.4; }
|
|
4384
|
+
.osc-confirm-row { display: flex; gap: 14px; }
|
|
4385
|
+
.osc-confirm-btn { flex: 1; padding: 14px 10px; border-radius: 12px; border: 3px solid #000; font-size: 15px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; cursor: pointer; transition: transform .1s, background .12s; }
|
|
4386
|
+
.osc-confirm-btn:active { transform: scale(.96); }
|
|
4387
|
+
.osc-confirm-no { background: #ffffff; color: #181b20; }
|
|
4388
|
+
.osc-confirm-no:hover { background: #eef1f6; }
|
|
4389
|
+
.osc-confirm-yes { background: #d99000; color: #1a1200; }
|
|
4390
|
+
.osc-confirm-yes:hover { filter: brightness(1.05); }
|
|
4391
|
+
`;
|
|
4392
|
+
|
|
4272
4393
|
// src/mountHud.ts
|
|
4273
4394
|
function showReplayModal(ui, info, buttonKey, onSelect) {
|
|
4274
4395
|
const cur = info.currency ?? ui.balance.currency.get();
|
|
4275
|
-
const money2 = (n) => core.
|
|
4396
|
+
const money2 = (n) => core.formatAmountPrecise(n, cur);
|
|
4276
4397
|
ui.showNotice(
|
|
4277
4398
|
[
|
|
4278
4399
|
{ kind: "heading", id: "openui-replay-h", text: "openui.replay.title" },
|
|
@@ -4387,17 +4508,15 @@ function mountHud(app, spec = {}, opts = {}) {
|
|
|
4387
4508
|
o.onConfirm();
|
|
4388
4509
|
return;
|
|
4389
4510
|
}
|
|
4390
|
-
const message = o.message ?? (o.name ? ui.t("openui.buyFeature.confirm", { name: ui.t(o.name), price: o.price ?? "" }) : "openui.buyFeature.message");
|
|
4391
|
-
ui
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
]
|
|
4400
|
-
);
|
|
4511
|
+
const message = o.message ?? (o.name ? ui.t("openui.buyFeature.confirm", { name: ui.t(o.name), price: o.price ?? "" }) : ui.t("openui.buyFeature.message"));
|
|
4512
|
+
void showConfirm(ui, {
|
|
4513
|
+
title: o.title ?? "openui.buyFeature.title",
|
|
4514
|
+
message,
|
|
4515
|
+
confirmLabel: o.confirmLabel,
|
|
4516
|
+
cancelLabel: o.cancelLabel
|
|
4517
|
+
}).then((ok) => {
|
|
4518
|
+
if (ok) o.onConfirm();
|
|
4519
|
+
});
|
|
4401
4520
|
},
|
|
4402
4521
|
showControls: () => pixi.setControlsVisible(true),
|
|
4403
4522
|
hideControls: () => pixi.setControlsVisible(false),
|
|
@@ -4412,13 +4531,14 @@ function mountHud(app, spec = {}, opts = {}) {
|
|
|
4412
4531
|
};
|
|
4413
4532
|
}
|
|
4414
4533
|
function money(amount, cur) {
|
|
4415
|
-
return core.
|
|
4534
|
+
return core.formatAmountPrecise(amount, cur);
|
|
4416
4535
|
}
|
|
4417
|
-
var
|
|
4536
|
+
var esc3 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4418
4537
|
function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
4419
4538
|
const ui = hud.ui;
|
|
4420
4539
|
const tr = (k) => ui.t(k);
|
|
4421
4540
|
const list = features.slice(0, 4);
|
|
4541
|
+
ui.declareFacts({ modes: list.map((f) => ({ id: f.id, name: f.name, kind: f.variant, cost: f.cost })) });
|
|
4422
4542
|
const boosts = /* @__PURE__ */ new Set();
|
|
4423
4543
|
const activation = opts.activation ?? "multi";
|
|
4424
4544
|
const blocksBuy = opts.activationBlocksBuy ?? false;
|
|
@@ -4440,23 +4560,14 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
|
4440
4560
|
<button class="bfm-x" data-close aria-label="Close">\u2715</button>
|
|
4441
4561
|
<div class="bfm-panel" role="dialog" aria-modal="true">
|
|
4442
4562
|
<div class="bfm-fit" id="bfm-fit">
|
|
4443
|
-
<h2 class="bfm-title" data-t="Buy Feature">${
|
|
4563
|
+
<h2 class="bfm-title" data-t="Buy Feature">${esc3(tr("Buy Feature"))}</h2>
|
|
4444
4564
|
<div class="bfm-bet">
|
|
4445
4565
|
<button class="bfm-step" id="bfm-minus" aria-label="Decrease">\u2212</button>
|
|
4446
|
-
<div class="bfm-betbox"><span class="bfm-betlabel" data-t="Bet">${
|
|
4566
|
+
<div class="bfm-betbox"><span class="bfm-betlabel" data-t="Bet">${esc3(tr("Bet"))}</span><b id="bfm-betval">\u2014</b></div>
|
|
4447
4567
|
<button class="bfm-step" id="bfm-plus" aria-label="Increase">+</button>
|
|
4448
4568
|
</div>
|
|
4449
4569
|
<div class="bfm-cards" id="bfm-cards"></div>
|
|
4450
4570
|
</div>
|
|
4451
|
-
</div>
|
|
4452
|
-
<div class="bfm-confirm" id="bfm-confirm">
|
|
4453
|
-
<div class="bfm-confirm-card">
|
|
4454
|
-
<p class="bfm-confirm-msg" id="bfm-confirm-msg"></p>
|
|
4455
|
-
<div class="bfm-confirm-row">
|
|
4456
|
-
<button class="bfm-confirm-btn bfm-confirm-no" id="bfm-confirm-no" data-t="openui.cancel">${esc2(tr("openui.cancel"))}</button>
|
|
4457
|
-
<button class="bfm-confirm-btn bfm-confirm-yes" id="bfm-confirm-yes" data-t="openui.confirm">${esc2(tr("openui.confirm"))}</button>
|
|
4458
|
-
</div>
|
|
4459
|
-
</div>
|
|
4460
4571
|
</div>`;
|
|
4461
4572
|
const style = document.createElement("style");
|
|
4462
4573
|
style.textContent = BFM_CSS;
|
|
@@ -4467,29 +4578,11 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
|
4467
4578
|
const fitEl = $("#bfm-fit");
|
|
4468
4579
|
const cardsEl = $("#bfm-cards");
|
|
4469
4580
|
const betValEl = $("#bfm-betval");
|
|
4470
|
-
const
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
const hideConfirm = () => {
|
|
4476
|
-
confirmEl.classList.remove("show");
|
|
4477
|
-
pendingConfirm = null;
|
|
4478
|
-
};
|
|
4479
|
-
confirmNo.addEventListener("click", hideConfirm);
|
|
4480
|
-
confirmYes.addEventListener("click", () => {
|
|
4481
|
-
const fn = pendingConfirm;
|
|
4482
|
-
hideConfirm();
|
|
4483
|
-
fn?.();
|
|
4484
|
-
});
|
|
4485
|
-
const askConfirm = (totalCost, name, price, onYes) => {
|
|
4486
|
-
if (!hud.shouldConfirmBuy(totalCost)) {
|
|
4487
|
-
onYes();
|
|
4488
|
-
return;
|
|
4489
|
-
}
|
|
4490
|
-
confirmMsg.textContent = ui.t("openui.buyFeature.confirm", { name: ui.t(name), price });
|
|
4491
|
-
pendingConfirm = onYes;
|
|
4492
|
-
confirmEl.classList.add("show");
|
|
4581
|
+
const askConfirm = (name, price, onYes) => {
|
|
4582
|
+
const message = ui.t("openui.buyFeature.confirm", { name: ui.t(name), price });
|
|
4583
|
+
void showConfirm(ui, { title: "Buy Feature", message }).then((ok) => {
|
|
4584
|
+
if (ok) onYes();
|
|
4585
|
+
});
|
|
4493
4586
|
};
|
|
4494
4587
|
const layout = () => {
|
|
4495
4588
|
const vw = window.innerWidth;
|
|
@@ -4521,11 +4614,11 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
|
4521
4614
|
<div class="bfm-cardimg"${img}></div>
|
|
4522
4615
|
<div class="bfm-strip"></div>
|
|
4523
4616
|
<div class="bfm-cardbody">
|
|
4524
|
-
<span class="bfm-name">${
|
|
4525
|
-
<b class="bfm-price">${
|
|
4617
|
+
<span class="bfm-name">${esc3(tr(f.name))}</span>
|
|
4618
|
+
<b class="bfm-price">${esc3(price)}</b>
|
|
4526
4619
|
</div>
|
|
4527
4620
|
</div>
|
|
4528
|
-
<button class="${cls}" data-id="${f.id}" data-variant="${f.variant}"${buyBlocked ? " disabled" : ""}>${
|
|
4621
|
+
<button class="${cls}" data-id="${f.id}" data-variant="${f.variant}"${buyBlocked ? " disabled" : ""}>${esc3(label)}</button>
|
|
4529
4622
|
</div>`;
|
|
4530
4623
|
}).join("");
|
|
4531
4624
|
betValEl.textContent = money(bet, cur);
|
|
@@ -4553,11 +4646,11 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
|
4553
4646
|
return;
|
|
4554
4647
|
}
|
|
4555
4648
|
const total = 1 + (f?.cost ?? 0);
|
|
4556
|
-
askConfirm(
|
|
4649
|
+
askConfirm(f?.name ?? id, money(total * bet, cur), commit);
|
|
4557
4650
|
} else {
|
|
4558
4651
|
if (blocksBuy && boosts.size > 0) return;
|
|
4559
4652
|
const cost = (f?.cost ?? 0) * bet;
|
|
4560
|
-
askConfirm(f?.
|
|
4653
|
+
askConfirm(f?.name ?? id, money(cost, cur), () => {
|
|
4561
4654
|
ui.bus.emit("cardActivated", { id });
|
|
4562
4655
|
close();
|
|
4563
4656
|
opts.onBuy?.(id, cost);
|
|
@@ -4568,10 +4661,16 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
|
4568
4661
|
$("#bfm-plus").addEventListener("click", () => ui.betStepper.inc());
|
|
4569
4662
|
disposers.push(ui.bet.value.subscribe(() => renderCards()));
|
|
4570
4663
|
const open = () => {
|
|
4664
|
+
if (host2.classList.contains("open")) return;
|
|
4571
4665
|
renderCards();
|
|
4572
4666
|
host2.classList.add("open");
|
|
4667
|
+
ui.lock();
|
|
4668
|
+
};
|
|
4669
|
+
const close = () => {
|
|
4670
|
+
if (!host2.classList.contains("open")) return;
|
|
4671
|
+
host2.classList.remove("open");
|
|
4672
|
+
ui.unlock();
|
|
4573
4673
|
};
|
|
4574
|
-
const close = () => host2.classList.remove("open");
|
|
4575
4674
|
host2.querySelectorAll("[data-close]").forEach((b) => b.addEventListener("click", close));
|
|
4576
4675
|
disposers.push(ui.on("buttonActivated", ({ id }) => {
|
|
4577
4676
|
if (id === "bonus") open();
|
|
@@ -4589,6 +4688,7 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
|
4589
4688
|
renderCards();
|
|
4590
4689
|
return () => {
|
|
4591
4690
|
window.removeEventListener("resize", onResize);
|
|
4691
|
+
if (host2.classList.contains("open")) ui.unlock();
|
|
4592
4692
|
for (const d of disposers.splice(0)) d();
|
|
4593
4693
|
host2.remove();
|
|
4594
4694
|
};
|
|
@@ -4626,22 +4726,11 @@ var BFM_CSS = `
|
|
|
4626
4726
|
.bfm-action.is-active { background: var(--accent); color: var(--accent-text); border-color: #000; }
|
|
4627
4727
|
.bfm-action.is-blocked, .bfm-action:disabled { opacity: .38; cursor: not-allowed; box-shadow: none; }
|
|
4628
4728
|
.bfm-action.is-blocked:hover, .bfm-action:disabled:hover { background: var(--surface); }
|
|
4629
|
-
.bfm-confirm { position: absolute; inset: 0; z-index: 5; display: grid; place-items: center; opacity: 0; pointer-events: none; transition: opacity .16s ease; }
|
|
4630
|
-
.bfm-confirm.show { opacity: 1; pointer-events: auto; }
|
|
4631
|
-
.bfm-confirm::before { content: ""; position: absolute; inset: 0; background: rgba(8,6,4,.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
|
|
4632
|
-
.bfm-confirm-card { position: relative; width: min(90%, 420px); background: var(--surface); color: var(--text); border: 3px solid #000; border-radius: 14px; padding: 26px 24px 22px; box-shadow: 0 24px 60px rgba(0,0,0,.55); text-align: center; }
|
|
4633
|
-
.bfm-confirm-msg { margin: 0 0 22px; font-size: 19px; font-weight: 700; line-height: 1.4; color: var(--text); }
|
|
4634
|
-
.bfm-confirm-row { display: flex; gap: 14px; }
|
|
4635
|
-
.bfm-confirm-btn { flex: 1; padding: 14px 10px; border-radius: 12px; border: 3px solid #000; font-size: 15px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; cursor: pointer; transition: transform .1s, background .12s; }
|
|
4636
|
-
.bfm-confirm-btn:active { transform: scale(.96); }
|
|
4637
|
-
.bfm-confirm-no { background: var(--surface); color: var(--text); }
|
|
4638
|
-
.bfm-confirm-no:hover { background: var(--surface-alt); }
|
|
4639
|
-
.bfm-confirm-yes { background: var(--accent); color: var(--accent-text); }
|
|
4640
4729
|
`;
|
|
4641
4730
|
|
|
4642
4731
|
// src/bootError.ts
|
|
4643
4732
|
var host = null;
|
|
4644
|
-
var
|
|
4733
|
+
var esc4 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4645
4734
|
function showBootError(opts = {}) {
|
|
4646
4735
|
const title = opts.title ?? "Connection lost";
|
|
4647
4736
|
const message = opts.message ?? "The game could not reach the game server. Please reload to reconnect and continue.";
|
|
@@ -4655,10 +4744,10 @@ function showBootError(opts = {}) {
|
|
|
4655
4744
|
<div class="openui-be-icon" aria-hidden="true">
|
|
4656
4745
|
<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>
|
|
4657
4746
|
</div>
|
|
4658
|
-
<h1 class="openui-be-title">${
|
|
4659
|
-
<p class="openui-be-msg">${
|
|
4660
|
-
${opts.detail ? `<p class="openui-be-detail">${
|
|
4661
|
-
${showReload ? `<button class="openui-be-reload" type="button">${
|
|
4747
|
+
<h1 class="openui-be-title">${esc4(title)}</h1>
|
|
4748
|
+
<p class="openui-be-msg">${esc4(message)}</p>
|
|
4749
|
+
${opts.detail ? `<p class="openui-be-detail">${esc4(opts.detail)}</p>` : ""}
|
|
4750
|
+
${showReload ? `<button class="openui-be-reload" type="button">${esc4(opts.reloadLabel ?? "Reload")}</button>` : ""}
|
|
4662
4751
|
</div>
|
|
4663
4752
|
<style>
|
|
4664
4753
|
.openui-boot-error { position: fixed; inset: 0; z-index: 2147483000; display: grid; place-items: center;
|
|
@@ -4742,6 +4831,7 @@ exports.mountBuyFeatureModal = mountBuyFeatureModal;
|
|
|
4742
4831
|
exports.mountHud = mountHud;
|
|
4743
4832
|
exports.mountInfoMenu = mountInfoMenu;
|
|
4744
4833
|
exports.showBootError = showBootError;
|
|
4834
|
+
exports.showConfirm = showConfirm;
|
|
4745
4835
|
exports.svgSpinSkin = svgSpinSkin;
|
|
4746
4836
|
//# sourceMappingURL=index.cjs.map
|
|
4747
4837
|
//# sourceMappingURL=index.cjs.map
|