@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/StatsWidget.tsx
2
- import { useCallback as useCallback17, useEffect as useEffect29, useMemo as useMemo6, useRef as useRef24, useState as useState48 } from "react";
2
+ import { useCallback as useCallback18, useEffect as useEffect29, useMemo as useMemo6, useRef as useRef25, useState as useState48 } from "react";
3
3
  import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
4
4
 
5
5
  // src/kickoff.ts
@@ -120,6 +120,7 @@ var STRINGS = {
120
120
  allLeagues: "All leagues",
121
121
  searchLeaguesPlaceholder: "Search leagues or teams",
122
122
  noLeagueResults: "No league or team matches that search.",
123
+ clearSearchLabel: "Clear search",
123
124
  starOnLabel: "Add to Your leagues",
124
125
  starOffLabel: "Remove from Your leagues",
125
126
  starredToast: "Added to Your leagues.",
@@ -485,6 +486,7 @@ var STRINGS = {
485
486
  allLeagues: "T\xFCm ligler",
486
487
  searchLeaguesPlaceholder: "Lig veya tak\u0131m ara",
487
488
  noLeagueResults: "Aramana uyan lig veya tak\u0131m yok.",
489
+ clearSearchLabel: "Aramay\u0131 temizle",
488
490
  starOnLabel: "Liglerine ekle",
489
491
  starOffLabel: "Liglerinden \xE7\u0131kar",
490
492
  starredToast: "Liglerin b\xF6l\xFCm\xFCne eklendi.",
@@ -847,6 +849,7 @@ function normalizeUi(cfg) {
847
849
  allLeagues: strings.allLeagues,
848
850
  searchLeaguesPlaceholder: strings.searchLeaguesPlaceholder,
849
851
  noLeagueResults: strings.noLeagueResults,
852
+ clearSearchLabel: strings.clearSearchLabel,
850
853
  starOnLabel: strings.starOnLabel,
851
854
  starOffLabel: strings.starOffLabel,
852
855
  starredToast: strings.starredToast,
@@ -3411,7 +3414,7 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
3411
3414
  }
3412
3415
 
3413
3416
  // src/components/ChatPanel.tsx
3414
- import { useCallback as useCallback16, useEffect as useEffect28, useMemo as useMemo5, useRef as useRef23, useState as useState47 } from "react";
3417
+ import { useCallback as useCallback17, useEffect as useEffect28, useMemo as useMemo5, useRef as useRef24, useState as useState47 } from "react";
3415
3418
 
3416
3419
  // src/components/ChatHeader.tsx
3417
3420
  import { useEffect as useEffect12, useRef as useRef12, useState as useState10 } from "react";
@@ -3816,7 +3819,8 @@ function PinToggle({ pin, monitor, ui, market }) {
3816
3819
  const key = pinKey(pin);
3817
3820
  const pinned = monitor.isPinned(key);
3818
3821
  const labels = pin.kind === "match" ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel } : { pin: ui.pinLabel, unpin: ui.unpinLabel };
3819
- const onClick = () => {
3822
+ const onClick = (e) => {
3823
+ e.stopPropagation();
3820
3824
  if (pin.kind === "match" && !monitor.isPinned(key)) {
3821
3825
  if (monitor.pinMatch({ matchId: pin.matchId, marketDeveloperName: market }) === "added") {
3822
3826
  log?.log({ name: "pin_add", entityType: "match", entityId: String(pin.matchId), marketDeveloperName: pin.marketDeveloperName });
@@ -5962,15 +5966,25 @@ function starClickable(group, pinnedCompetitionId) {
5962
5966
  function foldSearchText(s) {
5963
5967
  return s.replace(/İ/g, "I").replace(/ı/g, "i").normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
5964
5968
  }
5969
+ function competitionMatchesQuery(group, q) {
5970
+ if (foldSearchText(group.competitionName).includes(q)) return true;
5971
+ return !!group.competitionCountry && foldSearchText(group.competitionCountry).includes(q);
5972
+ }
5965
5973
  function matchesQuery(group, query) {
5966
5974
  const q = foldSearchText(query.trim());
5967
5975
  if (!q) return true;
5968
- if (foldSearchText(group.competitionName).includes(q)) return true;
5969
- if (group.competitionCountry && foldSearchText(group.competitionCountry).includes(q)) return true;
5976
+ if (competitionMatchesQuery(group, q)) return true;
5970
5977
  return group.matches.some(
5971
5978
  (m) => foldSearchText(m.homeTeamName).includes(q) || foldSearchText(m.awayTeamName).includes(q)
5972
5979
  );
5973
5980
  }
5981
+ function matchingFixtures(group, query) {
5982
+ const q = foldSearchText(query.trim());
5983
+ if (!q || competitionMatchesQuery(group, q)) return group.matches;
5984
+ return group.matches.filter(
5985
+ (m) => foldSearchText(m.homeTeamName).includes(q) || foldSearchText(m.awayTeamName).includes(q)
5986
+ );
5987
+ }
5974
5988
 
5975
5989
  // src/useStarTap.ts
5976
5990
  import { useCallback as useCallback13, useRef as useRef17, useState as useState27 } from "react";
@@ -6148,6 +6162,9 @@ function LeagueDetail({ group, position, states, stale, ui, monitor, starTap, on
6148
6162
  ] });
6149
6163
  }
6150
6164
 
6165
+ // src/components/games/ui/SearchField.tsx
6166
+ import { useCallback as useCallback14, useRef as useRef18 } from "react";
6167
+
6151
6168
  // src/components/games/ui/icons.tsx
6152
6169
  import { jsx as jsx58 } from "react/jsx-runtime";
6153
6170
  var svg = (size, children, fill = false) => /* @__PURE__ */ jsx58(
@@ -6184,7 +6201,13 @@ var IconFlame = ({ size = 16 }) => svg(size, /* @__PURE__ */ jsx58("path", { d:
6184
6201
 
6185
6202
  // src/components/games/ui/SearchField.tsx
6186
6203
  import { jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
6187
- function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown }) {
6204
+ function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown, clearLabel }) {
6205
+ const localRef = useRef18(null);
6206
+ const setInputRef = useCallback14((node) => {
6207
+ localRef.current = node;
6208
+ if (typeof inputRef === "function") inputRef(node);
6209
+ else if (inputRef) inputRef.current = node;
6210
+ }, [inputRef]);
6188
6211
  return /* @__PURE__ */ jsxs53("div", { className: "ss-g-search", children: [
6189
6212
  /* @__PURE__ */ jsx59("label", { htmlFor: id, className: labelHidden ? "ss-g-sr" : "ss-g-search-label", children: label }),
6190
6213
  /* @__PURE__ */ jsxs53("div", { className: "ss-g-search-box", children: [
@@ -6193,7 +6216,7 @@ function SearchField({ id, label, labelHidden = false, placeholder, value, onCha
6193
6216
  "input",
6194
6217
  {
6195
6218
  id,
6196
- ref: inputRef,
6219
+ ref: setInputRef,
6197
6220
  type: "text",
6198
6221
  autoComplete: "off",
6199
6222
  placeholder,
@@ -6202,7 +6225,20 @@ function SearchField({ id, label, labelHidden = false, placeholder, value, onCha
6202
6225
  onKeyDown,
6203
6226
  onChange: (e) => onChange(e.target.value)
6204
6227
  }
6205
- )
6228
+ ),
6229
+ clearLabel && value.length > 0 ? /* @__PURE__ */ jsx59(
6230
+ "button",
6231
+ {
6232
+ type: "button",
6233
+ className: "ss-g-search-clear",
6234
+ "aria-label": clearLabel,
6235
+ onClick: () => {
6236
+ onChange("");
6237
+ localRef.current?.focus();
6238
+ },
6239
+ children: /* @__PURE__ */ jsx59(IconClose, { size: 11 })
6240
+ }
6241
+ ) : null
6206
6242
  ] })
6207
6243
  ] });
6208
6244
  }
@@ -6286,7 +6322,7 @@ function TodayPanel({ discovery, ui, monitor }) {
6286
6322
  ] }) });
6287
6323
  }
6288
6324
  const searching = query.trim().length > 0;
6289
- const searchResults = searching ? visibleGroups.filter((g) => matchesQuery(g, query)) : [];
6325
+ const searchResults = searching ? placement.order.filter((g) => matchesQuery(g, query)) : [];
6290
6326
  return /* @__PURE__ */ jsxs54("div", { className: "ss-w-today-root", children: [
6291
6327
  /* @__PURE__ */ jsxs54("div", { className: "ss-w-mon-list", children: [
6292
6328
  stale && /* @__PURE__ */ jsx60("div", { className: "ss-w-stale", children: ui.staleStates }),
@@ -6299,21 +6335,41 @@ function TodayPanel({ discovery, ui, monitor }) {
6299
6335
  labelHidden: true,
6300
6336
  placeholder: ui.searchLeaguesPlaceholder,
6301
6337
  value: query,
6302
- onChange: setQuery
6338
+ onChange: setQuery,
6339
+ clearLabel: ui.clearSearchLabel
6303
6340
  }
6304
6341
  ),
6305
- searching ? searchResults.length === 0 ? /* @__PURE__ */ jsx60("div", { className: "ss-w-today-empty", children: ui.noLeagueResults }) : /* @__PURE__ */ jsx60("div", { className: "ss-w-today-tiles", children: searchResults.map((group) => /* @__PURE__ */ jsx60(
6306
- LeagueTile,
6307
- {
6308
- group,
6309
- starClickable: starClickable(group, placement.pinnedCompetitionId),
6310
- disambiguate: (nameCounts[group.competitionName] ?? 0) > 1,
6311
- onOpen: () => setSelectedCompetitionId(group.competitionId),
6312
- starTap: gridStarTap,
6313
- ui
6314
- },
6315
- group.competitionId
6316
- )) }) : /* @__PURE__ */ jsxs54(Fragment7, { children: [
6342
+ searching ? searchResults.length === 0 ? /* @__PURE__ */ jsx60("div", { className: "ss-w-today-empty", children: ui.noLeagueResults }) : /* @__PURE__ */ jsx60(Fragment7, { children: searchResults.map((group) => /* @__PURE__ */ jsxs54("div", { className: "ss-w-today-search-block", children: [
6343
+ /* @__PURE__ */ jsxs54("div", { className: "ss-w-today-search-group", children: [
6344
+ /* @__PURE__ */ jsx60(Crest2, { url: group.competitionImagePath ?? void 0, name: group.competitionName, kind: "comp" }),
6345
+ /* @__PURE__ */ jsxs54("span", { className: "ss-w-today-search-group-name", children: [
6346
+ group.competitionName,
6347
+ (nameCounts[group.competitionName] ?? 0) > 1 && group.competitionCountry ? /* @__PURE__ */ jsxs54("span", { className: "ss-w-today-tile-country", children: [
6348
+ " (",
6349
+ group.competitionCountry,
6350
+ ")"
6351
+ ] }) : null
6352
+ ] })
6353
+ ] }),
6354
+ matchingFixtures(group, query).map((match) => /* @__PURE__ */ jsx60(
6355
+ "div",
6356
+ {
6357
+ role: "button",
6358
+ tabIndex: 0,
6359
+ className: "ss-w-today-search-row",
6360
+ onClick: () => setSelectedCompetitionId(group.competitionId),
6361
+ onKeyDown: (e) => {
6362
+ if (e.target !== e.currentTarget) return;
6363
+ if (e.key === "Enter" || e.key === " ") {
6364
+ e.preventDefault();
6365
+ setSelectedCompetitionId(group.competitionId);
6366
+ }
6367
+ },
6368
+ children: /* @__PURE__ */ jsx60(FixtureRow, { match, state: states[match.matchId], stale, ui, monitor })
6369
+ },
6370
+ match.matchId
6371
+ ))
6372
+ ] }, group.competitionId)) }) : /* @__PURE__ */ jsxs54(Fragment7, { children: [
6317
6373
  /* @__PURE__ */ jsxs54("div", { className: "ss-w-today-sec", children: [
6318
6374
  placement.personal ? ui.yourLeagues : ui.topLeagues,
6319
6375
  !placement.personal && /* @__PURE__ */ jsx60("span", { className: "ss-w-today-sec-sub", children: ui.topLeaguesSub })
@@ -6571,10 +6627,10 @@ function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
6571
6627
  }
6572
6628
 
6573
6629
  // src/components/GameScreenHost.tsx
6574
- import { useEffect as useEffect24, useRef as useRef20, useState as useState42 } from "react";
6630
+ import { useEffect as useEffect24, useRef as useRef21, useState as useState42 } from "react";
6575
6631
 
6576
6632
  // src/useGamePlay.ts
6577
- import { useCallback as useCallback14, useRef as useRef18, useState as useState31 } from "react";
6633
+ import { useCallback as useCallback15, useRef as useRef19, useState as useState31 } from "react";
6578
6634
  function toSubmitResult(payload) {
6579
6635
  return {
6580
6636
  // 'pending' means the play is recorded but awaiting resolution (fixture games)
@@ -6589,14 +6645,14 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
6589
6645
  const [result, setResult] = useState31(null);
6590
6646
  const [submitting, setSubmitting] = useState31(false);
6591
6647
  const [rawStatus, setRawStatus] = useState31(null);
6592
- const inFlightRef = useRef18(false);
6593
- const convRef = useRef18(conversation);
6648
+ const inFlightRef = useRef19(false);
6649
+ const convRef = useRef19(conversation);
6594
6650
  convRef.current = conversation;
6595
- const optsRef = useRef18({ gameId, gameDay, fixtureId, locale, refresh });
6651
+ const optsRef = useRef19({ gameId, gameDay, fixtureId, locale, refresh });
6596
6652
  optsRef.current = { gameId, gameDay, fixtureId, locale, refresh };
6597
- const resultRef = useRef18(null);
6653
+ const resultRef = useRef19(null);
6598
6654
  resultRef.current = result;
6599
- const refetch = useCallback14(async () => {
6655
+ const refetch = useCallback15(async () => {
6600
6656
  const conv = convRef.current;
6601
6657
  if (!conv) return;
6602
6658
  const opts = optsRef.current;
@@ -6612,7 +6668,7 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
6612
6668
  } catch {
6613
6669
  }
6614
6670
  }, []);
6615
- const submit = useCallback14(async (answerJson) => {
6671
+ const submit = useCallback15(async (answerJson) => {
6616
6672
  const conv = convRef.current;
6617
6673
  if (!conv || inFlightRef.current) return;
6618
6674
  inFlightRef.current = true;
@@ -6639,7 +6695,7 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
6639
6695
  setSubmitting(false);
6640
6696
  }
6641
6697
  }, [refetch]);
6642
- const hydrate = useCallback14(() => {
6698
+ const hydrate = useCallback15(() => {
6643
6699
  void refetch();
6644
6700
  }, [refetch]);
6645
6701
  return { result, submitting, submit, hydrate, rawStatus };
@@ -7523,7 +7579,7 @@ function CareerPathGame({
7523
7579
  }
7524
7580
 
7525
7581
  // src/components/games/BeatTheGridGame.tsx
7526
- import React, { useEffect as useEffect23, useId as useId5, useRef as useRef19, useState as useState36 } from "react";
7582
+ import React, { useEffect as useEffect23, useId as useId5, useRef as useRef20, useState as useState36 } from "react";
7527
7583
 
7528
7584
  // src/components/games/ui/OptionList.tsx
7529
7585
  import { jsx as jsx79 } from "react/jsx-runtime";
@@ -7614,7 +7670,7 @@ function SearchSheet({
7614
7670
  const s = ui.games.beatTheGrid;
7615
7671
  const [query, setQuery] = useState36("");
7616
7672
  const inputId = useId5();
7617
- const inputRef = useRef19(null);
7673
+ const inputRef = useRef20(null);
7618
7674
  useEffect23(() => {
7619
7675
  inputRef.current?.focus();
7620
7676
  }, [row, col]);
@@ -8945,7 +9001,7 @@ function GameScreenHost({
8945
9001
  useEffect24(() => {
8946
9002
  if (conversation) hydrate();
8947
9003
  }, [conversation, gameId]);
8948
- const hydrateRef = useRef20(hydrate);
9004
+ const hydrateRef = useRef21(hydrate);
8949
9005
  hydrateRef.current = hydrate;
8950
9006
  useEffect24(() => {
8951
9007
  if (!FIXTURE_GAME_IDS.has(gameId)) return;
@@ -9316,11 +9372,11 @@ function PresetSpeedDial({ expanded, showDot, strings, onToggle, onOpen, rootRef
9316
9372
  }
9317
9373
 
9318
9374
  // src/components/PresetTools.tsx
9319
- import { Fragment as Fragment21, useEffect as useEffect26, useId as useId11, useRef as useRef21, useState as useState45 } from "react";
9375
+ import { Fragment as Fragment21, useEffect as useEffect26, useId as useId11, useRef as useRef22, useState as useState45 } from "react";
9320
9376
  import { Fragment as Fragment22, jsx as jsx95, jsxs as jsxs80 } from "react/jsx-runtime";
9321
9377
  var FOCUSABLE = 'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
9322
9378
  function PresetToolModal({ title, closeLabel, onClose, children, footer }) {
9323
- const dialogRef = useRef21(null);
9379
+ const dialogRef = useRef22(null);
9324
9380
  const titleId = useId11();
9325
9381
  useEffect26(() => {
9326
9382
  dialogRef.current?.focus();
@@ -9609,7 +9665,7 @@ function BuildComboTool({ grid, strings, streaming, formatKickoff, initialTotal,
9609
9665
  }
9610
9666
 
9611
9667
  // src/usePresetDial.ts
9612
- import { useCallback as useCallback15, useEffect as useEffect27, useRef as useRef22, useState as useState46 } from "react";
9668
+ import { useCallback as useCallback16, useEffect as useEffect27, useRef as useRef23, useState as useState46 } from "react";
9613
9669
  function sendInFlight(messages, isStreaming) {
9614
9670
  const last = messages[messages.length - 1];
9615
9671
  return isStreaming && !!last && last.role === "assistant" && !last.done && !last.isGreeting;
@@ -9624,22 +9680,22 @@ function lastUserId(messages) {
9624
9680
  var SCROLL_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", " "]);
9625
9681
  function usePresetDial({ layerRef, dialRef, dialButtonRef, messages, isStreaming, activeTab }) {
9626
9682
  const [expanded, setExpanded] = useState46(() => !sendInFlight(messages, isStreaming));
9627
- const fold = useCallback15(() => setExpanded(false), []);
9628
- const toggle = useCallback15(() => setExpanded((e) => !e), []);
9683
+ const fold = useCallback16(() => setExpanded(false), []);
9684
+ const toggle = useCallback16(() => setExpanded((e) => !e), []);
9629
9685
  const currentUserId = lastUserId(messages);
9630
- const userIdRef = useRef22(currentUserId);
9686
+ const userIdRef = useRef23(currentUserId);
9631
9687
  useEffect27(() => {
9632
9688
  if (currentUserId === userIdRef.current) return;
9633
9689
  userIdRef.current = currentUserId;
9634
9690
  setExpanded(false);
9635
9691
  }, [currentUserId]);
9636
- const tabRef = useRef22(activeTab);
9692
+ const tabRef = useRef23(activeTab);
9637
9693
  useEffect27(() => {
9638
9694
  if (activeTab === tabRef.current) return;
9639
9695
  tabRef.current = activeTab;
9640
9696
  setExpanded(false);
9641
9697
  }, [activeTab]);
9642
- const expandedRef = useRef22(expanded);
9698
+ const expandedRef = useRef23(expanded);
9643
9699
  expandedRef.current = expanded;
9644
9700
  useEffect27(() => {
9645
9701
  const onEscape = (e) => {
@@ -9744,13 +9800,13 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
9744
9800
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
9745
9801
  }, [monitor, state.isStreaming, state.messages.length]);
9746
9802
  const onChatTab = !monitor || monitor.activeTab === "chat";
9747
- const layerRef = useRef23(null);
9748
- const dialRef = useRef23(null);
9749
- const dialButtonRef = useRef23(null);
9750
- const inputRef = useRef23(null);
9751
- const limitRef = useRef23(null);
9752
- const typedSendRef = useRef23(false);
9753
- const focusAfterCloseRef = useRef23(null);
9803
+ const layerRef = useRef24(null);
9804
+ const dialRef = useRef24(null);
9805
+ const dialButtonRef = useRef24(null);
9806
+ const inputRef = useRef24(null);
9807
+ const limitRef = useRef24(null);
9808
+ const typedSendRef = useRef24(false);
9809
+ const focusAfterCloseRef = useRef24(null);
9754
9810
  const [tool, setTool] = useState47(null);
9755
9811
  const [toolSeen, setToolSeen] = useState47(readToolSeen);
9756
9812
  const dial = usePresetDial({
@@ -9772,28 +9828,28 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
9772
9828
  if (typedSendRef.current) limitRef.current?.focus();
9773
9829
  typedSendRef.current = false;
9774
9830
  }, [paused]);
9775
- const openTool = useCallback16((next) => {
9831
+ const openTool = useCallback17((next) => {
9776
9832
  fold();
9777
9833
  markToolSeen();
9778
9834
  setToolSeen(true);
9779
9835
  setTool(next);
9780
9836
  }, [fold]);
9781
- const onPill = useCallback16((kind) => openTool(kind === "numbers" ? { kind: "numbers" } : { kind: "combo" }), [openTool]);
9837
+ const onPill = useCallback17((kind) => openTool(kind === "numbers" ? { kind: "numbers" } : { kind: "combo" }), [openTool]);
9782
9838
  const toolsValue = useMemo5(
9783
9839
  () => presetGrid && !paused ? { openBuilder: (total, legs) => openTool({ kind: "combo", total, legs }), changeLabel: ui.presets.changeCombo } : null,
9784
9840
  [presetGrid, paused, openTool, ui.presets.changeCombo]
9785
9841
  );
9786
- const closeTool = useCallback16(() => {
9842
+ const closeTool = useCallback17(() => {
9787
9843
  focusAfterCloseRef.current = "dial";
9788
9844
  setTool(null);
9789
9845
  }, []);
9790
- const sendAsk = useCallback16((ask) => {
9846
+ const sendAsk = useCallback17((ask) => {
9791
9847
  focusAfterCloseRef.current = "composer";
9792
9848
  setTool(null);
9793
9849
  monitor?.setActiveTab("chat");
9794
9850
  send(ask.message, { displayText: ask.displayText, preset: ask.preset });
9795
9851
  }, [monitor, send]);
9796
- const formatKickoff = useCallback16((kickoffUtc) => {
9852
+ const formatKickoff = useCallback17((kickoffUtc) => {
9797
9853
  const k = ui.bettingKickoff(kickoffUtc);
9798
9854
  return `${k.dayLabel} ${k.time}`;
9799
9855
  }, [ui]);
@@ -10023,6 +10079,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
10023
10079
  .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); }
10024
10080
  .ss-g-search-box:focus-within { border-color: var(--ss-w-accent); }
10025
10081
  .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); }
10082
+ .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; }
10083
+ .ss-g-search-clear:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }
10026
10084
  .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); }
10027
10085
  .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); }
10028
10086
  .ss-g-sil--selected { background: var(--ss-g-accent-tint); color: color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-g-raised)); }
@@ -11112,6 +11170,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
11112
11170
  .ss-w-today-sec-sub { text-transform: none; letter-spacing: normal; font-weight: 600; }
11113
11171
  .ss-w-today-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
11114
11172
  .ss-w-today-empty { font-size: 12px; color: var(--ss-w-faint); padding: 10px 2px; }
11173
+ .ss-w-today-search-block { display: flex; flex-direction: column; }
11174
+ .ss-w-today-search-group { display: flex; align-items: center; gap: 7px; padding: 2px 2px 6px; }
11175
+ .ss-w-today-search-group::after { content: ""; flex: 1; height: 1px; background: var(--ss-w-line); }
11176
+ .ss-w-today-search-group .ss-w-bi-comp-logo { width: 16px; height: 16px; }
11177
+ .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; }
11178
+ .ss-w-today-search-row { cursor: pointer; border-radius: 10px; }
11179
+ .ss-w-today-search-row:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }
11115
11180
 
11116
11181
  /* League tile (Task 5): a flat row (crest + name as the open target, star as a separate sibling
11117
11182
  button) rather than a disclosure header -- opening is Task 6's LeagueDetail, not an inline
@@ -11667,9 +11732,9 @@ function StatsWidget(props) {
11667
11732
  [built?.client]
11668
11733
  );
11669
11734
  const ui = useMemo6(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
11670
- const rootRef = useRef24(null);
11671
- const introDoneRef = useRef24(false);
11672
- const markIntroDone = useCallback17(() => {
11735
+ const rootRef = useRef25(null);
11736
+ const introDoneRef = useRef25(false);
11737
+ const markIntroDone = useCallback18(() => {
11673
11738
  introDoneRef.current = true;
11674
11739
  }, []);
11675
11740
  const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
@@ -11699,15 +11764,15 @@ function StatsWidget(props) {
11699
11764
  });
11700
11765
  const operatorUserId = cfg?.userContext?.operatorUserId;
11701
11766
  const anonymousUserId = cfg?.userContext?.anonymousUserId;
11702
- const getSchedule = useCallback17(
11767
+ const getSchedule = useCallback18(
11703
11768
  (localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) : Promise.resolve(null),
11704
11769
  [built, operatorUserId, anonymousUserId]
11705
11770
  );
11706
- const postLeagueStar = useCallback17(
11771
+ const postLeagueStar = useCallback18(
11707
11772
  (competitionId, starred) => built ? built.conversation.starLeague(competitionId, starred, operatorUserId, anonymousUserId) : Promise.resolve(null),
11708
11773
  [built, operatorUserId, anonymousUserId]
11709
11774
  );
11710
- const getStates = useCallback17(
11775
+ const getStates = useCallback18(
11711
11776
  (matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
11712
11777
  [built]
11713
11778
  );
@@ -11729,7 +11794,7 @@ function StatsWidget(props) {
11729
11794
  useEffect29(() => {
11730
11795
  setHasToday(todayHasContent);
11731
11796
  }, [todayHasContent]);
11732
- const prevLiveSnapshotRef = useRef24(monitor.snapshot);
11797
+ const prevLiveSnapshotRef = useRef25(monitor.snapshot);
11733
11798
  useEffect29(() => {
11734
11799
  const snap = monitor.snapshot;
11735
11800
  if (!snap || snap === prevLiveSnapshotRef.current) return;
@@ -11766,13 +11831,13 @@ function StatsWidget(props) {
11766
11831
  }, [monitor.snapshot]);
11767
11832
  const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
11768
11833
  const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
11769
- const getPricePresets = useCallback17(
11834
+ const getPricePresets = useCallback18(
11770
11835
  (locale2) => built ? built.conversation.getPricePresets(locale2, { pool: "open" }) : Promise.resolve(null),
11771
11836
  [built]
11772
11837
  );
11773
11838
  const presetGrid = usePresetGrid({ getPricePresets, isOpen: controller.state.isOpen, locale: ui.presets.lang });
11774
11839
  const markTodayActivity = monitor.markTodayActivity;
11775
- const prevLiveCountRef = useRef24(0);
11840
+ const prevLiveCountRef = useRef25(0);
11776
11841
  useEffect29(() => {
11777
11842
  const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
11778
11843
  prevLiveCountRef.current = discovery.liveCount;