@sensiblestats/widget-react 0.81.0 → 0.81.2

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 CHANGED
@@ -37,7 +37,7 @@ __export(index_exports, {
37
37
  module.exports = __toCommonJS(index_exports);
38
38
 
39
39
  // src/StatsWidget.tsx
40
- var import_react60 = require("react");
40
+ var import_react61 = require("react");
41
41
  var import_widget_sdk6 = require("@sensiblestats/widget-sdk");
42
42
 
43
43
  // src/kickoff.ts
@@ -158,6 +158,7 @@ var STRINGS = {
158
158
  allLeagues: "All leagues",
159
159
  searchLeaguesPlaceholder: "Search leagues or teams",
160
160
  noLeagueResults: "No league or team matches that search.",
161
+ clearSearchLabel: "Clear search",
161
162
  starOnLabel: "Add to Your leagues",
162
163
  starOffLabel: "Remove from Your leagues",
163
164
  starredToast: "Added to Your leagues.",
@@ -523,6 +524,7 @@ var STRINGS = {
523
524
  allLeagues: "T\xFCm ligler",
524
525
  searchLeaguesPlaceholder: "Lig veya tak\u0131m ara",
525
526
  noLeagueResults: "Aramana uyan lig veya tak\u0131m yok.",
527
+ clearSearchLabel: "Aramay\u0131 temizle",
526
528
  starOnLabel: "Liglerine ekle",
527
529
  starOffLabel: "Liglerinden \xE7\u0131kar",
528
530
  starredToast: "Liglerin b\xF6l\xFCm\xFCne eklendi.",
@@ -885,6 +887,7 @@ function normalizeUi(cfg) {
885
887
  allLeagues: strings.allLeagues,
886
888
  searchLeaguesPlaceholder: strings.searchLeaguesPlaceholder,
887
889
  noLeagueResults: strings.noLeagueResults,
890
+ clearSearchLabel: strings.clearSearchLabel,
888
891
  starOnLabel: strings.starOnLabel,
889
892
  starOffLabel: strings.starOffLabel,
890
893
  starredToast: strings.starredToast,
@@ -3449,7 +3452,7 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
3449
3452
  }
3450
3453
 
3451
3454
  // src/components/ChatPanel.tsx
3452
- var import_react59 = require("react");
3455
+ var import_react60 = require("react");
3453
3456
 
3454
3457
  // src/components/ChatHeader.tsx
3455
3458
  var import_react15 = require("react");
@@ -3854,7 +3857,8 @@ function PinToggle({ pin, monitor, ui, market }) {
3854
3857
  const key = pinKey(pin);
3855
3858
  const pinned = monitor.isPinned(key);
3856
3859
  const labels = pin.kind === "match" ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel } : { pin: ui.pinLabel, unpin: ui.unpinLabel };
3857
- const onClick = () => {
3860
+ const onClick = (e) => {
3861
+ e.stopPropagation();
3858
3862
  if (pin.kind === "match" && !monitor.isPinned(key)) {
3859
3863
  if (monitor.pinMatch({ matchId: pin.matchId, marketDeveloperName: market }) === "added") {
3860
3864
  log?.log({ name: "pin_add", entityType: "match", entityId: String(pin.matchId), marketDeveloperName: pin.marketDeveloperName });
@@ -5958,7 +5962,7 @@ function OddsPanel({ monitor, ui, slip }) {
5958
5962
  }
5959
5963
 
5960
5964
  // src/components/TodayPanel.tsx
5961
- var import_react40 = require("react");
5965
+ var import_react41 = require("react");
5962
5966
 
5963
5967
  // src/placement.ts
5964
5968
  function placeLeagues(visible, pinnedMatchIds) {
@@ -6000,15 +6004,25 @@ function starClickable(group, pinnedCompetitionId) {
6000
6004
  function foldSearchText(s) {
6001
6005
  return s.replace(/İ/g, "I").replace(/ı/g, "i").normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
6002
6006
  }
6007
+ function competitionMatchesQuery(group, q) {
6008
+ if (foldSearchText(group.competitionName).includes(q)) return true;
6009
+ return !!group.competitionCountry && foldSearchText(group.competitionCountry).includes(q);
6010
+ }
6003
6011
  function matchesQuery(group, query) {
6004
6012
  const q = foldSearchText(query.trim());
6005
6013
  if (!q) return true;
6006
- if (foldSearchText(group.competitionName).includes(q)) return true;
6007
- if (group.competitionCountry && foldSearchText(group.competitionCountry).includes(q)) return true;
6014
+ if (competitionMatchesQuery(group, q)) return true;
6008
6015
  return group.matches.some(
6009
6016
  (m) => foldSearchText(m.homeTeamName).includes(q) || foldSearchText(m.awayTeamName).includes(q)
6010
6017
  );
6011
6018
  }
6019
+ function matchingFixtures(group, query) {
6020
+ const q = foldSearchText(query.trim());
6021
+ if (!q || competitionMatchesQuery(group, q)) return group.matches;
6022
+ return group.matches.filter(
6023
+ (m) => foldSearchText(m.homeTeamName).includes(q) || foldSearchText(m.awayTeamName).includes(q)
6024
+ );
6025
+ }
6012
6026
 
6013
6027
  // src/useStarTap.ts
6014
6028
  var import_react38 = require("react");
@@ -6186,6 +6200,9 @@ function LeagueDetail({ group, position, states, stale, ui, monitor, starTap, on
6186
6200
  ] });
6187
6201
  }
6188
6202
 
6203
+ // src/components/games/ui/SearchField.tsx
6204
+ var import_react40 = require("react");
6205
+
6189
6206
  // src/components/games/ui/icons.tsx
6190
6207
  var import_jsx_runtime58 = require("react/jsx-runtime");
6191
6208
  var svg = (size, children, fill = false) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
@@ -6222,7 +6239,13 @@ var IconFlame = ({ size = 16 }) => svg(size, /* @__PURE__ */ (0, import_jsx_runt
6222
6239
 
6223
6240
  // src/components/games/ui/SearchField.tsx
6224
6241
  var import_jsx_runtime59 = require("react/jsx-runtime");
6225
- function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown }) {
6242
+ function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown, clearLabel }) {
6243
+ const localRef = (0, import_react40.useRef)(null);
6244
+ const setInputRef = (0, import_react40.useCallback)((node) => {
6245
+ localRef.current = node;
6246
+ if (typeof inputRef === "function") inputRef(node);
6247
+ else if (inputRef) inputRef.current = node;
6248
+ }, [inputRef]);
6226
6249
  return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-g-search", children: [
6227
6250
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("label", { htmlFor: id, className: labelHidden ? "ss-g-sr" : "ss-g-search-label", children: label }),
6228
6251
  /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-g-search-box", children: [
@@ -6231,7 +6254,7 @@ function SearchField({ id, label, labelHidden = false, placeholder, value, onCha
6231
6254
  "input",
6232
6255
  {
6233
6256
  id,
6234
- ref: inputRef,
6257
+ ref: setInputRef,
6235
6258
  type: "text",
6236
6259
  autoComplete: "off",
6237
6260
  placeholder,
@@ -6240,7 +6263,20 @@ function SearchField({ id, label, labelHidden = false, placeholder, value, onCha
6240
6263
  onKeyDown,
6241
6264
  onChange: (e) => onChange(e.target.value)
6242
6265
  }
6243
- )
6266
+ ),
6267
+ clearLabel && value.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6268
+ "button",
6269
+ {
6270
+ type: "button",
6271
+ className: "ss-g-search-clear",
6272
+ "aria-label": clearLabel,
6273
+ onClick: () => {
6274
+ onChange("");
6275
+ localRef.current?.focus();
6276
+ },
6277
+ children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(IconClose, { size: 11 })
6278
+ }
6279
+ ) : null
6244
6280
  ] })
6245
6281
  ] });
6246
6282
  }
@@ -6249,23 +6285,23 @@ function SearchField({ id, label, labelHidden = false, placeholder, value, onCha
6249
6285
  var import_jsx_runtime60 = require("react/jsx-runtime");
6250
6286
  function TodayPanel({ discovery, ui, monitor }) {
6251
6287
  const { groups, states, stale, starLeague } = discovery;
6252
- const searchId = (0, import_react40.useId)();
6253
- const [query, setQuery] = (0, import_react40.useState)("");
6254
- const [selectedCompetitionId, setSelectedCompetitionId] = (0, import_react40.useState)(null);
6255
- const [toast, setToast] = (0, import_react40.useState)(null);
6256
- (0, import_react40.useEffect)(() => {
6288
+ const searchId = (0, import_react41.useId)();
6289
+ const [query, setQuery] = (0, import_react41.useState)("");
6290
+ const [selectedCompetitionId, setSelectedCompetitionId] = (0, import_react41.useState)(null);
6291
+ const [toast, setToast] = (0, import_react41.useState)(null);
6292
+ (0, import_react41.useEffect)(() => {
6257
6293
  if (toast === null) return;
6258
6294
  const id = setTimeout(() => setToast(null), 4e3);
6259
6295
  return () => clearTimeout(id);
6260
6296
  }, [toast]);
6261
6297
  const visibleGroups = visibleGroupsOf(groups, states);
6262
- const pinnedMatchIds = (0, import_react40.useMemo)(
6298
+ const pinnedMatchIds = (0, import_react41.useMemo)(
6263
6299
  () => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
6264
6300
  [monitor.pins]
6265
6301
  );
6266
- const placement = (0, import_react40.useMemo)(() => placeLeagues(visibleGroups, pinnedMatchIds), [visibleGroups, pinnedMatchIds]);
6302
+ const placement = (0, import_react41.useMemo)(() => placeLeagues(visibleGroups, pinnedMatchIds), [visibleGroups, pinnedMatchIds]);
6267
6303
  const starTap = useStarTap(starLeague);
6268
- const gridStarTap = (0, import_react40.useMemo)(() => ({
6304
+ const gridStarTap = (0, import_react41.useMemo)(() => ({
6269
6305
  pendingId: starTap.pendingId,
6270
6306
  tap: async (competitionId, next) => {
6271
6307
  const ok = await starTap.tap(competitionId, next);
@@ -6279,7 +6315,7 @@ function TodayPanel({ discovery, ui, monitor }) {
6279
6315
  }, {});
6280
6316
  const openIndex = selectedCompetitionId === null ? -1 : placement.order.findIndex((g) => g.competitionId === selectedCompetitionId);
6281
6317
  const openGroup = openIndex === -1 ? void 0 : placement.order[openIndex];
6282
- (0, import_react40.useEffect)(() => {
6318
+ (0, import_react41.useEffect)(() => {
6283
6319
  if (selectedCompetitionId !== null && openGroup === void 0) setSelectedCompetitionId(null);
6284
6320
  }, [selectedCompetitionId, openGroup]);
6285
6321
  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);
@@ -6324,7 +6360,7 @@ function TodayPanel({ discovery, ui, monitor }) {
6324
6360
  ] }) });
6325
6361
  }
6326
6362
  const searching = query.trim().length > 0;
6327
- const searchResults = searching ? visibleGroups.filter((g) => matchesQuery(g, query)) : [];
6363
+ const searchResults = searching ? placement.order.filter((g) => matchesQuery(g, query)) : [];
6328
6364
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-today-root", children: [
6329
6365
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-mon-list", children: [
6330
6366
  stale && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-stale", children: ui.staleStates }),
@@ -6337,21 +6373,41 @@ function TodayPanel({ discovery, ui, monitor }) {
6337
6373
  labelHidden: true,
6338
6374
  placeholder: ui.searchLeaguesPlaceholder,
6339
6375
  value: query,
6340
- onChange: setQuery
6376
+ onChange: setQuery,
6377
+ clearLabel: ui.clearSearchLabel
6341
6378
  }
6342
6379
  ),
6343
- searching ? searchResults.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-today-empty", children: ui.noLeagueResults }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-today-tiles", children: searchResults.map((group) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6344
- LeagueTile,
6345
- {
6346
- group,
6347
- starClickable: starClickable(group, placement.pinnedCompetitionId),
6348
- disambiguate: (nameCounts[group.competitionName] ?? 0) > 1,
6349
- onOpen: () => setSelectedCompetitionId(group.competitionId),
6350
- starTap: gridStarTap,
6351
- ui
6352
- },
6353
- group.competitionId
6354
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
6380
+ searching ? searchResults.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "ss-w-today-empty", children: ui.noLeagueResults }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_jsx_runtime60.Fragment, { children: searchResults.map((group) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-today-search-block", children: [
6381
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-today-search-group", children: [
6382
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Crest2, { url: group.competitionImagePath ?? void 0, name: group.competitionName, kind: "comp" }),
6383
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "ss-w-today-search-group-name", children: [
6384
+ group.competitionName,
6385
+ (nameCounts[group.competitionName] ?? 0) > 1 && group.competitionCountry ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "ss-w-today-tile-country", children: [
6386
+ " (",
6387
+ group.competitionCountry,
6388
+ ")"
6389
+ ] }) : null
6390
+ ] })
6391
+ ] }),
6392
+ matchingFixtures(group, query).map((match) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6393
+ "div",
6394
+ {
6395
+ role: "button",
6396
+ tabIndex: 0,
6397
+ className: "ss-w-today-search-row",
6398
+ onClick: () => setSelectedCompetitionId(group.competitionId),
6399
+ onKeyDown: (e) => {
6400
+ if (e.target !== e.currentTarget) return;
6401
+ if (e.key === "Enter" || e.key === " ") {
6402
+ e.preventDefault();
6403
+ setSelectedCompetitionId(group.competitionId);
6404
+ }
6405
+ },
6406
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FixtureRow, { match, state: states[match.matchId], stale, ui, monitor })
6407
+ },
6408
+ match.matchId
6409
+ ))
6410
+ ] }, group.competitionId)) }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
6355
6411
  /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "ss-w-today-sec", children: [
6356
6412
  placement.personal ? ui.yourLeagues : ui.topLeagues,
6357
6413
  !placement.personal && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "ss-w-today-sec-sub", children: ui.topLeaguesSub })
@@ -6388,7 +6444,7 @@ function TodayPanel({ discovery, ui, monitor }) {
6388
6444
  }
6389
6445
 
6390
6446
  // src/components/GamesPanel.tsx
6391
- var import_react54 = require("react");
6447
+ var import_react55 = require("react");
6392
6448
 
6393
6449
  // src/components/GamesLoginWall.tsx
6394
6450
  var import_jsx_runtime61 = require("react/jsx-runtime");
@@ -6397,7 +6453,7 @@ function GamesLoginWall({ ui }) {
6397
6453
  }
6398
6454
 
6399
6455
  // src/components/GamesHub.tsx
6400
- var import_react41 = require("react");
6456
+ var import_react42 = require("react");
6401
6457
 
6402
6458
  // src/components/games/ui/gameMeta.ts
6403
6459
  function prettifyGameId(gameId) {
@@ -6548,8 +6604,8 @@ function pickHeroGame(games) {
6548
6604
  }
6549
6605
  var tileKey = (g) => `${g.gameId}-${g.gameDay}-${g.fixtureId}`;
6550
6606
  function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
6551
- const [, setTick] = (0, import_react41.useState)(0);
6552
- (0, import_react41.useEffect)(() => {
6607
+ const [, setTick] = (0, import_react42.useState)(0);
6608
+ (0, import_react42.useEffect)(() => {
6553
6609
  const id = setInterval(() => setTick((t) => t + 1), 6e4);
6554
6610
  return () => clearInterval(id);
6555
6611
  }, []);
@@ -6609,10 +6665,10 @@ function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
6609
6665
  }
6610
6666
 
6611
6667
  // src/components/GameScreenHost.tsx
6612
- var import_react53 = require("react");
6668
+ var import_react54 = require("react");
6613
6669
 
6614
6670
  // src/useGamePlay.ts
6615
- var import_react42 = require("react");
6671
+ var import_react43 = require("react");
6616
6672
  function toSubmitResult(payload) {
6617
6673
  return {
6618
6674
  // 'pending' means the play is recorded but awaiting resolution (fixture games)
@@ -6624,17 +6680,17 @@ function toSubmitResult(payload) {
6624
6680
  };
6625
6681
  }
6626
6682
  function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh }) {
6627
- const [result, setResult] = (0, import_react42.useState)(null);
6628
- const [submitting, setSubmitting] = (0, import_react42.useState)(false);
6629
- const [rawStatus, setRawStatus] = (0, import_react42.useState)(null);
6630
- const inFlightRef = (0, import_react42.useRef)(false);
6631
- const convRef = (0, import_react42.useRef)(conversation);
6683
+ const [result, setResult] = (0, import_react43.useState)(null);
6684
+ const [submitting, setSubmitting] = (0, import_react43.useState)(false);
6685
+ const [rawStatus, setRawStatus] = (0, import_react43.useState)(null);
6686
+ const inFlightRef = (0, import_react43.useRef)(false);
6687
+ const convRef = (0, import_react43.useRef)(conversation);
6632
6688
  convRef.current = conversation;
6633
- const optsRef = (0, import_react42.useRef)({ gameId, gameDay, fixtureId, locale, refresh });
6689
+ const optsRef = (0, import_react43.useRef)({ gameId, gameDay, fixtureId, locale, refresh });
6634
6690
  optsRef.current = { gameId, gameDay, fixtureId, locale, refresh };
6635
- const resultRef = (0, import_react42.useRef)(null);
6691
+ const resultRef = (0, import_react43.useRef)(null);
6636
6692
  resultRef.current = result;
6637
- const refetch = (0, import_react42.useCallback)(async () => {
6693
+ const refetch = (0, import_react43.useCallback)(async () => {
6638
6694
  const conv = convRef.current;
6639
6695
  if (!conv) return;
6640
6696
  const opts = optsRef.current;
@@ -6650,7 +6706,7 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
6650
6706
  } catch {
6651
6707
  }
6652
6708
  }, []);
6653
- const submit = (0, import_react42.useCallback)(async (answerJson) => {
6709
+ const submit = (0, import_react43.useCallback)(async (answerJson) => {
6654
6710
  const conv = convRef.current;
6655
6711
  if (!conv || inFlightRef.current) return;
6656
6712
  inFlightRef.current = true;
@@ -6677,14 +6733,14 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
6677
6733
  setSubmitting(false);
6678
6734
  }
6679
6735
  }, [refetch]);
6680
- const hydrate = (0, import_react42.useCallback)(() => {
6736
+ const hydrate = (0, import_react43.useCallback)(() => {
6681
6737
  void refetch();
6682
6738
  }, [refetch]);
6683
6739
  return { result, submitting, submit, hydrate, rawStatus };
6684
6740
  }
6685
6741
 
6686
6742
  // src/components/games/MysteryTigerGame.tsx
6687
- var import_react44 = require("react");
6743
+ var import_react45 = require("react");
6688
6744
 
6689
6745
  // src/components/games/nationFlags.ts
6690
6746
  var FLAGS = {
@@ -6895,7 +6951,7 @@ function isNationCode(flag) {
6895
6951
  }
6896
6952
 
6897
6953
  // src/components/games/PlayerAvatar.tsx
6898
- var import_react43 = require("react");
6954
+ var import_react44 = require("react");
6899
6955
  var import_jsx_runtime66 = require("react/jsx-runtime");
6900
6956
  function initialsOf(name) {
6901
6957
  const parts = name.trim().split(/\s+/).filter(Boolean);
@@ -6913,7 +6969,7 @@ function PlayerAvatar({
6913
6969
  imagePath,
6914
6970
  className
6915
6971
  }) {
6916
- const [failed, setFailed] = (0, import_react43.useState)(false);
6972
+ const [failed, setFailed] = (0, import_react44.useState)(false);
6917
6973
  const showImage = Boolean(imagePath) && !isPlaceholderImage(imagePath) && !failed;
6918
6974
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className, "aria-hidden": "true", children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("img", { src: imagePath, alt: "", loading: "lazy", onError: () => setFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "ss-w-av-initials", children: initialsOf(name) }) });
6919
6975
  }
@@ -7154,8 +7210,8 @@ function MysteryTigerGame({
7154
7210
  onBack
7155
7211
  }) {
7156
7212
  const t = ui.games.mysteryTiger;
7157
- const [query, setQuery] = (0, import_react44.useState)("");
7158
- const inputId = (0, import_react44.useId)();
7213
+ const [query, setQuery] = (0, import_react45.useState)("");
7214
+ const inputId = (0, import_react45.useId)();
7159
7215
  const clientState = parseClientState(result?.clientStateJson);
7160
7216
  const guessResults = clientState?.guessResults ?? [];
7161
7217
  const alreadyGuessedIds = new Set(guessResults.map((g) => g.playerId));
@@ -7416,13 +7472,13 @@ function HigherOrLowerGame({
7416
7472
  }
7417
7473
 
7418
7474
  // src/components/games/CareerPathGame.tsx
7419
- var import_react46 = require("react");
7475
+ var import_react47 = require("react");
7420
7476
 
7421
7477
  // src/components/games/ui/CrestShield.tsx
7422
- var import_react45 = require("react");
7478
+ var import_react46 = require("react");
7423
7479
  var import_jsx_runtime77 = require("react/jsx-runtime");
7424
7480
  function CrestShield({ src, name, size = 28 }) {
7425
- const [failed, setFailed] = (0, import_react45.useState)(false);
7481
+ const [failed, setFailed] = (0, import_react46.useState)(false);
7426
7482
  if (src && !isPlaceholderImage(src) && !failed) {
7427
7483
  return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("img", { className: "ss-g-crest", src, alt: name, width: size, height: size, loading: "lazy", onError: () => setFailed(true) });
7428
7484
  }
@@ -7454,8 +7510,8 @@ function CareerPathGame({
7454
7510
  }) {
7455
7511
  const s = ui.games.careerPath;
7456
7512
  const title = gameTitle({ gameId: "career-path" }, ui.games.titles);
7457
- const [query, setQuery] = (0, import_react46.useState)("");
7458
- const inputId = (0, import_react46.useId)();
7513
+ const [query, setQuery] = (0, import_react47.useState)("");
7514
+ const inputId = (0, import_react47.useId)();
7459
7515
  const clientState = parseClientState3(result?.clientStateJson);
7460
7516
  const alreadyGuessedIds = new Set(clientState?.guessResults.map((g) => g.playerId) ?? []);
7461
7517
  const isOver = result?.alreadyPlayed === true || clientState?.solved === true || clientState?.failed === true;
@@ -7561,7 +7617,7 @@ function CareerPathGame({
7561
7617
  }
7562
7618
 
7563
7619
  // src/components/games/BeatTheGridGame.tsx
7564
- var import_react47 = __toESM(require("react"), 1);
7620
+ var import_react48 = __toESM(require("react"), 1);
7565
7621
 
7566
7622
  // src/components/games/ui/OptionList.tsx
7567
7623
  var import_jsx_runtime79 = require("react/jsx-runtime");
@@ -7650,10 +7706,10 @@ function SearchSheet({
7650
7706
  ui
7651
7707
  }) {
7652
7708
  const s = ui.games.beatTheGrid;
7653
- const [query, setQuery] = (0, import_react47.useState)("");
7654
- const inputId = (0, import_react47.useId)();
7655
- const inputRef = (0, import_react47.useRef)(null);
7656
- (0, import_react47.useEffect)(() => {
7709
+ const [query, setQuery] = (0, import_react48.useState)("");
7710
+ const inputId = (0, import_react48.useId)();
7711
+ const inputRef = (0, import_react48.useRef)(null);
7712
+ (0, import_react48.useEffect)(() => {
7657
7713
  inputRef.current?.focus();
7658
7714
  }, [row, col]);
7659
7715
  const filtered = playerPool.filter(
@@ -7718,7 +7774,7 @@ function BeatTheGridGame({
7718
7774
  }) {
7719
7775
  const s = ui.games.beatTheGrid;
7720
7776
  const title = gameTitle({ gameId: "beat-the-grid" }, ui.games.titles);
7721
- const [activeCell, setActiveCell] = (0, import_react47.useState)(null);
7777
+ const [activeCell, setActiveCell] = (0, import_react48.useState)(null);
7722
7778
  const clientState = parseClientState4(result?.clientStateJson);
7723
7779
  const filledCells = clientState?.cells ?? [];
7724
7780
  const isLocked2 = result?.alreadyPlayed === true || clientState?.isComplete === true;
@@ -7792,7 +7848,7 @@ function BeatTheGridGame({
7792
7848
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { "aria-hidden": "true", children: abbr }),
7793
7849
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "ss-g-sr", children: rowLabel })
7794
7850
  ] });
7795
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_react47.default.Fragment, { children: [
7851
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_react48.default.Fragment, { children: [
7796
7852
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "ss-g-btg-rowhdr", "data-meta": rowMeta ? "true" : void 0, children: rowHeaderContent }),
7797
7853
  cols.map((colLabel, colIdx) => {
7798
7854
  const filled = findCellResult(filledCells, rowIdx, colIdx);
@@ -7873,7 +7929,7 @@ function BeatTheGridGame({
7873
7929
  }
7874
7930
 
7875
7931
  // src/components/games/GuessTheXiGame.tsx
7876
- var import_react48 = require("react");
7932
+ var import_react49 = require("react");
7877
7933
 
7878
7934
  // src/components/games/ui/PitchSvg.tsx
7879
7935
  var import_jsx_runtime81 = require("react/jsx-runtime");
@@ -7962,8 +8018,8 @@ function GuessTheXiGame({
7962
8018
  onBack
7963
8019
  }) {
7964
8020
  const t = ui.games.guessTheXi;
7965
- const [query, setQuery] = (0, import_react48.useState)("");
7966
- const inputId = (0, import_react48.useId)();
8021
+ const [query, setQuery] = (0, import_react49.useState)("");
8022
+ const inputId = (0, import_react49.useId)();
7967
8023
  const clientState = parseClientState5(result?.clientStateJson);
7968
8024
  const isOver = result?.alreadyPlayed === true || clientState?.status === "solved" || clientState?.status === "failed";
7969
8025
  const solved = clientState?.status === "solved";
@@ -8105,7 +8161,7 @@ function GuessTheXiGame({
8105
8161
  }
8106
8162
 
8107
8163
  // src/components/games/DailyQuizGame.tsx
8108
- var import_react49 = require("react");
8164
+ var import_react50 = require("react");
8109
8165
  var import_jsx_runtime83 = require("react/jsx-runtime");
8110
8166
  function parseClientState6(json) {
8111
8167
  if (!json) return null;
@@ -8146,8 +8202,8 @@ function DailyQuizGame({
8146
8202
  }) {
8147
8203
  const s = ui.games.dailyQuiz;
8148
8204
  const title = gameTitle({ gameId: "daily-quiz" }, ui.games.titles);
8149
- const [selections, setSelections] = (0, import_react49.useState)(/* @__PURE__ */ new Map());
8150
- const [page, setPage] = (0, import_react49.useState)(0);
8205
+ const [selections, setSelections] = (0, import_react50.useState)(/* @__PURE__ */ new Map());
8206
+ const [page, setPage] = (0, import_react50.useState)(0);
8151
8207
  const clientState = parseClientState6(result?.clientStateJson);
8152
8208
  const results = clientState?.results ?? [];
8153
8209
  const isRevealed = results.length > 0 || result?.alreadyPlayed === true;
@@ -8257,7 +8313,7 @@ function DailyQuizGame({
8257
8313
  }
8258
8314
 
8259
8315
  // src/components/games/MatchdayPredictorGame.tsx
8260
- var import_react50 = require("react");
8316
+ var import_react51 = require("react");
8261
8317
  var import_jsx_runtime84 = require("react/jsx-runtime");
8262
8318
  var SCORER_SEARCH_THRESHOLD = 9;
8263
8319
  function parseClientState7(json) {
@@ -8353,12 +8409,12 @@ function MatchdayPredictorGame({
8353
8409
  onBack
8354
8410
  }) {
8355
8411
  const t = ui.games.predictor;
8356
- const [homeScore, setHomeScore] = (0, import_react50.useState)(0);
8357
- const [awayScore, setAwayScore] = (0, import_react50.useState)(0);
8358
- const [firstScorerPlayerId, setFirstScorerPlayerId] = (0, import_react50.useState)(null);
8359
- const [lastEdited, setLastEdited] = (0, import_react50.useState)("home");
8360
- const [query, setQuery] = (0, import_react50.useState)("");
8361
- const searchId = (0, import_react50.useId)();
8412
+ const [homeScore, setHomeScore] = (0, import_react51.useState)(0);
8413
+ const [awayScore, setAwayScore] = (0, import_react51.useState)(0);
8414
+ const [firstScorerPlayerId, setFirstScorerPlayerId] = (0, import_react51.useState)(null);
8415
+ const [lastEdited, setLastEdited] = (0, import_react51.useState)("home");
8416
+ const [query, setQuery] = (0, import_react51.useState)("");
8417
+ const searchId = (0, import_react51.useId)();
8362
8418
  const clientState = parseClientState7(result?.clientStateJson);
8363
8419
  const alreadyPlayed = result?.alreadyPlayed === true;
8364
8420
  const header = /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
@@ -8525,7 +8581,7 @@ function MatchdayPredictorGame({
8525
8581
  }
8526
8582
 
8527
8583
  // src/components/games/StartingXiGame.tsx
8528
- var import_react51 = require("react");
8584
+ var import_react52 = require("react");
8529
8585
  var import_jsx_runtime85 = require("react/jsx-runtime");
8530
8586
  var POINTS_PER_STARTER = 8;
8531
8587
  var XI_SIZE = 11;
@@ -8569,10 +8625,10 @@ function StartingXiGame({
8569
8625
  lockAtUtc
8570
8626
  }) {
8571
8627
  const t = ui.games.startingXi;
8572
- const [slotPlayers, setSlotPlayers] = (0, import_react51.useState)(() => Array(XI_SIZE).fill(null));
8573
- const [active, setActive] = (0, import_react51.useState)(0);
8574
- const [query, setQuery] = (0, import_react51.useState)("");
8575
- const searchId = (0, import_react51.useId)();
8628
+ const [slotPlayers, setSlotPlayers] = (0, import_react52.useState)(() => Array(XI_SIZE).fill(null));
8629
+ const [active, setActive] = (0, import_react52.useState)(0);
8630
+ const [query, setQuery] = (0, import_react52.useState)("");
8631
+ const searchId = (0, import_react52.useId)();
8576
8632
  const clientState = parseClientState8(result?.clientStateJson);
8577
8633
  const alreadyPlayed = result?.alreadyPlayed === true;
8578
8634
  const header = /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
@@ -8711,7 +8767,7 @@ function StartingXiGame({
8711
8767
  }
8712
8768
 
8713
8769
  // src/components/games/StatLadderGame.tsx
8714
- var import_react52 = require("react");
8770
+ var import_react53 = require("react");
8715
8771
  var import_jsx_runtime86 = require("react/jsx-runtime");
8716
8772
  function ladderClue(ladder) {
8717
8773
  const mystery = ladder.find((r) => r.rank === 2);
@@ -8748,9 +8804,9 @@ function StatLadderGame({
8748
8804
  onBack
8749
8805
  }) {
8750
8806
  const t = ui.games.statLadder;
8751
- const [query, setQuery] = (0, import_react52.useState)("");
8752
- const [selectedId, setSelectedId] = (0, import_react52.useState)(null);
8753
- const searchId = (0, import_react52.useId)();
8807
+ const [query, setQuery] = (0, import_react53.useState)("");
8808
+ const [selectedId, setSelectedId] = (0, import_react53.useState)(null);
8809
+ const searchId = (0, import_react53.useId)();
8754
8810
  const clientState = parseClientState9(result?.clientStateJson);
8755
8811
  const revealed = clientState != null;
8756
8812
  const header = /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(GameHeader, { title: gameTitle({ gameId: "stat-ladder" }, ui.games.titles), eyebrow: t.eyebrow, onBack, backLabel: ui.back });
@@ -8956,8 +9012,8 @@ function GameScreenHost({
8956
9012
  ui
8957
9013
  }) {
8958
9014
  const { gameId, fixtureId, gameDay = "", lockAtUtc = null } = selected;
8959
- const [configJson, setConfigJson] = (0, import_react53.useState)(null);
8960
- (0, import_react53.useEffect)(() => {
9015
+ const [configJson, setConfigJson] = (0, import_react54.useState)(null);
9016
+ (0, import_react54.useEffect)(() => {
8961
9017
  setConfigJson(null);
8962
9018
  if (!conversation) return;
8963
9019
  let cancelled = false;
@@ -8980,12 +9036,12 @@ function GameScreenHost({
8980
9036
  fixtureId: fixtureId || void 0,
8981
9037
  locale: ui.games.lang
8982
9038
  });
8983
- (0, import_react53.useEffect)(() => {
9039
+ (0, import_react54.useEffect)(() => {
8984
9040
  if (conversation) hydrate();
8985
9041
  }, [conversation, gameId]);
8986
- const hydrateRef = (0, import_react53.useRef)(hydrate);
9042
+ const hydrateRef = (0, import_react54.useRef)(hydrate);
8987
9043
  hydrateRef.current = hydrate;
8988
- (0, import_react53.useEffect)(() => {
9044
+ (0, import_react54.useEffect)(() => {
8989
9045
  if (!FIXTURE_GAME_IDS.has(gameId)) return;
8990
9046
  if (rawStatus !== "pending") return;
8991
9047
  const timerId = setInterval(() => {
@@ -9120,8 +9176,8 @@ function GamesPanel({
9120
9176
  leaderboard,
9121
9177
  refreshHub
9122
9178
  }) {
9123
- const [selected, setSelected] = (0, import_react54.useState)(null);
9124
- (0, import_react54.useEffect)(() => {
9179
+ const [selected, setSelected] = (0, import_react55.useState)(null);
9180
+ (0, import_react55.useEffect)(() => {
9125
9181
  ensureGamesFonts();
9126
9182
  }, []);
9127
9183
  if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(GamesLoginWall, { ui });
@@ -9152,7 +9208,7 @@ function GamesPanel({
9152
9208
  }
9153
9209
 
9154
9210
  // src/components/Leaderboard.tsx
9155
- var import_react55 = require("react");
9211
+ var import_react56 = require("react");
9156
9212
 
9157
9213
  // src/components/LeaderboardRow.tsx
9158
9214
  var import_jsx_runtime90 = require("react/jsx-runtime");
@@ -9237,7 +9293,7 @@ function Leaderboard({
9237
9293
  ui,
9238
9294
  onPlay
9239
9295
  }) {
9240
- const [segment, setSegment] = (0, import_react55.useState)("weekly");
9296
+ const [segment, setSegment] = (0, import_react56.useState)("weekly");
9241
9297
  const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
9242
9298
  const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
9243
9299
  const isEmpty = segment === "weekly" ? data.weeklyTop.length === 0 : data.allTimeTop.length === 0;
@@ -9317,10 +9373,10 @@ function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }) {
9317
9373
  }
9318
9374
 
9319
9375
  // src/components/PresetSpeedDial.tsx
9320
- var import_react56 = require("react");
9376
+ var import_react57 = require("react");
9321
9377
  var import_jsx_runtime94 = require("react/jsx-runtime");
9322
9378
  function PresetSpeedDial({ expanded, showDot, strings, onToggle, onOpen, rootRef, buttonRef }) {
9323
- const pillsId = (0, import_react56.useId)();
9379
+ const pillsId = (0, import_react57.useId)();
9324
9380
  const tabIndex = expanded ? 0 : -1;
9325
9381
  return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { ref: rootRef, className: "ss-w-dial", children: [
9326
9382
  /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(
@@ -9354,16 +9410,16 @@ function PresetSpeedDial({ expanded, showDot, strings, onToggle, onOpen, rootRef
9354
9410
  }
9355
9411
 
9356
9412
  // src/components/PresetTools.tsx
9357
- var import_react57 = require("react");
9413
+ var import_react58 = require("react");
9358
9414
  var import_jsx_runtime95 = require("react/jsx-runtime");
9359
9415
  var FOCUSABLE = 'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
9360
9416
  function PresetToolModal({ title, closeLabel, onClose, children, footer }) {
9361
- const dialogRef = (0, import_react57.useRef)(null);
9362
- const titleId = (0, import_react57.useId)();
9363
- (0, import_react57.useEffect)(() => {
9417
+ const dialogRef = (0, import_react58.useRef)(null);
9418
+ const titleId = (0, import_react58.useId)();
9419
+ (0, import_react58.useEffect)(() => {
9364
9420
  dialogRef.current?.focus();
9365
9421
  }, []);
9366
- (0, import_react57.useEffect)(() => {
9422
+ (0, import_react58.useEffect)(() => {
9367
9423
  const onKey = (e) => {
9368
9424
  if (e.key !== "Escape") return;
9369
9425
  e.stopPropagation();
@@ -9405,7 +9461,7 @@ function PresetToolModal({ title, closeLabel, onClose, children, footer }) {
9405
9461
  function fillTemplate(template, slots) {
9406
9462
  return template.split(/(\{[a-z]+\})/).filter((part) => part !== "").map((part, i) => {
9407
9463
  const key = /^\{([a-z]+)\}$/.exec(part)?.[1];
9408
- return /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(import_react57.Fragment, { children: key !== void 0 && key in slots ? slots[key] : part }, i);
9464
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(import_react58.Fragment, { children: key !== void 0 && key in slots ? slots[key] : part }, i);
9409
9465
  });
9410
9466
  }
9411
9467
  function NumberSelect({ current, choices: choices2, label, notToday, lockEmpty = true, onChoose }) {
@@ -9474,15 +9530,15 @@ function SetNumbersTool({ grid, strings, streaming, onSend, onClose }) {
9474
9530
  const totals = comboTotals(grid);
9475
9531
  const legChoices = comboLegChoices(grid);
9476
9532
  const count = FIXED_SINGLES_COUNT;
9477
- const [maxPrice, setMaxPrice] = (0, import_react57.useState)(() => startSingles(grid.singles, limits, START.maxPrice, count));
9478
- const [minPrice, setMinPrice] = (0, import_react57.useState)(() => startSingles(grid.singlesFrom, floors, START.minPrice, count));
9479
- const [start] = (0, import_react57.useState)(() => startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs));
9480
- const [total, setTotal] = (0, import_react57.useState)(start.total);
9481
- const [legs, setLegs] = (0, import_react57.useState)(start.legs);
9482
- const [bigStart] = (0, import_react57.useState)(() => startCombo(grid, totals, legChoices, BIG_COMBO.total, BIG_COMBO.legs));
9483
- const [bigTotal, setBigTotal] = (0, import_react57.useState)(bigStart.total);
9484
- const [bigLegs, setBigLegs] = (0, import_react57.useState)(bigStart.legs);
9485
- const [announcement, setAnnouncement] = (0, import_react57.useState)("");
9533
+ const [maxPrice, setMaxPrice] = (0, import_react58.useState)(() => startSingles(grid.singles, limits, START.maxPrice, count));
9534
+ const [minPrice, setMinPrice] = (0, import_react58.useState)(() => startSingles(grid.singlesFrom, floors, START.minPrice, count));
9535
+ const [start] = (0, import_react58.useState)(() => startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs));
9536
+ const [total, setTotal] = (0, import_react58.useState)(start.total);
9537
+ const [legs, setLegs] = (0, import_react58.useState)(start.legs);
9538
+ const [bigStart] = (0, import_react58.useState)(() => startCombo(grid, totals, legChoices, BIG_COMBO.total, BIG_COMBO.legs));
9539
+ const [bigTotal, setBigTotal] = (0, import_react58.useState)(bigStart.total);
9540
+ const [bigLegs, setBigLegs] = (0, import_react58.useState)(bigStart.legs);
9541
+ const [announcement, setAnnouncement] = (0, import_react58.useState)("");
9486
9542
  const maxCell = findSingles(grid.singles, maxPrice, count);
9487
9543
  const minCell = findSingles(grid.singlesFrom, minPrice, count);
9488
9544
  const comboCell = findCombo(grid, total, legs);
@@ -9526,7 +9582,7 @@ function SetNumbersTool({ grid, strings, streaming, onSend, onClose }) {
9526
9582
  const totalChoices = totals.map((v) => ({ value: v, text: v.toFixed(1), available: legChoices.some((n) => !!findCombo(grid, v, n)) }));
9527
9583
  const legChoicesFor = (t) => legChoices.map((n) => ({ value: n, text: String(n), available: !!findCombo(grid, t, n) }));
9528
9584
  const markets = grid.markets ?? [];
9529
- const [marketIdx, setMarketIdx] = (0, import_react57.useState)(0);
9585
+ const [marketIdx, setMarketIdx] = (0, import_react58.useState)(0);
9530
9586
  const marketCell = markets[marketIdx] ?? null;
9531
9587
  const marketLabels = markets.map((c) => strings.marketShort(c.marketDeveloperName, c.marketLabel, c.selectionLabel ?? null));
9532
9588
  const singlesReady = (cell) => cell ? strings.readyCount(cell.picks.length) : strings.unavailable;
@@ -9607,14 +9663,14 @@ function SetNumbersTool({ grid, strings, streaming, onSend, onClose }) {
9607
9663
  function BuildComboTool({ grid, strings, streaming, formatKickoff, initialTotal, initialLegs, onSend, onClose }) {
9608
9664
  const totals = comboTotals(grid);
9609
9665
  const legChoices = comboLegChoices(grid);
9610
- const [start] = (0, import_react57.useState)(() => initialTotal === void 0 ? startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs) : null);
9611
- const [total, setTotal] = (0, import_react57.useState)(() => initialTotal !== void 0 ? nearest(totals, initialTotal) : start.total);
9612
- const [legs, setLegs] = (0, import_react57.useState)(() => {
9666
+ const [start] = (0, import_react58.useState)(() => initialTotal === void 0 ? startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs) : null);
9667
+ const [total, setTotal] = (0, import_react58.useState)(() => initialTotal !== void 0 ? nearest(totals, initialTotal) : start.total);
9668
+ const [legs, setLegs] = (0, import_react58.useState)(() => {
9613
9669
  if (initialTotal === void 0) return initialLegs !== void 0 ? clampLegs(legChoices, initialLegs) : start.legs;
9614
9670
  const from = initialLegs !== void 0 ? clampLegs(legChoices, initialLegs) : startValue(legChoices, START.comboLegs);
9615
9671
  return legsForTotal(grid, nearest(totals, initialTotal), from);
9616
9672
  });
9617
- const [announcement, setAnnouncement] = (0, import_react57.useState)("");
9673
+ const [announcement, setAnnouncement] = (0, import_react58.useState)("");
9618
9674
  const cell = findCombo(grid, total, legs);
9619
9675
  const minLegs = legChoices[0] ?? legs;
9620
9676
  const maxLegs = legChoices[legChoices.length - 1] ?? legs;
@@ -9647,7 +9703,7 @@ function BuildComboTool({ grid, strings, streaming, formatKickoff, initialTotal,
9647
9703
  }
9648
9704
 
9649
9705
  // src/usePresetDial.ts
9650
- var import_react58 = require("react");
9706
+ var import_react59 = require("react");
9651
9707
  function sendInFlight(messages, isStreaming) {
9652
9708
  const last = messages[messages.length - 1];
9653
9709
  return isStreaming && !!last && last.role === "assistant" && !last.done && !last.isGreeting;
@@ -9661,25 +9717,25 @@ function lastUserId(messages) {
9661
9717
  }
9662
9718
  var SCROLL_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", " "]);
9663
9719
  function usePresetDial({ layerRef, dialRef, dialButtonRef, messages, isStreaming, activeTab }) {
9664
- const [expanded, setExpanded] = (0, import_react58.useState)(() => !sendInFlight(messages, isStreaming));
9665
- const fold = (0, import_react58.useCallback)(() => setExpanded(false), []);
9666
- const toggle = (0, import_react58.useCallback)(() => setExpanded((e) => !e), []);
9720
+ const [expanded, setExpanded] = (0, import_react59.useState)(() => !sendInFlight(messages, isStreaming));
9721
+ const fold = (0, import_react59.useCallback)(() => setExpanded(false), []);
9722
+ const toggle = (0, import_react59.useCallback)(() => setExpanded((e) => !e), []);
9667
9723
  const currentUserId = lastUserId(messages);
9668
- const userIdRef = (0, import_react58.useRef)(currentUserId);
9669
- (0, import_react58.useEffect)(() => {
9724
+ const userIdRef = (0, import_react59.useRef)(currentUserId);
9725
+ (0, import_react59.useEffect)(() => {
9670
9726
  if (currentUserId === userIdRef.current) return;
9671
9727
  userIdRef.current = currentUserId;
9672
9728
  setExpanded(false);
9673
9729
  }, [currentUserId]);
9674
- const tabRef = (0, import_react58.useRef)(activeTab);
9675
- (0, import_react58.useEffect)(() => {
9730
+ const tabRef = (0, import_react59.useRef)(activeTab);
9731
+ (0, import_react59.useEffect)(() => {
9676
9732
  if (activeTab === tabRef.current) return;
9677
9733
  tabRef.current = activeTab;
9678
9734
  setExpanded(false);
9679
9735
  }, [activeTab]);
9680
- const expandedRef = (0, import_react58.useRef)(expanded);
9736
+ const expandedRef = (0, import_react59.useRef)(expanded);
9681
9737
  expandedRef.current = expanded;
9682
- (0, import_react58.useEffect)(() => {
9738
+ (0, import_react59.useEffect)(() => {
9683
9739
  const onEscape = (e) => {
9684
9740
  const dial = dialRef.current;
9685
9741
  if (e.key !== "Escape" || !dial || !e.composedPath().includes(dial)) return;
@@ -9692,7 +9748,7 @@ function usePresetDial({ layerRef, dialRef, dialButtonRef, messages, isStreaming
9692
9748
  window.addEventListener("keydown", onEscape, true);
9693
9749
  return () => window.removeEventListener("keydown", onEscape, true);
9694
9750
  }, [dialRef, dialButtonRef]);
9695
- (0, import_react58.useEffect)(() => {
9751
+ (0, import_react59.useEffect)(() => {
9696
9752
  if (!expanded) return;
9697
9753
  const layer = layerRef.current;
9698
9754
  const inDial = (e) => {
@@ -9747,8 +9803,8 @@ function markToolSeen() {
9747
9803
  var import_jsx_runtime96 = require("react/jsx-runtime");
9748
9804
  var FULLSCREEN_QUERY = "(max-width: 639px)";
9749
9805
  function useIsModal() {
9750
- const [modal, setModal] = (0, import_react59.useState)(false);
9751
- (0, import_react59.useEffect)(() => {
9806
+ const [modal, setModal] = (0, import_react60.useState)(false);
9807
+ (0, import_react60.useEffect)(() => {
9752
9808
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
9753
9809
  const mql = window.matchMedia(FULLSCREEN_QUERY);
9754
9810
  const sync = () => setModal(mql.matches);
@@ -9762,7 +9818,7 @@ var HIDDEN_LAYER_STYLE = { position: "absolute", inset: 0, visibility: "hidden",
9762
9818
  function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation, presetGrid }) {
9763
9819
  const { state, close, stop, send, reset } = controller;
9764
9820
  const isModal = useIsModal();
9765
- (0, import_react59.useEffect)(() => {
9821
+ (0, import_react60.useEffect)(() => {
9766
9822
  const onKey = (e) => {
9767
9823
  if (e.key === "Escape") close();
9768
9824
  };
@@ -9778,19 +9834,19 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
9778
9834
  monitor?.setActiveTab("chat");
9779
9835
  send(text, { grounding });
9780
9836
  };
9781
- (0, import_react59.useEffect)(() => {
9837
+ (0, import_react60.useEffect)(() => {
9782
9838
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
9783
9839
  }, [monitor, state.isStreaming, state.messages.length]);
9784
9840
  const onChatTab = !monitor || monitor.activeTab === "chat";
9785
- const layerRef = (0, import_react59.useRef)(null);
9786
- const dialRef = (0, import_react59.useRef)(null);
9787
- const dialButtonRef = (0, import_react59.useRef)(null);
9788
- const inputRef = (0, import_react59.useRef)(null);
9789
- const limitRef = (0, import_react59.useRef)(null);
9790
- const typedSendRef = (0, import_react59.useRef)(false);
9791
- const focusAfterCloseRef = (0, import_react59.useRef)(null);
9792
- const [tool, setTool] = (0, import_react59.useState)(null);
9793
- const [toolSeen, setToolSeen] = (0, import_react59.useState)(readToolSeen);
9841
+ const layerRef = (0, import_react60.useRef)(null);
9842
+ const dialRef = (0, import_react60.useRef)(null);
9843
+ const dialButtonRef = (0, import_react60.useRef)(null);
9844
+ const inputRef = (0, import_react60.useRef)(null);
9845
+ const limitRef = (0, import_react60.useRef)(null);
9846
+ const typedSendRef = (0, import_react60.useRef)(false);
9847
+ const focusAfterCloseRef = (0, import_react60.useRef)(null);
9848
+ const [tool, setTool] = (0, import_react60.useState)(null);
9849
+ const [toolSeen, setToolSeen] = (0, import_react60.useState)(readToolSeen);
9794
9850
  const dial = usePresetDial({
9795
9851
  layerRef,
9796
9852
  dialRef,
@@ -9802,47 +9858,47 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
9802
9858
  const { fold } = dial;
9803
9859
  const paused = isPaused(state.limit);
9804
9860
  const showDial = !!presetGrid && onChatTab && !tool && !paused;
9805
- (0, import_react59.useEffect)(() => {
9861
+ (0, import_react60.useEffect)(() => {
9806
9862
  if (paused) setTool(null);
9807
9863
  }, [paused]);
9808
- (0, import_react59.useEffect)(() => {
9864
+ (0, import_react60.useEffect)(() => {
9809
9865
  if (!paused) return;
9810
9866
  if (typedSendRef.current) limitRef.current?.focus();
9811
9867
  typedSendRef.current = false;
9812
9868
  }, [paused]);
9813
- const openTool = (0, import_react59.useCallback)((next) => {
9869
+ const openTool = (0, import_react60.useCallback)((next) => {
9814
9870
  fold();
9815
9871
  markToolSeen();
9816
9872
  setToolSeen(true);
9817
9873
  setTool(next);
9818
9874
  }, [fold]);
9819
- const onPill = (0, import_react59.useCallback)((kind) => openTool(kind === "numbers" ? { kind: "numbers" } : { kind: "combo" }), [openTool]);
9820
- const toolsValue = (0, import_react59.useMemo)(
9875
+ const onPill = (0, import_react60.useCallback)((kind) => openTool(kind === "numbers" ? { kind: "numbers" } : { kind: "combo" }), [openTool]);
9876
+ const toolsValue = (0, import_react60.useMemo)(
9821
9877
  () => presetGrid && !paused ? { openBuilder: (total, legs) => openTool({ kind: "combo", total, legs }), changeLabel: ui.presets.changeCombo } : null,
9822
9878
  [presetGrid, paused, openTool, ui.presets.changeCombo]
9823
9879
  );
9824
- const closeTool = (0, import_react59.useCallback)(() => {
9880
+ const closeTool = (0, import_react60.useCallback)(() => {
9825
9881
  focusAfterCloseRef.current = "dial";
9826
9882
  setTool(null);
9827
9883
  }, []);
9828
- const sendAsk = (0, import_react59.useCallback)((ask) => {
9884
+ const sendAsk = (0, import_react60.useCallback)((ask) => {
9829
9885
  focusAfterCloseRef.current = "composer";
9830
9886
  setTool(null);
9831
9887
  monitor?.setActiveTab("chat");
9832
9888
  send(ask.message, { displayText: ask.displayText, preset: ask.preset });
9833
9889
  }, [monitor, send]);
9834
- const formatKickoff = (0, import_react59.useCallback)((kickoffUtc) => {
9890
+ const formatKickoff = (0, import_react60.useCallback)((kickoffUtc) => {
9835
9891
  const k = ui.bettingKickoff(kickoffUtc);
9836
9892
  return `${k.dayLabel} ${k.time}`;
9837
9893
  }, [ui]);
9838
- (0, import_react59.useEffect)(() => {
9894
+ (0, import_react60.useEffect)(() => {
9839
9895
  if (tool) return;
9840
9896
  const target = focusAfterCloseRef.current;
9841
9897
  focusAfterCloseRef.current = null;
9842
9898
  if (target === "dial") dialButtonRef.current?.focus();
9843
9899
  else if (target === "composer") inputRef.current?.focus();
9844
9900
  }, [tool]);
9845
- (0, import_react59.useEffect)(() => {
9901
+ (0, import_react60.useEffect)(() => {
9846
9902
  if (!tool || onChatTab && presetGrid) return;
9847
9903
  focusAfterCloseRef.current = "composer";
9848
9904
  setTool(null);
@@ -10061,6 +10117,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
10061
10117
  .ss-g-search-box { display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1.5px solid var(--ss-g-line); color: var(--ss-g-muted); }
10062
10118
  .ss-g-search-box:focus-within { border-color: var(--ss-w-accent); }
10063
10119
  .ss-g-search-box input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; color: var(--ss-g-ink); font: 500 15px var(--ss-g-font-body); }
10120
+ .ss-g-search-clear { flex: none; width: 20px; height: 20px; padding: 0; border: none; border-radius: 50%; background: var(--ss-g-line); color: var(--ss-g-muted); display: flex; align-items: center; justify-content: center; cursor: pointer; }
10121
+ .ss-g-search-clear:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }
10064
10122
  .ss-g-footer { flex: none; padding: 12px 16px 16px; border-top: 1px solid var(--ss-g-line); display: flex; flex-direction: column; gap: 10px; background: var(--ss-g-ground); }
10065
10123
  .ss-g-sil { position: relative; flex: none; display: inline-flex; align-items: flex-end; justify-content: center; overflow: hidden; border-radius: 50%; background: var(--ss-g-raised); color: var(--ss-g-strong-line); }
10066
10124
  .ss-g-sil--selected { background: var(--ss-g-accent-tint); color: color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-g-raised)); }
@@ -11150,6 +11208,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
11150
11208
  .ss-w-today-sec-sub { text-transform: none; letter-spacing: normal; font-weight: 600; }
11151
11209
  .ss-w-today-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
11152
11210
  .ss-w-today-empty { font-size: 12px; color: var(--ss-w-faint); padding: 10px 2px; }
11211
+ .ss-w-today-search-block { display: flex; flex-direction: column; }
11212
+ .ss-w-today-search-group { display: flex; align-items: center; gap: 7px; padding: 2px 2px 6px; }
11213
+ .ss-w-today-search-group::after { content: ""; flex: 1; height: 1px; background: var(--ss-w-line); }
11214
+ .ss-w-today-search-group .ss-w-bi-comp-logo { width: 16px; height: 16px; }
11215
+ .ss-w-today-search-group-name { font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
11216
+ .ss-w-today-search-row { cursor: pointer; border-radius: 10px; }
11217
+ .ss-w-today-search-row:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }
11153
11218
 
11154
11219
  /* League tile (Task 5): a flat row (crest + name as the open target, star as a separate sibling
11155
11220
  button) rather than a disclosure header -- opening is Task 6's LeagueDetail, not an inline
@@ -11696,24 +11761,24 @@ function injectStyles(root) {
11696
11761
  function StatsWidget(props) {
11697
11762
  const injectedClient = "client" in props ? props.client : void 0;
11698
11763
  const cfg = props.config;
11699
- const built = (0, import_react60.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
11700
- const logger = (0, import_react60.useMemo)(
11764
+ const built = (0, import_react61.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
11765
+ const logger = (0, import_react61.useMemo)(
11701
11766
  () => built ? built.client.createEventLogger({
11702
11767
  operatorUserId: cfg?.userContext?.operatorUserId,
11703
11768
  anonymousUserId: cfg?.userContext?.anonymousUserId
11704
11769
  }) : null,
11705
11770
  [built?.client]
11706
11771
  );
11707
- const ui = (0, import_react60.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
11708
- const rootRef = (0, import_react60.useRef)(null);
11709
- const introDoneRef = (0, import_react60.useRef)(false);
11710
- const markIntroDone = (0, import_react60.useCallback)(() => {
11772
+ const ui = (0, import_react61.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
11773
+ const rootRef = (0, import_react61.useRef)(null);
11774
+ const introDoneRef = (0, import_react61.useRef)(false);
11775
+ const markIntroDone = (0, import_react61.useCallback)(() => {
11711
11776
  introDoneRef.current = true;
11712
11777
  }, []);
11713
11778
  const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
11714
11779
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
11715
- const [hasToday, setHasToday] = (0, import_react60.useState)(false);
11716
- const liveCardWatches = (0, import_react60.useMemo)(() => {
11780
+ const [hasToday, setHasToday] = (0, import_react61.useState)(false);
11781
+ const liveCardWatches = (0, import_react61.useMemo)(() => {
11717
11782
  const seen = /* @__PURE__ */ new Set();
11718
11783
  const out = [];
11719
11784
  for (const msg of controller.state.messages) {
@@ -11737,19 +11802,19 @@ function StatsWidget(props) {
11737
11802
  });
11738
11803
  const operatorUserId = cfg?.userContext?.operatorUserId;
11739
11804
  const anonymousUserId = cfg?.userContext?.anonymousUserId;
11740
- const getSchedule = (0, import_react60.useCallback)(
11805
+ const getSchedule = (0, import_react61.useCallback)(
11741
11806
  (localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) : Promise.resolve(null),
11742
11807
  [built, operatorUserId, anonymousUserId]
11743
11808
  );
11744
- const postLeagueStar = (0, import_react60.useCallback)(
11809
+ const postLeagueStar = (0, import_react61.useCallback)(
11745
11810
  (competitionId, starred) => built ? built.conversation.starLeague(competitionId, starred, operatorUserId, anonymousUserId) : Promise.resolve(null),
11746
11811
  [built, operatorUserId, anonymousUserId]
11747
11812
  );
11748
- const getStates = (0, import_react60.useCallback)(
11813
+ const getStates = (0, import_react61.useCallback)(
11749
11814
  (matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
11750
11815
  [built]
11751
11816
  );
11752
- const pinnedMatchIds = (0, import_react60.useMemo)(
11817
+ const pinnedMatchIds = (0, import_react61.useMemo)(
11753
11818
  () => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
11754
11819
  [monitor.pins]
11755
11820
  );
@@ -11764,11 +11829,11 @@ function StatsWidget(props) {
11764
11829
  pinnedMatchIds
11765
11830
  });
11766
11831
  const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
11767
- (0, import_react60.useEffect)(() => {
11832
+ (0, import_react61.useEffect)(() => {
11768
11833
  setHasToday(todayHasContent);
11769
11834
  }, [todayHasContent]);
11770
- const prevLiveSnapshotRef = (0, import_react60.useRef)(monitor.snapshot);
11771
- (0, import_react60.useEffect)(() => {
11835
+ const prevLiveSnapshotRef = (0, import_react61.useRef)(monitor.snapshot);
11836
+ (0, import_react61.useEffect)(() => {
11772
11837
  const snap = monitor.snapshot;
11773
11838
  if (!snap || snap === prevLiveSnapshotRef.current) return;
11774
11839
  prevLiveSnapshotRef.current = snap;
@@ -11804,14 +11869,14 @@ function StatsWidget(props) {
11804
11869
  }, [monitor.snapshot]);
11805
11870
  const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
11806
11871
  const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
11807
- const getPricePresets = (0, import_react60.useCallback)(
11872
+ const getPricePresets = (0, import_react61.useCallback)(
11808
11873
  (locale2) => built ? built.conversation.getPricePresets(locale2, { pool: "open" }) : Promise.resolve(null),
11809
11874
  [built]
11810
11875
  );
11811
11876
  const presetGrid = usePresetGrid({ getPricePresets, isOpen: controller.state.isOpen, locale: ui.presets.lang });
11812
11877
  const markTodayActivity = monitor.markTodayActivity;
11813
- const prevLiveCountRef = (0, import_react60.useRef)(0);
11814
- (0, import_react60.useEffect)(() => {
11878
+ const prevLiveCountRef = (0, import_react61.useRef)(0);
11879
+ (0, import_react61.useEffect)(() => {
11815
11880
  const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
11816
11881
  prevLiveCountRef.current = discovery.liveCount;
11817
11882
  if (rose) markTodayActivity();
@@ -11825,7 +11890,7 @@ function StatsWidget(props) {
11825
11890
  closePanel: controller.close
11826
11891
  });
11827
11892
  const markAdded = hostEvents.markAdded;
11828
- const slip = (0, import_react60.useMemo)(
11893
+ const slip = (0, import_react61.useMemo)(
11829
11894
  () => {
11830
11895
  const handler = props.config?.onAddToSlip;
11831
11896
  return {
@@ -11844,7 +11909,7 @@ function StatsWidget(props) {
11844
11909
  },
11845
11910
  [props.config?.onAddToSlip, controller.state.conversationId, markAdded]
11846
11911
  );
11847
- const onDashboardTap = (0, import_react60.useMemo)(
11912
+ const onDashboardTap = (0, import_react61.useMemo)(
11848
11913
  () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
11849
11914
  [built, logger]
11850
11915
  );
@@ -11861,11 +11926,11 @@ function StatsWidget(props) {
11861
11926
  })
11862
11927
  }));
11863
11928
  const conversationId = controller.state.conversationId ?? void 0;
11864
- (0, import_react60.useEffect)(() => {
11929
+ (0, import_react61.useEffect)(() => {
11865
11930
  if (!logger) return;
11866
11931
  logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
11867
11932
  }, [logger, operatorUserId, anonymousUserId, conversationId]);
11868
- (0, import_react60.useEffect)(() => {
11933
+ (0, import_react61.useEffect)(() => {
11869
11934
  if (!logger) return;
11870
11935
  logger.resume();
11871
11936
  const onHide = () => {
@@ -11883,7 +11948,7 @@ function StatsWidget(props) {
11883
11948
  logger.dispose();
11884
11949
  };
11885
11950
  }, [logger]);
11886
- (0, import_react60.useEffect)(() => {
11951
+ (0, import_react61.useEffect)(() => {
11887
11952
  if (!built || !ui.injectStyles) return;
11888
11953
  const node = rootRef.current?.getRootNode();
11889
11954
  if (node) injectStyles(node);