@open-slot-ui/core 0.12.0 → 0.13.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 +33 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +33 -15
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -133,10 +133,10 @@ function anchorFactors(anchor) {
|
|
|
133
133
|
function resolvePlacement(spec, screen) {
|
|
134
134
|
const [ax, ay] = anchorFactors(spec.anchor);
|
|
135
135
|
const [ox, oy] = spec.offset ?? [0, 0];
|
|
136
|
-
const
|
|
136
|
+
const rect = spec.origin === "screen" ? { x: 0, y: 0, width: screen.width, height: screen.height } : screen.stage;
|
|
137
137
|
return {
|
|
138
|
-
x:
|
|
139
|
-
y:
|
|
138
|
+
x: rect.x + ax * rect.width + ox * screen.scale,
|
|
139
|
+
y: rect.y + ay * rect.height + oy * screen.scale,
|
|
140
140
|
scale: screen.scale * (spec.scale ?? 1),
|
|
141
141
|
rotation: (spec.rotation ?? 0) * Math.PI / 180
|
|
142
142
|
};
|
|
@@ -160,11 +160,13 @@ var landscapeDefaultLayouts = Object.freeze({
|
|
|
160
160
|
// Right-anchored so a long localized caption grows LEFT and never clips the edge.
|
|
161
161
|
"total-win": { anchor: "bottom-right", offset: [-150, -300] },
|
|
162
162
|
settings: { anchor: "bottom-center", offset: [-740, -320], rotation: -5 },
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
// Corner utilities anchor to the SCREEN (not the letterboxed frame) so they hug the true
|
|
164
|
+
// viewport corners at every aspect — see `LayoutSpec.origin`.
|
|
165
|
+
mute: { anchor: "top-right", offset: [-122, 46], origin: "screen" },
|
|
166
|
+
fullscreen: { anchor: "top-right", offset: [-46, 46], origin: "screen" },
|
|
167
|
+
rtp: { anchor: "top-left", offset: [20, 18], origin: "screen" },
|
|
168
|
+
"session-timer": { anchor: "top-left", offset: [20, 46], origin: "screen" },
|
|
169
|
+
"net-position": { anchor: "top-left", offset: [20, 74], origin: "screen" }
|
|
168
170
|
});
|
|
169
171
|
var portraitDefaultLayouts = Object.freeze({
|
|
170
172
|
// Mobile sizes run ~1.5× the desktop base (the Figma mobile frame draws the
|
|
@@ -179,19 +181,21 @@ var portraitDefaultLayouts = Object.freeze({
|
|
|
179
181
|
settings: { anchor: "bottom-center", offset: [438, -480], scale: 1.5, rotation: -5 },
|
|
180
182
|
"bet-minus": { anchor: "bottom-center", offset: [-105, -267], scale: 1.5 },
|
|
181
183
|
"bet-plus": { anchor: "bottom-center", offset: [105, -267], scale: 1.5 },
|
|
182
|
-
|
|
183
|
-
|
|
184
|
+
// Corner utilities anchor to the SCREEN (see `LayoutSpec.origin`) so they stay in the true
|
|
185
|
+
// viewport corner even when the portrait frame is letterboxed.
|
|
186
|
+
mute: { anchor: "top-right", offset: [-159, 57], scale: 1.5, origin: "screen" },
|
|
187
|
+
fullscreen: { anchor: "top-right", offset: [-57, 57], scale: 1.5, origin: "screen" },
|
|
184
188
|
// Compliance readouts scale up ~2× on mobile with wider line spacing.
|
|
185
|
-
rtp: { anchor: "top-left", offset: [16, 16], scale: 2 },
|
|
186
|
-
"session-timer": { anchor: "top-left", offset: [16, 66], scale: 2 },
|
|
187
|
-
"net-position": { anchor: "top-left", offset: [16, 116], scale: 2 },
|
|
189
|
+
rtp: { anchor: "top-left", offset: [16, 16], scale: 2, origin: "screen" },
|
|
190
|
+
"session-timer": { anchor: "top-left", offset: [16, 66], scale: 2, origin: "screen" },
|
|
191
|
+
"net-position": { anchor: "top-left", offset: [16, 116], scale: 2, origin: "screen" },
|
|
188
192
|
balance: { anchor: "bottom-left", offset: [36, -110], rotation: -5 },
|
|
189
193
|
bet: { anchor: "bottom-right", offset: [-36, -110], rotation: 5 }
|
|
190
194
|
});
|
|
191
195
|
function defaultLayout(id) {
|
|
192
196
|
const l = landscapeDefaultLayouts[id];
|
|
193
197
|
if (!l) return { anchor: "center" };
|
|
194
|
-
return { anchor: l.anchor, offset: l.offset ? [l.offset[0], l.offset[1]] : void 0, scale: l.scale, rotation: l.rotation };
|
|
198
|
+
return { anchor: l.anchor, offset: l.offset ? [l.offset[0], l.offset[1]] : void 0, scale: l.scale, rotation: l.rotation, origin: l.origin };
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
// src/transition/Transition.ts
|
|
@@ -1275,6 +1279,7 @@ var BLOCK_KINDS = [
|
|
|
1275
1279
|
"steps",
|
|
1276
1280
|
"table",
|
|
1277
1281
|
"paytable",
|
|
1282
|
+
"paylines",
|
|
1278
1283
|
"image",
|
|
1279
1284
|
"media",
|
|
1280
1285
|
"cards",
|
|
@@ -1436,6 +1441,10 @@ function validateSpec(spec) {
|
|
|
1436
1441
|
if (b.kind === "paytable" && (!b.rows || b.rows.length === 0)) {
|
|
1437
1442
|
add("warn", `${p}.rows`, "empty-paytable", "a paytable block has no rows");
|
|
1438
1443
|
}
|
|
1444
|
+
if (b.kind === "paylines") {
|
|
1445
|
+
if (!(b.reels > 0) || !(b.rows > 0)) add("error", `${p}.reels`, "paylines-shape", "a paylines block needs reels > 0 and rows > 0");
|
|
1446
|
+
if (!b.lines || b.lines.length === 0) add("warn", `${p}.lines`, "empty-paylines", "a paylines block has no lines");
|
|
1447
|
+
}
|
|
1439
1448
|
if (b.kind === "image" && (!b.src || !b.src.trim())) {
|
|
1440
1449
|
add("error", `${p}.src`, "image-src", "an image block needs a src");
|
|
1441
1450
|
}
|
|
@@ -2459,7 +2468,7 @@ var OpenUI = class {
|
|
|
2459
2468
|
|
|
2460
2469
|
// src/spec/responsive.ts
|
|
2461
2470
|
function cloneLayout(l) {
|
|
2462
|
-
return { anchor: l.anchor, offset: l.offset ? [l.offset[0], l.offset[1]] : void 0, scale: l.scale, rotation: l.rotation };
|
|
2471
|
+
return { anchor: l.anchor, offset: l.offset ? [l.offset[0], l.offset[1]] : void 0, scale: l.scale, rotation: l.rotation, origin: l.origin };
|
|
2463
2472
|
}
|
|
2464
2473
|
function activeKeys(screen) {
|
|
2465
2474
|
return [screen.orientation, screen.breakpoint];
|
|
@@ -2917,6 +2926,15 @@ function renderBlocksHtml(blocks, tr, facts) {
|
|
|
2917
2926
|
case "paytable":
|
|
2918
2927
|
out.push(`<div class="ohm-grid">${renderPaytable(b.rows, tr)}</div>`);
|
|
2919
2928
|
break;
|
|
2929
|
+
case "paylines": {
|
|
2930
|
+
const masks = b.lines.map((line, i) => {
|
|
2931
|
+
const cells = [];
|
|
2932
|
+
for (let row = 0; row < b.rows; row++) for (let reel = 0; reel < b.reels; reel++) cells.push(`<i class="${line[reel] === row ? "on" : ""}"></i>`);
|
|
2933
|
+
return `<div class="ohm-line"><div class="ohm-linegrid" style="grid-template-columns:repeat(${b.reels},1fr)">${cells.join("")}</div><span>${i + 1}</span></div>`;
|
|
2934
|
+
}).join("");
|
|
2935
|
+
out.push(`<div class="ohm-lines">${masks}</div>`);
|
|
2936
|
+
break;
|
|
2937
|
+
}
|
|
2920
2938
|
case "table": {
|
|
2921
2939
|
const head = b.columns?.length ? `<thead><tr>${b.columns.map((c) => `<th>${esc(tr(c))}</th>`).join("")}</tr></thead>` : "";
|
|
2922
2940
|
const body = b.rows.map((r) => `<tr>${r.map((c) => `<td>${esc(tr(c))}</td>`).join("")}</tr>`).join("");
|