@sensiblestats/widget-react 0.30.0 → 0.31.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 +1298 -576
- 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 +1292 -570
- package/dist/index.js.map +1 -1
- package/dist/styles.css +74 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/StatsWidget.tsx
|
|
2
|
-
import { useEffect as
|
|
2
|
+
import { useEffect as useEffect9, useMemo as useMemo2, useRef as useRef6 } from "react";
|
|
3
3
|
import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
|
|
4
4
|
|
|
5
5
|
// src/kickoff.ts
|
|
@@ -56,7 +56,7 @@ var STRINGS = {
|
|
|
56
56
|
return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`;
|
|
57
57
|
},
|
|
58
58
|
inSlip: "In slip",
|
|
59
|
-
slipAdded:
|
|
59
|
+
slipAdded: "Added to slip",
|
|
60
60
|
slipDuplicate: "Already in your slip",
|
|
61
61
|
slipPriceChanged: (from, to) => `Added at ${to} (was ${from})`,
|
|
62
62
|
slipPriceNotAccepted: (from, to) => `Price moved to ${to} (was ${from}). Tap to add.`,
|
|
@@ -65,7 +65,23 @@ var STRINGS = {
|
|
|
65
65
|
slipFailed: "Couldn't add to slip. Try again.",
|
|
66
66
|
today: "Today",
|
|
67
67
|
tomorrow: "Tomorrow",
|
|
68
|
-
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, "en", now)
|
|
68
|
+
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, "en", now),
|
|
69
|
+
tabChat: "Chat",
|
|
70
|
+
tabMatches: "Matches",
|
|
71
|
+
tabOdds: "Odds",
|
|
72
|
+
pinLabel: "Track odds",
|
|
73
|
+
unpinLabel: "Stop tracking odds",
|
|
74
|
+
matchPinLabel: "Track match",
|
|
75
|
+
matchUnpinLabel: "Stop tracking match",
|
|
76
|
+
matchLimitToast: "Match limit reached \u2014 unpin one first",
|
|
77
|
+
marketLimitToast: "Odds limit reached \u2014 unpin one first",
|
|
78
|
+
emptyMatchesTab: "No pinned matches yet. Pin a match from the conversation to track it live.",
|
|
79
|
+
emptyOddsTab: "No pinned odds yet. Pin a market from the conversation to track it live.",
|
|
80
|
+
asOf: (time) => `Prices as of ${time}`,
|
|
81
|
+
graceNote: "Unpins on next open \xB7 or in 4 h",
|
|
82
|
+
suspendedLabel: "Suspended",
|
|
83
|
+
fullTimeLabel: "Full time",
|
|
84
|
+
inSlipLabel: "In slip"
|
|
69
85
|
},
|
|
70
86
|
tr: {
|
|
71
87
|
launcherLabel: "SensibleStats ile sohbet et",
|
|
@@ -107,7 +123,7 @@ var STRINGS = {
|
|
|
107
123
|
return `Son ${span} i\xE7indeki oran hareketi: ${opening} ile a\xE7\u0131ld\u0131, \u015Fu anda ${current}${drift}.`;
|
|
108
124
|
},
|
|
109
125
|
inSlip: "Kuponda",
|
|
110
|
-
slipAdded:
|
|
126
|
+
slipAdded: "Kupona eklendi",
|
|
111
127
|
slipDuplicate: "Bu se\xE7im kuponunuzda zaten var",
|
|
112
128
|
slipPriceChanged: (from, to) => `${to} oran\u0131yla eklendi (\xF6nceki ${from})`,
|
|
113
129
|
slipPriceNotAccepted: (from, to) => `Oran ${to} oldu (\xF6nceki ${from}). Eklemek i\xE7in dokunun.`,
|
|
@@ -116,7 +132,23 @@ var STRINGS = {
|
|
|
116
132
|
slipFailed: "Kupona eklenemedi. Tekrar deneyin.",
|
|
117
133
|
today: "Bug\xFCn",
|
|
118
134
|
tomorrow: "Yar\u0131n",
|
|
119
|
-
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, "tr", now)
|
|
135
|
+
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, "tr", now),
|
|
136
|
+
tabChat: "Sohbet",
|
|
137
|
+
tabMatches: "Ma\xE7lar",
|
|
138
|
+
tabOdds: "Oranlar",
|
|
139
|
+
pinLabel: "Oran\u0131 takip et",
|
|
140
|
+
unpinLabel: "Oran takibini b\u0131rak",
|
|
141
|
+
matchPinLabel: "Ma\xE7\u0131 takip et",
|
|
142
|
+
matchUnpinLabel: "Ma\xE7 takibini b\u0131rak",
|
|
143
|
+
matchLimitToast: "Ma\xE7 limiti dolu \u2014 \xF6nce bir ma\xE7\u0131 kald\u0131r",
|
|
144
|
+
marketLimitToast: "Oran limiti dolu \u2014 \xF6nce birini kald\u0131r",
|
|
145
|
+
emptyMatchesTab: "Hen\xFCz sabitlenmi\u015F ma\xE7 yok. Canl\u0131 takip i\xE7in sohbetteki bir ma\xE7\u0131 sabitle.",
|
|
146
|
+
emptyOddsTab: "Hen\xFCz sabitlenmi\u015F oran yok. Canl\u0131 takip i\xE7in sohbetteki bir marketi sabitle.",
|
|
147
|
+
asOf: (time) => `Fiyatlar ${time} itibar\u0131yla`,
|
|
148
|
+
graceNote: "Bir sonraki a\xE7\u0131l\u0131\u015Fta kald\u0131r\u0131l\u0131r \xB7 en ge\xE7 4 saat",
|
|
149
|
+
suspendedLabel: "Ask\u0131da",
|
|
150
|
+
fullTimeLabel: "Ma\xE7 sonu",
|
|
151
|
+
inSlipLabel: "Kuponda"
|
|
120
152
|
}
|
|
121
153
|
};
|
|
122
154
|
function resolveLocaleStrings(locale) {
|
|
@@ -180,7 +212,23 @@ function normalizeUi(cfg) {
|
|
|
180
212
|
slipFailed: strings.slipFailed,
|
|
181
213
|
today: strings.today,
|
|
182
214
|
tomorrow: strings.tomorrow,
|
|
183
|
-
bettingKickoff: strings.bettingKickoff
|
|
215
|
+
bettingKickoff: strings.bettingKickoff,
|
|
216
|
+
tabChat: strings.tabChat,
|
|
217
|
+
tabMatches: strings.tabMatches,
|
|
218
|
+
tabOdds: strings.tabOdds,
|
|
219
|
+
pinLabel: strings.pinLabel,
|
|
220
|
+
unpinLabel: strings.unpinLabel,
|
|
221
|
+
matchPinLabel: strings.matchPinLabel,
|
|
222
|
+
matchUnpinLabel: strings.matchUnpinLabel,
|
|
223
|
+
matchLimitToast: strings.matchLimitToast,
|
|
224
|
+
marketLimitToast: strings.marketLimitToast,
|
|
225
|
+
emptyMatchesTab: strings.emptyMatchesTab,
|
|
226
|
+
emptyOddsTab: strings.emptyOddsTab,
|
|
227
|
+
asOf: strings.asOf,
|
|
228
|
+
graceNote: strings.graceNote,
|
|
229
|
+
suspendedLabel: strings.suspendedLabel,
|
|
230
|
+
fullTimeLabel: strings.fullTimeLabel,
|
|
231
|
+
inSlipLabel: strings.inSlipLabel
|
|
184
232
|
};
|
|
185
233
|
}
|
|
186
234
|
function toClientOptions(cfg) {
|
|
@@ -192,6 +240,34 @@ function toUserContext(cfg) {
|
|
|
192
240
|
return cfg.userContext && Object.keys(cfg.userContext).length > 0 ? cfg.userContext : void 0;
|
|
193
241
|
}
|
|
194
242
|
|
|
243
|
+
// src/slip.ts
|
|
244
|
+
var ADD_TO_SLIP_TIMEOUT_MS = 1e4;
|
|
245
|
+
function wasAdded(result) {
|
|
246
|
+
if (!result) return true;
|
|
247
|
+
if (result.status === "price_changed") return result.accepted;
|
|
248
|
+
return result.status === "added";
|
|
249
|
+
}
|
|
250
|
+
function isTerminal(result) {
|
|
251
|
+
if (!result) return true;
|
|
252
|
+
if (result.status === "price_changed") return result.accepted;
|
|
253
|
+
return result.status === "added" || result.status === "duplicate";
|
|
254
|
+
}
|
|
255
|
+
function resultToToast(result, shownOdds, ui) {
|
|
256
|
+
if (!result) return { kind: "success", text: ui.slipAdded };
|
|
257
|
+
switch (result.status) {
|
|
258
|
+
case "added":
|
|
259
|
+
return { kind: "success", text: ui.slipAdded };
|
|
260
|
+
case "duplicate":
|
|
261
|
+
return { kind: "success", text: ui.slipDuplicate };
|
|
262
|
+
case "price_changed":
|
|
263
|
+
return result.accepted ? { kind: "success", text: ui.slipPriceChanged(shownOdds, result.newOddsDecimal.toFixed(2)) } : { kind: "error", text: ui.slipPriceNotAccepted(shownOdds, result.newOddsDecimal.toFixed(2)) };
|
|
264
|
+
case "rejected":
|
|
265
|
+
if (result.reason === "login_required") return { kind: "error", text: ui.slipLoginRequired };
|
|
266
|
+
if (result.reason === "suspended") return { kind: "error", text: ui.slipSuspended };
|
|
267
|
+
return { kind: "error", text: result.message ?? ui.slipFailed };
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
195
271
|
// src/dashboardTap.ts
|
|
196
272
|
import { ENTITY_TYPE_CODES } from "@sensiblestats/widget-sdk";
|
|
197
273
|
function isSignalEntityType(value) {
|
|
@@ -365,7 +441,11 @@ function toInsightVM(insight) {
|
|
|
365
441
|
disclaimer: str(insight.disclaimer),
|
|
366
442
|
matchId: typeof insight.matchId === "number" ? insight.matchId : 0,
|
|
367
443
|
matchOddsId,
|
|
444
|
+
marketDeveloperName: str(insight.marketDeveloperName),
|
|
445
|
+
selectionLabel: str(insight.selectionLabel),
|
|
446
|
+
line: str(insight.line),
|
|
368
447
|
addToSlipEnabled: insight.addToSlipEnabled === true,
|
|
448
|
+
pinEnabled: insight.pinEnabled === true,
|
|
369
449
|
isMarketFloor: insight.isMarketFloor === true,
|
|
370
450
|
oddsDecimal: typeof oddsValue === "number" && Number.isFinite(oddsValue) ? oddsValue : void 0,
|
|
371
451
|
quotedAtUtc: str(insight.odds?.quotedAtUtc),
|
|
@@ -432,7 +512,10 @@ function toMarketOddsVM(card) {
|
|
|
432
512
|
mainRows: vms.filter((r) => r.isMain),
|
|
433
513
|
moreRows: vms.filter((r) => !r.isMain),
|
|
434
514
|
disclaimer: str(card.disclaimer),
|
|
435
|
-
addToSlipEnabled: card.addToSlipEnabled === true
|
|
515
|
+
addToSlipEnabled: card.addToSlipEnabled === true,
|
|
516
|
+
marketDeveloperName: str(card.marketDeveloperName),
|
|
517
|
+
mainLine: str(card.mainLine),
|
|
518
|
+
pinEnabled: card.pinEnabled === true
|
|
436
519
|
};
|
|
437
520
|
}
|
|
438
521
|
function toOddsMovementVM(card) {
|
|
@@ -454,8 +537,12 @@ function toOddsMovementVM(card) {
|
|
|
454
537
|
const bookmakerId = typeof card.bookmakerId === "number" ? card.bookmakerId : "";
|
|
455
538
|
return {
|
|
456
539
|
id: `${typeof card.matchId === "number" ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ""}:${selection}:${bookmakerId}`,
|
|
540
|
+
matchId: typeof card.matchId === "number" ? card.matchId : 0,
|
|
457
541
|
market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? "",
|
|
542
|
+
marketDeveloperName: str(card.marketDeveloperName),
|
|
458
543
|
selection,
|
|
544
|
+
selectionLabel: str(card.selectionLabel),
|
|
545
|
+
line: str(card.line),
|
|
459
546
|
fixture: home && away ? `${home} vs ${away}` : void 0,
|
|
460
547
|
competition: str(card.competitionName),
|
|
461
548
|
bookmaker: str(card.bookmakerName),
|
|
@@ -467,7 +554,9 @@ function toOddsMovementVM(card) {
|
|
|
467
554
|
isSuspended: card.isSuspended === true,
|
|
468
555
|
disclaimer: str(card.disclaimer),
|
|
469
556
|
geometry: projectSeries(samples),
|
|
470
|
-
observationCount: samples.length
|
|
557
|
+
observationCount: samples.length,
|
|
558
|
+
pinEnabled: card.pinEnabled === true,
|
|
559
|
+
matchOddsId: typeof card.matchOddsId === "number" ? card.matchOddsId : void 0
|
|
471
560
|
};
|
|
472
561
|
}
|
|
473
562
|
function marketOddsRowToSlipSelection(vm, row, conversationId) {
|
|
@@ -782,6 +871,264 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
|
|
|
782
871
|
return { state, open, close, stop, toggle, send, retry, dismissPopup };
|
|
783
872
|
}
|
|
784
873
|
|
|
874
|
+
// src/useLiveMonitor.ts
|
|
875
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState } from "react";
|
|
876
|
+
|
|
877
|
+
// src/pinStore.ts
|
|
878
|
+
var MAX_MATCH_PINS = 5;
|
|
879
|
+
var MAX_MARKET_PINS = 10;
|
|
880
|
+
function pinKey(p) {
|
|
881
|
+
return `${p.kind}:${p.matchId}:${p.marketDeveloperName ?? ""}:${p.selectionLabel ?? ""}:${p.line ?? ""}:${p.matchOddsId ?? ""}`;
|
|
882
|
+
}
|
|
883
|
+
var GRACE_MS = 4 * 60 * 60 * 1e3;
|
|
884
|
+
function pruneExpired(pins, sessionId, now) {
|
|
885
|
+
return pins.filter((p) => p.graceAt === void 0 || p.graceSession === sessionId && now - p.graceAt <= GRACE_MS);
|
|
886
|
+
}
|
|
887
|
+
function safeRead(storageKey) {
|
|
888
|
+
try {
|
|
889
|
+
const raw = window.localStorage.getItem(storageKey);
|
|
890
|
+
if (!raw) return [];
|
|
891
|
+
const parsed = JSON.parse(raw);
|
|
892
|
+
return parsed.v === 1 && Array.isArray(parsed.pins) ? parsed.pins : [];
|
|
893
|
+
} catch {
|
|
894
|
+
return [];
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
function safeWrite(storageKey, pins) {
|
|
898
|
+
try {
|
|
899
|
+
window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, pins }));
|
|
900
|
+
} catch {
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
function createPinStore(storageKey, sessionId, onChange) {
|
|
904
|
+
let pins = pruneExpired(safeRead(storageKey), sessionId, Date.now());
|
|
905
|
+
const commit = (next) => {
|
|
906
|
+
pins = next;
|
|
907
|
+
safeWrite(storageKey, pins);
|
|
908
|
+
onChange(pins);
|
|
909
|
+
};
|
|
910
|
+
commit(pins);
|
|
911
|
+
return {
|
|
912
|
+
get pins() {
|
|
913
|
+
return pins;
|
|
914
|
+
},
|
|
915
|
+
has: (key) => pins.some((p) => p.key === key),
|
|
916
|
+
remove: (key) => commit(pins.filter((p) => p.key !== key)),
|
|
917
|
+
markGrace(keys, session, now) {
|
|
918
|
+
commit(
|
|
919
|
+
pins.map((p) => keys.includes(p.key) && p.graceAt === void 0 ? { ...p, graceAt: now, graceSession: session } : p)
|
|
920
|
+
);
|
|
921
|
+
},
|
|
922
|
+
toggle(pin) {
|
|
923
|
+
if (pins.some((p) => p.key === pin.key)) {
|
|
924
|
+
commit(pins.filter((p) => p.key !== pin.key));
|
|
925
|
+
return "removed";
|
|
926
|
+
}
|
|
927
|
+
const matchCount = pins.filter((p) => p.kind === "match").length;
|
|
928
|
+
const marketCount = pins.length - matchCount;
|
|
929
|
+
if (pin.kind === "match" && matchCount >= MAX_MATCH_PINS) return "match_limit";
|
|
930
|
+
if (pin.kind !== "match" && marketCount >= MAX_MARKET_PINS) return "market_limit";
|
|
931
|
+
commit([...pins, pin]);
|
|
932
|
+
return "added";
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// src/useLiveMonitor.ts
|
|
938
|
+
var GOAL_OR_RED = /* @__PURE__ */ new Set(["goal", "red"]);
|
|
939
|
+
var MIN_POLL_MS = 5e3;
|
|
940
|
+
var DEFAULT_POLL_MS = 6e4;
|
|
941
|
+
function eventIdentity(e) {
|
|
942
|
+
return `${e.type}:${e.side}:${e.minuteLabel}:${e.player ?? ""}`;
|
|
943
|
+
}
|
|
944
|
+
function priceForPin(snapshot, pin) {
|
|
945
|
+
if (!snapshot) return void 0;
|
|
946
|
+
const market = snapshot.markets.find((m) => m.key === pin.key);
|
|
947
|
+
const rows = market?.card?.rows;
|
|
948
|
+
if (!rows || rows.length === 0) return void 0;
|
|
949
|
+
const row = pin.matchOddsId != null ? rows.find((r) => r.matchOddsId === pin.matchOddsId) : rows[0];
|
|
950
|
+
return row?.price;
|
|
951
|
+
}
|
|
952
|
+
function phaseForPin(snapshot, pin) {
|
|
953
|
+
if (pin.kind === "match") return snapshot.matches.find((m) => m.matchId === pin.matchId)?.phase;
|
|
954
|
+
return snapshot.markets.find((mk) => mk.key === pin.key)?.phase;
|
|
955
|
+
}
|
|
956
|
+
function useLiveMonitor(opts) {
|
|
957
|
+
const sessionIdRef = useRef3(crypto.randomUUID());
|
|
958
|
+
const [pins, setPins] = useState([]);
|
|
959
|
+
const [store] = useState(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins));
|
|
960
|
+
const [enabled, setEnabled] = useState(true);
|
|
961
|
+
const [snapshot, setSnapshotState] = useState(null);
|
|
962
|
+
const [activeTab, setActiveTabState] = useState("chat");
|
|
963
|
+
const [chatDot, setChatDot] = useState(false);
|
|
964
|
+
const [matchesDot, setMatchesDot] = useState(false);
|
|
965
|
+
const [oddsDot, setOddsDot] = useState(false);
|
|
966
|
+
const [lastViewedPrices, setLastViewedPrices] = useState({});
|
|
967
|
+
const [inSlip, setInSlip] = useState({});
|
|
968
|
+
const pinsRef = useRef3(pins);
|
|
969
|
+
pinsRef.current = pins;
|
|
970
|
+
const activeTabRef = useRef3(activeTab);
|
|
971
|
+
activeTabRef.current = activeTab;
|
|
972
|
+
const snapshotRef = useRef3(snapshot);
|
|
973
|
+
snapshotRef.current = snapshot;
|
|
974
|
+
const lastViewedPricesRef = useRef3(lastViewedPrices);
|
|
975
|
+
lastViewedPricesRef.current = lastViewedPrices;
|
|
976
|
+
const applySnapshot = useCallback2((next) => {
|
|
977
|
+
if (next === null) {
|
|
978
|
+
setEnabled(false);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
const prev = snapshotRef.current;
|
|
982
|
+
const currentPins = pinsRef.current;
|
|
983
|
+
const pinnedMatchIds = new Set(currentPins.filter((p) => p.kind === "match").map((p) => p.matchId));
|
|
984
|
+
let sawNewGoalOrRed = false;
|
|
985
|
+
for (const m of next.matches) {
|
|
986
|
+
if (!pinnedMatchIds.has(m.matchId)) continue;
|
|
987
|
+
const prevMatch = prev?.matches.find((pm) => pm.matchId === m.matchId);
|
|
988
|
+
const prevKeys = new Set((prevMatch?.events ?? []).filter((e) => GOAL_OR_RED.has(e.type)).map(eventIdentity));
|
|
989
|
+
if (m.events.some((e) => GOAL_OR_RED.has(e.type) && !prevKeys.has(eventIdentity(e)))) {
|
|
990
|
+
sawNewGoalOrRed = true;
|
|
991
|
+
break;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
if (sawNewGoalOrRed && activeTabRef.current !== "matches") setMatchesDot(true);
|
|
995
|
+
const marketPins = currentPins.filter((p) => p.kind !== "match");
|
|
996
|
+
if (activeTabRef.current === "odds") {
|
|
997
|
+
setLastViewedPrices((prevMap) => {
|
|
998
|
+
let changed = false;
|
|
999
|
+
const out = { ...prevMap };
|
|
1000
|
+
for (const pin of marketPins) {
|
|
1001
|
+
const price = priceForPin(next, pin);
|
|
1002
|
+
if (price !== void 0 && out[pin.key] !== price) {
|
|
1003
|
+
out[pin.key] = price;
|
|
1004
|
+
changed = true;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return changed ? out : prevMap;
|
|
1008
|
+
});
|
|
1009
|
+
} else {
|
|
1010
|
+
let sawPriceMove = false;
|
|
1011
|
+
for (const pin of marketPins) {
|
|
1012
|
+
const price = priceForPin(next, pin);
|
|
1013
|
+
const last = lastViewedPricesRef.current[pin.key];
|
|
1014
|
+
if (price !== void 0 && last !== void 0 && price !== last) {
|
|
1015
|
+
sawPriceMove = true;
|
|
1016
|
+
break;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (sawPriceMove) setOddsDot(true);
|
|
1020
|
+
}
|
|
1021
|
+
const graceKeys = currentPins.filter((p) => {
|
|
1022
|
+
const phase = phaseForPin(next, p);
|
|
1023
|
+
return phase === "fullTime" || phase === "postponed" || phase === "gone";
|
|
1024
|
+
}).map((p) => p.key);
|
|
1025
|
+
if (graceKeys.length > 0) store.markGrace(graceKeys, sessionIdRef.current, Date.now());
|
|
1026
|
+
snapshotRef.current = next;
|
|
1027
|
+
setSnapshotState(next);
|
|
1028
|
+
}, [store]);
|
|
1029
|
+
const inFlightRef = useRef3(false);
|
|
1030
|
+
const timerRef = useRef3(void 0);
|
|
1031
|
+
const disabledRef = useRef3(false);
|
|
1032
|
+
const getLiveMonitorRef = useRef3(opts.getLiveMonitor);
|
|
1033
|
+
getLiveMonitorRef.current = opts.getLiveMonitor;
|
|
1034
|
+
const tick = useCallback2(async () => {
|
|
1035
|
+
if (inFlightRef.current || disabledRef.current || pinsRef.current.length === 0) return;
|
|
1036
|
+
inFlightRef.current = true;
|
|
1037
|
+
try {
|
|
1038
|
+
const snap = await getLiveMonitorRef.current(pinsRef.current);
|
|
1039
|
+
if (snap === null) {
|
|
1040
|
+
disabledRef.current = true;
|
|
1041
|
+
applySnapshot(null);
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
applySnapshot(snap);
|
|
1045
|
+
} catch {
|
|
1046
|
+
} finally {
|
|
1047
|
+
inFlightRef.current = false;
|
|
1048
|
+
scheduleRef.current();
|
|
1049
|
+
}
|
|
1050
|
+
}, [applySnapshot]);
|
|
1051
|
+
const scheduleRef = useRef3(() => {
|
|
1052
|
+
});
|
|
1053
|
+
scheduleRef.current = () => {
|
|
1054
|
+
window.clearTimeout(timerRef.current);
|
|
1055
|
+
if (disabledRef.current || pinsRef.current.length === 0 || document.visibilityState === "hidden") return;
|
|
1056
|
+
const hinted = (snapshotRef.current?.nextPollSeconds ?? DEFAULT_POLL_MS / 1e3) * 1e3;
|
|
1057
|
+
timerRef.current = window.setTimeout(() => void tick(), Math.max(MIN_POLL_MS, hinted));
|
|
1058
|
+
};
|
|
1059
|
+
const prevPinsLengthRef = useRef3(0);
|
|
1060
|
+
useEffect3(() => {
|
|
1061
|
+
const wasEmpty = prevPinsLengthRef.current === 0;
|
|
1062
|
+
prevPinsLengthRef.current = pins.length;
|
|
1063
|
+
if (pins.length === 0) {
|
|
1064
|
+
window.clearTimeout(timerRef.current);
|
|
1065
|
+
setActiveTabState("chat");
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
if (wasEmpty) void tick();
|
|
1069
|
+
}, [pins.length, tick]);
|
|
1070
|
+
const prevIsOpenRef = useRef3(false);
|
|
1071
|
+
useEffect3(() => {
|
|
1072
|
+
const wasClosed = !prevIsOpenRef.current;
|
|
1073
|
+
prevIsOpenRef.current = opts.isOpen;
|
|
1074
|
+
if (wasClosed && opts.isOpen) void tick();
|
|
1075
|
+
}, [opts.isOpen, tick]);
|
|
1076
|
+
useEffect3(() => {
|
|
1077
|
+
const onVisibility = () => {
|
|
1078
|
+
if (document.visibilityState === "hidden") window.clearTimeout(timerRef.current);
|
|
1079
|
+
else void tick();
|
|
1080
|
+
};
|
|
1081
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
1082
|
+
return () => {
|
|
1083
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
1084
|
+
window.clearTimeout(timerRef.current);
|
|
1085
|
+
};
|
|
1086
|
+
}, [tick]);
|
|
1087
|
+
const setActiveTab = useCallback2((tab) => {
|
|
1088
|
+
setActiveTabState(tab);
|
|
1089
|
+
if (tab === "chat") setChatDot(false);
|
|
1090
|
+
if (tab === "matches") {
|
|
1091
|
+
setMatchesDot(false);
|
|
1092
|
+
void tick();
|
|
1093
|
+
}
|
|
1094
|
+
if (tab === "odds") {
|
|
1095
|
+
setOddsDot(false);
|
|
1096
|
+
setLastViewedPrices((prevMap) => {
|
|
1097
|
+
const out = { ...prevMap };
|
|
1098
|
+
for (const pin of pinsRef.current.filter((p) => p.kind !== "match")) {
|
|
1099
|
+
const price = priceForPin(snapshotRef.current, pin);
|
|
1100
|
+
if (price !== void 0) out[pin.key] = price;
|
|
1101
|
+
}
|
|
1102
|
+
return out;
|
|
1103
|
+
});
|
|
1104
|
+
void tick();
|
|
1105
|
+
}
|
|
1106
|
+
}, [tick]);
|
|
1107
|
+
const togglePin = useCallback2((pin) => store.toggle(pin), [store]);
|
|
1108
|
+
const isPinned = useCallback2((key) => pinsRef.current.some((p) => p.key === key), []);
|
|
1109
|
+
const markChatActivity = useCallback2(() => setChatDot(true), []);
|
|
1110
|
+
const markInSlip = useCallback2((matchOddsId) => {
|
|
1111
|
+
setInSlip((prev) => prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true });
|
|
1112
|
+
}, []);
|
|
1113
|
+
return {
|
|
1114
|
+
enabled,
|
|
1115
|
+
pins,
|
|
1116
|
+
snapshot,
|
|
1117
|
+
activeTab,
|
|
1118
|
+
setActiveTab,
|
|
1119
|
+
togglePin,
|
|
1120
|
+
isPinned,
|
|
1121
|
+
chatDot,
|
|
1122
|
+
markChatActivity,
|
|
1123
|
+
matchesDot,
|
|
1124
|
+
oddsDot,
|
|
1125
|
+
lastViewedPrices,
|
|
1126
|
+
inSlip,
|
|
1127
|
+
markInSlip,
|
|
1128
|
+
_setSnapshot: applySnapshot
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
|
|
785
1132
|
// src/assets/logo.ts
|
|
786
1133
|
var SS_LOGO_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjA5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjE5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3N0UmVmOmRvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+QWRvYmUgUGhvdG9zaG9wIDI2LjEwICgyMDI1MDczMC5tLjMxNjYgMDdiMTIzNCkgIChNYWNpbnRvc2gpPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgrJu30+AABAAElEQVR4Ae2dB5wlRbX/T8/sLuyEXbIgCBhRERBQwfAABRURE6JPMSFiBtN7f0XF8Hzqw5xFfUYEfYqKiBhAgkoSAwoYEFSSAkvemdldlt3p/6/u3YXZZcINHU5Vf/vz6bn3dledOudbPff+urqCGRsEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEKiKQFZVQZQDAQhEQGCpbWaZbWG5bWrz9D5v7ZvK8030fiOdG9H70TX74tbn3Obr80LtG+jzoNKFNHNty5TgzjWJbleeVco7ps9LtU/o/YSOhc+36P0tNqnd7ObWe7Ob9P56G7Yl+jyp92wQgAAEZiSA0JkRDScgkBiBIGLm2f1stW0vgRD2bRXhlpIKW+v9Vnof9gURRR1EzhLt/2y95naNDdhVEkhXKaarFOuVkl/XKbbVEcWEqxCAQMEEEDoFA8UcBGolEMSM2YPVrvIg/eDvoP1B+qF/oI5tr31Ye9O20FJ0pThcpsAv1+vl+nyZ+FwuEXR102AQLwSaSACh08RaJ+b4Cdxsi/TA6GH6wd5JweykH/CH6XVn7RvHH1xlEYyJ26Uq7Y/aL9F+qT5fLLLh0RgbBCCQCAGETiIVSRgJE7hd/WMGbXdFuLtaI3bXj3F4f9+EI647tGvE+Dd6DPZbOfJ7vf+teh1dX7dTlA8BCPRGAKHTGzdyQaAcArkkzTLbRX1MHi1R81j9yO6h1/uVUxhWuyBwjdKeq/o4XzV0gR57XaR6WduZugszJIUABKomgNCpmjjlQWAqgdyGNL7oMfoB3bslbMwepdNN7EszlUoM71eovn4jQfpzvZ6tGjtPr2EkGRsEIOCMAELHWYXgTuIEctvQxtVaY7avHo3sI4EThE0Yns0WN4E7JXQulPA5W2GcqUdd5+rzHXGHhPcQSIMAQieNeiQKzwTGbEf96D1ZLoZ9L+0benYX3wohEFp3zpaQ/an209TB+S+FWMUIBCDQNQGETtfIyACBOQgs0f38QnuSxM1TlfJJ2reZIwen0ydwta6HH0r0nKLHXGfR2pN+hROhHwIIHT91gScxE1imSfdye5r2pyuMJ2jfIOZw8L1UAmHm59DSc4oedf2Q4eylssY4BPTvxgYBCPRG4Da7v2bffY4yH6w9DPlmg0C3BMLszmfrm/hEiZ7vaXGNMNMzGwQgUCABhE6BMDHVAAJLNdPwgB2kSIPA2a0BERNidQSC6Pm5WnpO0uu3ED3VgaektAkgdNKuX6IrgsCE3Vs/PofI1Au171KESWxAYA4CYX2u07Ufr0HrJ2uZ1fE50nMaAhCYgQBCZwYwHG44gbDEwgatlpsXiMS+2vlfafglUWP4Eyr7ZO1fV0fm03QlhpYfNghAoEMCfHl3CIpkDSCQ6ydkXHPbZPYyRfts7QwDb0C1RxbitWpd/KpmXvqKrs6/R+Y77kKgFgIInVqwU6grAu0RU4fqPvkwiRyWW3BVOTgzC4GzdO7LauX5jq7bFbOk4xQEGk0AodPo6m9w8Lm6FC+z/XV3/GpROED7QINpEHrcBG6W+1/RCMBjaeWJuyLxvhwCCJ1yuGLVK4GltqkkzWFyLwic+3p1E78g0AOBXHl+qtadz2oFtVP1Sl+eHiCSJT0CCJ306pSIpiMwoaHgub1ep/5dO5P5TceIYykRuFLBfMKW25dscxtLKTBigUC3BBA63RIjfTwE2o+nDpTAeZOc3jsex/EUAoURWCpLX7RB+5SWJbmyMKsYgkBEBBA6EVUWrnZIIFfD/bi9VE33oQXngR3mIhkEUiawWv8PYSLCY9R5+bcpB0psEFifAEJnfSJ8jpfArbaRLbAj1ILzBgWxabyB4DkESiVwmv5HjtHMy2HUFhsEkieA0Em+ihsQ4IRt1RI3mb1GryMNiJgQIVAEgV+plecYtX+erNfQkZkNAkkSQOgkWa0NCWq5bWur7G36kn6JImZyv4ZUO2EWTuD3+h/6LwRP4Vwx6IQAQsdJReBGFwRCC47Z0boHfble53eRk6QQgMDMBBA8M7PhTMQEEDoRV17jXG8/onqL4n6ldlpwGncBEHBFBILgeac6LZ9SUXkUA4FSCSB0SsWL8UIIhE7G8+2tsvU67QicQqBiBAJzEMjsXFttR2l523PmSMlpCLgmgNBxXT0Ndy7XzB8TdqQoBJGzUcNpED4E6iLwQxX8dnXzv7guBygXAv0QQOj0Q4+85RDINb3ZMs2Dk9u7VcDW5RSCVQhAoAsCYVTW8Vo+5W3qtHxtF/lICoHaCSB0aq8CHFiHwLjtq88f077TOsf5AAEIeCCwXDcgH1LrzgfVj2fCg0P4AIG5CCB05iLE+WoILLUH6W7xwyrsadUUSCkQgEAfBP6lvG9Xh+XjJHhYPLQPkGQtnwBCp3zGlDAbgVtssWYzfreSvFY7Q8VnY8U5CPgjcJFuUF6rx1nn+3MNjyDQJoDQ4Uqoh0Deavh+kQr/kPYt6nGCUiEAgYIIfEWPtI7SshJLCrKHGQgURgChUxhKDHVMYNx2kcz5jL4YH9txHhJCAALeCdym/+l3qv/Osfr/XuXdWfxrDgGETnPquv5Ib9T93kJ7rxwJj6kG63cIDyAAgRIIXKzHWS/X46wLS7CNSQh0TQCh0zUyMvREYMKerru9TyvvfXrKTyYIQCAmAuHh9KdthZZq2dSWxuQ4vqZHAKGTXp36imjcttQX3qckcg725Rje9EEgPJYIP15hv/2u9/maxxXtYcd36vjU7XZdAwt1LSzQwQ3WvJ+n92G1+fA9tLh13GwTvYY9nGOLn8C1qt0jNDrr5PhDIYJYCSB0Yq05736H+7ll9jL9oIUh4+FHjM03gZvk3g3a/7nmNQwfvk71d7328P4GPY64XT9YS1Wzy/W53G2JBNCoBM+kbabyN2ntA63XbVVwaBXcRn5so+Ph/QblOoP1vgnkdpLq6zWq1ev7toUBCHRJAKHTJTCSd0BguW2rNXK+qJRP7CA1SaohEGa2vVb73yQOrtCPTni9vPW6XO83t7Fq3CihlDGN2htoCZ77KKYHqYQHK64d9P4her9xCSVisjcCtyjb6yR2TugtO7kg0BsBhE5v3Mg1HYF2K87h+oH5iE6PTpeEY5UQuFGlXKz9D3e9Dtuf9eN/RyWleypkqVqETIJnUAIotx31Psy4vbt2BJAg1LLleoyV2ato3amFfiMLReg0stpLCHqZ7qgn7UuyTCtOCXhnMXm1zp2n/SLtf9APyMV6vHTdLOk5FQissPvZnRI8WUv0BOHzcO1BFLFVQyC07hwpsfONaoqjlCYTQOg0ufaLin3MnqcfjGNljhXGi2I6vZ2VapX4nVifr9fz9LjmPIma0H+GrQgCy207PXJ9rNjuJcZ7yWR49MVWLoFvqQv7q/XNcWu5xWC9yQQQOk2u/X5jv9kWqRvoZ2Tmhf2aIv+0BFbo6DnaT1dr2Tl6GBhETjjGVgWBMfVcGrTHif3eKu5x2nfVPlBF0Q0rI3SAf4lad85oWNyEWxEBhE5FoJMrZqm++AfseMW1XXKx1RdQ6DD8e+0/036aWmvOQdjUVxn3KDmsyzbf9lWdHKBz+2vf+h5pONArgXDtf0zX/NvEt3l9yXqlRr6OCCB0OsJEorsI5LrHHbd36MvoHTrG3e1dYHp+E4Z0/0iPS07T6xlqtQkdidliIDBuO8vNp6zZw3ImzP3Tf739QS1o/6624sv6N4UFCLQJIHS4EjonMGH31g9y6DwYmvLZeifwJ2U9WTLxFE2h9yuJxsneTZHTBYHwGHeB7ae6fJb8ebr2RS78itOJCbkd5tw5Lk738dobAYSOtxrx6s+4PUmuhUdVm3t10blfv5N/35GkOUk/gX9x7ivu9UMgV8+1Zfp/ye25MoPo6Z3lceL4Ws2SNN67CXJCoD31OhwgMDOB8KhqorUQ51EzJ+LMDARCy83xGlXybY0q+dsMaTicMgFET7+1Gx5hPUetO5f0a4j8zSVAi05z637uyMOok8y+pYSPnzsxKdYQCMO9w+O9E/TlHDoWs0GgTSCInnF7hv6nDtWBJ2unj1ubzFx/lynBK/X/FFqU2SDQNQGETtfIGpJhme2hxyzfUbTbNCTifsJcqcwnaf+yRo38jD43/aBsSN5lGrE1aS9StC/V/qCGRN1fmJmmshiyN+n/K/y/sUGgYwIInY5RNSjhhKZnz+0TinhBg6LuJdQJcTpKk8ydwIRnveAjT4vAUnuMfrxfqvad5+l6Cqu5s81M4FfidLAEz7UzJ+EMBNYlgNBZl0ezP+USNhP2WUF4WbNBdBz9VfpZ2r7j1CSEwGwExu2rOv2S2ZJwrkVgiVrDDlan/l/CAwKdEOAZcSeUmpBm3O6lEQ5nKlREThPqmxghEC+BsFr9Gbope3m8IeB5lQQQOlXS9lrWeGtBwwvVbB4mPWODAAQg4J3AfH1ffUFi59N6ZaJG77VVs38InZoroPbix+zZ8uFc7dvW7gsOQAACEOiGQK55diY0q/hS27SbbKRtFgGETrPqe91ox+0t6gQZRlYNrXuCTxCAAASiIfB4Pco63263B0bjMY5WSgChUyluJ4WFpt4x+7y8OcaJR7gBAQhAoB8CD9TUpuerZSesMs8GgXUIIHTWwdGAD2FNngn7oVpyXtGAaAkRAhBoDoFNW52Ux+2Q5oRMpJ0QQOh0QimVNMs0+d8G9guFE2ZlZYMABCCQGoEw99cJupk7OrXAiKd3Agid3tnFlXOp7aC5J0Kn413ichxvIQABCHRJILf/ltj5rEZkDXaZk+QJEkDoJFip9whpmT1KTbrn6Dgjq+4BhwMQgECSBHJ7teYG+5bEzgZJxkdQHRNA6HSMKtKE43pMNWlnyfvNIo0AtyEAAQj0RiDX9Blh+Pkttrg3A+RKgQBCJ4VanCmGcXu+Tp2ineHjMzHiOAQgkDqBvbS4zS800nSL1AMlvukJIHSm5xL/0fb06McrkPnxB0MEEIAABPoisLMe35+nR1nb9GWFzFESQOhEWW1zOD1mR7amRzf9a7NBAAIQgIDpO/H+eox/niYWfAA4mkWAH8LU6nvcjtIcOZ9MLSzigQAEIFAAgftoHNYvbdx2KsAWJiIhgNCJpKI6cnPc/kfpws4GAQhAAALTE9hSh8/UY6xHTX+ao6kRQOikUqPjreUcjkolHOKAAAQgUCKBzfQY63SJnT1KLAPTTgggdJxURF9utEXOW/qyQWYIQAACzSKwSGLnNMRO+pWO0Im9jhE5sdcg/kMAAvURQOzUx76ykhE6laEuoaAxTXNu1oSWnEsU5x9KIIhJCEBgdgKTOr169iTRn22LnQl7RPSREMC0BBA602KJ4OC4BE6W/MJ14Uv2gzZsj9TQ0CsjqBVchEBqBMb0PfNoBXVZaoGtF88ifcf8mNFY61FJ5CNCJ8aKHNMaLtbqfByj9535nNvf9fx8bxtpCbo7OstEKghAoHACw/Zr3WzsKrupT1sRlsk5jXl2Cr+CajeI0Km9Crp0YNxeoDusz3aZK67kuX3RlmuV9UWthUjj8h1vIZAigUz/kSP2eoW2n/brUgxxTUxbap6ds9VB+T4Jx9i40BA6MVX5hD1T7h4Xk8td+nq7mo+fa6P2cq1KM95lXpJDAAJlExixM9TSurP+T39QdlE12t9a8Z2lxUC3qtEHii6QAEKnQJilmhrTY5zcvqUy0qyz3C7QndSuEjknlsoR4xCAQH8EFtlN+j99hr6PXitDK/oz5jR3WC4it5+w6rnT+unSrTR/NLuE4D75uB7jZK07qAXufe3ewVxZPqBm8b1sof2j++zkgAAEaiEw2nqE/mh9N11RS/nlF7qzVj3/gQTPhuUXRQllEkDolEm3CNvLbXuZ+bH2RUWYc2bjVvlzgEROWJ/rTme+4Q4EIDAXgRH7vfqz7KZkobU5xW0vPUT/hsTOYIrBNSUmhI7nmh6zzTWDxWlyMcVnxRfpq2N3iZyfeK4CfIMABOYgsLmN6f/4eWseZaV3w5LZsyR2PjcHBU47JoDQ8Vo5uR7kWOtx1QO9utiHX1/RcNXH8KiqD4JkhYA3AuFR1oAeQZv9y5trffuT2eHqnHx033YwUAsBhE4t2OcoNNeDnGX2Nf3dc46UsZ2+UzG9Und/h+k1zU6MsdUI/kKgSAJDGlRgaqk1+0WRZl3YyjUTfZjegy06Aggdj1U2ockAc3uOR9f68GmJhqU+Xi05X+jDBlkhAAHvBEbsev2f76ubmRTn+/qKLbV/814F+LcuAYTOujzq/zShOWTM3ly/I4V6cLH64zxK3anPLdQqxiAAAZ8EMlslsfNaiZ0wi3tK/Xbm6/HcyRI7O/gEj1fTEUDoTEelrmPjugvKE7sLChOLLbPHqj/OVXVhpVwIQKAmAsPqxJvbk1T6zTV5UEaxG0vA/UhiZ9MyjGOzeAIIneKZ9mbxNk1QZa3J8ub1ZsBlrjA/zrOY5dhl3eAUBKohMKolFVa3+hv+tZoCKygls/upZedEibj5FZRGEX0SQOj0CbCQ7DdqntF5rRFWGxdir34jk7rjeZVETpgfJ6xAzgYBCDSZwGJNKrhaq6BnSa1f93i1Vn+iydUaS+wInbprKtd9wUI7QW48tG5XCip/ub7Mnqnn858vyB5mIACBFAgs1oIKQ3o8b5qAL5UtVx+kCd3UsbkmgNCpu3rGNWTR7Gl1u1FQ+TdJtu0jkXNKQfYwAwEIpEQgs5X6fnihQvpIMmHl9klNmbhPMvEkGAhCp85KHbOD1PrxtjpdKKzszP6mcRZ76o7twsJsYggCEEiPQKaeLSP2nwrsjYkEN1/f49/SY6xtEoknuTAQOnVV6VJ7kP45vlpX8QWXe6ns7WUbSeywQQACEOiEwIh9XJLn+UqawvDzLdQb8TuKZ0EnoZOmWgIInWp5t0vL1Xg7YN/Th9E6ii+4zAv1Dx4eV/2rYLuYgwAEUicwav+nG75nKczlCYS6h1p1Pp5AHMmFgNCpo0on7H9V7I51FF1wmWfp62k/TQSY0hwZBSPCHAQgMCuBYTtVLSEHKM3SWdPFcDJ0Th63l8TgapN8ROhUXdtjdoSKDM21sW+nqBXnAK2vPhZ7IPgPAQjUTCDMtZPppsnsppo9KaL4z0ns7FSEIWwUQwChUwzHzqxM2G76Z05htEEQOQcrFhbm7KzmSQUBCMxFYNh+rSRP0B672NlQMZxoS9Tlms0FAYROVdUQJgU09cy36DurrRU5K6tCRzkQgEBDCIzYJYo0BbGzg0agfqYhteY+TIROVVW0sLXmywOqKq6kchA5JYHFLAQgsIZAOmLnxXqEdSj1Wj8BhE4VdTBhh6mYQ6ooqsQyEDklwsU0BCAwhUA6Yucz6mL94CmR8bYGAgidsqEvtR00ouBTZRdTsv2frOmTw+OqkkFjHgIQWEPgbrFzS8RMhjSVyP/pN2CDiGOI3nWETplVGFa2HWitYzVUZjEl2/6FRM6z1fEYkVMyaMxDAALrEQhiZyD6oee7aD2s964XGR8rJIDQKRP2uL1b5ncvs4iSbV8oefN0iZxlJZeDeQhAAALTExiyX2lS0gN1MuZJBf9DE3E8YfoAOVo2AYROWYSX2mMlEI4qy3wFdi9Vc+uBtondXkFZFAEBCEBgZgKL7Jf6Pj1YCWJdLiKT/8fZbbbxzEFypiwCCJ0yyIah5AP2dZmOle/V+qd8sqK4sQw82IQABCDQNYFh+5Fuvl6sfJNd5/WRYWubp9G3bJUTmFd5iU0ocEP7qMK8b6Sh3qovk/011RVrV81dgUN69v7MuZORAgIdEMht2w5SNTtJWBtr3O4lCLGuKfVcPcL6jm4iT2x2RVYbfVZtcQ0obdyepCh/GmmkK3Sv9EStXXWOO//H7PtqZXqGO79wCAJpE7hdNz0buQtx3D4gn97szq/OHLpJN5MPpcW8M1hFpIr10UoRsRdv42ZJBLMvFm+4EouT+ud7gUuRU0n4FAIBCERDYLjV/zF0D4hx20ydGj4bo+Ox+ozQKbLmFrTWsbpPkSYrs5Xb63WH8b3KyqMgCEAAAr0SyHRbNmyHK/vZvZqoNV+ujtXjSSzuXCvGTgtH6HRKaq504ZFV1vrHmyulv/OZ1mQZtU/7cwyPIAABCMxAIMzttcoO0tnLZkjh/fCn1V9nC+9OpuAfQqeIWsy1fJvZF4owVYON0+X962solyIhAAEI9EdgI7tVI5kOkJEYVzzfRDfHH+sPALk7IYDQ6YTSXGkm7D1Kst1cyRyev0yzUjxX/2yrHfqGSxCAAATmJrCh/V2DKELLToxz7ByiR1j7zx0kKfohgNDph17IO2G76e8b+jVTQ/5b1Oz7VE1fdVsNZVMkBCAAgeIItCcUfG1xBiu19Dn1OIp5maBKYfVSGEKnF2pr8+Q2qAv08/o4uPZQJK9hhNXBGjT6t0j8xU0IQAACsxMYtv9V6/RnZk/k8ux2umH+b5eeJeIUQqefipywI5X9Ef2YqCnvW9T5+KyayqZYCEAAAuUQGGq1rsf43fZ6iZ1dy4GCVYROr9fAhN1bdw/xqfBMs3IOt4bB9xo5+SAAAQj4JJDpgXxu/y7nrvXp4IxeDaqf0WflO5P4zoio9xMInV7Z5fYhXZQjvWavKd+fdNfwUv0r5TWVT7EQgAAEyiUQ1ugbaC0AurLcggq2ntmetkzfz2yFE0Do9IJ0zPZWtkN6yVpjnjHdMTxLszaM1+gDRUMAAhAon8CQ/Uo3dPFNm5HbMaxwXvzlgdDplmmuWRti7PCWazLDRfbXbsMlPQQgAIEoCQy3Vgo/ITLfN7f59t7IfHbvLkKn2ypqd0DesdtstaYPI8NG7du1+kDhEIAABKomsMxepSLjmjk5l8/jtnPVqFIuD6HTTe2O2eZK/q5usjhIe6l6EsU4z48DdLgAAQhETaD9qP45imFFRHGE3+WPR+Sve1cROt1U0YD9l5Iv7iZLzWmXqV/Oc/SoLaZ/8pqRUTwEIJAUgRG7RN+Bb4wspsdr4MjTI/PZrbsInU6rZsweqrFKr+g0uZN0R6hfzl+c+IIbEIAABOohEPrr5PaDegrvsdTcPiyfF/SYm2xTCCB0psCY9W3WmnsmnhmQM/uuHll9ZdaYOAkBCECgKQRye5lC/VdE4T5QrTqxLmvhCjNCp5PqGLcnK1lMC69dp2U6X9lJaKSBAAQg0AgCi1ornL84sljfyXDz/msMoTMXw1xTT5maEGPaMt25LLKbY3IZXyEAAQiUTmDEzlAZnyi9nOIK2EgTmry1OHPNtITQmaveJ+yFSvKwuZK5OZ/rWfSw/diNPzgCAQhAwBOB4ZZwiGnI+ZGaMXkbTwhj8wWhM1uNtTuCvWe2JK7OZXaF+uX8pyufcAYCEICAJwKZLVc7/Uvk0mpPbs3iy4YaPfvuWc5zag4CCJ3ZAE3Yq3V6u9mSuDq32g7TMMoJVz7hDAQgAAFvBMISEbl9wJtbs/hzqI3ZQ2Y5z6lZCCB0ZoKzpLVg59EznXZ3PNPKt4vsl+78wiEIQAACHgmMWGitj+URVhjx+z6PGGPwCaEzUy0N23/o1GYznXZ2/BpNCUiHNWeVgjsQgIBjApndoUdCh8nD3LGXd7uWaVHmCdv17gO865QAQmc6UrfaRrr0Y5pJ8xW2qS2dLhSOQQACEIDADAQW2Xk686kZzvo7PBndEkQuGCJ0pquGea21oWJZ6uE4PWT7yXRhcAwCEIAABOYgsMzerhTXzJHKx+nMnkGrTvdVgdBZn1lozcmiWQTzVrU8Mcpq/TrkMwQgAIFOCYSFPzN7XafJa09Hq07XVYDQWR9ZTK05mfrljNqN64fAZwhAAAIQ6ILAsH1fN41xrIVFq04XFdtOitCZiiyu1pwLbcj+d6r7vIcABCAAgR4JzLMjlXNZj7mrzhbPiOCqyUxTHkJnKpQFdoQ+xtA3Z1JNra/WPjnVfd5DAAIQgECPBBba1cr53h5zV5st1wgs5tXpmDlCZy2q3Baq6fINaz+6fs3sWC3z8DvXPuIcBCAAgdgIDNtHdQN5RQRuZ/LzLRH46cJFhM7aahi3w/V207UfHb/eYnfaOxz7h2sQgAAE4iQQ5taxSG54zQ7RYhbbxgm6Wq8ROoF3bvOljv9fteh7LC23d2pc2K095iYbBCAAAQjMRmDYTtXpGBZGnq/OC4y6na0u15xD6AQQE1LGZvdZw8Tzy581Z87nPTuIbxCAAASiJ5C3Zsb3v+hnbi+z222T6HmXHABCJ1dbjkWiijP982W2quRrAvMQgAAEmk1g1P6s79oYbiqHbNBe2ezKmjt6hM6E7SdMD5sbVe0pfqIOyDE0p9YOCgcgAAEI9E1g0t4tGzEsrXOEul8s6DvehA2E1oxmb+Mt8bC/cwiTupB31uSAf3TuZ3nujbXEaCyLrJbHAcsQqJJArhbkRXZOlUW6Kmu8tVjy+135NL0zL1K3huOnP8XRZgudMA9BZn+K4DL4mi7iQyPwExchAAEIpEMgTDsyYX9XQFs6D+oi/Ubs5tzH2txr+qOrGObNWalnsO+s7QqhYAhAAAJNJZBpAHfWeoTlncCumkBwL+9O1uVfc4VO6Kme2YvrAt9FucfqnuLqLtKTFAIQgAAEiiIwZF/Sb4X/SQQze01RIadmp7lCZ9AOU2Vu6LpCM62qOxnJlOSuQeIcBCAAgR4JhJGuk1FM0nqQfjHu1WOUSWdrptDJbUAK/VXua3bSPqKOgDe59xMHIQABCKRMYMS+rfD+7DzEMPHty537WIt7zRQ6E/ZEjWK6fy3EOy90qe4jPt55clJCAAIQgEApBMICyrm9pxTbRRrNNadObvOKNJmCrWYKnTyKZ5nH2sZ2WwoXGTFAAAIQiJ5AHK0629gyOzB61gUH0DyhExZBy9xfCBO6f/hwwXWNOQhAAAIQ6JVAPK06h/caYqr5mid0Ju2lqkzvcX+avjmp/ssRFwQgEC2BETtRN8p/c+7/U9Sqs7VzHyt1z/sPfrEwQifkvCV0irVbrLUVtOYUCxRrEIAABAohkFlY6POYQmyVZyT8zh1anvn4LDdL6EzYE1RF27mupkxzNjDSynUV4RwEINBgAkN2nKK/1jmBl0rsNHvlgykV1CyhY1rS3ve2Wm1OH/HtIt5BAAIQaDCBzFYq+k+4JhBGFY/bPq59rNC55gidMBOy2UEVsu2lqG9rFuR/9JKRPBCAAAQgUBGBlfa/KmmsotJ6Kybj8dVacM0ROgP2PAXtfSn7D66tGF4hAAEIQMApgU3sdnn2Bafetd3KdGMfFiVlcz/6qMgqemGRxkqwdaZWn/19CXYxCQEIQAACRRMYaD2+Cp2TfW65flHG7Rk+navWq2a06Kyw+6lb1qOrRdtlaZl9ssscJIcABCAAgboIDNk1+l35Xl3Fd1RuZi/qKF3iiZohdFbbIc7r8UobslOc+4h7EIAABCAwlcBq+9TUjw7fP0k9iTZ36FelLjVD6OTm/bHVJ3VnMFlpzVMYBCAAAQj0R2CR/VIGLu7PSKm5w7pXzy21hAiMpy90Jmx31cMOjutiQoMVv+zYP1yDAAQgAIGZCHjvdtAeiDOT9404nr7Qye05rmsyt29o4Hvowc8GAQhAAAKxERiyb8plv9/huT3WJuzesWEt0l+ETpE0e7E1YJ/vJRt5IAABCEDAAYFMK0tl9nUHnszkQugY8eyZTjbheNpCJzy2yjTiyu/2Oxu23/p1D88gAAEIQGBOArnzOXUGmt1PJ22h4/2xVUZrzpxfICSAAAQg4J3AiF2iyfkucOtmbo/R6Kst3PpXsmMInZIBz2g+01ROy1rPdmdMwgkIQAACEIiEwIDrQSUDmh7Y+xJIpVV0ukJn3HZx/dgqtxM1u8FYaTWLYQhAAAIQqI7ACvuWClteXYFdlpTb07vMkUzydIVOZge6rqXcjnPtH85BAAIQgEDnBDa1pUrseabkfW2JloVo4Jau0Mldr/FxpS63nzfweiNkCEAAAikT+Krj4BZoic8nOfavNNfSFDrjtqWIPaI0av0azjUUMVPXNTYIQAACEEiHwLCdqWCucxtQ1szHV2kKnfZjq8ztxTbpes4Ft9hwDAIQgIBrAu2lfP7PsY8H6hZ70LF/pbiWptCZtKeVQqsYo7+yxXZ5MaawAgEIQAACrghkrkfTbqru0o9yxasCZ9ITOrkt0GOh/Spg12sRJ/aakXwQgAAEIOCcwLD9Wh76vZldbU92TrBw99ITOuNa18NsqHBSRRkc1LByNghAAAIQSJdA3hpq7jU+hI7XmunYr8yxWs3sXPV6v7rjWEgIAQhAAALxEcjsO26dzvTo6jbb2K1/JTiWXouOOR4+N+la5ZdweWESAhCAQAMJjNgf1On3704jH1B3ZM/dOwrHlpbQaa/lsWvhlIoyOGgnFWUKOxCAAAQg4JhA5ribgucnHyVUaVpCJ7MnlsCoKJO/Vc+ha4syhh0IQAACEHBMYMD5LMmO0RXtWlpCx+zxRQMqzF5mJxdmC0MQgAAEIOCbwMLW6KvrnTq5vYaZb+/Ut8LdSkvoZLZP4YSKMpgjdIpCiR0IQAAC7gmE2e9z+6FbP1c7/r0sGFo6QmeZbaOL6v4F8ynK3D+0ttXFRRnDDgQgAAEIREBgwH7g2Mt9HPtWqGvpCJ1Jx+o0c6zqC72cMAYBCEAAAncRGLKf6f2Kuz77erOPL3fK8yYdoWOOhY7ZT8urQixDAAIQgIBLApl6wpj9wqVvZtvJu+2c+laoWykJnTAjssftDo22OsujY/gEAQhAAAKlE/B7o7u6tZJA6QDqLiANodOe5fHBdcOcofxfau2tZTOc4zAEIAABCKRMIHfcop/ZY1JGvza2NITOfNtzbUAOX3/s0CdcggAEIACBKgiM2h9VjM851HKEThWXQDFlTLpufju9mCCxAgEIQAACkRLw+juwsy3RmODEtzRadDK3LTo32bBdmvg1RHgQgAAEIDA7gTNnP13b2UEtNP2o2kqvqOD4hU6u5cky26MiXt0Vk9nP5VveXSZSQwACEIBAUgQG7Gy38YTVzBPf4hc6Y/ZASQmfTW+Tji/uxC9swoMABCDghkBY5zCzv7nxZ6ojme0+9WOK7+MXOgOuK+nsFC8aYoIABCAAgS4J5E5vfHN7ZJeRRJc8fqFjboXOzWpnCr3t2SAAAQhAAAI/d4pgOxuzzZ36VohbKQidRxRCongjF9A/p3ioWIQABCAQJYHVdr5bvxN/fBW30MltQGJiV5cXT2bnufQLpyAAAQhAoHoCi+0KFXpj9QV3UCJCpwNIdSVZqtXK/XZERujUdV1QLgQgAAGfBC7w6Zbt4tSvQtyKu0VnwHYqhELxRlarf86vizeLRQhAAAIQiJZAZj6FTm4Pi5ZpB47HLnS8Vs4leqQ20QF/kkAAAhCAQFMITDoVOmYP0tORDVKthriFjjlt0cntN6leMMQFAQhAAAI9Eljp9rdhULfmD+kxKvfZ4hY6ue3olPDvnfqFWxCAAAQgUBeBTW2pWvtDp2SP284enSrCp3iFTm4LBOBBRUAo3Mag/bZwmxiEAAQgAIEUCFzkNAivXUH6xhWv0BlviZzBvgkUb2C1Fkn7Q/FmsQgBCEAAAtETyO13LmPIbQeXfhXgVLxCZ1BrXPncLlPT5HKfruEVBCAAAQjUTMBni06G0Kn5upim+Em3QueSabzlEAQgAAEIQCAQ8NriH+alm5diFcXbomNO1Wdmf0rxQiEmCEAAAhAogMCIXS8rtxZgqWgT89RVevuijXqwF7PQeYAHgPfwITNadO4BhQMQgAAEIDCFwKVT3vt5O88e7MeZ4jyJWej4HHF1p/m8gIu7ZrAEAQhAAAL9EMidtvznbruE9ENbi2LGuOW2odze0qHrd9gi+7tDv3AJAhCAAAT8EPDZxSGz+/pBVJwncQqdMbfPES/XiKvVxVUPliAAAQhAIDkCmf3ZZUy529/WvnDFKXQGbLu+oi4rc05rTllosQsBCEAgGQKDbmdH3j4ZxlMCiVPoZE6Fjt+pvadUOW8hAAEIQKBWAhva1Sr/zlp9mL7w7ac/HPfROIWO1+a1zC6P+3LAewhAAAIQKJ1Au4vDlaWX030Bo3a7bdJ9Nt854hQ6Ztu6xJojdFzWC05BAAIQ8EfA543xoNPf1z7qL1ah43HEldkqu7KPuiArBCAAAQg0hUDmtE9nZlulVgWxCp2tXVbEYrvWpV84BQEIQAACvgjkrX46vnxqe+Pz97UPUrEKHY8tOjdoaPkdfdQFWSEAAQhAoCkEcrvGaagef1/7QhWf0GlPFrhRX1GXk9nrRVtOtFiFAAQgAIHeCXht0Zk0WnR6r9WCcq5w+vzQrzovCDxmIAABCECgMALz3Lbo0EensEru1VBu9+o1a6n5BuyfpdrHOAQgAAEIpENgoV2nYHKHAfn8je0DVIyPrryO8b++j3ogKwQgAAEINIlApnG6Zje6CzmzTd351KdDCJ0+AU7J7u+CneIcbyEAAQhAwB2BJe48MoRO/XWSu5218Yb64eABBCAAAQhERMDjk4BN9EAtvkaQWSo9xmA2nyWe+k5l5lGZ18eDkiEAAQhAYC4CPp8EjKfVqjNvrlpwd35ALToeu2+ttl1twmlHaXeViEMQgAAEIKDfskUuKeQtoeNThPUALD6hk9toD3GWnyWzz7gUYOVHTgkQgAAEIJASgXm2OKVw4nt05VUBp3RVEAsEIAABCDSXwKSNpBR8fEInc9qik9JVQSwQgAAEINBcAon9zsYndMyGm3v1ETkEIAABCECgZAI5j65KJjyneYTOnIhIAAEIQAACEOiRgNe+sD2GE2OLjs/OyD1WANkgAAEIQAACrghk9NGpuz42qNsByocABCAAAQgkSyC3DVOKLcYWnYUpVQCxQAACEIAABJwRGHTmT1/uxCh0+gqYzBCAAAQgAAEIzEKAUVezwKnmFJ2Rq+FMKRCAAAQgAIHoCcTYohPfbM7RXyYEAAEIQAACDSKQ1KCfGIVOg641QoUABCAAAQhUToA+OpUjp0AIQAACEIAABCDQAwFadHqARhYIQAACEIAABOIggNCJo57wEgIQgAAEIACBHgggdHqARhYIQAACEIAABOIggNCJo57wEgIQgAAEIACBHgggdHqARhYIQAACEIAABOIgEKPQyeNAi5cQgAAEIAABCNRNIEahs7RuaJQPAQhAAAIQSJjAbSnFFqPQSYk/sUAAAhCAAAQgUCKBGIXOeIk8MA0BCEAAAhBoOoFVKQGIUegkVQEpXUzEAgEIQAACCRDILakGhRiFzrIELiNCgAAEIAABCPgkMGB3+nSsN69iFDpJKc3eqo1cEIAABCAAgZII5DZRkuVazMYodMZqIUWhEIAABCAAgWYQYNRVrfWcG0Kn1gqgcAhAAAIQSJoALTo1V29mt9fsAcVDAAIQgAAE0iUwwKOreis3S6s3eL0wKR0CEIAABCCwHoHJtH5n4+ujM2lJPTtc7/LiIwQgAAEIQKBuArfU7UCR5ccndDK7uUgA2IIABCAAAQhAYAqBAUPoTMFRx9sb6yiUMiEAAQhAAAKNIDCE0Km3nmnRqZc/pUMAAhCAQMoElllmK1IKkEdXKdUmsUAAAhCAAAT6I5DUY6uAIj6hcyd9dPq7hskNAQhAAAIQmJFAct1D4hM6i+xfM1YPJyAAAQhAAAIQ6IfADf1k9pg3PqGTWVjUk9mRPV5N+AQBCEAAArETuC72ANb3f976ByL5HFp1dnDo65MsT2vVV4eMcQkCEIBA/AQG7DH6vXifw0Cud+hTXy4hdPrCt17mVfZ328j+tt5RPkIAAhCAAATWJTBmO2p0k78tT697SHyPrtqXhU/FOc8e4O+qxSMIQAACEHBHILP7uvOp7RB9dJxUzDVO/FjXjRyhsy4QPkEAAhCAwLQEMtt+2uN1Hxy0a+t2oejy42zRye2qokEUYi+z+xViByMQgAAEIJA2gdyp0PH6+9rH1RCn0BmwK/uIubystOiUxxbLEIAABNIi8ECH4ay0IUtu1FWcQmfSqdChRcfh/y0uQQACEHBGYNy2lEeLnHll6hx9jfbcnV99OhSn0BlxKnSMPjp9Xo9khwAEIJA+gdzl9CgmiXNlivDjFDrtSQM9TlO9oaYz3CbFC4WYIAABCECgIAIDToWOOe3/2if2OIVOO+i/9xl7Odlz26kcw1iFAAQgAIEkCOT2YJdxZJoLLsEtZqHzV5f1gdBxWS04BQEIQMARgR0d+XK3K5N22d0f0nkXr9DJ7HKn1bCzU79wCwIQgAAEfBDw2fLv93e1r1qLV+hM2l/6iry8zD4v4PLixTIEIAABCHRKYKltqqRbdZq80nTDdkWl5VVUWLxCJzOfj67MHqqe6/Mrqj+KgQAEIACBmAhkbvtxXquh5RMxoezU13iFzrDbR1fzdKk8pNMKIB0EIAABCDSIQGa7OI02ydacwDpeodMeYu5zKQgz+uk4/U/GLQhAAAI1E9i95vKnLz6zS6Y/Ef/ReIVOm/3FTquAfjpOKwa3IAABCNRM4JE1lz9T8X+c6UTsx+MWOrlbBbpH7BcG/kMAAhCAQMEEbrRRWdyhYKvFmFttlxZjyJ+VuIWOuRU6j1SH5Hn+qhuPIAABCECgNgIb2q4qO6ut/NkKXoXQmQ1Pnee8KtAhLQVBP506rwzKhgAEIOCNQGZeW/uvsU3sdm+4ivIn7hadkdYsjncWBaNQO5O2Z6H2MAYBCEAAAnETyO3RTgNItiNy4B230MksiByfrTqZPcbpBY1bEIAABCBQB4HMHltHsXOWmdtv50wTcYK4hU4A77WCMlp0Iv6/wHUIQAACxRK4ze4vg1sUa7Qga4N2UUGWXJqJX+gMOFWiuS7qMacXtctLEacgAAEIJExgnuNW/szp72hBl0P8QsfswoJYFG9mgFad4qFiEQIQgECUBPZ26vVNttCudupbIW7FL3SGWkPMVxZCo2gjue1VtEnsQQACEIBAhAQy28ep10n3zwnM4xc67Q7JXmdI9nphO/1/wy0IQAACCRJYZtuoP2noo+Nvyx0/FSmIVvxCJ4DI7IKCeBRtZlfNTLBJ0UaxBwEIQAACERGYtP3cejtg57v1rSDH0hA6uZ1XEI+izQxofmQeXxVNFXsQgAAE4iLweLfu3um2oaAwZGkInUG3QidUlF8lX9hlhCEIQAACEJiWQN5a8uGJ056r/+BfbCO7tX43yvUgDaGz0K4SpuvKRdWz9f17zklGCEAAAhCIm8CE7aQAtnIaRPKPrQL3NIROiCSzc8KLuy10QFth93PnFw5BAAIQgEAVBPze7GZ2bhUA6i4jHaHjt5+OaaGKp9Rd0ZQPAQhAAAK1EPArdFbZz2shUnGh6Qgds7MrZtd5cRlCp3NYpIQABCCQCIGbbZEieZzTaP5pi+0Kp74V6lY6QmfYwlw6XjtV7as5FIYKrTmMQQACEICAbwILLLTmzHfq5NlO/SrcrXSETmaTEhO/KJxQMQY3tGXmtdd9MRFiBQIQgAAE1iWQ2dPXPeDoU+b4KUjBmNIROm0wZxTMpzhzueMLvrgosQQBCEAAAoFArlnUzA5wC2MVQsdt3czh2FlznK/z9IG68FMTlnXypGwIQAACfgmMt/rmbOzUwWub0j8n8E/rh3fE/qiYlji9sLawMXusU99wCwIQgAAEiiQwYM8u0lzBtk4v2J5rc2kJnUxtJmY/dUt80J7r1jccgwAEIACBYgiE1vvcsdDJHf9OFlMD61hJS+i0QzttnQg9fQgXfns6cE9e4QsEIAABCBRJoN1673U25Fy/Qz8rMlzvttITOrkFoRNadjxuW9ly28OjY/gEAQhAAAIFEfDdev8bze5zc0GRRmEmPaEz2uqj83u39HN7gVvfcAwCEIAABPojkNugbrUP7s9Iibkb9tgqkExP6ISocvtReHG55eqnE/4R2CAAAQhAID0CE7avgtrSbWCDdqpb30pyDKFTEthZzG5hE7bfLOc5BQEIQAAC8RLw3Gq/xBbahfGi7c3zNIXOqF0gHF6HmYeaen5v1UUuCEAAAhBwS6C91I/nYeWnWlhFoGFbmkKnXZF+m+ey1uir4YZda4QLAQhAIG0CE/YMBej3uz2zH6RdAdNHl6bQCbF6rtDcRvT4yrPqn/5q4SgEIAABCMxG4LDZTtZ87g4tLd2oiQLX8k5X6Ay1hpmvWBuow9dDHfqESxCAAAQg0AuB5badsoWOyF6309UAMOHVuTL9SlfoZFov3FxPirSP5tS5b5mVi20IQAACEKiIwCoLrTlZRaV1X0xmJ3WfKY0c6Qqddv1823E1Zdb+x3DsIq5BAAIQgMCcBMKSD5kdOme6+hKs0u/N9+srvt6S0xY6K1sdr1bWi3iW0jN7mebUmTdLCk5BAAIQgIB3AhP2JLm4rWM3z9Bq5bc49q9U19IWOpvY7aLnd+0rs630gO3AUmsY4xCAAAQgUC6B3F5dbgF9Ws/sxD4tRJ09baHTrhrfFZzbK6K+gnAeAhCAQJMJhE7Imesb1vDYqrH9c8Klmb7QWW0/VJyrHP8f7m+32f0d+4drEIAABCAwE4HV9kqd8vxb+rMmP7YK1ea5cma6rLo73n4u+ZPuMlWaOlMvnSMqLZHCIAABCECgfwK5LZCRw/s3VKqF40u1HoHx9IVOqITcvFf0ofLR72yaEVzIuAgBCECgcgITdojK3LzycjsvcEL9QE/uPHmaKZshdEZao6/GHFfhRroYX+TYP1yDAAQgAIF7EnjjPQ+5OnKybWHjrjyqwZlmCJ1MU/OZfa8Gvp0Xmdsb1Krjd7KpziMhJQQgAIH0CYzZExTkzq4Dzdw/zagEXzOEThul98dXO6hV56mV1DqFQAACEIBAfwQye1N/BkrPfUNT17Zan2xzhM6wnang/7U+AFefc/tPV/7gDAQgAAEI3JPAmD1UBw+45wlXR76uZwSeRxxXBqs5QiezST0a+mplZHsraG8tufaI3rKSCwIQgAAEKiGQ2ZtVju+uBpP2pUpYRFBIc4ROqIxJ+0oEdfKWCHzERQhAAALNJLC8tdRDGG3ld8vsPFtkf/HrYLWeNUvoLLYrhPfsahF3WVpuz7Yxe0iXuUgOAQhAAAJVEJhsdTGYX0VRfZTx5T7yJpe1WUKnXX3eL4BMDaK06iT3r0ZAEIBA9ASW2mbqAvFy53GEuXO+7dzHSt1rntAZtu+IcFjs0/P2Qg2I97wSrmd2+AYBCECgHAIDrdacDcsxXpDV3L6hKQw9zxtXUKCdm2me0Alz6mT29c4R1ZJyUH3l31ZLyRQKAQhAAAL3JBBacyyC5Xoy++w9nW/2keYJnVDfk3as+2rP7DBaddzXEg5CAAJNIdBuzfG9VE9u59uI/b4pVdJpnM0UOqP2JwE6u1NINaWbb6vtPTWVTbEQgAAEILCWwIRtpbf+F1+mNWdtja3z2kyhExDk9pl1SPj88EL1JnqAT9fwCgIQgEBDCOStASK+W3PMbtLS0Cc2pEa6CrO5QmektaLrdV3Rqj7xoA3af1VfLCVCAAIQgECLwHLbTq+viYDGF9X/9I4I/KzcxeYKnczu1EXx+cqJd1/g87X27MO7z0YOCEAAAhDom0C7C4H3eXPutAH7dN+xJmrA9xTWZUMf0wL2mV2tYjYou6g+7f9YHcy8r6vSZ4hzZB+zfeZIwWkIQKBoArld3+gZdsfsYfqNuFhYvf9WfkO/ES8ouvpTsee98srnPG5fVCEvK7+gPkvI7fE26r4DdZ9BzpJ9XL2q2CAAgaoJfE0/oIdWXaib8sbtFPlyoBt/ZnIks0eqf85vZjrd9OPNfXS1tuZz+/jat65fM/uwfuqpL9eVhHMQgEAyBMbtiYrFv8gx+yUiZ/arjh/OUbtUiE6bHZOLs7trZfMXuvAEJyAAAQikTCDXMBCzj0QRYmYfjcLPGp1E6LThx3KhvF+tOkM1Xi8UDQEIQCB9AsvscAW5UwSB/kW/CD+IwM9aXUToBPzDrRadGGaT3FqLtf2/Wq8YCocABCCQMoFbbLFuKP87khA/qG7Sk5H4WpubCJ2APtNlndsHaquFbgrO7SgtDRHmdWCDAAQgAIGiCSxorTO4edFmS7B3jW7STyjBbnImETprq3REy9pn9re1Hx2/bij9HsujNscYcQ0CEIDAegTG7KE68sb1jnr9+BH9Zq306pwnvxA6a2uj3fwXS6vOQZpEMIwIYIMABCAAgSII5JINWWvSPe+TA4Zob1ZrTpgaha0DAgidqZCG7Gv6+K+phxy//6Qet3mf6NAxPlyDAAQgMIXAhB2iT4+fcsTz2w9LlE14dtCTbwidqbXRbgb80NRDjt8/WB2T3+LYP1yDAAQgEAeB0AE5luHkoTVnGcs9dHNhIXTWpzXcWv/q+vUPu/ycq9Mcq5u7rBqcggAEIiKwgb1X3t4rEo8/rMWLxiPx1YWbCJ31qyHTmCaLZARWWKNr0D63fgh8hgAEIACBDgkssz3VDSCG1clDQLTmdFitU5MhdKbSWPu+3apzzdqPzl/3lbY/1LmPuAcBCEDAH4HQz3Gy1ak3lt9CWnN6uIpiqdweQusjS2jVyez9fVioOuvHJHa2rLpQyoMABCAQNYHx1pw5O0YSwxL65vRWUwidmbgN2Zd16uqZTjs7vpGaXo915hPuQAACEPBLYFxLPGQtoePXx6me5epHRN+cqUQ6fo/QmQlVewTWO2c67e54Zs+0MXuOO79wCAIQgIA3Au1FO78it+Z5c20Gf/5hI62BMjOc5vBsBBA6s9EZtq/rdFjdPI4tU8dkHmHFUVd4CQEI1Edgmb1Vhe9enwNdl/xOtT4xC3LX2NoZEDqzgQuzJcfUtGm2icJhtszZ6pRzEIBAswlM2G561P+uiCBcrFmQvxGRv+5cRejMVSXDdorEzrlzJXN0/qmaL/NljvzBFQhAAAI+COS2oUTO8XImlkdWYdHpt2pnhfI+riCETifwVtubO0nmKM3H7Ta7vyN/cAUCEIBA/QQmWnOkPaR+Rzr24DS15vyo49QknJYAQmdaLOsdXGTn6ci31zvq92Oubmvz7ATducRz1+KXJp5BAAIpEBi3fRXG6yIKZbW+w98Ukb9uXUXodFo1g611pVZ0mtxBuj3UMfm/HPiBCxCAAATqJTCmgdnWGlxSrx/dlJ5plNWo/bGbLKSdngBCZ3ou9zy60K7UwY/d84TjI5kdpSHn+zj2ENcgAAEIlEsgVw+XzL6mQrYqt6BCrd9qqy2e6U0KDb14Ywidbpgut/9R8hu6yVJz2gH9g39DYifczbBBAAIQaB6BCftPBb1/VIHn9m5bpHWt2AohgNDpBuPmkgzWmn+hm1x1p91KYud4PeulruuuCcqHAASqJRAW7LSolvMJfP6iXpafrRZU2qXx49dt/Q7bVyUaLug2W83pn6g1Ut5Wsw8UDwEIQKA6ArfZxhqU/U0VGNegjEwdkDNbVR2o9EtC6HRbx1mrbeQ1yhbXvAa5OiaP237dhkt6CEAAAtERCC3Y81rz5Wwfme+naDj5jyPz2b27CJ1eqmjYLpLi/lwvWWvME+r6/7Qu+7Y1+kDREIAABMonMN6a+fiA8gsqtIRlNmhHFmoRYy0CCJ1eL4Q77WhlvbHX7DXl21Q9+b+rNqkNaiqfYiEAAQiUS2DCDtSNaIwjlt5lC+2qcuE00zpCp9d638huVdY395q9xnyP0BIRx9ZYPkVDAAIQKIfA7fYA3ciFxZhj2y7RI6uPx+Z0LP4idPqpqeHW3Axn9WOiprwvVX+d19dUNsVCAAIQKJ7AjZpeb9BOkuGNijdewCwmgwAAIQhJREFUqsXQo+gVdEAujzFCpx+2oWPyanulTNzRj5ma8n6Uzsk1kadYCECgWAK5JM7C1grfDyvWcAXWcvuCDUU3krcCMMUVgdDpl+Viu1xK/D39mqkhf6j7E22pPaiGsikSAhCAQHEEJlqTuR5YnMHKLN2ggeRHVVZaQwtC6BRR8UP2IZm5tAhTFdvYSE2mP5TY2bTicikOAhCAQDEExu1QGfp/xRir3MobNdvPbZWX2rACETpFVHhmd0owHC5Tcc2t0479gWr0/b4ewi0oAgU2IAABCFRGYKn9m8r6QmXlFVlQbidrBuQwoSFbyQQQOkUBHrJfydQHizJXqZ3cHqeRWF+W2MkqLZfCIAABCPRKYKk9WDeY31f2+b2aqDHfbfq2fVWN5TeqaIROkdU9rIXYzP5YpMkKbb1AnZPfW2F5FAUBCECgNwITWol8wH6izJv0ZqD2XG9Ua871tXvREAfmNSTOasLMNPpqQs+L22thDVZTaIGlZFoPa8yu0yDNTxdoNWVTP9Rd2ZdSDpDYKiSQ2wkqbajCEuMs6mat653bj+T8dnEGYKdK5Hw1Ut+jdBuhU3S1DdtvJBY+oB/AOBfRzOwTa8TOd4tGk6C9v2mSr9B0zgaB/gmMq68f2+wEQl/CCfuOEj189oRuz94szw53612ijvHoqoyKHWkNN/9DGaYrsDkgkXaCxM4TKiiLIiAAAQh0RiD0IZxotYQ8sbMMDlPl9moeWVVfLwidMpiHR1i5HSLTMU4kGIhsoOffJ9sy26MMPNiEAAQg0BWBIHLG7bPK8/yu8vlKfIK6BZzoy6VmeIPQKaueR+1PEjuxzu1g8n1Eg+VP1ZfLTmUhwi4EIACBjgiECQHjHqV0la2013YUK4kKJ4DQKRzpFIMjrU69YWRArFuYSPAnFhbKY4MABCBQB4GJVn/Ht9RRdEFlTuqm8UUaH3Z7QfYw0yUBhE6XwLpKHtbCyuww5bmpq3y+Et9bEwqejdjxVSl4A4FGEBhTK0hu74s61lytUYvsl1HHELnzCJ2yK3BYw7Uze3HZxZRsf+uW2Flm9ym5HMxDAAIQaBMYU8fdLPKpLnI7X50A3k2V1ksAoVMF/2H7sYqJc9bku/lsrTurs9RBeZu7D/EOAhCAQAkE2iIndD6OebvV5tnzJNZWxRxECr4jdKqqxWE7WkLhgqqKK6Wc3O6vZ83n8RirFLoYhQAEAoE0RI5p5OrLbKFdTaXWTwChU1UdhIU/59m/q7hbqyqypHLuQ5+dkshiFgJNJ5CKyDFNvDpkJzW9Or3Ej9CpsiaCus+0RET8W7vPzpjtGH8oRAABCLggMG5H6fsx9sdVAeWvNGP6m10wxYkWAYRO1RfCsP1Aj7DeX3WxJZS3tb6UztZMpY8swTYmIQCBphBoTwZ4jML9nwRCvlmPrJ6j78aVCcSSTAgInTqqcsTeqWJ/VkfRBZe5mUTbz/RMfZ+C7WIOAhBoAoFcsqA943HM8+Ssralcbw7RI6tr1h7g1QcBhE4d9ZDZanXqfZ6KvrqO4gsuc5HuXn6klp2nF2wXcxCAQMoEcpuv742v6/vjVUmEmdm7NJT8tCRiSSwIhE5dFbrIbtY/+MEqPtb1sKaSW6iWnZP0pcWqvFOp8B4CEJiewBJJggk7RSfDmoDxb7l9Xy05740/kDQjQOjUWa/D9msV/8o6XSiw7AGJnf/VY6x3F2gTUxCAQGoExm1LiYJfKKwnJxLan22FJoUNM+GzuSSA0Km7Wkbsa3LhI3W7UVj5ofl23L6of/n5hdnEEAQgkAaBpfZgBRLmE9s1jYA0q9ikPdM21y0em1sCCB0PVTNsoSNemD05le1lapb+kd1ii1MJiDggAIE+CSy1x6nr8bmysl2flrxkn5Qjz9U6Vn/14hB+TE8AoTM9l2qPhs7JK+35KvSyagsutbT9bIHWeVlu25daCsYhAAH/BMa1eveAnSFHN/HvbIce5vZGOh93yKrmZAidmivgruI3URPoanuaPt9y17H43zxEMf3Kwp0cGwQg0DwC7eHjYY6c47QvSAZA6I84ap9MJp7EA0HoeKrgxXZ563mvJTXZ1Ba6kzuTEVmeLjR8gUAFBG6UFBhvLYOQwhw5U4H9TC05r516gPe+CSB0vNXPIvulXDrUm1t9+jO/NSJrQndAuVb8YoMABNImsNzuqwUtz9NIpNTm1/qzbkMPVlx3pl2BaUWH0PFYnyP2Tf0jHe3Rtb58yu1Itez8THd59+rLDpkhAAG/BCbsKXpk/Vs5+DC/Tvbk2Q1a0Pgp6mV0e0+5yVQbAYRObejnKHjY3qcUX54jVYyn95bTv7NltmeMzuMzBCAwA4GwZtWEppfI7VSl2HiGVLEenlB0T1Ur1VWxBtBkvxE6nmt/2F4h98KXRmrbvdUX6ReaeeKI1AIjHgg0ksBtEjYT9kOJnHcr/iwxBuEx1cFakTy0UrFFSACh47nSwrDzYc3TkOlZd3rbfMX1KX05fof5dtKrXCJqEIEJe6Qe6fxGER+QaNSvUOfjnyQaWyPCQuh4r+ZMD3nutAPl5h+9u9qTf7k9W3Mo/06CZ/ee8pMJAhCoh0B4VDVu/6FWnHP17n71OFF6qUdJ5Hy19FIooFQCCJ1S8RZkfCO7VUO095e1awqy6MtM+JLM1Wo1bq/Xa2rN3r5Y4w0EiiCw1DbTzUl4rP5h7aku9/JhiZwPFIELG/USQOjUy7/z0ofsWj3IeoIy3NR5pqhShsnEPq4vzx8xKiuqesPZphEYs8frxutihf2UhEP/sroNvDnh+BoVGkInpupebFfI3SB2bo7J7S59DS1Xl0jwpPq8v0scJIeAEwK5baibkI+ozTUs5bCVE6+KdyNTv8EwEITVyItnW5NFhE5N4HsudkQiYEDDHE0LK6S7ba5HWKdqVNYXbIkaj9kgAIF6CUxotfGJVofjN8mRlB8vn2JD9gJFuLpe4JReJAGETpE0q7I1pPWjJlsdlJdXVWQt5WT2cn3pXCJJ92+1lE+hEIDAoATO23XjcaFQ7Jg4jrPUkvMciZyVicfZuPCYjj/WKg9LRYxJ7GSau8I0jVW62/Zqwfp5uuERGQRcEzhEIqcJN8RB5ITv0ztc1wbO9USgCRdwT2CiyDSqxTLzBrTspN1UHsWlhpONJdCE34i1ImdZY2s58cCbcBGnXYXNETtp1yPRQQACdRBA5NRBveIyEToVAy+lOMROKVgxCgEIJE3g53pc9TQ9rqIlJ+lqtkY8e028CteEt1bshLlK2SAAAQhAYDYCoSXnAImcidkScS4NArTopFGP7SiC2MlsP324PaWwiAUCEIBAgQROXdPxmJacAqF6NoXQ8Vw7vfgWhp5bazh2qjMo90KFPBCAAARMgze+L5FzEI+rmnUxIHRSrO8wqeCkPVah/TPF8IgJAhCAQA8EvqbpRw+WyGGenB7gxZwFoRNz7c3m+yL7qw3a45Tk8tmScQ4CEIBAAwh8Qi05L5XIYcbjBlT2+iEidNYnktLnhXalmmpDy86vUwqLWCAAAQh0TCCzd6kl5w0SOXnHeUiYFAGETlLVOU0wo3aj7mT20ZmfTnOWQxCAAARSJTApcXO4vv/ek2qAxNUZAYROZ5ziThXmiRi2pyuI4+IOBO8hAAEIdERguUTOM/W996WOUpMoaQIInaSrd0pwoQPesB2qI8dMOcpbCEAAAqkRuEmDMfbT990pqQVGPL0RQOj0xi3OXOEZ9Yi9tdWca3ZnnEHgNQQgAIEZCfzVVtmetsjOmzEFJxpHAKHTuCpXwO3m3KfoHRMLNrH+iRkCKRLI7By15DzGNrK/pRgeMfVOAKHTO7u4c47YGWrfebSCuCruQPAeAhCAgB1vQ3pctchuhgUE1ieA0FmfSJM+j9qfJXYeqZB/0aSwiRUCEEiGQBgy/lY9kn+RHsnfkUxUBFIoAYROoTgjNNYefv5ECZ7PR+g9LkMAAs0lMCFx8yyJHAZYNPca6ChyhE5HmBJPFEZkjdqrJHZeo0hXJR4t4UEAArETyNQPJ1en42E7OfZQ8L98Agid8hnHU8KoHasvjyfK4RvjcbpGT3PboMbSKRoCTSVwum7HHqWbs0ubCoC4uyOA0OmOV/qpR+1sG7DdFGhYBZ1tNgKZWsHG7Tc2Zq+2WzXWgw0CECibwAfVivMUW2y3lF0Q9tMhkKUTCpEUSiC3BZpP+aNq4XltoXbTNbZCoX1P+1f0RXym+g5MphsqkZVCYNxuk93FpdiO3+hS/U+9RP9b348/FCKomgBCp2risZU3bi+Uy6Gj8lBsrtfo73Uq+5v6Yv6Gvph/W6MfFB0TAYTOTLV1qdYcP0gS8PKZEnAcArMRQOjMRodzbQLjtpPefEv7Q0DSNYG/tgTPpJ2oPgV/6jo3GZpDAKEzXV1/STcLr9P/0LLpTnIMAp0QQOh0Qok0pkdYwzZhnxKKl4KjZwKXieN31Qfqe7T09Mww3YwInal1O6EPr9LQ8eOnHuQ9BHohgNDphVqT84RHWVlrdNZIkzEUEPtV4vgDCZ9TJXrO1nsmOysAatQmEDprq+9i9XD7d81y/Je1B3iFQD8EEDr90Gtq3tvtgTbYepS1a1MRFBz3Mgme09XS8yPtP7GFdnXB9jEXAwGETqilT0r4vxnhH8MFG4+PCJ146sqXp7nN16Os98ipN2tnmoIiayezK2TudN3VnqH9LIbSFgnXsa1mC50lEjeHSuT82HEN4VqkBBA6kVacG7fHbC99QR0nf7Zz41NajoS1fC7Sfo5afc4R61+q38L1aYVINC0CzRU6p+jaPlyd9ZdwJUCgDAIInTKoNs3mzXqavoF9WmG/qGmh1xJve/r7c/XjcKEeIf5aj7r+QFN/LTVRbKFNEzqZpts0e4Nacb5ULEisQWBdAgiddXnwqR8CE/ZM/fh+Tibu1Y8Z8nZN4E7l+IPY/0YPEX8v0XOxfkIusS1aPyRdGyNDTQSaJXR+LpH+Uon0f9REm2IbRACh06DKriTUpbapfmw/qbIOqaQ8CpmZQG5/18lLtF8q8fNX1ctlGtt1mW3cmoF35nycqYdAM4TOmAT5W/T49XO6JsNjWTYIlE4AoVM64oYWQOuO54q/sSV8crtSPzVXSgCF16vV8fkq9ZO4RueYnK2O2ktf6PxYrTivYlRhHRdXs8tE6DS7/suNvt2681EV8uJyC8J6oQRC34nc/iWbN2i/TsJniUTQrXq9VZ9vbr2uVqvQgJYznZQomq92ohV2u5Y1XaFzYc2vzrawEOoC/ewN2Iaa4n+xbA3p/bDKXiQ7i2RksV4X63NY/2ntsSW20o5OslUqXaETFuB8g1pxvt7ZhUEqCBRLAKFTLE+sTUdg3PbVD9bn9IP1gOlOcyxZAqFlKPQfWruN6k0RUxFcq2vpJWp9OnOt4SReUxQ6mX1HdXWERE4QzWwQqIVAEV86tThOoRERGNF8MENaLyu398vrVRF5jqv9EQgLwYbWmLV7Ud8320g4n6F2p4/pmtqwPxfJXRKBq1VHz1L73HMQOSURxmzHBGjR6RgVCQshMGYP0z39sfqBelwh9jDSdAJ/1g/qC/SDelH0INJo0Vmp/+0PS9y8T/VCX6/oL8o0AijqDisNGkRRPoFRjQAa0iSDpjWzjInvygeefAkP0Q/rhZql+216HUw+Wt8B/lR9rR6mR4pvR+T4rqimeYfQaVqNe4g3DCsdsRPUhXUHufMx7as9uIUP0RKYpyvqfWo/+IW6SN8/2ijidfxq8X+2/qf310PKy+MNA89TJYDQSbVmY4hrU1uqL8c36Uvy4XL3jBhcxkfHBHJ7jM3TxIkT9grHXqbk2gr9775fjw0folac76UUGLGkRYA+OmnVZ9zRTNiB+uL8iIJ4UNyB4L0DAj+UD4dLSMcz2ieePjphor8T9KDwaE0OcJWDusYFCMxKgBadWfFwslICw/ZD3R3uKLHzepUb5t5gg0CvBA5UxkvVuvPMXg2Qb1oCZ6n/zSMlIF+EyJmWDwcdEkDoOKyURruUafj5qJaQWNWacye07nQ+AV2jwRH8NAQ2k2g+ScPQv6xpDsMEhGy9Ewij254mgfME3Yz8tncz5IRA9QR4dFU9c0rshsAy21pdld+lL9nDlI1RNd2wI+1UAldq5uUXS+78cupBV+99Prq6Sf97b9dIyS/rlTmwXF0wONMpAVp0OiVFunoIDNk/1cLzComdB8uBb9XjBKUmQGB7zd90tlp3PqBWng0SiKeqEE5VC84XEDlV4aacMgggdMqgis3iCSy2K9Rs/jx94e4m4z8uvgAsNoBA+L57s/rtXCjBs1MD4iVECEBABBA6XAZxEQgz4I7YAbpyHy3HfxqX83jrhMDO8uM3Ejv/qdYdvgOdVApuQKAsAvyTl0UWu+USGLILJHj2b7Xw5HZyuYVhPUECCxTTh9S6c6Ytt+0SjI+QIACBNQQQOlwKcRMILTyjGkKca+r5dh+eMMcHGwQ6JbC3+n9dotadF3eagXQQgEBcBBA6cdUX3s5EYNT+2OrDM6lZWs2+pP2OmZJyHALrERjV56+pdee7mqt7s/XO8RECEIicAEIn8grE/fUILLLLJHgOVwvPttr/W2dvWi8FHyEwPYHcDlKPnTDJ4AHTJ+AoBCAQIwGEToy1hs9zExi1JXqk9U4Njd1W/XheqQyXzZ2JFBCwe0kgn2pj9jldQSPwgAAE4ieA0Im/DolgNgKZupqGeUDCwoOZ1tIyO2225JyDQItAEMeh/9cy2xMiEIBA3AQQOnHXH953SiDTffqw7tRH7MnqfPpAZfuw9ps7zU66BhLItQzJpJ2j1p3/1tUzv4EECBkCSRBA6CRRjQTRFYH25IP/T8Jna+V7sVp6zusqP4mbRGBQ18fR6rdzvjoqh9m52SAAgcgIIHQiqzDcLZBAppFZI/Z1CZ7HyurO+kH7jF5ZNb1AxAmZ2l0dlS9S687r1LrDGoEJVSyhpE8AoZN+HRNhJwRGNJfKsB2hfSv9kD1b+w+UjUUMO2HXnDQbSuJ8Qq07p6nvTmgNZIMABCIggNCJoJJwsUICma3UaK3vaX+GxM69VfIbtF9UoQcU5Z/Afuq7c6lad57n31U8hAAEEDpcAxCYicCo3ahHW5/QvptEz8O0v1dJGaY+E69mHd9IrTvf1IzK37TbbONmhU60EIiLAEInrvrC27oIhJmXR+0dEj2hQ+rOiJ66KsJduc+zea0lJPZz5xkOQQACLQIIHS4ECHRLIPTnuafo+VO3ZkifDIHQX+d09d35pATwwmSiIhAIJEIAoZNIRRJGTQTuFj072qDdVz90r5Mnp2tfWZNHFFsXgdyOlNj5nfbd63KBciEAgXsSQOjckwlHINAbgYV2pVp6PqXHW0/SqJxNNRz5IBn6qvbrezNIrggJPFhi9wKJnXfodTBC/3EZAskRYD6I5KqUgNwRCPOujNuO+hv6ceyrfW/tYcVstpQJBMEzqQkpF9vlHYU5rm7NptS+tq9JuB/qyyW8gUB3BBA63fEiNQT6J5Cr++qYPUr3+/vqrj8Inz20b9i/YSw4JDAhgfsfNqT11sIyJLNtCJ3Z6HAOAj0TQOj0jI6MECiIQG4LtPTobrr7f4x+DB+jn8PHyvKWBVnHjA8CP5IbL1PryMyPMRE6PmoKL5IjgNBJrkoJKAkCK+x+mpf50S3hM2m76nUXxTWURGzNDeJmidhX6KHl96ZFgNCZFgsHIdAvAYROvwTJD4EqCISOreO2gwTPrioujOp5+JrXRVUUTxmFEjhOq6wdqe7qS9exitBZBwcfIFAUAYROUSSxA4E6CCy3bW21BJCps3OuyQwze4jeP1T7ZnW4Q5kdE7hK9fUSte78/K4cCJ27UPAGAkUSQOgUSRNbEPBC4HbbRKLnoRrivr1e76cf1e3lWtjvq/0+2hn6LAg1b6Fz8ke0kOzRqqM71GLHqKuaK4Ti0ySQpRkWUUEAAjMSCKO+Vtg2dqcET6bV2s3udderrfncft1E5zaY0Q4niiJwiQy9SPvPtTO8vCiq2IHAGgLzIAEBCDSMQKZuzqbJDdv77MHnEjoTtpFGhC2WPGq/5nrNNH5o7Y9ypgcwk2ohylrLH2yg1/lqQRq+y3CuWaIzTaE4dcvsqUrzgKmHGvx+J8V+oXa+jxt8ERB6eQT4xyqPLZYhED+B8EjF7IY1e3Hx3KiZgxfasTL4guKMRm1pQdTe4zwEHBNgCQjHlYNrEEiWwOaaMnHEXqj4DtO+bmtPskETGAQgUAcBhE4d1CkTAhBoExixr+ixVxguH/qpsEEAAhAonABCp3CkGIQABLoisMj+oh49j1Kfnc91lY/EEIAABDoggNDpABJJIACBkglkGgc2aq+W2HmOSgrDrNkgAAEIFEIAoVMIRoxAAAKFEBi172j81m4SPBcUYg8jEIBA4wkgdBp/CQAAAs4ILLR/qKPyXvLqg848wx0IQCBCAgidCCsNlyGQPIFM0xmO2FsU5/7ab0w+XgKEAARKI4DQKQ0thiEAgb4JjNhPNdlgWLn9zL5tYQACEGgkAYROI6udoCEQEYFhu06jsp4owfMOeb06Is9xFQIQcEAAoeOgEnABAhCYg0Cm2XaG7b36u49SXjtHak5DAAIQuIsAQucuFLyBAATcE1hk56hNZxeNyjrZva84CAEIuCCA0HFRDTgBAQh0TGCx3aKOys+S2Hmd8qzsOB8JIQCBRhJA6DSy2gkaApETyCRzRu1T6rezp/YrIo8G9yEAgRIJIHRKhItpCECgZALDdpFN2K4q5YSSS8I8BCAQKQGETqQVh9sQgMAaAlvY+JqV0F+qIxNwgQAEIDCVAEJnKg3eQwAC8RIYsa9qVNYjFMDF8QaB5xCAQNEEEDpFE8UeBCBQH4H2Suh7qN/OsfU5QckQgIAnAggdT7WBLxCAQP8Ewkrow/YadVc+WMZYCb1/oliAQNQEEDpRVx/OQwACMxIYte9qJfRdJXhYCX1GSJyAQPoEEDrp1zERQqC5BBbalWtWQv9AcyEQOQSaTQCh0+z6J3oIpE+gvRL6UQr0ydpZCT39GidCCKxDAKGzDg4+QAACyRIYsdMU287az0g2RgKDAATuQQChcw8kHIAABJIlMGLXq6PykzQq62jFyEroyVY0gUHgbgIInbtZ8A4CEGgCgfZK6O9bsxL6NU0ImRgh0GQCCJ0m1z6xQ6DJBNoroT9co7JYCb3J1wGxJ08AoZN8FRMgBCAwIwFWQp8RDScgkAoBhE4qNUkcEIBAbwTWroRutocMXN6bEXJBAAJeCSB0vNYMfkEAAtUSGLHf2zLbTYUeX23BlAYBCJRJAKFTJl1sQwACcRFor4T+Ijl9qHZWQo+r9vAWAtMSQOhMi4WDEIBAowmM2NfWrIT+h0ZzIHgIJEAAoZNAJRICBCBQAoH2Suh7as6dz5ZgHZMQgEBFBBA6FYGmGAhAIEIC7ZXQX6sh6M+W96yEHmEV4jIEEDpcAxCAAATmIjBq39NK6GHOHVZCn4sV5yHgjABCx1mF4A4EIOCUwEK7Siuh/5u8Cyuh5069xC0IQGA9Agid9YDwEQIQgMCMBDJbJbETVkLfX/uSGdNxAgIQcEMAoeOmKnAEAhCIhkB7JfRd5O/PovEZRyHQUAIInYZWPGFDAAJ9EmivhP5kjcp6uyyxEnqfOMkOgbIIIHTKIotdCEAgfQLtldDfrzl39lawrISefo0TYYQEEDoRVhouQwACzggssnPVphNGZX3fmWe4A4HGE0DoNP4SAAAEIFAIgfZK6AdJ7BwpeysLsYkRCECgbwIInb4RYgACEIDAGgLtldA/rU+shM5FAQEnBBA6TioCNyAAgYQI3L0S+tcTiopQIBAlAYROlNWG0xCAgHsC7ZXQXyw/X6KdldDdVxgOpkoAoZNqzRIXBCDgg8CIHadRWbvLGVZC91EjeNEwAgidhlU44UIAAjUQWGSX2bCFldA/U0PpFAmBRhNA6DS6+gkeAhCojEB7JfQjbMAOUpmshF4ZeApqOgGETtOvAOKHAASqJTBkJ2kl9F00DP38agumNAg0kwBCp5n1TtQQgECdBBba1VocdC+5cIx2VkKvsy4oO3kCCJ3kq5gAIQABlwTaK6G/Vb6FldBvcOkjTkEgAQIInQQqkRAgAIGICbRXQn+4Ijg94ihwHQJuCSB03FYNjkEAAo0h0F4JPbTsvE07K6E3puIJtAoCCJ0qKFMGBCAAgbkIhJXQR+x/9Df03WEl9Ll4cR4CHRJA6HQIimQQgAAEKiGwyM6zVa1RWayEXglwCkmdAEIn9RomPghAID4CG9mtNmrPWrMS+h3xBYDHEPBDAKHjpy7wBAIQgMC6BEYtrIS+p/a/rnuCTxCAQKcEEDqdkiIdBCAAgToItFdCD2tlsRJ6HfwpM3oCCJ3oq5AAIACB5AmwEnryVUyA5RFA6JTHFssQgAAEiiXQXgl9NxllJfRiyWItYQIInYQrl9AgAIEECSxSf51h24OV0BOsW0IqhQBCpxSsGIUABCBQIoHM7pDYWbsS+q0lloRpCERPAKETfRUSAAQg0FgC7ZXQH67WnfMay4DAITAHAYTOHIA4DQEIQMA1gbAS+pDtLR//RzsrobuuLJyrgwBCpw7qlAkBCECgSALtldDDOllP1s5K6EWyxVb0BBA60VchAUAAAhBYQ2CktQL6LvrESuhcFBBYQwChw6UAAQhAICUCI2rRGbawEvpbtbMSekp1Syw9EUDo9ISNTBCAAAQcE2ivhH6MDdi/ycurHXuKaxAonQBCp3TEFAABCECgJgJDdr5WQn+4uiifVJMHFAuB2gkgdGqvAhyAAAQgUCKB9kroB0nsHKFSWAm9RNSY9kkAoeOzXvAKAhCAQLEERu0zMhhWQr+sWMNYg4BvAggd3/WDdxCAAASKI9BeCf0RMnhccUaxBAHfBBA6vusH7yAAAQgUS6C9EvpLZPTF2ieKNY41CPgjgNDxVyd4BAEIQKB8AiP2dZs0VkIvnzQl1EwAoVNzBVA8BCAAgdoI3L0S+qdr84GCIVAyAYROyYAxDwEIQMA1gfZK6EdqYdBnyU9WQnddWTjXCwGETi/UyAMBCEAgNQLD9n0b1Jw7mZ2bWmjE02wCCJ1m1z/RQwACELibQHsl9H005877dZCV0O8mwzsIQAACEIAABJIiMG772bgdk1RMBAMBCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIBAqgT+PwQUc6J1VOHQAAAAAElFTkSuQmCC";
|
|
787
1134
|
|
|
@@ -839,7 +1186,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
839
1186
|
}
|
|
840
1187
|
|
|
841
1188
|
// src/components/ChatPanel.tsx
|
|
842
|
-
import { useEffect as
|
|
1189
|
+
import { useEffect as useEffect8, useState as useState15 } from "react";
|
|
843
1190
|
|
|
844
1191
|
// src/components/ChatHeader.tsx
|
|
845
1192
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -852,7 +1199,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
852
1199
|
}
|
|
853
1200
|
|
|
854
1201
|
// src/components/MessageList.tsx
|
|
855
|
-
import { useEffect as
|
|
1202
|
+
import { useEffect as useEffect7, useRef as useRef5 } from "react";
|
|
856
1203
|
|
|
857
1204
|
// src/components/Markdown.tsx
|
|
858
1205
|
import ReactMarkdown from "react-markdown";
|
|
@@ -870,7 +1217,7 @@ function Markdown({ text }) {
|
|
|
870
1217
|
}
|
|
871
1218
|
|
|
872
1219
|
// src/components/EntityCardList.tsx
|
|
873
|
-
import { useState } from "react";
|
|
1220
|
+
import { useState as useState2 } from "react";
|
|
874
1221
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
875
1222
|
var MAX_VISIBLE = 3;
|
|
876
1223
|
var RECORD_RE = /^(\d+)-(\d+)-(\d+)$/;
|
|
@@ -954,7 +1301,7 @@ function ScopeTabs({ scopes, active, onSelect }) {
|
|
|
954
1301
|
)) });
|
|
955
1302
|
}
|
|
956
1303
|
function EntityCardItem({ c }) {
|
|
957
|
-
const [active, setActive] =
|
|
1304
|
+
const [active, setActive] = useState2(0);
|
|
958
1305
|
const hasBody = c.scopes.length > 0;
|
|
959
1306
|
if (!hasBody) {
|
|
960
1307
|
return /* @__PURE__ */ jsx6("div", { className: "ss-w-ecard ss-w-ecard-bare", "data-kind": c.kind, children: /* @__PURE__ */ jsx6(CardHeader, { c, showScopeCrest: false }) });
|
|
@@ -968,7 +1315,7 @@ function EntityCardItem({ c }) {
|
|
|
968
1315
|
] });
|
|
969
1316
|
}
|
|
970
1317
|
function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMoreLabel = (n) => `Show ${n} more` }) {
|
|
971
|
-
const [expanded, setExpanded] =
|
|
1318
|
+
const [expanded, setExpanded] = useState2(false);
|
|
972
1319
|
if (cards.length === 0) return null;
|
|
973
1320
|
const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE);
|
|
974
1321
|
const overflow = cards.length - MAX_VISIBLE;
|
|
@@ -979,46 +1326,18 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
979
1326
|
}
|
|
980
1327
|
|
|
981
1328
|
// src/components/BettingInsightList.tsx
|
|
982
|
-
import { useState as
|
|
1329
|
+
import { useState as useState6 } from "react";
|
|
983
1330
|
|
|
984
1331
|
// src/components/AddToSlipButton.tsx
|
|
985
|
-
import { useCallback as
|
|
1332
|
+
import { useCallback as useCallback3, useState as useState3 } from "react";
|
|
986
1333
|
import { isAddToSlipResult } from "@sensiblestats/widget-sdk";
|
|
987
1334
|
|
|
988
|
-
// src/slip.ts
|
|
989
|
-
var ADD_TO_SLIP_TIMEOUT_MS = 1e4;
|
|
990
|
-
function wasAdded(result) {
|
|
991
|
-
if (!result) return true;
|
|
992
|
-
if (result.status === "price_changed") return result.accepted;
|
|
993
|
-
return result.status === "added";
|
|
994
|
-
}
|
|
995
|
-
function isTerminal(result) {
|
|
996
|
-
if (!result) return true;
|
|
997
|
-
if (result.status === "price_changed") return result.accepted;
|
|
998
|
-
return result.status === "added" || result.status === "duplicate";
|
|
999
|
-
}
|
|
1000
|
-
function resultToToast(result, shownOdds, ui) {
|
|
1001
|
-
if (!result) return { kind: "success", text: ui.slipAdded(void 0) };
|
|
1002
|
-
switch (result.status) {
|
|
1003
|
-
case "added":
|
|
1004
|
-
return { kind: "success", text: ui.slipAdded(result.slip?.selectionCount) };
|
|
1005
|
-
case "duplicate":
|
|
1006
|
-
return { kind: "success", text: ui.slipDuplicate };
|
|
1007
|
-
case "price_changed":
|
|
1008
|
-
return result.accepted ? { kind: "success", text: ui.slipPriceChanged(shownOdds, result.newOddsDecimal.toFixed(2)) } : { kind: "error", text: ui.slipPriceNotAccepted(shownOdds, result.newOddsDecimal.toFixed(2)) };
|
|
1009
|
-
case "rejected":
|
|
1010
|
-
if (result.reason === "login_required") return { kind: "error", text: ui.slipLoginRequired };
|
|
1011
|
-
if (result.reason === "suspended") return { kind: "error", text: ui.slipSuspended };
|
|
1012
|
-
return { kind: "error", text: result.message ?? ui.slipFailed };
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
1335
|
// src/components/Toast.tsx
|
|
1017
|
-
import { useEffect as
|
|
1336
|
+
import { useEffect as useEffect4 } from "react";
|
|
1018
1337
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1019
1338
|
var DISMISS_MS = 4e3;
|
|
1020
1339
|
function Toast({ toast, onDismiss }) {
|
|
1021
|
-
|
|
1340
|
+
useEffect4(() => {
|
|
1022
1341
|
if (!toast) return;
|
|
1023
1342
|
const timer = setTimeout(onDismiss, DISMISS_MS);
|
|
1024
1343
|
return () => clearTimeout(timer);
|
|
@@ -1036,10 +1355,10 @@ function withTimeout(value) {
|
|
|
1036
1355
|
]);
|
|
1037
1356
|
}
|
|
1038
1357
|
function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
|
|
1039
|
-
const [pending, setPending] =
|
|
1040
|
-
const [settled, setSettled] =
|
|
1041
|
-
const [toast, setToast] =
|
|
1042
|
-
const dismiss =
|
|
1358
|
+
const [pending, setPending] = useState3(false);
|
|
1359
|
+
const [settled, setSettled] = useState3(false);
|
|
1360
|
+
const [toast, setToast] = useState3(null);
|
|
1361
|
+
const dismiss = useCallback3(() => setToast(null), []);
|
|
1043
1362
|
const handler = slip.onAddToSlip;
|
|
1044
1363
|
if (!ui || !handler || !selection) return null;
|
|
1045
1364
|
const onClick = async () => {
|
|
@@ -1103,53 +1422,88 @@ function OddsMovementBadge({
|
|
|
1103
1422
|
}
|
|
1104
1423
|
|
|
1105
1424
|
// src/components/Crest.tsx
|
|
1106
|
-
import { useState as
|
|
1425
|
+
import { useState as useState4 } from "react";
|
|
1107
1426
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1108
1427
|
function initials2(name) {
|
|
1109
1428
|
return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
|
|
1110
1429
|
}
|
|
1111
1430
|
function Crest2({ url, name, kind }) {
|
|
1112
1431
|
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
1113
|
-
const [failed, setFailed] =
|
|
1432
|
+
const [failed, setFailed] = useState4(false);
|
|
1114
1433
|
if (url && !failed) {
|
|
1115
1434
|
return /* @__PURE__ */ jsx10("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1116
1435
|
}
|
|
1117
1436
|
return /* @__PURE__ */ jsx10("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
|
|
1118
1437
|
}
|
|
1119
1438
|
|
|
1439
|
+
// src/components/PinToggle.tsx
|
|
1440
|
+
import { useCallback as useCallback4, useState as useState5 } from "react";
|
|
1441
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1442
|
+
function PinToggle({ pin, monitor, ui }) {
|
|
1443
|
+
const [toast, setToast] = useState5(null);
|
|
1444
|
+
const dismiss = useCallback4(() => setToast(null), []);
|
|
1445
|
+
if (!monitor || !monitor.enabled) return null;
|
|
1446
|
+
const key = pinKey(pin);
|
|
1447
|
+
const pinned = monitor.isPinned(key);
|
|
1448
|
+
const labels = pin.kind === "match" ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel } : { pin: ui.pinLabel, unpin: ui.unpinLabel };
|
|
1449
|
+
const onClick = () => {
|
|
1450
|
+
const result = monitor.togglePin({ ...pin, key });
|
|
1451
|
+
if (result === "match_limit") {
|
|
1452
|
+
setToast({ kind: "error", text: ui.matchLimitToast });
|
|
1453
|
+
} else if (result === "market_limit") {
|
|
1454
|
+
setToast({ kind: "error", text: ui.marketLimitToast });
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-pin-wrap", children: [
|
|
1458
|
+
/* @__PURE__ */ jsx11(
|
|
1459
|
+
"button",
|
|
1460
|
+
{
|
|
1461
|
+
type: "button",
|
|
1462
|
+
className: "ss-w-pin",
|
|
1463
|
+
"data-on": pinned || void 0,
|
|
1464
|
+
"aria-pressed": pinned,
|
|
1465
|
+
"aria-label": pinned ? labels.unpin : labels.pin,
|
|
1466
|
+
onClick,
|
|
1467
|
+
children: /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx11("path", { fill: "currentColor", d: "M9.5 1.5 14.5 6.5 13 8l-.5-.5-3 3 .3 2.2-1.4 1.4L5.6 11.3l-3.3 3.3-1-1 3.3-3.3L1.9 7.5l1.4-1.4 2.2.3 3-3L8 2.9z" }) })
|
|
1468
|
+
}
|
|
1469
|
+
),
|
|
1470
|
+
/* @__PURE__ */ jsx11(Toast, { toast, onDismiss: dismiss })
|
|
1471
|
+
] });
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1120
1474
|
// src/components/BettingInsightList.tsx
|
|
1121
|
-
import { Fragment, jsx as
|
|
1475
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1122
1476
|
function StatRows({ stats }) {
|
|
1123
|
-
return /* @__PURE__ */
|
|
1124
|
-
/* @__PURE__ */
|
|
1125
|
-
/* @__PURE__ */
|
|
1477
|
+
return /* @__PURE__ */ jsx12("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-row", children: [
|
|
1478
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
1479
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
1126
1480
|
] }, `${s.label}:${s.value}`)) });
|
|
1127
1481
|
}
|
|
1128
1482
|
function ScopedStats({ scopes }) {
|
|
1129
|
-
const [active, setActive] =
|
|
1483
|
+
const [active, setActive] = useState6(0);
|
|
1130
1484
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
1131
|
-
return /* @__PURE__ */
|
|
1132
|
-
/* @__PURE__ */
|
|
1133
|
-
/* @__PURE__ */
|
|
1485
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-scoped", children: [
|
|
1486
|
+
/* @__PURE__ */ jsx12("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx12("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
1487
|
+
/* @__PURE__ */ jsx12(StatRows, { stats: current.stats }, current.key)
|
|
1134
1488
|
] });
|
|
1135
1489
|
}
|
|
1136
1490
|
function hasStatsContent(it) {
|
|
1137
1491
|
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
1138
1492
|
}
|
|
1139
1493
|
function ReasonStrip({ it, ui }) {
|
|
1140
|
-
const [open, setOpen] =
|
|
1494
|
+
const [open, setOpen] = useState6(false);
|
|
1141
1495
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
1142
1496
|
const hasStats = hasStatsContent(it);
|
|
1143
1497
|
const hasText = !!it.text;
|
|
1144
1498
|
if (!hasText && !hasStats) return null;
|
|
1145
1499
|
const expandable = hasStats || (it.text?.length ?? 0) > 90;
|
|
1146
|
-
return /* @__PURE__ */
|
|
1147
|
-
/* @__PURE__ */
|
|
1148
|
-
/* @__PURE__ */
|
|
1149
|
-
hasText ? /* @__PURE__ */
|
|
1150
|
-
open && hasStats ? hasScopes ? /* @__PURE__ */
|
|
1500
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-reason", children: [
|
|
1501
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1502
|
+
/* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-reason-body", children: [
|
|
1503
|
+
hasText ? /* @__PURE__ */ jsx12("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
|
|
1504
|
+
open && hasStats ? hasScopes ? /* @__PURE__ */ jsx12(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ jsx12(StatRows, { stats: it.stats }) : null
|
|
1151
1505
|
] }),
|
|
1152
|
-
expandable ? /* @__PURE__ */
|
|
1506
|
+
expandable ? /* @__PURE__ */ jsx12(
|
|
1153
1507
|
"button",
|
|
1154
1508
|
{
|
|
1155
1509
|
type: "button",
|
|
@@ -1157,166 +1511,214 @@ function ReasonStrip({ it, ui }) {
|
|
|
1157
1511
|
"aria-expanded": open,
|
|
1158
1512
|
"aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
|
|
1159
1513
|
onClick: () => setOpen((v) => !v),
|
|
1160
|
-
children: /* @__PURE__ */
|
|
1514
|
+
children: /* @__PURE__ */ jsx12("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
|
|
1161
1515
|
}
|
|
1162
1516
|
) : null
|
|
1163
1517
|
] });
|
|
1164
1518
|
}
|
|
1165
1519
|
function CardFixture({ it }) {
|
|
1166
1520
|
if (it.homeTeamName && it.awayTeamName) {
|
|
1167
|
-
return /* @__PURE__ */
|
|
1168
|
-
/* @__PURE__ */
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1172
|
-
/* @__PURE__ */
|
|
1521
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
1522
|
+
/* @__PURE__ */ jsx12(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
|
|
1523
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
|
|
1524
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1525
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
|
|
1526
|
+
/* @__PURE__ */ jsx12(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
|
|
1173
1527
|
] });
|
|
1174
1528
|
}
|
|
1175
|
-
if (it.fixture) return /* @__PURE__ */
|
|
1529
|
+
if (it.fixture) return /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-fixture-txt", children: it.fixture });
|
|
1176
1530
|
if (it.competition) {
|
|
1177
|
-
return /* @__PURE__ */
|
|
1178
|
-
/* @__PURE__ */
|
|
1179
|
-
/* @__PURE__ */
|
|
1531
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
1532
|
+
/* @__PURE__ */ jsx12(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
|
|
1533
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-comp", children: it.competition })
|
|
1180
1534
|
] });
|
|
1181
1535
|
}
|
|
1182
1536
|
return null;
|
|
1183
1537
|
}
|
|
1184
|
-
function InsightCard({ it, ui, slip }) {
|
|
1538
|
+
function InsightCard({ it, ui, slip, monitor }) {
|
|
1185
1539
|
const live = it.isLive || it.phase === "live";
|
|
1186
1540
|
const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : void 0;
|
|
1187
1541
|
const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName;
|
|
1188
1542
|
const leftIsFixture = hasNamedTeams || !!it.fixture;
|
|
1189
1543
|
const compInMeta = leftIsFixture && !!it.competition;
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
/* @__PURE__ */
|
|
1195
|
-
|
|
1196
|
-
|
|
1544
|
+
const showPin = !!monitor && it.pinEnabled;
|
|
1545
|
+
const showHeader = leftIsFixture || !!it.competition || live || !!kickoff || showPin;
|
|
1546
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ss-w-binsight", children: [
|
|
1547
|
+
showHeader ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-header", children: [
|
|
1548
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-header-left", children: /* @__PURE__ */ jsx12(CardFixture, { it }) }),
|
|
1549
|
+
/* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-header-right", children: [
|
|
1550
|
+
live ? /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-live", children: [
|
|
1551
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1197
1552
|
ui?.liveLabel ?? "Live"
|
|
1198
1553
|
] }) : null,
|
|
1199
|
-
compInMeta ? /* @__PURE__ */
|
|
1200
|
-
/* @__PURE__ */
|
|
1201
|
-
/* @__PURE__ */
|
|
1554
|
+
compInMeta ? /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-comp-meta", children: [
|
|
1555
|
+
/* @__PURE__ */ jsx12(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
|
|
1556
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-comp", children: it.competition })
|
|
1202
1557
|
] }) : null,
|
|
1203
|
-
kickoff ? /* @__PURE__ */
|
|
1558
|
+
kickoff ? /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-kick", children: [
|
|
1204
1559
|
kickoff.dayLabel,
|
|
1205
1560
|
" ",
|
|
1206
1561
|
kickoff.time
|
|
1207
|
-
] }) : null
|
|
1562
|
+
] }) : null,
|
|
1563
|
+
showPin && ui ? /* @__PURE__ */ jsx12(PinToggle, { ui, monitor, pin: { kind: "match", matchId: it.matchId } }) : null
|
|
1208
1564
|
] })
|
|
1209
1565
|
] }) : null,
|
|
1210
|
-
/* @__PURE__ */
|
|
1211
|
-
/* @__PURE__ */
|
|
1212
|
-
/* @__PURE__ */
|
|
1213
|
-
it.selection ? /* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
/* @__PURE__ */
|
|
1566
|
+
/* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-action-row", children: [
|
|
1567
|
+
/* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-pick", children: [
|
|
1568
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-market", children: it.market }),
|
|
1569
|
+
it.selection ? /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
1570
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-pick-dot", "aria-hidden": "true", children: "\xB7" }),
|
|
1571
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-bi-sel", children: it.selection })
|
|
1216
1572
|
] }) : null
|
|
1217
1573
|
] }),
|
|
1218
|
-
it.odds ? /* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1220
|
-
/* @__PURE__ */
|
|
1221
|
-
it.bookmaker ? /* @__PURE__ */
|
|
1574
|
+
it.odds ? /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-odds", children: [
|
|
1575
|
+
/* @__PURE__ */ jsx12("b", { children: it.odds }),
|
|
1576
|
+
/* @__PURE__ */ jsx12(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
|
|
1577
|
+
it.bookmaker ? /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
|
|
1222
1578
|
] }) : null,
|
|
1223
|
-
/* @__PURE__ */
|
|
1579
|
+
/* @__PURE__ */ jsx12(AddToSlipButton, { it, slip, ui }),
|
|
1580
|
+
showPin && ui ? /* @__PURE__ */ jsx12(
|
|
1581
|
+
PinToggle,
|
|
1582
|
+
{
|
|
1583
|
+
ui,
|
|
1584
|
+
monitor,
|
|
1585
|
+
pin: {
|
|
1586
|
+
kind: "selection",
|
|
1587
|
+
matchId: it.matchId,
|
|
1588
|
+
marketDeveloperName: it.marketDeveloperName,
|
|
1589
|
+
selectionLabel: it.selectionLabel,
|
|
1590
|
+
line: it.line,
|
|
1591
|
+
matchOddsId: it.matchOddsId
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
) : null
|
|
1224
1595
|
] }),
|
|
1225
|
-
it.isMarketFloor ? /* @__PURE__ */
|
|
1226
|
-
/* @__PURE__ */
|
|
1227
|
-
it.disclaimer ? /* @__PURE__ */
|
|
1596
|
+
it.isMarketFloor ? /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
|
|
1597
|
+
/* @__PURE__ */ jsx12(ReasonStrip, { it, ui }),
|
|
1598
|
+
it.disclaimer ? /* @__PURE__ */ jsx12("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
1228
1599
|
] });
|
|
1229
1600
|
}
|
|
1230
|
-
function BettingInsightList({ insights, ui, slip }) {
|
|
1601
|
+
function BettingInsightList({ insights, ui, slip, monitor }) {
|
|
1231
1602
|
if (!insights || insights.length === 0) return null;
|
|
1232
|
-
return /* @__PURE__ */
|
|
1603
|
+
return /* @__PURE__ */ jsx12("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ jsx12(InsightCard, { it, ui, slip, monitor }, it.id)) });
|
|
1233
1604
|
}
|
|
1234
1605
|
|
|
1235
1606
|
// src/components/MarketOddsCardList.tsx
|
|
1236
|
-
import { useState as
|
|
1237
|
-
import { Fragment as Fragment2, jsx as
|
|
1238
|
-
function OddsRow({ vm, row, ui, slip }) {
|
|
1607
|
+
import { useState as useState7 } from "react";
|
|
1608
|
+
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1609
|
+
function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
1239
1610
|
const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
/* @__PURE__ */
|
|
1243
|
-
/* @__PURE__ */
|
|
1244
|
-
/* @__PURE__ */
|
|
1611
|
+
const inSlip = !!inSlipIds && row.matchOddsId != null && !!inSlipIds[row.matchOddsId];
|
|
1612
|
+
return /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-row", children: [
|
|
1613
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-mo-sel", children: row.selection }),
|
|
1614
|
+
/* @__PURE__ */ jsx13(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
|
|
1615
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-mo-price", children: row.odds }),
|
|
1616
|
+
inSlip && ui ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-mon-inslip", children: [
|
|
1617
|
+
"\u2713 ",
|
|
1618
|
+
ui.inSlipLabel
|
|
1619
|
+
] }) : null,
|
|
1620
|
+
/* @__PURE__ */ jsx13(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
|
|
1245
1621
|
] });
|
|
1246
1622
|
}
|
|
1247
|
-
function MarketOddsCard({ vm, ui, slip }) {
|
|
1248
|
-
const [open, setOpen] =
|
|
1623
|
+
function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds }) {
|
|
1624
|
+
const [open, setOpen] = useState7(false);
|
|
1249
1625
|
const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
|
|
1250
1626
|
const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
/* @__PURE__ */
|
|
1627
|
+
const showPin = !!monitor && vm.pinEnabled;
|
|
1628
|
+
const showHeader = !!vm.competition || vm.isLive || !!kickoff || showPin;
|
|
1629
|
+
return /* @__PURE__ */ jsxs9("div", { className: "ss-w-mocard", children: [
|
|
1630
|
+
showHeader ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-header", children: [
|
|
1631
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1632
|
+
/* @__PURE__ */ jsx13(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
|
|
1633
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-bi-comp", children: vm.competition })
|
|
1257
1634
|
] }) : null }),
|
|
1258
|
-
/* @__PURE__ */
|
|
1259
|
-
vm.isLive ? /* @__PURE__ */
|
|
1260
|
-
/* @__PURE__ */
|
|
1635
|
+
/* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-header-right", children: [
|
|
1636
|
+
vm.isLive ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-live", children: [
|
|
1637
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1261
1638
|
ui?.liveLabel ?? "Live"
|
|
1262
1639
|
] }) : null,
|
|
1263
|
-
kickoff ? /* @__PURE__ */
|
|
1640
|
+
kickoff ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-kick", children: [
|
|
1264
1641
|
kickoff.dayLabel,
|
|
1265
1642
|
" ",
|
|
1266
1643
|
kickoff.time
|
|
1267
|
-
] }) : null
|
|
1644
|
+
] }) : null,
|
|
1645
|
+
showPin && ui ? /* @__PURE__ */ jsx13(
|
|
1646
|
+
PinToggle,
|
|
1647
|
+
{
|
|
1648
|
+
ui,
|
|
1649
|
+
monitor,
|
|
1650
|
+
pin: { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
|
|
1651
|
+
}
|
|
1652
|
+
) : null
|
|
1268
1653
|
] })
|
|
1269
1654
|
] }) : null,
|
|
1270
|
-
hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */
|
|
1271
|
-
hasNamedTeams ? /* @__PURE__ */
|
|
1272
|
-
/* @__PURE__ */
|
|
1273
|
-
/* @__PURE__ */
|
|
1274
|
-
/* @__PURE__ */
|
|
1275
|
-
/* @__PURE__ */
|
|
1276
|
-
/* @__PURE__ */
|
|
1277
|
-
] }) : vm.fixture ? /* @__PURE__ */
|
|
1278
|
-
vm.market ? /* @__PURE__ */
|
|
1655
|
+
hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-sub", children: [
|
|
1656
|
+
hasNamedTeams ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-fixture", children: [
|
|
1657
|
+
/* @__PURE__ */ jsx13(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
|
|
1658
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
|
|
1659
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1660
|
+
/* @__PURE__ */ jsx13("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
|
|
1661
|
+
/* @__PURE__ */ jsx13(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
|
|
1662
|
+
] }) : vm.fixture ? /* @__PURE__ */ jsx13("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
|
|
1663
|
+
vm.market ? /* @__PURE__ */ jsx13("span", { className: "ss-w-mo-market", children: vm.market }) : null
|
|
1279
1664
|
] }) : null,
|
|
1280
|
-
/* @__PURE__ */
|
|
1281
|
-
vm.mainRows.map((row) => /* @__PURE__ */
|
|
1282
|
-
open ? vm.moreRows.map((row) => /* @__PURE__ */
|
|
1665
|
+
/* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-rows", children: [
|
|
1666
|
+
vm.mainRows.map((row) => /* @__PURE__ */ jsx13(OddsRow, { vm, row, ui, slip, inSlipIds }, row.key)),
|
|
1667
|
+
open ? vm.moreRows.map((row) => /* @__PURE__ */ jsx13(OddsRow, { vm, row, ui, slip, inSlipIds }, row.key)) : null
|
|
1283
1668
|
] }),
|
|
1284
|
-
vm.moreRows.length > 0 ? /* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1669
|
+
vm.moreRows.length > 0 ? /* @__PURE__ */ jsxs9("button", { type: "button", className: "ss-w-mo-more", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
|
|
1670
|
+
/* @__PURE__ */ jsx13("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
|
|
1671
|
+
/* @__PURE__ */ jsx13("span", { className: `ss-w-mo-more-chev${open ? " ss-w-mo-more-chev-up" : ""}`, "aria-hidden": "true" })
|
|
1287
1672
|
] }) : null,
|
|
1288
|
-
vm.bookmaker ? /* @__PURE__ */
|
|
1289
|
-
vm.disclaimer ? /* @__PURE__ */
|
|
1673
|
+
vm.bookmaker ? /* @__PURE__ */ jsx13("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ jsx13("span", { children: vm.bookmaker }) }) : null,
|
|
1674
|
+
vm.disclaimer ? /* @__PURE__ */ jsx13("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
|
|
1290
1675
|
] });
|
|
1291
1676
|
}
|
|
1292
|
-
function MarketOddsCardList({ cards, ui, slip }) {
|
|
1677
|
+
function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds }) {
|
|
1293
1678
|
if (!cards || cards.length === 0) return null;
|
|
1294
|
-
return /* @__PURE__ */
|
|
1679
|
+
return /* @__PURE__ */ jsx13("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ jsx13(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds }, vm.id)) });
|
|
1295
1680
|
}
|
|
1296
1681
|
|
|
1297
1682
|
// src/components/OddsMovementCard.tsx
|
|
1298
|
-
import { Fragment as Fragment3, jsx as
|
|
1683
|
+
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1299
1684
|
function directionWord(vm, ui) {
|
|
1300
1685
|
if (vm.direction === "shortened") return ui?.oddsShortened ?? "shortened";
|
|
1301
1686
|
if (vm.direction === "drifted") return ui?.oddsDrifted ?? "drifted";
|
|
1302
1687
|
return "";
|
|
1303
1688
|
}
|
|
1304
|
-
function OddsMovementCard({ vm, ui }) {
|
|
1689
|
+
function OddsMovementCard({ vm, ui, monitor }) {
|
|
1305
1690
|
const word = directionWord(vm, ui);
|
|
1306
1691
|
const drift = word ? `, ${word}` : "";
|
|
1307
1692
|
const aria = ui?.chartAria ? ui.chartAria(vm.opening, vm.current, word, vm.windowHours) : `Price movement over the last ${vm.windowHours} hours: opened at ${vm.opening}, currently ${vm.current}${drift}.`;
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
/* @__PURE__ */
|
|
1693
|
+
const showPin = !!monitor && vm.pinEnabled;
|
|
1694
|
+
return /* @__PURE__ */ jsxs10("div", { className: "ss-w-omcard", children: [
|
|
1695
|
+
/* @__PURE__ */ jsxs10("div", { className: "ss-w-om-head", children: [
|
|
1696
|
+
/* @__PURE__ */ jsx14("span", { className: "ss-w-om-market", children: vm.market }),
|
|
1697
|
+
/* @__PURE__ */ jsx14("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" }),
|
|
1698
|
+
showPin && ui ? /* @__PURE__ */ jsx14(
|
|
1699
|
+
PinToggle,
|
|
1700
|
+
{
|
|
1701
|
+
ui,
|
|
1702
|
+
monitor,
|
|
1703
|
+
pin: {
|
|
1704
|
+
kind: "selection",
|
|
1705
|
+
matchId: vm.matchId,
|
|
1706
|
+
marketDeveloperName: vm.marketDeveloperName,
|
|
1707
|
+
selectionLabel: vm.selectionLabel,
|
|
1708
|
+
line: vm.line,
|
|
1709
|
+
withHistory: true,
|
|
1710
|
+
matchOddsId: vm.matchOddsId
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
) : null
|
|
1312
1714
|
] }),
|
|
1313
|
-
vm.fixture ? /* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
vm.competition ? /* @__PURE__ */
|
|
1715
|
+
vm.fixture ? /* @__PURE__ */ jsxs10("div", { className: "ss-w-om-fixture", children: [
|
|
1716
|
+
/* @__PURE__ */ jsx14("span", { children: vm.fixture }),
|
|
1717
|
+
vm.competition ? /* @__PURE__ */ jsx14("span", { className: "ss-w-om-comp", children: vm.competition }) : null
|
|
1316
1718
|
] }) : null,
|
|
1317
|
-
/* @__PURE__ */
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
vm.geometry === null ? /* @__PURE__ */
|
|
1719
|
+
/* @__PURE__ */ jsx14("div", { className: "ss-w-om-sel", children: vm.selection }),
|
|
1720
|
+
/* @__PURE__ */ jsx14(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
|
|
1721
|
+
vm.geometry === null ? /* @__PURE__ */ jsx14("div", { className: "ss-w-om-empty", children: vm.observationCount === 1 ? ui?.singlePricePoint ?? "Only one price recorded so far for this selection." : ui?.notEnoughHistory ?? "No price history recorded yet for this selection." }) : /* @__PURE__ */ jsxs10(
|
|
1320
1722
|
"svg",
|
|
1321
1723
|
{
|
|
1322
1724
|
className: "ss-w-om-chart",
|
|
@@ -1325,83 +1727,83 @@ function OddsMovementCard({ vm, ui }) {
|
|
|
1325
1727
|
role: "img",
|
|
1326
1728
|
"aria-label": aria,
|
|
1327
1729
|
children: [
|
|
1328
|
-
vm.geometry.gridlines.map((g) => /* @__PURE__ */
|
|
1329
|
-
/* @__PURE__ */
|
|
1330
|
-
/* @__PURE__ */
|
|
1730
|
+
vm.geometry.gridlines.map((g) => /* @__PURE__ */ jsxs10("g", { children: [
|
|
1731
|
+
/* @__PURE__ */ jsx14("line", { className: "ss-w-om-grid", x1: 40, y1: g.y, x2: CHART_VIEW_W - 8, y2: g.y }),
|
|
1732
|
+
/* @__PURE__ */ jsx14("text", { className: "ss-w-om-ylab", x: 34, y: g.y + 3, textAnchor: "end", children: g.price.toFixed(2) })
|
|
1331
1733
|
] }, g.price)),
|
|
1332
|
-
/* @__PURE__ */
|
|
1333
|
-
vm.geometry.markers.map((m, i) => /* @__PURE__ */
|
|
1334
|
-
ui?.chartTimeLabel ? /* @__PURE__ */
|
|
1335
|
-
/* @__PURE__ */
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
] }) : /* @__PURE__ */
|
|
1734
|
+
/* @__PURE__ */ jsx14("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
|
|
1735
|
+
vm.geometry.markers.map((m, i) => /* @__PURE__ */ jsx14("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
|
|
1736
|
+
ui?.chartTimeLabel ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
1737
|
+
/* @__PURE__ */ jsx14("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
|
|
1738
|
+
/* @__PURE__ */ jsx14("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
|
|
1739
|
+
] }) : /* @__PURE__ */ jsx14("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
|
|
1338
1740
|
]
|
|
1339
1741
|
}
|
|
1340
1742
|
),
|
|
1341
|
-
/* @__PURE__ */
|
|
1342
|
-
/* @__PURE__ */
|
|
1743
|
+
/* @__PURE__ */ jsxs10("div", { className: "ss-w-om-foot", children: [
|
|
1744
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
1343
1745
|
ui?.openingLabel ?? "Opening",
|
|
1344
1746
|
" ",
|
|
1345
|
-
/* @__PURE__ */
|
|
1747
|
+
/* @__PURE__ */ jsx14("b", { children: vm.opening })
|
|
1346
1748
|
] }),
|
|
1347
|
-
/* @__PURE__ */
|
|
1749
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
1348
1750
|
ui?.currentLabel ?? "Current",
|
|
1349
1751
|
" ",
|
|
1350
|
-
/* @__PURE__ */
|
|
1752
|
+
/* @__PURE__ */ jsx14("b", { children: vm.current })
|
|
1351
1753
|
] })
|
|
1352
1754
|
] }),
|
|
1353
|
-
vm.bookmaker ? /* @__PURE__ */
|
|
1354
|
-
vm.excludedCount > 0 ? /* @__PURE__ */
|
|
1355
|
-
vm.isSuspended ? /* @__PURE__ */
|
|
1356
|
-
vm.disclaimer ? /* @__PURE__ */
|
|
1755
|
+
vm.bookmaker ? /* @__PURE__ */ jsx14("div", { className: "ss-w-om-foot", children: /* @__PURE__ */ jsx14("span", { children: vm.bookmaker }) }) : null,
|
|
1756
|
+
vm.excludedCount > 0 ? /* @__PURE__ */ jsx14("div", { className: "ss-w-om-excl", children: ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.` }) : null,
|
|
1757
|
+
vm.isSuspended ? /* @__PURE__ */ jsx14("div", { className: "ss-w-om-susp", children: ui?.selectionSuspended ?? "This selection is not currently available to bet." }) : null,
|
|
1758
|
+
vm.disclaimer ? /* @__PURE__ */ jsx14("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
|
|
1357
1759
|
] });
|
|
1358
1760
|
}
|
|
1359
|
-
function OddsMovementCardList({ cards, ui }) {
|
|
1761
|
+
function OddsMovementCardList({ cards, ui, monitor }) {
|
|
1360
1762
|
if (!cards || cards.length === 0) return null;
|
|
1361
|
-
return /* @__PURE__ */
|
|
1763
|
+
return /* @__PURE__ */ jsx14("div", { className: "ss-w-omcards", children: cards.map((vm) => /* @__PURE__ */ jsx14(OddsMovementCard, { vm, ui, monitor }, vm.id)) });
|
|
1362
1764
|
}
|
|
1363
1765
|
|
|
1364
1766
|
// src/components/ActionButtons.tsx
|
|
1365
|
-
import { Fragment as Fragment4, jsx as
|
|
1767
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1366
1768
|
function ActionButtons({ actions, loading, disabled, onAct }) {
|
|
1367
1769
|
if (actions.length === 0 && !loading) return null;
|
|
1368
|
-
return /* @__PURE__ */
|
|
1369
|
-
actions.map((a, i) => /* @__PURE__ */
|
|
1370
|
-
actions.length === 0 && loading ? /* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
1372
|
-
/* @__PURE__ */
|
|
1770
|
+
return /* @__PURE__ */ jsxs11("div", { className: "ss-w-actions", children: [
|
|
1771
|
+
actions.map((a, i) => /* @__PURE__ */ jsx15("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
|
|
1772
|
+
actions.length === 0 && loading ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
1773
|
+
/* @__PURE__ */ jsx15("span", { className: "ss-w-abtn-shimmer" }),
|
|
1774
|
+
/* @__PURE__ */ jsx15("span", { className: "ss-w-abtn-shimmer" })
|
|
1373
1775
|
] }) : null
|
|
1374
1776
|
] });
|
|
1375
1777
|
}
|
|
1376
1778
|
|
|
1377
1779
|
// src/components/dashboard/DashboardTile.tsx
|
|
1378
|
-
import { jsx as
|
|
1780
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1379
1781
|
var MAX_CRESTS = 3;
|
|
1380
1782
|
function DashboardTile({ tile, onTap }) {
|
|
1381
1783
|
const spanClass = tile.span === "full" ? "ss-w-dash-tile--full" : "ss-w-dash-tile--half";
|
|
1382
1784
|
const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS);
|
|
1383
1785
|
const hasMeta = Boolean(tile.badgeText) || crests.length > 0;
|
|
1384
|
-
return /* @__PURE__ */
|
|
1385
|
-
/* @__PURE__ */
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1388
|
-
tile.subtitle ? /* @__PURE__ */
|
|
1786
|
+
return /* @__PURE__ */ jsxs12("button", { type: "button", className: `ss-w-dash-tile ${spanClass}`, onClick: onTap, children: [
|
|
1787
|
+
/* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ jsx16(DashboardIcon, { name: tile.icon }) }),
|
|
1788
|
+
/* @__PURE__ */ jsxs12("span", { className: "ss-w-dash-tile-body", children: [
|
|
1789
|
+
/* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-title", children: tile.title }),
|
|
1790
|
+
tile.subtitle ? /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
|
|
1389
1791
|
hasMeta ? (
|
|
1390
1792
|
// Badge + crests sit on their own row, below the title, instead of sharing the
|
|
1391
1793
|
// icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone
|
|
1392
1794
|
// (~70px) left the title column at ~22px and forced character-by-character wrapping.
|
|
1393
|
-
/* @__PURE__ */
|
|
1394
|
-
tile.badgeText ? /* @__PURE__ */
|
|
1395
|
-
crests.length > 0 ? /* @__PURE__ */
|
|
1795
|
+
/* @__PURE__ */ jsxs12("span", { className: "ss-w-dash-tile-meta", children: [
|
|
1796
|
+
tile.badgeText ? /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
|
|
1797
|
+
crests.length > 0 ? /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-crests", children: crests.map((url, i) => /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-crest", style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" }, `${url}-${i}`)) }) : null
|
|
1396
1798
|
] })
|
|
1397
1799
|
) : null
|
|
1398
1800
|
] }),
|
|
1399
|
-
/* @__PURE__ */
|
|
1801
|
+
/* @__PURE__ */ jsx16("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ jsx16(ChevronIcon, {}) })
|
|
1400
1802
|
] });
|
|
1401
1803
|
}
|
|
1402
1804
|
|
|
1403
1805
|
// src/components/dashboard/GreetingDashboard.tsx
|
|
1404
|
-
import { jsx as
|
|
1806
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1405
1807
|
var LAYOUT_CLASSES = {
|
|
1406
1808
|
market: "ss-w-dash--market",
|
|
1407
1809
|
goal: "ss-w-dash--goal",
|
|
@@ -1411,109 +1813,109 @@ function layoutClass(layout) {
|
|
|
1411
1813
|
return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout) ? LAYOUT_CLASSES[layout] : LAYOUT_CLASSES.goal;
|
|
1412
1814
|
}
|
|
1413
1815
|
function GreetingDashboard({ dashboard, onTap }) {
|
|
1414
|
-
return /* @__PURE__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1416
|
-
/* @__PURE__ */
|
|
1417
|
-
dashboard.subtitle ? /* @__PURE__ */
|
|
1816
|
+
return /* @__PURE__ */ jsxs13("div", { className: `ss-w-dash ${layoutClass(dashboard.layout)}`, children: [
|
|
1817
|
+
/* @__PURE__ */ jsxs13("div", { className: "ss-w-dash-head", children: [
|
|
1818
|
+
/* @__PURE__ */ jsx17("span", { className: "ss-w-dash-title", children: dashboard.title }),
|
|
1819
|
+
dashboard.subtitle ? /* @__PURE__ */ jsx17("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
|
|
1418
1820
|
] }),
|
|
1419
|
-
/* @__PURE__ */
|
|
1420
|
-
dashboard.footerTip ? /* @__PURE__ */
|
|
1821
|
+
/* @__PURE__ */ jsx17("div", { className: "ss-w-dash-grid", children: dashboard.tiles.map((t, i) => /* @__PURE__ */ jsx17(DashboardTile, { tile: t, onTap: () => onTap(t, i) }, `${t.title}-${i}`)) }),
|
|
1822
|
+
dashboard.footerTip ? /* @__PURE__ */ jsx17("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
|
|
1421
1823
|
] });
|
|
1422
1824
|
}
|
|
1423
1825
|
|
|
1424
1826
|
// src/components/dashboard/FixtureCard.tsx
|
|
1425
|
-
import { Fragment as Fragment5, jsx as
|
|
1827
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1426
1828
|
function teamFormResultClass(result) {
|
|
1427
1829
|
if (result === "W") return "ss-w-fandash-teamform-cell--win";
|
|
1428
1830
|
if (result === "L") return "ss-w-fandash-teamform-cell--loss";
|
|
1429
1831
|
return "ss-w-fandash-teamform-cell--draw";
|
|
1430
1832
|
}
|
|
1431
1833
|
function TeamFormCell({ m, subjectCrestUrl, subjectName }) {
|
|
1432
|
-
const subjectCrest = /* @__PURE__ */
|
|
1433
|
-
const opponentCrest = /* @__PURE__ */
|
|
1834
|
+
const subjectCrest = /* @__PURE__ */ jsx18(Crest2, { url: subjectCrestUrl ?? void 0, name: subjectName, kind: "team" });
|
|
1835
|
+
const opponentCrest = /* @__PURE__ */ jsx18(Crest2, { url: m.opponentCrestUrl ?? void 0, kind: "team" });
|
|
1434
1836
|
const score = m.teamIsHome ? `${m.teamScore} - ${m.oppScore}` : `${m.oppScore} - ${m.teamScore}`;
|
|
1435
|
-
return /* @__PURE__ */
|
|
1837
|
+
return /* @__PURE__ */ jsxs14("div", { className: `ss-w-fandash-teamform-cell ${teamFormResultClass(m.result)}`, children: [
|
|
1436
1838
|
m.teamIsHome ? subjectCrest : opponentCrest,
|
|
1437
|
-
/* @__PURE__ */
|
|
1839
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-teamform-score", children: score }),
|
|
1438
1840
|
m.teamIsHome ? opponentCrest : subjectCrest
|
|
1439
1841
|
] });
|
|
1440
1842
|
}
|
|
1441
1843
|
var TEAM_FORM_ROWS = 5;
|
|
1442
1844
|
function teamFormRows(data) {
|
|
1443
1845
|
return Array.from({ length: TEAM_FORM_ROWS }, (_, i) => i).flatMap((i) => [
|
|
1444
|
-
/* @__PURE__ */
|
|
1445
|
-
/* @__PURE__ */
|
|
1846
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-teamform-slot", children: data.homeForm[i] ? /* @__PURE__ */ jsx18(TeamFormCell, { m: data.homeForm[i], subjectCrestUrl: data.homeCrestUrl, subjectName: data.homeName }) : null }, `h-${i}`),
|
|
1847
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-teamform-slot", children: data.awayForm[i] ? /* @__PURE__ */ jsx18(TeamFormCell, { m: data.awayForm[i], subjectCrestUrl: data.awayCrestUrl, subjectName: data.awayName }) : null }, `a-${i}`)
|
|
1446
1848
|
]);
|
|
1447
1849
|
}
|
|
1448
1850
|
function FixtureCard({ card }) {
|
|
1449
1851
|
const { data } = card;
|
|
1450
1852
|
const h2h = data.h2H;
|
|
1451
|
-
return /* @__PURE__ */
|
|
1452
|
-
/* @__PURE__ */
|
|
1453
|
-
/* @__PURE__ */
|
|
1853
|
+
return /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
1854
|
+
/* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-card ss-w-fandash-fixture", children: [
|
|
1855
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-eyebrow", children: [
|
|
1454
1856
|
card.title,
|
|
1455
1857
|
" \xB7 ",
|
|
1456
1858
|
data.competition
|
|
1457
1859
|
] }),
|
|
1458
|
-
/* @__PURE__ */
|
|
1459
|
-
/* @__PURE__ */
|
|
1460
|
-
/* @__PURE__ */
|
|
1461
|
-
/* @__PURE__ */
|
|
1860
|
+
/* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-fixture-teams", children: [
|
|
1861
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-fixture-team", children: [
|
|
1862
|
+
/* @__PURE__ */ jsx18(Crest2, { url: data.homeCrestUrl ?? void 0, name: data.homeName, kind: "team" }),
|
|
1863
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-fixture-name", children: data.homeName })
|
|
1462
1864
|
] }),
|
|
1463
|
-
/* @__PURE__ */
|
|
1464
|
-
/* @__PURE__ */
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
/* @__PURE__ */
|
|
1865
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-fixture-vs", children: "v" }),
|
|
1866
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-fixture-team ss-w-fandash-fixture-team--away", children: [
|
|
1867
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-fixture-name", children: data.awayName }),
|
|
1868
|
+
/* @__PURE__ */ jsx18(Crest2, { url: data.awayCrestUrl ?? void 0, name: data.awayName, kind: "team" })
|
|
1467
1869
|
] })
|
|
1468
1870
|
] }),
|
|
1469
|
-
/* @__PURE__ */
|
|
1470
|
-
/* @__PURE__ */
|
|
1471
|
-
data.venue ? /* @__PURE__ */
|
|
1871
|
+
/* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-fixture-meta", children: [
|
|
1872
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-fixture-kickoff", children: data.kickoffLabel }),
|
|
1873
|
+
data.venue ? /* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-fixture-venue", children: [
|
|
1472
1874
|
" \xB7 ",
|
|
1473
1875
|
data.venue
|
|
1474
1876
|
] }) : null
|
|
1475
1877
|
] })
|
|
1476
1878
|
] }),
|
|
1477
|
-
/* @__PURE__ */
|
|
1478
|
-
/* @__PURE__ */
|
|
1479
|
-
/* @__PURE__ */
|
|
1480
|
-
/* @__PURE__ */
|
|
1481
|
-
/* @__PURE__ */
|
|
1482
|
-
/* @__PURE__ */
|
|
1879
|
+
/* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-card ss-w-fandash-lastfive", children: [
|
|
1880
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-eyebrow", children: data.formLabel }),
|
|
1881
|
+
/* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-teamform-head", children: [
|
|
1882
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-teamform-head-team", children: [
|
|
1883
|
+
/* @__PURE__ */ jsx18(Crest2, { url: data.homeCrestUrl ?? void 0, name: data.homeName, kind: "team" }),
|
|
1884
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-teamform-head-name", children: data.homeName })
|
|
1483
1885
|
] }),
|
|
1484
|
-
/* @__PURE__ */
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
/* @__PURE__ */
|
|
1886
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-teamform-head-team", children: [
|
|
1887
|
+
/* @__PURE__ */ jsx18(Crest2, { url: data.awayCrestUrl ?? void 0, name: data.awayName, kind: "team" }),
|
|
1888
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-teamform-head-name", children: data.awayName })
|
|
1487
1889
|
] })
|
|
1488
1890
|
] }),
|
|
1489
|
-
/* @__PURE__ */
|
|
1891
|
+
/* @__PURE__ */ jsx18("div", { className: "ss-w-fandash-teamform-rows", children: teamFormRows(data) })
|
|
1490
1892
|
] }),
|
|
1491
|
-
h2h || data.fact ? /* @__PURE__ */
|
|
1492
|
-
h2h ? /* @__PURE__ */
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
/* @__PURE__ */
|
|
1495
|
-
/* @__PURE__ */
|
|
1496
|
-
/* @__PURE__ */
|
|
1497
|
-
/* @__PURE__ */
|
|
1893
|
+
h2h || data.fact ? /* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-card ss-w-fandash-h2h", children: [
|
|
1894
|
+
h2h ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
1895
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-eyebrow", children: h2h.label }),
|
|
1896
|
+
/* @__PURE__ */ jsxs14("div", { className: "ss-w-fandash-split", children: [
|
|
1897
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-split-cell", children: [
|
|
1898
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-split-value", children: h2h.wins }),
|
|
1899
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-split-label", children: h2h.homeWinsLabel })
|
|
1498
1900
|
] }),
|
|
1499
|
-
/* @__PURE__ */
|
|
1500
|
-
/* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1901
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-split-cell", children: [
|
|
1902
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-split-value", children: h2h.draws }),
|
|
1903
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-split-label", children: h2h.drawsLabel })
|
|
1502
1904
|
] }),
|
|
1503
|
-
/* @__PURE__ */
|
|
1504
|
-
/* @__PURE__ */
|
|
1505
|
-
/* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ jsxs14("span", { className: "ss-w-fandash-split-cell", children: [
|
|
1906
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-split-value", children: h2h.losses }),
|
|
1907
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-split-label", children: h2h.awayWinsLabel })
|
|
1506
1908
|
] })
|
|
1507
1909
|
] })
|
|
1508
1910
|
] }) : null,
|
|
1509
|
-
data.fact ? /* @__PURE__ */
|
|
1911
|
+
data.fact ? /* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-fact", children: data.fact }) : null
|
|
1510
1912
|
] }) : null
|
|
1511
1913
|
] });
|
|
1512
1914
|
}
|
|
1513
1915
|
|
|
1514
1916
|
// src/components/dashboard/CountdownCard.tsx
|
|
1515
|
-
import { Fragment as Fragment6, useEffect as
|
|
1516
|
-
import { jsx as
|
|
1917
|
+
import { Fragment as Fragment6, useEffect as useEffect5, useState as useState8 } from "react";
|
|
1918
|
+
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1517
1919
|
var DAY_MS = 864e5;
|
|
1518
1920
|
function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
1519
1921
|
const totalSeconds = Math.floor((kickoffUnix * 1e3 - nowMs) / 1e3);
|
|
@@ -1531,72 +1933,72 @@ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
|
1531
1933
|
function CountdownCard({ card }) {
|
|
1532
1934
|
const { data } = card;
|
|
1533
1935
|
const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
|
|
1534
|
-
const [nowMs, setNowMs] =
|
|
1535
|
-
const [reduced] =
|
|
1936
|
+
const [nowMs, setNowMs] = useState8(() => Date.now());
|
|
1937
|
+
const [reduced] = useState8(
|
|
1536
1938
|
() => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
1537
1939
|
);
|
|
1538
1940
|
const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
|
|
1539
|
-
|
|
1941
|
+
useEffect5(() => {
|
|
1540
1942
|
if (reduced) return;
|
|
1541
1943
|
const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
|
|
1542
1944
|
return () => window.clearInterval(id);
|
|
1543
1945
|
}, [reduced, withinDay]);
|
|
1544
1946
|
const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced);
|
|
1545
|
-
return /* @__PURE__ */
|
|
1546
|
-
/* @__PURE__ */
|
|
1547
|
-
segments ? /* @__PURE__ */
|
|
1548
|
-
i > 0 ? /* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1550
|
-
/* @__PURE__ */
|
|
1551
|
-
/* @__PURE__ */
|
|
1947
|
+
return /* @__PURE__ */ jsx19("div", { className: "ss-w-fandash-card ss-w-fandash-countdown", children: /* @__PURE__ */ jsxs15("div", { className: "ss-w-fandash-countdown-top", children: [
|
|
1948
|
+
/* @__PURE__ */ jsx19("span", { className: "ss-w-fandash-eyebrow", children: card.title ?? "Kick-off in" }),
|
|
1949
|
+
segments ? /* @__PURE__ */ jsx19("span", { className: "ss-w-fandash-countdown-clock", children: segments.map((s, i) => /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
1950
|
+
i > 0 ? /* @__PURE__ */ jsx19("span", { className: "ss-w-fandash-countdown-colon", children: ":" }) : null,
|
|
1951
|
+
/* @__PURE__ */ jsxs15("span", { className: "ss-w-fandash-countdown-seg", children: [
|
|
1952
|
+
/* @__PURE__ */ jsx19("span", { className: "ss-w-fandash-countdown-value", children: s.value }),
|
|
1953
|
+
/* @__PURE__ */ jsx19("span", { className: "ss-w-fandash-countdown-unit", children: unitLabel[s.unit] })
|
|
1552
1954
|
] })
|
|
1553
1955
|
] }, s.unit)) }) : null
|
|
1554
1956
|
] }) });
|
|
1555
1957
|
}
|
|
1556
1958
|
|
|
1557
1959
|
// src/components/dashboard/InjuriesCard.tsx
|
|
1558
|
-
import { useState as
|
|
1559
|
-
import { jsx as
|
|
1960
|
+
import { useState as useState9 } from "react";
|
|
1961
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1560
1962
|
var SHOWN = 3;
|
|
1561
1963
|
function ColHead({ name, crestUrl }) {
|
|
1562
|
-
return /* @__PURE__ */
|
|
1563
|
-
/* @__PURE__ */
|
|
1564
|
-
/* @__PURE__ */
|
|
1964
|
+
return /* @__PURE__ */ jsxs16("span", { className: "ss-w-fandash-injuries-col-head", children: [
|
|
1965
|
+
/* @__PURE__ */ jsx20(Crest2, { url: crestUrl ?? void 0, name, kind: "team" }),
|
|
1966
|
+
/* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injuries-col-head-name", children: name })
|
|
1565
1967
|
] });
|
|
1566
1968
|
}
|
|
1567
1969
|
function InjuryList({ rows, emptyLabel, limit }) {
|
|
1568
|
-
if (rows.length === 0) return /* @__PURE__ */
|
|
1970
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injuries-empty", children: emptyLabel });
|
|
1569
1971
|
const shown = limit === void 0 ? rows : rows.slice(0, limit);
|
|
1570
|
-
return /* @__PURE__ */
|
|
1571
|
-
/* @__PURE__ */
|
|
1572
|
-
/* @__PURE__ */
|
|
1573
|
-
/* @__PURE__ */
|
|
1574
|
-
r.injuryType ? /* @__PURE__ */
|
|
1575
|
-
r.expectedReturnLabel ? /* @__PURE__ */
|
|
1972
|
+
return /* @__PURE__ */ jsx20("ul", { className: "ss-w-fandash-injury-list", children: shown.map((r, i) => /* @__PURE__ */ jsxs16("li", { className: "ss-w-fandash-injury-row", children: [
|
|
1973
|
+
/* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injury-name", children: r.playerName }),
|
|
1974
|
+
/* @__PURE__ */ jsxs16("span", { className: "ss-w-fandash-injury-meta", children: [
|
|
1975
|
+
/* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injury-status", children: r.status }),
|
|
1976
|
+
r.injuryType ? /* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injury-type", children: r.injuryType }) : null,
|
|
1977
|
+
r.expectedReturnLabel ? /* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injury-return", children: r.expectedReturnLabel }) : null
|
|
1576
1978
|
] })
|
|
1577
1979
|
] }, `${r.playerName}-${i}`)) });
|
|
1578
1980
|
}
|
|
1579
1981
|
function InjuriesCard({ card, ui }) {
|
|
1580
1982
|
const { data } = card;
|
|
1581
|
-
const [expanded, setExpanded] =
|
|
1983
|
+
const [expanded, setExpanded] = useState9(false);
|
|
1582
1984
|
const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
|
|
1583
1985
|
const limit = expanded ? void 0 : SHOWN;
|
|
1584
1986
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
1585
1987
|
const showLess = ui?.showLess ?? "Show less";
|
|
1586
|
-
return /* @__PURE__ */
|
|
1587
|
-
card.title ? /* @__PURE__ */
|
|
1588
|
-
/* @__PURE__ */
|
|
1589
|
-
/* @__PURE__ */
|
|
1590
|
-
/* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1988
|
+
return /* @__PURE__ */ jsxs16("div", { className: "ss-w-fandash-card ss-w-fandash-injuries", children: [
|
|
1989
|
+
card.title ? /* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
1990
|
+
/* @__PURE__ */ jsxs16("div", { className: "ss-w-fandash-injuries-cols", children: [
|
|
1991
|
+
/* @__PURE__ */ jsxs16("div", { className: "ss-w-fandash-injuries-col", children: [
|
|
1992
|
+
/* @__PURE__ */ jsx20(ColHead, { name: data.oursName, crestUrl: data.oursCrestUrl }),
|
|
1993
|
+
/* @__PURE__ */ jsx20(InjuryList, { rows: data.ours, emptyLabel: data.emptyLabel, limit })
|
|
1592
1994
|
] }),
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1995
|
+
/* @__PURE__ */ jsx20("div", { className: "ss-w-fandash-injuries-divider" }),
|
|
1996
|
+
/* @__PURE__ */ jsxs16("div", { className: "ss-w-fandash-injuries-col", children: [
|
|
1997
|
+
/* @__PURE__ */ jsx20(ColHead, { name: data.theirsName, crestUrl: data.theirsCrestUrl }),
|
|
1998
|
+
/* @__PURE__ */ jsx20(InjuryList, { rows: data.theirs, emptyLabel: data.emptyLabel, limit })
|
|
1597
1999
|
] })
|
|
1598
2000
|
] }),
|
|
1599
|
-
hidden > 0 ? /* @__PURE__ */
|
|
2001
|
+
hidden > 0 ? /* @__PURE__ */ jsx20(
|
|
1600
2002
|
"button",
|
|
1601
2003
|
{
|
|
1602
2004
|
type: "button",
|
|
@@ -1610,80 +2012,80 @@ function InjuriesCard({ card, ui }) {
|
|
|
1610
2012
|
}
|
|
1611
2013
|
|
|
1612
2014
|
// src/components/dashboard/ReasonToBetCard.tsx
|
|
1613
|
-
import { jsx as
|
|
2015
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1614
2016
|
function ReasonToBetCard({ card }) {
|
|
1615
|
-
return /* @__PURE__ */
|
|
1616
|
-
card.title ? /* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
2017
|
+
return /* @__PURE__ */ jsxs17("div", { className: "ss-w-fandash-card ss-w-fandash-reasons", children: [
|
|
2018
|
+
card.title ? /* @__PURE__ */ jsx21("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2019
|
+
/* @__PURE__ */ jsx21("ul", { className: "ss-w-fandash-reason-list", children: card.data.angles.map((angle, i) => /* @__PURE__ */ jsx21("li", { className: "ss-w-fandash-reason-item", children: angle }, `${angle}-${i}`)) })
|
|
1618
2020
|
] });
|
|
1619
2021
|
}
|
|
1620
2022
|
|
|
1621
2023
|
// src/components/dashboard/WhereToWatchCard.tsx
|
|
1622
|
-
import { jsx as
|
|
2024
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1623
2025
|
function WhereToWatchCard({ card }) {
|
|
1624
|
-
return /* @__PURE__ */
|
|
1625
|
-
card.title ? /* @__PURE__ */
|
|
1626
|
-
/* @__PURE__ */
|
|
2026
|
+
return /* @__PURE__ */ jsxs18("div", { className: "ss-w-fandash-card ss-w-fandash-watch", children: [
|
|
2027
|
+
card.title ? /* @__PURE__ */ jsx22("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2028
|
+
/* @__PURE__ */ jsx22("span", { className: "ss-w-fandash-stations", children: card.data.stations.map((station, i) => /* @__PURE__ */ jsx22("span", { className: "ss-w-fandash-station-chip", children: station }, `${station}-${i}`)) })
|
|
1627
2029
|
] });
|
|
1628
2030
|
}
|
|
1629
2031
|
|
|
1630
2032
|
// src/components/dashboard/CongestedWeekCard.tsx
|
|
1631
|
-
import { jsx as
|
|
2033
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1632
2034
|
function CongestedWeekCard({ card, onTap }) {
|
|
1633
|
-
return /* @__PURE__ */
|
|
1634
|
-
card.title ? /* @__PURE__ */
|
|
1635
|
-
/* @__PURE__ */
|
|
1636
|
-
/* @__PURE__ */
|
|
1637
|
-
/* @__PURE__ */
|
|
1638
|
-
/* @__PURE__ */
|
|
1639
|
-
/* @__PURE__ */
|
|
2035
|
+
return /* @__PURE__ */ jsxs19("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-congested", onClick: () => onTap(card), children: [
|
|
2036
|
+
card.title ? /* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2037
|
+
/* @__PURE__ */ jsx23("div", { className: "ss-w-fandash-congested-grid", children: card.data.entries.map((entry, i) => /* @__PURE__ */ jsxs19("span", { className: "ss-w-fandash-congested-cell", children: [
|
|
2038
|
+
/* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-congested-day", children: entry.dayLabel }),
|
|
2039
|
+
/* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-congested-opponent", children: entry.opponent }),
|
|
2040
|
+
/* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-congested-comp", children: entry.competition }),
|
|
2041
|
+
/* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-congested-time", children: entry.timeLabel })
|
|
1640
2042
|
] }, `${entry.opponent}-${i}`)) }),
|
|
1641
|
-
/* @__PURE__ */
|
|
2043
|
+
/* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1642
2044
|
] });
|
|
1643
2045
|
}
|
|
1644
2046
|
|
|
1645
2047
|
// src/components/dashboard/TransfersCard.tsx
|
|
1646
|
-
import { jsx as
|
|
2048
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1647
2049
|
function TransferList({ rows }) {
|
|
1648
|
-
if (rows.length === 0) return /* @__PURE__ */
|
|
1649
|
-
return /* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
1652
|
-
r.type ? /* @__PURE__ */
|
|
2050
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-transfers-empty", children: "None" });
|
|
2051
|
+
return /* @__PURE__ */ jsx24("ul", { className: "ss-w-fandash-transfer-list", children: rows.map((r, i) => /* @__PURE__ */ jsxs20("li", { className: "ss-w-fandash-transfer-row", children: [
|
|
2052
|
+
/* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-transfer-name", children: r.playerName }),
|
|
2053
|
+
/* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-transfer-club", children: r.otherClub }),
|
|
2054
|
+
r.type ? /* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-transfer-type", children: r.type }) : null
|
|
1653
2055
|
] }, `${r.playerName}-${i}`)) });
|
|
1654
2056
|
}
|
|
1655
2057
|
function TransfersCard({ card }) {
|
|
1656
2058
|
const { data } = card;
|
|
1657
|
-
return /* @__PURE__ */
|
|
1658
|
-
card.title ? /* @__PURE__ */
|
|
1659
|
-
/* @__PURE__ */
|
|
1660
|
-
/* @__PURE__ */
|
|
1661
|
-
/* @__PURE__ */
|
|
1662
|
-
/* @__PURE__ */
|
|
2059
|
+
return /* @__PURE__ */ jsxs20("div", { className: "ss-w-fandash-card ss-w-fandash-transfers", children: [
|
|
2060
|
+
card.title ? /* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2061
|
+
/* @__PURE__ */ jsxs20("div", { className: "ss-w-fandash-transfers-cols", children: [
|
|
2062
|
+
/* @__PURE__ */ jsxs20("div", { className: "ss-w-fandash-transfers-col", children: [
|
|
2063
|
+
/* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-transfers-col-head", children: "In" }),
|
|
2064
|
+
/* @__PURE__ */ jsx24(TransferList, { rows: data.in })
|
|
1663
2065
|
] }),
|
|
1664
|
-
/* @__PURE__ */
|
|
1665
|
-
/* @__PURE__ */
|
|
1666
|
-
/* @__PURE__ */
|
|
2066
|
+
/* @__PURE__ */ jsxs20("div", { className: "ss-w-fandash-transfers-col", children: [
|
|
2067
|
+
/* @__PURE__ */ jsx24("span", { className: "ss-w-fandash-transfers-col-head", children: "Out" }),
|
|
2068
|
+
/* @__PURE__ */ jsx24(TransferList, { rows: data.out })
|
|
1667
2069
|
] })
|
|
1668
2070
|
] })
|
|
1669
2071
|
] });
|
|
1670
2072
|
}
|
|
1671
2073
|
|
|
1672
2074
|
// src/components/dashboard/LinksCard.tsx
|
|
1673
|
-
import { jsx as
|
|
2075
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1674
2076
|
function LinksCard({ card }) {
|
|
1675
|
-
return /* @__PURE__ */
|
|
1676
|
-
card.title ? /* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
/* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
2077
|
+
return /* @__PURE__ */ jsxs21("div", { className: "ss-w-fandash-card ss-w-fandash-links", children: [
|
|
2078
|
+
card.title ? /* @__PURE__ */ jsx25("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2079
|
+
/* @__PURE__ */ jsx25("div", { className: "ss-w-fandash-link-grid", children: card.data.links.map((link, i) => /* @__PURE__ */ jsxs21("a", { className: "ss-w-fandash-link-tile", href: link.url, target: "_blank", rel: "noopener noreferrer", children: [
|
|
2080
|
+
/* @__PURE__ */ jsx25("span", { className: "ss-w-fandash-link-label", children: link.label }),
|
|
2081
|
+
/* @__PURE__ */ jsx25("span", { className: "ss-w-fandash-link-chevron", children: /* @__PURE__ */ jsx25(ChevronIcon, {}) })
|
|
1680
2082
|
] }, `${link.url}-${i}`)) })
|
|
1681
2083
|
] });
|
|
1682
2084
|
}
|
|
1683
2085
|
|
|
1684
2086
|
// src/components/dashboard/PostMatchResultCard.tsx
|
|
1685
|
-
import { useState as
|
|
1686
|
-
import { jsx as
|
|
2087
|
+
import { useState as useState10 } from "react";
|
|
2088
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1687
2089
|
function initials3(name) {
|
|
1688
2090
|
return name.trim().slice(0, 3).toUpperCase();
|
|
1689
2091
|
}
|
|
@@ -1692,37 +2094,37 @@ function PostMatchCrest({
|
|
|
1692
2094
|
name,
|
|
1693
2095
|
side
|
|
1694
2096
|
}) {
|
|
1695
|
-
const [failed, setFailed] =
|
|
2097
|
+
const [failed, setFailed] = useState10(false);
|
|
1696
2098
|
const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
|
|
1697
2099
|
if (url && !failed) {
|
|
1698
|
-
return /* @__PURE__ */
|
|
2100
|
+
return /* @__PURE__ */ jsx26("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1699
2101
|
}
|
|
1700
|
-
return /* @__PURE__ */
|
|
2102
|
+
return /* @__PURE__ */ jsx26("span", { className: `${cls} ss-w-fandash-postmatch-crest--fallback`, "aria-hidden": "true", children: initials3(name) });
|
|
1701
2103
|
}
|
|
1702
2104
|
function PostMatchResultCard({ card }) {
|
|
1703
2105
|
const { data } = card;
|
|
1704
2106
|
const homeWon = data.homeScore >= data.awayScore;
|
|
1705
2107
|
const awayWon = data.awayScore >= data.homeScore;
|
|
1706
|
-
return /* @__PURE__ */
|
|
1707
|
-
/* @__PURE__ */
|
|
1708
|
-
card.title ? /* @__PURE__ */
|
|
1709
|
-
/* @__PURE__ */
|
|
2108
|
+
return /* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-card ss-w-fandash-postmatch-result", children: [
|
|
2109
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-top", children: [
|
|
2110
|
+
card.title ? /* @__PURE__ */ jsx26("span", { className: "ss-w-fandash-postmatch-pill", children: card.title }) : null,
|
|
2111
|
+
/* @__PURE__ */ jsx26("span", { className: `ss-w-fandash-postmatch-tag ss-w-fandash-postmatch-tag--${data.outcome}`, children: data.resultLabel })
|
|
1710
2112
|
] }),
|
|
1711
|
-
/* @__PURE__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
2113
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-main", children: [
|
|
2114
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--home", children: [
|
|
2115
|
+
/* @__PURE__ */ jsx26(PostMatchCrest, { url: data.homeCrestUrl, name: data.homeName, side: "home" }),
|
|
2116
|
+
/* @__PURE__ */ jsx26("span", { className: "ss-w-fandash-postmatch-team-name", children: data.homeName })
|
|
1715
2117
|
] }),
|
|
1716
|
-
/* @__PURE__ */
|
|
1717
|
-
/* @__PURE__ */
|
|
2118
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-score-main", children: [
|
|
2119
|
+
/* @__PURE__ */ jsx26(
|
|
1718
2120
|
"span",
|
|
1719
2121
|
{
|
|
1720
2122
|
className: `ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${homeWon ? "win" : "lose"}`,
|
|
1721
2123
|
children: data.homeScore
|
|
1722
2124
|
}
|
|
1723
2125
|
),
|
|
1724
|
-
/* @__PURE__ */
|
|
1725
|
-
/* @__PURE__ */
|
|
2126
|
+
/* @__PURE__ */ jsx26("span", { className: "ss-w-fandash-postmatch-score-sep", children: "\u2013" }),
|
|
2127
|
+
/* @__PURE__ */ jsx26(
|
|
1726
2128
|
"span",
|
|
1727
2129
|
{
|
|
1728
2130
|
className: `ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${awayWon ? "win" : "lose"}`,
|
|
@@ -1730,12 +2132,12 @@ function PostMatchResultCard({ card }) {
|
|
|
1730
2132
|
}
|
|
1731
2133
|
)
|
|
1732
2134
|
] }),
|
|
1733
|
-
/* @__PURE__ */
|
|
1734
|
-
/* @__PURE__ */
|
|
1735
|
-
/* @__PURE__ */
|
|
2135
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--away", children: [
|
|
2136
|
+
/* @__PURE__ */ jsx26(PostMatchCrest, { url: data.awayCrestUrl, name: data.awayName, side: "away" }),
|
|
2137
|
+
/* @__PURE__ */ jsx26("span", { className: "ss-w-fandash-postmatch-team-name", children: data.awayName })
|
|
1736
2138
|
] })
|
|
1737
2139
|
] }),
|
|
1738
|
-
/* @__PURE__ */
|
|
2140
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-meta", children: [
|
|
1739
2141
|
data.kickoffLabel,
|
|
1740
2142
|
data.competition ? ` \xB7 ${data.competition}` : ""
|
|
1741
2143
|
] })
|
|
@@ -1743,20 +2145,20 @@ function PostMatchResultCard({ card }) {
|
|
|
1743
2145
|
}
|
|
1744
2146
|
|
|
1745
2147
|
// src/components/dashboard/PostMatchGoalsCard.tsx
|
|
1746
|
-
import { jsx as
|
|
2148
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1747
2149
|
function PostMatchGoalsCard({ card, onTap }) {
|
|
1748
|
-
return /* @__PURE__ */
|
|
1749
|
-
card.title ? /* @__PURE__ */
|
|
1750
|
-
/* @__PURE__ */
|
|
1751
|
-
/* @__PURE__ */
|
|
1752
|
-
/* @__PURE__ */
|
|
2150
|
+
return /* @__PURE__ */ jsxs23("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-goals", onClick: () => onTap(card), children: [
|
|
2151
|
+
card.title ? /* @__PURE__ */ jsx27("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2152
|
+
/* @__PURE__ */ jsx27("ul", { className: "ss-w-fandash-postmatch-goal-list", children: card.data.goals.map((g, i) => /* @__PURE__ */ jsxs23("li", { className: g.scoredByClub ? "ss-w-fandash-postmatch-goal ss-w-fandash-postmatch-goal--club" : "ss-w-fandash-postmatch-goal", children: [
|
|
2153
|
+
/* @__PURE__ */ jsx27("span", { className: "ss-w-fandash-postmatch-goal-ball" }),
|
|
2154
|
+
/* @__PURE__ */ jsx27("span", { children: g.text })
|
|
1753
2155
|
] }, `${g.text}-${i}`)) }),
|
|
1754
|
-
/* @__PURE__ */
|
|
2156
|
+
/* @__PURE__ */ jsx27("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1755
2157
|
] });
|
|
1756
2158
|
}
|
|
1757
2159
|
|
|
1758
2160
|
// src/components/dashboard/PostMatchStatsCard.tsx
|
|
1759
|
-
import { jsx as
|
|
2161
|
+
import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1760
2162
|
function splitWidths(homeNum, awayNum) {
|
|
1761
2163
|
const total = homeNum + awayNum;
|
|
1762
2164
|
if (total <= 0) return { home: "50%", away: "50%" };
|
|
@@ -1765,42 +2167,42 @@ function splitWidths(homeNum, awayNum) {
|
|
|
1765
2167
|
}
|
|
1766
2168
|
function PostMatchStatsCard({ card, onTap }) {
|
|
1767
2169
|
const { data } = card;
|
|
1768
|
-
return /* @__PURE__ */
|
|
1769
|
-
card.title ? /* @__PURE__ */
|
|
1770
|
-
/* @__PURE__ */
|
|
2170
|
+
return /* @__PURE__ */ jsxs24("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-stats", onClick: () => onTap(card), children: [
|
|
2171
|
+
card.title ? /* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2172
|
+
/* @__PURE__ */ jsx28("div", { className: "ss-w-fandash-postmatch-stat-rows", children: data.rows.map((r, i) => {
|
|
1771
2173
|
const leftValue = data.clubIsHome ? r.clubValue : r.oppValue;
|
|
1772
2174
|
const rightValue = data.clubIsHome ? r.oppValue : r.clubValue;
|
|
1773
2175
|
const homeNum = data.clubIsHome ? r.clubNum : r.oppNum;
|
|
1774
2176
|
const awayNum = data.clubIsHome ? r.oppNum : r.clubNum;
|
|
1775
2177
|
const { home, away } = splitWidths(homeNum, awayNum);
|
|
1776
|
-
return /* @__PURE__ */
|
|
1777
|
-
/* @__PURE__ */
|
|
1778
|
-
/* @__PURE__ */
|
|
1779
|
-
/* @__PURE__ */
|
|
1780
|
-
/* @__PURE__ */
|
|
2178
|
+
return /* @__PURE__ */ jsxs24("div", { className: "ss-w-fandash-postmatch-stat", children: [
|
|
2179
|
+
/* @__PURE__ */ jsxs24("div", { className: "ss-w-fandash-postmatch-stat-row", children: [
|
|
2180
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--home", children: leftValue }),
|
|
2181
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-postmatch-stat-label", children: r.label }),
|
|
2182
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--away", children: rightValue })
|
|
1781
2183
|
] }),
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
/* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
2184
|
+
/* @__PURE__ */ jsxs24("div", { className: "ss-w-fandash-postmatch-stat-bar", children: [
|
|
2185
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-postmatch-stat-bar-home", style: { width: home } }),
|
|
2186
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-postmatch-stat-bar-away", style: { width: away } })
|
|
1785
2187
|
] })
|
|
1786
2188
|
] }, `${r.label}-${i}`);
|
|
1787
2189
|
}) }),
|
|
1788
|
-
data.rows.length > 0 ? /* @__PURE__ */
|
|
1789
|
-
/* @__PURE__ */
|
|
1790
|
-
/* @__PURE__ */
|
|
2190
|
+
data.rows.length > 0 ? /* @__PURE__ */ jsxs24("div", { className: "ss-w-fandash-postmatch-legend", children: [
|
|
2191
|
+
/* @__PURE__ */ jsxs24("span", { className: "ss-w-fandash-postmatch-legend-item", children: [
|
|
2192
|
+
/* @__PURE__ */ jsx28("i", { className: "ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--home" }),
|
|
1791
2193
|
data.homeName
|
|
1792
2194
|
] }),
|
|
1793
|
-
/* @__PURE__ */
|
|
1794
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ jsxs24("span", { className: "ss-w-fandash-postmatch-legend-item", children: [
|
|
2196
|
+
/* @__PURE__ */ jsx28("i", { className: "ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--away" }),
|
|
1795
2197
|
data.awayName
|
|
1796
2198
|
] })
|
|
1797
2199
|
] }) : null,
|
|
1798
|
-
/* @__PURE__ */
|
|
2200
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1799
2201
|
] });
|
|
1800
2202
|
}
|
|
1801
2203
|
|
|
1802
2204
|
// src/components/dashboard/PostMatchTopPerformerCard.tsx
|
|
1803
|
-
import { jsx as
|
|
2205
|
+
import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1804
2206
|
function initials4(playerName) {
|
|
1805
2207
|
const words = playerName.trim().split(/\s+/).filter(Boolean);
|
|
1806
2208
|
if (words.length === 0) return "?";
|
|
@@ -1810,72 +2212,72 @@ function initials4(playerName) {
|
|
|
1810
2212
|
}
|
|
1811
2213
|
function PostMatchTopPerformerCard({ card, onTap }) {
|
|
1812
2214
|
const { data } = card;
|
|
1813
|
-
return /* @__PURE__ */
|
|
1814
|
-
card.title ? /* @__PURE__ */
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
/* @__PURE__ */
|
|
1818
|
-
/* @__PURE__ */
|
|
2215
|
+
return /* @__PURE__ */ jsxs25("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-performer", onClick: () => onTap(card), children: [
|
|
2216
|
+
card.title ? /* @__PURE__ */ jsx29("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2217
|
+
/* @__PURE__ */ jsxs25("div", { className: "ss-w-fandash-postmatch-perf-row", children: [
|
|
2218
|
+
/* @__PURE__ */ jsx29("span", { className: "ss-w-fandash-postmatch-perf-avatar", "aria-hidden": "true", children: initials4(data.playerName) }),
|
|
2219
|
+
/* @__PURE__ */ jsx29("span", { className: "ss-w-fandash-postmatch-perf-name", children: data.playerName }),
|
|
2220
|
+
/* @__PURE__ */ jsx29("span", { className: "ss-w-fandash-postmatch-perf-rating", children: data.ratingLabel })
|
|
1819
2221
|
] }),
|
|
1820
|
-
/* @__PURE__ */
|
|
2222
|
+
/* @__PURE__ */ jsx29("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1821
2223
|
] });
|
|
1822
2224
|
}
|
|
1823
2225
|
|
|
1824
2226
|
// src/components/dashboard/PostMatchNextCard.tsx
|
|
1825
|
-
import { jsx as
|
|
2227
|
+
import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1826
2228
|
function PostMatchNextCard({ card }) {
|
|
1827
2229
|
const { data } = card;
|
|
1828
|
-
return /* @__PURE__ */
|
|
1829
|
-
card.title ? /* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
2230
|
+
return /* @__PURE__ */ jsxs26("div", { className: "ss-w-fandash-card ss-w-fandash-postmatch-next", children: [
|
|
2231
|
+
card.title ? /* @__PURE__ */ jsx30("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2232
|
+
/* @__PURE__ */ jsx30("div", { className: "ss-w-fandash-postmatch-next-row", children: /* @__PURE__ */ jsx30("span", { className: "ss-w-fandash-postmatch-next-when", children: data.whenLabel }) })
|
|
1831
2233
|
] });
|
|
1832
2234
|
}
|
|
1833
2235
|
|
|
1834
2236
|
// src/components/dashboard/RestingNextCard.tsx
|
|
1835
|
-
import { jsx as
|
|
2237
|
+
import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1836
2238
|
function RestingNextCard({ card, onTap }) {
|
|
1837
2239
|
const { data } = card;
|
|
1838
|
-
return /* @__PURE__ */
|
|
1839
|
-
card.title ? /* @__PURE__ */
|
|
1840
|
-
/* @__PURE__ */
|
|
1841
|
-
/* @__PURE__ */
|
|
1842
|
-
data.competition ? /* @__PURE__ */
|
|
2240
|
+
return /* @__PURE__ */ jsxs27("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-next", onClick: () => onTap(card), children: [
|
|
2241
|
+
card.title ? /* @__PURE__ */ jsx31("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2242
|
+
/* @__PURE__ */ jsxs27("div", { className: "ss-w-fandash-resting-next-row", children: [
|
|
2243
|
+
/* @__PURE__ */ jsx31("span", { className: "ss-w-fandash-resting-next-when", children: data.whenLabel }),
|
|
2244
|
+
data.competition ? /* @__PURE__ */ jsx31("span", { className: "ss-w-fandash-resting-next-competition", children: data.competition }) : null
|
|
1843
2245
|
] }),
|
|
1844
|
-
/* @__PURE__ */
|
|
2246
|
+
/* @__PURE__ */ jsx31("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1845
2247
|
] });
|
|
1846
2248
|
}
|
|
1847
2249
|
|
|
1848
2250
|
// src/components/dashboard/RestingStandingsCard.tsx
|
|
1849
|
-
import { jsx as
|
|
2251
|
+
import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1850
2252
|
function RestingStandingsCard({ card, onTap }) {
|
|
1851
2253
|
const { data } = card;
|
|
1852
|
-
return /* @__PURE__ */
|
|
1853
|
-
card.title ? /* @__PURE__ */
|
|
1854
|
-
/* @__PURE__ */
|
|
1855
|
-
/* @__PURE__ */
|
|
1856
|
-
/* @__PURE__ */
|
|
2254
|
+
return /* @__PURE__ */ jsxs28("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-standings", onClick: () => onTap(card), children: [
|
|
2255
|
+
card.title ? /* @__PURE__ */ jsx32("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2256
|
+
/* @__PURE__ */ jsxs28("div", { className: "ss-w-fandash-resting-standings-row", children: [
|
|
2257
|
+
/* @__PURE__ */ jsx32("span", { className: "ss-w-fandash-resting-standings-position", children: data.positionLabel }),
|
|
2258
|
+
/* @__PURE__ */ jsx32("span", { className: "ss-w-fandash-resting-standings-record", children: data.recordLabel })
|
|
1857
2259
|
] }),
|
|
1858
|
-
/* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ jsx32("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1859
2261
|
] });
|
|
1860
2262
|
}
|
|
1861
2263
|
|
|
1862
2264
|
// src/components/dashboard/RestingSeasonCard.tsx
|
|
1863
|
-
import { jsx as
|
|
2265
|
+
import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1864
2266
|
function RestingSeasonCard({ card, onTap }) {
|
|
1865
2267
|
const { data } = card;
|
|
1866
|
-
return /* @__PURE__ */
|
|
1867
|
-
card.title ? /* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
data.scorerLabel ? /* @__PURE__ */
|
|
1870
|
-
data.playerLabel ? /* @__PURE__ */
|
|
1871
|
-
/* @__PURE__ */
|
|
2268
|
+
return /* @__PURE__ */ jsxs29("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-season", onClick: () => onTap(card), children: [
|
|
2269
|
+
card.title ? /* @__PURE__ */ jsx33("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2270
|
+
/* @__PURE__ */ jsxs29("div", { className: "ss-w-fandash-resting-season-rows", children: [
|
|
2271
|
+
data.scorerLabel ? /* @__PURE__ */ jsx33("span", { className: "ss-w-fandash-resting-season-row", children: data.scorerLabel }) : null,
|
|
2272
|
+
data.playerLabel ? /* @__PURE__ */ jsx33("span", { className: "ss-w-fandash-resting-season-row", children: data.playerLabel }) : null,
|
|
2273
|
+
/* @__PURE__ */ jsx33("span", { className: "ss-w-fandash-resting-season-row", children: data.tallyLabel })
|
|
1872
2274
|
] }),
|
|
1873
|
-
/* @__PURE__ */
|
|
2275
|
+
/* @__PURE__ */ jsx33("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1874
2276
|
] });
|
|
1875
2277
|
}
|
|
1876
2278
|
|
|
1877
2279
|
// src/components/dashboard/RestingFormCard.tsx
|
|
1878
|
-
import { jsx as
|
|
2280
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
1879
2281
|
function resultClass(result) {
|
|
1880
2282
|
const upper = result.toUpperCase();
|
|
1881
2283
|
if (upper === "W") return "ss-w-fandash-form-pill--win";
|
|
@@ -1884,17 +2286,17 @@ function resultClass(result) {
|
|
|
1884
2286
|
}
|
|
1885
2287
|
function RestingFormCard({ card }) {
|
|
1886
2288
|
const { data } = card;
|
|
1887
|
-
return /* @__PURE__ */
|
|
1888
|
-
card.title ? /* @__PURE__ */
|
|
1889
|
-
/* @__PURE__ */
|
|
2289
|
+
return /* @__PURE__ */ jsxs30("div", { className: "ss-w-fandash-card ss-w-fandash-resting-form", children: [
|
|
2290
|
+
card.title ? /* @__PURE__ */ jsx34("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2291
|
+
/* @__PURE__ */ jsx34("span", { className: "ss-w-fandash-form", children: data.letters.map((r, i) => /* @__PURE__ */ jsx34("span", { className: `ss-w-fandash-form-pill ${resultClass(r)}`, children: r }, `${r}-${i}`)) })
|
|
1890
2292
|
] });
|
|
1891
2293
|
}
|
|
1892
2294
|
|
|
1893
2295
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
1894
|
-
import { useRef as
|
|
2296
|
+
import { useRef as useRef4, useState as useState12 } from "react";
|
|
1895
2297
|
|
|
1896
2298
|
// src/useLiveClock.ts
|
|
1897
|
-
import { useEffect as
|
|
2299
|
+
import { useEffect as useEffect6, useState as useState11 } from "react";
|
|
1898
2300
|
var TICK_MS = 6e4;
|
|
1899
2301
|
var MAX_LIVE_TICK_MINUTES = 15;
|
|
1900
2302
|
function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
@@ -1903,10 +2305,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
|
1903
2305
|
return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
|
|
1904
2306
|
}
|
|
1905
2307
|
function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
1906
|
-
const [displayMinute, setDisplayMinute] =
|
|
2308
|
+
const [displayMinute, setDisplayMinute] = useState11(
|
|
1907
2309
|
() => computeDisplayMinute(minute, clockRunning, receivedAtMs)
|
|
1908
2310
|
);
|
|
1909
|
-
|
|
2311
|
+
useEffect6(() => {
|
|
1910
2312
|
setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
|
|
1911
2313
|
if (!clockRunning) return;
|
|
1912
2314
|
const id = window.setInterval(() => {
|
|
@@ -1918,17 +2320,17 @@ function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
|
1918
2320
|
}
|
|
1919
2321
|
|
|
1920
2322
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
1921
|
-
import { jsx as
|
|
2323
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1922
2324
|
function initials5(name) {
|
|
1923
2325
|
return name.trim().slice(0, 3).toUpperCase();
|
|
1924
2326
|
}
|
|
1925
2327
|
function LiveCrest({ url, name, side }) {
|
|
1926
|
-
const [failed, setFailed] =
|
|
2328
|
+
const [failed, setFailed] = useState12(false);
|
|
1927
2329
|
const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
|
|
1928
2330
|
if (url && !failed) {
|
|
1929
|
-
return /* @__PURE__ */
|
|
2331
|
+
return /* @__PURE__ */ jsx35("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1930
2332
|
}
|
|
1931
|
-
return /* @__PURE__ */
|
|
2333
|
+
return /* @__PURE__ */ jsx35("span", { className: `${cls} ss-w-fandash-live-crest--fallback`, "aria-hidden": "true", children: initials5(name) });
|
|
1932
2334
|
}
|
|
1933
2335
|
function scorersLine(goalEvents) {
|
|
1934
2336
|
if (!goalEvents || goalEvents.length === 0) return null;
|
|
@@ -1942,72 +2344,72 @@ function LiveScoreCard({
|
|
|
1942
2344
|
}) {
|
|
1943
2345
|
const { data } = card;
|
|
1944
2346
|
const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
|
|
1945
|
-
const seedRef =
|
|
2347
|
+
const seedRef = useRef4(null);
|
|
1946
2348
|
if (!seedRef.current || seedRef.current.key !== seedKey) {
|
|
1947
2349
|
seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
|
|
1948
2350
|
}
|
|
1949
2351
|
const displayMinute = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs);
|
|
1950
2352
|
const minuteSuffix = data.minuteLabel.replace(/^\d+/, "");
|
|
1951
2353
|
const scorers = scorersLine(goalEvents);
|
|
1952
|
-
return /* @__PURE__ */
|
|
1953
|
-
card.title ? /* @__PURE__ */
|
|
1954
|
-
/* @__PURE__ */
|
|
1955
|
-
/* @__PURE__ */
|
|
1956
|
-
/* @__PURE__ */
|
|
2354
|
+
return /* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-card ss-w-fandash-live-score", children: [
|
|
2355
|
+
card.title ? /* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2356
|
+
/* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-live-top", children: [
|
|
2357
|
+
/* @__PURE__ */ jsxs31("span", { className: "ss-w-fandash-live-pill", children: [
|
|
2358
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
|
|
1957
2359
|
data.statusLabel
|
|
1958
2360
|
] }),
|
|
1959
|
-
/* @__PURE__ */
|
|
1960
|
-
data.competition ? /* @__PURE__ */
|
|
2361
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-minute", children: `${displayMinute}${minuteSuffix}` }),
|
|
2362
|
+
data.competition ? /* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-competition", children: data.competition }) : null
|
|
1961
2363
|
] }),
|
|
1962
|
-
/* @__PURE__ */
|
|
1963
|
-
/* @__PURE__ */
|
|
1964
|
-
/* @__PURE__ */
|
|
1965
|
-
/* @__PURE__ */
|
|
2364
|
+
/* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-live-main", children: [
|
|
2365
|
+
/* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-live-side ss-w-fandash-live-side--home", children: [
|
|
2366
|
+
/* @__PURE__ */ jsx35(LiveCrest, { url: data.homeCrestUrl, name: data.homeName, side: "home" }),
|
|
2367
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-team-name", children: data.homeName })
|
|
1966
2368
|
] }),
|
|
1967
|
-
/* @__PURE__ */
|
|
1968
|
-
/* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
1970
|
-
/* @__PURE__ */
|
|
2369
|
+
/* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-live-score-main", children: [
|
|
2370
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-score-value", children: data.homeScore }),
|
|
2371
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-score-sep", children: "\u2013" }),
|
|
2372
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-score-value", children: data.awayScore })
|
|
1971
2373
|
] }),
|
|
1972
|
-
/* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
2374
|
+
/* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-live-side ss-w-fandash-live-side--away", children: [
|
|
2375
|
+
/* @__PURE__ */ jsx35(LiveCrest, { url: data.awayCrestUrl, name: data.awayName, side: "away" }),
|
|
2376
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-team-name", children: data.awayName })
|
|
1975
2377
|
] })
|
|
1976
2378
|
] }),
|
|
1977
|
-
scorers ? /* @__PURE__ */
|
|
1978
|
-
/* @__PURE__ */
|
|
2379
|
+
scorers ? /* @__PURE__ */ jsxs31("div", { className: "ss-w-fandash-live-scorers", children: [
|
|
2380
|
+
/* @__PURE__ */ jsx35("span", { className: "ss-w-fandash-live-scorers-icon", "aria-hidden": "true", children: "\u26BD" }),
|
|
1979
2381
|
scorers
|
|
1980
2382
|
] }) : null
|
|
1981
2383
|
] });
|
|
1982
2384
|
}
|
|
1983
2385
|
|
|
1984
2386
|
// src/components/dashboard/LiveTimelineCard.tsx
|
|
1985
|
-
import { useState as
|
|
1986
|
-
import { jsx as
|
|
2387
|
+
import { useState as useState13 } from "react";
|
|
2388
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
1987
2389
|
var SHOWN2 = 3;
|
|
1988
2390
|
function EventIcon({ type }) {
|
|
1989
2391
|
if (type === "goal") {
|
|
1990
|
-
return /* @__PURE__ */
|
|
2392
|
+
return /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-ico ss-w-fandash-live-tl-ico--goal", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-ball" }) });
|
|
1991
2393
|
}
|
|
1992
2394
|
if (type === "yellow" || type === "red") {
|
|
1993
|
-
return /* @__PURE__ */
|
|
2395
|
+
return /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-ico", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("span", { className: `ss-w-fandash-live-tl-card ss-w-fandash-live-tl-card--${type}` }) });
|
|
1994
2396
|
}
|
|
1995
2397
|
if (type === "sub") {
|
|
1996
|
-
return /* @__PURE__ */
|
|
2398
|
+
return /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-ico", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-subarrows", children: "\u21C5" }) });
|
|
1997
2399
|
}
|
|
1998
|
-
return /* @__PURE__ */
|
|
2400
|
+
return /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-ico", "aria-hidden": "true", children: /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-dot" }) });
|
|
1999
2401
|
}
|
|
2000
2402
|
function EventLabel({ e }) {
|
|
2001
2403
|
if (e.type === "sub") {
|
|
2002
|
-
return /* @__PURE__ */
|
|
2404
|
+
return /* @__PURE__ */ jsxs32("span", { className: "ss-w-fandash-live-tl-who", children: [
|
|
2003
2405
|
e.player ?? e.text,
|
|
2004
|
-
e.playerOff ? /* @__PURE__ */
|
|
2406
|
+
e.playerOff ? /* @__PURE__ */ jsxs32("span", { className: "ss-w-fandash-live-tl-off", children: [
|
|
2005
2407
|
" for ",
|
|
2006
2408
|
e.playerOff
|
|
2007
2409
|
] }) : null
|
|
2008
2410
|
] });
|
|
2009
2411
|
}
|
|
2010
|
-
return /* @__PURE__ */
|
|
2412
|
+
return /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-who", children: e.player ?? e.text });
|
|
2011
2413
|
}
|
|
2012
2414
|
function EventRow({ e }) {
|
|
2013
2415
|
const cls = [
|
|
@@ -2015,16 +2417,16 @@ function EventRow({ e }) {
|
|
|
2015
2417
|
e.side === "home" ? "ss-w-fandash-live-tl-ev--home" : "ss-w-fandash-live-tl-ev--away",
|
|
2016
2418
|
e.type === "goal" ? "ss-w-fandash-live-tl-ev--goal" : ""
|
|
2017
2419
|
].filter(Boolean).join(" ");
|
|
2018
|
-
return /* @__PURE__ */
|
|
2019
|
-
/* @__PURE__ */
|
|
2020
|
-
/* @__PURE__ */
|
|
2021
|
-
/* @__PURE__ */
|
|
2420
|
+
return /* @__PURE__ */ jsxs32("div", { className: cls, children: [
|
|
2421
|
+
/* @__PURE__ */ jsxs32("span", { className: "ss-w-fandash-live-tl-txt", children: [
|
|
2422
|
+
/* @__PURE__ */ jsx36(EventLabel, { e }),
|
|
2423
|
+
/* @__PURE__ */ jsx36(EventIcon, { type: e.type })
|
|
2022
2424
|
] }),
|
|
2023
|
-
/* @__PURE__ */
|
|
2425
|
+
/* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-badge", children: e.minuteLabel })
|
|
2024
2426
|
] });
|
|
2025
2427
|
}
|
|
2026
2428
|
function LiveTimelineCard({ card, ui }) {
|
|
2027
|
-
const [expanded, setExpanded] =
|
|
2429
|
+
const [expanded, setExpanded] = useState13(false);
|
|
2028
2430
|
const events = card.data.events;
|
|
2029
2431
|
if (!events || events.length === 0) return null;
|
|
2030
2432
|
const sorted = [...events].sort((a, b) => b.minute - a.minute);
|
|
@@ -2032,10 +2434,10 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
2032
2434
|
const shown = expanded ? sorted : sorted.slice(0, SHOWN2);
|
|
2033
2435
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
2034
2436
|
const showLess = ui?.showLess ?? "Show less";
|
|
2035
|
-
return /* @__PURE__ */
|
|
2036
|
-
card.title ? /* @__PURE__ */
|
|
2037
|
-
/* @__PURE__ */
|
|
2038
|
-
rest > 0 ? /* @__PURE__ */
|
|
2437
|
+
return /* @__PURE__ */ jsxs32("div", { className: "ss-w-fandash-card ss-w-fandash-live-timeline", children: [
|
|
2438
|
+
card.title ? /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2439
|
+
/* @__PURE__ */ jsx36("div", { className: "ss-w-fandash-live-tl", children: shown.map((e, i) => /* @__PURE__ */ jsx36(EventRow, { e }, `${e.minute}-${e.side}-${e.type}-${i}`)) }),
|
|
2440
|
+
rest > 0 ? /* @__PURE__ */ jsx36(
|
|
2039
2441
|
"button",
|
|
2040
2442
|
{
|
|
2041
2443
|
type: "button",
|
|
@@ -2050,7 +2452,7 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
2050
2452
|
|
|
2051
2453
|
// src/components/dashboard/MomentumWave.tsx
|
|
2052
2454
|
import { useId } from "react";
|
|
2053
|
-
import { jsx as
|
|
2455
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2054
2456
|
var WIDTH = 270;
|
|
2055
2457
|
var HEIGHT = 56;
|
|
2056
2458
|
var BASELINE = HEIGHT / 2;
|
|
@@ -2077,9 +2479,9 @@ function MomentumWave({
|
|
|
2077
2479
|
const bottomClipId = `${clipId}-bottom`;
|
|
2078
2480
|
const topClass = clubIsHome ? "ss-w-fandash-live-mom-home" : "ss-w-fandash-live-mom-away";
|
|
2079
2481
|
const bottomClass = clubIsHome ? "ss-w-fandash-live-mom-away" : "ss-w-fandash-live-mom-home";
|
|
2080
|
-
return /* @__PURE__ */
|
|
2081
|
-
caption ? /* @__PURE__ */
|
|
2082
|
-
/* @__PURE__ */
|
|
2482
|
+
return /* @__PURE__ */ jsxs33("div", { className: "ss-w-fandash-live-mom", children: [
|
|
2483
|
+
caption ? /* @__PURE__ */ jsx37("span", { className: "ss-w-fandash-live-mom-caption", children: caption }) : null,
|
|
2484
|
+
/* @__PURE__ */ jsxs33(
|
|
2083
2485
|
"svg",
|
|
2084
2486
|
{
|
|
2085
2487
|
className: "ss-w-fandash-live-mom-svg",
|
|
@@ -2088,15 +2490,15 @@ function MomentumWave({
|
|
|
2088
2490
|
role: "img",
|
|
2089
2491
|
"aria-label": caption ?? "Momentum",
|
|
2090
2492
|
children: [
|
|
2091
|
-
/* @__PURE__ */
|
|
2092
|
-
/* @__PURE__ */
|
|
2093
|
-
/* @__PURE__ */
|
|
2493
|
+
/* @__PURE__ */ jsxs33("defs", { children: [
|
|
2494
|
+
/* @__PURE__ */ jsx37("clipPath", { id: topClipId, children: /* @__PURE__ */ jsx37("rect", { x: 0, y: 0, width: WIDTH, height: BASELINE }) }),
|
|
2495
|
+
/* @__PURE__ */ jsx37("clipPath", { id: bottomClipId, children: /* @__PURE__ */ jsx37("rect", { x: 0, y: BASELINE, width: WIDTH, height: HEIGHT - BASELINE }) })
|
|
2094
2496
|
] }),
|
|
2095
|
-
/* @__PURE__ */
|
|
2096
|
-
/* @__PURE__ */
|
|
2097
|
-
/* @__PURE__ */
|
|
2098
|
-
/* @__PURE__ */
|
|
2099
|
-
/* @__PURE__ */
|
|
2497
|
+
/* @__PURE__ */ jsx37("path", { d: area, className: topClass, clipPath: `url(#${topClipId})` }),
|
|
2498
|
+
/* @__PURE__ */ jsx37("path", { d: area, className: bottomClass, clipPath: `url(#${bottomClipId})` }),
|
|
2499
|
+
/* @__PURE__ */ jsx37("line", { x1: 0, y1: BASELINE, x2: WIDTH, y2: BASELINE, className: "ss-w-fandash-live-mom-base" }),
|
|
2500
|
+
/* @__PURE__ */ jsx37("path", { d: line, className: "ss-w-fandash-live-mom-line", vectorEffect: "non-scaling-stroke" }),
|
|
2501
|
+
/* @__PURE__ */ jsx37("circle", { cx: lastX, cy: lastY, r: 3.2, className: "ss-w-fandash-live-mom-now", vectorEffect: "non-scaling-stroke" })
|
|
2100
2502
|
]
|
|
2101
2503
|
}
|
|
2102
2504
|
)
|
|
@@ -2104,7 +2506,7 @@ function MomentumWave({
|
|
|
2104
2506
|
}
|
|
2105
2507
|
|
|
2106
2508
|
// src/components/dashboard/LiveStatsCard.tsx
|
|
2107
|
-
import { jsx as
|
|
2509
|
+
import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2108
2510
|
function splitWidths2(homeNum, awayNum) {
|
|
2109
2511
|
const total = homeNum + awayNum;
|
|
2110
2512
|
if (total <= 0) return { home: "50%", away: "50%" };
|
|
@@ -2113,34 +2515,34 @@ function splitWidths2(homeNum, awayNum) {
|
|
|
2113
2515
|
}
|
|
2114
2516
|
function LiveStatsCard({ card }) {
|
|
2115
2517
|
const { data } = card;
|
|
2116
|
-
return /* @__PURE__ */
|
|
2117
|
-
card.title ? /* @__PURE__ */
|
|
2118
|
-
/* @__PURE__ */
|
|
2518
|
+
return /* @__PURE__ */ jsxs34("div", { className: "ss-w-fandash-card ss-w-fandash-live-stats", children: [
|
|
2519
|
+
card.title ? /* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
2520
|
+
/* @__PURE__ */ jsx38("div", { className: "ss-w-fandash-live-stat-rows", children: data.rows.map((r, i) => {
|
|
2119
2521
|
const homeValue = data.clubIsHome ? r.clubValue : r.oppValue;
|
|
2120
2522
|
const awayValue = data.clubIsHome ? r.oppValue : r.clubValue;
|
|
2121
2523
|
const homeNum = data.clubIsHome ? r.clubNum : r.oppNum;
|
|
2122
2524
|
const awayNum = data.clubIsHome ? r.oppNum : r.clubNum;
|
|
2123
2525
|
const { home, away } = splitWidths2(homeNum, awayNum);
|
|
2124
|
-
return /* @__PURE__ */
|
|
2125
|
-
/* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
2127
|
-
/* @__PURE__ */
|
|
2128
|
-
/* @__PURE__ */
|
|
2526
|
+
return /* @__PURE__ */ jsxs34("div", { className: "ss-w-fandash-live-stat", children: [
|
|
2527
|
+
/* @__PURE__ */ jsxs34("div", { className: "ss-w-fandash-live-stat-row", children: [
|
|
2528
|
+
/* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--home", children: homeValue }),
|
|
2529
|
+
/* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-live-stat-label", children: r.label }),
|
|
2530
|
+
/* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--away", children: awayValue })
|
|
2129
2531
|
] }),
|
|
2130
|
-
/* @__PURE__ */
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2532
|
+
/* @__PURE__ */ jsxs34("div", { className: "ss-w-fandash-live-bar", children: [
|
|
2533
|
+
/* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-live-bar-home", style: { width: home } }),
|
|
2534
|
+
/* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-live-bar-away", style: { width: away } })
|
|
2133
2535
|
] })
|
|
2134
2536
|
] }, `${r.label}-${i}`);
|
|
2135
2537
|
}) }),
|
|
2136
|
-
data.momentum.length > 0 ? /* @__PURE__ */
|
|
2137
|
-
data.rows.length > 0 ? /* @__PURE__ */
|
|
2138
|
-
/* @__PURE__ */
|
|
2139
|
-
/* @__PURE__ */
|
|
2538
|
+
data.momentum.length > 0 ? /* @__PURE__ */ jsx38(MomentumWave, { points: data.momentum, caption: data.momentumLabel, clubIsHome: data.clubIsHome }) : data.momentumLabel ? /* @__PURE__ */ jsx38("span", { className: "ss-w-fandash-live-momentum", children: data.momentumLabel }) : null,
|
|
2539
|
+
data.rows.length > 0 ? /* @__PURE__ */ jsxs34("div", { className: "ss-w-fandash-live-legend", children: [
|
|
2540
|
+
/* @__PURE__ */ jsxs34("span", { className: "ss-w-fandash-live-legend-item", children: [
|
|
2541
|
+
/* @__PURE__ */ jsx38("i", { className: "ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--home" }),
|
|
2140
2542
|
data.homeName
|
|
2141
2543
|
] }),
|
|
2142
|
-
/* @__PURE__ */
|
|
2143
|
-
/* @__PURE__ */
|
|
2544
|
+
/* @__PURE__ */ jsxs34("span", { className: "ss-w-fandash-live-legend-item", children: [
|
|
2545
|
+
/* @__PURE__ */ jsx38("i", { className: "ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--away" }),
|
|
2144
2546
|
data.awayName
|
|
2145
2547
|
] })
|
|
2146
2548
|
] }) : null
|
|
@@ -2148,7 +2550,7 @@ function LiveStatsCard({ card }) {
|
|
|
2148
2550
|
}
|
|
2149
2551
|
|
|
2150
2552
|
// src/components/dashboard/ClubFanDashboard.tsx
|
|
2151
|
-
import { jsx as
|
|
2553
|
+
import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2152
2554
|
function ClubFanDashboard({ dashboard, onTap, ui }) {
|
|
2153
2555
|
const orderedCards = [
|
|
2154
2556
|
...dashboard.cards.filter((c) => c.cardType === "countdown"),
|
|
@@ -2158,84 +2560,84 @@ function ClubFanDashboard({ dashboard, onTap, ui }) {
|
|
|
2158
2560
|
(c) => c.cardType === "liveTimeline"
|
|
2159
2561
|
);
|
|
2160
2562
|
const goalEvents = timelineCard?.data.events.filter((e) => e.type === "goal");
|
|
2161
|
-
return /* @__PURE__ */
|
|
2162
|
-
dashboard.greeting ? /* @__PURE__ */
|
|
2163
|
-
/* @__PURE__ */
|
|
2563
|
+
return /* @__PURE__ */ jsxs35("div", { className: "ss-w-fandash", children: [
|
|
2564
|
+
dashboard.greeting ? /* @__PURE__ */ jsx39("span", { className: "ss-w-fandash-greeting", children: dashboard.greeting }) : null,
|
|
2565
|
+
/* @__PURE__ */ jsx39("div", { className: "ss-w-fandash-cards", children: orderedCards.map((card, i) => /* @__PURE__ */ jsx39(FanDashboardCard, { card, onTap, ui, goalEvents }, `${card.cardType}-${i}`)) })
|
|
2164
2566
|
] });
|
|
2165
2567
|
}
|
|
2166
2568
|
function FanDashboardCard({ card, onTap, ui, goalEvents }) {
|
|
2167
2569
|
switch (card.cardType) {
|
|
2168
2570
|
case "fixture":
|
|
2169
|
-
return /* @__PURE__ */
|
|
2571
|
+
return /* @__PURE__ */ jsx39(FixtureCard, { card });
|
|
2170
2572
|
case "countdown":
|
|
2171
|
-
return /* @__PURE__ */
|
|
2573
|
+
return /* @__PURE__ */ jsx39(CountdownCard, { card });
|
|
2172
2574
|
case "injuries":
|
|
2173
|
-
return /* @__PURE__ */
|
|
2575
|
+
return /* @__PURE__ */ jsx39(InjuriesCard, { card, ui });
|
|
2174
2576
|
case "reasonToBet":
|
|
2175
|
-
return /* @__PURE__ */
|
|
2577
|
+
return /* @__PURE__ */ jsx39(ReasonToBetCard, { card });
|
|
2176
2578
|
case "whereToWatch":
|
|
2177
|
-
return /* @__PURE__ */
|
|
2579
|
+
return /* @__PURE__ */ jsx39(WhereToWatchCard, { card });
|
|
2178
2580
|
case "congestedWeek":
|
|
2179
|
-
return /* @__PURE__ */
|
|
2581
|
+
return /* @__PURE__ */ jsx39(CongestedWeekCard, { card, onTap });
|
|
2180
2582
|
case "transfers":
|
|
2181
|
-
return /* @__PURE__ */
|
|
2583
|
+
return /* @__PURE__ */ jsx39(TransfersCard, { card });
|
|
2182
2584
|
case "links":
|
|
2183
|
-
return /* @__PURE__ */
|
|
2585
|
+
return /* @__PURE__ */ jsx39(LinksCard, { card });
|
|
2184
2586
|
case "postMatchResult":
|
|
2185
|
-
return /* @__PURE__ */
|
|
2587
|
+
return /* @__PURE__ */ jsx39(PostMatchResultCard, { card });
|
|
2186
2588
|
case "postMatchGoals":
|
|
2187
|
-
return /* @__PURE__ */
|
|
2589
|
+
return /* @__PURE__ */ jsx39(PostMatchGoalsCard, { card, onTap });
|
|
2188
2590
|
case "postMatchStats":
|
|
2189
|
-
return /* @__PURE__ */
|
|
2591
|
+
return /* @__PURE__ */ jsx39(PostMatchStatsCard, { card, onTap });
|
|
2190
2592
|
case "postMatchTopPerformer":
|
|
2191
|
-
return /* @__PURE__ */
|
|
2593
|
+
return /* @__PURE__ */ jsx39(PostMatchTopPerformerCard, { card, onTap });
|
|
2192
2594
|
case "postMatchNext":
|
|
2193
|
-
return /* @__PURE__ */
|
|
2595
|
+
return /* @__PURE__ */ jsx39(PostMatchNextCard, { card });
|
|
2194
2596
|
case "restingNext":
|
|
2195
|
-
return /* @__PURE__ */
|
|
2597
|
+
return /* @__PURE__ */ jsx39(RestingNextCard, { card, onTap });
|
|
2196
2598
|
case "restingStandings":
|
|
2197
|
-
return /* @__PURE__ */
|
|
2599
|
+
return /* @__PURE__ */ jsx39(RestingStandingsCard, { card, onTap });
|
|
2198
2600
|
case "restingSeason":
|
|
2199
|
-
return /* @__PURE__ */
|
|
2601
|
+
return /* @__PURE__ */ jsx39(RestingSeasonCard, { card, onTap });
|
|
2200
2602
|
case "restingForm":
|
|
2201
|
-
return /* @__PURE__ */
|
|
2603
|
+
return /* @__PURE__ */ jsx39(RestingFormCard, { card });
|
|
2202
2604
|
case "liveScore":
|
|
2203
|
-
return /* @__PURE__ */
|
|
2605
|
+
return /* @__PURE__ */ jsx39(LiveScoreCard, { card, goalEvents });
|
|
2204
2606
|
case "liveTimeline":
|
|
2205
|
-
return /* @__PURE__ */
|
|
2607
|
+
return /* @__PURE__ */ jsx39(LiveTimelineCard, { card, ui });
|
|
2206
2608
|
case "liveStats":
|
|
2207
|
-
return /* @__PURE__ */
|
|
2609
|
+
return /* @__PURE__ */ jsx39(LiveStatsCard, { card });
|
|
2208
2610
|
default:
|
|
2209
2611
|
return null;
|
|
2210
2612
|
}
|
|
2211
2613
|
}
|
|
2212
2614
|
|
|
2213
2615
|
// src/components/ChatMessage.tsx
|
|
2214
|
-
import { jsx as
|
|
2215
|
-
function ChatMessage({ message, disabled, onAct, onTap, ui, slip }) {
|
|
2616
|
+
import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2617
|
+
function ChatMessage({ message, disabled, onAct, onTap, ui, slip, monitor }) {
|
|
2216
2618
|
if (message.role === "user") {
|
|
2217
|
-
return /* @__PURE__ */
|
|
2619
|
+
return /* @__PURE__ */ jsx40("div", { className: "ss-w-msg ss-w-user", "data-msg-id": message.id, children: /* @__PURE__ */ jsx40("div", { className: "ss-w-bubble", children: message.text }) });
|
|
2218
2620
|
}
|
|
2219
2621
|
const onFanDashboardTap = (card) => {
|
|
2220
2622
|
onAct({ message: card.actionLabel, actionRef: card.actionRef, label: card.actionLabel || card.title || "" });
|
|
2221
2623
|
};
|
|
2222
|
-
return /* @__PURE__ */
|
|
2223
|
-
message.text && !message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */
|
|
2224
|
-
message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */
|
|
2225
|
-
message.clubFanDashboard ? /* @__PURE__ */
|
|
2226
|
-
/* @__PURE__ */
|
|
2227
|
-
/* @__PURE__ */
|
|
2228
|
-
/* @__PURE__ */
|
|
2229
|
-
/* @__PURE__ */
|
|
2230
|
-
/* @__PURE__ */
|
|
2624
|
+
return /* @__PURE__ */ jsxs36("div", { className: "ss-w-msg ss-w-bot", "data-msg-id": message.id, children: [
|
|
2625
|
+
message.text && !message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */ jsx40(Markdown, { text: message.text }) : null,
|
|
2626
|
+
message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */ jsx40(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
|
|
2627
|
+
message.clubFanDashboard ? /* @__PURE__ */ jsx40(ClubFanDashboard, { dashboard: message.clubFanDashboard, onTap: onFanDashboardTap, ui }) : null,
|
|
2628
|
+
/* @__PURE__ */ jsx40(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
2629
|
+
/* @__PURE__ */ jsx40(BettingInsightList, { insights: message.insights, ui, slip, monitor }),
|
|
2630
|
+
/* @__PURE__ */ jsx40(MarketOddsCardList, { cards: message.marketOdds, ui, slip, monitor }),
|
|
2631
|
+
/* @__PURE__ */ jsx40(OddsMovementCardList, { cards: message.oddsMovement, ui, monitor }),
|
|
2632
|
+
/* @__PURE__ */ jsx40(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
2231
2633
|
] });
|
|
2232
2634
|
}
|
|
2233
2635
|
|
|
2234
2636
|
// src/components/IntentChips.tsx
|
|
2235
|
-
import { jsx as
|
|
2637
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2236
2638
|
function IntentChips({ chips, onPick }) {
|
|
2237
2639
|
if (chips.length === 0) return null;
|
|
2238
|
-
return /* @__PURE__ */
|
|
2640
|
+
return /* @__PURE__ */ jsx41("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx41("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
2239
2641
|
}
|
|
2240
2642
|
|
|
2241
2643
|
// src/scroll.ts
|
|
@@ -2245,20 +2647,20 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
2245
2647
|
}
|
|
2246
2648
|
|
|
2247
2649
|
// src/components/MessageList.tsx
|
|
2248
|
-
import { jsx as
|
|
2650
|
+
import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2249
2651
|
function turnAnchor(messages) {
|
|
2250
2652
|
const last = messages[messages.length - 1];
|
|
2251
2653
|
if (!last || last.role !== "assistant") return null;
|
|
2252
2654
|
const prev = messages[messages.length - 2];
|
|
2253
2655
|
return { turnId: last.id, anchorId: prev && prev.role === "user" ? prev.id : last.id };
|
|
2254
2656
|
}
|
|
2255
|
-
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
2657
|
+
function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
2256
2658
|
const { state, send } = controller;
|
|
2257
|
-
const listRef =
|
|
2258
|
-
const endRef =
|
|
2259
|
-
const pinnedRef =
|
|
2260
|
-
const anchoredTurnRef =
|
|
2261
|
-
|
|
2659
|
+
const listRef = useRef5(null);
|
|
2660
|
+
const endRef = useRef5(null);
|
|
2661
|
+
const pinnedRef = useRef5(true);
|
|
2662
|
+
const anchoredTurnRef = useRef5(null);
|
|
2663
|
+
useEffect7(() => {
|
|
2262
2664
|
const anchor = turnAnchor(state.messages);
|
|
2263
2665
|
const list = listRef.current;
|
|
2264
2666
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
@@ -2273,7 +2675,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2273
2675
|
}, [state.messages, state.status, state.isStreaming]);
|
|
2274
2676
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
2275
2677
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && (m.greetingDashboard || m.clubFanDashboard));
|
|
2276
|
-
return /* @__PURE__ */
|
|
2678
|
+
return /* @__PURE__ */ jsxs37(
|
|
2277
2679
|
"div",
|
|
2278
2680
|
{
|
|
2279
2681
|
className: "ss-w-list",
|
|
@@ -2283,7 +2685,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2283
2685
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
2284
2686
|
},
|
|
2285
2687
|
children: [
|
|
2286
|
-
state.messages.map((m) => /* @__PURE__ */
|
|
2688
|
+
state.messages.map((m) => /* @__PURE__ */ jsx42(
|
|
2287
2689
|
ChatMessage,
|
|
2288
2690
|
{
|
|
2289
2691
|
message: m,
|
|
@@ -2294,29 +2696,30 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2294
2696
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
2295
2697
|
},
|
|
2296
2698
|
ui,
|
|
2297
|
-
slip
|
|
2699
|
+
slip,
|
|
2700
|
+
monitor
|
|
2298
2701
|
},
|
|
2299
2702
|
m.id
|
|
2300
2703
|
)),
|
|
2301
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */
|
|
2704
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx42(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
2302
2705
|
} }) : null,
|
|
2303
|
-
state.status ? /* @__PURE__ */
|
|
2304
|
-
state.error ? /* @__PURE__ */
|
|
2305
|
-
/* @__PURE__ */
|
|
2306
|
-
/* @__PURE__ */
|
|
2706
|
+
state.status ? /* @__PURE__ */ jsx42("div", { className: "ss-w-status", children: state.status }) : null,
|
|
2707
|
+
state.error ? /* @__PURE__ */ jsxs37("div", { className: "ss-w-error", role: "alert", children: [
|
|
2708
|
+
/* @__PURE__ */ jsx42("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
2709
|
+
/* @__PURE__ */ jsx42("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
2307
2710
|
] }) : null,
|
|
2308
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */
|
|
2309
|
-
/* @__PURE__ */
|
|
2711
|
+
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ jsx42(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
2712
|
+
/* @__PURE__ */ jsx42("div", { ref: endRef, className: "ss-w-turn-spacer", "aria-hidden": "true" })
|
|
2310
2713
|
]
|
|
2311
2714
|
}
|
|
2312
2715
|
);
|
|
2313
2716
|
}
|
|
2314
2717
|
|
|
2315
2718
|
// src/components/ChatInput.tsx
|
|
2316
|
-
import { useState as
|
|
2317
|
-
import { jsx as
|
|
2719
|
+
import { useState as useState14 } from "react";
|
|
2720
|
+
import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2318
2721
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
2319
|
-
const [value, setValue] =
|
|
2722
|
+
const [value, setValue] = useState14("");
|
|
2320
2723
|
const submit = () => {
|
|
2321
2724
|
const t = value.trim();
|
|
2322
2725
|
if (!t) return;
|
|
@@ -2329,18 +2732,228 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
2329
2732
|
submit();
|
|
2330
2733
|
}
|
|
2331
2734
|
};
|
|
2332
|
-
return /* @__PURE__ */
|
|
2333
|
-
/* @__PURE__ */
|
|
2334
|
-
streaming ? /* @__PURE__ */
|
|
2735
|
+
return /* @__PURE__ */ jsxs38("div", { className: "ss-w-input", children: [
|
|
2736
|
+
/* @__PURE__ */ jsx43("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
2737
|
+
streaming ? /* @__PURE__ */ jsx43("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ jsx43("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ jsx43("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ jsx43(SendIcon, {}) })
|
|
2738
|
+
] });
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
// src/components/TabBar.tsx
|
|
2742
|
+
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
2743
|
+
var TABS = [
|
|
2744
|
+
{ tab: "chat", labelKey: "tabChat" },
|
|
2745
|
+
{ tab: "matches", labelKey: "tabMatches" },
|
|
2746
|
+
{ tab: "odds", labelKey: "tabOdds" }
|
|
2747
|
+
];
|
|
2748
|
+
function TabBar({ monitor, ui, matchCount, oddsCount }) {
|
|
2749
|
+
if (monitor.pins.length === 0) return null;
|
|
2750
|
+
const counts = { chat: 0, matches: matchCount, odds: oddsCount };
|
|
2751
|
+
const dots = {
|
|
2752
|
+
chat: monitor.chatDot && monitor.activeTab !== "chat",
|
|
2753
|
+
matches: monitor.matchesDot && monitor.activeTab !== "matches",
|
|
2754
|
+
odds: monitor.oddsDot && monitor.activeTab !== "odds"
|
|
2755
|
+
};
|
|
2756
|
+
return /* @__PURE__ */ jsx44("div", { className: "ss-w-tabs", role: "tablist", children: TABS.map(({ tab, labelKey }) => {
|
|
2757
|
+
const active = monitor.activeTab === tab;
|
|
2758
|
+
const count = counts[tab];
|
|
2759
|
+
return /* @__PURE__ */ jsxs39(
|
|
2760
|
+
"button",
|
|
2761
|
+
{
|
|
2762
|
+
type: "button",
|
|
2763
|
+
role: "tab",
|
|
2764
|
+
"aria-selected": active,
|
|
2765
|
+
"data-on": active ? "" : void 0,
|
|
2766
|
+
className: "ss-w-tab",
|
|
2767
|
+
onClick: () => monitor.setActiveTab(tab),
|
|
2768
|
+
children: [
|
|
2769
|
+
ui[labelKey],
|
|
2770
|
+
count > 0 && /* @__PURE__ */ jsx44("span", { className: "ss-w-tab-count", children: count }),
|
|
2771
|
+
dots[tab] && /* @__PURE__ */ jsx44("span", { className: "ss-w-tab-dot", "aria-hidden": "true" })
|
|
2772
|
+
]
|
|
2773
|
+
},
|
|
2774
|
+
tab
|
|
2775
|
+
);
|
|
2776
|
+
}) });
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
// src/components/MonitorMatchCard.tsx
|
|
2780
|
+
import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
2781
|
+
function chipSelection(row, matchId, conversationId) {
|
|
2782
|
+
const chip = row.market;
|
|
2783
|
+
if (!chip || !chip.addToSlipEnabled || typeof chip.matchOddsId !== "number" || typeof chip.price !== "number") return null;
|
|
2784
|
+
const selection = { matchOddsId: chip.matchOddsId, matchId, oddsDecimal: chip.price };
|
|
2785
|
+
if (conversationId !== void 0) selection.conversationId = conversationId;
|
|
2786
|
+
return selection;
|
|
2787
|
+
}
|
|
2788
|
+
function isPromoted(row, promotedPins) {
|
|
2789
|
+
const chip = row.market;
|
|
2790
|
+
if (!chip) return false;
|
|
2791
|
+
return promotedPins.some((pin) => pin.marketDeveloperName === chip.marketDeveloperName || chip.matchOddsId != null && pin.matchOddsId === chip.matchOddsId);
|
|
2792
|
+
}
|
|
2793
|
+
function formatTime(iso) {
|
|
2794
|
+
return new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
2795
|
+
}
|
|
2796
|
+
function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
|
|
2797
|
+
const live = match.phase === "live";
|
|
2798
|
+
const scorers = match.events.filter((e) => e.type === "goal");
|
|
2799
|
+
const promotedRows = match.statRows.filter((row) => isPromoted(row, promotedPins));
|
|
2800
|
+
const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins));
|
|
2801
|
+
const orderedRows = [...promotedRows, ...otherRows];
|
|
2802
|
+
const kickoff = match.phase === "preMatch" && match.kickoffUtc ? ui.bettingKickoff(match.kickoffUtc) : void 0;
|
|
2803
|
+
return /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon", children: [
|
|
2804
|
+
/* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-top", children: [
|
|
2805
|
+
live && /* @__PURE__ */ jsxs40("span", { className: "ss-w-fandash-live-pill", children: [
|
|
2806
|
+
/* @__PURE__ */ jsx45("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
|
|
2807
|
+
ui.liveLabel
|
|
2808
|
+
] }),
|
|
2809
|
+
match.phase === "fullTime" && /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
|
|
2810
|
+
kickoff && /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-pill", children: [
|
|
2811
|
+
kickoff.dayLabel,
|
|
2812
|
+
" \xB7 ",
|
|
2813
|
+
kickoff.time
|
|
2814
|
+
] }),
|
|
2815
|
+
live && match.minuteLabel && /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-min", children: match.minuteLabel }),
|
|
2816
|
+
match.competitionName && /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-comp", children: match.competitionName }),
|
|
2817
|
+
/* @__PURE__ */ jsx45(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
|
|
2818
|
+
] }),
|
|
2819
|
+
/* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-main", children: [
|
|
2820
|
+
/* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-side", children: [
|
|
2821
|
+
/* @__PURE__ */ jsx45(Crest2, { kind: "team", url: match.homeCrestUrl ?? void 0, name: match.homeTeamName ?? void 0 }),
|
|
2822
|
+
/* @__PURE__ */ jsx45("span", { className: "ss-w-mon-name", children: match.homeTeamName })
|
|
2823
|
+
] }),
|
|
2824
|
+
match.phase === "preMatch" ? /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-vs", children: "vs" }) : /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-score", children: [
|
|
2825
|
+
match.homeScore,
|
|
2826
|
+
/* @__PURE__ */ jsx45("i", { children: "\u2013" }),
|
|
2827
|
+
match.awayScore
|
|
2828
|
+
] }),
|
|
2829
|
+
/* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-side ss-w-mon-side--away", children: [
|
|
2830
|
+
/* @__PURE__ */ jsx45(Crest2, { kind: "team", url: match.awayCrestUrl ?? void 0, name: match.awayTeamName ?? void 0 }),
|
|
2831
|
+
/* @__PURE__ */ jsx45("span", { className: "ss-w-mon-name", children: match.awayTeamName })
|
|
2832
|
+
] })
|
|
2833
|
+
] }),
|
|
2834
|
+
scorers.length > 0 && /* @__PURE__ */ jsx45("div", { className: "ss-w-mon-scorers", children: scorers.map((e) => `${e.player ?? ""} ${e.minuteLabel}`).join(", ") }),
|
|
2835
|
+
/* @__PURE__ */ jsx45("div", { className: "ss-w-mon-stats", children: orderedRows.map((row) => {
|
|
2836
|
+
const total = row.homeNum + row.awayNum;
|
|
2837
|
+
const homePct = total > 0 ? row.homeNum / total * 75 : 0;
|
|
2838
|
+
const awayPct = total > 0 ? row.awayNum / total * 75 : 0;
|
|
2839
|
+
const promoted = isPromoted(row, promotedPins);
|
|
2840
|
+
const selection = chipSelection(row, match.matchId, slip.conversationId);
|
|
2841
|
+
return /* @__PURE__ */ jsxs40("div", { className: promoted ? "ss-w-mon-stat ss-w-mon-pstrip" : "ss-w-mon-stat", children: [
|
|
2842
|
+
/* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-stat-row", children: [
|
|
2843
|
+
/* @__PURE__ */ jsx45("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: row.homeValue }),
|
|
2844
|
+
/* @__PURE__ */ jsx45("span", { className: "ss-w-mon-stat-l", children: row.label }),
|
|
2845
|
+
/* @__PURE__ */ jsx45("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: row.awayValue })
|
|
2846
|
+
] }),
|
|
2847
|
+
/* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-bar", children: [
|
|
2848
|
+
/* @__PURE__ */ jsx45("b", { className: "ss-w-mon-bar-home", style: { width: `${homePct}%` } }),
|
|
2849
|
+
/* @__PURE__ */ jsx45("i", { className: "ss-w-mon-bar-away", style: { width: `${awayPct}%` } })
|
|
2850
|
+
] }),
|
|
2851
|
+
row.market && /* @__PURE__ */ jsxs40("div", { className: promoted ? "ss-w-mon-stat-mkt ss-w-mon-mkt" : "ss-w-mon-stat-mkt", children: [
|
|
2852
|
+
/* @__PURE__ */ jsxs40("span", { children: [
|
|
2853
|
+
row.market.marketLabel,
|
|
2854
|
+
" \xB7 ",
|
|
2855
|
+
row.market.selectionLabel
|
|
2856
|
+
] }),
|
|
2857
|
+
/* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-stat-mkt-right", children: [
|
|
2858
|
+
row.market.isSuspended ? /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }) : typeof row.market.price === "number" && /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-price", children: row.market.price.toFixed(2) }),
|
|
2859
|
+
/* @__PURE__ */ jsx45(
|
|
2860
|
+
SlipButton,
|
|
2861
|
+
{
|
|
2862
|
+
selection,
|
|
2863
|
+
shownOdds: typeof row.market.price === "number" ? row.market.price.toFixed(2) : "",
|
|
2864
|
+
marketName: row.market.marketLabel,
|
|
2865
|
+
slip,
|
|
2866
|
+
ui
|
|
2867
|
+
}
|
|
2868
|
+
)
|
|
2869
|
+
] })
|
|
2870
|
+
] })
|
|
2871
|
+
] }, row.label);
|
|
2872
|
+
}) }),
|
|
2873
|
+
match.status === "stale" && /* @__PURE__ */ jsx45("span", { className: "ss-w-mon-asof", children: ui.asOf(formatTime(match.asOfUtc)) }),
|
|
2874
|
+
match.momentum.length > 0 && /* @__PURE__ */ jsx45(MomentumWave, { points: match.momentum, clubIsHome: true }),
|
|
2875
|
+
match.mainMarket && match.phase !== "fullTime" && /* @__PURE__ */ jsx45(MarketOddsCardList, { cards: [toMarketOddsVM(match.mainMarket)], ui, slip }),
|
|
2876
|
+
match.phase === "fullTime" && /* @__PURE__ */ jsx45("div", { className: "ss-w-mon-grace", children: ui.graceNote })
|
|
2335
2877
|
] });
|
|
2336
2878
|
}
|
|
2337
2879
|
|
|
2880
|
+
// src/components/MonitorTabs.tsx
|
|
2881
|
+
import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
2882
|
+
function ContextLine({ m, monitor, ui }) {
|
|
2883
|
+
return /* @__PURE__ */ jsxs41("div", { className: "ss-w-mk-ctx", children: [
|
|
2884
|
+
/* @__PURE__ */ jsx46(Crest2, { kind: "team", name: m.homeTeamName ?? void 0 }),
|
|
2885
|
+
typeof m.homeScore === "number" && /* @__PURE__ */ jsxs41("b", { children: [
|
|
2886
|
+
m.homeScore,
|
|
2887
|
+
"\u2013",
|
|
2888
|
+
m.awayScore
|
|
2889
|
+
] }),
|
|
2890
|
+
/* @__PURE__ */ jsx46(Crest2, { kind: "team", name: m.awayTeamName ?? void 0 }),
|
|
2891
|
+
/* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-name", children: [
|
|
2892
|
+
m.homeTeamName,
|
|
2893
|
+
" v ",
|
|
2894
|
+
m.awayTeamName
|
|
2895
|
+
] }),
|
|
2896
|
+
m.minuteLabel && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
|
|
2897
|
+
/* @__PURE__ */ jsxs41("span", { className: "ss-w-mk-ctx-right", children: [
|
|
2898
|
+
m.isSuspended && !m.isSettled && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
|
|
2899
|
+
m.isSettled && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
|
|
2900
|
+
m.status === "stale" && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) }),
|
|
2901
|
+
(() => {
|
|
2902
|
+
const pin = monitor.pins.find((p) => p.key === m.key);
|
|
2903
|
+
return pin ? /* @__PURE__ */ jsx46(PinToggle, { ui, monitor, pin }) : null;
|
|
2904
|
+
})()
|
|
2905
|
+
] })
|
|
2906
|
+
] });
|
|
2907
|
+
}
|
|
2908
|
+
function MatchesPanel({ monitor, ui, slip }) {
|
|
2909
|
+
const matches = (monitor.snapshot?.matches ?? []).filter((m) => monitor.pins.some((p) => p.kind === "match" && p.matchId === m.matchId));
|
|
2910
|
+
if (matches.length === 0) return /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-empty", children: ui.emptyMatchesTab });
|
|
2911
|
+
return /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-list", children: matches.map((m) => /* @__PURE__ */ jsx46(
|
|
2912
|
+
MonitorMatchCard,
|
|
2913
|
+
{
|
|
2914
|
+
match: m,
|
|
2915
|
+
promotedPins: monitor.pins.filter((p) => p.kind !== "match" && p.matchId === m.matchId),
|
|
2916
|
+
monitor,
|
|
2917
|
+
ui,
|
|
2918
|
+
slip
|
|
2919
|
+
},
|
|
2920
|
+
m.matchId
|
|
2921
|
+
)) });
|
|
2922
|
+
}
|
|
2923
|
+
function withSinceViewMovement(vm, prev) {
|
|
2924
|
+
const primary = vm.mainRows[0];
|
|
2925
|
+
if (prev === void 0 || !primary || primary.oddsDecimal === void 0 || primary.oddsDecimal === prev) return vm;
|
|
2926
|
+
const updatedPrimary = {
|
|
2927
|
+
...primary,
|
|
2928
|
+
previousOdds: prev.toFixed(2),
|
|
2929
|
+
movementDirection: primary.oddsDecimal < prev ? "shortened" : "drifted"
|
|
2930
|
+
};
|
|
2931
|
+
return { ...vm, mainRows: [updatedPrimary, ...vm.mainRows.slice(1)] };
|
|
2932
|
+
}
|
|
2933
|
+
function OddsPanel({ monitor, ui, slip }) {
|
|
2934
|
+
const markets = (monitor.snapshot?.markets ?? []).filter((m) => monitor.pins.some((p) => p.key === m.key));
|
|
2935
|
+
if (markets.length === 0) return /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-empty", children: ui.emptyOddsTab });
|
|
2936
|
+
return /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-list", children: markets.map((m) => /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
|
|
2937
|
+
/* @__PURE__ */ jsx46(ContextLine, { m, monitor, ui }),
|
|
2938
|
+
m.card && /* @__PURE__ */ jsx46(
|
|
2939
|
+
MarketOddsCardList,
|
|
2940
|
+
{
|
|
2941
|
+
cards: [withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])],
|
|
2942
|
+
ui,
|
|
2943
|
+
slip,
|
|
2944
|
+
inSlipIds: monitor.inSlip
|
|
2945
|
+
}
|
|
2946
|
+
),
|
|
2947
|
+
m.history && /* @__PURE__ */ jsx46(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui })
|
|
2948
|
+
] }, m.key)) });
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2338
2951
|
// src/components/ChatPanel.tsx
|
|
2339
|
-
import { jsx as
|
|
2952
|
+
import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
2340
2953
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
2341
2954
|
function useIsModal() {
|
|
2342
|
-
const [modal, setModal] =
|
|
2343
|
-
|
|
2955
|
+
const [modal, setModal] = useState15(false);
|
|
2956
|
+
useEffect8(() => {
|
|
2344
2957
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
2345
2958
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
2346
2959
|
const sync = () => setModal(mql.matches);
|
|
@@ -2350,20 +2963,44 @@ function useIsModal() {
|
|
|
2350
2963
|
}, []);
|
|
2351
2964
|
return modal;
|
|
2352
2965
|
}
|
|
2353
|
-
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
2966
|
+
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
2354
2967
|
const { state, close, stop, send } = controller;
|
|
2355
2968
|
const isModal = useIsModal();
|
|
2356
|
-
|
|
2969
|
+
useEffect8(() => {
|
|
2357
2970
|
const onKey = (e) => {
|
|
2358
2971
|
if (e.key === "Escape") close();
|
|
2359
2972
|
};
|
|
2360
2973
|
window.addEventListener("keydown", onKey);
|
|
2361
2974
|
return () => window.removeEventListener("keydown", onKey);
|
|
2362
2975
|
}, [close]);
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2976
|
+
const handleSend = (text) => {
|
|
2977
|
+
monitor?.setActiveTab("chat");
|
|
2978
|
+
send(text);
|
|
2979
|
+
};
|
|
2980
|
+
useEffect8(() => {
|
|
2981
|
+
if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
|
|
2982
|
+
}, [monitor, state.isStreaming, state.messages.length]);
|
|
2983
|
+
return /* @__PURE__ */ jsxs42("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
2984
|
+
/* @__PURE__ */ jsx47(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
2985
|
+
monitor && /* @__PURE__ */ jsx47(
|
|
2986
|
+
TabBar,
|
|
2987
|
+
{
|
|
2988
|
+
monitor,
|
|
2989
|
+
ui,
|
|
2990
|
+
matchCount: monitor.pins.filter((p) => p.kind === "match").length,
|
|
2991
|
+
oddsCount: monitor.pins.filter((p) => p.kind !== "match").length
|
|
2992
|
+
}
|
|
2993
|
+
),
|
|
2994
|
+
/* @__PURE__ */ jsx47(
|
|
2995
|
+
"div",
|
|
2996
|
+
{
|
|
2997
|
+
style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
|
|
2998
|
+
children: /* @__PURE__ */ jsx47(MessageList, { controller, ui, slip, onDashboardTap, monitor })
|
|
2999
|
+
}
|
|
3000
|
+
),
|
|
3001
|
+
monitor && monitor.activeTab === "matches" && /* @__PURE__ */ jsx47(MatchesPanel, { monitor, ui, slip }),
|
|
3002
|
+
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ jsx47(OddsPanel, { monitor, ui, slip }),
|
|
3003
|
+
/* @__PURE__ */ jsx47(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
2367
3004
|
] });
|
|
2368
3005
|
}
|
|
2369
3006
|
|
|
@@ -2431,7 +3068,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2431
3068
|
.ss-w-close { margin-left: auto; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }
|
|
2432
3069
|
|
|
2433
3070
|
/* messages */
|
|
2434
|
-
.ss-w-list
|
|
3071
|
+
/* .ss-w-mon-list (Matches/Odds tab scrollers) shares .ss-w-list's box/scroll rules by design --
|
|
3072
|
+
same visual rhythm as the chat message list -- but gets its own class so it isn't the same DOM
|
|
3073
|
+
landmark as the chat list when both exist in the panel at once (Task 16 fix round, M4). */
|
|
3074
|
+
.ss-w-list, .ss-w-mon-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; scroll-padding-top: 14px; }
|
|
2435
3075
|
/* Transient bottom spacer: reserves a viewport of room below a new turn so its
|
|
2436
3076
|
top can be scrolled into view while the reply is still streaming in. Height is
|
|
2437
3077
|
set imperatively and flex must not shrink it away. */
|
|
@@ -2547,8 +3187,6 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2547
3187
|
.ss-w-bi-odds b { font-size: 20px; font-family: ui-monospace, monospace; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.05; }
|
|
2548
3188
|
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
2549
3189
|
.ss-w-bi-action-row .ss-w-slip { flex: none; }
|
|
2550
|
-
/* let the slip toast size to its own text and anchor to the card's right edge, not the button width */
|
|
2551
|
-
.ss-w-bi-action-row .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
|
|
2552
3190
|
|
|
2553
3191
|
/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
|
|
2554
3192
|
.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }
|
|
@@ -2655,10 +3293,21 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2655
3293
|
.ss-w-slip { position: relative; display: flex; }
|
|
2656
3294
|
.ss-w-slip-btn { font-size: 11.5px; font-weight: 620; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: 1px solid var(--ss-w-cta); border-radius: 14px; padding: 5px 12px; cursor: pointer; }
|
|
2657
3295
|
.ss-w-slip-btn:disabled { opacity: .6; cursor: default; background: var(--ss-w-bubble); color: var(--ss-w-faint); border-color: var(--ss-w-line); }
|
|
2658
|
-
|
|
3296
|
+
/* Anchored to the RIGHT of its (narrow) button wrapper and sized by content, growing leftward
|
|
3297
|
+
into the card -- inheriting the wrapper's width squeezes the text to one character per line.
|
|
3298
|
+
Every toast site (slip buttons, pin toggles) sits at the right edge of its row. */
|
|
3299
|
+
.ss-w-toast { position: absolute; top: calc(100% + 6px); right: 0; z-index: 1; width: max-content; max-width: 210px; font-size: 11px; font-weight: 560; border-radius: 10px; padding: 5px 10px; overflow-wrap: anywhere; box-shadow: 0 4px 14px rgba(0,0,0,.14); }
|
|
2659
3300
|
.ss-w-toast-success { color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); }
|
|
2660
3301
|
.ss-w-toast-error { color: #c0392b; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }
|
|
2661
3302
|
|
|
3303
|
+
/* pin affordance */
|
|
3304
|
+
.ss-w-pin-wrap { position: relative; display: inline-flex; flex: none; }
|
|
3305
|
+
.ss-w-pin { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }
|
|
3306
|
+
.ss-w-pin svg { width: 12px; height: 12px; }
|
|
3307
|
+
.ss-w-pin:hover { color: var(--ss-w-ink); border-color: var(--ss-w-faint); }
|
|
3308
|
+
.ss-w-pin[data-on] { background: var(--ss-w-accent); border-color: var(--ss-w-accent); color: #fff; }
|
|
3309
|
+
.ss-w-pin[data-on]:hover { background: var(--ss-w-accent); color: #fff; }
|
|
3310
|
+
|
|
2662
3311
|
@media (prefers-reduced-motion: reduce) {
|
|
2663
3312
|
.ss-w-abtn-shimmer { animation: none; }
|
|
2664
3313
|
}
|
|
@@ -3027,10 +3676,68 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
3027
3676
|
.ss-w-fandash-live-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
|
|
3028
3677
|
.ss-w-fandash-live-legend-swatch--home { background: var(--ss-w-home); }
|
|
3029
3678
|
.ss-w-fandash-live-legend-swatch--away { background: var(--ss-w-away); }
|
|
3679
|
+
|
|
3680
|
+
/* live monitor tab bar: underline pattern mirrors .ss-w-ecard-scope; the unread dot uses --ss-w-neg */
|
|
3681
|
+
.ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); }
|
|
3682
|
+
.ss-w-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 9px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; }
|
|
3683
|
+
.ss-w-tab[data-on] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }
|
|
3684
|
+
.ss-w-tab-count { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 999px; padding: 1px 6px; }
|
|
3685
|
+
.ss-w-tab[data-on] .ss-w-tab-count { color: var(--ss-w-accent); }
|
|
3686
|
+
.ss-w-tab-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }
|
|
3687
|
+
|
|
3688
|
+
/* Matches tab match card (MonitorMatchCard): pill row, crest/score main row, per-stat split
|
|
3689
|
+
bars (venue-oriented -- home always left/blue, away always right/red, never club-oriented,
|
|
3690
|
+
the u316 bug class), a promoted-market strip for the user's pinned stat chips, and a grace
|
|
3691
|
+
note once the match has gone full time. Reuses the --ss-w-home/--ss-w-away/--ss-w-track venue
|
|
3692
|
+
tokens and .ss-w-fandash-live-pill for the Live pill so all live surfaces share one look. */
|
|
3693
|
+
.ss-w-mon { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }
|
|
3694
|
+
.ss-w-mon-top { display: flex; align-items: center; gap: 8px; }
|
|
3695
|
+
.ss-w-mon-pill { display: inline-flex; flex: none; align-items: center; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 3px 8px; }
|
|
3696
|
+
.ss-w-mon-min { flex: none; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
3697
|
+
.ss-w-mon-comp { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3698
|
+
.ss-w-mon-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }
|
|
3699
|
+
.ss-w-mon-side { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
3700
|
+
.ss-w-mon-side--away { flex-direction: row-reverse; text-align: right; }
|
|
3701
|
+
.ss-w-mon-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; font-weight: 700; color: var(--ss-w-ink); }
|
|
3702
|
+
.ss-w-mon-vs { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; }
|
|
3703
|
+
.ss-w-mon-score { display: flex; align-items: baseline; justify-content: center; font-size: 26px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; color: var(--ss-w-ink); }
|
|
3704
|
+
.ss-w-mon-score i { font-style: normal; color: var(--ss-w-faint); font-weight: 500; margin: 0 4px; }
|
|
3705
|
+
.ss-w-mon-scorers { font-size: 11.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }
|
|
3706
|
+
.ss-w-mon-stats { display: flex; flex-direction: column; gap: 10px; }
|
|
3707
|
+
.ss-w-mon-stat { display: flex; flex-direction: column; gap: 5px; }
|
|
3708
|
+
.ss-w-mon-pstrip { padding: 6px 8px; border-radius: 8px; background: color-mix(in srgb, var(--ss-w-accent) 8%, transparent); }
|
|
3709
|
+
.ss-w-mon-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }
|
|
3710
|
+
.ss-w-mon-stat-v { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
3711
|
+
.ss-w-mon-stat-v--home { color: var(--ss-w-home); }
|
|
3712
|
+
.ss-w-mon-stat-v--away { color: var(--ss-w-away); text-align: right; }
|
|
3713
|
+
.ss-w-mon-stat-l { font-size: 10px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }
|
|
3714
|
+
.ss-w-mon-bar { position: relative; height: 6px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }
|
|
3715
|
+
.ss-w-mon-bar-home { height: 100%; background: var(--ss-w-home); }
|
|
3716
|
+
.ss-w-mon-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }
|
|
3717
|
+
.ss-w-mon-stat-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ss-w-faint); }
|
|
3718
|
+
.ss-w-mon-mkt { background: color-mix(in srgb, var(--ss-w-accent) 10%, transparent); border-radius: 6px; padding: 3px 6px; color: var(--ss-w-ink); }
|
|
3719
|
+
.ss-w-mon-stat-mkt-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }
|
|
3720
|
+
.ss-w-mon-price { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }
|
|
3721
|
+
.ss-w-mon-susp { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 2px 6px; }
|
|
3722
|
+
.ss-w-mon-asof { display: block; font-size: 10.5px; font-weight: 600; color: var(--ss-w-cta); }
|
|
3723
|
+
.ss-w-mon-grace { font-size: 11px; color: var(--ss-w-faint); border-top: 1px solid var(--ss-w-line); padding-top: 8px; }
|
|
3724
|
+
|
|
3725
|
+
/* Matches/Odds tab panels (MonitorTabs): the shared per-market-pin context line, the empty
|
|
3726
|
+
state shown when the snapshot carries no matches/markets yet, the persistent D5 in-slip badge,
|
|
3727
|
+
and the per-market-pin wrapper card (struck price on settlement is a pure CSS hook off its
|
|
3728
|
+
[data-settled] attribute -- no separate class on the price element itself). */
|
|
3729
|
+
.ss-w-mk-ctx { display: flex; align-items: center; gap: 6px; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--ss-w-line); }
|
|
3730
|
+
.ss-w-mk-ctx-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }
|
|
3731
|
+
/* flex:1 keeps the composer pinned to the panel bottom when a tab is empty */
|
|
3732
|
+
.ss-w-mon-empty { flex: 1; padding: 24px 16px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }
|
|
3733
|
+
.ss-w-mon-inslip { display: inline-flex; flex: none; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-pos); }
|
|
3734
|
+
.ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }
|
|
3735
|
+
.ss-w-mon-oddspin[data-settled] .ss-w-mo-price,
|
|
3736
|
+
.ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }
|
|
3030
3737
|
`;
|
|
3031
3738
|
|
|
3032
3739
|
// src/StatsWidget.tsx
|
|
3033
|
-
import { jsx as
|
|
3740
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
3034
3741
|
function buildClient(props) {
|
|
3035
3742
|
try {
|
|
3036
3743
|
if ("client" in props && props.client) {
|
|
@@ -3057,33 +3764,48 @@ function StatsWidget(props) {
|
|
|
3057
3764
|
const cfg = props.config;
|
|
3058
3765
|
const built = useMemo2(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
3059
3766
|
const ui = useMemo2(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
3060
|
-
const rootRef =
|
|
3767
|
+
const rootRef = useRef6(null);
|
|
3061
3768
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
3769
|
+
const monitor = useLiveMonitor({
|
|
3770
|
+
getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
|
|
3771
|
+
storageKey: `ss-w-pins:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`,
|
|
3772
|
+
isOpen: controller.state.isOpen
|
|
3773
|
+
});
|
|
3062
3774
|
const slip = useMemo2(
|
|
3063
|
-
() =>
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3775
|
+
() => {
|
|
3776
|
+
const handler = props.config?.onAddToSlip;
|
|
3777
|
+
return {
|
|
3778
|
+
// I3: the D5 persistent in-slip badge must arm from ANY add path -- a chat-message
|
|
3779
|
+
// insight/market card, not just the ones rendered inside the Odds tab itself -- so the
|
|
3780
|
+
// wasAdded->markInSlip wrap lives here (once), not duplicated per consumer.
|
|
3781
|
+
onAddToSlip: handler && (async (sel) => {
|
|
3782
|
+
const result = await handler(sel);
|
|
3783
|
+
if (wasAdded(result)) monitor.markInSlip(sel.matchOddsId);
|
|
3784
|
+
return result;
|
|
3785
|
+
}),
|
|
3786
|
+
conversationId: controller.state.conversationId ?? void 0,
|
|
3787
|
+
onMarketClicked: (marketName) => {
|
|
3788
|
+
try {
|
|
3789
|
+
void built?.conversation.sendSignal({ signalType: "InsightMarketClicked", entityType: "Market", entityName: marketName }).catch(() => void 0);
|
|
3790
|
+
} catch {
|
|
3791
|
+
}
|
|
3070
3792
|
}
|
|
3071
|
-
}
|
|
3072
|
-
}
|
|
3073
|
-
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
3793
|
+
};
|
|
3794
|
+
},
|
|
3795
|
+
[props.config?.onAddToSlip, controller.state.conversationId, built, monitor.markInSlip]
|
|
3074
3796
|
);
|
|
3075
3797
|
const onDashboardTap = useMemo2(
|
|
3076
3798
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
3077
3799
|
[built]
|
|
3078
3800
|
);
|
|
3079
|
-
|
|
3801
|
+
useEffect9(() => {
|
|
3080
3802
|
if (!built || !ui.injectStyles) return;
|
|
3081
3803
|
const node = rootRef.current?.getRootNode();
|
|
3082
3804
|
if (node) injectStyles(node);
|
|
3083
3805
|
}, [built, ui.injectStyles]);
|
|
3084
3806
|
if (!built) return null;
|
|
3085
3807
|
const attrs = themeAttrs(ui);
|
|
3086
|
-
return /* @__PURE__ */
|
|
3808
|
+
return /* @__PURE__ */ jsx48("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ jsx48(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0 }) : /* @__PURE__ */ jsx48(
|
|
3087
3809
|
ChatFab,
|
|
3088
3810
|
{
|
|
3089
3811
|
label: ui.launcherLabel,
|