@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 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
- return map[label] ?? label;
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: nationalityFlag(pos.nationality)
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; }