@sensiblestats/widget-react 0.29.5 → 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 +22 -0
- package/dist/index.cjs +1335 -590
- 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 +1329 -584
- package/dist/index.js.map +1 -1
- package/dist/styles.css +93 -11
- 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+CiAgICAgICAgICAgIDxzdFJlZjppbnN0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";
|
|
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,98 +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
|
|
1426
|
-
function
|
|
1427
|
-
|
|
1428
|
-
if (
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
/* @__PURE__ */
|
|
1438
|
-
|
|
1439
|
-
/* @__PURE__ */ jsx17("span", { className: "ss-w-fandash-formrow-name", children: name })
|
|
1440
|
-
] }),
|
|
1441
|
-
/* @__PURE__ */ jsx17(FormStrip, { form })
|
|
1827
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1828
|
+
function teamFormResultClass(result) {
|
|
1829
|
+
if (result === "W") return "ss-w-fandash-teamform-cell--win";
|
|
1830
|
+
if (result === "L") return "ss-w-fandash-teamform-cell--loss";
|
|
1831
|
+
return "ss-w-fandash-teamform-cell--draw";
|
|
1832
|
+
}
|
|
1833
|
+
function TeamFormCell({ m, subjectCrestUrl, subjectName }) {
|
|
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" });
|
|
1836
|
+
const score = m.teamIsHome ? `${m.teamScore} - ${m.oppScore}` : `${m.oppScore} - ${m.teamScore}`;
|
|
1837
|
+
return /* @__PURE__ */ jsxs14("div", { className: `ss-w-fandash-teamform-cell ${teamFormResultClass(m.result)}`, children: [
|
|
1838
|
+
m.teamIsHome ? subjectCrest : opponentCrest,
|
|
1839
|
+
/* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-teamform-score", children: score }),
|
|
1840
|
+
m.teamIsHome ? opponentCrest : subjectCrest
|
|
1442
1841
|
] });
|
|
1443
1842
|
}
|
|
1843
|
+
var TEAM_FORM_ROWS = 5;
|
|
1844
|
+
function teamFormRows(data) {
|
|
1845
|
+
return Array.from({ length: TEAM_FORM_ROWS }, (_, i) => i).flatMap((i) => [
|
|
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}`)
|
|
1848
|
+
]);
|
|
1849
|
+
}
|
|
1444
1850
|
function FixtureCard({ card }) {
|
|
1445
1851
|
const { data } = card;
|
|
1446
1852
|
const h2h = data.h2H;
|
|
1447
|
-
return /* @__PURE__ */
|
|
1448
|
-
/* @__PURE__ */
|
|
1449
|
-
/* @__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: [
|
|
1450
1856
|
card.title,
|
|
1451
1857
|
" \xB7 ",
|
|
1452
1858
|
data.competition
|
|
1453
1859
|
] }),
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
/* @__PURE__ */
|
|
1456
|
-
/* @__PURE__ */
|
|
1457
|
-
/* @__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 })
|
|
1458
1864
|
] }),
|
|
1459
|
-
/* @__PURE__ */
|
|
1460
|
-
/* @__PURE__ */
|
|
1461
|
-
/* @__PURE__ */
|
|
1462
|
-
/* @__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" })
|
|
1463
1869
|
] })
|
|
1464
1870
|
] }),
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
/* @__PURE__ */
|
|
1467
|
-
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: [
|
|
1468
1874
|
" \xB7 ",
|
|
1469
1875
|
data.venue
|
|
1470
1876
|
] }) : null
|
|
1471
1877
|
] })
|
|
1472
1878
|
] }),
|
|
1473
|
-
/* @__PURE__ */
|
|
1474
|
-
/* @__PURE__ */
|
|
1475
|
-
/* @__PURE__ */
|
|
1476
|
-
/* @__PURE__ */
|
|
1477
|
-
|
|
1478
|
-
|
|
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 })
|
|
1885
|
+
] }),
|
|
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 })
|
|
1889
|
+
] })
|
|
1890
|
+
] }),
|
|
1891
|
+
/* @__PURE__ */ jsx18("div", { className: "ss-w-fandash-teamform-rows", children: teamFormRows(data) })
|
|
1479
1892
|
] }),
|
|
1480
|
-
h2h || data.fact ? /* @__PURE__ */
|
|
1481
|
-
h2h ? /* @__PURE__ */
|
|
1482
|
-
/* @__PURE__ */
|
|
1483
|
-
/* @__PURE__ */
|
|
1484
|
-
/* @__PURE__ */
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
/* @__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 })
|
|
1487
1900
|
] }),
|
|
1488
|
-
/* @__PURE__ */
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
/* @__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 })
|
|
1491
1904
|
] }),
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
/* @__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 })
|
|
1495
1908
|
] })
|
|
1496
1909
|
] })
|
|
1497
1910
|
] }) : null,
|
|
1498
|
-
data.fact ? /* @__PURE__ */
|
|
1911
|
+
data.fact ? /* @__PURE__ */ jsx18("span", { className: "ss-w-fandash-fact", children: data.fact }) : null
|
|
1499
1912
|
] }) : null
|
|
1500
1913
|
] });
|
|
1501
1914
|
}
|
|
1502
1915
|
|
|
1503
1916
|
// src/components/dashboard/CountdownCard.tsx
|
|
1504
|
-
import { Fragment as Fragment6, useEffect as
|
|
1505
|
-
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";
|
|
1506
1919
|
var DAY_MS = 864e5;
|
|
1507
1920
|
function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
1508
1921
|
const totalSeconds = Math.floor((kickoffUnix * 1e3 - nowMs) / 1e3);
|
|
@@ -1520,72 +1933,72 @@ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
|
1520
1933
|
function CountdownCard({ card }) {
|
|
1521
1934
|
const { data } = card;
|
|
1522
1935
|
const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
|
|
1523
|
-
const [nowMs, setNowMs] =
|
|
1524
|
-
const [reduced] =
|
|
1936
|
+
const [nowMs, setNowMs] = useState8(() => Date.now());
|
|
1937
|
+
const [reduced] = useState8(
|
|
1525
1938
|
() => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
1526
1939
|
);
|
|
1527
1940
|
const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
|
|
1528
|
-
|
|
1941
|
+
useEffect5(() => {
|
|
1529
1942
|
if (reduced) return;
|
|
1530
1943
|
const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
|
|
1531
1944
|
return () => window.clearInterval(id);
|
|
1532
1945
|
}, [reduced, withinDay]);
|
|
1533
1946
|
const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced);
|
|
1534
|
-
return /* @__PURE__ */
|
|
1535
|
-
/* @__PURE__ */
|
|
1536
|
-
segments ? /* @__PURE__ */
|
|
1537
|
-
i > 0 ? /* @__PURE__ */
|
|
1538
|
-
/* @__PURE__ */
|
|
1539
|
-
/* @__PURE__ */
|
|
1540
|
-
/* @__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] })
|
|
1541
1954
|
] })
|
|
1542
1955
|
] }, s.unit)) }) : null
|
|
1543
1956
|
] }) });
|
|
1544
1957
|
}
|
|
1545
1958
|
|
|
1546
1959
|
// src/components/dashboard/InjuriesCard.tsx
|
|
1547
|
-
import { useState as
|
|
1548
|
-
import { jsx as
|
|
1960
|
+
import { useState as useState9 } from "react";
|
|
1961
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1549
1962
|
var SHOWN = 3;
|
|
1550
1963
|
function ColHead({ name, crestUrl }) {
|
|
1551
|
-
return /* @__PURE__ */
|
|
1552
|
-
/* @__PURE__ */
|
|
1553
|
-
/* @__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 })
|
|
1554
1967
|
] });
|
|
1555
1968
|
}
|
|
1556
1969
|
function InjuryList({ rows, emptyLabel, limit }) {
|
|
1557
|
-
if (rows.length === 0) return /* @__PURE__ */
|
|
1970
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx20("span", { className: "ss-w-fandash-injuries-empty", children: emptyLabel });
|
|
1558
1971
|
const shown = limit === void 0 ? rows : rows.slice(0, limit);
|
|
1559
|
-
return /* @__PURE__ */
|
|
1560
|
-
/* @__PURE__ */
|
|
1561
|
-
/* @__PURE__ */
|
|
1562
|
-
/* @__PURE__ */
|
|
1563
|
-
r.injuryType ? /* @__PURE__ */
|
|
1564
|
-
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
|
|
1565
1978
|
] })
|
|
1566
1979
|
] }, `${r.playerName}-${i}`)) });
|
|
1567
1980
|
}
|
|
1568
1981
|
function InjuriesCard({ card, ui }) {
|
|
1569
1982
|
const { data } = card;
|
|
1570
|
-
const [expanded, setExpanded] =
|
|
1983
|
+
const [expanded, setExpanded] = useState9(false);
|
|
1571
1984
|
const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
|
|
1572
1985
|
const limit = expanded ? void 0 : SHOWN;
|
|
1573
1986
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
1574
1987
|
const showLess = ui?.showLess ?? "Show less";
|
|
1575
|
-
return /* @__PURE__ */
|
|
1576
|
-
card.title ? /* @__PURE__ */
|
|
1577
|
-
/* @__PURE__ */
|
|
1578
|
-
/* @__PURE__ */
|
|
1579
|
-
/* @__PURE__ */
|
|
1580
|
-
/* @__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 })
|
|
1581
1994
|
] }),
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
1584
|
-
/* @__PURE__ */
|
|
1585
|
-
/* @__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 })
|
|
1586
1999
|
] })
|
|
1587
2000
|
] }),
|
|
1588
|
-
hidden > 0 ? /* @__PURE__ */
|
|
2001
|
+
hidden > 0 ? /* @__PURE__ */ jsx20(
|
|
1589
2002
|
"button",
|
|
1590
2003
|
{
|
|
1591
2004
|
type: "button",
|
|
@@ -1599,80 +2012,80 @@ function InjuriesCard({ card, ui }) {
|
|
|
1599
2012
|
}
|
|
1600
2013
|
|
|
1601
2014
|
// src/components/dashboard/ReasonToBetCard.tsx
|
|
1602
|
-
import { jsx as
|
|
2015
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1603
2016
|
function ReasonToBetCard({ card }) {
|
|
1604
|
-
return /* @__PURE__ */
|
|
1605
|
-
card.title ? /* @__PURE__ */
|
|
1606
|
-
/* @__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}`)) })
|
|
1607
2020
|
] });
|
|
1608
2021
|
}
|
|
1609
2022
|
|
|
1610
2023
|
// src/components/dashboard/WhereToWatchCard.tsx
|
|
1611
|
-
import { jsx as
|
|
2024
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1612
2025
|
function WhereToWatchCard({ card }) {
|
|
1613
|
-
return /* @__PURE__ */
|
|
1614
|
-
card.title ? /* @__PURE__ */
|
|
1615
|
-
/* @__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}`)) })
|
|
1616
2029
|
] });
|
|
1617
2030
|
}
|
|
1618
2031
|
|
|
1619
2032
|
// src/components/dashboard/CongestedWeekCard.tsx
|
|
1620
|
-
import { jsx as
|
|
2033
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1621
2034
|
function CongestedWeekCard({ card, onTap }) {
|
|
1622
|
-
return /* @__PURE__ */
|
|
1623
|
-
card.title ? /* @__PURE__ */
|
|
1624
|
-
/* @__PURE__ */
|
|
1625
|
-
/* @__PURE__ */
|
|
1626
|
-
/* @__PURE__ */
|
|
1627
|
-
/* @__PURE__ */
|
|
1628
|
-
/* @__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 })
|
|
1629
2042
|
] }, `${entry.opponent}-${i}`)) }),
|
|
1630
|
-
/* @__PURE__ */
|
|
2043
|
+
/* @__PURE__ */ jsx23("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1631
2044
|
] });
|
|
1632
2045
|
}
|
|
1633
2046
|
|
|
1634
2047
|
// src/components/dashboard/TransfersCard.tsx
|
|
1635
|
-
import { jsx as
|
|
2048
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1636
2049
|
function TransferList({ rows }) {
|
|
1637
|
-
if (rows.length === 0) return /* @__PURE__ */
|
|
1638
|
-
return /* @__PURE__ */
|
|
1639
|
-
/* @__PURE__ */
|
|
1640
|
-
/* @__PURE__ */
|
|
1641
|
-
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
|
|
1642
2055
|
] }, `${r.playerName}-${i}`)) });
|
|
1643
2056
|
}
|
|
1644
2057
|
function TransfersCard({ card }) {
|
|
1645
2058
|
const { data } = card;
|
|
1646
|
-
return /* @__PURE__ */
|
|
1647
|
-
card.title ? /* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__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 })
|
|
1652
2065
|
] }),
|
|
1653
|
-
/* @__PURE__ */
|
|
1654
|
-
/* @__PURE__ */
|
|
1655
|
-
/* @__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 })
|
|
1656
2069
|
] })
|
|
1657
2070
|
] })
|
|
1658
2071
|
] });
|
|
1659
2072
|
}
|
|
1660
2073
|
|
|
1661
2074
|
// src/components/dashboard/LinksCard.tsx
|
|
1662
|
-
import { jsx as
|
|
2075
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1663
2076
|
function LinksCard({ card }) {
|
|
1664
|
-
return /* @__PURE__ */
|
|
1665
|
-
card.title ? /* @__PURE__ */
|
|
1666
|
-
/* @__PURE__ */
|
|
1667
|
-
/* @__PURE__ */
|
|
1668
|
-
/* @__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, {}) })
|
|
1669
2082
|
] }, `${link.url}-${i}`)) })
|
|
1670
2083
|
] });
|
|
1671
2084
|
}
|
|
1672
2085
|
|
|
1673
2086
|
// src/components/dashboard/PostMatchResultCard.tsx
|
|
1674
|
-
import { useState as
|
|
1675
|
-
import { jsx as
|
|
2087
|
+
import { useState as useState10 } from "react";
|
|
2088
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1676
2089
|
function initials3(name) {
|
|
1677
2090
|
return name.trim().slice(0, 3).toUpperCase();
|
|
1678
2091
|
}
|
|
@@ -1681,37 +2094,37 @@ function PostMatchCrest({
|
|
|
1681
2094
|
name,
|
|
1682
2095
|
side
|
|
1683
2096
|
}) {
|
|
1684
|
-
const [failed, setFailed] =
|
|
2097
|
+
const [failed, setFailed] = useState10(false);
|
|
1685
2098
|
const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
|
|
1686
2099
|
if (url && !failed) {
|
|
1687
|
-
return /* @__PURE__ */
|
|
2100
|
+
return /* @__PURE__ */ jsx26("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1688
2101
|
}
|
|
1689
|
-
return /* @__PURE__ */
|
|
2102
|
+
return /* @__PURE__ */ jsx26("span", { className: `${cls} ss-w-fandash-postmatch-crest--fallback`, "aria-hidden": "true", children: initials3(name) });
|
|
1690
2103
|
}
|
|
1691
2104
|
function PostMatchResultCard({ card }) {
|
|
1692
2105
|
const { data } = card;
|
|
1693
2106
|
const homeWon = data.homeScore >= data.awayScore;
|
|
1694
2107
|
const awayWon = data.awayScore >= data.homeScore;
|
|
1695
|
-
return /* @__PURE__ */
|
|
1696
|
-
/* @__PURE__ */
|
|
1697
|
-
card.title ? /* @__PURE__ */
|
|
1698
|
-
/* @__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 })
|
|
1699
2112
|
] }),
|
|
1700
|
-
/* @__PURE__ */
|
|
1701
|
-
/* @__PURE__ */
|
|
1702
|
-
/* @__PURE__ */
|
|
1703
|
-
/* @__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 })
|
|
1704
2117
|
] }),
|
|
1705
|
-
/* @__PURE__ */
|
|
1706
|
-
/* @__PURE__ */
|
|
2118
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-score-main", children: [
|
|
2119
|
+
/* @__PURE__ */ jsx26(
|
|
1707
2120
|
"span",
|
|
1708
2121
|
{
|
|
1709
2122
|
className: `ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${homeWon ? "win" : "lose"}`,
|
|
1710
2123
|
children: data.homeScore
|
|
1711
2124
|
}
|
|
1712
2125
|
),
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
2126
|
+
/* @__PURE__ */ jsx26("span", { className: "ss-w-fandash-postmatch-score-sep", children: "\u2013" }),
|
|
2127
|
+
/* @__PURE__ */ jsx26(
|
|
1715
2128
|
"span",
|
|
1716
2129
|
{
|
|
1717
2130
|
className: `ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${awayWon ? "win" : "lose"}`,
|
|
@@ -1719,12 +2132,12 @@ function PostMatchResultCard({ card }) {
|
|
|
1719
2132
|
}
|
|
1720
2133
|
)
|
|
1721
2134
|
] }),
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
/* @__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 })
|
|
1725
2138
|
] })
|
|
1726
2139
|
] }),
|
|
1727
|
-
/* @__PURE__ */
|
|
2140
|
+
/* @__PURE__ */ jsxs22("div", { className: "ss-w-fandash-postmatch-meta", children: [
|
|
1728
2141
|
data.kickoffLabel,
|
|
1729
2142
|
data.competition ? ` \xB7 ${data.competition}` : ""
|
|
1730
2143
|
] })
|
|
@@ -1732,20 +2145,20 @@ function PostMatchResultCard({ card }) {
|
|
|
1732
2145
|
}
|
|
1733
2146
|
|
|
1734
2147
|
// src/components/dashboard/PostMatchGoalsCard.tsx
|
|
1735
|
-
import { jsx as
|
|
2148
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1736
2149
|
function PostMatchGoalsCard({ card, onTap }) {
|
|
1737
|
-
return /* @__PURE__ */
|
|
1738
|
-
card.title ? /* @__PURE__ */
|
|
1739
|
-
/* @__PURE__ */
|
|
1740
|
-
/* @__PURE__ */
|
|
1741
|
-
/* @__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 })
|
|
1742
2155
|
] }, `${g.text}-${i}`)) }),
|
|
1743
|
-
/* @__PURE__ */
|
|
2156
|
+
/* @__PURE__ */ jsx27("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1744
2157
|
] });
|
|
1745
2158
|
}
|
|
1746
2159
|
|
|
1747
2160
|
// src/components/dashboard/PostMatchStatsCard.tsx
|
|
1748
|
-
import { jsx as
|
|
2161
|
+
import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1749
2162
|
function splitWidths(homeNum, awayNum) {
|
|
1750
2163
|
const total = homeNum + awayNum;
|
|
1751
2164
|
if (total <= 0) return { home: "50%", away: "50%" };
|
|
@@ -1754,42 +2167,42 @@ function splitWidths(homeNum, awayNum) {
|
|
|
1754
2167
|
}
|
|
1755
2168
|
function PostMatchStatsCard({ card, onTap }) {
|
|
1756
2169
|
const { data } = card;
|
|
1757
|
-
return /* @__PURE__ */
|
|
1758
|
-
card.title ? /* @__PURE__ */
|
|
1759
|
-
/* @__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) => {
|
|
1760
2173
|
const leftValue = data.clubIsHome ? r.clubValue : r.oppValue;
|
|
1761
2174
|
const rightValue = data.clubIsHome ? r.oppValue : r.clubValue;
|
|
1762
2175
|
const homeNum = data.clubIsHome ? r.clubNum : r.oppNum;
|
|
1763
2176
|
const awayNum = data.clubIsHome ? r.oppNum : r.clubNum;
|
|
1764
2177
|
const { home, away } = splitWidths(homeNum, awayNum);
|
|
1765
|
-
return /* @__PURE__ */
|
|
1766
|
-
/* @__PURE__ */
|
|
1767
|
-
/* @__PURE__ */
|
|
1768
|
-
/* @__PURE__ */
|
|
1769
|
-
/* @__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 })
|
|
1770
2183
|
] }),
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
1773
|
-
/* @__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 } })
|
|
1774
2187
|
] })
|
|
1775
2188
|
] }, `${r.label}-${i}`);
|
|
1776
2189
|
}) }),
|
|
1777
|
-
data.rows.length > 0 ? /* @__PURE__ */
|
|
1778
|
-
/* @__PURE__ */
|
|
1779
|
-
/* @__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" }),
|
|
1780
2193
|
data.homeName
|
|
1781
2194
|
] }),
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
/* @__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" }),
|
|
1784
2197
|
data.awayName
|
|
1785
2198
|
] })
|
|
1786
2199
|
] }) : null,
|
|
1787
|
-
/* @__PURE__ */
|
|
2200
|
+
/* @__PURE__ */ jsx28("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1788
2201
|
] });
|
|
1789
2202
|
}
|
|
1790
2203
|
|
|
1791
2204
|
// src/components/dashboard/PostMatchTopPerformerCard.tsx
|
|
1792
|
-
import { jsx as
|
|
2205
|
+
import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1793
2206
|
function initials4(playerName) {
|
|
1794
2207
|
const words = playerName.trim().split(/\s+/).filter(Boolean);
|
|
1795
2208
|
if (words.length === 0) return "?";
|
|
@@ -1799,73 +2212,73 @@ function initials4(playerName) {
|
|
|
1799
2212
|
}
|
|
1800
2213
|
function PostMatchTopPerformerCard({ card, onTap }) {
|
|
1801
2214
|
const { data } = card;
|
|
1802
|
-
return /* @__PURE__ */
|
|
1803
|
-
card.title ? /* @__PURE__ */
|
|
1804
|
-
/* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
1806
|
-
/* @__PURE__ */
|
|
1807
|
-
/* @__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 })
|
|
1808
2221
|
] }),
|
|
1809
|
-
/* @__PURE__ */
|
|
2222
|
+
/* @__PURE__ */ jsx29("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1810
2223
|
] });
|
|
1811
2224
|
}
|
|
1812
2225
|
|
|
1813
2226
|
// src/components/dashboard/PostMatchNextCard.tsx
|
|
1814
|
-
import { jsx as
|
|
2227
|
+
import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1815
2228
|
function PostMatchNextCard({ card }) {
|
|
1816
2229
|
const { data } = card;
|
|
1817
|
-
return /* @__PURE__ */
|
|
1818
|
-
card.title ? /* @__PURE__ */
|
|
1819
|
-
/* @__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 }) })
|
|
1820
2233
|
] });
|
|
1821
2234
|
}
|
|
1822
2235
|
|
|
1823
2236
|
// src/components/dashboard/RestingNextCard.tsx
|
|
1824
|
-
import { jsx as
|
|
2237
|
+
import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1825
2238
|
function RestingNextCard({ card, onTap }) {
|
|
1826
2239
|
const { data } = card;
|
|
1827
|
-
return /* @__PURE__ */
|
|
1828
|
-
card.title ? /* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
1831
|
-
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
|
|
1832
2245
|
] }),
|
|
1833
|
-
/* @__PURE__ */
|
|
2246
|
+
/* @__PURE__ */ jsx31("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1834
2247
|
] });
|
|
1835
2248
|
}
|
|
1836
2249
|
|
|
1837
2250
|
// src/components/dashboard/RestingStandingsCard.tsx
|
|
1838
|
-
import { jsx as
|
|
2251
|
+
import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1839
2252
|
function RestingStandingsCard({ card, onTap }) {
|
|
1840
2253
|
const { data } = card;
|
|
1841
|
-
return /* @__PURE__ */
|
|
1842
|
-
card.title ? /* @__PURE__ */
|
|
1843
|
-
/* @__PURE__ */
|
|
1844
|
-
/* @__PURE__ */
|
|
1845
|
-
/* @__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 })
|
|
1846
2259
|
] }),
|
|
1847
|
-
/* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ jsx32("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1848
2261
|
] });
|
|
1849
2262
|
}
|
|
1850
2263
|
|
|
1851
2264
|
// src/components/dashboard/RestingSeasonCard.tsx
|
|
1852
|
-
import { jsx as
|
|
2265
|
+
import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1853
2266
|
function RestingSeasonCard({ card, onTap }) {
|
|
1854
2267
|
const { data } = card;
|
|
1855
|
-
return /* @__PURE__ */
|
|
1856
|
-
card.title ? /* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
1858
|
-
data.scorerLabel ? /* @__PURE__ */
|
|
1859
|
-
data.playerLabel ? /* @__PURE__ */
|
|
1860
|
-
/* @__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 })
|
|
1861
2274
|
] }),
|
|
1862
|
-
/* @__PURE__ */
|
|
2275
|
+
/* @__PURE__ */ jsx33("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1863
2276
|
] });
|
|
1864
2277
|
}
|
|
1865
2278
|
|
|
1866
2279
|
// src/components/dashboard/RestingFormCard.tsx
|
|
1867
|
-
import { jsx as
|
|
1868
|
-
function
|
|
2280
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2281
|
+
function resultClass(result) {
|
|
1869
2282
|
const upper = result.toUpperCase();
|
|
1870
2283
|
if (upper === "W") return "ss-w-fandash-form-pill--win";
|
|
1871
2284
|
if (upper === "L") return "ss-w-fandash-form-pill--loss";
|
|
@@ -1873,17 +2286,17 @@ function resultClass2(result) {
|
|
|
1873
2286
|
}
|
|
1874
2287
|
function RestingFormCard({ card }) {
|
|
1875
2288
|
const { data } = card;
|
|
1876
|
-
return /* @__PURE__ */
|
|
1877
|
-
card.title ? /* @__PURE__ */
|
|
1878
|
-
/* @__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}`)) })
|
|
1879
2292
|
] });
|
|
1880
2293
|
}
|
|
1881
2294
|
|
|
1882
2295
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
1883
|
-
import { useRef as
|
|
2296
|
+
import { useRef as useRef4, useState as useState12 } from "react";
|
|
1884
2297
|
|
|
1885
2298
|
// src/useLiveClock.ts
|
|
1886
|
-
import { useEffect as
|
|
2299
|
+
import { useEffect as useEffect6, useState as useState11 } from "react";
|
|
1887
2300
|
var TICK_MS = 6e4;
|
|
1888
2301
|
var MAX_LIVE_TICK_MINUTES = 15;
|
|
1889
2302
|
function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
@@ -1892,10 +2305,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
|
1892
2305
|
return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
|
|
1893
2306
|
}
|
|
1894
2307
|
function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
1895
|
-
const [displayMinute, setDisplayMinute] =
|
|
2308
|
+
const [displayMinute, setDisplayMinute] = useState11(
|
|
1896
2309
|
() => computeDisplayMinute(minute, clockRunning, receivedAtMs)
|
|
1897
2310
|
);
|
|
1898
|
-
|
|
2311
|
+
useEffect6(() => {
|
|
1899
2312
|
setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
|
|
1900
2313
|
if (!clockRunning) return;
|
|
1901
2314
|
const id = window.setInterval(() => {
|
|
@@ -1907,17 +2320,17 @@ function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
|
1907
2320
|
}
|
|
1908
2321
|
|
|
1909
2322
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
1910
|
-
import { jsx as
|
|
2323
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1911
2324
|
function initials5(name) {
|
|
1912
2325
|
return name.trim().slice(0, 3).toUpperCase();
|
|
1913
2326
|
}
|
|
1914
2327
|
function LiveCrest({ url, name, side }) {
|
|
1915
|
-
const [failed, setFailed] =
|
|
2328
|
+
const [failed, setFailed] = useState12(false);
|
|
1916
2329
|
const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
|
|
1917
2330
|
if (url && !failed) {
|
|
1918
|
-
return /* @__PURE__ */
|
|
2331
|
+
return /* @__PURE__ */ jsx35("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1919
2332
|
}
|
|
1920
|
-
return /* @__PURE__ */
|
|
2333
|
+
return /* @__PURE__ */ jsx35("span", { className: `${cls} ss-w-fandash-live-crest--fallback`, "aria-hidden": "true", children: initials5(name) });
|
|
1921
2334
|
}
|
|
1922
2335
|
function scorersLine(goalEvents) {
|
|
1923
2336
|
if (!goalEvents || goalEvents.length === 0) return null;
|
|
@@ -1931,72 +2344,72 @@ function LiveScoreCard({
|
|
|
1931
2344
|
}) {
|
|
1932
2345
|
const { data } = card;
|
|
1933
2346
|
const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
|
|
1934
|
-
const seedRef =
|
|
2347
|
+
const seedRef = useRef4(null);
|
|
1935
2348
|
if (!seedRef.current || seedRef.current.key !== seedKey) {
|
|
1936
2349
|
seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
|
|
1937
2350
|
}
|
|
1938
2351
|
const displayMinute = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs);
|
|
1939
2352
|
const minuteSuffix = data.minuteLabel.replace(/^\d+/, "");
|
|
1940
2353
|
const scorers = scorersLine(goalEvents);
|
|
1941
|
-
return /* @__PURE__ */
|
|
1942
|
-
card.title ? /* @__PURE__ */
|
|
1943
|
-
/* @__PURE__ */
|
|
1944
|
-
/* @__PURE__ */
|
|
1945
|
-
/* @__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" }),
|
|
1946
2359
|
data.statusLabel
|
|
1947
2360
|
] }),
|
|
1948
|
-
/* @__PURE__ */
|
|
1949
|
-
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
|
|
1950
2363
|
] }),
|
|
1951
|
-
/* @__PURE__ */
|
|
1952
|
-
/* @__PURE__ */
|
|
1953
|
-
/* @__PURE__ */
|
|
1954
|
-
/* @__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 })
|
|
1955
2368
|
] }),
|
|
1956
|
-
/* @__PURE__ */
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
/* @__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 })
|
|
1960
2373
|
] }),
|
|
1961
|
-
/* @__PURE__ */
|
|
1962
|
-
/* @__PURE__ */
|
|
1963
|
-
/* @__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 })
|
|
1964
2377
|
] })
|
|
1965
2378
|
] }),
|
|
1966
|
-
scorers ? /* @__PURE__ */
|
|
1967
|
-
/* @__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" }),
|
|
1968
2381
|
scorers
|
|
1969
2382
|
] }) : null
|
|
1970
2383
|
] });
|
|
1971
2384
|
}
|
|
1972
2385
|
|
|
1973
2386
|
// src/components/dashboard/LiveTimelineCard.tsx
|
|
1974
|
-
import { useState as
|
|
1975
|
-
import { jsx as
|
|
2387
|
+
import { useState as useState13 } from "react";
|
|
2388
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
1976
2389
|
var SHOWN2 = 3;
|
|
1977
2390
|
function EventIcon({ type }) {
|
|
1978
2391
|
if (type === "goal") {
|
|
1979
|
-
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" }) });
|
|
1980
2393
|
}
|
|
1981
2394
|
if (type === "yellow" || type === "red") {
|
|
1982
|
-
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}` }) });
|
|
1983
2396
|
}
|
|
1984
2397
|
if (type === "sub") {
|
|
1985
|
-
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" }) });
|
|
1986
2399
|
}
|
|
1987
|
-
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" }) });
|
|
1988
2401
|
}
|
|
1989
2402
|
function EventLabel({ e }) {
|
|
1990
2403
|
if (e.type === "sub") {
|
|
1991
|
-
return /* @__PURE__ */
|
|
2404
|
+
return /* @__PURE__ */ jsxs32("span", { className: "ss-w-fandash-live-tl-who", children: [
|
|
1992
2405
|
e.player ?? e.text,
|
|
1993
|
-
e.playerOff ? /* @__PURE__ */
|
|
2406
|
+
e.playerOff ? /* @__PURE__ */ jsxs32("span", { className: "ss-w-fandash-live-tl-off", children: [
|
|
1994
2407
|
" for ",
|
|
1995
2408
|
e.playerOff
|
|
1996
2409
|
] }) : null
|
|
1997
2410
|
] });
|
|
1998
2411
|
}
|
|
1999
|
-
return /* @__PURE__ */
|
|
2412
|
+
return /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-who", children: e.player ?? e.text });
|
|
2000
2413
|
}
|
|
2001
2414
|
function EventRow({ e }) {
|
|
2002
2415
|
const cls = [
|
|
@@ -2004,16 +2417,16 @@ function EventRow({ e }) {
|
|
|
2004
2417
|
e.side === "home" ? "ss-w-fandash-live-tl-ev--home" : "ss-w-fandash-live-tl-ev--away",
|
|
2005
2418
|
e.type === "goal" ? "ss-w-fandash-live-tl-ev--goal" : ""
|
|
2006
2419
|
].filter(Boolean).join(" ");
|
|
2007
|
-
return /* @__PURE__ */
|
|
2008
|
-
/* @__PURE__ */
|
|
2009
|
-
/* @__PURE__ */
|
|
2010
|
-
/* @__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 })
|
|
2011
2424
|
] }),
|
|
2012
|
-
/* @__PURE__ */
|
|
2425
|
+
/* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-tl-badge", children: e.minuteLabel })
|
|
2013
2426
|
] });
|
|
2014
2427
|
}
|
|
2015
2428
|
function LiveTimelineCard({ card, ui }) {
|
|
2016
|
-
const [expanded, setExpanded] =
|
|
2429
|
+
const [expanded, setExpanded] = useState13(false);
|
|
2017
2430
|
const events = card.data.events;
|
|
2018
2431
|
if (!events || events.length === 0) return null;
|
|
2019
2432
|
const sorted = [...events].sort((a, b) => b.minute - a.minute);
|
|
@@ -2021,10 +2434,10 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
2021
2434
|
const shown = expanded ? sorted : sorted.slice(0, SHOWN2);
|
|
2022
2435
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
2023
2436
|
const showLess = ui?.showLess ?? "Show less";
|
|
2024
|
-
return /* @__PURE__ */
|
|
2025
|
-
card.title ? /* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2027
|
-
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(
|
|
2028
2441
|
"button",
|
|
2029
2442
|
{
|
|
2030
2443
|
type: "button",
|
|
@@ -2039,7 +2452,7 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
2039
2452
|
|
|
2040
2453
|
// src/components/dashboard/MomentumWave.tsx
|
|
2041
2454
|
import { useId } from "react";
|
|
2042
|
-
import { jsx as
|
|
2455
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2043
2456
|
var WIDTH = 270;
|
|
2044
2457
|
var HEIGHT = 56;
|
|
2045
2458
|
var BASELINE = HEIGHT / 2;
|
|
@@ -2066,9 +2479,9 @@ function MomentumWave({
|
|
|
2066
2479
|
const bottomClipId = `${clipId}-bottom`;
|
|
2067
2480
|
const topClass = clubIsHome ? "ss-w-fandash-live-mom-home" : "ss-w-fandash-live-mom-away";
|
|
2068
2481
|
const bottomClass = clubIsHome ? "ss-w-fandash-live-mom-away" : "ss-w-fandash-live-mom-home";
|
|
2069
|
-
return /* @__PURE__ */
|
|
2070
|
-
caption ? /* @__PURE__ */
|
|
2071
|
-
/* @__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(
|
|
2072
2485
|
"svg",
|
|
2073
2486
|
{
|
|
2074
2487
|
className: "ss-w-fandash-live-mom-svg",
|
|
@@ -2077,15 +2490,15 @@ function MomentumWave({
|
|
|
2077
2490
|
role: "img",
|
|
2078
2491
|
"aria-label": caption ?? "Momentum",
|
|
2079
2492
|
children: [
|
|
2080
|
-
/* @__PURE__ */
|
|
2081
|
-
/* @__PURE__ */
|
|
2082
|
-
/* @__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 }) })
|
|
2083
2496
|
] }),
|
|
2084
|
-
/* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2088
|
-
/* @__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" })
|
|
2089
2502
|
]
|
|
2090
2503
|
}
|
|
2091
2504
|
)
|
|
@@ -2093,7 +2506,7 @@ function MomentumWave({
|
|
|
2093
2506
|
}
|
|
2094
2507
|
|
|
2095
2508
|
// src/components/dashboard/LiveStatsCard.tsx
|
|
2096
|
-
import { jsx as
|
|
2509
|
+
import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2097
2510
|
function splitWidths2(homeNum, awayNum) {
|
|
2098
2511
|
const total = homeNum + awayNum;
|
|
2099
2512
|
if (total <= 0) return { home: "50%", away: "50%" };
|
|
@@ -2102,34 +2515,34 @@ function splitWidths2(homeNum, awayNum) {
|
|
|
2102
2515
|
}
|
|
2103
2516
|
function LiveStatsCard({ card }) {
|
|
2104
2517
|
const { data } = card;
|
|
2105
|
-
return /* @__PURE__ */
|
|
2106
|
-
card.title ? /* @__PURE__ */
|
|
2107
|
-
/* @__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) => {
|
|
2108
2521
|
const homeValue = data.clubIsHome ? r.clubValue : r.oppValue;
|
|
2109
2522
|
const awayValue = data.clubIsHome ? r.oppValue : r.clubValue;
|
|
2110
2523
|
const homeNum = data.clubIsHome ? r.clubNum : r.oppNum;
|
|
2111
2524
|
const awayNum = data.clubIsHome ? r.oppNum : r.clubNum;
|
|
2112
2525
|
const { home, away } = splitWidths2(homeNum, awayNum);
|
|
2113
|
-
return /* @__PURE__ */
|
|
2114
|
-
/* @__PURE__ */
|
|
2115
|
-
/* @__PURE__ */
|
|
2116
|
-
/* @__PURE__ */
|
|
2117
|
-
/* @__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 })
|
|
2118
2531
|
] }),
|
|
2119
|
-
/* @__PURE__ */
|
|
2120
|
-
/* @__PURE__ */
|
|
2121
|
-
/* @__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 } })
|
|
2122
2535
|
] })
|
|
2123
2536
|
] }, `${r.label}-${i}`);
|
|
2124
2537
|
}) }),
|
|
2125
|
-
data.momentum.length > 0 ? /* @__PURE__ */
|
|
2126
|
-
data.rows.length > 0 ? /* @__PURE__ */
|
|
2127
|
-
/* @__PURE__ */
|
|
2128
|
-
/* @__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" }),
|
|
2129
2542
|
data.homeName
|
|
2130
2543
|
] }),
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__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" }),
|
|
2133
2546
|
data.awayName
|
|
2134
2547
|
] })
|
|
2135
2548
|
] }) : null
|
|
@@ -2137,7 +2550,7 @@ function LiveStatsCard({ card }) {
|
|
|
2137
2550
|
}
|
|
2138
2551
|
|
|
2139
2552
|
// src/components/dashboard/ClubFanDashboard.tsx
|
|
2140
|
-
import { jsx as
|
|
2553
|
+
import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2141
2554
|
function ClubFanDashboard({ dashboard, onTap, ui }) {
|
|
2142
2555
|
const orderedCards = [
|
|
2143
2556
|
...dashboard.cards.filter((c) => c.cardType === "countdown"),
|
|
@@ -2147,84 +2560,84 @@ function ClubFanDashboard({ dashboard, onTap, ui }) {
|
|
|
2147
2560
|
(c) => c.cardType === "liveTimeline"
|
|
2148
2561
|
);
|
|
2149
2562
|
const goalEvents = timelineCard?.data.events.filter((e) => e.type === "goal");
|
|
2150
|
-
return /* @__PURE__ */
|
|
2151
|
-
dashboard.greeting ? /* @__PURE__ */
|
|
2152
|
-
/* @__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}`)) })
|
|
2153
2566
|
] });
|
|
2154
2567
|
}
|
|
2155
2568
|
function FanDashboardCard({ card, onTap, ui, goalEvents }) {
|
|
2156
2569
|
switch (card.cardType) {
|
|
2157
2570
|
case "fixture":
|
|
2158
|
-
return /* @__PURE__ */
|
|
2571
|
+
return /* @__PURE__ */ jsx39(FixtureCard, { card });
|
|
2159
2572
|
case "countdown":
|
|
2160
|
-
return /* @__PURE__ */
|
|
2573
|
+
return /* @__PURE__ */ jsx39(CountdownCard, { card });
|
|
2161
2574
|
case "injuries":
|
|
2162
|
-
return /* @__PURE__ */
|
|
2575
|
+
return /* @__PURE__ */ jsx39(InjuriesCard, { card, ui });
|
|
2163
2576
|
case "reasonToBet":
|
|
2164
|
-
return /* @__PURE__ */
|
|
2577
|
+
return /* @__PURE__ */ jsx39(ReasonToBetCard, { card });
|
|
2165
2578
|
case "whereToWatch":
|
|
2166
|
-
return /* @__PURE__ */
|
|
2579
|
+
return /* @__PURE__ */ jsx39(WhereToWatchCard, { card });
|
|
2167
2580
|
case "congestedWeek":
|
|
2168
|
-
return /* @__PURE__ */
|
|
2581
|
+
return /* @__PURE__ */ jsx39(CongestedWeekCard, { card, onTap });
|
|
2169
2582
|
case "transfers":
|
|
2170
|
-
return /* @__PURE__ */
|
|
2583
|
+
return /* @__PURE__ */ jsx39(TransfersCard, { card });
|
|
2171
2584
|
case "links":
|
|
2172
|
-
return /* @__PURE__ */
|
|
2585
|
+
return /* @__PURE__ */ jsx39(LinksCard, { card });
|
|
2173
2586
|
case "postMatchResult":
|
|
2174
|
-
return /* @__PURE__ */
|
|
2587
|
+
return /* @__PURE__ */ jsx39(PostMatchResultCard, { card });
|
|
2175
2588
|
case "postMatchGoals":
|
|
2176
|
-
return /* @__PURE__ */
|
|
2589
|
+
return /* @__PURE__ */ jsx39(PostMatchGoalsCard, { card, onTap });
|
|
2177
2590
|
case "postMatchStats":
|
|
2178
|
-
return /* @__PURE__ */
|
|
2591
|
+
return /* @__PURE__ */ jsx39(PostMatchStatsCard, { card, onTap });
|
|
2179
2592
|
case "postMatchTopPerformer":
|
|
2180
|
-
return /* @__PURE__ */
|
|
2593
|
+
return /* @__PURE__ */ jsx39(PostMatchTopPerformerCard, { card, onTap });
|
|
2181
2594
|
case "postMatchNext":
|
|
2182
|
-
return /* @__PURE__ */
|
|
2595
|
+
return /* @__PURE__ */ jsx39(PostMatchNextCard, { card });
|
|
2183
2596
|
case "restingNext":
|
|
2184
|
-
return /* @__PURE__ */
|
|
2597
|
+
return /* @__PURE__ */ jsx39(RestingNextCard, { card, onTap });
|
|
2185
2598
|
case "restingStandings":
|
|
2186
|
-
return /* @__PURE__ */
|
|
2599
|
+
return /* @__PURE__ */ jsx39(RestingStandingsCard, { card, onTap });
|
|
2187
2600
|
case "restingSeason":
|
|
2188
|
-
return /* @__PURE__ */
|
|
2601
|
+
return /* @__PURE__ */ jsx39(RestingSeasonCard, { card, onTap });
|
|
2189
2602
|
case "restingForm":
|
|
2190
|
-
return /* @__PURE__ */
|
|
2603
|
+
return /* @__PURE__ */ jsx39(RestingFormCard, { card });
|
|
2191
2604
|
case "liveScore":
|
|
2192
|
-
return /* @__PURE__ */
|
|
2605
|
+
return /* @__PURE__ */ jsx39(LiveScoreCard, { card, goalEvents });
|
|
2193
2606
|
case "liveTimeline":
|
|
2194
|
-
return /* @__PURE__ */
|
|
2607
|
+
return /* @__PURE__ */ jsx39(LiveTimelineCard, { card, ui });
|
|
2195
2608
|
case "liveStats":
|
|
2196
|
-
return /* @__PURE__ */
|
|
2609
|
+
return /* @__PURE__ */ jsx39(LiveStatsCard, { card });
|
|
2197
2610
|
default:
|
|
2198
2611
|
return null;
|
|
2199
2612
|
}
|
|
2200
2613
|
}
|
|
2201
2614
|
|
|
2202
2615
|
// src/components/ChatMessage.tsx
|
|
2203
|
-
import { jsx as
|
|
2204
|
-
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 }) {
|
|
2205
2618
|
if (message.role === "user") {
|
|
2206
|
-
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 }) });
|
|
2207
2620
|
}
|
|
2208
2621
|
const onFanDashboardTap = (card) => {
|
|
2209
2622
|
onAct({ message: card.actionLabel, actionRef: card.actionRef, label: card.actionLabel || card.title || "" });
|
|
2210
2623
|
};
|
|
2211
|
-
return /* @__PURE__ */
|
|
2212
|
-
message.text && !message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */
|
|
2213
|
-
message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */
|
|
2214
|
-
message.clubFanDashboard ? /* @__PURE__ */
|
|
2215
|
-
/* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
2217
|
-
/* @__PURE__ */
|
|
2218
|
-
/* @__PURE__ */
|
|
2219
|
-
/* @__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 })
|
|
2220
2633
|
] });
|
|
2221
2634
|
}
|
|
2222
2635
|
|
|
2223
2636
|
// src/components/IntentChips.tsx
|
|
2224
|
-
import { jsx as
|
|
2637
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2225
2638
|
function IntentChips({ chips, onPick }) {
|
|
2226
2639
|
if (chips.length === 0) return null;
|
|
2227
|
-
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}`)) });
|
|
2228
2641
|
}
|
|
2229
2642
|
|
|
2230
2643
|
// src/scroll.ts
|
|
@@ -2234,20 +2647,20 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
2234
2647
|
}
|
|
2235
2648
|
|
|
2236
2649
|
// src/components/MessageList.tsx
|
|
2237
|
-
import { jsx as
|
|
2650
|
+
import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2238
2651
|
function turnAnchor(messages) {
|
|
2239
2652
|
const last = messages[messages.length - 1];
|
|
2240
2653
|
if (!last || last.role !== "assistant") return null;
|
|
2241
2654
|
const prev = messages[messages.length - 2];
|
|
2242
2655
|
return { turnId: last.id, anchorId: prev && prev.role === "user" ? prev.id : last.id };
|
|
2243
2656
|
}
|
|
2244
|
-
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
2657
|
+
function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
2245
2658
|
const { state, send } = controller;
|
|
2246
|
-
const listRef =
|
|
2247
|
-
const endRef =
|
|
2248
|
-
const pinnedRef =
|
|
2249
|
-
const anchoredTurnRef =
|
|
2250
|
-
|
|
2659
|
+
const listRef = useRef5(null);
|
|
2660
|
+
const endRef = useRef5(null);
|
|
2661
|
+
const pinnedRef = useRef5(true);
|
|
2662
|
+
const anchoredTurnRef = useRef5(null);
|
|
2663
|
+
useEffect7(() => {
|
|
2251
2664
|
const anchor = turnAnchor(state.messages);
|
|
2252
2665
|
const list = listRef.current;
|
|
2253
2666
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
@@ -2262,7 +2675,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2262
2675
|
}, [state.messages, state.status, state.isStreaming]);
|
|
2263
2676
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
2264
2677
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && (m.greetingDashboard || m.clubFanDashboard));
|
|
2265
|
-
return /* @__PURE__ */
|
|
2678
|
+
return /* @__PURE__ */ jsxs37(
|
|
2266
2679
|
"div",
|
|
2267
2680
|
{
|
|
2268
2681
|
className: "ss-w-list",
|
|
@@ -2272,7 +2685,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2272
2685
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
2273
2686
|
},
|
|
2274
2687
|
children: [
|
|
2275
|
-
state.messages.map((m) => /* @__PURE__ */
|
|
2688
|
+
state.messages.map((m) => /* @__PURE__ */ jsx42(
|
|
2276
2689
|
ChatMessage,
|
|
2277
2690
|
{
|
|
2278
2691
|
message: m,
|
|
@@ -2283,29 +2696,30 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2283
2696
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
2284
2697
|
},
|
|
2285
2698
|
ui,
|
|
2286
|
-
slip
|
|
2699
|
+
slip,
|
|
2700
|
+
monitor
|
|
2287
2701
|
},
|
|
2288
2702
|
m.id
|
|
2289
2703
|
)),
|
|
2290
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */
|
|
2704
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx42(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
2291
2705
|
} }) : null,
|
|
2292
|
-
state.status ? /* @__PURE__ */
|
|
2293
|
-
state.error ? /* @__PURE__ */
|
|
2294
|
-
/* @__PURE__ */
|
|
2295
|
-
/* @__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 })
|
|
2296
2710
|
] }) : null,
|
|
2297
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */
|
|
2298
|
-
/* @__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" })
|
|
2299
2713
|
]
|
|
2300
2714
|
}
|
|
2301
2715
|
);
|
|
2302
2716
|
}
|
|
2303
2717
|
|
|
2304
2718
|
// src/components/ChatInput.tsx
|
|
2305
|
-
import { useState as
|
|
2306
|
-
import { jsx as
|
|
2719
|
+
import { useState as useState14 } from "react";
|
|
2720
|
+
import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2307
2721
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
2308
|
-
const [value, setValue] =
|
|
2722
|
+
const [value, setValue] = useState14("");
|
|
2309
2723
|
const submit = () => {
|
|
2310
2724
|
const t = value.trim();
|
|
2311
2725
|
if (!t) return;
|
|
@@ -2318,18 +2732,228 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
2318
2732
|
submit();
|
|
2319
2733
|
}
|
|
2320
2734
|
};
|
|
2321
|
-
return /* @__PURE__ */
|
|
2322
|
-
/* @__PURE__ */
|
|
2323
|
-
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 })
|
|
2877
|
+
] });
|
|
2878
|
+
}
|
|
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
|
+
] })
|
|
2324
2906
|
] });
|
|
2325
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
|
+
}
|
|
2326
2950
|
|
|
2327
2951
|
// src/components/ChatPanel.tsx
|
|
2328
|
-
import { jsx as
|
|
2952
|
+
import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
2329
2953
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
2330
2954
|
function useIsModal() {
|
|
2331
|
-
const [modal, setModal] =
|
|
2332
|
-
|
|
2955
|
+
const [modal, setModal] = useState15(false);
|
|
2956
|
+
useEffect8(() => {
|
|
2333
2957
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
2334
2958
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
2335
2959
|
const sync = () => setModal(mql.matches);
|
|
@@ -2339,20 +2963,44 @@ function useIsModal() {
|
|
|
2339
2963
|
}, []);
|
|
2340
2964
|
return modal;
|
|
2341
2965
|
}
|
|
2342
|
-
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
2966
|
+
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
2343
2967
|
const { state, close, stop, send } = controller;
|
|
2344
2968
|
const isModal = useIsModal();
|
|
2345
|
-
|
|
2969
|
+
useEffect8(() => {
|
|
2346
2970
|
const onKey = (e) => {
|
|
2347
2971
|
if (e.key === "Escape") close();
|
|
2348
2972
|
};
|
|
2349
2973
|
window.addEventListener("keydown", onKey);
|
|
2350
2974
|
return () => window.removeEventListener("keydown", onKey);
|
|
2351
2975
|
}, [close]);
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
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 })
|
|
2356
3004
|
] });
|
|
2357
3005
|
}
|
|
2358
3006
|
|
|
@@ -2420,7 +3068,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2420
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; }
|
|
2421
3069
|
|
|
2422
3070
|
/* messages */
|
|
2423
|
-
.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; }
|
|
2424
3075
|
/* Transient bottom spacer: reserves a viewport of room below a new turn so its
|
|
2425
3076
|
top can be scrolled into view while the reply is still streaming in. Height is
|
|
2426
3077
|
set imperatively and flex must not shrink it away. */
|
|
@@ -2536,8 +3187,6 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2536
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; }
|
|
2537
3188
|
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
2538
3189
|
.ss-w-bi-action-row .ss-w-slip { flex: none; }
|
|
2539
|
-
/* let the slip toast size to its own text and anchor to the card's right edge, not the button width */
|
|
2540
|
-
.ss-w-bi-action-row .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
|
|
2541
3190
|
|
|
2542
3191
|
/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
|
|
2543
3192
|
.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }
|
|
@@ -2644,10 +3293,21 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2644
3293
|
.ss-w-slip { position: relative; display: flex; }
|
|
2645
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; }
|
|
2646
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); }
|
|
2647
|
-
|
|
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); }
|
|
2648
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)); }
|
|
2649
3301
|
.ss-w-toast-error { color: #c0392b; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }
|
|
2650
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
|
+
|
|
2651
3311
|
@media (prefers-reduced-motion: reduce) {
|
|
2652
3312
|
.ss-w-abtn-shimmer { animation: none; }
|
|
2653
3313
|
}
|
|
@@ -2764,13 +3424,25 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2764
3424
|
/* extra breathing room between the tally row and the fact beyond the card's own gap */
|
|
2765
3425
|
.ss-w-fandash-h2h .ss-w-fandash-fact { margin-top: 4px; }
|
|
2766
3426
|
|
|
2767
|
-
/*
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
.ss-w-fandash-
|
|
2771
|
-
.ss-w-fandash-
|
|
2772
|
-
.ss-w-fandash-
|
|
2773
|
-
.ss-w-fandash-
|
|
3427
|
+
/* Team form: a two-column result-card grid, left = home team's last 5, right = away team's last 5,
|
|
3428
|
+
most-recent first. The head row carries each column's crest + name; the rows grid is filled
|
|
3429
|
+
home-cell/away-cell per index so the 2-col grid lays out pairs without extra JS bookkeeping. */
|
|
3430
|
+
.ss-w-fandash-teamform-head { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }
|
|
3431
|
+
.ss-w-fandash-teamform-head-team { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11.5px; font-weight: 750; }
|
|
3432
|
+
.ss-w-fandash-teamform-head-team .ss-w-bi-crest { width: 18px; height: 18px; }
|
|
3433
|
+
.ss-w-fandash-teamform-head-team .ss-w-bi-crest-mono { font-size: 8px; }
|
|
3434
|
+
.ss-w-fandash-teamform-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3435
|
+
.ss-w-fandash-teamform-rows { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 6px; }
|
|
3436
|
+
.ss-w-fandash-teamform-slot { display: block; min-width: 0; }
|
|
3437
|
+
.ss-w-fandash-teamform-cell {
|
|
3438
|
+
display: flex; align-items: center; gap: 4px; border-radius: 7px; padding: 4px 5px; color: #fff;
|
|
3439
|
+
}
|
|
3440
|
+
.ss-w-fandash-teamform-cell--win { background: var(--ss-w-pos); }
|
|
3441
|
+
.ss-w-fandash-teamform-cell--loss { background: var(--ss-w-neg); }
|
|
3442
|
+
.ss-w-fandash-teamform-cell--draw { background: var(--ss-w-faint); }
|
|
3443
|
+
.ss-w-fandash-teamform-cell .ss-w-bi-crest { width: 16px; height: 16px; flex: none; background: rgba(255, 255, 255, .22); }
|
|
3444
|
+
.ss-w-fandash-teamform-cell .ss-w-bi-crest-mono { font-size: 7px; color: #fff; }
|
|
3445
|
+
.ss-w-fandash-teamform-score { flex: 1; text-align: center; font-size: 12.5px; font-weight: 750; font-variant-numeric: tabular-nums; }
|
|
2774
3446
|
.ss-w-fandash-injuries-more { margin-top: 10px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }
|
|
2775
3447
|
.ss-w-fandash-injuries-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }
|
|
2776
3448
|
.ss-w-fandash-form { display: inline-flex; gap: 3px; flex: none; }
|
|
@@ -3004,10 +3676,68 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
3004
3676
|
.ss-w-fandash-live-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
|
|
3005
3677
|
.ss-w-fandash-live-legend-swatch--home { background: var(--ss-w-home); }
|
|
3006
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); }
|
|
3007
3737
|
`;
|
|
3008
3738
|
|
|
3009
3739
|
// src/StatsWidget.tsx
|
|
3010
|
-
import { jsx as
|
|
3740
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
3011
3741
|
function buildClient(props) {
|
|
3012
3742
|
try {
|
|
3013
3743
|
if ("client" in props && props.client) {
|
|
@@ -3034,33 +3764,48 @@ function StatsWidget(props) {
|
|
|
3034
3764
|
const cfg = props.config;
|
|
3035
3765
|
const built = useMemo2(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
3036
3766
|
const ui = useMemo2(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
3037
|
-
const rootRef =
|
|
3767
|
+
const rootRef = useRef6(null);
|
|
3038
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
|
+
});
|
|
3039
3774
|
const slip = useMemo2(
|
|
3040
|
-
() =>
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
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
|
+
}
|
|
3047
3792
|
}
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
3793
|
+
};
|
|
3794
|
+
},
|
|
3795
|
+
[props.config?.onAddToSlip, controller.state.conversationId, built, monitor.markInSlip]
|
|
3051
3796
|
);
|
|
3052
3797
|
const onDashboardTap = useMemo2(
|
|
3053
3798
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
3054
3799
|
[built]
|
|
3055
3800
|
);
|
|
3056
|
-
|
|
3801
|
+
useEffect9(() => {
|
|
3057
3802
|
if (!built || !ui.injectStyles) return;
|
|
3058
3803
|
const node = rootRef.current?.getRootNode();
|
|
3059
3804
|
if (node) injectStyles(node);
|
|
3060
3805
|
}, [built, ui.injectStyles]);
|
|
3061
3806
|
if (!built) return null;
|
|
3062
3807
|
const attrs = themeAttrs(ui);
|
|
3063
|
-
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(
|
|
3064
3809
|
ChatFab,
|
|
3065
3810
|
{
|
|
3066
3811
|
label: ui.launcherLabel,
|