@sensiblestats/widget-react 0.64.0 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/index.cjs +273 -351
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +113 -191
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -17
- package/package.json +2 -2
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
|
|
40
|
+
var import_react48 = require("react");
|
|
41
41
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
42
42
|
|
|
43
43
|
// src/kickoff.ts
|
|
@@ -70,8 +70,6 @@ var STRINGS = {
|
|
|
70
70
|
retry: "Retry",
|
|
71
71
|
showLess: "Show less",
|
|
72
72
|
showMore: (n) => `Show ${n} more`,
|
|
73
|
-
showStats: "Show stats",
|
|
74
|
-
hideStats: "Hide stats",
|
|
75
73
|
oddsLabel: "Odds",
|
|
76
74
|
liveLabel: "Live",
|
|
77
75
|
marketFloorLabel: "Market price \xB7 not a value pick",
|
|
@@ -132,7 +130,6 @@ var STRINGS = {
|
|
|
132
130
|
liveFactAsk: "Ask about this",
|
|
133
131
|
liveFactEarlier: (n) => `Earlier facts (${n})`,
|
|
134
132
|
liveFactHideEarlier: "Hide earlier facts",
|
|
135
|
-
accordionValueLabel: "Value",
|
|
136
133
|
accordionRetry: "Couldn't load odds \u2014 tap to retry",
|
|
137
134
|
accordionSuspended: "Suspended",
|
|
138
135
|
tabToday: "Today",
|
|
@@ -371,8 +368,6 @@ var STRINGS = {
|
|
|
371
368
|
retry: "Tekrar dene",
|
|
372
369
|
showLess: "Daha az g\xF6ster",
|
|
373
370
|
showMore: (n) => `${n} tane daha g\xF6ster`,
|
|
374
|
-
showStats: "\u0130statistikleri g\xF6ster",
|
|
375
|
-
hideStats: "\u0130statistikleri gizle",
|
|
376
371
|
oddsLabel: "Oran",
|
|
377
372
|
liveLabel: "Canl\u0131",
|
|
378
373
|
marketFloorLabel: "Piyasa oran\u0131 \xB7 de\u011Fer bahsi de\u011Fil",
|
|
@@ -433,7 +428,6 @@ var STRINGS = {
|
|
|
433
428
|
liveFactAsk: "Bunu sor",
|
|
434
429
|
liveFactEarlier: (n) => `\xD6nceki bilgiler (${n})`,
|
|
435
430
|
liveFactHideEarlier: "\xD6nceki bilgileri gizle",
|
|
436
|
-
accordionValueLabel: "De\u011Fer",
|
|
437
431
|
accordionRetry: "Oranlar y\xFCklenemedi \u2014 yeniden dene",
|
|
438
432
|
accordionSuspended: "Ask\u0131da",
|
|
439
433
|
tabToday: "Bug\xFCn",
|
|
@@ -700,8 +694,6 @@ function normalizeUi(cfg) {
|
|
|
700
694
|
retry: strings.retry,
|
|
701
695
|
showLess: strings.showLess,
|
|
702
696
|
showMore: strings.showMore,
|
|
703
|
-
showStats: strings.showStats,
|
|
704
|
-
hideStats: strings.hideStats,
|
|
705
697
|
oddsLabel: strings.oddsLabel,
|
|
706
698
|
liveLabel: strings.liveLabel,
|
|
707
699
|
marketFloorLabel: strings.marketFloorLabel,
|
|
@@ -762,7 +754,6 @@ function normalizeUi(cfg) {
|
|
|
762
754
|
liveFactAsk: strings.liveFactAsk,
|
|
763
755
|
liveFactEarlier: strings.liveFactEarlier,
|
|
764
756
|
liveFactHideEarlier: strings.liveFactHideEarlier,
|
|
765
|
-
accordionValueLabel: strings.accordionValueLabel,
|
|
766
757
|
accordionRetry: strings.accordionRetry,
|
|
767
758
|
accordionSuspended: strings.accordionSuspended,
|
|
768
759
|
tabGames: strings.tabGames,
|
|
@@ -853,10 +844,10 @@ function resultToToast(result, shownOdds, ui) {
|
|
|
853
844
|
}
|
|
854
845
|
|
|
855
846
|
// src/useHostEvents.ts
|
|
856
|
-
var
|
|
847
|
+
var import_react38 = require("react");
|
|
857
848
|
|
|
858
849
|
// src/components/ChatPanel.tsx
|
|
859
|
-
var
|
|
850
|
+
var import_react37 = require("react");
|
|
860
851
|
|
|
861
852
|
// src/components/ChatHeader.tsx
|
|
862
853
|
var import_react2 = require("react");
|
|
@@ -990,7 +981,7 @@ function ChatHeader({
|
|
|
990
981
|
}
|
|
991
982
|
|
|
992
983
|
// src/components/MessageList.tsx
|
|
993
|
-
var
|
|
984
|
+
var import_react19 = require("react");
|
|
994
985
|
|
|
995
986
|
// src/components/Markdown.tsx
|
|
996
987
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -1116,16 +1107,6 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
1116
1107
|
] });
|
|
1117
1108
|
}
|
|
1118
1109
|
|
|
1119
|
-
// src/components/BettingInsightList.tsx
|
|
1120
|
-
var import_react11 = require("react");
|
|
1121
|
-
|
|
1122
|
-
// src/eventLogContext.ts
|
|
1123
|
-
var import_react4 = require("react");
|
|
1124
|
-
var EventLogContext = (0, import_react4.createContext)(null);
|
|
1125
|
-
function useEventLog() {
|
|
1126
|
-
return (0, import_react4.useContext)(EventLogContext);
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
1110
|
// src/components/AddToSlipButton.tsx
|
|
1130
1111
|
var import_react7 = require("react");
|
|
1131
1112
|
var import_widget_sdk = require("@sensiblestats/widget-sdk");
|
|
@@ -1249,7 +1230,6 @@ function toInsightVM(insight) {
|
|
|
1249
1230
|
const away = str(insight.awayTeamName);
|
|
1250
1231
|
const fixture = home && away ? `${home} vs ${away}` : void 0;
|
|
1251
1232
|
const competition = str(insight.competitionName);
|
|
1252
|
-
const scopes = Array.isArray(insight.scopes) ? insight.scopes.map((s) => ({ key: str(s.key), label: str(s.label), stats: readStatCells(s.stats) })).filter((s) => !!s.key && !!s.label) : void 0;
|
|
1253
1233
|
const previousValue = insight.odds?.previousValue;
|
|
1254
1234
|
const previous = typeof previousValue === "number" && Number.isFinite(previousValue) ? previousValue : void 0;
|
|
1255
1235
|
const direction = insight.odds?.movementDirection === "shortened" || insight.odds?.movementDirection === "drifted" ? insight.odds.movementDirection : void 0;
|
|
@@ -1264,9 +1244,7 @@ function toInsightVM(insight) {
|
|
|
1264
1244
|
phase: str(insight.phase),
|
|
1265
1245
|
fixture,
|
|
1266
1246
|
competition,
|
|
1267
|
-
scopes,
|
|
1268
1247
|
text: str(insight.text) ?? "",
|
|
1269
|
-
stats: readStatCells(insight.stats),
|
|
1270
1248
|
disclaimer: str(insight.disclaimer),
|
|
1271
1249
|
matchId: typeof insight.matchId === "number" ? insight.matchId : 0,
|
|
1272
1250
|
matchOddsId,
|
|
@@ -1403,6 +1381,13 @@ function marketOddsRowToSlipSelection(vm, row, conversationId) {
|
|
|
1403
1381
|
return selection;
|
|
1404
1382
|
}
|
|
1405
1383
|
|
|
1384
|
+
// src/eventLogContext.ts
|
|
1385
|
+
var import_react4 = require("react");
|
|
1386
|
+
var EventLogContext = (0, import_react4.createContext)(null);
|
|
1387
|
+
function useEventLog() {
|
|
1388
|
+
return (0, import_react4.useContext)(EventLogContext);
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1406
1391
|
// src/slipStateContext.ts
|
|
1407
1392
|
var import_react5 = require("react");
|
|
1408
1393
|
var SlipStateContext = (0, import_react5.createContext)(null);
|
|
@@ -1764,55 +1749,11 @@ function MatchLink({ matchId, home, away, detail, className, as: Tag = "span", c
|
|
|
1764
1749
|
|
|
1765
1750
|
// src/components/BettingInsightList.tsx
|
|
1766
1751
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1767
|
-
function
|
|
1768
|
-
|
|
1769
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
1770
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
1771
|
-
] }, `${s.label}:${s.value}`)) });
|
|
1772
|
-
}
|
|
1773
|
-
function ScopedStats({ scopes }) {
|
|
1774
|
-
const [active, setActive] = (0, import_react11.useState)(0);
|
|
1775
|
-
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
1776
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-scoped", children: [
|
|
1777
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
1778
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(StatRows, { stats: current.stats }, current.key)
|
|
1779
|
-
] });
|
|
1780
|
-
}
|
|
1781
|
-
function hasStatsContent(it) {
|
|
1782
|
-
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
1783
|
-
}
|
|
1784
|
-
function ReasonStrip({ it, ui }) {
|
|
1785
|
-
const [open, setOpen] = (0, import_react11.useState)(false);
|
|
1786
|
-
const log = useEventLog();
|
|
1787
|
-
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
1788
|
-
const hasStats = hasStatsContent(it);
|
|
1789
|
-
const hasText = !!it.text;
|
|
1790
|
-
if (!hasText && !hasStats) return null;
|
|
1791
|
-
const expandable = hasStats || (it.text?.length ?? 0) > 90;
|
|
1792
|
-
const onToggle = () => {
|
|
1793
|
-
setOpen((v) => {
|
|
1794
|
-
const next = !v;
|
|
1795
|
-
if (next) log?.log({ name: "insight_expand", entityType: "match", entityId: String(it.matchId) });
|
|
1796
|
-
return next;
|
|
1797
|
-
});
|
|
1798
|
-
};
|
|
1752
|
+
function ReasonStrip({ it }) {
|
|
1753
|
+
if (!it.text) return null;
|
|
1799
1754
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-reason", children: [
|
|
1800
1755
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1801
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.
|
|
1802
|
-
hasText ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
|
|
1803
|
-
open && hasStats ? hasScopes ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(StatRows, { stats: it.stats }) : null
|
|
1804
|
-
] }),
|
|
1805
|
-
expandable ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1806
|
-
"button",
|
|
1807
|
-
{
|
|
1808
|
-
type: "button",
|
|
1809
|
-
className: "ss-w-bi-expand",
|
|
1810
|
-
"aria-expanded": open,
|
|
1811
|
-
"aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
|
|
1812
|
-
onClick: onToggle,
|
|
1813
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
|
|
1814
|
-
}
|
|
1815
|
-
) : null
|
|
1756
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "ss-w-bi-text", children: it.text })
|
|
1816
1757
|
] });
|
|
1817
1758
|
}
|
|
1818
1759
|
function CardFixture({ it }) {
|
|
@@ -1892,7 +1833,7 @@ function InsightCard({ it, ui, slip, monitor }) {
|
|
|
1892
1833
|
] })
|
|
1893
1834
|
] }),
|
|
1894
1835
|
it.isMarketFloor ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
|
|
1895
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ReasonStrip, { it
|
|
1836
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ReasonStrip, { it }),
|
|
1896
1837
|
it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
1897
1838
|
] });
|
|
1898
1839
|
}
|
|
@@ -1902,7 +1843,7 @@ function BettingInsightList({ insights, ui, slip, monitor }) {
|
|
|
1902
1843
|
}
|
|
1903
1844
|
|
|
1904
1845
|
// src/components/MarketOddsCardList.tsx
|
|
1905
|
-
var
|
|
1846
|
+
var import_react11 = require("react");
|
|
1906
1847
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1907
1848
|
function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
1908
1849
|
const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
|
|
@@ -1919,7 +1860,7 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
|
1919
1860
|
] });
|
|
1920
1861
|
}
|
|
1921
1862
|
function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }) {
|
|
1922
|
-
const [open, setOpen] = (0,
|
|
1863
|
+
const [open, setOpen] = (0, import_react11.useState)(false);
|
|
1923
1864
|
const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
|
|
1924
1865
|
const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : void 0);
|
|
1925
1866
|
const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
|
|
@@ -2252,7 +2193,7 @@ function FixtureCard({ card }) {
|
|
|
2252
2193
|
}
|
|
2253
2194
|
|
|
2254
2195
|
// src/components/dashboard/CountdownCard.tsx
|
|
2255
|
-
var
|
|
2196
|
+
var import_react12 = require("react");
|
|
2256
2197
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2257
2198
|
var DAY_MS = 864e5;
|
|
2258
2199
|
function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
@@ -2271,12 +2212,12 @@ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
|
2271
2212
|
function CountdownCard({ card }) {
|
|
2272
2213
|
const { data } = card;
|
|
2273
2214
|
const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
|
|
2274
|
-
const [nowMs, setNowMs] = (0,
|
|
2275
|
-
const [reduced] = (0,
|
|
2215
|
+
const [nowMs, setNowMs] = (0, import_react12.useState)(() => Date.now());
|
|
2216
|
+
const [reduced] = (0, import_react12.useState)(
|
|
2276
2217
|
() => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
2277
2218
|
);
|
|
2278
2219
|
const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
|
|
2279
|
-
(0,
|
|
2220
|
+
(0, import_react12.useEffect)(() => {
|
|
2280
2221
|
if (reduced) return;
|
|
2281
2222
|
const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
|
|
2282
2223
|
return () => window.clearInterval(id);
|
|
@@ -2284,7 +2225,7 @@ function CountdownCard({ card }) {
|
|
|
2284
2225
|
const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced);
|
|
2285
2226
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-fandash-card ss-w-fandash-countdown", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-countdown-top", children: [
|
|
2286
2227
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title ?? "Kick-off in" }),
|
|
2287
|
-
segments ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-countdown-clock", children: segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2228
|
+
segments ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-countdown-clock", children: segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react12.Fragment, { children: [
|
|
2288
2229
|
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-countdown-colon", children: ":" }) : null,
|
|
2289
2230
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-fandash-countdown-seg", children: [
|
|
2290
2231
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-countdown-value", children: s.value }),
|
|
@@ -2295,7 +2236,7 @@ function CountdownCard({ card }) {
|
|
|
2295
2236
|
}
|
|
2296
2237
|
|
|
2297
2238
|
// src/components/dashboard/InjuriesCard.tsx
|
|
2298
|
-
var
|
|
2239
|
+
var import_react13 = require("react");
|
|
2299
2240
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2300
2241
|
var SHOWN = 3;
|
|
2301
2242
|
function ColHead({ name, crestUrl }) {
|
|
@@ -2318,7 +2259,7 @@ function InjuryList({ rows, emptyLabel, limit }) {
|
|
|
2318
2259
|
}
|
|
2319
2260
|
function InjuriesCard({ card, ui }) {
|
|
2320
2261
|
const { data } = card;
|
|
2321
|
-
const [expanded, setExpanded] = (0,
|
|
2262
|
+
const [expanded, setExpanded] = (0, import_react13.useState)(false);
|
|
2322
2263
|
const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
|
|
2323
2264
|
const limit = expanded ? void 0 : SHOWN;
|
|
2324
2265
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
@@ -2424,7 +2365,7 @@ function LinksCard({ card }) {
|
|
|
2424
2365
|
}
|
|
2425
2366
|
|
|
2426
2367
|
// src/components/dashboard/PostMatchResultCard.tsx
|
|
2427
|
-
var
|
|
2368
|
+
var import_react14 = require("react");
|
|
2428
2369
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2429
2370
|
function initials3(name) {
|
|
2430
2371
|
return name.trim().slice(0, 3).toUpperCase();
|
|
@@ -2434,7 +2375,7 @@ function PostMatchCrest({
|
|
|
2434
2375
|
name,
|
|
2435
2376
|
side
|
|
2436
2377
|
}) {
|
|
2437
|
-
const [failed, setFailed] = (0,
|
|
2378
|
+
const [failed, setFailed] = (0, import_react14.useState)(false);
|
|
2438
2379
|
const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
|
|
2439
2380
|
if (url && !failed) {
|
|
2440
2381
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
@@ -2633,10 +2574,10 @@ function RestingFormCard({ card }) {
|
|
|
2633
2574
|
}
|
|
2634
2575
|
|
|
2635
2576
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
2636
|
-
var
|
|
2577
|
+
var import_react16 = require("react");
|
|
2637
2578
|
|
|
2638
2579
|
// src/useLiveClock.ts
|
|
2639
|
-
var
|
|
2580
|
+
var import_react15 = require("react");
|
|
2640
2581
|
var TICK_MS = 6e4;
|
|
2641
2582
|
var MAX_LIVE_TICK_MINUTES = 15;
|
|
2642
2583
|
function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
@@ -2645,10 +2586,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
|
2645
2586
|
return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
|
|
2646
2587
|
}
|
|
2647
2588
|
function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
2648
|
-
const [displayMinute, setDisplayMinute] = (0,
|
|
2589
|
+
const [displayMinute, setDisplayMinute] = (0, import_react15.useState)(
|
|
2649
2590
|
() => computeDisplayMinute(minute, clockRunning, receivedAtMs)
|
|
2650
2591
|
);
|
|
2651
|
-
(0,
|
|
2592
|
+
(0, import_react15.useEffect)(() => {
|
|
2652
2593
|
setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
|
|
2653
2594
|
if (!clockRunning) return;
|
|
2654
2595
|
const id = window.setInterval(() => {
|
|
@@ -2665,7 +2606,7 @@ function initials5(name) {
|
|
|
2665
2606
|
return name.trim().slice(0, 3).toUpperCase();
|
|
2666
2607
|
}
|
|
2667
2608
|
function LiveCrest({ url, name, side }) {
|
|
2668
|
-
const [failed, setFailed] = (0,
|
|
2609
|
+
const [failed, setFailed] = (0, import_react16.useState)(false);
|
|
2669
2610
|
const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
|
|
2670
2611
|
if (url && !failed) {
|
|
2671
2612
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
@@ -2684,7 +2625,7 @@ function LiveScoreCard({
|
|
|
2684
2625
|
}) {
|
|
2685
2626
|
const { data } = card;
|
|
2686
2627
|
const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
|
|
2687
|
-
const seedRef = (0,
|
|
2628
|
+
const seedRef = (0, import_react16.useRef)(null);
|
|
2688
2629
|
if (!seedRef.current || seedRef.current.key !== seedKey) {
|
|
2689
2630
|
seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
|
|
2690
2631
|
}
|
|
@@ -2724,7 +2665,7 @@ function LiveScoreCard({
|
|
|
2724
2665
|
}
|
|
2725
2666
|
|
|
2726
2667
|
// src/components/dashboard/LiveTimelineCard.tsx
|
|
2727
|
-
var
|
|
2668
|
+
var import_react17 = require("react");
|
|
2728
2669
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2729
2670
|
var SHOWN2 = 3;
|
|
2730
2671
|
function EventIcon({ type }) {
|
|
@@ -2766,7 +2707,7 @@ function EventRow({ e }) {
|
|
|
2766
2707
|
] });
|
|
2767
2708
|
}
|
|
2768
2709
|
function LiveTimelineCard({ card, ui }) {
|
|
2769
|
-
const [expanded, setExpanded] = (0,
|
|
2710
|
+
const [expanded, setExpanded] = (0, import_react17.useState)(false);
|
|
2770
2711
|
const events = card.data.events;
|
|
2771
2712
|
if (!events || events.length === 0) return null;
|
|
2772
2713
|
const sorted = [...events].sort((a, b) => b.minute - a.minute);
|
|
@@ -2791,7 +2732,7 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
2791
2732
|
}
|
|
2792
2733
|
|
|
2793
2734
|
// src/components/dashboard/MomentumWave.tsx
|
|
2794
|
-
var
|
|
2735
|
+
var import_react18 = require("react");
|
|
2795
2736
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2796
2737
|
var WIDTH = 270;
|
|
2797
2738
|
var HEIGHT = 56;
|
|
@@ -2815,7 +2756,7 @@ function MomentumWave({
|
|
|
2815
2756
|
}) {
|
|
2816
2757
|
if (points.length === 0) return null;
|
|
2817
2758
|
const { area, line, lastLeftPct, lastTopPx } = buildPaths(points);
|
|
2818
|
-
const clipId = (0,
|
|
2759
|
+
const clipId = (0, import_react18.useId)();
|
|
2819
2760
|
const topClipId = `${clipId}-top`;
|
|
2820
2761
|
const bottomClipId = `${clipId}-bottom`;
|
|
2821
2762
|
const topClass = clubIsHome ? "ss-w-fandash-live-mom-home" : "ss-w-fandash-live-mom-away";
|
|
@@ -3006,11 +2947,11 @@ function turnAnchor(messages) {
|
|
|
3006
2947
|
}
|
|
3007
2948
|
function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
3008
2949
|
const { state, send } = controller;
|
|
3009
|
-
const listRef = (0,
|
|
3010
|
-
const endRef = (0,
|
|
3011
|
-
const pinnedRef = (0,
|
|
3012
|
-
const anchoredTurnRef = (0,
|
|
3013
|
-
(0,
|
|
2950
|
+
const listRef = (0, import_react19.useRef)(null);
|
|
2951
|
+
const endRef = (0, import_react19.useRef)(null);
|
|
2952
|
+
const pinnedRef = (0, import_react19.useRef)(true);
|
|
2953
|
+
const anchoredTurnRef = (0, import_react19.useRef)(null);
|
|
2954
|
+
(0, import_react19.useEffect)(() => {
|
|
3014
2955
|
const anchor = turnAnchor(state.messages);
|
|
3015
2956
|
const list = listRef.current;
|
|
3016
2957
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
@@ -3066,10 +3007,10 @@ function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
3066
3007
|
}
|
|
3067
3008
|
|
|
3068
3009
|
// src/components/ChatInput.tsx
|
|
3069
|
-
var
|
|
3010
|
+
var import_react20 = require("react");
|
|
3070
3011
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3071
3012
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
3072
|
-
const [value, setValue] = (0,
|
|
3013
|
+
const [value, setValue] = (0, import_react20.useState)("");
|
|
3073
3014
|
const submit = () => {
|
|
3074
3015
|
const t = value.trim();
|
|
3075
3016
|
if (!t) return;
|
|
@@ -3171,11 +3112,7 @@ function MarketAccordion({ match, monitor, ui, slip }) {
|
|
|
3171
3112
|
children: ui.accordionRetry
|
|
3172
3113
|
}
|
|
3173
3114
|
),
|
|
3174
|
-
entry?.block?.insight?.text && /* @__PURE__ */ (0, import_jsx_runtime45.
|
|
3175
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "ss-w-acc-badge", children: ui.accordionValueLabel }),
|
|
3176
|
-
" ",
|
|
3177
|
-
entry.block.insight.text
|
|
3178
|
-
] }),
|
|
3115
|
+
entry?.block?.insight?.text && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "ss-w-acc-insight", children: entry.block.insight.text }),
|
|
3179
3116
|
entry?.block?.card && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3180
3117
|
MarketOddsCardList,
|
|
3181
3118
|
{
|
|
@@ -3193,10 +3130,10 @@ function MarketAccordion({ match, monitor, ui, slip }) {
|
|
|
3193
3130
|
}
|
|
3194
3131
|
|
|
3195
3132
|
// src/components/LiveFactBlock.tsx
|
|
3196
|
-
var
|
|
3133
|
+
var import_react21 = require("react");
|
|
3197
3134
|
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3198
3135
|
function LiveFactBlock({ facts, matchId, ui, slip, onAsk }) {
|
|
3199
|
-
const [expanded, setExpanded] = (0,
|
|
3136
|
+
const [expanded, setExpanded] = (0, import_react21.useState)(false);
|
|
3200
3137
|
const [current, ...earlier] = facts;
|
|
3201
3138
|
if (!current) return null;
|
|
3202
3139
|
const m = current.market;
|
|
@@ -3583,7 +3520,7 @@ function TodayPanel({ discovery, ui, monitor }) {
|
|
|
3583
3520
|
}
|
|
3584
3521
|
|
|
3585
3522
|
// src/components/GamesPanel.tsx
|
|
3586
|
-
var
|
|
3523
|
+
var import_react35 = require("react");
|
|
3587
3524
|
|
|
3588
3525
|
// src/components/GamesLoginWall.tsx
|
|
3589
3526
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
@@ -3592,7 +3529,7 @@ function GamesLoginWall({ ui }) {
|
|
|
3592
3529
|
}
|
|
3593
3530
|
|
|
3594
3531
|
// src/components/GamesHub.tsx
|
|
3595
|
-
var
|
|
3532
|
+
var import_react22 = require("react");
|
|
3596
3533
|
|
|
3597
3534
|
// src/components/games/ui/gameMeta.ts
|
|
3598
3535
|
function prettifyGameId(gameId) {
|
|
@@ -3777,8 +3714,8 @@ function pickHeroGame(games) {
|
|
|
3777
3714
|
}
|
|
3778
3715
|
var tileKey = (g) => `${g.gameId}-${g.gameDay}-${g.fixtureId}`;
|
|
3779
3716
|
function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
|
|
3780
|
-
const [, setTick] = (0,
|
|
3781
|
-
(0,
|
|
3717
|
+
const [, setTick] = (0, import_react22.useState)(0);
|
|
3718
|
+
(0, import_react22.useEffect)(() => {
|
|
3782
3719
|
const id = setInterval(() => setTick((t) => t + 1), 6e4);
|
|
3783
3720
|
return () => clearInterval(id);
|
|
3784
3721
|
}, []);
|
|
@@ -3838,10 +3775,10 @@ function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }) {
|
|
|
3838
3775
|
}
|
|
3839
3776
|
|
|
3840
3777
|
// src/components/GameScreenHost.tsx
|
|
3841
|
-
var
|
|
3778
|
+
var import_react34 = require("react");
|
|
3842
3779
|
|
|
3843
3780
|
// src/useGamePlay.ts
|
|
3844
|
-
var
|
|
3781
|
+
var import_react23 = require("react");
|
|
3845
3782
|
function toSubmitResult(payload) {
|
|
3846
3783
|
return {
|
|
3847
3784
|
// 'pending' means the play is recorded but awaiting resolution (fixture games)
|
|
@@ -3853,17 +3790,17 @@ function toSubmitResult(payload) {
|
|
|
3853
3790
|
};
|
|
3854
3791
|
}
|
|
3855
3792
|
function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh }) {
|
|
3856
|
-
const [result, setResult] = (0,
|
|
3857
|
-
const [submitting, setSubmitting] = (0,
|
|
3858
|
-
const [rawStatus, setRawStatus] = (0,
|
|
3859
|
-
const inFlightRef = (0,
|
|
3860
|
-
const convRef = (0,
|
|
3793
|
+
const [result, setResult] = (0, import_react23.useState)(null);
|
|
3794
|
+
const [submitting, setSubmitting] = (0, import_react23.useState)(false);
|
|
3795
|
+
const [rawStatus, setRawStatus] = (0, import_react23.useState)(null);
|
|
3796
|
+
const inFlightRef = (0, import_react23.useRef)(false);
|
|
3797
|
+
const convRef = (0, import_react23.useRef)(conversation);
|
|
3861
3798
|
convRef.current = conversation;
|
|
3862
|
-
const optsRef = (0,
|
|
3799
|
+
const optsRef = (0, import_react23.useRef)({ gameId, gameDay, fixtureId, locale, refresh });
|
|
3863
3800
|
optsRef.current = { gameId, gameDay, fixtureId, locale, refresh };
|
|
3864
|
-
const resultRef = (0,
|
|
3801
|
+
const resultRef = (0, import_react23.useRef)(null);
|
|
3865
3802
|
resultRef.current = result;
|
|
3866
|
-
const refetch = (0,
|
|
3803
|
+
const refetch = (0, import_react23.useCallback)(async () => {
|
|
3867
3804
|
const conv = convRef.current;
|
|
3868
3805
|
if (!conv) return;
|
|
3869
3806
|
const opts = optsRef.current;
|
|
@@ -3879,7 +3816,7 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
|
|
|
3879
3816
|
} catch {
|
|
3880
3817
|
}
|
|
3881
3818
|
}, []);
|
|
3882
|
-
const submit = (0,
|
|
3819
|
+
const submit = (0, import_react23.useCallback)(async (answerJson) => {
|
|
3883
3820
|
const conv = convRef.current;
|
|
3884
3821
|
if (!conv || inFlightRef.current) return;
|
|
3885
3822
|
inFlightRef.current = true;
|
|
@@ -3906,14 +3843,14 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, locale, refresh
|
|
|
3906
3843
|
setSubmitting(false);
|
|
3907
3844
|
}
|
|
3908
3845
|
}, [refetch]);
|
|
3909
|
-
const hydrate = (0,
|
|
3846
|
+
const hydrate = (0, import_react23.useCallback)(() => {
|
|
3910
3847
|
void refetch();
|
|
3911
3848
|
}, [refetch]);
|
|
3912
3849
|
return { result, submitting, submit, hydrate, rawStatus };
|
|
3913
3850
|
}
|
|
3914
3851
|
|
|
3915
3852
|
// src/components/games/MysteryTigerGame.tsx
|
|
3916
|
-
var
|
|
3853
|
+
var import_react25 = require("react");
|
|
3917
3854
|
|
|
3918
3855
|
// src/components/games/nationFlags.ts
|
|
3919
3856
|
var FLAGS = {
|
|
@@ -4124,7 +4061,7 @@ function isNationCode(flag) {
|
|
|
4124
4061
|
}
|
|
4125
4062
|
|
|
4126
4063
|
// src/components/games/PlayerAvatar.tsx
|
|
4127
|
-
var
|
|
4064
|
+
var import_react24 = require("react");
|
|
4128
4065
|
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
4129
4066
|
function initialsOf(name) {
|
|
4130
4067
|
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
@@ -4142,7 +4079,7 @@ function PlayerAvatar({
|
|
|
4142
4079
|
imagePath,
|
|
4143
4080
|
className
|
|
4144
4081
|
}) {
|
|
4145
|
-
const [failed, setFailed] = (0,
|
|
4082
|
+
const [failed, setFailed] = (0, import_react24.useState)(false);
|
|
4146
4083
|
const showImage = Boolean(imagePath) && !isPlaceholderImage(imagePath) && !failed;
|
|
4147
4084
|
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className, "aria-hidden": "true", children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("img", { src: imagePath, alt: "", loading: "lazy", onError: () => setFailed(true) }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "ss-w-av-initials", children: initialsOf(name) }) });
|
|
4148
4085
|
}
|
|
@@ -4357,8 +4294,8 @@ function MysteryTigerGame({
|
|
|
4357
4294
|
onBack
|
|
4358
4295
|
}) {
|
|
4359
4296
|
const t = ui.games.mysteryTiger;
|
|
4360
|
-
const [query, setQuery] = (0,
|
|
4361
|
-
const inputId = (0,
|
|
4297
|
+
const [query, setQuery] = (0, import_react25.useState)("");
|
|
4298
|
+
const inputId = (0, import_react25.useId)();
|
|
4362
4299
|
const clientState = parseClientState(result?.clientStateJson);
|
|
4363
4300
|
const guessResults = clientState?.guessResults ?? [];
|
|
4364
4301
|
const alreadyGuessedIds = new Set(guessResults.map((g) => g.playerId));
|
|
@@ -4633,13 +4570,13 @@ function HigherOrLowerGame({
|
|
|
4633
4570
|
}
|
|
4634
4571
|
|
|
4635
4572
|
// src/components/games/CareerPathGame.tsx
|
|
4636
|
-
var
|
|
4573
|
+
var import_react27 = require("react");
|
|
4637
4574
|
|
|
4638
4575
|
// src/components/games/ui/CrestShield.tsx
|
|
4639
|
-
var
|
|
4576
|
+
var import_react26 = require("react");
|
|
4640
4577
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
4641
4578
|
function CrestShield({ src, name, size = 28 }) {
|
|
4642
|
-
const [failed, setFailed] = (0,
|
|
4579
|
+
const [failed, setFailed] = (0, import_react26.useState)(false);
|
|
4643
4580
|
if (src && !isPlaceholderImage(src) && !failed) {
|
|
4644
4581
|
return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("img", { className: "ss-g-crest", src, alt: name, width: size, height: size, loading: "lazy", onError: () => setFailed(true) });
|
|
4645
4582
|
}
|
|
@@ -4671,8 +4608,8 @@ function CareerPathGame({
|
|
|
4671
4608
|
}) {
|
|
4672
4609
|
const s = ui.games.careerPath;
|
|
4673
4610
|
const title = gameTitle({ gameId: "career-path" }, ui.games.titles);
|
|
4674
|
-
const [query, setQuery] = (0,
|
|
4675
|
-
const inputId = (0,
|
|
4611
|
+
const [query, setQuery] = (0, import_react27.useState)("");
|
|
4612
|
+
const inputId = (0, import_react27.useId)();
|
|
4676
4613
|
const clientState = parseClientState3(result?.clientStateJson);
|
|
4677
4614
|
const alreadyGuessedIds = new Set(clientState?.guessResults.map((g) => g.playerId) ?? []);
|
|
4678
4615
|
const isOver = result?.alreadyPlayed === true || clientState?.solved === true || clientState?.failed === true;
|
|
@@ -4791,7 +4728,7 @@ function CareerPathGame({
|
|
|
4791
4728
|
}
|
|
4792
4729
|
|
|
4793
4730
|
// src/components/games/BeatTheGridGame.tsx
|
|
4794
|
-
var
|
|
4731
|
+
var import_react28 = __toESM(require("react"), 1);
|
|
4795
4732
|
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
4796
4733
|
function criterionIconKind(label, key) {
|
|
4797
4734
|
const l = (key ?? label).toLowerCase();
|
|
@@ -4872,10 +4809,10 @@ function SearchSheet({
|
|
|
4872
4809
|
ui
|
|
4873
4810
|
}) {
|
|
4874
4811
|
const s = ui.games.beatTheGrid;
|
|
4875
|
-
const [query, setQuery] = (0,
|
|
4876
|
-
const inputId = (0,
|
|
4877
|
-
const inputRef = (0,
|
|
4878
|
-
(0,
|
|
4812
|
+
const [query, setQuery] = (0, import_react28.useState)("");
|
|
4813
|
+
const inputId = (0, import_react28.useId)();
|
|
4814
|
+
const inputRef = (0, import_react28.useRef)(null);
|
|
4815
|
+
(0, import_react28.useEffect)(() => {
|
|
4879
4816
|
inputRef.current?.focus();
|
|
4880
4817
|
}, [row, col]);
|
|
4881
4818
|
const filtered = playerPool.filter(
|
|
@@ -4940,7 +4877,7 @@ function BeatTheGridGame({
|
|
|
4940
4877
|
}) {
|
|
4941
4878
|
const s = ui.games.beatTheGrid;
|
|
4942
4879
|
const title = gameTitle({ gameId: "beat-the-grid" }, ui.games.titles);
|
|
4943
|
-
const [activeCell, setActiveCell] = (0,
|
|
4880
|
+
const [activeCell, setActiveCell] = (0, import_react28.useState)(null);
|
|
4944
4881
|
const clientState = parseClientState4(result?.clientStateJson);
|
|
4945
4882
|
const filledCells = clientState?.cells ?? [];
|
|
4946
4883
|
const isLocked2 = result?.alreadyPlayed === true || clientState?.isComplete === true;
|
|
@@ -5014,7 +4951,7 @@ function BeatTheGridGame({
|
|
|
5014
4951
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { "aria-hidden": "true", children: abbr }),
|
|
5015
4952
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "ss-g-sr", children: rowLabel })
|
|
5016
4953
|
] });
|
|
5017
|
-
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
|
|
4954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(import_react28.default.Fragment, { children: [
|
|
5018
4955
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "ss-g-btg-rowhdr", "data-meta": rowMeta ? "true" : void 0, children: rowHeaderContent }),
|
|
5019
4956
|
cols.map((colLabel, colIdx) => {
|
|
5020
4957
|
const filled = findCellResult(filledCells, rowIdx, colIdx);
|
|
@@ -5095,7 +5032,7 @@ function BeatTheGridGame({
|
|
|
5095
5032
|
}
|
|
5096
5033
|
|
|
5097
5034
|
// src/components/games/GuessTheXiGame.tsx
|
|
5098
|
-
var
|
|
5035
|
+
var import_react29 = require("react");
|
|
5099
5036
|
|
|
5100
5037
|
// src/components/games/ui/PitchSvg.tsx
|
|
5101
5038
|
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
@@ -5184,8 +5121,8 @@ function GuessTheXiGame({
|
|
|
5184
5121
|
onBack
|
|
5185
5122
|
}) {
|
|
5186
5123
|
const t = ui.games.guessTheXi;
|
|
5187
|
-
const [query, setQuery] = (0,
|
|
5188
|
-
const inputId = (0,
|
|
5124
|
+
const [query, setQuery] = (0, import_react29.useState)("");
|
|
5125
|
+
const inputId = (0, import_react29.useId)();
|
|
5189
5126
|
const clientState = parseClientState5(result?.clientStateJson);
|
|
5190
5127
|
const isOver = result?.alreadyPlayed === true || clientState?.status === "solved" || clientState?.status === "failed";
|
|
5191
5128
|
const solved = clientState?.status === "solved";
|
|
@@ -5326,7 +5263,7 @@ function GuessTheXiGame({
|
|
|
5326
5263
|
}
|
|
5327
5264
|
|
|
5328
5265
|
// src/components/games/DailyQuizGame.tsx
|
|
5329
|
-
var
|
|
5266
|
+
var import_react30 = require("react");
|
|
5330
5267
|
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
5331
5268
|
function parseClientState6(json) {
|
|
5332
5269
|
if (!json) return null;
|
|
@@ -5367,8 +5304,8 @@ function DailyQuizGame({
|
|
|
5367
5304
|
}) {
|
|
5368
5305
|
const s = ui.games.dailyQuiz;
|
|
5369
5306
|
const title = gameTitle({ gameId: "daily-quiz" }, ui.games.titles);
|
|
5370
|
-
const [selections, setSelections] = (0,
|
|
5371
|
-
const [page, setPage] = (0,
|
|
5307
|
+
const [selections, setSelections] = (0, import_react30.useState)(/* @__PURE__ */ new Map());
|
|
5308
|
+
const [page, setPage] = (0, import_react30.useState)(0);
|
|
5372
5309
|
const clientState = parseClientState6(result?.clientStateJson);
|
|
5373
5310
|
const results = clientState?.results ?? [];
|
|
5374
5311
|
const isRevealed = results.length > 0 || result?.alreadyPlayed === true;
|
|
@@ -5478,7 +5415,7 @@ function DailyQuizGame({
|
|
|
5478
5415
|
}
|
|
5479
5416
|
|
|
5480
5417
|
// src/components/games/MatchdayPredictorGame.tsx
|
|
5481
|
-
var
|
|
5418
|
+
var import_react31 = require("react");
|
|
5482
5419
|
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
5483
5420
|
var SCORER_SEARCH_THRESHOLD = 9;
|
|
5484
5421
|
function parseClientState7(json) {
|
|
@@ -5574,12 +5511,12 @@ function MatchdayPredictorGame({
|
|
|
5574
5511
|
onBack
|
|
5575
5512
|
}) {
|
|
5576
5513
|
const t = ui.games.predictor;
|
|
5577
|
-
const [homeScore, setHomeScore] = (0,
|
|
5578
|
-
const [awayScore, setAwayScore] = (0,
|
|
5579
|
-
const [firstScorerPlayerId, setFirstScorerPlayerId] = (0,
|
|
5580
|
-
const [lastEdited, setLastEdited] = (0,
|
|
5581
|
-
const [query, setQuery] = (0,
|
|
5582
|
-
const searchId = (0,
|
|
5514
|
+
const [homeScore, setHomeScore] = (0, import_react31.useState)(0);
|
|
5515
|
+
const [awayScore, setAwayScore] = (0, import_react31.useState)(0);
|
|
5516
|
+
const [firstScorerPlayerId, setFirstScorerPlayerId] = (0, import_react31.useState)(null);
|
|
5517
|
+
const [lastEdited, setLastEdited] = (0, import_react31.useState)("home");
|
|
5518
|
+
const [query, setQuery] = (0, import_react31.useState)("");
|
|
5519
|
+
const searchId = (0, import_react31.useId)();
|
|
5583
5520
|
const clientState = parseClientState7(result?.clientStateJson);
|
|
5584
5521
|
const alreadyPlayed = result?.alreadyPlayed === true;
|
|
5585
5522
|
const header = /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
@@ -5746,7 +5683,7 @@ function MatchdayPredictorGame({
|
|
|
5746
5683
|
}
|
|
5747
5684
|
|
|
5748
5685
|
// src/components/games/StartingXiGame.tsx
|
|
5749
|
-
var
|
|
5686
|
+
var import_react32 = require("react");
|
|
5750
5687
|
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
5751
5688
|
var POINTS_PER_STARTER = 8;
|
|
5752
5689
|
var XI_SIZE = 11;
|
|
@@ -5790,10 +5727,10 @@ function StartingXiGame({
|
|
|
5790
5727
|
lockAtUtc
|
|
5791
5728
|
}) {
|
|
5792
5729
|
const t = ui.games.startingXi;
|
|
5793
|
-
const [slotPlayers, setSlotPlayers] = (0,
|
|
5794
|
-
const [active, setActive] = (0,
|
|
5795
|
-
const [query, setQuery] = (0,
|
|
5796
|
-
const searchId = (0,
|
|
5730
|
+
const [slotPlayers, setSlotPlayers] = (0, import_react32.useState)(() => Array(XI_SIZE).fill(null));
|
|
5731
|
+
const [active, setActive] = (0, import_react32.useState)(0);
|
|
5732
|
+
const [query, setQuery] = (0, import_react32.useState)("");
|
|
5733
|
+
const searchId = (0, import_react32.useId)();
|
|
5797
5734
|
const clientState = parseClientState8(result?.clientStateJson);
|
|
5798
5735
|
const alreadyPlayed = result?.alreadyPlayed === true;
|
|
5799
5736
|
const header = /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
@@ -5932,7 +5869,7 @@ function StartingXiGame({
|
|
|
5932
5869
|
}
|
|
5933
5870
|
|
|
5934
5871
|
// src/components/games/StatLadderGame.tsx
|
|
5935
|
-
var
|
|
5872
|
+
var import_react33 = require("react");
|
|
5936
5873
|
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
5937
5874
|
function ladderClue(ladder) {
|
|
5938
5875
|
const mystery = ladder.find((r) => r.rank === 2);
|
|
@@ -5969,9 +5906,9 @@ function StatLadderGame({
|
|
|
5969
5906
|
onBack
|
|
5970
5907
|
}) {
|
|
5971
5908
|
const t = ui.games.statLadder;
|
|
5972
|
-
const [query, setQuery] = (0,
|
|
5973
|
-
const [selectedId, setSelectedId] = (0,
|
|
5974
|
-
const searchId = (0,
|
|
5909
|
+
const [query, setQuery] = (0, import_react33.useState)("");
|
|
5910
|
+
const [selectedId, setSelectedId] = (0, import_react33.useState)(null);
|
|
5911
|
+
const searchId = (0, import_react33.useId)();
|
|
5975
5912
|
const clientState = parseClientState9(result?.clientStateJson);
|
|
5976
5913
|
const revealed = clientState != null;
|
|
5977
5914
|
const header = /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(GameHeader, { title: gameTitle({ gameId: "stat-ladder" }, ui.games.titles), eyebrow: t.eyebrow, onBack, backLabel: ui.back });
|
|
@@ -6176,8 +6113,8 @@ function GameScreenHost({
|
|
|
6176
6113
|
ui
|
|
6177
6114
|
}) {
|
|
6178
6115
|
const { gameId, fixtureId, gameDay = "", lockAtUtc = null } = selected;
|
|
6179
|
-
const [configJson, setConfigJson] = (0,
|
|
6180
|
-
(0,
|
|
6116
|
+
const [configJson, setConfigJson] = (0, import_react34.useState)(null);
|
|
6117
|
+
(0, import_react34.useEffect)(() => {
|
|
6181
6118
|
setConfigJson(null);
|
|
6182
6119
|
if (!conversation) return;
|
|
6183
6120
|
let cancelled = false;
|
|
@@ -6200,12 +6137,12 @@ function GameScreenHost({
|
|
|
6200
6137
|
fixtureId: fixtureId || void 0,
|
|
6201
6138
|
locale: ui.games.lang
|
|
6202
6139
|
});
|
|
6203
|
-
(0,
|
|
6140
|
+
(0, import_react34.useEffect)(() => {
|
|
6204
6141
|
if (conversation) hydrate();
|
|
6205
6142
|
}, [conversation, gameId]);
|
|
6206
|
-
const hydrateRef = (0,
|
|
6143
|
+
const hydrateRef = (0, import_react34.useRef)(hydrate);
|
|
6207
6144
|
hydrateRef.current = hydrate;
|
|
6208
|
-
(0,
|
|
6145
|
+
(0, import_react34.useEffect)(() => {
|
|
6209
6146
|
if (!FIXTURE_GAME_IDS.has(gameId)) return;
|
|
6210
6147
|
if (rawStatus !== "pending") return;
|
|
6211
6148
|
const timerId = setInterval(() => {
|
|
@@ -6340,8 +6277,8 @@ function GamesPanel({
|
|
|
6340
6277
|
leaderboard,
|
|
6341
6278
|
refreshHub
|
|
6342
6279
|
}) {
|
|
6343
|
-
const [selected, setSelected] = (0,
|
|
6344
|
-
(0,
|
|
6280
|
+
const [selected, setSelected] = (0, import_react35.useState)(null);
|
|
6281
|
+
(0, import_react35.useEffect)(() => {
|
|
6345
6282
|
ensureGamesFonts();
|
|
6346
6283
|
}, []);
|
|
6347
6284
|
if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(GamesLoginWall, { ui });
|
|
@@ -6372,7 +6309,7 @@ function GamesPanel({
|
|
|
6372
6309
|
}
|
|
6373
6310
|
|
|
6374
6311
|
// src/components/Leaderboard.tsx
|
|
6375
|
-
var
|
|
6312
|
+
var import_react36 = require("react");
|
|
6376
6313
|
|
|
6377
6314
|
// src/components/LeaderboardRow.tsx
|
|
6378
6315
|
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
@@ -6457,7 +6394,7 @@ function Leaderboard({
|
|
|
6457
6394
|
ui,
|
|
6458
6395
|
onPlay
|
|
6459
6396
|
}) {
|
|
6460
|
-
const [segment, setSegment] = (0,
|
|
6397
|
+
const [segment, setSegment] = (0, import_react36.useState)("weekly");
|
|
6461
6398
|
const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
|
|
6462
6399
|
const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
|
|
6463
6400
|
const isEmpty = segment === "weekly" ? data.weeklyTop.length === 0 : data.allTimeTop.length === 0;
|
|
@@ -6540,8 +6477,8 @@ function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }) {
|
|
|
6540
6477
|
var import_jsx_runtime85 = require("react/jsx-runtime");
|
|
6541
6478
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
6542
6479
|
function useIsModal() {
|
|
6543
|
-
const [modal, setModal] = (0,
|
|
6544
|
-
(0,
|
|
6480
|
+
const [modal, setModal] = (0, import_react37.useState)(false);
|
|
6481
|
+
(0, import_react37.useEffect)(() => {
|
|
6545
6482
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
6546
6483
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
6547
6484
|
const sync = () => setModal(mql.matches);
|
|
@@ -6554,7 +6491,7 @@ function useIsModal() {
|
|
|
6554
6491
|
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }) {
|
|
6555
6492
|
const { state, close, stop, send, reset } = controller;
|
|
6556
6493
|
const isModal = useIsModal();
|
|
6557
|
-
(0,
|
|
6494
|
+
(0, import_react37.useEffect)(() => {
|
|
6558
6495
|
const onKey = (e) => {
|
|
6559
6496
|
if (e.key === "Escape") close();
|
|
6560
6497
|
};
|
|
@@ -6569,7 +6506,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
6569
6506
|
monitor?.setActiveTab("chat");
|
|
6570
6507
|
send(text, { grounding });
|
|
6571
6508
|
};
|
|
6572
|
-
(0,
|
|
6509
|
+
(0, import_react37.useEffect)(() => {
|
|
6573
6510
|
if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
|
|
6574
6511
|
}, [monitor, state.isStreaming, state.messages.length]);
|
|
6575
6512
|
return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
@@ -6841,15 +6778,15 @@ function toSlipEvent(name, entry) {
|
|
|
6841
6778
|
// src/useHostEvents.ts
|
|
6842
6779
|
function useHostEvents(opts) {
|
|
6843
6780
|
const { host, operatorId, currentUser, logger, isOpen, closePanel, onOpenMatch, openMatchLabel } = opts;
|
|
6844
|
-
const [added, setAdded] = (0,
|
|
6845
|
-
const [settled, setSettled] = (0,
|
|
6846
|
-
const markAdded = (0,
|
|
6781
|
+
const [added, setAdded] = (0, import_react38.useState)({});
|
|
6782
|
+
const [settled, setSettled] = (0, import_react38.useState)({});
|
|
6783
|
+
const markAdded = (0, import_react38.useCallback)((matchOddsId) => {
|
|
6847
6784
|
setAdded((prev) => prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true });
|
|
6848
6785
|
}, []);
|
|
6849
|
-
const settle = (0,
|
|
6786
|
+
const settle = (0, import_react38.useCallback)((matchOddsId) => {
|
|
6850
6787
|
setSettled((prev) => prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true });
|
|
6851
6788
|
}, []);
|
|
6852
|
-
const clearMarks = (0,
|
|
6789
|
+
const clearMarks = (0, import_react38.useCallback)((ids) => {
|
|
6853
6790
|
const drop = (prev) => {
|
|
6854
6791
|
if (!ids.some((id) => prev[id])) return prev;
|
|
6855
6792
|
const next = { ...prev };
|
|
@@ -6860,26 +6797,26 @@ function useHostEvents(opts) {
|
|
|
6860
6797
|
setSettled(drop);
|
|
6861
6798
|
}, []);
|
|
6862
6799
|
const hasHost = host !== void 0;
|
|
6863
|
-
const ledger = (0,
|
|
6800
|
+
const ledger = (0, import_react38.useMemo)(
|
|
6864
6801
|
() => hasHost ? createSlipLedger(`ss-w-slip:${operatorId}`) : null,
|
|
6865
6802
|
[hasHost, operatorId]
|
|
6866
6803
|
);
|
|
6867
|
-
const currentUserRef = (0,
|
|
6804
|
+
const currentUserRef = (0, import_react38.useRef)(currentUser);
|
|
6868
6805
|
currentUserRef.current = currentUser;
|
|
6869
|
-
const recordAdd = (0,
|
|
6806
|
+
const recordAdd = (0, import_react38.useCallback)((add) => {
|
|
6870
6807
|
ledger?.record({ id: add.selection.matchOddsId, market: add.market, ...add.pick, user: currentUserRef.current });
|
|
6871
6808
|
}, [ledger]);
|
|
6872
|
-
const slipState = (0,
|
|
6809
|
+
const slipState = (0, import_react38.useMemo)(
|
|
6873
6810
|
() => ({ added, settled, settle, recordAdd }),
|
|
6874
6811
|
[added, settled, settle, recordAdd]
|
|
6875
6812
|
);
|
|
6876
6813
|
const hasOpenMatch = typeof onOpenMatch === "function";
|
|
6877
6814
|
const tracksViews = hasHost || hasOpenMatch;
|
|
6878
|
-
const views = (0,
|
|
6815
|
+
const views = (0, import_react38.useMemo)(
|
|
6879
6816
|
() => tracksViews ? createMatchViews(`ss-w-views:${operatorId}`, { user: currentUser }) : null,
|
|
6880
6817
|
[tracksViews, operatorId, currentUser]
|
|
6881
6818
|
);
|
|
6882
|
-
const sinkRef = (0,
|
|
6819
|
+
const sinkRef = (0, import_react38.useRef)(() => {
|
|
6883
6820
|
});
|
|
6884
6821
|
sinkRef.current = (command) => {
|
|
6885
6822
|
if (command.kind === "matchOpened") {
|
|
@@ -6900,11 +6837,11 @@ function useHostEvents(opts) {
|
|
|
6900
6837
|
logger?.log(toSlipEvent(name, entry));
|
|
6901
6838
|
}
|
|
6902
6839
|
};
|
|
6903
|
-
(0,
|
|
6840
|
+
(0, import_react38.useEffect)(() => {
|
|
6904
6841
|
if (!host) return;
|
|
6905
6842
|
return attachHost(host, (command) => sinkRef.current(command));
|
|
6906
6843
|
}, [host]);
|
|
6907
|
-
(0,
|
|
6844
|
+
(0, import_react38.useEffect)(() => {
|
|
6908
6845
|
if (!isOpen || !views) return;
|
|
6909
6846
|
const held = views.markOpened();
|
|
6910
6847
|
if (held.length === 0) return;
|
|
@@ -6913,7 +6850,7 @@ function useHostEvents(opts) {
|
|
|
6913
6850
|
}
|
|
6914
6851
|
void logger?.flushNow();
|
|
6915
6852
|
}, [isOpen, views, logger]);
|
|
6916
|
-
const openMatchRef = (0,
|
|
6853
|
+
const openMatchRef = (0, import_react38.useRef)(() => {
|
|
6917
6854
|
});
|
|
6918
6855
|
openMatchRef.current = (matchId) => {
|
|
6919
6856
|
if (views?.view(matchId) === "log") {
|
|
@@ -6927,7 +6864,7 @@ function useHostEvents(opts) {
|
|
|
6927
6864
|
}
|
|
6928
6865
|
if (typeof window.matchMedia === "function" && window.matchMedia(FULLSCREEN_QUERY).matches) closePanel();
|
|
6929
6866
|
};
|
|
6930
|
-
const matchLink = (0,
|
|
6867
|
+
const matchLink = (0, import_react38.useMemo)(
|
|
6931
6868
|
() => hasOpenMatch ? { open: (matchId) => openMatchRef.current(matchId), label: openMatchLabel } : null,
|
|
6932
6869
|
[hasOpenMatch, openMatchLabel]
|
|
6933
6870
|
);
|
|
@@ -6995,7 +6932,7 @@ function themeAttrs(ui) {
|
|
|
6995
6932
|
}
|
|
6996
6933
|
|
|
6997
6934
|
// src/useChatStream.ts
|
|
6998
|
-
var
|
|
6935
|
+
var import_react40 = require("react");
|
|
6999
6936
|
var import_widget_sdk4 = require("@sensiblestats/widget-sdk");
|
|
7000
6937
|
|
|
7001
6938
|
// src/reducer.ts
|
|
@@ -7119,7 +7056,7 @@ function reducer(state, action) {
|
|
|
7119
7056
|
}
|
|
7120
7057
|
|
|
7121
7058
|
// src/useLiveDashboardPoll.ts
|
|
7122
|
-
var
|
|
7059
|
+
var import_react39 = require("react");
|
|
7123
7060
|
var POLL_INTERVAL_MS = 6e4;
|
|
7124
7061
|
var LEAD_MS = 12e4;
|
|
7125
7062
|
var GIVE_UP_MS = 30 * 6e4;
|
|
@@ -7161,13 +7098,13 @@ function findEarliestWakeupMs(messages) {
|
|
|
7161
7098
|
return earliest;
|
|
7162
7099
|
}
|
|
7163
7100
|
function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }) {
|
|
7164
|
-
const [, forceUpdate] = (0,
|
|
7101
|
+
const [, forceUpdate] = (0, import_react39.useReducer)((x) => x + 1, 0);
|
|
7165
7102
|
const anchor = findAnchor(messages);
|
|
7166
|
-
const anchorRef = (0,
|
|
7103
|
+
const anchorRef = (0, import_react39.useRef)(anchor);
|
|
7167
7104
|
anchorRef.current = anchor;
|
|
7168
|
-
const inFlightRef = (0,
|
|
7105
|
+
const inFlightRef = (0, import_react39.useRef)(false);
|
|
7169
7106
|
const anchorKey = anchor ? `${anchor.messageId}:${anchor.kind}` : null;
|
|
7170
|
-
(0,
|
|
7107
|
+
(0, import_react39.useEffect)(() => {
|
|
7171
7108
|
if (!anchorKey || !anchorRef.current) return;
|
|
7172
7109
|
const tick = async () => {
|
|
7173
7110
|
if (inFlightRef.current) return;
|
|
@@ -7203,7 +7140,7 @@ function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }) {
|
|
|
7203
7140
|
}, POLL_INTERVAL_MS);
|
|
7204
7141
|
return () => window.clearInterval(id);
|
|
7205
7142
|
}, [anchorKey, dispatch, getLiveDashboard]);
|
|
7206
|
-
(0,
|
|
7143
|
+
(0, import_react39.useEffect)(() => {
|
|
7207
7144
|
if (anchorKey !== null) return;
|
|
7208
7145
|
const wakeAt = findEarliestWakeupMs(messages);
|
|
7209
7146
|
if (wakeAt === null) return;
|
|
@@ -7268,7 +7205,7 @@ function seedIdCounter(messages) {
|
|
|
7268
7205
|
return max + 1;
|
|
7269
7206
|
}
|
|
7270
7207
|
function useChatStream(conversation, starterTexts, greetingMessage, storageKey) {
|
|
7271
|
-
const boot = (0,
|
|
7208
|
+
const boot = (0, import_react40.useMemo)(() => {
|
|
7272
7209
|
const payload = storageKey ? readConversation(storageKey, Date.now()) : null;
|
|
7273
7210
|
const restored = payload != null && payload !== "expired" && payload !== "corrupt";
|
|
7274
7211
|
const base = initialState(starterTexts.map(chipFromText));
|
|
@@ -7277,27 +7214,27 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7277
7214
|
}
|
|
7278
7215
|
return { state: base, restored: false, stale: payload === "expired" || payload === "corrupt" };
|
|
7279
7216
|
}, []);
|
|
7280
|
-
const [state, dispatch] = (0,
|
|
7281
|
-
const idRef = (0,
|
|
7282
|
-
const handleRef = (0,
|
|
7283
|
-
const fallbackTimerRef = (0,
|
|
7284
|
-
const stateRef = (0,
|
|
7217
|
+
const [state, dispatch] = (0, import_react40.useReducer)(reducer, boot.state);
|
|
7218
|
+
const idRef = (0, import_react40.useRef)(seedIdCounter(boot.state.messages));
|
|
7219
|
+
const handleRef = (0, import_react40.useRef)(null);
|
|
7220
|
+
const fallbackTimerRef = (0, import_react40.useRef)(null);
|
|
7221
|
+
const stateRef = (0, import_react40.useRef)(state);
|
|
7285
7222
|
stateRef.current = state;
|
|
7286
|
-
const greetedRef = (0,
|
|
7287
|
-
const hydratedRef = (0,
|
|
7288
|
-
const restoreSeededRef = (0,
|
|
7223
|
+
const greetedRef = (0, import_react40.useRef)(boot.restored);
|
|
7224
|
+
const hydratedRef = (0, import_react40.useRef)(false);
|
|
7225
|
+
const restoreSeededRef = (0, import_react40.useRef)(false);
|
|
7289
7226
|
if (!restoreSeededRef.current) {
|
|
7290
7227
|
restoreSeededRef.current = true;
|
|
7291
7228
|
if (boot.restored && boot.state.conversationId) conversation.conversationId = boot.state.conversationId;
|
|
7292
7229
|
}
|
|
7293
7230
|
const nextId = () => `m${idRef.current++}`;
|
|
7294
|
-
const clearFallbackTimer = (0,
|
|
7231
|
+
const clearFallbackTimer = (0, import_react40.useCallback)(() => {
|
|
7295
7232
|
if (fallbackTimerRef.current != null) {
|
|
7296
7233
|
clearTimeout(fallbackTimerRef.current);
|
|
7297
7234
|
fallbackTimerRef.current = null;
|
|
7298
7235
|
}
|
|
7299
7236
|
}, []);
|
|
7300
|
-
const armFallbackTimer = (0,
|
|
7237
|
+
const armFallbackTimer = (0, import_react40.useCallback)((onFire) => {
|
|
7301
7238
|
clearFallbackTimer();
|
|
7302
7239
|
fallbackTimerRef.current = setTimeout(() => {
|
|
7303
7240
|
fallbackTimerRef.current = null;
|
|
@@ -7306,7 +7243,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7306
7243
|
onFire();
|
|
7307
7244
|
}, STREAM_FALLBACK_TIMEOUT_MS);
|
|
7308
7245
|
}, [clearFallbackTimer]);
|
|
7309
|
-
const consume = (0,
|
|
7246
|
+
const consume = (0, import_react40.useCallback)((handle, onError) => {
|
|
7310
7247
|
;
|
|
7311
7248
|
(async () => {
|
|
7312
7249
|
try {
|
|
@@ -7324,7 +7261,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7324
7261
|
}
|
|
7325
7262
|
})();
|
|
7326
7263
|
}, [clearFallbackTimer]);
|
|
7327
|
-
const run = (0,
|
|
7264
|
+
const run = (0, import_react40.useCallback)((input, displayText) => {
|
|
7328
7265
|
handleRef.current?.cancel();
|
|
7329
7266
|
clearFallbackTimer();
|
|
7330
7267
|
dispatch({ kind: "USER_SENT", input, userId: nextId(), assistantId: nextId(), displayText });
|
|
@@ -7336,16 +7273,16 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7336
7273
|
});
|
|
7337
7274
|
consume(handle, (err) => dispatch({ kind: "STREAM_ERROR", error: err }));
|
|
7338
7275
|
}, [conversation, consume, clearFallbackTimer, armFallbackTimer]);
|
|
7339
|
-
const send = (0,
|
|
7276
|
+
const send = (0, import_react40.useCallback)((text, opts) => {
|
|
7340
7277
|
const trimmed = text.trim();
|
|
7341
7278
|
if (!trimmed) return;
|
|
7342
7279
|
run({ message: trimmed, actionId: opts?.actionId, actionRef: opts?.actionRef, grounding: opts?.grounding }, opts?.displayText);
|
|
7343
7280
|
}, [run]);
|
|
7344
|
-
const retry = (0,
|
|
7281
|
+
const retry = (0, import_react40.useCallback)(() => {
|
|
7345
7282
|
const last = stateRef.current.lastUserInput;
|
|
7346
7283
|
if (last) run(last, stateRef.current.lastDisplayText ?? void 0);
|
|
7347
7284
|
}, [run]);
|
|
7348
|
-
const fireGreeting = (0,
|
|
7285
|
+
const fireGreeting = (0, import_react40.useCallback)(() => {
|
|
7349
7286
|
const message = greetingMessage?.trim();
|
|
7350
7287
|
if (!message) return;
|
|
7351
7288
|
try {
|
|
@@ -7360,15 +7297,15 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7360
7297
|
dispatch({ kind: "STOP" });
|
|
7361
7298
|
}
|
|
7362
7299
|
}, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer]);
|
|
7363
|
-
(0,
|
|
7300
|
+
(0, import_react40.useEffect)(() => {
|
|
7364
7301
|
if (greetedRef.current) return;
|
|
7365
7302
|
greetedRef.current = true;
|
|
7366
7303
|
fireGreeting();
|
|
7367
7304
|
}, [fireGreeting]);
|
|
7368
|
-
(0,
|
|
7305
|
+
(0, import_react40.useEffect)(() => {
|
|
7369
7306
|
if (boot.stale && storageKey) clearConversation(storageKey);
|
|
7370
7307
|
}, []);
|
|
7371
|
-
(0,
|
|
7308
|
+
(0, import_react40.useEffect)(() => {
|
|
7372
7309
|
if (!storageKey || state.isStreaming) return;
|
|
7373
7310
|
if (hydratedRef.current) {
|
|
7374
7311
|
hydratedRef.current = false;
|
|
@@ -7385,7 +7322,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7385
7322
|
if (persistable.length === 0) return;
|
|
7386
7323
|
writeConversation(storageKey, state.conversationId, persistable, Date.now());
|
|
7387
7324
|
}, [storageKey, state.isStreaming, state.messages, state.conversationId]);
|
|
7388
|
-
(0,
|
|
7325
|
+
(0, import_react40.useEffect)(() => {
|
|
7389
7326
|
if (!storageKey) return;
|
|
7390
7327
|
const onStorage = (e) => {
|
|
7391
7328
|
if (e.key !== storageKey || e.storageArea !== window.localStorage) return;
|
|
@@ -7409,25 +7346,25 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7409
7346
|
window.addEventListener("storage", onStorage);
|
|
7410
7347
|
return () => window.removeEventListener("storage", onStorage);
|
|
7411
7348
|
}, [storageKey, conversation, fireGreeting]);
|
|
7412
|
-
const open = (0,
|
|
7413
|
-
const close = (0,
|
|
7349
|
+
const open = (0, import_react40.useCallback)(() => dispatch({ kind: "OPEN" }), []);
|
|
7350
|
+
const close = (0, import_react40.useCallback)(() => {
|
|
7414
7351
|
handleRef.current?.cancel();
|
|
7415
7352
|
handleRef.current = null;
|
|
7416
7353
|
clearFallbackTimer();
|
|
7417
7354
|
dispatch({ kind: "CLOSE" });
|
|
7418
7355
|
}, [clearFallbackTimer]);
|
|
7419
|
-
const stop = (0,
|
|
7356
|
+
const stop = (0, import_react40.useCallback)(() => {
|
|
7420
7357
|
handleRef.current?.cancel();
|
|
7421
7358
|
handleRef.current = null;
|
|
7422
7359
|
clearFallbackTimer();
|
|
7423
7360
|
dispatch({ kind: "STOP" });
|
|
7424
7361
|
}, [clearFallbackTimer]);
|
|
7425
|
-
const toggle = (0,
|
|
7362
|
+
const toggle = (0, import_react40.useCallback)(() => {
|
|
7426
7363
|
if (stateRef.current.isOpen) close();
|
|
7427
7364
|
else open();
|
|
7428
7365
|
}, [close, open]);
|
|
7429
|
-
const dismissPopup = (0,
|
|
7430
|
-
const reset = (0,
|
|
7366
|
+
const dismissPopup = (0, import_react40.useCallback)(() => dispatch({ kind: "DISMISS_POPUP" }), []);
|
|
7367
|
+
const reset = (0, import_react40.useCallback)(() => {
|
|
7431
7368
|
handleRef.current?.cancel();
|
|
7432
7369
|
handleRef.current = null;
|
|
7433
7370
|
clearFallbackTimer();
|
|
@@ -7438,18 +7375,18 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
7438
7375
|
greetedRef.current = true;
|
|
7439
7376
|
fireGreeting();
|
|
7440
7377
|
}, [storageKey, conversation, clearFallbackTimer, fireGreeting]);
|
|
7441
|
-
const getLiveDashboard = (0,
|
|
7378
|
+
const getLiveDashboard = (0, import_react40.useCallback)(() => conversation.getLiveDashboard(), [conversation]);
|
|
7442
7379
|
useLiveDashboardPoll({ messages: state.messages, dispatch, getLiveDashboard });
|
|
7443
7380
|
return { state, open, close, stop, toggle, send, retry, dismissPopup, reset };
|
|
7444
7381
|
}
|
|
7445
7382
|
|
|
7446
7383
|
// src/useLiveMonitor.ts
|
|
7447
|
-
var
|
|
7384
|
+
var import_react42 = require("react");
|
|
7448
7385
|
|
|
7449
7386
|
// src/useTabs.ts
|
|
7450
|
-
var
|
|
7387
|
+
var import_react41 = require("react");
|
|
7451
7388
|
function useTabs(initial = "chat") {
|
|
7452
|
-
const [activeTab, setActiveTab] = (0,
|
|
7389
|
+
const [activeTab, setActiveTab] = (0, import_react41.useState)(initial);
|
|
7453
7390
|
return { activeTab, setActiveTab };
|
|
7454
7391
|
}
|
|
7455
7392
|
|
|
@@ -7473,36 +7410,36 @@ function phaseForPin(snapshot, pin) {
|
|
|
7473
7410
|
return snapshot.markets.find((mk) => mk.key === pin.key)?.phase;
|
|
7474
7411
|
}
|
|
7475
7412
|
function useLiveMonitor(opts) {
|
|
7476
|
-
const sessionIdRef = (0,
|
|
7477
|
-
const [pins, setPins] = (0,
|
|
7478
|
-
const [store] = (0,
|
|
7479
|
-
const [enabled, setEnabled] = (0,
|
|
7480
|
-
const [snapshot, setSnapshotState] = (0,
|
|
7413
|
+
const sessionIdRef = (0, import_react42.useRef)(crypto.randomUUID());
|
|
7414
|
+
const [pins, setPins] = (0, import_react42.useState)([]);
|
|
7415
|
+
const [store] = (0, import_react42.useState)(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins));
|
|
7416
|
+
const [enabled, setEnabled] = (0, import_react42.useState)(true);
|
|
7417
|
+
const [snapshot, setSnapshotState] = (0, import_react42.useState)(null);
|
|
7481
7418
|
const { activeTab, setActiveTab: setActiveTabState } = useTabs("chat");
|
|
7482
|
-
const [chatDot, setChatDot] = (0,
|
|
7483
|
-
const [matchesDot, setMatchesDot] = (0,
|
|
7484
|
-
const [oddsDot, setOddsDot] = (0,
|
|
7485
|
-
const [todayDot, setTodayDot] = (0,
|
|
7486
|
-
const [lastViewedPrices, setLastViewedPrices] = (0,
|
|
7487
|
-
const [openMarket, setOpenMarket] = (0,
|
|
7488
|
-
const [marketOdds, setMarketOdds] = (0,
|
|
7489
|
-
const pinsRef = (0,
|
|
7419
|
+
const [chatDot, setChatDot] = (0, import_react42.useState)(false);
|
|
7420
|
+
const [matchesDot, setMatchesDot] = (0, import_react42.useState)(false);
|
|
7421
|
+
const [oddsDot, setOddsDot] = (0, import_react42.useState)(false);
|
|
7422
|
+
const [todayDot, setTodayDot] = (0, import_react42.useState)(false);
|
|
7423
|
+
const [lastViewedPrices, setLastViewedPrices] = (0, import_react42.useState)({});
|
|
7424
|
+
const [openMarket, setOpenMarket] = (0, import_react42.useState)({});
|
|
7425
|
+
const [marketOdds, setMarketOdds] = (0, import_react42.useState)({});
|
|
7426
|
+
const pinsRef = (0, import_react42.useRef)(pins);
|
|
7490
7427
|
pinsRef.current = pins;
|
|
7491
|
-
const activeTabRef = (0,
|
|
7428
|
+
const activeTabRef = (0, import_react42.useRef)(activeTab);
|
|
7492
7429
|
activeTabRef.current = activeTab;
|
|
7493
|
-
const snapshotRef = (0,
|
|
7430
|
+
const snapshotRef = (0, import_react42.useRef)(snapshot);
|
|
7494
7431
|
snapshotRef.current = snapshot;
|
|
7495
|
-
const lastViewedPricesRef = (0,
|
|
7432
|
+
const lastViewedPricesRef = (0, import_react42.useRef)(lastViewedPrices);
|
|
7496
7433
|
lastViewedPricesRef.current = lastViewedPrices;
|
|
7497
|
-
const openMarketRef = (0,
|
|
7434
|
+
const openMarketRef = (0, import_react42.useRef)(openMarket);
|
|
7498
7435
|
openMarketRef.current = openMarket;
|
|
7499
|
-
const marketOddsRef = (0,
|
|
7436
|
+
const marketOddsRef = (0, import_react42.useRef)(marketOdds);
|
|
7500
7437
|
marketOddsRef.current = marketOdds;
|
|
7501
7438
|
const hasToday = opts.hasToday ?? false;
|
|
7502
7439
|
const marketKey = (matchId, dev) => `${matchId}:${dev}`;
|
|
7503
|
-
const getMarketOddsRef = (0,
|
|
7440
|
+
const getMarketOddsRef = (0, import_react42.useRef)(opts.getMarketOdds);
|
|
7504
7441
|
getMarketOddsRef.current = opts.getMarketOdds;
|
|
7505
|
-
const fetchMarket = (0,
|
|
7442
|
+
const fetchMarket = (0, import_react42.useCallback)((matchId, dev) => {
|
|
7506
7443
|
const key = marketKey(matchId, dev);
|
|
7507
7444
|
const existing = marketOddsRef.current[key];
|
|
7508
7445
|
if (existing?.loading) return;
|
|
@@ -7521,7 +7458,7 @@ function useLiveMonitor(opts) {
|
|
|
7521
7458
|
setMarketOdds((prev) => ({ ...prev, [key]: entry }));
|
|
7522
7459
|
});
|
|
7523
7460
|
}, []);
|
|
7524
|
-
const toggleMarket = (0,
|
|
7461
|
+
const toggleMarket = (0, import_react42.useCallback)((matchId, dev) => {
|
|
7525
7462
|
const key = marketKey(matchId, dev);
|
|
7526
7463
|
const wasOpen = openMarketRef.current[matchId] === dev;
|
|
7527
7464
|
const nextValue = wasOpen ? null : dev;
|
|
@@ -7532,10 +7469,10 @@ function useLiveMonitor(opts) {
|
|
|
7532
7469
|
fetchMarket(matchId, dev);
|
|
7533
7470
|
}
|
|
7534
7471
|
}, [fetchMarket]);
|
|
7535
|
-
const retryMarket = (0,
|
|
7472
|
+
const retryMarket = (0, import_react42.useCallback)((matchId, dev) => {
|
|
7536
7473
|
fetchMarket(matchId, dev);
|
|
7537
7474
|
}, [fetchMarket]);
|
|
7538
|
-
const applySnapshot = (0,
|
|
7475
|
+
const applySnapshot = (0, import_react42.useCallback)((next) => {
|
|
7539
7476
|
if (next === null) {
|
|
7540
7477
|
setEnabled(false);
|
|
7541
7478
|
return;
|
|
@@ -7598,13 +7535,13 @@ function useLiveMonitor(opts) {
|
|
|
7598
7535
|
snapshotRef.current = next;
|
|
7599
7536
|
setSnapshotState(next);
|
|
7600
7537
|
}, [store]);
|
|
7601
|
-
const inFlightRef = (0,
|
|
7602
|
-
const timerRef = (0,
|
|
7603
|
-
const disabledRef = (0,
|
|
7604
|
-
const mountedRef = (0,
|
|
7605
|
-
const getLiveMonitorRef = (0,
|
|
7538
|
+
const inFlightRef = (0, import_react42.useRef)(false);
|
|
7539
|
+
const timerRef = (0, import_react42.useRef)(void 0);
|
|
7540
|
+
const disabledRef = (0, import_react42.useRef)(false);
|
|
7541
|
+
const mountedRef = (0, import_react42.useRef)(false);
|
|
7542
|
+
const getLiveMonitorRef = (0, import_react42.useRef)(opts.getLiveMonitor);
|
|
7606
7543
|
getLiveMonitorRef.current = opts.getLiveMonitor;
|
|
7607
|
-
const tick = (0,
|
|
7544
|
+
const tick = (0, import_react42.useCallback)(async () => {
|
|
7608
7545
|
if (inFlightRef.current || disabledRef.current || pinsRef.current.length === 0) return;
|
|
7609
7546
|
inFlightRef.current = true;
|
|
7610
7547
|
try {
|
|
@@ -7627,7 +7564,7 @@ function useLiveMonitor(opts) {
|
|
|
7627
7564
|
scheduleRef.current();
|
|
7628
7565
|
}
|
|
7629
7566
|
}, [applySnapshot, fetchMarket]);
|
|
7630
|
-
const scheduleRef = (0,
|
|
7567
|
+
const scheduleRef = (0, import_react42.useRef)(() => {
|
|
7631
7568
|
});
|
|
7632
7569
|
scheduleRef.current = () => {
|
|
7633
7570
|
window.clearTimeout(timerRef.current);
|
|
@@ -7635,14 +7572,14 @@ function useLiveMonitor(opts) {
|
|
|
7635
7572
|
const hinted = (snapshotRef.current?.nextPollSeconds ?? DEFAULT_POLL_MS / 1e3) * 1e3;
|
|
7636
7573
|
timerRef.current = window.setTimeout(() => void tick(), Math.max(MIN_POLL_MS, hinted));
|
|
7637
7574
|
};
|
|
7638
|
-
(0,
|
|
7575
|
+
(0, import_react42.useEffect)(() => {
|
|
7639
7576
|
mountedRef.current = true;
|
|
7640
7577
|
return () => {
|
|
7641
7578
|
mountedRef.current = false;
|
|
7642
7579
|
};
|
|
7643
7580
|
}, []);
|
|
7644
|
-
const prevPinsLengthRef = (0,
|
|
7645
|
-
(0,
|
|
7581
|
+
const prevPinsLengthRef = (0, import_react42.useRef)(0);
|
|
7582
|
+
(0, import_react42.useEffect)(() => {
|
|
7646
7583
|
const wasEmpty = prevPinsLengthRef.current === 0;
|
|
7647
7584
|
prevPinsLengthRef.current = pins.length;
|
|
7648
7585
|
if (pins.length === 0) {
|
|
@@ -7651,20 +7588,20 @@ function useLiveMonitor(opts) {
|
|
|
7651
7588
|
}
|
|
7652
7589
|
if (wasEmpty) void tick();
|
|
7653
7590
|
}, [pins.length, tick]);
|
|
7654
|
-
(0,
|
|
7591
|
+
(0, import_react42.useEffect)(() => {
|
|
7655
7592
|
const matchPins = pins.filter((p) => p.kind === "match").length;
|
|
7656
7593
|
const marketPins = pins.length - matchPins;
|
|
7657
7594
|
if (activeTab === "following" && matchPins === 0) setActiveTabState(hasToday ? "today" : "chat");
|
|
7658
7595
|
if (activeTab === "odds" && marketPins === 0) setActiveTabState(hasToday ? "today" : "chat");
|
|
7659
7596
|
if (activeTab === "today" && !hasToday) setActiveTabState("chat");
|
|
7660
7597
|
}, [pins, activeTab, hasToday]);
|
|
7661
|
-
const prevIsOpenRef = (0,
|
|
7662
|
-
(0,
|
|
7598
|
+
const prevIsOpenRef = (0, import_react42.useRef)(false);
|
|
7599
|
+
(0, import_react42.useEffect)(() => {
|
|
7663
7600
|
const wasClosed = !prevIsOpenRef.current;
|
|
7664
7601
|
prevIsOpenRef.current = opts.isOpen;
|
|
7665
7602
|
if (wasClosed && opts.isOpen) void tick();
|
|
7666
7603
|
}, [opts.isOpen, tick]);
|
|
7667
|
-
(0,
|
|
7604
|
+
(0, import_react42.useEffect)(() => {
|
|
7668
7605
|
const onVisibility = () => {
|
|
7669
7606
|
if (document.visibilityState === "hidden") window.clearTimeout(timerRef.current);
|
|
7670
7607
|
else void tick();
|
|
@@ -7675,7 +7612,7 @@ function useLiveMonitor(opts) {
|
|
|
7675
7612
|
window.clearTimeout(timerRef.current);
|
|
7676
7613
|
};
|
|
7677
7614
|
}, [tick]);
|
|
7678
|
-
const setActiveTab = (0,
|
|
7615
|
+
const setActiveTab = (0, import_react42.useCallback)((tab) => {
|
|
7679
7616
|
setActiveTabState(tab);
|
|
7680
7617
|
if (tab === "chat") setChatDot(false);
|
|
7681
7618
|
if (tab === "today") setTodayDot(false);
|
|
@@ -7696,10 +7633,10 @@ function useLiveMonitor(opts) {
|
|
|
7696
7633
|
void tick();
|
|
7697
7634
|
}
|
|
7698
7635
|
}, [tick]);
|
|
7699
|
-
const togglePin = (0,
|
|
7700
|
-
const isPinned = (0,
|
|
7701
|
-
const markChatActivity = (0,
|
|
7702
|
-
const markTodayActivity = (0,
|
|
7636
|
+
const togglePin = (0, import_react42.useCallback)((pin) => store.toggle(pin), [store]);
|
|
7637
|
+
const isPinned = (0, import_react42.useCallback)((key) => pinsRef.current.some((p) => p.key === key), []);
|
|
7638
|
+
const markChatActivity = (0, import_react42.useCallback)(() => setChatDot(true), []);
|
|
7639
|
+
const markTodayActivity = (0, import_react42.useCallback)(() => {
|
|
7703
7640
|
if (activeTabRef.current !== "today") setTodayDot(true);
|
|
7704
7641
|
}, []);
|
|
7705
7642
|
return {
|
|
@@ -7726,7 +7663,7 @@ function useLiveMonitor(opts) {
|
|
|
7726
7663
|
}
|
|
7727
7664
|
|
|
7728
7665
|
// src/useMatchDiscovery.ts
|
|
7729
|
-
var
|
|
7666
|
+
var import_react43 = require("react");
|
|
7730
7667
|
|
|
7731
7668
|
// src/scheduleCache.ts
|
|
7732
7669
|
var PREFIX = "ss-w-schedule:";
|
|
@@ -7814,27 +7751,27 @@ function localDateOf(now) {
|
|
|
7814
7751
|
return `${y}-${m}-${d}`;
|
|
7815
7752
|
}
|
|
7816
7753
|
function useMatchDiscovery(opts) {
|
|
7817
|
-
const [groups, setGroups] = (0,
|
|
7818
|
-
const [states, setStates] = (0,
|
|
7819
|
-
const [failures, setFailures] = (0,
|
|
7820
|
-
const [expanded, setExpanded] = (0,
|
|
7821
|
-
const [touched, setTouched] = (0,
|
|
7822
|
-
const groupsRef = (0,
|
|
7754
|
+
const [groups, setGroups] = (0, import_react43.useState)([]);
|
|
7755
|
+
const [states, setStates] = (0, import_react43.useState)({});
|
|
7756
|
+
const [failures, setFailures] = (0, import_react43.useState)(0);
|
|
7757
|
+
const [expanded, setExpanded] = (0, import_react43.useState)({});
|
|
7758
|
+
const [touched, setTouched] = (0, import_react43.useState)({});
|
|
7759
|
+
const groupsRef = (0, import_react43.useRef)(groups);
|
|
7823
7760
|
groupsRef.current = groups;
|
|
7824
|
-
const statesRef = (0,
|
|
7761
|
+
const statesRef = (0, import_react43.useRef)(states);
|
|
7825
7762
|
statesRef.current = states;
|
|
7826
|
-
const getStatesRef = (0,
|
|
7763
|
+
const getStatesRef = (0, import_react43.useRef)(opts.getStates);
|
|
7827
7764
|
getStatesRef.current = opts.getStates;
|
|
7828
7765
|
const pinnedKey = opts.pinnedMatchIds.join(",");
|
|
7829
|
-
const [localDate, setLocalDate] = (0,
|
|
7830
|
-
(0,
|
|
7766
|
+
const [localDate, setLocalDate] = (0, import_react43.useState)(() => localDateOf(/* @__PURE__ */ new Date()));
|
|
7767
|
+
(0, import_react43.useEffect)(() => {
|
|
7831
7768
|
const id = setInterval(() => {
|
|
7832
7769
|
const next = localDateOf(/* @__PURE__ */ new Date());
|
|
7833
7770
|
setLocalDate((prev) => prev === next ? prev : next);
|
|
7834
7771
|
}, ROLLOVER_CHECK_MS);
|
|
7835
7772
|
return () => clearInterval(id);
|
|
7836
7773
|
}, []);
|
|
7837
|
-
(0,
|
|
7774
|
+
(0, import_react43.useEffect)(() => {
|
|
7838
7775
|
let cancelled = false;
|
|
7839
7776
|
const utcOffsetMinutes = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
7840
7777
|
const cached = readSchedule(opts.operatorId, localDate, Date.now());
|
|
@@ -7859,7 +7796,7 @@ function useMatchDiscovery(opts) {
|
|
|
7859
7796
|
cancelled = true;
|
|
7860
7797
|
};
|
|
7861
7798
|
}, [opts.operatorId, localDate]);
|
|
7862
|
-
(0,
|
|
7799
|
+
(0, import_react43.useEffect)(() => {
|
|
7863
7800
|
setExpanded((prev) => {
|
|
7864
7801
|
const next = {};
|
|
7865
7802
|
for (const group of groups) {
|
|
@@ -7870,7 +7807,7 @@ function useMatchDiscovery(opts) {
|
|
|
7870
7807
|
return next;
|
|
7871
7808
|
});
|
|
7872
7809
|
}, [groups, pinnedKey, touched]);
|
|
7873
|
-
const tick = (0,
|
|
7810
|
+
const tick = (0, import_react43.useCallback)(async () => {
|
|
7874
7811
|
const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now());
|
|
7875
7812
|
if (ids.length === 0) return;
|
|
7876
7813
|
try {
|
|
@@ -7886,7 +7823,7 @@ function useMatchDiscovery(opts) {
|
|
|
7886
7823
|
setFailures((n) => n + 1);
|
|
7887
7824
|
}
|
|
7888
7825
|
}, []);
|
|
7889
|
-
(0,
|
|
7826
|
+
(0, import_react43.useEffect)(() => {
|
|
7890
7827
|
if (!opts.isOpen) return;
|
|
7891
7828
|
void tick();
|
|
7892
7829
|
const id = setInterval(() => {
|
|
@@ -7895,11 +7832,11 @@ function useMatchDiscovery(opts) {
|
|
|
7895
7832
|
return () => clearInterval(id);
|
|
7896
7833
|
}, [opts.isOpen, tick, groups]);
|
|
7897
7834
|
const stale = failures >= STALE_AFTER_FAILURES;
|
|
7898
|
-
const liveCount = (0,
|
|
7835
|
+
const liveCount = (0, import_react43.useMemo)(
|
|
7899
7836
|
() => stale ? 0 : Object.values(states).filter((s) => s.phase === "live").length,
|
|
7900
7837
|
[states, stale]
|
|
7901
7838
|
);
|
|
7902
|
-
const toggleGroup = (0,
|
|
7839
|
+
const toggleGroup = (0, import_react43.useCallback)((competitionId) => {
|
|
7903
7840
|
setTouched((prev) => ({ ...prev, [competitionId]: true }));
|
|
7904
7841
|
setExpanded((prev) => ({ ...prev, [competitionId]: !prev[competitionId] }));
|
|
7905
7842
|
}, []);
|
|
@@ -7907,25 +7844,25 @@ function useMatchDiscovery(opts) {
|
|
|
7907
7844
|
}
|
|
7908
7845
|
|
|
7909
7846
|
// src/useGames.ts
|
|
7910
|
-
var
|
|
7847
|
+
var import_react44 = require("react");
|
|
7911
7848
|
var GAMES_POLL_MS = 6e4;
|
|
7912
7849
|
var DEFAULT_TZ = "Europe/London";
|
|
7913
7850
|
function computeGameDay(timezone) {
|
|
7914
7851
|
return new Intl.DateTimeFormat("en-CA", { timeZone: timezone }).format(/* @__PURE__ */ new Date());
|
|
7915
7852
|
}
|
|
7916
7853
|
function useGames(conversation, { activeTab, operatorTimezone }) {
|
|
7917
|
-
const [enabled, setEnabled] = (0,
|
|
7918
|
-
const [games, setGames] = (0,
|
|
7919
|
-
const [loading, setLoading] = (0,
|
|
7920
|
-
const [refreshCount, setRefreshCount] = (0,
|
|
7921
|
-
const inFlightRef = (0,
|
|
7922
|
-
const hardOffRef = (0,
|
|
7923
|
-
const conversationRef = (0,
|
|
7854
|
+
const [enabled, setEnabled] = (0, import_react44.useState)(false);
|
|
7855
|
+
const [games, setGames] = (0, import_react44.useState)([]);
|
|
7856
|
+
const [loading, setLoading] = (0, import_react44.useState)(false);
|
|
7857
|
+
const [refreshCount, setRefreshCount] = (0, import_react44.useState)(0);
|
|
7858
|
+
const inFlightRef = (0, import_react44.useRef)(false);
|
|
7859
|
+
const hardOffRef = (0, import_react44.useRef)(false);
|
|
7860
|
+
const conversationRef = (0, import_react44.useRef)(conversation);
|
|
7924
7861
|
conversationRef.current = conversation;
|
|
7925
|
-
const tzRef = (0,
|
|
7862
|
+
const tzRef = (0, import_react44.useRef)(operatorTimezone ?? DEFAULT_TZ);
|
|
7926
7863
|
tzRef.current = operatorTimezone ?? DEFAULT_TZ;
|
|
7927
7864
|
const ready = conversation != null;
|
|
7928
|
-
(0,
|
|
7865
|
+
(0, import_react44.useEffect)(() => {
|
|
7929
7866
|
if (hardOffRef.current) return;
|
|
7930
7867
|
let active = true;
|
|
7931
7868
|
const doFetch = async () => {
|
|
@@ -7968,22 +7905,22 @@ function useGames(conversation, { activeTab, operatorTimezone }) {
|
|
|
7968
7905
|
if (intervalId !== void 0) window.clearInterval(intervalId);
|
|
7969
7906
|
};
|
|
7970
7907
|
}, [activeTab, refreshCount, ready]);
|
|
7971
|
-
const refresh = (0,
|
|
7908
|
+
const refresh = (0, import_react44.useCallback)(() => {
|
|
7972
7909
|
setRefreshCount((c) => c + 1);
|
|
7973
7910
|
}, []);
|
|
7974
7911
|
return { enabled, games, loading, refresh };
|
|
7975
7912
|
}
|
|
7976
7913
|
|
|
7977
7914
|
// src/useLeaderboard.ts
|
|
7978
|
-
var
|
|
7915
|
+
var import_react45 = require("react");
|
|
7979
7916
|
function useLeaderboard(conversation, { activeTab }) {
|
|
7980
|
-
const [data, setData] = (0,
|
|
7981
|
-
const [loading, setLoading] = (0,
|
|
7982
|
-
const [refreshCount, setRefreshCount] = (0,
|
|
7983
|
-
const inFlightRef = (0,
|
|
7984
|
-
const conversationRef = (0,
|
|
7917
|
+
const [data, setData] = (0, import_react45.useState)(null);
|
|
7918
|
+
const [loading, setLoading] = (0, import_react45.useState)(false);
|
|
7919
|
+
const [refreshCount, setRefreshCount] = (0, import_react45.useState)(0);
|
|
7920
|
+
const inFlightRef = (0, import_react45.useRef)(false);
|
|
7921
|
+
const conversationRef = (0, import_react45.useRef)(conversation);
|
|
7985
7922
|
conversationRef.current = conversation;
|
|
7986
|
-
(0,
|
|
7923
|
+
(0, import_react45.useEffect)(() => {
|
|
7987
7924
|
if (activeTab !== "leaderboard" && activeTab !== "games") return;
|
|
7988
7925
|
let active = true;
|
|
7989
7926
|
const doFetch = async () => {
|
|
@@ -8006,18 +7943,18 @@ function useLeaderboard(conversation, { activeTab }) {
|
|
|
8006
7943
|
inFlightRef.current = false;
|
|
8007
7944
|
};
|
|
8008
7945
|
}, [activeTab, refreshCount]);
|
|
8009
|
-
const refresh = (0,
|
|
7946
|
+
const refresh = (0, import_react45.useCallback)(() => {
|
|
8010
7947
|
setRefreshCount((c) => c + 1);
|
|
8011
7948
|
}, []);
|
|
8012
7949
|
return { data, loading, refresh };
|
|
8013
7950
|
}
|
|
8014
7951
|
|
|
8015
7952
|
// src/popupTelemetry.ts
|
|
8016
|
-
var
|
|
7953
|
+
var import_react46 = require("react");
|
|
8017
7954
|
function usePopupTelemetry(log, isOpen, popupText, dismissPopup) {
|
|
8018
|
-
const shownRef = (0,
|
|
8019
|
-
const closedTextRef = (0,
|
|
8020
|
-
(0,
|
|
7955
|
+
const shownRef = (0, import_react46.useRef)(/* @__PURE__ */ new Set());
|
|
7956
|
+
const closedTextRef = (0, import_react46.useRef)(null);
|
|
7957
|
+
(0, import_react46.useEffect)(() => {
|
|
8021
7958
|
if (isOpen) {
|
|
8022
7959
|
if (closedTextRef.current) log?.log({ name: "popup_opened" });
|
|
8023
7960
|
closedTextRef.current = null;
|
|
@@ -8029,14 +7966,14 @@ function usePopupTelemetry(log, isOpen, popupText, dismissPopup) {
|
|
|
8029
7966
|
log?.log({ name: "popup_shown" });
|
|
8030
7967
|
}
|
|
8031
7968
|
}, [log, isOpen, popupText]);
|
|
8032
|
-
return (0,
|
|
7969
|
+
return (0, import_react46.useCallback)(() => {
|
|
8033
7970
|
log?.log({ name: "popup_dismissed" });
|
|
8034
7971
|
dismissPopup();
|
|
8035
7972
|
}, [log, dismissPopup]);
|
|
8036
7973
|
}
|
|
8037
7974
|
|
|
8038
7975
|
// src/components/ChatFab.tsx
|
|
8039
|
-
var
|
|
7976
|
+
var import_react47 = require("react");
|
|
8040
7977
|
|
|
8041
7978
|
// src/components/GreetingBubble.tsx
|
|
8042
7979
|
var import_jsx_runtime86 = require("react/jsx-runtime");
|
|
@@ -8058,9 +7995,9 @@ function GreetingBubble({ text, onOpen, onDismiss, dismissLabel = "Dismiss" }) {
|
|
|
8058
7995
|
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
8059
7996
|
function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = "Dismiss", introAllowed = false, onIntroStart }) {
|
|
8060
7997
|
const bubble = popupText ?? greeting;
|
|
8061
|
-
const [intro, setIntro] = (0,
|
|
8062
|
-
const armedRef = (0,
|
|
8063
|
-
(0,
|
|
7998
|
+
const [intro, setIntro] = (0, import_react47.useState)(false);
|
|
7999
|
+
const armedRef = (0, import_react47.useRef)(introAllowed);
|
|
8000
|
+
(0, import_react47.useEffect)(() => {
|
|
8064
8001
|
if (armedRef.current && bubble) {
|
|
8065
8002
|
armedRef.current = false;
|
|
8066
8003
|
setIntro(true);
|
|
@@ -8434,7 +8371,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
8434
8371
|
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
8435
8372
|
.ss-w-bi-pick-row .ss-w-slip { flex: none; }
|
|
8436
8373
|
|
|
8437
|
-
/* row 3: bar-chart glyph + reasoning prose
|
|
8374
|
+
/* row 3: bar-chart glyph + reasoning prose, in a subtle strip */
|
|
8438
8375
|
.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }
|
|
8439
8376
|
.ss-w-bi-chart { flex: none; width: 13px; height: 12px; margin-top: 2px; opacity: .55;
|
|
8440
8377
|
background:
|
|
@@ -8443,23 +8380,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
8443
8380
|
linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) right / 3px 75% no-repeat;
|
|
8444
8381
|
background-position: left bottom, center bottom, right bottom;
|
|
8445
8382
|
}
|
|
8446
|
-
.ss-w-bi-
|
|
8447
|
-
.ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
|
|
8448
|
-
.ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
8449
|
-
.ss-w-bi-expand { flex: none; align-self: center; display: grid; place-items: center; width: 22px; height: 22px; margin: -2px -4px -2px 0; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; }
|
|
8450
|
-
.ss-w-bi-expand:hover { color: var(--ss-w-ink); }
|
|
8451
|
-
.ss-w-bi-arrow { width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-top: 1.6px solid currentColor; transform: rotate(45deg); transition: transform .15s ease; }
|
|
8452
|
-
.ss-w-bi-arrow-open { transform: rotate(135deg); }
|
|
8453
|
-
.ss-w-bi-rows { display: flex; flex-direction: column; }
|
|
8454
|
-
.ss-w-bi-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 5px 0; border-top: 1px solid var(--ss-w-line); }
|
|
8455
|
-
.ss-w-bi-row:first-child { border-top: none; }
|
|
8456
|
-
.ss-w-bi-row-lbl { font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }
|
|
8457
|
-
.ss-w-bi-row-num { font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 13px; flex: none; color: var(--ss-w-ink); }
|
|
8383
|
+
.ss-w-bi-text { flex: 1; min-width: 0; font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
|
|
8458
8384
|
.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }
|
|
8459
|
-
.ss-w-bi-scoped { display: flex; flex-direction: column; gap: 8px; }
|
|
8460
|
-
.ss-w-bi-scopes { display: inline-flex; align-items: center; gap: 2px; flex-wrap: wrap; align-self: flex-start; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 2px; }
|
|
8461
|
-
.ss-w-bi-chip { font-size: 11px; font-weight: 600; border: none; border-radius: 7px; padding: 4px 10px; color: var(--ss-w-faint); background: none; cursor: pointer; }
|
|
8462
|
-
.ss-w-bi-chip[aria-pressed="true"] { color: var(--ss-w-ink); background: var(--ss-w-panel); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
|
|
8463
8385
|
|
|
8464
8386
|
/* market odds card */
|
|
8465
8387
|
.ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
|
|
@@ -9600,23 +9522,23 @@ function injectStyles(root) {
|
|
|
9600
9522
|
function StatsWidget(props) {
|
|
9601
9523
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
9602
9524
|
const cfg = props.config;
|
|
9603
|
-
const built = (0,
|
|
9604
|
-
const logger = (0,
|
|
9525
|
+
const built = (0, import_react48.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
9526
|
+
const logger = (0, import_react48.useMemo)(
|
|
9605
9527
|
() => built ? built.client.createEventLogger({
|
|
9606
9528
|
operatorUserId: cfg?.userContext?.operatorUserId,
|
|
9607
9529
|
anonymousUserId: cfg?.userContext?.anonymousUserId
|
|
9608
9530
|
}) : null,
|
|
9609
9531
|
[built?.client]
|
|
9610
9532
|
);
|
|
9611
|
-
const ui = (0,
|
|
9612
|
-
const rootRef = (0,
|
|
9613
|
-
const introDoneRef = (0,
|
|
9614
|
-
const markIntroDone = (0,
|
|
9533
|
+
const ui = (0, import_react48.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
9534
|
+
const rootRef = (0, import_react48.useRef)(null);
|
|
9535
|
+
const introDoneRef = (0, import_react48.useRef)(false);
|
|
9536
|
+
const markIntroDone = (0, import_react48.useCallback)(() => {
|
|
9615
9537
|
introDoneRef.current = true;
|
|
9616
9538
|
}, []);
|
|
9617
9539
|
const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
|
|
9618
9540
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
|
|
9619
|
-
const [hasToday, setHasToday] = (0,
|
|
9541
|
+
const [hasToday, setHasToday] = (0, import_react48.useState)(false);
|
|
9620
9542
|
const monitor = useLiveMonitor({
|
|
9621
9543
|
getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
|
|
9622
9544
|
getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
|
|
@@ -9624,15 +9546,15 @@ function StatsWidget(props) {
|
|
|
9624
9546
|
isOpen: controller.state.isOpen,
|
|
9625
9547
|
hasToday
|
|
9626
9548
|
});
|
|
9627
|
-
const getSchedule = (0,
|
|
9549
|
+
const getSchedule = (0, import_react48.useCallback)(
|
|
9628
9550
|
(localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),
|
|
9629
9551
|
[built]
|
|
9630
9552
|
);
|
|
9631
|
-
const getStates = (0,
|
|
9553
|
+
const getStates = (0, import_react48.useCallback)(
|
|
9632
9554
|
(matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
|
|
9633
9555
|
[built]
|
|
9634
9556
|
);
|
|
9635
|
-
const pinnedMatchIds = (0,
|
|
9557
|
+
const pinnedMatchIds = (0, import_react48.useMemo)(
|
|
9636
9558
|
() => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
|
|
9637
9559
|
[monitor.pins]
|
|
9638
9560
|
);
|
|
@@ -9644,14 +9566,14 @@ function StatsWidget(props) {
|
|
|
9644
9566
|
pinnedMatchIds
|
|
9645
9567
|
});
|
|
9646
9568
|
const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
|
|
9647
|
-
(0,
|
|
9569
|
+
(0, import_react48.useEffect)(() => {
|
|
9648
9570
|
setHasToday(todayHasContent);
|
|
9649
9571
|
}, [todayHasContent]);
|
|
9650
9572
|
const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
|
|
9651
9573
|
const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
|
|
9652
9574
|
const markTodayActivity = monitor.markTodayActivity;
|
|
9653
|
-
const prevLiveCountRef = (0,
|
|
9654
|
-
(0,
|
|
9575
|
+
const prevLiveCountRef = (0, import_react48.useRef)(0);
|
|
9576
|
+
(0, import_react48.useEffect)(() => {
|
|
9655
9577
|
const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
|
|
9656
9578
|
prevLiveCountRef.current = discovery.liveCount;
|
|
9657
9579
|
if (rose) markTodayActivity();
|
|
@@ -9667,7 +9589,7 @@ function StatsWidget(props) {
|
|
|
9667
9589
|
openMatchLabel: ui.openMatch
|
|
9668
9590
|
});
|
|
9669
9591
|
const markAdded = hostEvents.markAdded;
|
|
9670
|
-
const slip = (0,
|
|
9592
|
+
const slip = (0, import_react48.useMemo)(
|
|
9671
9593
|
() => {
|
|
9672
9594
|
const handler = props.config?.onAddToSlip;
|
|
9673
9595
|
return {
|
|
@@ -9686,7 +9608,7 @@ function StatsWidget(props) {
|
|
|
9686
9608
|
},
|
|
9687
9609
|
[props.config?.onAddToSlip, controller.state.conversationId, markAdded]
|
|
9688
9610
|
);
|
|
9689
|
-
const onDashboardTap = (0,
|
|
9611
|
+
const onDashboardTap = (0, import_react48.useMemo)(
|
|
9690
9612
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
|
|
9691
9613
|
[built, logger]
|
|
9692
9614
|
);
|
|
@@ -9694,11 +9616,11 @@ function StatsWidget(props) {
|
|
|
9694
9616
|
const operatorUserId = cfg?.userContext?.operatorUserId;
|
|
9695
9617
|
const anonymousUserId = cfg?.userContext?.anonymousUserId;
|
|
9696
9618
|
const conversationId = controller.state.conversationId ?? void 0;
|
|
9697
|
-
(0,
|
|
9619
|
+
(0, import_react48.useEffect)(() => {
|
|
9698
9620
|
if (!logger) return;
|
|
9699
9621
|
logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
|
|
9700
9622
|
}, [logger, operatorUserId, anonymousUserId, conversationId]);
|
|
9701
|
-
(0,
|
|
9623
|
+
(0, import_react48.useEffect)(() => {
|
|
9702
9624
|
if (!logger) return;
|
|
9703
9625
|
logger.resume();
|
|
9704
9626
|
const onHide = () => {
|
|
@@ -9716,7 +9638,7 @@ function StatsWidget(props) {
|
|
|
9716
9638
|
logger.dispose();
|
|
9717
9639
|
};
|
|
9718
9640
|
}, [logger]);
|
|
9719
|
-
(0,
|
|
9641
|
+
(0, import_react48.useEffect)(() => {
|
|
9720
9642
|
if (!built || !ui.injectStyles) return;
|
|
9721
9643
|
const node = rootRef.current?.getRootNode();
|
|
9722
9644
|
if (node) injectStyles(node);
|