@sensiblestats/widget-react 0.60.4 → 0.60.6
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/CHANGELOG.md +14 -0
- package/dist/index.cjs +35 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +35 -16
- package/dist/index.js.map +1 -1
- package/dist/styles.css +11 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @sensiblestats/widget-react
|
|
2
2
|
|
|
3
|
+
## 0.60.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Games: Higher/Lower buttons fit phone-width cards (icons drop and type tightens on narrow cards, stacking below 180px), and Guess the XI shows a nationality's three-letter code at a size that fits its disc when there is no flag.
|
|
8
|
+
|
|
9
|
+
## 0.60.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Games: send the widget language with game config, result and play requests so server-written game text (quiz questions, grid labels, stat names, hints) arrives in Turkish; Beat the Grid resolves row abbreviations and header icons from stable keys.
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @sensiblestats/widget-sdk@0.36.0
|
|
16
|
+
|
|
3
17
|
## 0.60.4
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -4704,15 +4704,15 @@ function toSubmitResult(payload) {
|
|
|
4704
4704
|
attemptsUsed: payload.attemptsUsed
|
|
4705
4705
|
};
|
|
4706
4706
|
}
|
|
4707
|
-
function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
4707
|
+
function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh }) {
|
|
4708
4708
|
const [result, setResult] = (0, import_react29.useState)(null);
|
|
4709
4709
|
const [submitting, setSubmitting] = (0, import_react29.useState)(false);
|
|
4710
4710
|
const [rawStatus, setRawStatus] = (0, import_react29.useState)(null);
|
|
4711
4711
|
const inFlightRef = (0, import_react29.useRef)(false);
|
|
4712
4712
|
const convRef = (0, import_react29.useRef)(conversation);
|
|
4713
4713
|
convRef.current = conversation;
|
|
4714
|
-
const optsRef = (0, import_react29.useRef)({ gameId, gameDay, fixtureId, refresh });
|
|
4715
|
-
optsRef.current = { gameId, gameDay, fixtureId, refresh };
|
|
4714
|
+
const optsRef = (0, import_react29.useRef)({ gameId, gameDay, fixtureId, locale, refresh });
|
|
4715
|
+
optsRef.current = { gameId, gameDay, fixtureId, locale, refresh };
|
|
4716
4716
|
const resultRef = (0, import_react29.useRef)(null);
|
|
4717
4717
|
resultRef.current = result;
|
|
4718
4718
|
const refetch = (0, import_react29.useCallback)(async () => {
|
|
@@ -4720,7 +4720,7 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
|
4720
4720
|
if (!conv) return;
|
|
4721
4721
|
const opts = optsRef.current;
|
|
4722
4722
|
try {
|
|
4723
|
-
const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay);
|
|
4723
|
+
const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay, opts.locale);
|
|
4724
4724
|
if (payload === null) return;
|
|
4725
4725
|
if (payload.clientStateJson == null && resultRef.current?.clientStateJson != null) {
|
|
4726
4726
|
setRawStatus(payload.status);
|
|
@@ -4738,7 +4738,7 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
|
4738
4738
|
setSubmitting(true);
|
|
4739
4739
|
try {
|
|
4740
4740
|
const opts = optsRef.current;
|
|
4741
|
-
const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId);
|
|
4741
|
+
const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId, opts.locale);
|
|
4742
4742
|
if (playResult !== null) {
|
|
4743
4743
|
const hasFreshState = playResult.clientStateJson != null;
|
|
4744
4744
|
const isTerminal2 = playResult.alreadyPlayed === true;
|
|
@@ -4847,6 +4847,9 @@ function nationalityFlag(nationality) {
|
|
|
4847
4847
|
const key = nationality.trim().toLowerCase();
|
|
4848
4848
|
return FLAGS[key] ?? nationality.slice(0, 3).toUpperCase();
|
|
4849
4849
|
}
|
|
4850
|
+
function isNationCode(flag) {
|
|
4851
|
+
return /^[A-Z]{1,3}$/.test(flag);
|
|
4852
|
+
}
|
|
4850
4853
|
|
|
4851
4854
|
// src/components/games/PlayerAvatar.tsx
|
|
4852
4855
|
var import_react30 = require("react");
|
|
@@ -5515,8 +5518,8 @@ function CareerPathGame({
|
|
|
5515
5518
|
// src/components/games/BeatTheGridGame.tsx
|
|
5516
5519
|
var import_react34 = __toESM(require("react"), 1);
|
|
5517
5520
|
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
5518
|
-
function criterionIconKind(label) {
|
|
5519
|
-
const l = label.toLowerCase();
|
|
5521
|
+
function criterionIconKind(label, key) {
|
|
5522
|
+
const l = (key ?? label).toLowerCase();
|
|
5520
5523
|
if (l.includes("app")) return "calendar";
|
|
5521
5524
|
if (l.includes("goal")) return "ball";
|
|
5522
5525
|
if (l.includes("assist")) return "boot";
|
|
@@ -5524,8 +5527,10 @@ function criterionIconKind(label) {
|
|
|
5524
5527
|
if (l.includes("tackle")) return "shield";
|
|
5525
5528
|
return "flag";
|
|
5526
5529
|
}
|
|
5527
|
-
function rowAbbrev(label, map) {
|
|
5528
|
-
|
|
5530
|
+
function rowAbbrev(label, map, key) {
|
|
5531
|
+
const suffix = key?.split(".").pop();
|
|
5532
|
+
const english = suffix ? suffix.charAt(0).toUpperCase() + suffix.slice(1) : label;
|
|
5533
|
+
return map[english] ?? map[label] ?? label;
|
|
5529
5534
|
}
|
|
5530
5535
|
function CriterionIcon({ kind }) {
|
|
5531
5536
|
switch (kind) {
|
|
@@ -5700,12 +5705,12 @@ function BeatTheGridGame({
|
|
|
5700
5705
|
role: "grid",
|
|
5701
5706
|
children: [
|
|
5702
5707
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "ss-g-btg-corner" }),
|
|
5703
|
-
cols.map((col) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "ss-g-btg-colhdr", children: [
|
|
5704
|
-
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(CriterionIcon, { kind: criterionIconKind(col) }),
|
|
5708
|
+
cols.map((col, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "ss-g-btg-colhdr", children: [
|
|
5709
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(CriterionIcon, { kind: criterionIconKind(col, config.colsI18n?.[colIdx]?.key) }),
|
|
5705
5710
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: col })
|
|
5706
5711
|
] }, col)),
|
|
5707
5712
|
rows.map((rowLabel, rowIdx) => {
|
|
5708
|
-
const abbr = rowAbbrev(rowLabel, s.rowAbbrev);
|
|
5713
|
+
const abbr = rowAbbrev(rowLabel, s.rowAbbrev, config.rowsI18n?.[rowIdx]?.key);
|
|
5709
5714
|
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_react34.default.Fragment, { children: [
|
|
5710
5715
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "ss-g-btg-rowhdr", children: abbr === rowLabel ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: rowLabel }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_jsx_runtime71.Fragment, { children: [
|
|
5711
5716
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { "aria-hidden": "true", children: abbr }),
|
|
@@ -5914,15 +5919,17 @@ function GuessTheXiGame({
|
|
|
5914
5919
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "ss-g-gxi-rows", children: rows.map((row, r) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "ss-g-gxi-row", children: row.map((pos, c) => {
|
|
5915
5920
|
const posLabel = pos.slot ? posBySlot.get(pos.slot) ?? "" : "";
|
|
5916
5921
|
const name = pos.slot ? nameBySlot.get(pos.slot) : void 0;
|
|
5922
|
+
const flag = nationalityFlag(pos.nationality);
|
|
5917
5923
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "ss-g-gxi-node", "data-revealed": name ? "true" : void 0, children: [
|
|
5918
5924
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
5919
5925
|
"span",
|
|
5920
5926
|
{
|
|
5921
5927
|
className: "ss-g-gxi-disc",
|
|
5928
|
+
"data-code": isNationCode(flag) ? "true" : void 0,
|
|
5922
5929
|
role: "img",
|
|
5923
5930
|
title: pos.nationality,
|
|
5924
5931
|
"aria-label": `${posLabel ? posLabel + " \u2014 " : ""}${pos.nationality}${name ? " \u2014 " + name : ""}`,
|
|
5925
|
-
children:
|
|
5932
|
+
children: flag
|
|
5926
5933
|
}
|
|
5927
5934
|
),
|
|
5928
5935
|
name ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "ss-g-gxi-pos ss-g-gxi-pos--name", children: splitName(name).last }) : posLabel && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "ss-g-gxi-pos", children: posLabel })
|
|
@@ -6834,7 +6841,7 @@ function GameScreenHost({
|
|
|
6834
6841
|
let cancelled = false;
|
|
6835
6842
|
void (async () => {
|
|
6836
6843
|
try {
|
|
6837
|
-
const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || void 0);
|
|
6844
|
+
const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || void 0, ui.games.lang);
|
|
6838
6845
|
if (!cancelled && payload?.configJson) {
|
|
6839
6846
|
setConfigJson(payload.configJson);
|
|
6840
6847
|
}
|
|
@@ -6844,11 +6851,12 @@ function GameScreenHost({
|
|
|
6844
6851
|
return () => {
|
|
6845
6852
|
cancelled = true;
|
|
6846
6853
|
};
|
|
6847
|
-
}, [conversation, gameId, fixtureId, gameDay]);
|
|
6854
|
+
}, [conversation, gameId, fixtureId, gameDay, ui.games.lang]);
|
|
6848
6855
|
const { result, submitting, submit, hydrate, rawStatus } = useGamePlay(conversation, {
|
|
6849
6856
|
gameId,
|
|
6850
6857
|
gameDay,
|
|
6851
|
-
fixtureId: fixtureId || void 0
|
|
6858
|
+
fixtureId: fixtureId || void 0,
|
|
6859
|
+
locale: ui.games.lang
|
|
6852
6860
|
});
|
|
6853
6861
|
(0, import_react40.useEffect)(() => {
|
|
6854
6862
|
if (conversation) hydrate();
|
|
@@ -8383,6 +8391,16 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
8383
8391
|
/* Labels stay on one line: Turkish "DAHA FAZLA" wrapped to two in a ~115px button. */
|
|
8384
8392
|
.ss-g-hl-btns .ss-g-btn { font-weight: 800; font-size: 13px; letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }
|
|
8385
8393
|
.ss-g-hl-btns .ss-g-btn svg { flex: none; }
|
|
8394
|
+
/* Phone-width cards: the info column is ~230px, too narrow for "DAHA FAZLA" + icon side by side.
|
|
8395
|
+
Drop the icons and tighten the type first; stack the buttons only when even that cannot fit. */
|
|
8396
|
+
.ss-g-hl-info { container: hlinfo / inline-size; }
|
|
8397
|
+
@container hlinfo (max-width: 280px) {
|
|
8398
|
+
.ss-g-hl-btns .ss-g-btn svg { display: none; }
|
|
8399
|
+
.ss-g-hl-btns .ss-g-btn { font-size: 12px; letter-spacing: 0; padding: 0 4px; }
|
|
8400
|
+
}
|
|
8401
|
+
@container hlinfo (max-width: 180px) {
|
|
8402
|
+
.ss-g-hl-btns { flex-direction: column; }
|
|
8403
|
+
}
|
|
8386
8404
|
.ss-g-hl-vs { position: relative; z-index: 1; flex: none; align-self: center; width: 44px; height: 44px; margin: -28px 0; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-ground); border: 2px solid var(--ss-g-line-warm); color: var(--ss-w-accent); font: 800 18px var(--ss-g-font-display); }
|
|
8387
8405
|
/* Clear the VS badge that straddles the seam between the two cards. */
|
|
8388
8406
|
.ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 24px; }
|
|
@@ -8419,6 +8437,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
8419
8437
|
.ss-g-gxi-node { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; max-width: 72px; }
|
|
8420
8438
|
.ss-g-gxi-disc { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-pitch-chip); border: 2px solid var(--ss-g-pitch-ink); font-size: 22px; line-height: 1; }
|
|
8421
8439
|
.ss-g-gxi-node[data-revealed] .ss-g-gxi-disc { border-color: var(--ss-w-accent); }
|
|
8440
|
+
.ss-g-gxi-disc[data-code] { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; letter-spacing: .02em; color: var(--ss-g-pitch-ink); }
|
|
8422
8441
|
.ss-g-gxi-pos { max-width: 100%; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-pitch-chip); color: var(--ss-g-pitch-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
8423
8442
|
.ss-g-gxi-pos--name { color: var(--ss-w-accent); text-transform: uppercase; }
|
|
8424
8443
|
.ss-g-gxi-wrong { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|