@sensiblestats/widget-react 0.90.0 → 0.91.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 CHANGED
@@ -1,5 +1,16 @@
1
1
  # @sensiblestats/widget-react
2
2
 
3
+ ## 0.91.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2392632: Today tab lists NBA games alongside football for operators offered NBA
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [2392632]
12
+ - @sensiblestats/widget-sdk@0.61.0
13
+
3
14
  ## 0.90.0
4
15
 
5
16
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -38,7 +38,7 @@ module.exports = __toCommonJS(index_exports);
38
38
 
39
39
  // src/StatsWidget.tsx
40
40
  var import_react70 = require("react");
41
- var import_widget_sdk6 = require("@sensiblestats/widget-sdk");
41
+ var import_widget_sdk12 = require("@sensiblestats/widget-sdk");
42
42
 
43
43
  // src/kickoff.ts
44
44
  function formatBettingKickoff(kickoffUtc, ui, locale, now = /* @__PURE__ */ new Date()) {
@@ -1079,7 +1079,7 @@ function isEnglishLocale(locale) {
1079
1079
  }
1080
1080
 
1081
1081
  // src/version.generated.ts
1082
- var WIDGET_REACT_VERSION = "0.90.0";
1082
+ var WIDGET_REACT_VERSION = "0.91.0";
1083
1083
 
1084
1084
  // src/config.ts
1085
1085
  function normalizeUi(cfg) {
@@ -3278,10 +3278,11 @@ function useLiveMonitor(opts) {
3278
3278
 
3279
3279
  // src/useMatchDiscovery.ts
3280
3280
  var import_react6 = require("react");
3281
+ var import_widget_sdk6 = require("@sensiblestats/widget-sdk");
3281
3282
 
3282
3283
  // src/scheduleCache.ts
3283
3284
  var PREFIX = "ss-w-schedule:";
3284
- var SCHEMA_VERSION = 2;
3285
+ var SCHEMA_VERSION = 3;
3285
3286
  var TTL_MS2 = 6 * 36e5;
3286
3287
  function scheduleCacheKey(operatorId, encodedUserKey2, localDate) {
3287
3288
  return `${PREFIX}${operatorId}:${encodedUserKey2}:${localDate}`;
@@ -3309,6 +3310,7 @@ function skeletonOnly(payload) {
3309
3310
  return {
3310
3311
  localDate: payload.localDate,
3311
3312
  groups: payload.groups.map((g) => ({
3313
+ sport: g.sport,
3312
3314
  competitionId: g.competitionId,
3313
3315
  competitionName: g.competitionName,
3314
3316
  competitionCountry: g.competitionCountry ?? null,
@@ -3320,10 +3322,13 @@ function skeletonOnly(payload) {
3320
3322
  learnedRank: g.learnedRank,
3321
3323
  matches: g.matches.map((m) => ({
3322
3324
  matchId: m.matchId,
3325
+ sport: m.sport,
3323
3326
  homeTeamName: m.homeTeamName,
3324
3327
  awayTeamName: m.awayTeamName,
3325
3328
  homeTeamImagePath: m.homeTeamImagePath ?? null,
3326
3329
  awayTeamImagePath: m.awayTeamImagePath ?? null,
3330
+ homeTeamAbbr: m.homeTeamAbbr,
3331
+ awayTeamAbbr: m.awayTeamAbbr,
3327
3332
  kickoffUnix: m.kickoffUnix
3328
3333
  }))
3329
3334
  }))
@@ -3350,18 +3355,21 @@ function patchScheduleStar(operatorId, encodedUserKey2, localDate, competitionId
3350
3355
  }
3351
3356
 
3352
3357
  // src/dueSet.ts
3358
+ var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
3353
3359
  var TERMINAL_PHASES = /* @__PURE__ */ new Set(["fullTime", "postponed"]);
3354
3360
  function dueMatchIds(groups, states, nowMs) {
3355
- const due = /* @__PURE__ */ new Set();
3361
+ const football = /* @__PURE__ */ new Set();
3362
+ const nba = /* @__PURE__ */ new Set();
3356
3363
  for (const group of groups) {
3357
3364
  for (const match of group.matches) {
3358
3365
  if (nowMs - match.kickoffUnix * 1e3 < 0) continue;
3359
- const phase = states[match.matchId]?.phase;
3366
+ const phase = states.get((0, import_widget_sdk5.matchKey)(match.sport, match.matchId))?.phase;
3360
3367
  if (phase !== void 0 && TERMINAL_PHASES.has(phase)) continue;
3361
- due.add(match.matchId);
3368
+ const bucket = match.sport === "basketball" ? nba : football;
3369
+ bucket.add(match.matchId);
3362
3370
  }
3363
3371
  }
3364
- return [...due];
3372
+ return { football: [...football], nba: [...nba] };
3365
3373
  }
3366
3374
 
3367
3375
  // src/useMatchDiscovery.ts
@@ -3379,7 +3387,7 @@ function localDateOf(now) {
3379
3387
  }
3380
3388
  function useMatchDiscovery(opts) {
3381
3389
  const [groups, setGroups] = (0, import_react6.useState)([]);
3382
- const [states, setStates] = (0, import_react6.useState)({});
3390
+ const [states, setStates] = (0, import_react6.useState)(() => /* @__PURE__ */ new Map());
3383
3391
  const [failures, setFailures] = (0, import_react6.useState)(0);
3384
3392
  const groupsRef = (0, import_react6.useRef)(groups);
3385
3393
  groupsRef.current = groups;
@@ -3423,13 +3431,13 @@ function useMatchDiscovery(opts) {
3423
3431
  }, [opts.operatorId, opts.operatorUserId, opts.anonymousUserId, localDate]);
3424
3432
  const tick = (0, import_react6.useCallback)(async () => {
3425
3433
  const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now());
3426
- if (ids.length === 0) return;
3434
+ if (ids.football.length === 0 && ids.nba.length === 0) return;
3427
3435
  try {
3428
- const payload = await getStatesRef.current(ids);
3436
+ const payload = await getStatesRef.current(ids.football, ids.nba);
3429
3437
  if (!payload) return;
3430
3438
  setStates((prev) => {
3431
- const next = { ...prev };
3432
- for (const state of payload.states) next[state.matchId] = state;
3439
+ const next = new Map(prev);
3440
+ for (const state of payload.states) next.set((0, import_widget_sdk6.matchKey)(state.sport, state.matchId), state);
3433
3441
  return next;
3434
3442
  });
3435
3443
  setFailures(0);
@@ -3447,7 +3455,7 @@ function useMatchDiscovery(opts) {
3447
3455
  }, [opts.isOpen, tick, groups]);
3448
3456
  const stale = failures >= STALE_AFTER_FAILURES;
3449
3457
  const liveCount = (0, import_react6.useMemo)(
3450
- () => stale ? 0 : Object.values(states).filter((s) => s.phase === "live").length,
3458
+ () => stale ? 0 : [...states.values()].filter((s) => s.phase === "live").length,
3451
3459
  [states, stale]
3452
3460
  );
3453
3461
  const starLeague = (0, import_react6.useCallback)(async (competitionId, starred) => {
@@ -3985,6 +3993,7 @@ function hasAnyCell(grid) {
3985
3993
  }
3986
3994
 
3987
3995
  // src/liveClock.ts
3996
+ var import_widget_sdk7 = require("@sensiblestats/widget-sdk");
3988
3997
  function isTreatedLive(state, pollStale) {
3989
3998
  return state?.phase === "live" && !pollStale;
3990
3999
  }
@@ -3992,7 +4001,7 @@ function isFinished(state) {
3992
4001
  return state?.phase === "fullTime";
3993
4002
  }
3994
4003
  function visibleGroupsOf(groups, states) {
3995
- return groups.map((group) => ({ ...group, matches: group.matches.filter((m) => !isFinished(states[m.matchId])) })).filter((group) => group.matches.length > 0);
4004
+ return groups.map((group) => ({ ...group, matches: group.matches.filter((m) => !isFinished(states.get((0, import_widget_sdk7.matchKey)(m.sport, m.matchId)))) })).filter((group) => group.matches.length > 0);
3996
4005
  }
3997
4006
 
3998
4007
  // src/eventLogContext.ts
@@ -4369,7 +4378,7 @@ var import_react25 = require("react");
4369
4378
 
4370
4379
  // src/slipAdd.ts
4371
4380
  var import_react23 = require("react");
4372
- var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
4381
+ var import_widget_sdk8 = require("@sensiblestats/widget-sdk");
4373
4382
 
4374
4383
  // src/slipStateContext.ts
4375
4384
  var import_react22 = require("react");
@@ -4398,7 +4407,7 @@ function useSlipAdd(slip, ui) {
4398
4407
  }
4399
4408
  try {
4400
4409
  const raw = await withTimeout(Promise.resolve(handler(selection)));
4401
- if (raw != null && !(0, import_widget_sdk5.isAddToSlipResult)(raw)) throw new Error("malformed add-to-slip result");
4410
+ if (raw != null && !(0, import_widget_sdk8.isAddToSlipResult)(raw)) throw new Error("malformed add-to-slip result");
4402
4411
  const result = raw ?? void 0;
4403
4412
  if (marketDeveloperName !== void 0) {
4404
4413
  log?.log({
@@ -7158,6 +7167,7 @@ function OddsPanel({ monitor, ui, slip }) {
7158
7167
 
7159
7168
  // src/components/TodayPanel.tsx
7160
7169
  var import_react48 = require("react");
7170
+ var import_widget_sdk11 = require("@sensiblestats/widget-sdk");
7161
7171
 
7162
7172
  // src/placement.ts
7163
7173
  function placeLeagues(visible, pinnedMatchIds) {
@@ -7171,7 +7181,7 @@ function placeLeagues(visible, pinnedMatchIds) {
7171
7181
  }
7172
7182
  let budget = 4;
7173
7183
  const pinned = visible.find(
7174
- (g) => !candidateIds.has(g.competitionId) && g.matches.some((m) => pinnedMatchIds.includes(m.matchId))
7184
+ (g) => !candidateIds.has(g.competitionId) && g.matches.some((m) => m.sport !== "basketball" && pinnedMatchIds.includes(m.matchId))
7175
7185
  ) ?? null;
7176
7186
  if (pinned && budget > 0) {
7177
7187
  candidates.push(pinned);
@@ -7192,6 +7202,7 @@ function placeLeagues(visible, pinnedMatchIds) {
7192
7202
  return { personal, candidates: pool, others, order: [...pool, ...others], pinnedCompetitionId: pinned?.competitionId ?? null };
7193
7203
  }
7194
7204
  function starClickable(group, pinnedCompetitionId) {
7205
+ if (group.sport === "basketball") return false;
7195
7206
  return group.isStarred || group.competitionId !== pinnedCompetitionId;
7196
7207
  }
7197
7208
 
@@ -7257,7 +7268,7 @@ function LeagueTile({ group, starClickable: starClickable2, disambiguate, onOpen
7257
7268
  ] }) : null
7258
7269
  ] })
7259
7270
  ] }),
7260
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7271
+ group.sport !== "basketball" && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7261
7272
  "button",
7262
7273
  {
7263
7274
  type: "button",
@@ -7284,16 +7295,25 @@ function LeagueTile({ group, starClickable: starClickable2, disambiguate, onOpen
7284
7295
 
7285
7296
  // src/components/LeagueDetail.tsx
7286
7297
  var import_react46 = require("react");
7298
+ var import_widget_sdk9 = require("@sensiblestats/widget-sdk");
7287
7299
 
7288
7300
  // src/components/FixtureRow.tsx
7289
7301
  var import_jsx_runtime58 = require("react/jsx-runtime");
7302
+ function splitAtFirstSpace(label) {
7303
+ const i = label.indexOf(" ");
7304
+ return i > 0 && i < label.length - 1 ? [label.slice(0, i), label.slice(i + 1)] : null;
7305
+ }
7306
+ function isOtherLocalDay(kickoffUnix, now) {
7307
+ const at = new Date(kickoffUnix * 1e3);
7308
+ return at.getFullYear() !== now.getFullYear() || at.getMonth() !== now.getMonth() || at.getDate() !== now.getDate();
7309
+ }
7290
7310
  function kickoffLabel(kickoffUnix) {
7291
7311
  const d = new Date(kickoffUnix * 1e3);
7292
7312
  return `${`${d.getHours()}`.padStart(2, "0")}:${`${d.getMinutes()}`.padStart(2, "0")}`;
7293
7313
  }
7294
- function Side({ name, crest, away = false }) {
7314
+ function Side({ name, crest, abbr, away = false }) {
7295
7315
  return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: away ? "ss-w-drow-side ss-w-drow-side--away" : "ss-w-drow-side", children: [
7296
- crest ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("img", { className: "ss-w-drow-crest", src: crest, alt: "" }) : null,
7316
+ abbr ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-drow-crest ss-w-drow-crest--abbr", children: abbr }) : crest ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("img", { className: "ss-w-drow-crest", src: crest, alt: "" }) : null,
7297
7317
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-drow-nm", children: name })
7298
7318
  ] });
7299
7319
  }
@@ -7303,14 +7323,24 @@ function FixtureRow({ match, state, stale, ui, monitor }) {
7303
7323
  const score = hasScore ? `${state.homeScore}\u2013${state.awayScore}` : void 0;
7304
7324
  const ticked = state?.phase === "live" ? state.minuteLabel ?? null : null;
7305
7325
  const when = state?.isHalfTime && !stale ? ui.halfTime : isLive ? ticked ?? "\u2014" : state?.phase === "live" ? "\u2014" : kickoffLabel(match.kickoffUnix);
7306
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: isLive || state?.isHalfTime ? "ss-w-drow ss-w-drow--live" : "ss-w-drow", children: [
7307
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: isLive || state?.isHalfTime ? "ss-w-drow-when ss-w-drow-when--live" : "ss-w-drow-when", children: when }),
7326
+ const isNba = match.sport === "basketball";
7327
+ const liveTone = isLive || state?.isHalfTime;
7328
+ const clockParts = isNba && isLive && ticked !== null && !state?.isHalfTime ? splitAtFirstSpace(ticked) : null;
7329
+ const dayMarker = isNba && !liveTone && state?.phase !== "live" && isOtherLocalDay(match.kickoffUnix, /* @__PURE__ */ new Date()) ? new Intl.DateTimeFormat(ui.locale === "tr" ? "tr-TR" : "en-GB", { weekday: "short" }).format(new Date(match.kickoffUnix * 1e3)) : null;
7330
+ const twoLines = clockParts ?? (dayMarker !== null ? [when, dayMarker] : null);
7331
+ const whenClass = [
7332
+ "ss-w-drow-when",
7333
+ liveTone ? "ss-w-drow-when--live" : null,
7334
+ twoLines ? "ss-w-drow-when--two" : null
7335
+ ].filter(Boolean).join(" ");
7336
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: liveTone ? "ss-w-drow ss-w-drow--live" : "ss-w-drow", children: [
7337
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: whenClass, children: twoLines ? twoLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: line }, i)) : when }),
7308
7338
  /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "ss-w-drow-fx", children: [
7309
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Side, { name: match.homeTeamName, crest: match.homeTeamImagePath }),
7339
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Side, { name: match.homeTeamName, crest: match.homeTeamImagePath, abbr: isNba ? match.homeTeamAbbr ?? void 0 : void 0 }),
7310
7340
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: hasScore ? "ss-w-drow-sc" : "ss-w-drow-sc ss-w-drow-sc--idle", children: score ?? "\u2013" }),
7311
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Side, { name: match.awayTeamName, crest: match.awayTeamImagePath, away: true })
7341
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Side, { name: match.awayTeamName, crest: match.awayTeamImagePath, abbr: isNba ? match.awayTeamAbbr ?? void 0 : void 0, away: true })
7312
7342
  ] }),
7313
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
7343
+ !isNba && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
7314
7344
  ] });
7315
7345
  }
7316
7346
 
@@ -7327,7 +7357,7 @@ function LeagueDetail({ group, position, states, stale, ui, monitor, starTap, on
7327
7357
  const id = setTimeout(() => setToast(null), 4e3);
7328
7358
  return () => clearTimeout(id);
7329
7359
  }, [toast]);
7330
- const own = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale));
7360
+ const own = group.matches.filter((m) => !isTreatedLive(states.get((0, import_widget_sdk9.matchKey)(m.sport, m.matchId)), stale));
7331
7361
  const onStarClick = () => {
7332
7362
  const next = !group.isStarred;
7333
7363
  void starTap.tap(group.competitionId, next).then((ok) => {
@@ -7339,7 +7369,7 @@ function LeagueDetail({ group, position, states, stale, ui, monitor, starTap, on
7339
7369
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "ss-w-today-detail-back", "aria-label": ui.back, onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ChevronIcon, {}) }),
7340
7370
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Crest2, { url: group.competitionImagePath ?? void 0, name: group.competitionName, kind: "comp" }),
7341
7371
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-today-detail-name", children: group.competitionName }),
7342
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7372
+ group.sport !== "basketball" && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7343
7373
  "button",
7344
7374
  {
7345
7375
  type: "button",
@@ -7389,23 +7419,34 @@ function LeagueDetail({ group, position, states, stale, ui, monitor, starTap, on
7389
7419
  ] }),
7390
7420
  /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-today-detail-body", children: [
7391
7421
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-today-detail-count", children: own.length }),
7392
- own.map((m) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(FixtureRow, { match: m, state: states[m.matchId], stale, ui, monitor }, m.matchId))
7422
+ own.map((m) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7423
+ FixtureRow,
7424
+ {
7425
+ match: m,
7426
+ state: states.get((0, import_widget_sdk9.matchKey)(m.sport, m.matchId)),
7427
+ stale,
7428
+ ui,
7429
+ monitor
7430
+ },
7431
+ (0, import_widget_sdk9.matchKey)(m.sport, m.matchId)
7432
+ ))
7393
7433
  ] }),
7394
7434
  toast !== null && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "ss-w-today-toast", role: "status", "aria-live": "polite", children: toast })
7395
7435
  ] });
7396
7436
  }
7397
7437
 
7398
7438
  // src/components/LeagueRowGroup.tsx
7439
+ var import_widget_sdk10 = require("@sensiblestats/widget-sdk");
7399
7440
  var import_jsx_runtime60 = require("react/jsx-runtime");
7400
7441
  var ROW_CAP_PER_LEAGUE = 3;
7401
7442
  var SECTION_ROW_BUDGET = 12;
7402
7443
  function rowsFor(group, states, stale) {
7403
- const nonLive = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale)).length;
7444
+ const nonLive = group.matches.filter((m) => !isTreatedLive(states.get((0, import_widget_sdk10.matchKey)(m.sport, m.matchId)), stale)).length;
7404
7445
  return Math.min(nonLive, ROW_CAP_PER_LEAGUE);
7405
7446
  }
7406
7447
  var STAR_PATH3 = "M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z";
7407
7448
  function LeagueRowGroup({ group, states, stale, cap, starClickable: starClickable2, disambiguate, onOpen, starTap, ui, monitor }) {
7408
- const sorted = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale)).sort((a, b) => a.kickoffUnix - b.kickoffUnix);
7449
+ const sorted = group.matches.filter((m) => !isTreatedLive(states.get((0, import_widget_sdk10.matchKey)(m.sport, m.matchId)), stale)).sort((a, b) => a.kickoffUnix - b.kickoffUnix);
7409
7450
  if (sorted.length === 0) return null;
7410
7451
  const shown = sorted.slice(0, cap);
7411
7452
  const overflow = sorted.length - shown.length;
@@ -7425,7 +7466,7 @@ function LeagueRowGroup({ group, states, stale, cap, starClickable: starClickabl
7425
7466
  ] }) : null
7426
7467
  ] })
7427
7468
  ] }),
7428
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7469
+ group.sport !== "basketball" && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7429
7470
  "button",
7430
7471
  {
7431
7472
  type: "button",
@@ -7448,7 +7489,17 @@ function LeagueRowGroup({ group, states, stale, cap, starClickable: starClickabl
7448
7489
  }
7449
7490
  )
7450
7491
  ] }),
7451
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-today-rowgroup-rows", children: shown.map((m) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FixtureRow, { match: m, state: states[m.matchId], stale, ui, monitor }, m.matchId)) }),
7492
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-today-rowgroup-rows", children: shown.map((m) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7493
+ FixtureRow,
7494
+ {
7495
+ match: m,
7496
+ state: states.get((0, import_widget_sdk10.matchKey)(m.sport, m.matchId)),
7497
+ stale,
7498
+ ui,
7499
+ monitor
7500
+ },
7501
+ (0, import_widget_sdk10.matchKey)(m.sport, m.matchId)
7502
+ )) }),
7452
7503
  overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "ss-w-today-rowgroup-seeall", onClick: onOpen, children: ui.seeAllFixturesLabel(sorted.length) })
7453
7504
  ] });
7454
7505
  }
@@ -7591,7 +7642,7 @@ function TodayPanel({ discovery, ui, monitor }) {
7591
7642
  (0, import_react48.useEffect)(() => {
7592
7643
  if (selectedCompetitionId !== null && openGroup === void 0) setSelectedCompetitionId(null);
7593
7644
  }, [selectedCompetitionId, openGroup]);
7594
- const liveRows = stale ? [] : visibleGroups.flatMap((group) => group.matches.filter((m) => isTreatedLive(states[m.matchId], stale)).map((match) => ({ match, rank: group.rank }))).sort((a, b) => a.rank - b.rank);
7645
+ const liveRows = stale ? [] : visibleGroups.flatMap((group) => group.matches.filter((m) => isTreatedLive(states.get((0, import_widget_sdk11.matchKey)(m.sport, m.matchId)), stale)).map((match) => ({ match, rank: group.rank }))).sort((a, b) => a.rank - b.rank);
7595
7646
  const liveBand = liveRows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_jsx_runtime63.Fragment, { children: [
7596
7647
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "ss-w-sec-head", children: [
7597
7648
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "ss-w-sec-dot", "aria-hidden": "true" }),
@@ -7601,12 +7652,12 @@ function TodayPanel({ discovery, ui, monitor }) {
7601
7652
  FixtureRow,
7602
7653
  {
7603
7654
  match,
7604
- state: states[match.matchId],
7655
+ state: states.get((0, import_widget_sdk11.matchKey)(match.sport, match.matchId)),
7605
7656
  stale,
7606
7657
  ui,
7607
7658
  monitor
7608
7659
  },
7609
- match.matchId
7660
+ (0, import_widget_sdk11.matchKey)(match.sport, match.matchId)
7610
7661
  )) })
7611
7662
  ] });
7612
7663
  if (openGroup !== void 0) {
@@ -7676,9 +7727,18 @@ function TodayPanel({ discovery, ui, monitor }) {
7676
7727
  setSelectedCompetitionId(group.competitionId);
7677
7728
  }
7678
7729
  },
7679
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(FixtureRow, { match, state: states[match.matchId], stale, ui, monitor })
7730
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
7731
+ FixtureRow,
7732
+ {
7733
+ match,
7734
+ state: states.get((0, import_widget_sdk11.matchKey)(match.sport, match.matchId)),
7735
+ stale,
7736
+ ui,
7737
+ monitor
7738
+ }
7739
+ )
7680
7740
  },
7681
- match.matchId
7741
+ (0, import_widget_sdk11.matchKey)(match.sport, match.matchId)
7682
7742
  ))
7683
7743
  ] }, group.competitionId)) }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_jsx_runtime63.Fragment, { children: [
7684
7744
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "ss-w-today-sec", children: [
@@ -13372,6 +13432,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
13372
13432
  .ss-w-drow:last-child { border-bottom: none; }
13373
13433
  .ss-w-drow-when { font-size: 11px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }
13374
13434
  .ss-w-drow-when--live { color: var(--ss-w-neg); }
13435
+ .ss-w-drow-when--two { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
13436
+ .ss-w-drow-when--two > span:last-child { font-size: 10px; font-weight: 600; }
13375
13437
  /* Each side ellipsises independently: a single joined string truncates the away team off the end,
13376
13438
  which is the u350 betting-card truncation one layer down. */
13377
13439
  .ss-w-drow-fx { display: flex; align-items: center; gap: 6px; min-width: 0; }
@@ -13387,6 +13449,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
13387
13449
  .ss-w-drow-sc--idle { color: var(--ss-w-faint); font-weight: 600; }
13388
13450
  .ss-w-drow--live { background: color-mix(in srgb, var(--ss-w-neg) 5%, transparent); border-radius: 8px; padding: 7px 6px; margin: 0 -6px; border-bottom: none; }
13389
13451
  .ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }
13452
+ .ss-w-drow-crest--abbr { width: 26px; height: 16px; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; font-size: 8px; font-weight: 800; letter-spacing: .02em; line-height: 1; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); box-sizing: border-box; }
13390
13453
 
13391
13454
  .ss-w-stale { font-size: 11px; font-weight: 600; color: var(--ss-w-cta); background: color-mix(in srgb, var(--ss-w-cta) 12%, var(--ss-w-panel)); border-radius: 8px; padding: 6px 9px; }
13392
13455
 
@@ -13859,7 +13922,7 @@ function buildClient(props) {
13859
13922
  return { client: props.client, conversation: props.client.conversation() };
13860
13923
  }
13861
13924
  const cfg = props.config;
13862
- const client = new import_widget_sdk6.StatsWidgetClient(toClientOptions(cfg));
13925
+ const client = new import_widget_sdk12.StatsWidgetClient(toClientOptions(cfg));
13863
13926
  return { client, conversation: client.conversation(toUserContext(cfg)) };
13864
13927
  } catch (err) {
13865
13928
  console.error("[StatsWidget] failed to initialize:", err instanceof Error ? err.message : err);
@@ -13929,7 +13992,7 @@ function StatsWidget(props) {
13929
13992
  [built, operatorUserId, anonymousUserId]
13930
13993
  );
13931
13994
  const getStates = (0, import_react70.useCallback)(
13932
- (matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
13995
+ (matchIds, nbaGameIds) => built ? built.conversation.getStates(matchIds, nbaGameIds) : Promise.resolve(null),
13933
13996
  [built]
13934
13997
  );
13935
13998
  const pinnedMatchIds = (0, import_react70.useMemo)(