@sensiblestats/widget-react 0.66.0 → 0.67.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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/StatsWidget.tsx
2
- import { useCallback as useCallback12, useEffect as useEffect20, useMemo as useMemo4, useRef as useRef16, useState as useState41 } from "react";
2
+ import { useCallback as useCallback12, useEffect as useEffect21, useMemo as useMemo4, useRef as useRef17, useState as useState41 } from "react";
3
3
  import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
4
4
 
5
5
  // src/kickoff.ts
@@ -34,6 +34,7 @@ var STRINGS = {
34
34
  showMore: (n) => `Show ${n} more`,
35
35
  oddsLabel: "Odds",
36
36
  liveLabel: "Live",
37
+ yourMarketTag: "Your market",
37
38
  marketFloorLabel: "Market price \xB7 not a value pick",
38
39
  addToSlip: "Add to slip",
39
40
  marketPrices: "Market prices",
@@ -333,6 +334,7 @@ var STRINGS = {
333
334
  showMore: (n) => `${n} tane daha g\xF6ster`,
334
335
  oddsLabel: "Oran",
335
336
  liveLabel: "Canl\u0131",
337
+ yourMarketTag: "\u0130lgilendi\u011Fin bahis",
336
338
  marketFloorLabel: "Piyasa oran\u0131 \xB7 de\u011Fer bahsi de\u011Fil",
337
339
  addToSlip: "Kupona ekle",
338
340
  marketPrices: "Piyasa fiyatlar\u0131",
@@ -660,6 +662,7 @@ function normalizeUi(cfg) {
660
662
  showMore: strings.showMore,
661
663
  oddsLabel: strings.oddsLabel,
662
664
  liveLabel: strings.liveLabel,
665
+ yourMarketTag: strings.yourMarketTag,
663
666
  marketFloorLabel: strings.marketFloorLabel,
664
667
  marketPrices: strings.marketPrices,
665
668
  moreLines: strings.moreLines,
@@ -809,10 +812,10 @@ function resultToToast(result, shownOdds, ui) {
809
812
  }
810
813
 
811
814
  // src/useHostEvents.ts
812
- import { useCallback as useCallback5, useEffect as useEffect11, useMemo, useRef as useRef7, useState as useState34 } from "react";
815
+ import { useCallback as useCallback5, useEffect as useEffect12, useMemo, useRef as useRef8, useState as useState34 } from "react";
813
816
 
814
817
  // src/components/ChatPanel.tsx
815
- import { useEffect as useEffect10, useState as useState33 } from "react";
818
+ import { useEffect as useEffect11, useState as useState33 } from "react";
816
819
 
817
820
  // src/components/ChatHeader.tsx
818
821
  import { useEffect, useRef, useState as useState2 } from "react";
@@ -946,7 +949,7 @@ function ChatHeader({
946
949
  }
947
950
 
948
951
  // src/components/MessageList.tsx
949
- import { useEffect as useEffect5, useRef as useRef3 } from "react";
952
+ import { useEffect as useEffect6, useRef as useRef4 } from "react";
950
953
 
951
954
  // src/components/Markdown.tsx
952
955
  import ReactMarkdown from "react-markdown";
@@ -1295,7 +1298,8 @@ function toMarketOddsVM(card) {
1295
1298
  marketDeveloperName: str(card.marketDeveloperName),
1296
1299
  mainLine: str(card.mainLine),
1297
1300
  pinEnabled: card.pinEnabled === true,
1298
- statText: card.insight && typeof card.insight === "object" ? str(card.insight.text) : void 0
1301
+ statText: card.insight && typeof card.insight === "object" ? str(card.insight.text) : void 0,
1302
+ tag: card.tag === "your_market" ? "your_market" : void 0
1299
1303
  };
1300
1304
  }
1301
1305
  function toOddsMovementVM(card) {
@@ -1442,8 +1446,9 @@ function SlipButton({ selection, shownOdds, marketDeveloperName, selectionLabel,
1442
1446
  disabled: pending || settled,
1443
1447
  onClick,
1444
1448
  children: [
1449
+ settled ? /* @__PURE__ */ jsx7("span", { className: "ss-w-mol-tick", "aria-hidden": "true", children: "\u2713" }) : null,
1445
1450
  price.label ? /* @__PURE__ */ jsx7("span", { className: "ss-w-mol-lab", children: price.label }) : null,
1446
- shownOdds
1451
+ /* @__PURE__ */ jsx7("span", { children: shownOdds })
1447
1452
  ]
1448
1453
  }
1449
1454
  ) : /* @__PURE__ */ jsx7(
@@ -1910,10 +1915,13 @@ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }
1910
1915
  /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1911
1916
  /* @__PURE__ */ jsx14(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1912
1917
  ] }) : vm.fixture ? /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1913
- vm.market ? /* @__PURE__ */ jsx14("div", { className: "ss-w-mo-market-row", children: /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-market", children: vm.market }) }) : null
1918
+ vm.market ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-market-row", children: [
1919
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-market", children: vm.market }),
1920
+ vm.tag === "your_market" ? /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-tag", children: ui?.yourMarketTag ?? "Your market" }) : null
1921
+ ] }) : null
1914
1922
  ] }) : null
1915
1923
  ] }),
1916
- vm.statText && !hideHeader ? /* @__PURE__ */ jsx14("div", { className: "ss-w-mo-stat", children: vm.statText }) : null,
1924
+ vm.statText && !hideHeader && !pinRef ? /* @__PURE__ */ jsx14("div", { className: "ss-w-mo-stat", children: vm.statText }) : null,
1917
1925
  /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-rows", children: [
1918
1926
  vm.mainRows.map((row) => /* @__PURE__ */ jsx14(OddsRow, { vm, row, ui, slip, inSlipIds, history }, row.key)),
1919
1927
  open ? vm.moreRows.map((row) => /* @__PURE__ */ jsx14(OddsRow, { vm, row, ui, slip, inSlipIds, history }, row.key)) : null
@@ -1932,7 +1940,7 @@ function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds, hideHeader, p
1932
1940
  }
1933
1941
 
1934
1942
  // src/components/CompactOddsList.tsx
1935
- import { useState as useState9 } from "react";
1943
+ import { useEffect as useEffect3, useRef as useRef2, useState as useState9 } from "react";
1936
1944
 
1937
1945
  // src/compactList.ts
1938
1946
  var COMPACT_MIN_CARDS = 3;
@@ -1994,6 +2002,7 @@ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1994
2002
  function Cell({ row, cell, ui, slip }) {
1995
2003
  const vm = row.card;
1996
2004
  const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, cell.row, slip.conversationId) : null;
2005
+ const name = `${vm.homeTeamName ?? ""} ${vm.awayTeamName ?? ""}, ${cell.row.selection} ${cell.row.odds}`;
1997
2006
  const button = /* @__PURE__ */ jsx15(
1998
2007
  SlipButton,
1999
2008
  {
@@ -2004,7 +2013,7 @@ function Cell({ row, cell, ui, slip }) {
2004
2013
  line: cell.row.line,
2005
2014
  slip,
2006
2015
  ui,
2007
- price: { label: cell.label, ariaLabel: `${vm.homeTeamName ?? ""} ${vm.awayTeamName ?? ""}, ${cell.row.selection} ${cell.row.odds}` }
2016
+ price: { label: cell.label, ariaLabel: name }
2008
2017
  }
2009
2018
  );
2010
2019
  return (
@@ -2012,18 +2021,19 @@ function Cell({ row, cell, ui, slip }) {
2012
2021
  // and 101.00 two.
2013
2022
  /* @__PURE__ */ jsxs10("span", { className: ["ss-w-mol-cell", cell.row.odds.length >= 5 && "ss-w-mol-cell--wide", cell.row.odds.length >= 6 && "ss-w-mol-cell--wider"].filter(Boolean).join(" "), children: [
2014
2023
  selection && slip.onAddToSlip && ui ? button : /* @__PURE__ */ jsxs10("span", { className: "ss-w-mol-price", children: [
2015
- cell.label ? /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-lab", children: cell.label }) : null,
2016
- cell.row.odds
2024
+ cell.label ? /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-lab", "aria-hidden": "true", children: cell.label }) : null,
2025
+ /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: cell.row.odds }),
2026
+ /* @__PURE__ */ jsx15("span", { className: "ss-w-vh", children: name })
2017
2027
  ] }),
2018
2028
  /* @__PURE__ */ jsx15(OddsMovementBadge, { previous: cell.row.previousOdds, current: cell.row.odds, direction: cell.row.movementDirection, ui })
2019
2029
  ] })
2020
2030
  );
2021
2031
  }
2022
- function Row({ row, columns, ui, slip, monitor }) {
2032
+ function Row({ row, columns, ui, slip, monitor, rowRef }) {
2023
2033
  const vm = row.card;
2024
2034
  const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
2025
2035
  const when = vm.isLive ? ui?.liveLabel ?? "Live" : vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : void 0);
2026
- return /* @__PURE__ */ jsxs10("div", { className: "ss-w-mol-row", children: [
2036
+ return /* @__PURE__ */ jsxs10("div", { className: "ss-w-mol-row", ref: rowRef, tabIndex: rowRef ? -1 : void 0, children: [
2027
2037
  /* @__PURE__ */ jsxs10(MatchLink, { as: "div", matchId: vm.matchId, home: vm.homeTeamName, away: vm.awayTeamName, className: "ss-w-mol-fx", children: [
2028
2038
  /* @__PURE__ */ jsxs10("span", { className: "ss-w-mol-team", children: [
2029
2039
  /* @__PURE__ */ jsx15(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName ?? "" }),
@@ -2045,11 +2055,17 @@ function Row({ row, columns, ui, slip, monitor }) {
2045
2055
  function CompactOddsList({ list, ui, slip, monitor }) {
2046
2056
  const [shown, setShown] = useState9(COMPACT_PAGE);
2047
2057
  const hidden = list.rowCount - shown;
2058
+ const [focusIndex, setFocusIndex] = useState9(null);
2059
+ const focusRef = useRef2(null);
2060
+ useEffect3(() => {
2061
+ if (focusIndex !== null) focusRef.current?.focus();
2062
+ }, [focusIndex]);
2048
2063
  let left = shown;
2064
+ let index = 0;
2049
2065
  return /* @__PURE__ */ jsxs10("div", { className: "ss-w-mol", children: [
2050
2066
  /* @__PURE__ */ jsxs10("div", { className: "ss-w-mol-head", children: [
2051
2067
  /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-market", children: list.market }),
2052
- /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-cols", style: { gridTemplateColumns: `repeat(${list.columns.length}, minmax(0, 1fr))` }, children: list.columns.map((c, i) => /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-col", children: c }, `${c}:${i}`)) }),
2068
+ /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-cols", "aria-hidden": "true", style: { gridTemplateColumns: `repeat(${list.columns.length}, minmax(0, 1fr))` }, children: list.columns.map((c, i) => /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-col", children: c }, `${c}:${i}`)) }),
2053
2069
  /* @__PURE__ */ jsx15("span", { className: "ss-w-mol-side", "aria-hidden": "true" })
2054
2070
  ] }),
2055
2071
  list.groups.map((group, gi) => {
@@ -2061,10 +2077,16 @@ function CompactOddsList({ list, ui, slip, monitor }) {
2061
2077
  /* @__PURE__ */ jsx15(Crest2, { kind: "comp", url: group.competitionCrest, name: group.competition }),
2062
2078
  /* @__PURE__ */ jsx15("span", { children: group.competition })
2063
2079
  ] }) : null,
2064
- rows.map((row) => /* @__PURE__ */ jsx15(Row, { row, columns: list.columns.length, ui, slip, monitor }, row.card.id))
2080
+ rows.map((row) => {
2081
+ const at = index++;
2082
+ return /* @__PURE__ */ jsx15(Row, { row, columns: list.columns.length, ui, slip, monitor, rowRef: at === focusIndex ? focusRef : void 0 }, row.card.id);
2083
+ })
2065
2084
  ] }, `${group.competition ?? ""}:${gi}`);
2066
2085
  }),
2067
- hidden > 0 ? /* @__PURE__ */ jsxs10("button", { type: "button", className: "ss-w-mo-more", onClick: () => setShown((n) => n + COMPACT_PAGE), children: [
2086
+ hidden > 0 ? /* @__PURE__ */ jsxs10("button", { type: "button", className: "ss-w-mo-more", onClick: () => {
2087
+ setFocusIndex(shown);
2088
+ setShown((n) => n + COMPACT_PAGE);
2089
+ }, children: [
2068
2090
  /* @__PURE__ */ jsx15("span", { children: ui?.showMore ? ui.showMore(Math.min(COMPACT_PAGE, hidden)) : `Show ${Math.min(COMPACT_PAGE, hidden)} more` }),
2069
2091
  /* @__PURE__ */ jsx15("span", { className: "ss-w-mo-more-chev", "aria-hidden": "true" })
2070
2092
  ] }) : null,
@@ -2336,7 +2358,7 @@ function FixtureCard({ card }) {
2336
2358
  }
2337
2359
 
2338
2360
  // src/components/dashboard/CountdownCard.tsx
2339
- import { Fragment as Fragment6, useEffect as useEffect3, useState as useState10 } from "react";
2361
+ import { Fragment as Fragment6, useEffect as useEffect4, useState as useState10 } from "react";
2340
2362
  import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
2341
2363
  var DAY_MS = 864e5;
2342
2364
  function remainingSegments(kickoffUnix, nowMs, withSeconds) {
@@ -2360,7 +2382,7 @@ function CountdownCard({ card }) {
2360
2382
  () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
2361
2383
  );
2362
2384
  const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
2363
- useEffect3(() => {
2385
+ useEffect4(() => {
2364
2386
  if (reduced) return;
2365
2387
  const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
2366
2388
  return () => window.clearInterval(id);
@@ -2717,10 +2739,10 @@ function RestingFormCard({ card }) {
2717
2739
  }
2718
2740
 
2719
2741
  // src/components/dashboard/LiveScoreCard.tsx
2720
- import { useRef as useRef2, useState as useState14 } from "react";
2742
+ import { useRef as useRef3, useState as useState14 } from "react";
2721
2743
 
2722
2744
  // src/useLiveClock.ts
2723
- import { useEffect as useEffect4, useState as useState13 } from "react";
2745
+ import { useEffect as useEffect5, useState as useState13 } from "react";
2724
2746
  var TICK_MS = 6e4;
2725
2747
  var MAX_LIVE_TICK_MINUTES = 15;
2726
2748
  function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
@@ -2732,7 +2754,7 @@ function useLiveClock(minute, clockRunning, receivedAtMs) {
2732
2754
  const [displayMinute, setDisplayMinute] = useState13(
2733
2755
  () => computeDisplayMinute(minute, clockRunning, receivedAtMs)
2734
2756
  );
2735
- useEffect4(() => {
2757
+ useEffect5(() => {
2736
2758
  setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
2737
2759
  if (!clockRunning) return;
2738
2760
  const id = window.setInterval(() => {
@@ -2768,7 +2790,7 @@ function LiveScoreCard({
2768
2790
  }) {
2769
2791
  const { data } = card;
2770
2792
  const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
2771
- const seedRef = useRef2(null);
2793
+ const seedRef = useRef3(null);
2772
2794
  if (!seedRef.current || seedRef.current.key !== seedKey) {
2773
2795
  seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
2774
2796
  }
@@ -3091,11 +3113,11 @@ function turnAnchor(messages) {
3091
3113
  }
3092
3114
  function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
3093
3115
  const { state, send } = controller;
3094
- const listRef = useRef3(null);
3095
- const endRef = useRef3(null);
3096
- const pinnedRef = useRef3(true);
3097
- const anchoredTurnRef = useRef3(null);
3098
- useEffect5(() => {
3116
+ const listRef = useRef4(null);
3117
+ const endRef = useRef4(null);
3118
+ const pinnedRef = useRef4(true);
3119
+ const anchoredTurnRef = useRef4(null);
3120
+ useEffect6(() => {
3099
3121
  const anchor = turnAnchor(state.messages);
3100
3122
  const list = listRef.current;
3101
3123
  if (anchor && anchor.turnId !== anchoredTurnRef.current) {
@@ -3654,7 +3676,7 @@ function TodayPanel({ discovery, ui, monitor }) {
3654
3676
  }
3655
3677
 
3656
3678
  // src/components/GamesPanel.tsx
3657
- import { useEffect as useEffect9, useState as useState31 } from "react";
3679
+ import { useEffect as useEffect10, useState as useState31 } from "react";
3658
3680
 
3659
3681
  // src/components/GamesLoginWall.tsx
3660
3682
  import { jsx as jsx54 } from "react/jsx-runtime";
@@ -3663,7 +3685,7 @@ function GamesLoginWall({ ui }) {
3663
3685
  }
3664
3686
 
3665
3687
  // src/components/GamesHub.tsx
3666
- import { useEffect as useEffect6, useState as useState18 } from "react";
3688
+ import { useEffect as useEffect7, useState as useState18 } from "react";
3667
3689
 
3668
3690
  // src/components/games/ui/gameMeta.ts
3669
3691
  function prettifyGameId(gameId) {
@@ -3849,7 +3871,7 @@ function pickHeroGame(games) {
3849
3871
  var tileKey = (g) => `${g.gameId}-${g.gameDay}-${g.fixtureId}`;
3850
3872
  function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
3851
3873
  const [, setTick] = useState18(0);
3852
- useEffect6(() => {
3874
+ useEffect7(() => {
3853
3875
  const id = setInterval(() => setTick((t) => t + 1), 6e4);
3854
3876
  return () => clearInterval(id);
3855
3877
  }, []);
@@ -3909,10 +3931,10 @@ function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
3909
3931
  }
3910
3932
 
3911
3933
  // src/components/GameScreenHost.tsx
3912
- import { useEffect as useEffect8, useRef as useRef6, useState as useState30 } from "react";
3934
+ import { useEffect as useEffect9, useRef as useRef7, useState as useState30 } from "react";
3913
3935
 
3914
3936
  // src/useGamePlay.ts
3915
- import { useCallback as useCallback4, useRef as useRef4, useState as useState19 } from "react";
3937
+ import { useCallback as useCallback4, useRef as useRef5, useState as useState19 } from "react";
3916
3938
  function toSubmitResult(payload) {
3917
3939
  return {
3918
3940
  // 'pending' means the play is recorded but awaiting resolution (fixture games)
@@ -3927,12 +3949,12 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
3927
3949
  const [result, setResult] = useState19(null);
3928
3950
  const [submitting, setSubmitting] = useState19(false);
3929
3951
  const [rawStatus, setRawStatus] = useState19(null);
3930
- const inFlightRef = useRef4(false);
3931
- const convRef = useRef4(conversation);
3952
+ const inFlightRef = useRef5(false);
3953
+ const convRef = useRef5(conversation);
3932
3954
  convRef.current = conversation;
3933
- const optsRef = useRef4({ gameId, gameDay, fixtureId, locale, refresh });
3955
+ const optsRef = useRef5({ gameId, gameDay, fixtureId, locale, refresh });
3934
3956
  optsRef.current = { gameId, gameDay, fixtureId, locale, refresh };
3935
- const resultRef = useRef4(null);
3957
+ const resultRef = useRef5(null);
3936
3958
  resultRef.current = result;
3937
3959
  const refetch = useCallback4(async () => {
3938
3960
  const conv = convRef.current;
@@ -4862,7 +4884,7 @@ function CareerPathGame({
4862
4884
  }
4863
4885
 
4864
4886
  // src/components/games/BeatTheGridGame.tsx
4865
- import React, { useEffect as useEffect7, useId as useId4, useRef as useRef5, useState as useState24 } from "react";
4887
+ import React, { useEffect as useEffect8, useId as useId4, useRef as useRef6, useState as useState24 } from "react";
4866
4888
  import { Fragment as Fragment14, jsx as jsx73, jsxs as jsxs60 } from "react/jsx-runtime";
4867
4889
  function criterionIconKind(label, key) {
4868
4890
  const l = (key ?? label).toLowerCase();
@@ -4945,8 +4967,8 @@ function SearchSheet({
4945
4967
  const s = ui.games.beatTheGrid;
4946
4968
  const [query, setQuery] = useState24("");
4947
4969
  const inputId = useId4();
4948
- const inputRef = useRef5(null);
4949
- useEffect7(() => {
4970
+ const inputRef = useRef6(null);
4971
+ useEffect8(() => {
4950
4972
  inputRef.current?.focus();
4951
4973
  }, [row, col]);
4952
4974
  const filtered = playerPool.filter(
@@ -6248,7 +6270,7 @@ function GameScreenHost({
6248
6270
  }) {
6249
6271
  const { gameId, fixtureId, gameDay = "", lockAtUtc = null } = selected;
6250
6272
  const [configJson, setConfigJson] = useState30(null);
6251
- useEffect8(() => {
6273
+ useEffect9(() => {
6252
6274
  setConfigJson(null);
6253
6275
  if (!conversation) return;
6254
6276
  let cancelled = false;
@@ -6271,12 +6293,12 @@ function GameScreenHost({
6271
6293
  fixtureId: fixtureId || void 0,
6272
6294
  locale: ui.games.lang
6273
6295
  });
6274
- useEffect8(() => {
6296
+ useEffect9(() => {
6275
6297
  if (conversation) hydrate();
6276
6298
  }, [conversation, gameId]);
6277
- const hydrateRef = useRef6(hydrate);
6299
+ const hydrateRef = useRef7(hydrate);
6278
6300
  hydrateRef.current = hydrate;
6279
- useEffect8(() => {
6301
+ useEffect9(() => {
6280
6302
  if (!FIXTURE_GAME_IDS.has(gameId)) return;
6281
6303
  if (rawStatus !== "pending") return;
6282
6304
  const timerId = setInterval(() => {
@@ -6412,7 +6434,7 @@ function GamesPanel({
6412
6434
  refreshHub
6413
6435
  }) {
6414
6436
  const [selected, setSelected] = useState31(null);
6415
- useEffect9(() => {
6437
+ useEffect10(() => {
6416
6438
  ensureGamesFonts();
6417
6439
  }, []);
6418
6440
  if (!loggedIn) return /* @__PURE__ */ jsx82(GamesLoginWall, { ui });
@@ -6612,7 +6634,7 @@ import { jsx as jsx87, jsxs as jsxs71 } from "react/jsx-runtime";
6612
6634
  var FULLSCREEN_QUERY = "(max-width: 639px)";
6613
6635
  function useIsModal() {
6614
6636
  const [modal, setModal] = useState33(false);
6615
- useEffect10(() => {
6637
+ useEffect11(() => {
6616
6638
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
6617
6639
  const mql = window.matchMedia(FULLSCREEN_QUERY);
6618
6640
  const sync = () => setModal(mql.matches);
@@ -6625,7 +6647,7 @@ function useIsModal() {
6625
6647
  function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }) {
6626
6648
  const { state, close, stop, send, reset } = controller;
6627
6649
  const isModal = useIsModal();
6628
- useEffect10(() => {
6650
+ useEffect11(() => {
6629
6651
  const onKey = (e) => {
6630
6652
  if (e.key === "Escape") close();
6631
6653
  };
@@ -6640,7 +6662,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
6640
6662
  monitor?.setActiveTab("chat");
6641
6663
  send(text, { grounding });
6642
6664
  };
6643
- useEffect10(() => {
6665
+ useEffect11(() => {
6644
6666
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
6645
6667
  }, [monitor, state.isStreaming, state.messages.length]);
6646
6668
  return /* @__PURE__ */ jsxs71("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
@@ -6935,7 +6957,7 @@ function useHostEvents(opts) {
6935
6957
  () => hasHost ? createSlipLedger(`ss-w-slip:${operatorId}`) : null,
6936
6958
  [hasHost, operatorId]
6937
6959
  );
6938
- const currentUserRef = useRef7(currentUser);
6960
+ const currentUserRef = useRef8(currentUser);
6939
6961
  currentUserRef.current = currentUser;
6940
6962
  const recordAdd = useCallback5((add) => {
6941
6963
  ledger?.record({ id: add.selection.matchOddsId, market: add.market, ...add.pick, user: currentUserRef.current });
@@ -6950,7 +6972,7 @@ function useHostEvents(opts) {
6950
6972
  () => tracksViews ? createMatchViews(`ss-w-views:${operatorId}`, { user: currentUser }) : null,
6951
6973
  [tracksViews, operatorId, currentUser]
6952
6974
  );
6953
- const sinkRef = useRef7(() => {
6975
+ const sinkRef = useRef8(() => {
6954
6976
  });
6955
6977
  sinkRef.current = (command) => {
6956
6978
  if (command.kind === "matchOpened") {
@@ -6971,11 +6993,11 @@ function useHostEvents(opts) {
6971
6993
  logger?.log(toSlipEvent(name, entry));
6972
6994
  }
6973
6995
  };
6974
- useEffect11(() => {
6996
+ useEffect12(() => {
6975
6997
  if (!host) return;
6976
6998
  return attachHost(host, (command) => sinkRef.current(command));
6977
6999
  }, [host]);
6978
- useEffect11(() => {
7000
+ useEffect12(() => {
6979
7001
  if (!isOpen || !views) return;
6980
7002
  const held = views.markOpened();
6981
7003
  if (held.length === 0) return;
@@ -6984,7 +7006,7 @@ function useHostEvents(opts) {
6984
7006
  }
6985
7007
  void logger?.flushNow();
6986
7008
  }, [isOpen, views, logger]);
6987
- const openMatchRef = useRef7(() => {
7009
+ const openMatchRef = useRef8(() => {
6988
7010
  });
6989
7011
  openMatchRef.current = (matchId) => {
6990
7012
  if (views?.view(matchId) === "log") {
@@ -7066,7 +7088,7 @@ function themeAttrs(ui) {
7066
7088
  }
7067
7089
 
7068
7090
  // src/useChatStream.ts
7069
- import { useCallback as useCallback6, useEffect as useEffect13, useMemo as useMemo2, useReducer as useReducer2, useRef as useRef9 } from "react";
7091
+ import { useCallback as useCallback6, useEffect as useEffect14, useMemo as useMemo2, useReducer as useReducer2, useRef as useRef10 } from "react";
7070
7092
  import { WidgetSdkError as WidgetSdkError2 } from "@sensiblestats/widget-sdk";
7071
7093
 
7072
7094
  // src/reducer.ts
@@ -7190,7 +7212,7 @@ function reducer(state, action) {
7190
7212
  }
7191
7213
 
7192
7214
  // src/useLiveDashboardPoll.ts
7193
- import { useEffect as useEffect12, useReducer, useRef as useRef8 } from "react";
7215
+ import { useEffect as useEffect13, useReducer, useRef as useRef9 } from "react";
7194
7216
  var POLL_INTERVAL_MS = 6e4;
7195
7217
  var LEAD_MS = 12e4;
7196
7218
  var GIVE_UP_MS = 30 * 6e4;
@@ -7234,11 +7256,11 @@ function findEarliestWakeupMs(messages) {
7234
7256
  function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }) {
7235
7257
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
7236
7258
  const anchor = findAnchor(messages);
7237
- const anchorRef = useRef8(anchor);
7259
+ const anchorRef = useRef9(anchor);
7238
7260
  anchorRef.current = anchor;
7239
- const inFlightRef = useRef8(false);
7261
+ const inFlightRef = useRef9(false);
7240
7262
  const anchorKey = anchor ? `${anchor.messageId}:${anchor.kind}` : null;
7241
- useEffect12(() => {
7263
+ useEffect13(() => {
7242
7264
  if (!anchorKey || !anchorRef.current) return;
7243
7265
  const tick = async () => {
7244
7266
  if (inFlightRef.current) return;
@@ -7274,7 +7296,7 @@ function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }) {
7274
7296
  }, POLL_INTERVAL_MS);
7275
7297
  return () => window.clearInterval(id);
7276
7298
  }, [anchorKey, dispatch, getLiveDashboard]);
7277
- useEffect12(() => {
7299
+ useEffect13(() => {
7278
7300
  if (anchorKey !== null) return;
7279
7301
  const wakeAt = findEarliestWakeupMs(messages);
7280
7302
  if (wakeAt === null) return;
@@ -7349,14 +7371,14 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
7349
7371
  return { state: base, restored: false, stale: payload === "expired" || payload === "corrupt" };
7350
7372
  }, []);
7351
7373
  const [state, dispatch] = useReducer2(reducer, boot.state);
7352
- const idRef = useRef9(seedIdCounter(boot.state.messages));
7353
- const handleRef = useRef9(null);
7354
- const fallbackTimerRef = useRef9(null);
7355
- const stateRef = useRef9(state);
7374
+ const idRef = useRef10(seedIdCounter(boot.state.messages));
7375
+ const handleRef = useRef10(null);
7376
+ const fallbackTimerRef = useRef10(null);
7377
+ const stateRef = useRef10(state);
7356
7378
  stateRef.current = state;
7357
- const greetedRef = useRef9(boot.restored);
7358
- const hydratedRef = useRef9(false);
7359
- const restoreSeededRef = useRef9(false);
7379
+ const greetedRef = useRef10(boot.restored);
7380
+ const hydratedRef = useRef10(false);
7381
+ const restoreSeededRef = useRef10(false);
7360
7382
  if (!restoreSeededRef.current) {
7361
7383
  restoreSeededRef.current = true;
7362
7384
  if (boot.restored && boot.state.conversationId) conversation.conversationId = boot.state.conversationId;
@@ -7431,15 +7453,15 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
7431
7453
  dispatch({ kind: "STOP" });
7432
7454
  }
7433
7455
  }, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer]);
7434
- useEffect13(() => {
7456
+ useEffect14(() => {
7435
7457
  if (greetedRef.current) return;
7436
7458
  greetedRef.current = true;
7437
7459
  fireGreeting();
7438
7460
  }, [fireGreeting]);
7439
- useEffect13(() => {
7461
+ useEffect14(() => {
7440
7462
  if (boot.stale && storageKey) clearConversation(storageKey);
7441
7463
  }, []);
7442
- useEffect13(() => {
7464
+ useEffect14(() => {
7443
7465
  if (!storageKey || state.isStreaming) return;
7444
7466
  if (hydratedRef.current) {
7445
7467
  hydratedRef.current = false;
@@ -7456,7 +7478,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
7456
7478
  if (persistable.length === 0) return;
7457
7479
  writeConversation(storageKey, state.conversationId, persistable, Date.now());
7458
7480
  }, [storageKey, state.isStreaming, state.messages, state.conversationId]);
7459
- useEffect13(() => {
7481
+ useEffect14(() => {
7460
7482
  if (!storageKey) return;
7461
7483
  const onStorage = (e) => {
7462
7484
  if (e.key !== storageKey || e.storageArea !== window.localStorage) return;
@@ -7515,7 +7537,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
7515
7537
  }
7516
7538
 
7517
7539
  // src/useLiveMonitor.ts
7518
- import { useCallback as useCallback7, useEffect as useEffect14, useRef as useRef10, useState as useState36 } from "react";
7540
+ import { useCallback as useCallback7, useEffect as useEffect15, useRef as useRef11, useState as useState36 } from "react";
7519
7541
 
7520
7542
  // src/useTabs.ts
7521
7543
  import { useState as useState35 } from "react";
@@ -7544,7 +7566,7 @@ function phaseForPin(snapshot, pin) {
7544
7566
  return snapshot.markets.find((mk) => mk.key === pin.key)?.phase;
7545
7567
  }
7546
7568
  function useLiveMonitor(opts) {
7547
- const sessionIdRef = useRef10(crypto.randomUUID());
7569
+ const sessionIdRef = useRef11(crypto.randomUUID());
7548
7570
  const [pins, setPins] = useState36([]);
7549
7571
  const [store] = useState36(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins));
7550
7572
  const [enabled, setEnabled] = useState36(true);
@@ -7557,21 +7579,21 @@ function useLiveMonitor(opts) {
7557
7579
  const [lastViewedPrices, setLastViewedPrices] = useState36({});
7558
7580
  const [openMarket, setOpenMarket] = useState36({});
7559
7581
  const [marketOdds, setMarketOdds] = useState36({});
7560
- const pinsRef = useRef10(pins);
7582
+ const pinsRef = useRef11(pins);
7561
7583
  pinsRef.current = pins;
7562
- const activeTabRef = useRef10(activeTab);
7584
+ const activeTabRef = useRef11(activeTab);
7563
7585
  activeTabRef.current = activeTab;
7564
- const snapshotRef = useRef10(snapshot);
7586
+ const snapshotRef = useRef11(snapshot);
7565
7587
  snapshotRef.current = snapshot;
7566
- const lastViewedPricesRef = useRef10(lastViewedPrices);
7588
+ const lastViewedPricesRef = useRef11(lastViewedPrices);
7567
7589
  lastViewedPricesRef.current = lastViewedPrices;
7568
- const openMarketRef = useRef10(openMarket);
7590
+ const openMarketRef = useRef11(openMarket);
7569
7591
  openMarketRef.current = openMarket;
7570
- const marketOddsRef = useRef10(marketOdds);
7592
+ const marketOddsRef = useRef11(marketOdds);
7571
7593
  marketOddsRef.current = marketOdds;
7572
7594
  const hasToday = opts.hasToday ?? false;
7573
7595
  const marketKey = (matchId, dev) => `${matchId}:${dev}`;
7574
- const getMarketOddsRef = useRef10(opts.getMarketOdds);
7596
+ const getMarketOddsRef = useRef11(opts.getMarketOdds);
7575
7597
  getMarketOddsRef.current = opts.getMarketOdds;
7576
7598
  const fetchMarket = useCallback7((matchId, dev) => {
7577
7599
  const key = marketKey(matchId, dev);
@@ -7669,11 +7691,11 @@ function useLiveMonitor(opts) {
7669
7691
  snapshotRef.current = next;
7670
7692
  setSnapshotState(next);
7671
7693
  }, [store]);
7672
- const inFlightRef = useRef10(false);
7673
- const timerRef = useRef10(void 0);
7674
- const disabledRef = useRef10(false);
7675
- const mountedRef = useRef10(false);
7676
- const getLiveMonitorRef = useRef10(opts.getLiveMonitor);
7694
+ const inFlightRef = useRef11(false);
7695
+ const timerRef = useRef11(void 0);
7696
+ const disabledRef = useRef11(false);
7697
+ const mountedRef = useRef11(false);
7698
+ const getLiveMonitorRef = useRef11(opts.getLiveMonitor);
7677
7699
  getLiveMonitorRef.current = opts.getLiveMonitor;
7678
7700
  const tick = useCallback7(async () => {
7679
7701
  if (inFlightRef.current || disabledRef.current || pinsRef.current.length === 0) return;
@@ -7698,7 +7720,7 @@ function useLiveMonitor(opts) {
7698
7720
  scheduleRef.current();
7699
7721
  }
7700
7722
  }, [applySnapshot, fetchMarket]);
7701
- const scheduleRef = useRef10(() => {
7723
+ const scheduleRef = useRef11(() => {
7702
7724
  });
7703
7725
  scheduleRef.current = () => {
7704
7726
  window.clearTimeout(timerRef.current);
@@ -7706,14 +7728,14 @@ function useLiveMonitor(opts) {
7706
7728
  const hinted = (snapshotRef.current?.nextPollSeconds ?? DEFAULT_POLL_MS / 1e3) * 1e3;
7707
7729
  timerRef.current = window.setTimeout(() => void tick(), Math.max(MIN_POLL_MS, hinted));
7708
7730
  };
7709
- useEffect14(() => {
7731
+ useEffect15(() => {
7710
7732
  mountedRef.current = true;
7711
7733
  return () => {
7712
7734
  mountedRef.current = false;
7713
7735
  };
7714
7736
  }, []);
7715
- const prevPinsLengthRef = useRef10(0);
7716
- useEffect14(() => {
7737
+ const prevPinsLengthRef = useRef11(0);
7738
+ useEffect15(() => {
7717
7739
  const wasEmpty = prevPinsLengthRef.current === 0;
7718
7740
  prevPinsLengthRef.current = pins.length;
7719
7741
  if (pins.length === 0) {
@@ -7722,20 +7744,20 @@ function useLiveMonitor(opts) {
7722
7744
  }
7723
7745
  if (wasEmpty) void tick();
7724
7746
  }, [pins.length, tick]);
7725
- useEffect14(() => {
7747
+ useEffect15(() => {
7726
7748
  const matchPins = pins.filter((p) => p.kind === "match").length;
7727
7749
  const marketPins = pins.length - matchPins;
7728
7750
  if (activeTab === "following" && matchPins === 0) setActiveTabState(hasToday ? "today" : "chat");
7729
7751
  if (activeTab === "odds" && marketPins === 0) setActiveTabState(hasToday ? "today" : "chat");
7730
7752
  if (activeTab === "today" && !hasToday) setActiveTabState("chat");
7731
7753
  }, [pins, activeTab, hasToday]);
7732
- const prevIsOpenRef = useRef10(false);
7733
- useEffect14(() => {
7754
+ const prevIsOpenRef = useRef11(false);
7755
+ useEffect15(() => {
7734
7756
  const wasClosed = !prevIsOpenRef.current;
7735
7757
  prevIsOpenRef.current = opts.isOpen;
7736
7758
  if (wasClosed && opts.isOpen) void tick();
7737
7759
  }, [opts.isOpen, tick]);
7738
- useEffect14(() => {
7760
+ useEffect15(() => {
7739
7761
  const onVisibility = () => {
7740
7762
  if (document.visibilityState === "hidden") window.clearTimeout(timerRef.current);
7741
7763
  else void tick();
@@ -7801,7 +7823,7 @@ function useLiveMonitor(opts) {
7801
7823
  }
7802
7824
 
7803
7825
  // src/useMatchDiscovery.ts
7804
- import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo3, useRef as useRef11, useState as useState37 } from "react";
7826
+ import { useCallback as useCallback8, useEffect as useEffect16, useMemo as useMemo3, useRef as useRef12, useState as useState37 } from "react";
7805
7827
 
7806
7828
  // src/scheduleCache.ts
7807
7829
  var PREFIX = "ss-w-schedule:";
@@ -7894,22 +7916,22 @@ function useMatchDiscovery(opts) {
7894
7916
  const [failures, setFailures] = useState37(0);
7895
7917
  const [expanded, setExpanded] = useState37({});
7896
7918
  const [touched, setTouched] = useState37({});
7897
- const groupsRef = useRef11(groups);
7919
+ const groupsRef = useRef12(groups);
7898
7920
  groupsRef.current = groups;
7899
- const statesRef = useRef11(states);
7921
+ const statesRef = useRef12(states);
7900
7922
  statesRef.current = states;
7901
- const getStatesRef = useRef11(opts.getStates);
7923
+ const getStatesRef = useRef12(opts.getStates);
7902
7924
  getStatesRef.current = opts.getStates;
7903
7925
  const pinnedKey = opts.pinnedMatchIds.join(",");
7904
7926
  const [localDate, setLocalDate] = useState37(() => localDateOf(/* @__PURE__ */ new Date()));
7905
- useEffect15(() => {
7927
+ useEffect16(() => {
7906
7928
  const id = setInterval(() => {
7907
7929
  const next = localDateOf(/* @__PURE__ */ new Date());
7908
7930
  setLocalDate((prev) => prev === next ? prev : next);
7909
7931
  }, ROLLOVER_CHECK_MS);
7910
7932
  return () => clearInterval(id);
7911
7933
  }, []);
7912
- useEffect15(() => {
7934
+ useEffect16(() => {
7913
7935
  let cancelled = false;
7914
7936
  const utcOffsetMinutes = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
7915
7937
  const cached = readSchedule(opts.operatorId, localDate, Date.now());
@@ -7934,7 +7956,7 @@ function useMatchDiscovery(opts) {
7934
7956
  cancelled = true;
7935
7957
  };
7936
7958
  }, [opts.operatorId, localDate]);
7937
- useEffect15(() => {
7959
+ useEffect16(() => {
7938
7960
  setExpanded((prev) => {
7939
7961
  const next = {};
7940
7962
  for (const group of groups) {
@@ -7961,7 +7983,7 @@ function useMatchDiscovery(opts) {
7961
7983
  setFailures((n) => n + 1);
7962
7984
  }
7963
7985
  }, []);
7964
- useEffect15(() => {
7986
+ useEffect16(() => {
7965
7987
  if (!opts.isOpen) return;
7966
7988
  void tick();
7967
7989
  const id = setInterval(() => {
@@ -7982,7 +8004,7 @@ function useMatchDiscovery(opts) {
7982
8004
  }
7983
8005
 
7984
8006
  // src/useGames.ts
7985
- import { useCallback as useCallback9, useEffect as useEffect16, useRef as useRef12, useState as useState38 } from "react";
8007
+ import { useCallback as useCallback9, useEffect as useEffect17, useRef as useRef13, useState as useState38 } from "react";
7986
8008
  var GAMES_POLL_MS = 6e4;
7987
8009
  var DEFAULT_TZ = "Europe/London";
7988
8010
  function computeGameDay(timezone) {
@@ -7993,14 +8015,14 @@ function useGames(conversation, { activeTab, operatorTimezone }) {
7993
8015
  const [games, setGames] = useState38([]);
7994
8016
  const [loading, setLoading] = useState38(false);
7995
8017
  const [refreshCount, setRefreshCount] = useState38(0);
7996
- const inFlightRef = useRef12(false);
7997
- const hardOffRef = useRef12(false);
7998
- const conversationRef = useRef12(conversation);
8018
+ const inFlightRef = useRef13(false);
8019
+ const hardOffRef = useRef13(false);
8020
+ const conversationRef = useRef13(conversation);
7999
8021
  conversationRef.current = conversation;
8000
- const tzRef = useRef12(operatorTimezone ?? DEFAULT_TZ);
8022
+ const tzRef = useRef13(operatorTimezone ?? DEFAULT_TZ);
8001
8023
  tzRef.current = operatorTimezone ?? DEFAULT_TZ;
8002
8024
  const ready = conversation != null;
8003
- useEffect16(() => {
8025
+ useEffect17(() => {
8004
8026
  if (hardOffRef.current) return;
8005
8027
  let active = true;
8006
8028
  const doFetch = async () => {
@@ -8050,15 +8072,15 @@ function useGames(conversation, { activeTab, operatorTimezone }) {
8050
8072
  }
8051
8073
 
8052
8074
  // src/useLeaderboard.ts
8053
- import { useCallback as useCallback10, useEffect as useEffect17, useRef as useRef13, useState as useState39 } from "react";
8075
+ import { useCallback as useCallback10, useEffect as useEffect18, useRef as useRef14, useState as useState39 } from "react";
8054
8076
  function useLeaderboard(conversation, { activeTab }) {
8055
8077
  const [data, setData] = useState39(null);
8056
8078
  const [loading, setLoading] = useState39(false);
8057
8079
  const [refreshCount, setRefreshCount] = useState39(0);
8058
- const inFlightRef = useRef13(false);
8059
- const conversationRef = useRef13(conversation);
8080
+ const inFlightRef = useRef14(false);
8081
+ const conversationRef = useRef14(conversation);
8060
8082
  conversationRef.current = conversation;
8061
- useEffect17(() => {
8083
+ useEffect18(() => {
8062
8084
  if (activeTab !== "leaderboard" && activeTab !== "games") return;
8063
8085
  let active = true;
8064
8086
  const doFetch = async () => {
@@ -8088,11 +8110,11 @@ function useLeaderboard(conversation, { activeTab }) {
8088
8110
  }
8089
8111
 
8090
8112
  // src/popupTelemetry.ts
8091
- import { useCallback as useCallback11, useEffect as useEffect18, useRef as useRef14 } from "react";
8113
+ import { useCallback as useCallback11, useEffect as useEffect19, useRef as useRef15 } from "react";
8092
8114
  function usePopupTelemetry(log, isOpen, popupText, dismissPopup) {
8093
- const shownRef = useRef14(/* @__PURE__ */ new Set());
8094
- const closedTextRef = useRef14(null);
8095
- useEffect18(() => {
8115
+ const shownRef = useRef15(/* @__PURE__ */ new Set());
8116
+ const closedTextRef = useRef15(null);
8117
+ useEffect19(() => {
8096
8118
  if (isOpen) {
8097
8119
  if (closedTextRef.current) log?.log({ name: "popup_opened" });
8098
8120
  closedTextRef.current = null;
@@ -8111,7 +8133,7 @@ function usePopupTelemetry(log, isOpen, popupText, dismissPopup) {
8111
8133
  }
8112
8134
 
8113
8135
  // src/components/ChatFab.tsx
8114
- import { useEffect as useEffect19, useRef as useRef15, useState as useState40 } from "react";
8136
+ import { useEffect as useEffect20, useRef as useRef16, useState as useState40 } from "react";
8115
8137
 
8116
8138
  // src/components/GreetingBubble.tsx
8117
8139
  import { jsx as jsx88, jsxs as jsxs72 } from "react/jsx-runtime";
@@ -8134,8 +8156,8 @@ import { jsx as jsx89, jsxs as jsxs73 } from "react/jsx-runtime";
8134
8156
  function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = "Dismiss", introAllowed = false, onIntroStart }) {
8135
8157
  const bubble = popupText ?? greeting;
8136
8158
  const [intro, setIntro] = useState40(false);
8137
- const armedRef = useRef15(introAllowed);
8138
- useEffect19(() => {
8159
+ const armedRef = useRef16(introAllowed);
8160
+ useEffect20(() => {
8139
8161
  if (armedRef.current && bubble) {
8140
8162
  armedRef.current = false;
8141
8163
  setIntro(true);
@@ -8531,6 +8553,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
8531
8553
  .ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8532
8554
  .ss-w-mo-market-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
8533
8555
  .ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8556
+ .ss-w-mo-tag { flex: none; font-size: 10.5px; font-weight: 700; line-height: 1.4; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 12%, transparent); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }
8534
8557
  .ss-w-mo-more { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11.5px; font-weight: 600; padding: 2px 0; cursor: pointer; }
8535
8558
  .ss-w-mo-more:hover { text-decoration: underline; }
8536
8559
  .ss-w-mo-more-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }
@@ -8563,6 +8586,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
8563
8586
  .ss-w-mol-col { font-size: 10px; font-weight: 700; color: var(--ss-w-faint); text-align: center; overflow-wrap: break-word; min-width: 0; }
8564
8587
  .ss-w-mol-comp { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding-top: 4px; }
8565
8588
  .ss-w-mol-row { padding: 6px 0; border-bottom: 1px dashed var(--ss-w-line); min-height: 48px; box-sizing: border-box; }
8589
+ .ss-w-mol-row:focus { outline: none; }
8590
+ .ss-w-mol-row:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; border-radius: 6px; }
8591
+ .ss-w-mol-tick { font-family: inherit; font-size: 9.5px; font-weight: 700; line-height: 1.1; }
8592
+ .ss-w-vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
8566
8593
  .ss-w-mol-group .ss-w-mol-row:last-child { border-bottom: none; }
8567
8594
  .ss-w-mol-fx { display: flex; flex-direction: column; gap: 3px; min-width: 0; background: none; border: none; padding: 0; text-align: left; font: inherit; color: inherit; }
8568
8595
  .ss-w-mol-team { display: flex; align-items: center; gap: 5px; min-width: 0; }
@@ -9708,8 +9735,8 @@ function StatsWidget(props) {
9708
9735
  [built?.client]
9709
9736
  );
9710
9737
  const ui = useMemo4(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
9711
- const rootRef = useRef16(null);
9712
- const introDoneRef = useRef16(false);
9738
+ const rootRef = useRef17(null);
9739
+ const introDoneRef = useRef17(false);
9713
9740
  const markIntroDone = useCallback12(() => {
9714
9741
  introDoneRef.current = true;
9715
9742
  }, []);
@@ -9743,14 +9770,14 @@ function StatsWidget(props) {
9743
9770
  pinnedMatchIds
9744
9771
  });
9745
9772
  const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
9746
- useEffect20(() => {
9773
+ useEffect21(() => {
9747
9774
  setHasToday(todayHasContent);
9748
9775
  }, [todayHasContent]);
9749
9776
  const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
9750
9777
  const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
9751
9778
  const markTodayActivity = monitor.markTodayActivity;
9752
- const prevLiveCountRef = useRef16(0);
9753
- useEffect20(() => {
9779
+ const prevLiveCountRef = useRef17(0);
9780
+ useEffect21(() => {
9754
9781
  const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
9755
9782
  prevLiveCountRef.current = discovery.liveCount;
9756
9783
  if (rose) markTodayActivity();
@@ -9793,11 +9820,11 @@ function StatsWidget(props) {
9793
9820
  const operatorUserId = cfg?.userContext?.operatorUserId;
9794
9821
  const anonymousUserId = cfg?.userContext?.anonymousUserId;
9795
9822
  const conversationId = controller.state.conversationId ?? void 0;
9796
- useEffect20(() => {
9823
+ useEffect21(() => {
9797
9824
  if (!logger) return;
9798
9825
  logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
9799
9826
  }, [logger, operatorUserId, anonymousUserId, conversationId]);
9800
- useEffect20(() => {
9827
+ useEffect21(() => {
9801
9828
  if (!logger) return;
9802
9829
  logger.resume();
9803
9830
  const onHide = () => {
@@ -9815,7 +9842,7 @@ function StatsWidget(props) {
9815
9842
  logger.dispose();
9816
9843
  };
9817
9844
  }, [logger]);
9818
- useEffect20(() => {
9845
+ useEffect21(() => {
9819
9846
  if (!built || !ui.injectStyles) return;
9820
9847
  const node = rootRef.current?.getRootNode();
9821
9848
  if (node) injectStyles(node);