@sensiblestats/widget-react 0.54.0 → 0.55.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/CHANGELOG.md +11 -0
- package/dist/index.cjs +59 -37
- 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 +59 -37
- package/dist/index.js.map +1 -1
- package/dist/styles.css +14 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @sensiblestats/widget-react
|
|
2
2
|
|
|
3
|
+
## 0.55.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ede9739: Fix the daily games resetting on the second guess, and tighten three screens to the design artifact:
|
|
8
|
+
|
|
9
|
+
- Guard the play lifecycle against a state-losing submit response: an in-progress `postPlay` that returns no `clientStateJson` (e.g. a server-side concurrency retry) no longer wipes the board — the widget reconciles from `getGameResult` instead of rendering an empty state. (The root-cause fix is server-side; this is defence-in-depth so the board can never blank mid-game.)
|
|
10
|
+
- Guess the XI pitch now reads as a football field — fixed grass-green with visible yard-lines and a halfway line, and smaller flag dots — instead of a flat dark box.
|
|
11
|
+
- Mystery Tiger's first load shows one lead line above the search (no empty attribute tiles), matching the artifact; the shirt tile is labelled "Shirt" not "Kit".
|
|
12
|
+
- Beat the Grid filled cells now name the placed player (compact "F. Last") above the rarity score, so the fan can see who they put where.
|
|
13
|
+
|
|
3
14
|
## 0.54.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -4189,6 +4189,24 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
|
4189
4189
|
convRef.current = conversation;
|
|
4190
4190
|
const optsRef = (0, import_react28.useRef)({ gameId, gameDay, fixtureId, refresh });
|
|
4191
4191
|
optsRef.current = { gameId, gameDay, fixtureId, refresh };
|
|
4192
|
+
const resultRef = (0, import_react28.useRef)(null);
|
|
4193
|
+
resultRef.current = result;
|
|
4194
|
+
const refetch = (0, import_react28.useCallback)(async () => {
|
|
4195
|
+
const conv = convRef.current;
|
|
4196
|
+
if (!conv) return;
|
|
4197
|
+
const opts = optsRef.current;
|
|
4198
|
+
try {
|
|
4199
|
+
const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay);
|
|
4200
|
+
if (payload === null) return;
|
|
4201
|
+
if (payload.clientStateJson == null && resultRef.current?.clientStateJson != null) {
|
|
4202
|
+
setRawStatus(payload.status);
|
|
4203
|
+
return;
|
|
4204
|
+
}
|
|
4205
|
+
setResult(toSubmitResult(payload));
|
|
4206
|
+
setRawStatus(payload.status);
|
|
4207
|
+
} catch {
|
|
4208
|
+
}
|
|
4209
|
+
}, []);
|
|
4192
4210
|
const submit = (0, import_react28.useCallback)(async (answerJson) => {
|
|
4193
4211
|
const conv = convRef.current;
|
|
4194
4212
|
if (!conv || inFlightRef.current) return;
|
|
@@ -4198,7 +4216,14 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
|
4198
4216
|
const opts = optsRef.current;
|
|
4199
4217
|
const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId);
|
|
4200
4218
|
if (playResult !== null) {
|
|
4201
|
-
|
|
4219
|
+
const hasFreshState = playResult.clientStateJson != null;
|
|
4220
|
+
const isTerminal2 = playResult.alreadyPlayed === true;
|
|
4221
|
+
const holdsState = resultRef.current?.clientStateJson != null;
|
|
4222
|
+
if (!hasFreshState && !isTerminal2 && holdsState) {
|
|
4223
|
+
await refetch();
|
|
4224
|
+
} else {
|
|
4225
|
+
setResult(playResult);
|
|
4226
|
+
}
|
|
4202
4227
|
if (playResult.pointsDelta != null) {
|
|
4203
4228
|
opts.refresh?.();
|
|
4204
4229
|
}
|
|
@@ -4208,22 +4233,10 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
|
4208
4233
|
inFlightRef.current = false;
|
|
4209
4234
|
setSubmitting(false);
|
|
4210
4235
|
}
|
|
4211
|
-
}, []);
|
|
4236
|
+
}, [refetch]);
|
|
4212
4237
|
const hydrate = (0, import_react28.useCallback)(() => {
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
const opts = optsRef.current;
|
|
4216
|
-
void (async () => {
|
|
4217
|
-
try {
|
|
4218
|
-
const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay);
|
|
4219
|
-
if (payload !== null) {
|
|
4220
|
-
setResult(toSubmitResult(payload));
|
|
4221
|
-
setRawStatus(payload.status);
|
|
4222
|
-
}
|
|
4223
|
-
} catch {
|
|
4224
|
-
}
|
|
4225
|
-
})();
|
|
4226
|
-
}, []);
|
|
4238
|
+
void refetch();
|
|
4239
|
+
}, [refetch]);
|
|
4227
4240
|
return { result, submitting, submit, hydrate, rawStatus };
|
|
4228
4241
|
}
|
|
4229
4242
|
|
|
@@ -4325,7 +4338,7 @@ var ATTR_LABELS = {
|
|
|
4325
4338
|
position: "Pos",
|
|
4326
4339
|
nationality: "Nat",
|
|
4327
4340
|
age: "Age",
|
|
4328
|
-
shirtNumber: "
|
|
4341
|
+
shirtNumber: "Shirt",
|
|
4329
4342
|
apps: "Apps"
|
|
4330
4343
|
};
|
|
4331
4344
|
var ATTR_KEYS = [
|
|
@@ -4386,13 +4399,7 @@ function MysteryTigerGame({
|
|
|
4386
4399
|
" left"
|
|
4387
4400
|
] })
|
|
4388
4401
|
] }),
|
|
4389
|
-
guessResults.length === 0 && !isOver && /* @__PURE__ */ (0, import_jsx_runtime55.
|
|
4390
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gt-legend-lead", children: "Guess any squad player \u2014 each guess reveals how close you are:" }),
|
|
4391
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gtrow", children: ATTR_KEYS.map((key) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gtile ss-w-gtile--legend", children: [
|
|
4392
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "ss-w-gtile-lab", children: ATTR_LABELS[key] }),
|
|
4393
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "ss-w-gtile-v", "aria-hidden": "true", children: "\xB7" })
|
|
4394
|
-
] }, key)) })
|
|
4395
|
-
] }),
|
|
4402
|
+
guessResults.length === 0 && !isOver && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gt-lead", children: "Guess any squad player \u2014 each guess reveals how close you are on position, nationality, age, shirt and apps." }),
|
|
4396
4403
|
guessResults.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gtrows", children: guessResults.map((gr, i) => {
|
|
4397
4404
|
const player = config.squadPlayers.find((p) => p.id === gr.playerId);
|
|
4398
4405
|
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "ss-w-gtguess", children: [
|
|
@@ -4726,6 +4733,15 @@ function parseClientState4(json) {
|
|
|
4726
4733
|
function findCellResult(cells, row, col) {
|
|
4727
4734
|
return cells.find((c) => c.row === row && c.col === col);
|
|
4728
4735
|
}
|
|
4736
|
+
function shortName(name) {
|
|
4737
|
+
if (!name) return "";
|
|
4738
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
4739
|
+
if (parts.length === 0) return "";
|
|
4740
|
+
const first = parts[0];
|
|
4741
|
+
if (parts.length === 1) return first;
|
|
4742
|
+
const last = parts[parts.length - 1];
|
|
4743
|
+
return `${first.charAt(0)}. ${last}`;
|
|
4744
|
+
}
|
|
4729
4745
|
function SearchSheet({
|
|
4730
4746
|
row,
|
|
4731
4747
|
col,
|
|
@@ -4871,8 +4887,11 @@ function BeatTheGridGame({
|
|
|
4871
4887
|
disabled: isLocked2 || submitting,
|
|
4872
4888
|
onClick: () => handleCellClick(rowIdx, colIdx),
|
|
4873
4889
|
children: filled ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
|
|
4874
|
-
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-
|
|
4875
|
-
|
|
4890
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-nm", children: shortName(playerPool.find((p) => p.id === filled.playerId)?.name) }),
|
|
4891
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "ss-w-btg-cell-score", children: [
|
|
4892
|
+
filled.rarityScore,
|
|
4893
|
+
filled.isCorrect && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-check", "aria-hidden": "true", children: " \u2713" })
|
|
4894
|
+
] })
|
|
4876
4895
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-btg-cell-empty", "aria-hidden": "true", children: "+" })
|
|
4877
4896
|
},
|
|
4878
4897
|
`cell-${rowIdx}-${colIdx}`
|
|
@@ -6981,10 +7000,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
6981
7000
|
/* Guess rows \u2014 one labelled block per guess */
|
|
6982
7001
|
.ss-w-gtrows { display: flex; flex-direction: column; gap: 8px; }
|
|
6983
7002
|
/* First-load legend (empty state) */
|
|
6984
|
-
.ss-w-gt-
|
|
6985
|
-
.ss-w-gt-legend-lead { font-size: 11.5px; color: var(--ss-w-faint); line-height: 1.35; }
|
|
6986
|
-
.ss-w-gtile--legend { background: var(--ss-w-bubble); border: 1px dashed var(--ss-w-line); color: var(--ss-w-faint); }
|
|
6987
|
-
.ss-w-gtile--legend .ss-w-gtile-lab { opacity: .9; }
|
|
7003
|
+
.ss-w-gt-lead { font-size: 11.5px; color: var(--ss-w-faint); line-height: 1.4; }
|
|
6988
7004
|
.ss-w-gtguess { display: flex; flex-direction: column; gap: 4px; }
|
|
6989
7005
|
.ss-w-gtguess-nm { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }
|
|
6990
7006
|
.ss-w-gtrow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; }
|
|
@@ -7103,8 +7119,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
7103
7119
|
.ss-w-btg-cell--correct { background: color-mix(in srgb, var(--ss-w-correct) 14%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 35%, var(--ss-w-line)); }
|
|
7104
7120
|
.ss-w-btg-cell--wrong { background: color-mix(in srgb, var(--ss-w-wrong) 10%, var(--ss-w-panel)); }
|
|
7105
7121
|
.ss-w-btg-cell--active { border-color: var(--ss-w-accent); }
|
|
7106
|
-
.ss-w-btg-cell-
|
|
7107
|
-
.ss-w-btg-cell-
|
|
7122
|
+
.ss-w-btg-cell-nm { font-size: 8.5px; font-weight: 600; line-height: 1.05; color: var(--ss-w-ink); text-align: center; max-width: 100%; padding: 0 2px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
|
|
7123
|
+
.ss-w-btg-cell-score { font-size: 12px; font-weight: 800; color: var(--ss-w-accent); font-variant-numeric: tabular-nums; }
|
|
7124
|
+
.ss-w-btg-cell--correct .ss-w-btg-cell-score { color: var(--ss-w-correct); }
|
|
7125
|
+
.ss-w-btg-cell-check { color: var(--ss-w-correct); line-height: 1; }
|
|
7108
7126
|
.ss-w-btg-cell-empty { font-size: 16px; color: var(--ss-w-faint); }
|
|
7109
7127
|
/* Scoped search sheet: slides up over the grid */
|
|
7110
7128
|
.ss-w-btg-sheet { display: flex; flex-direction: column; gap: 10px; padding: 12px; background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-line); border-radius: 14px; box-shadow: 0 4px 20px rgba(0,0,0,.1); }
|
|
@@ -7126,12 +7144,16 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
7126
7144
|
/* Pitch: a flag per slot laid out in formation rows on a green field. A real min-height plus
|
|
7127
7145
|
space-between distributes the formation lines top\u2192bottom like a pitch (GK at the back, forwards
|
|
7128
7146
|
forward); yard-line stripes reinforce the read. Without a height the lines collapse together. */
|
|
7129
|
-
|
|
7147
|
+
/* A football pitch is grass-green regardless of the operator accent, so the field uses fixed
|
|
7148
|
+
green values (not --ss-w-correct, which is a muted per-operator token that vanished on dark
|
|
7149
|
+
themes) plus visible horizontal yard-lines and a brighter halfway line. */
|
|
7150
|
+
.ss-w-gxi-pitch { position: relative; display: flex; flex-direction: column; justify-content: space-between; gap: 8px; min-height: 300px; padding: 18px 10px; border-radius: 14px; border: 1px solid rgba(46, 160, 86, .38);
|
|
7130
7151
|
background:
|
|
7131
|
-
linear-gradient(180deg,
|
|
7132
|
-
repeating-linear-gradient(180deg, transparent 0
|
|
7133
|
-
|
|
7134
|
-
.ss-w-gxi-
|
|
7152
|
+
linear-gradient(180deg, rgba(46, 160, 86, .015) 0, rgba(46, 160, 86, .015) 49.5%, rgba(255,255,255,.14) 49.5%, rgba(255,255,255,.14) 50.5%, rgba(46, 160, 86, .015) 50.5%),
|
|
7153
|
+
repeating-linear-gradient(180deg, transparent 0 31px, rgba(255,255,255,.045) 31px 32px),
|
|
7154
|
+
linear-gradient(180deg, rgba(46, 160, 86, .28), rgba(38, 132, 71, .16)); }
|
|
7155
|
+
.ss-w-gxi-prow { display: flex; justify-content: center; align-items: center; gap: 12px; }
|
|
7156
|
+
.ss-w-gxi-flag { width: 32px; height: 32px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 17px; line-height: 1; background: rgba(9, 12, 10, .55); border: 1px solid rgba(255,255,255,.16); box-shadow: 0 1px 3px rgba(0,0,0,.3); overflow: hidden; }
|
|
7135
7157
|
/* Wrong-guess trail */
|
|
7136
7158
|
.ss-w-gxi-wrong { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
7137
7159
|
.ss-w-gxi-wrong-pill { font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: color-mix(in srgb, var(--ss-w-wrong) 10%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); text-decoration: line-through; }
|