@open-slot-ui/core 0.5.0 → 0.6.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/index.cjs +30 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -1
- package/dist/index.d.ts +36 -1
- package/dist/index.js +30 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1249,6 +1249,9 @@ function validateSpec(spec) {
|
|
|
1249
1249
|
if (spec.realityCheck != null && !(typeof spec.realityCheck.everyMinutes === "number" && spec.realityCheck.everyMinutes > 0)) {
|
|
1250
1250
|
add("error", "realityCheck.everyMinutes", "bad-interval", "realityCheck.everyMinutes must be a number > 0");
|
|
1251
1251
|
}
|
|
1252
|
+
if (spec.buyFeature?.confirmAboveCost != null && !(typeof spec.buyFeature.confirmAboveCost === "number" && Number.isFinite(spec.buyFeature.confirmAboveCost) && spec.buyFeature.confirmAboveCost >= 0)) {
|
|
1253
|
+
add("error", "buyFeature.confirmAboveCost", "bad-threshold", "buyFeature.confirmAboveCost must be a finite number >= 0");
|
|
1254
|
+
}
|
|
1252
1255
|
if (spec.controls) {
|
|
1253
1256
|
for (const [id, ov] of Object.entries(spec.controls)) {
|
|
1254
1257
|
checkLayout(ov.layout?.anchor, `controls.${id}.layout.anchor`);
|
|
@@ -1401,6 +1404,9 @@ function applyJurisdiction(ui, jur) {
|
|
|
1401
1404
|
if (typeof jur.minimumRoundDuration === "number" && Number.isFinite(jur.minimumRoundDuration)) {
|
|
1402
1405
|
ui.minimumRoundDuration = Math.max(0, jur.minimumRoundDuration);
|
|
1403
1406
|
}
|
|
1407
|
+
if (typeof jur.confirmBuyAboveCost === "number" && Number.isFinite(jur.confirmBuyAboveCost)) {
|
|
1408
|
+
ui.confirmBuyAboveCost = Math.max(0, jur.confirmBuyAboveCost);
|
|
1409
|
+
}
|
|
1404
1410
|
}
|
|
1405
1411
|
|
|
1406
1412
|
// src/notice.ts
|
|
@@ -1458,6 +1464,8 @@ var openuiDefaults = {
|
|
|
1458
1464
|
"openui.replay": "Replay",
|
|
1459
1465
|
"openui.buyFeature.title": "Buy feature",
|
|
1460
1466
|
"openui.buyFeature.message": "Buy this feature now?",
|
|
1467
|
+
// Confirm step for a higher-cost play — {{name}} / {{price}} are interpolated.
|
|
1468
|
+
"openui.buyFeature.confirm": "Buy {{name}} for {{price}}?",
|
|
1461
1469
|
"openui.freeSpins": "FS",
|
|
1462
1470
|
// reality check (RTS 13) — {{minutes}} is interpolated by open-ui's scheduler
|
|
1463
1471
|
"openui.realityCheck.title": "Reality check",
|
|
@@ -1493,6 +1501,7 @@ var openuiSocialDefaults = {
|
|
|
1493
1501
|
"openui.err.insufficient.title": "Insufficient balance",
|
|
1494
1502
|
"openui.buyFeature.title": "Play bonus",
|
|
1495
1503
|
"openui.buyFeature.message": "Play this bonus now?",
|
|
1504
|
+
"openui.buyFeature.confirm": "Play {{name}} for {{price}}?",
|
|
1496
1505
|
"openui.err.insufficient.message": "You don't have enough balance for this play.",
|
|
1497
1506
|
"openui.err.limit.message": "A play limit has been reached. Please try again later."
|
|
1498
1507
|
};
|
|
@@ -1673,6 +1682,11 @@ var OpenUI = class {
|
|
|
1673
1682
|
gameInfo = {};
|
|
1674
1683
|
/** Minimum round duration (ms) from jurisdiction — stored for the GAME to enforce. */
|
|
1675
1684
|
minimumRoundDuration = 0;
|
|
1685
|
+
/** Buy-feature confirm threshold, as a multiple of the base bet. A play (buy or
|
|
1686
|
+
* bet-mode activation) that costs STRICTLY MORE than this must show a confirm step
|
|
1687
|
+
* — Stake requires that bet modes above 2× never activate on a single click. `0`
|
|
1688
|
+
* (the default) = off. Set via `spec.buyFeature.confirmAboveCost` or a jurisdiction. */
|
|
1689
|
+
confirmBuyAboveCost = 0;
|
|
1676
1690
|
sessionNet = 0;
|
|
1677
1691
|
prevVolumes = null;
|
|
1678
1692
|
/** The frozen UISpec `createUI` built this from, if any — authored = run = tested. */
|
|
@@ -2022,6 +2036,13 @@ var OpenUI = class {
|
|
|
2022
2036
|
const j = this.jurisdiction;
|
|
2023
2037
|
return feature === "autoplay" && !!j.disabledAutoplay || feature === "buyFeature" && !!j.disabledBuyFeature || feature === "turbo" && !!j.disabledTurbo || feature === "fullscreen" && !!j.disabledFullscreen || feature === "slamstop" && !!j.disabledSlamstop || feature === "spacebar" && !!j.disabledSpacebar;
|
|
2024
2038
|
}
|
|
2039
|
+
/** True when a buy / bet-mode activation of `cost`× the base bet must be confirmed
|
|
2040
|
+
* before it commits (Stake: no one-click activation above `confirmBuyAboveCost`×).
|
|
2041
|
+
* Always false when the threshold is 0/unset or `cost` isn't a finite number. */
|
|
2042
|
+
shouldConfirmBuy(cost) {
|
|
2043
|
+
const t = this.confirmBuyAboveCost;
|
|
2044
|
+
return t > 0 && Number.isFinite(cost) && cost > t;
|
|
2045
|
+
}
|
|
2025
2046
|
/**
|
|
2026
2047
|
* Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
|
|
2027
2048
|
* backgrounded tab can't cheat it) it emits a `realityCheck` event, stops autoplay,
|
|
@@ -2253,15 +2274,18 @@ function collectSocialCopy(spec) {
|
|
|
2253
2274
|
if (spec.game?.name) out.push({ source: "game.name", text: spec.game.name });
|
|
2254
2275
|
const en = spec.locale?.messages?.en;
|
|
2255
2276
|
if (en) {
|
|
2256
|
-
for (const [k, v] of Object.entries(en)) if (typeof v === "string") out.push({ source: `locale.en[${JSON.stringify(k)}]`, text: v });
|
|
2277
|
+
for (const [k, v] of Object.entries(en)) if (typeof v === "string") out.push({ source: `locale.en[${JSON.stringify(k)}]`, text: v, key: k });
|
|
2257
2278
|
}
|
|
2258
2279
|
return out;
|
|
2259
2280
|
}
|
|
2260
2281
|
function checkSocialPhrases(spec) {
|
|
2282
|
+
const socialEn = spec.locale?.socialMessages?.en ?? {};
|
|
2283
|
+
const render = (e) => socialEn[e.key ?? e.text] ?? openuiSocialDefaults[e.key ?? e.text] ?? e.text;
|
|
2261
2284
|
const issues = [];
|
|
2262
|
-
for (const
|
|
2285
|
+
for (const e of collectSocialCopy(spec)) {
|
|
2286
|
+
const text = render(e);
|
|
2263
2287
|
const matches = findForbiddenPhrases(text);
|
|
2264
|
-
if (matches.length) issues.push({ source, text, matches });
|
|
2288
|
+
if (matches.length) issues.push({ source: e.source, text, matches });
|
|
2265
2289
|
}
|
|
2266
2290
|
return issues;
|
|
2267
2291
|
}
|
|
@@ -2352,6 +2376,9 @@ function createUI(spec = {}, hooks = {}) {
|
|
|
2352
2376
|
}
|
|
2353
2377
|
}
|
|
2354
2378
|
}
|
|
2379
|
+
if (spec.buyFeature?.confirmAboveCost != null && Number.isFinite(spec.buyFeature.confirmAboveCost)) {
|
|
2380
|
+
ui.confirmBuyAboveCost = Math.max(0, spec.buyFeature.confirmAboveCost);
|
|
2381
|
+
}
|
|
2355
2382
|
if (spec.jurisdiction) ui.applyJurisdiction(spec.jurisdiction);
|
|
2356
2383
|
const portraitControls = {};
|
|
2357
2384
|
for (const [id, layout] of Object.entries(portraitDefaultLayouts)) {
|