@sensiblestats/widget-react 0.85.0 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/index.cjs +743 -273
- 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 +682 -212
- package/dist/index.js.map +1 -1
- package/dist/styles.css +93 -13
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -37,7 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
|
|
39
39
|
// src/StatsWidget.tsx
|
|
40
|
-
var
|
|
40
|
+
var import_react69 = require("react");
|
|
41
41
|
var import_widget_sdk6 = require("@sensiblestats/widget-sdk");
|
|
42
42
|
|
|
43
43
|
// src/kickoff.ts
|
|
@@ -53,8 +53,13 @@ function formatBettingKickoff(kickoffUtc, ui, locale, now = /* @__PURE__ */ new
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// src/i18n.ts
|
|
56
|
+
var GROUP_NOUN_EN = { G: "goalkeepers", D: "defenders", M: "midfielders", F: "forwards" };
|
|
57
|
+
var GROUP_NOUN_TR = { G: "kalecileri", D: "defans oyuncular\u0131", M: "orta saha oyuncular\u0131", F: "forvetleri" };
|
|
56
58
|
var formatPtsEn = (n) => new Intl.NumberFormat("en-GB").format(n);
|
|
57
59
|
var formatPtsTr = (n) => new Intl.NumberFormat("tr-TR").format(n);
|
|
60
|
+
var nbsp = (s) => s.replace(/\s/g, "\xA0");
|
|
61
|
+
var pdDateEn = (ms, opts) => nbsp(new Intl.DateTimeFormat("en-GB", opts).format(new Date(ms)).replace("Sept", "Sep"));
|
|
62
|
+
var pdDateTr = (ms, opts) => nbsp(new Intl.DateTimeFormat("tr-TR", opts).format(new Date(ms)));
|
|
58
63
|
var STRINGS = {
|
|
59
64
|
en: {
|
|
60
65
|
launcherLabel: "Chat with SensibleStats",
|
|
@@ -190,6 +195,60 @@ var STRINGS = {
|
|
|
190
195
|
recordsMostAssists: "Most assists",
|
|
191
196
|
recordsSince: "Since {season}",
|
|
192
197
|
standingsColClub: "Club",
|
|
198
|
+
statHeadPos: "Pos",
|
|
199
|
+
statHeadMins: "Mins",
|
|
200
|
+
statHeadGoals: "G",
|
|
201
|
+
statHeadAssists: "A",
|
|
202
|
+
statHeadYellow: "Y",
|
|
203
|
+
statHeadRed: "R",
|
|
204
|
+
statHeadRating: "Rtg",
|
|
205
|
+
squadStatsEyebrow: (season, competition, n) => `${season} ${competition} \xB7 after ${n} game${n === 1 ? "" : "s"}`,
|
|
206
|
+
squadTopScorer: (name, n) => `Top scorer: ${name} (${n})`,
|
|
207
|
+
squadTopAssists: (name, n) => `Most assists: ${name} (${n})`,
|
|
208
|
+
detailStarted: "Started",
|
|
209
|
+
detailMatches: "Matches",
|
|
210
|
+
detailNatShort: "Nat.",
|
|
211
|
+
detailYellows: "Yellows",
|
|
212
|
+
detailReds: "Reds",
|
|
213
|
+
availabilityNext: (opponent, isHome, kickoffMs) => `Next: ${isHome ? "vs" : "at"} ${opponent} (${isHome ? "H" : "A"})` + (kickoffMs !== null && kickoffMs > 0 ? ` \xB7 ${pdDateEn(kickoffMs, { weekday: "short", day: "numeric", month: "short" })}` : ""),
|
|
214
|
+
availabilityAvailable: "Available",
|
|
215
|
+
availabilityInjured: "Injured",
|
|
216
|
+
availabilitySuspended: "Suspended",
|
|
217
|
+
availabilityUnavailable: "Unavailable",
|
|
218
|
+
availabilityNoConcerns: "No fitness concerns reported",
|
|
219
|
+
availabilityBack: (ms) => `Expected back ${pdDateEn(ms, { day: "numeric", month: "short" })}`,
|
|
220
|
+
perfTitle: "Season performance",
|
|
221
|
+
perfTotal: "Total",
|
|
222
|
+
perfPer90: "Per 90",
|
|
223
|
+
perfRankedAgainst: (competition, group) => `Ranked against ${competition} ${GROUP_NOUN_EN[group] ?? group}`,
|
|
224
|
+
perfUnranked: "Not enough minutes to rank",
|
|
225
|
+
perfUnrankedCohort: "Not enough players in this position to rank",
|
|
226
|
+
perfUnrankedNoLeague: "Not ranked \u2014 no league data",
|
|
227
|
+
perfGroupShooting: "Shooting",
|
|
228
|
+
perfGroupPassing: "Passing",
|
|
229
|
+
perfGroupPossession: "Possession",
|
|
230
|
+
perfGroupDefending: "Defending",
|
|
231
|
+
perfMetric: {
|
|
232
|
+
goals: "Goals",
|
|
233
|
+
xg: "Expected goals (xG)",
|
|
234
|
+
shots: "Shots",
|
|
235
|
+
shotsOnTarget: "Shots on target",
|
|
236
|
+
assists: "Assists",
|
|
237
|
+
successfulPasses: "Successful passes",
|
|
238
|
+
passAccuracy: "Pass accuracy",
|
|
239
|
+
chancesCreated: "Chances created",
|
|
240
|
+
successfulDribbles: "Successful dribbles",
|
|
241
|
+
dribbleSuccess: "Dribble success",
|
|
242
|
+
touches: "Touches",
|
|
243
|
+
tacklesWon: "Tackles won",
|
|
244
|
+
interceptions: "Interceptions",
|
|
245
|
+
duelsWon: "Duels won"
|
|
246
|
+
},
|
|
247
|
+
perfGroupNoun: GROUP_NOUN_EN,
|
|
248
|
+
matchLogTitle: "Match log",
|
|
249
|
+
matchLogOpponent: (name, isHome) => isHome ? `vs ${name}` : `at ${name}`,
|
|
250
|
+
resultLetter: { W: "W", D: "D", L: "L" },
|
|
251
|
+
logShortDate: (ms) => pdDateEn(ms, { day: "numeric", month: "short" }),
|
|
193
252
|
standingsColPlayed: "P",
|
|
194
253
|
standingsColWon: "W",
|
|
195
254
|
standingsColDrawn: "D",
|
|
@@ -603,6 +662,60 @@ var STRINGS = {
|
|
|
603
662
|
recordsMostAssists: "En \xE7ok asist yapanlar",
|
|
604
663
|
recordsSince: "{season} sezonundan beri",
|
|
605
664
|
standingsColClub: "Tak\u0131m",
|
|
665
|
+
statHeadPos: "Mvk",
|
|
666
|
+
statHeadMins: "Dk",
|
|
667
|
+
statHeadGoals: "G",
|
|
668
|
+
statHeadAssists: "A",
|
|
669
|
+
statHeadYellow: "S",
|
|
670
|
+
statHeadRed: "K",
|
|
671
|
+
statHeadRating: "Puan",
|
|
672
|
+
squadStatsEyebrow: (season, competition, n) => `${season} ${competition} \xB7 ${n} ma\xE7 sonra`,
|
|
673
|
+
squadTopScorer: (name, n) => `Gol kral\u0131: ${name} (${n})`,
|
|
674
|
+
squadTopAssists: (name, n) => `Asist lideri: ${name} (${n})`,
|
|
675
|
+
detailStarted: "\u0130lk 11",
|
|
676
|
+
detailMatches: "Ma\xE7",
|
|
677
|
+
detailNatShort: "Uyruk",
|
|
678
|
+
detailYellows: "Sar\u0131",
|
|
679
|
+
detailReds: "K\u0131rm\u0131z\u0131",
|
|
680
|
+
availabilityNext: (opponent, isHome, kickoffMs) => `Sonraki: ${opponent} (${isHome ? "\u0130\xE7\xA0saha" : "Deplasman"})` + (kickoffMs !== null && kickoffMs > 0 ? ` \xB7 ${pdDateTr(kickoffMs, { day: "numeric", month: "short", weekday: "short" })}` : ""),
|
|
681
|
+
availabilityAvailable: "Haz\u0131r",
|
|
682
|
+
availabilityInjured: "Sakat",
|
|
683
|
+
availabilitySuspended: "Cezal\u0131",
|
|
684
|
+
availabilityUnavailable: "Haz\u0131r de\u011Fil",
|
|
685
|
+
availabilityNoConcerns: "Sakatl\u0131k bildirimi yok",
|
|
686
|
+
availabilityBack: (ms) => `D\xF6n\xFC\u015F: ${pdDateTr(ms, { day: "numeric", month: "short" })}`,
|
|
687
|
+
perfTitle: "Sezon performans\u0131",
|
|
688
|
+
perfTotal: "Toplam",
|
|
689
|
+
perfPer90: "90 dk",
|
|
690
|
+
perfRankedAgainst: (competition, group) => `${competition} ${GROUP_NOUN_TR[group] ?? group} aras\u0131nda`,
|
|
691
|
+
perfUnranked: "S\u0131ralama i\xE7in yeterli s\xFCre yok",
|
|
692
|
+
perfUnrankedCohort: "Bu mevkide s\u0131ralama i\xE7in yeterli oyuncu yok",
|
|
693
|
+
perfUnrankedNoLeague: "S\u0131ralanmad\u0131 \u2014 lig verisi yok",
|
|
694
|
+
perfGroupShooting: "\u015Eut",
|
|
695
|
+
perfGroupPassing: "Pas",
|
|
696
|
+
perfGroupPossession: "Top hakimiyeti",
|
|
697
|
+
perfGroupDefending: "Savunma",
|
|
698
|
+
perfMetric: {
|
|
699
|
+
goals: "Gol",
|
|
700
|
+
xg: "Gol beklentisi (xG)",
|
|
701
|
+
shots: "\u015Eut",
|
|
702
|
+
shotsOnTarget: "\u0130sabetli \u015Fut",
|
|
703
|
+
assists: "Asist",
|
|
704
|
+
successfulPasses: "Ba\u015Far\u0131l\u0131 pas",
|
|
705
|
+
passAccuracy: "Pas isabeti",
|
|
706
|
+
chancesCreated: "Yarat\u0131lan f\u0131rsat",
|
|
707
|
+
successfulDribbles: "Ba\u015Far\u0131l\u0131 \xE7al\u0131m",
|
|
708
|
+
dribbleSuccess: "\xC7al\u0131m ba\u015Far\u0131s\u0131",
|
|
709
|
+
touches: "Topla bulu\u015Fma",
|
|
710
|
+
tacklesWon: "Kazan\u0131lan m\xFCdahale",
|
|
711
|
+
interceptions: "Top kapma",
|
|
712
|
+
duelsWon: "Kazan\u0131lan ikili m\xFCcadele"
|
|
713
|
+
},
|
|
714
|
+
perfGroupNoun: GROUP_NOUN_TR,
|
|
715
|
+
matchLogTitle: "Ma\xE7 ge\xE7mi\u015Fi",
|
|
716
|
+
matchLogOpponent: (name, isHome) => isHome ? `${name} (\u0130)` : `${name} (D)`,
|
|
717
|
+
resultLetter: { W: "G", D: "B", L: "M" },
|
|
718
|
+
logShortDate: (ms) => pdDateTr(ms, { day: "numeric", month: "short" }),
|
|
606
719
|
standingsColPlayed: "O",
|
|
607
720
|
standingsColWon: "G",
|
|
608
721
|
standingsColDrawn: "B",
|
|
@@ -1013,6 +1126,45 @@ function normalizeUi(cfg) {
|
|
|
1013
1126
|
recordsMostAssists: strings.recordsMostAssists,
|
|
1014
1127
|
recordsSince: strings.recordsSince,
|
|
1015
1128
|
standingsColClub: strings.standingsColClub,
|
|
1129
|
+
statHeadPos: strings.statHeadPos,
|
|
1130
|
+
statHeadMins: strings.statHeadMins,
|
|
1131
|
+
statHeadGoals: strings.statHeadGoals,
|
|
1132
|
+
statHeadAssists: strings.statHeadAssists,
|
|
1133
|
+
statHeadYellow: strings.statHeadYellow,
|
|
1134
|
+
statHeadRed: strings.statHeadRed,
|
|
1135
|
+
statHeadRating: strings.statHeadRating,
|
|
1136
|
+
squadStatsEyebrow: strings.squadStatsEyebrow,
|
|
1137
|
+
squadTopScorer: strings.squadTopScorer,
|
|
1138
|
+
squadTopAssists: strings.squadTopAssists,
|
|
1139
|
+
detailStarted: strings.detailStarted,
|
|
1140
|
+
detailMatches: strings.detailMatches,
|
|
1141
|
+
detailNatShort: strings.detailNatShort,
|
|
1142
|
+
detailYellows: strings.detailYellows,
|
|
1143
|
+
detailReds: strings.detailReds,
|
|
1144
|
+
availabilityNext: strings.availabilityNext,
|
|
1145
|
+
availabilityAvailable: strings.availabilityAvailable,
|
|
1146
|
+
availabilityInjured: strings.availabilityInjured,
|
|
1147
|
+
availabilitySuspended: strings.availabilitySuspended,
|
|
1148
|
+
availabilityUnavailable: strings.availabilityUnavailable,
|
|
1149
|
+
availabilityNoConcerns: strings.availabilityNoConcerns,
|
|
1150
|
+
availabilityBack: strings.availabilityBack,
|
|
1151
|
+
perfTitle: strings.perfTitle,
|
|
1152
|
+
perfTotal: strings.perfTotal,
|
|
1153
|
+
perfPer90: strings.perfPer90,
|
|
1154
|
+
perfRankedAgainst: strings.perfRankedAgainst,
|
|
1155
|
+
perfUnranked: strings.perfUnranked,
|
|
1156
|
+
perfUnrankedCohort: strings.perfUnrankedCohort,
|
|
1157
|
+
perfUnrankedNoLeague: strings.perfUnrankedNoLeague,
|
|
1158
|
+
perfGroupShooting: strings.perfGroupShooting,
|
|
1159
|
+
perfGroupPassing: strings.perfGroupPassing,
|
|
1160
|
+
perfGroupPossession: strings.perfGroupPossession,
|
|
1161
|
+
perfGroupDefending: strings.perfGroupDefending,
|
|
1162
|
+
perfMetric: strings.perfMetric,
|
|
1163
|
+
perfGroupNoun: strings.perfGroupNoun,
|
|
1164
|
+
matchLogTitle: strings.matchLogTitle,
|
|
1165
|
+
matchLogOpponent: strings.matchLogOpponent,
|
|
1166
|
+
resultLetter: strings.resultLetter,
|
|
1167
|
+
logShortDate: strings.logShortDate,
|
|
1016
1168
|
standingsColPlayed: strings.standingsColPlayed,
|
|
1017
1169
|
standingsColWon: strings.standingsColWon,
|
|
1018
1170
|
standingsColDrawn: strings.standingsColDrawn,
|
|
@@ -3382,6 +3534,8 @@ var import_react12 = require("react");
|
|
|
3382
3534
|
function useClubSquadStats(conversation, { activeTab, enabled }) {
|
|
3383
3535
|
const [data, setData] = (0, import_react12.useState)(null);
|
|
3384
3536
|
const [seasonName, setSeasonName] = (0, import_react12.useState)(null);
|
|
3537
|
+
const [competitionName, setCompetitionName] = (0, import_react12.useState)(null);
|
|
3538
|
+
const [matchesPlayed, setMatchesPlayed] = (0, import_react12.useState)(null);
|
|
3385
3539
|
const [loading, setLoading] = (0, import_react12.useState)(false);
|
|
3386
3540
|
const [refreshCount, setRefreshCount] = (0, import_react12.useState)(0);
|
|
3387
3541
|
const inFlightRef = (0, import_react12.useRef)(false);
|
|
@@ -3400,6 +3554,8 @@ function useClubSquadStats(conversation, { activeTab, enabled }) {
|
|
|
3400
3554
|
if (active) {
|
|
3401
3555
|
setData(result?.players ?? null);
|
|
3402
3556
|
setSeasonName(result?.seasonName ?? null);
|
|
3557
|
+
setCompetitionName(result?.competitionName ?? null);
|
|
3558
|
+
setMatchesPlayed(result?.clubMatchesPlayed ?? null);
|
|
3403
3559
|
}
|
|
3404
3560
|
} catch {
|
|
3405
3561
|
} finally {
|
|
@@ -3417,7 +3573,7 @@ function useClubSquadStats(conversation, { activeTab, enabled }) {
|
|
|
3417
3573
|
setRefreshCount((c) => c + 1);
|
|
3418
3574
|
}, []);
|
|
3419
3575
|
const effectiveLoading = loading || activeTab === "squad" && enabled && data === null;
|
|
3420
|
-
return { data, seasonName, loading: effectiveLoading, refresh };
|
|
3576
|
+
return { data, seasonName, competitionName, matchesPlayed, loading: effectiveLoading, refresh };
|
|
3421
3577
|
}
|
|
3422
3578
|
|
|
3423
3579
|
// src/useClubPlayerDetail.ts
|
|
@@ -3817,7 +3973,7 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
|
|
|
3817
3973
|
}
|
|
3818
3974
|
|
|
3819
3975
|
// src/components/ChatPanel.tsx
|
|
3820
|
-
var
|
|
3976
|
+
var import_react68 = require("react");
|
|
3821
3977
|
|
|
3822
3978
|
// src/components/ChatHeader.tsx
|
|
3823
3979
|
var import_react20 = require("react");
|
|
@@ -10005,51 +10161,92 @@ function footLabel(ui, foot) {
|
|
|
10005
10161
|
return v;
|
|
10006
10162
|
}
|
|
10007
10163
|
}
|
|
10164
|
+
var GROUP_CODE = { Goalkeeper: "GK", Defender: "DF", Midfielder: "MF", Attacker: "FW" };
|
|
10165
|
+
function positionShort(code, positionName) {
|
|
10166
|
+
const c = code?.trim().toUpperCase() ?? "";
|
|
10167
|
+
if (c !== "") return c === "CF" || c === "SS" ? "ST" : c;
|
|
10168
|
+
return positionName !== null && GROUP_CODE[positionName] || "\u2013";
|
|
10169
|
+
}
|
|
10170
|
+
function statsEyebrow(ui, season, competition, matches) {
|
|
10171
|
+
if (season === null || competition === null || matches === null || matches <= 0) return null;
|
|
10172
|
+
return ui.squadStatsEyebrow(season, competition, matches);
|
|
10173
|
+
}
|
|
10008
10174
|
|
|
10009
10175
|
// src/components/SquadStats.tsx
|
|
10010
10176
|
var import_jsx_runtime97 = require("react/jsx-runtime");
|
|
10177
|
+
function leader(stats, pick) {
|
|
10178
|
+
let best = null;
|
|
10179
|
+
for (const p of stats) {
|
|
10180
|
+
if (pick(p) <= 0) continue;
|
|
10181
|
+
if (best === null || pick(p) > pick(best) || pick(p) === pick(best) && p.minutesPlayed < best.minutesPlayed) best = p;
|
|
10182
|
+
}
|
|
10183
|
+
return best;
|
|
10184
|
+
}
|
|
10185
|
+
function ratingClass(rating) {
|
|
10186
|
+
if (rating === null) return "ss-w-sq-c36 ss-w-sq-rtg-none";
|
|
10187
|
+
return Number(rating.toFixed(1)) >= 7 ? "ss-w-sq-c36 ss-w-sq-rtg ss-w-pos-ink" : "ss-w-sq-c36 ss-w-sq-rtg";
|
|
10188
|
+
}
|
|
10011
10189
|
function SquadStats({ stats, loading, ui, onSelectPlayer }) {
|
|
10012
10190
|
if (stats === null && loading) return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "ss-w-mon-list" });
|
|
10013
10191
|
if (stats === null || stats.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "ss-w-mon-empty", children: ui.clubSquadStatsEmpty });
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-
|
|
10027
|
-
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-
|
|
10028
|
-
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-
|
|
10029
|
-
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-
|
|
10030
|
-
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-
|
|
10031
|
-
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-
|
|
10192
|
+
const scorer = leader(stats, (p) => p.goals);
|
|
10193
|
+
const assister = leader(stats, (p) => p.assists);
|
|
10194
|
+
const footer = [
|
|
10195
|
+
scorer && ui.squadTopScorer(scorer.playerName, scorer.goals),
|
|
10196
|
+
assister && ui.squadTopAssists(assister.playerName, assister.assists)
|
|
10197
|
+
].filter((part) => !!part).join(" \xB7 ");
|
|
10198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "ss-w-mon-list ss-w-sq-stats", children: [
|
|
10199
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "ss-w-sq-card", children: [
|
|
10200
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "ss-w-sq-row ss-w-sq-head", "aria-hidden": "true", children: [
|
|
10201
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-name" }),
|
|
10202
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-pos", children: ui.statHeadPos }),
|
|
10203
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c30", children: ui.statColApps }),
|
|
10204
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c36", children: ui.statHeadMins }),
|
|
10205
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20", children: ui.statHeadGoals }),
|
|
10206
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20", children: ui.statHeadAssists }),
|
|
10207
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20 ss-w-sq-yr", children: ui.statHeadYellow }),
|
|
10208
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20 ss-w-sq-yr", children: ui.statHeadRed }),
|
|
10209
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c36", children: ui.statHeadRating })
|
|
10210
|
+
] }),
|
|
10211
|
+
stats.map((p) => /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("button", { type: "button", className: "ss-w-sq-row ss-w-sq-tap", onClick: () => onSelectPlayer(p.playerId), children: [
|
|
10212
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "ss-w-sq-player", children: [
|
|
10213
|
+
p.jerseyNumber !== null && /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-badge", children: p.jerseyNumber }),
|
|
10214
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-name ss-w-sq-name-1", children: p.playerName })
|
|
10215
|
+
] }),
|
|
10216
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-pos", children: positionShort(p.positionCode, p.positionName) }),
|
|
10217
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c30", children: p.appearances }),
|
|
10218
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c36", children: p.minutesPlayed }),
|
|
10219
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20", children: p.goals }),
|
|
10220
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20", children: p.assists }),
|
|
10221
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20 ss-w-sq-yr", children: p.yellowCards }),
|
|
10222
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "ss-w-sq-c20 ss-w-sq-yr", children: p.redCards }),
|
|
10223
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: ratingClass(p.averageRating), children: p.averageRating === null ? "\u2013" : p.averageRating.toFixed(1) })
|
|
10032
10224
|
] }, p.playerId))
|
|
10033
|
-
] },
|
|
10225
|
+
] }),
|
|
10226
|
+
footer !== "" && /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "ss-w-sq-foot", children: footer })
|
|
10034
10227
|
] });
|
|
10035
10228
|
}
|
|
10036
10229
|
|
|
10037
10230
|
// src/components/Squad.tsx
|
|
10038
10231
|
var import_jsx_runtime98 = require("react/jsx-runtime");
|
|
10039
|
-
function Squad({ squad, loading, ui, view, onToggleView, stats, statsLoading, onSelectPlayer }) {
|
|
10040
|
-
const
|
|
10041
|
-
|
|
10042
|
-
{
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10232
|
+
function Squad({ squad, loading, ui, view, onToggleView, stats, statsLoading, seasonName = null, competitionName = null, matchesPlayed = null, onSelectPlayer }) {
|
|
10233
|
+
const eyebrow = view === "stats" ? statsEyebrow(ui, seasonName, competitionName, matchesPlayed) : null;
|
|
10234
|
+
const toggle = /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "ss-w-sq-bar", children: [
|
|
10235
|
+
eyebrow !== null && /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "ss-w-sq-eyebrow", children: eyebrow }),
|
|
10236
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "ss-w-sq-seg", role: "group", children: ["roster", "stats"].map((v) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
10237
|
+
"button",
|
|
10238
|
+
{
|
|
10239
|
+
type: "button",
|
|
10240
|
+
className: "ss-w-sq-seg-btn",
|
|
10241
|
+
"aria-pressed": view === v,
|
|
10242
|
+
onClick: () => {
|
|
10243
|
+
if (view !== v) onToggleView();
|
|
10244
|
+
},
|
|
10245
|
+
children: v === "roster" ? ui.squadViewRoster : ui.squadViewStats
|
|
10048
10246
|
},
|
|
10049
|
-
|
|
10050
|
-
}
|
|
10051
|
-
|
|
10052
|
-
)) });
|
|
10247
|
+
v
|
|
10248
|
+
)) })
|
|
10249
|
+
] });
|
|
10053
10250
|
if (view === "stats") {
|
|
10054
10251
|
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
10055
10252
|
toggle,
|
|
@@ -10076,8 +10273,125 @@ function Squad({ squad, loading, ui, view, onToggleView, stats, statsLoading, on
|
|
|
10076
10273
|
] });
|
|
10077
10274
|
}
|
|
10078
10275
|
|
|
10079
|
-
// src/components/
|
|
10276
|
+
// src/components/PlayerPhoto.tsx
|
|
10277
|
+
var import_react63 = require("react");
|
|
10080
10278
|
var import_jsx_runtime99 = require("react/jsx-runtime");
|
|
10279
|
+
function PlayerPhoto({ photoUrl, jerseyNumber, size }) {
|
|
10280
|
+
const [failed, setFailed] = (0, import_react63.useState)(false);
|
|
10281
|
+
const box = { width: size, height: size };
|
|
10282
|
+
if (photoUrl && !failed) {
|
|
10283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("img", { className: "ss-w-pd-photo", style: box, src: photoUrl, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
10284
|
+
}
|
|
10285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "ss-w-pd-photo ss-w-pd-avatar", style: { ...box, fontSize: Math.round(size * 0.35) }, "aria-hidden": "true", children: jerseyNumber ?? "" });
|
|
10286
|
+
}
|
|
10287
|
+
|
|
10288
|
+
// src/components/MiniPitch.tsx
|
|
10289
|
+
var import_jsx_runtime100 = require("react/jsx-runtime");
|
|
10290
|
+
var SPOT = {
|
|
10291
|
+
GK: [50, 90],
|
|
10292
|
+
CB: [50, 75],
|
|
10293
|
+
LB: [18, 70],
|
|
10294
|
+
RB: [82, 70],
|
|
10295
|
+
LWB: [15, 58],
|
|
10296
|
+
RWB: [85, 58],
|
|
10297
|
+
DM: [50, 60],
|
|
10298
|
+
CM: [50, 48],
|
|
10299
|
+
LM: [18, 45],
|
|
10300
|
+
RM: [82, 45],
|
|
10301
|
+
AM: [50, 32],
|
|
10302
|
+
LW: [20, 25],
|
|
10303
|
+
RW: [80, 25],
|
|
10304
|
+
CF: [50, 14],
|
|
10305
|
+
SS: [50, 14],
|
|
10306
|
+
ST: [50, 14]
|
|
10307
|
+
};
|
|
10308
|
+
function MiniPitch({ positionCode }) {
|
|
10309
|
+
const spot = SPOT[positionCode?.trim().toUpperCase() ?? ""];
|
|
10310
|
+
if (spot === void 0) return null;
|
|
10311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "ss-w-pd-pitch", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "ss-w-pd-pitch-dot", style: { left: `${spot[0]}%`, top: `${spot[1]}%` } }) });
|
|
10312
|
+
}
|
|
10313
|
+
|
|
10314
|
+
// src/components/PerformanceBars.tsx
|
|
10315
|
+
var import_react64 = require("react");
|
|
10316
|
+
var import_jsx_runtime101 = require("react/jsx-runtime");
|
|
10317
|
+
var GROUPS = ["shooting", "passing", "possession", "defending"];
|
|
10318
|
+
function finite3(v) {
|
|
10319
|
+
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
10320
|
+
}
|
|
10321
|
+
function valueOf(m, mode) {
|
|
10322
|
+
return finite3(mode === "total" ? m.total : m.per90);
|
|
10323
|
+
}
|
|
10324
|
+
function rankOf(m, mode) {
|
|
10325
|
+
const r = finite3(mode === "total" ? m.totalRank : m.per90Rank);
|
|
10326
|
+
return r === null ? null : Math.min(100, Math.max(0, Math.round(r)));
|
|
10327
|
+
}
|
|
10328
|
+
function format(m, v, mode) {
|
|
10329
|
+
if (m.isPercent) return `${v.toFixed(1)}%`;
|
|
10330
|
+
if (mode === "per90" || m.key === "xg") return v.toFixed(2);
|
|
10331
|
+
return String(Math.round(v));
|
|
10332
|
+
}
|
|
10333
|
+
function band(rank) {
|
|
10334
|
+
if (rank >= 67) return "pos";
|
|
10335
|
+
if (rank >= 34) return "warn";
|
|
10336
|
+
return "neg";
|
|
10337
|
+
}
|
|
10338
|
+
function groupTitle(ui, g) {
|
|
10339
|
+
switch (g) {
|
|
10340
|
+
case "shooting":
|
|
10341
|
+
return ui.perfGroupShooting;
|
|
10342
|
+
case "passing":
|
|
10343
|
+
return ui.perfGroupPassing;
|
|
10344
|
+
case "possession":
|
|
10345
|
+
return ui.perfGroupPossession;
|
|
10346
|
+
case "defending":
|
|
10347
|
+
return ui.perfGroupDefending;
|
|
10348
|
+
}
|
|
10349
|
+
}
|
|
10350
|
+
function unrankedLine(ui, reason) {
|
|
10351
|
+
switch (reason) {
|
|
10352
|
+
case "cohort":
|
|
10353
|
+
return ui.perfUnrankedCohort;
|
|
10354
|
+
case "noLeague":
|
|
10355
|
+
return ui.perfUnrankedNoLeague;
|
|
10356
|
+
default:
|
|
10357
|
+
return ui.perfUnranked;
|
|
10358
|
+
}
|
|
10359
|
+
}
|
|
10360
|
+
function PerformanceBars({ performance, competitionName, strings }) {
|
|
10361
|
+
const [mode, setMode] = (0, import_react64.useState)("total");
|
|
10362
|
+
const labelled = performance.metrics.filter((m) => Object.prototype.hasOwnProperty.call(strings.perfMetric, m.key));
|
|
10363
|
+
if (!labelled.some((m) => valueOf(m, "total") !== null || valueOf(m, "per90") !== null)) return null;
|
|
10364
|
+
const subtitle = !performance.ranked ? unrankedLine(strings, performance.unrankedReason) : competitionName ? strings.perfRankedAgainst(competitionName, performance.positionGroup) : null;
|
|
10365
|
+
const cards = GROUPS.map((g) => {
|
|
10366
|
+
const rows = labelled.filter((m) => m.group === g && valueOf(m, mode) !== null);
|
|
10367
|
+
if (rows.length === 0) return null;
|
|
10368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "ss-w-pd-card ss-w-pd-perf-card", children: [
|
|
10369
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "ss-w-pd-perf-group", children: groupTitle(strings, g) }),
|
|
10370
|
+
rows.map((m) => {
|
|
10371
|
+
const v = valueOf(m, mode);
|
|
10372
|
+
const rank = performance.ranked ? rankOf(m, mode) : null;
|
|
10373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "ss-w-pd-bar-row", children: [
|
|
10374
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "ss-w-pd-bar-top", children: [
|
|
10375
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "ss-w-pd-bar-label", children: strings.perfMetric[m.key] }),
|
|
10376
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "ss-w-pd-bar-value", children: format(m, v, mode) })
|
|
10377
|
+
] }),
|
|
10378
|
+
rank !== null && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "ss-w-pd-track", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: `ss-w-pd-fill ss-w-pd-fill--${band(rank)}`, style: { width: `${rank}%` } }) })
|
|
10379
|
+
] }, m.key);
|
|
10380
|
+
})
|
|
10381
|
+
] }, g);
|
|
10382
|
+
});
|
|
10383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { children: [
|
|
10384
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "ss-w-pd-perf-head", children: [
|
|
10385
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "ss-w-pd-eyebrow", children: strings.perfTitle }),
|
|
10386
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "ss-w-pd-seg", role: "group", children: ["total", "per90"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "ss-w-pd-seg-btn", "aria-pressed": mode === m, onClick: () => setMode(m), children: m === "total" ? strings.perfTotal : strings.perfPer90 }, m)) })
|
|
10387
|
+
] }),
|
|
10388
|
+
subtitle !== null && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "ss-w-pd-perf-sub", children: subtitle }),
|
|
10389
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "ss-w-pd-perf-cards", children: cards })
|
|
10390
|
+
] });
|
|
10391
|
+
}
|
|
10392
|
+
|
|
10393
|
+
// src/components/PlayerDetail.tsx
|
|
10394
|
+
var import_jsx_runtime102 = require("react/jsx-runtime");
|
|
10081
10395
|
var DASH = "\u2014";
|
|
10082
10396
|
function ageFrom(dobMs) {
|
|
10083
10397
|
if (dobMs === null) return DASH;
|
|
@@ -10088,68 +10402,141 @@ function ageFrom(dobMs) {
|
|
|
10088
10402
|
if (beforeBirthday) age--;
|
|
10089
10403
|
return String(age);
|
|
10090
10404
|
}
|
|
10091
|
-
function
|
|
10092
|
-
return
|
|
10093
|
-
|
|
10094
|
-
|
|
10405
|
+
function validMs(ms) {
|
|
10406
|
+
return typeof ms === "number" && Number.isFinite(ms) && ms > 0 ? ms : null;
|
|
10407
|
+
}
|
|
10408
|
+
function ratingTone(rounded) {
|
|
10409
|
+
if (rounded >= 7) return "pos";
|
|
10410
|
+
if (rounded >= 6) return "warn";
|
|
10411
|
+
return "neg";
|
|
10412
|
+
}
|
|
10413
|
+
function Bio({ label, value }) {
|
|
10414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-bio-item", children: [
|
|
10415
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "ss-w-pd-faint", children: label }),
|
|
10416
|
+
" ",
|
|
10417
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: value })
|
|
10418
|
+
] });
|
|
10419
|
+
}
|
|
10420
|
+
function Tile({ label, value, pos }) {
|
|
10421
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-tile", children: [
|
|
10422
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-tile-label", children: label }),
|
|
10423
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: pos ? "ss-w-pd-tile-value ss-w-pd-pos-ink" : "ss-w-pd-tile-value", children: value })
|
|
10424
|
+
] });
|
|
10425
|
+
}
|
|
10426
|
+
function AvailabilityCard({ ui, next, availability }) {
|
|
10427
|
+
let note = null;
|
|
10428
|
+
let pill = null;
|
|
10429
|
+
if (availability !== null) {
|
|
10430
|
+
if (availability.status === "available") {
|
|
10431
|
+
note = ui.availabilityNoConcerns;
|
|
10432
|
+
pill = { text: ui.availabilityAvailable, tone: "pos" };
|
|
10433
|
+
} else {
|
|
10434
|
+
const back = validMs(availability.expectedReturnUnixMs);
|
|
10435
|
+
note = [availability.detail?.trim() || null, back === null ? null : ui.availabilityBack(back)].filter(Boolean).join(" \xB7 ") || null;
|
|
10436
|
+
pill = availability.status === "injured" ? { text: ui.availabilityInjured, tone: "neg" } : availability.status === "suspended" ? { text: ui.availabilitySuspended, tone: "warn" } : { text: ui.availabilityUnavailable, tone: "warn" };
|
|
10437
|
+
}
|
|
10438
|
+
}
|
|
10439
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-card ss-w-pd-avail", children: [
|
|
10440
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-avail-text", children: [
|
|
10441
|
+
next !== null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-avail-next", children: ui.availabilityNext(next.opponentName, next.isHome, validMs(next.kickoffUnixMs)) }),
|
|
10442
|
+
note !== null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-avail-note", children: note })
|
|
10443
|
+
] }),
|
|
10444
|
+
pill !== null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: `ss-w-pd-pill ss-w-pd-pill--${pill.tone}`, children: pill.text })
|
|
10445
|
+
] });
|
|
10446
|
+
}
|
|
10447
|
+
function MatchRow({ ui, row }) {
|
|
10448
|
+
const date = validMs(row.kickoffUnixMs);
|
|
10449
|
+
const extras = [
|
|
10450
|
+
row.goals > 0 ? `${row.goals}${ui.statHeadGoals}` : null,
|
|
10451
|
+
row.assists > 0 ? `${row.assists}${ui.statHeadAssists}` : null,
|
|
10452
|
+
row.yellowCards > 0 ? `${row.yellowCards}${ui.statHeadYellow}` : null,
|
|
10453
|
+
row.sentOff ? ui.statHeadRed : null
|
|
10454
|
+
].filter((x) => x !== null);
|
|
10455
|
+
const sub = [`${ui.resultLetter[row.result]} ${row.goalsFor}\u2013${row.goalsAgainst}`, `${row.minutes}\u2032`, ...extras].join(" \xB7 ");
|
|
10456
|
+
const rating = typeof row.rating === "number" && Number.isFinite(row.rating) ? Math.round(row.rating * 10) / 10 : null;
|
|
10457
|
+
const pillTone = row.result === "W" ? "pos" : row.result === "L" ? "neg" : "draw";
|
|
10458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-match", children: [
|
|
10459
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-match-date", children: date === null ? "" : ui.logShortDate(date) }),
|
|
10460
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-match-main", children: [
|
|
10461
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-match-opp", children: ui.matchLogOpponent(row.opponentName, row.isHome) }),
|
|
10462
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-match-sub", children: sub })
|
|
10463
|
+
] }),
|
|
10464
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: `ss-w-pd-pill ss-w-pd-pill--${pillTone}`, children: ui.resultLetter[row.result] }),
|
|
10465
|
+
rating === null ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-chip-empty" }) : /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: `ss-w-pd-chip ss-w-pd-chip--${ratingTone(rating)}`, children: rating.toFixed(1) })
|
|
10095
10466
|
] });
|
|
10096
10467
|
}
|
|
10097
10468
|
function PlayerDetail({ detail, loading, ui, seasonName, onClose }) {
|
|
10098
|
-
const back = /* @__PURE__ */ (0,
|
|
10099
|
-
/* @__PURE__ */ (0,
|
|
10100
|
-
" ",
|
|
10469
|
+
const back = /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "ss-w-pd-back", onClick: onClose, children: [
|
|
10470
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("path", { d: "M15 18l-6-6 6-6" }) }),
|
|
10101
10471
|
ui.clubPlayerBack
|
|
10102
10472
|
] });
|
|
10103
10473
|
if (detail === null) {
|
|
10104
|
-
return loading ? /* @__PURE__ */ (0,
|
|
10105
|
-
/* @__PURE__ */ (0,
|
|
10106
|
-
/* @__PURE__ */ (0,
|
|
10107
|
-
] }) : /* @__PURE__ */ (0,
|
|
10108
|
-
/* @__PURE__ */ (0,
|
|
10109
|
-
/* @__PURE__ */ (0,
|
|
10474
|
+
return loading ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(import_jsx_runtime102.Fragment, { children: [
|
|
10475
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-bar", children: back }),
|
|
10476
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-mon-list" })
|
|
10477
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(import_jsx_runtime102.Fragment, { children: [
|
|
10478
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-bar", children: back }),
|
|
10479
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-mon-empty", children: ui.clubPlayerDetailEmpty })
|
|
10110
10480
|
] });
|
|
10111
10481
|
}
|
|
10112
10482
|
const s = detail.seasonStats;
|
|
10113
|
-
const
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10483
|
+
const foot = footLabel(ui, detail.foot);
|
|
10484
|
+
const position = positionLabel(ui, detail.positionName);
|
|
10485
|
+
const subLine = [detail.teamName?.trim() || null, position].filter(Boolean).join(" \xB7 ");
|
|
10486
|
+
const competition = detail.competitionName?.trim() || null;
|
|
10487
|
+
const eyebrow = seasonName === null ? null : competition === null ? ui.detailSeason.replace("{season}", seasonName) : `${seasonName} ${competition}`;
|
|
10488
|
+
const rating = typeof s.averageRating === "number" && Number.isFinite(s.averageRating) ? s.averageRating : null;
|
|
10489
|
+
const next = detail.nextFixture ?? null;
|
|
10490
|
+
const availability = detail.availability ?? null;
|
|
10491
|
+
const log = detail.matchLog ?? [];
|
|
10492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(import_jsx_runtime102.Fragment, { children: [
|
|
10493
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-bar", children: back }),
|
|
10494
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-mon-list ss-w-pd-list", children: [
|
|
10495
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-card ss-w-pd-profile", children: [
|
|
10496
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(PlayerPhoto, { photoUrl: detail.photoUrl, jerseyNumber: detail.jerseyNumber, size: 52 }, detail.photoUrl ?? ""),
|
|
10497
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-profile-main", children: [
|
|
10498
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-name", children: detail.playerName }),
|
|
10499
|
+
subLine !== "" && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-sub", children: subLine }),
|
|
10500
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-bio", children: [
|
|
10501
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Bio, { label: ui.detailAge, value: ageFrom(detail.dateOfBirthUnixMs) }),
|
|
10502
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Bio, { label: ui.detailHeight, value: detail.heightCm === null ? DASH : `${detail.heightCm} cm` }),
|
|
10503
|
+
foot !== null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Bio, { label: ui.detailFoot, value: foot }),
|
|
10504
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Bio, { label: ui.detailNatShort, value: detail.nationality ?? DASH })
|
|
10505
|
+
] })
|
|
10506
|
+
] }),
|
|
10507
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(MiniPitch, { positionCode: detail.positionCode })
|
|
10126
10508
|
] }),
|
|
10127
|
-
/* @__PURE__ */ (0,
|
|
10128
|
-
|
|
10129
|
-
/* @__PURE__ */ (0,
|
|
10130
|
-
|
|
10131
|
-
/* @__PURE__ */ (0,
|
|
10132
|
-
/* @__PURE__ */ (0,
|
|
10133
|
-
/* @__PURE__ */ (0,
|
|
10134
|
-
/* @__PURE__ */ (0,
|
|
10135
|
-
/* @__PURE__ */ (0,
|
|
10136
|
-
/* @__PURE__ */ (0,
|
|
10137
|
-
/* @__PURE__ */ (0,
|
|
10138
|
-
/* @__PURE__ */ (0,
|
|
10509
|
+
(next !== null || availability !== null) && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(AvailabilityCard, { ui, next, availability }),
|
|
10510
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { children: [
|
|
10511
|
+
eyebrow !== null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-eyebrow ss-w-pd-eyebrow--block", children: eyebrow }),
|
|
10512
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "ss-w-pd-tiles", children: [
|
|
10513
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.statColGoals, value: String(s.goals) }),
|
|
10514
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.statColAssists, value: String(s.assists) }),
|
|
10515
|
+
typeof s.starts === "number" && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.detailStarted, value: String(s.starts) }),
|
|
10516
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.detailMatches, value: String(s.appearances) }),
|
|
10517
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.statColMinutes, value: String(s.minutesPlayed) }),
|
|
10518
|
+
rating !== null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.statColRating, value: rating.toFixed(2), pos: Math.round(rating * 100) / 100 >= 7 }),
|
|
10519
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.detailYellows, value: String(s.yellowCards) }),
|
|
10520
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Tile, { label: ui.detailReds, value: String(s.redCards) })
|
|
10139
10521
|
] })
|
|
10522
|
+
] }),
|
|
10523
|
+
detail.performance != null && /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(PerformanceBars, { performance: detail.performance, competitionName: competition, strings: ui }),
|
|
10524
|
+
log.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { children: [
|
|
10525
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-eyebrow ss-w-pd-eyebrow--block", children: ui.matchLogTitle }),
|
|
10526
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "ss-w-pd-card ss-w-pd-log", children: log.map((row) => /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(MatchRow, { ui, row }, row.matchId)) })
|
|
10140
10527
|
] })
|
|
10141
10528
|
] })
|
|
10142
10529
|
] });
|
|
10143
10530
|
}
|
|
10144
10531
|
|
|
10145
10532
|
// src/components/PresetSpeedDial.tsx
|
|
10146
|
-
var
|
|
10147
|
-
var
|
|
10533
|
+
var import_react65 = require("react");
|
|
10534
|
+
var import_jsx_runtime103 = require("react/jsx-runtime");
|
|
10148
10535
|
function PresetSpeedDial({ expanded, showDot, strings, onToggle, onOpen, rootRef, buttonRef }) {
|
|
10149
|
-
const pillsId = (0,
|
|
10536
|
+
const pillsId = (0, import_react65.useId)();
|
|
10150
10537
|
const tabIndex = expanded ? 0 : -1;
|
|
10151
|
-
return /* @__PURE__ */ (0,
|
|
10152
|
-
/* @__PURE__ */ (0,
|
|
10538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { ref: rootRef, className: "ss-w-dial", children: [
|
|
10539
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(
|
|
10153
10540
|
"button",
|
|
10154
10541
|
{
|
|
10155
10542
|
ref: buttonRef,
|
|
@@ -10160,36 +10547,36 @@ function PresetSpeedDial({ expanded, showDot, strings, onToggle, onOpen, rootRef
|
|
|
10160
10547
|
"aria-label": strings.dialName,
|
|
10161
10548
|
onClick: onToggle,
|
|
10162
10549
|
children: [
|
|
10163
|
-
/* @__PURE__ */ (0,
|
|
10164
|
-
/* @__PURE__ */ (0,
|
|
10165
|
-
showDot && !expanded ? /* @__PURE__ */ (0,
|
|
10550
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "ss-w-dial-icon ss-w-dial-icon--open", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(SlidersIcon, {}) }),
|
|
10551
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "ss-w-dial-icon ss-w-dial-icon--close", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(CloseIcon, {}) }),
|
|
10552
|
+
showDot && !expanded ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "ss-w-dial-dot", "aria-hidden": "true" }) : null
|
|
10166
10553
|
]
|
|
10167
10554
|
}
|
|
10168
10555
|
),
|
|
10169
|
-
/* @__PURE__ */ (0,
|
|
10170
|
-
/* @__PURE__ */ (0,
|
|
10171
|
-
/* @__PURE__ */ (0,
|
|
10172
|
-
/* @__PURE__ */ (0,
|
|
10556
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { id: pillsId, className: "ss-w-dial-pills", "data-open": expanded ? "" : void 0, children: [
|
|
10557
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("button", { type: "button", className: "ss-w-dial-pill", tabIndex, onClick: () => onOpen("numbers"), children: [
|
|
10558
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)(SlidersIcon, {}),
|
|
10559
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "ss-w-dial-pill-label", children: strings.setNumbers })
|
|
10173
10560
|
] }),
|
|
10174
|
-
/* @__PURE__ */ (0,
|
|
10175
|
-
/* @__PURE__ */ (0,
|
|
10176
|
-
/* @__PURE__ */ (0,
|
|
10561
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("button", { type: "button", className: "ss-w-dial-pill", tabIndex, onClick: () => onOpen("combo"), children: [
|
|
10562
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)(ComboIcon, {}),
|
|
10563
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "ss-w-dial-pill-label", children: strings.buildCombo })
|
|
10177
10564
|
] })
|
|
10178
10565
|
] })
|
|
10179
10566
|
] });
|
|
10180
10567
|
}
|
|
10181
10568
|
|
|
10182
10569
|
// src/components/PresetTools.tsx
|
|
10183
|
-
var
|
|
10184
|
-
var
|
|
10570
|
+
var import_react66 = require("react");
|
|
10571
|
+
var import_jsx_runtime104 = require("react/jsx-runtime");
|
|
10185
10572
|
var FOCUSABLE = 'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
10186
10573
|
function PresetToolModal({ title, closeLabel, onClose, children, footer }) {
|
|
10187
|
-
const dialogRef = (0,
|
|
10188
|
-
const titleId = (0,
|
|
10189
|
-
(0,
|
|
10574
|
+
const dialogRef = (0, import_react66.useRef)(null);
|
|
10575
|
+
const titleId = (0, import_react66.useId)();
|
|
10576
|
+
(0, import_react66.useEffect)(() => {
|
|
10190
10577
|
dialogRef.current?.focus();
|
|
10191
10578
|
}, []);
|
|
10192
|
-
(0,
|
|
10579
|
+
(0, import_react66.useEffect)(() => {
|
|
10193
10580
|
const onKey = (e) => {
|
|
10194
10581
|
if (e.key !== "Escape") return;
|
|
10195
10582
|
e.stopPropagation();
|
|
@@ -10219,79 +10606,79 @@ function PresetToolModal({ title, closeLabel, onClose, children, footer }) {
|
|
|
10219
10606
|
first.focus();
|
|
10220
10607
|
}
|
|
10221
10608
|
};
|
|
10222
|
-
return /* @__PURE__ */ (0,
|
|
10223
|
-
/* @__PURE__ */ (0,
|
|
10224
|
-
/* @__PURE__ */ (0,
|
|
10225
|
-
/* @__PURE__ */ (0,
|
|
10609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "ss-w-tool-backdrop", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { ref: dialogRef, className: "ss-w-tool", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, tabIndex: -1, onKeyDown: trapTab, children: [
|
|
10610
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "ss-w-tool-head", children: [
|
|
10611
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("h2", { id: titleId, className: "ss-w-tool-title", children: title }),
|
|
10612
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("button", { type: "button", className: "ss-w-tool-close", "aria-label": closeLabel, onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(CloseIcon, {}) })
|
|
10226
10613
|
] }),
|
|
10227
|
-
/* @__PURE__ */ (0,
|
|
10228
|
-
footer ? /* @__PURE__ */ (0,
|
|
10614
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "ss-w-tool-body", children }),
|
|
10615
|
+
footer ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "ss-w-tool-foot", children: footer }) : null
|
|
10229
10616
|
] }) });
|
|
10230
10617
|
}
|
|
10231
10618
|
function fillTemplate(template, slots) {
|
|
10232
10619
|
return template.split(/(\{[a-z]+\})/).filter((part) => part !== "").map((part, i) => {
|
|
10233
10620
|
const key = /^\{([a-z]+)\}$/.exec(part)?.[1];
|
|
10234
|
-
return /* @__PURE__ */ (0,
|
|
10621
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(import_react66.Fragment, { children: key !== void 0 && key in slots ? slots[key] : part }, i);
|
|
10235
10622
|
});
|
|
10236
10623
|
}
|
|
10237
10624
|
function NumberSelect({ current, choices: choices2, label, notToday, lockEmpty = true, onChoose }) {
|
|
10238
10625
|
const selected = Math.max(0, choices2.findIndex((c) => c.text === current));
|
|
10239
|
-
return /* @__PURE__ */ (0,
|
|
10240
|
-
/* @__PURE__ */ (0,
|
|
10241
|
-
/* @__PURE__ */ (0,
|
|
10626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "ss-w-tool-num", children: [
|
|
10627
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-num-size", "aria-hidden": "true", children: current }),
|
|
10628
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("select", { className: "ss-w-tool-num-select", "aria-label": label, value: String(selected), onChange: (e) => {
|
|
10242
10629
|
const c = choices2[Number(e.target.value)];
|
|
10243
10630
|
if (c) onChoose(c.value);
|
|
10244
|
-
}, children: choices2.map((c, i) => /* @__PURE__ */ (0,
|
|
10631
|
+
}, children: choices2.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("option", { value: String(i), disabled: lockEmpty && !c.available && i !== selected, children: c.available ? c.text : `${c.text}${notToday}` }, i)) })
|
|
10245
10632
|
] });
|
|
10246
10633
|
}
|
|
10247
10634
|
function ChoiceSelect({ currentIdx, sizeLabels, optionLabels, label, onChoose }) {
|
|
10248
10635
|
const sizeText = sizeLabels[currentIdx] ?? "";
|
|
10249
|
-
return /* @__PURE__ */ (0,
|
|
10250
|
-
/* @__PURE__ */ (0,
|
|
10251
|
-
/* @__PURE__ */ (0,
|
|
10636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "ss-w-tool-num", children: [
|
|
10637
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-num-size", "aria-hidden": "true", children: sizeText }),
|
|
10638
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("select", { className: "ss-w-tool-num-select", "aria-label": label, value: String(currentIdx), onChange: (e) => onChoose(Number(e.target.value)), children: optionLabels.map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("option", { value: String(i), children: opt }, i)) })
|
|
10252
10639
|
] });
|
|
10253
10640
|
}
|
|
10254
10641
|
function SendButton({ label, display, disabled, onClick }) {
|
|
10255
|
-
return /* @__PURE__ */ (0,
|
|
10642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("button", { type: "button", className: "ss-w-tool-send", "aria-label": `${label}: ${display}`, disabled, onClick, children: label });
|
|
10256
10643
|
}
|
|
10257
10644
|
function PickList({ picks, formatKickoff }) {
|
|
10258
|
-
return /* @__PURE__ */ (0,
|
|
10259
|
-
/* @__PURE__ */ (0,
|
|
10645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("ul", { className: "ss-w-tool-picks", role: "list", children: picks.map((p) => /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("li", { className: "ss-w-tool-pick", children: [
|
|
10646
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "ss-w-tool-pick-match", children: [
|
|
10260
10647
|
p.homeTeamName,
|
|
10261
10648
|
" \u2013 ",
|
|
10262
10649
|
p.awayTeamName
|
|
10263
10650
|
] }),
|
|
10264
|
-
/* @__PURE__ */ (0,
|
|
10651
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "ss-w-tool-pick-sel", children: [
|
|
10265
10652
|
p.marketLabel,
|
|
10266
10653
|
": ",
|
|
10267
10654
|
p.selectionLabel,
|
|
10268
10655
|
p.line ? ` ${p.line}` : ""
|
|
10269
10656
|
] }),
|
|
10270
|
-
/* @__PURE__ */ (0,
|
|
10271
|
-
/* @__PURE__ */ (0,
|
|
10657
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-pick-kick", children: formatKickoff(p.kickoffUtc) }),
|
|
10658
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-pick-price", children: p.price.toFixed(2) })
|
|
10272
10659
|
] }, p.matchOddsId)) });
|
|
10273
10660
|
}
|
|
10274
10661
|
function ComboPreview({ cell, formatKickoff }) {
|
|
10275
|
-
return /* @__PURE__ */ (0,
|
|
10276
|
-
/* @__PURE__ */ (0,
|
|
10277
|
-
/* @__PURE__ */ (0,
|
|
10662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(import_jsx_runtime104.Fragment, { children: [
|
|
10663
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(PickList, { picks: cell.combo.legs, formatKickoff }),
|
|
10664
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "ss-w-tool-math", children: cell.combo.multiplication })
|
|
10278
10665
|
] });
|
|
10279
10666
|
}
|
|
10280
10667
|
function Unavailable({ text }) {
|
|
10281
|
-
return /* @__PURE__ */ (0,
|
|
10668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("p", { className: "ss-w-tool-unavailable", children: text });
|
|
10282
10669
|
}
|
|
10283
10670
|
function AskRow({ icon, ask, ready, send }) {
|
|
10284
|
-
return /* @__PURE__ */ (0,
|
|
10285
|
-
/* @__PURE__ */ (0,
|
|
10286
|
-
/* @__PURE__ */ (0,
|
|
10287
|
-
/* @__PURE__ */ (0,
|
|
10288
|
-
ready ? /* @__PURE__ */ (0,
|
|
10671
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("section", { className: "ss-w-tool-row ss-w-tool-row--ask", children: [
|
|
10672
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-icon", "aria-hidden": "true", children: icon }),
|
|
10673
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "ss-w-tool-main", children: [
|
|
10674
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("p", { className: "ss-w-tool-ask", children: ask }),
|
|
10675
|
+
ready ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-ready", children: ready }) : null
|
|
10289
10676
|
] }),
|
|
10290
10677
|
send
|
|
10291
10678
|
] });
|
|
10292
10679
|
}
|
|
10293
10680
|
function RoundSend({ label, display, disabled, onClick }) {
|
|
10294
|
-
return /* @__PURE__ */ (0,
|
|
10681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("button", { type: "button", className: "ss-w-tool-go", "aria-label": `${label}: ${display}`, disabled, onClick, children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(SendIcon, {}) });
|
|
10295
10682
|
}
|
|
10296
10683
|
var BIG_COMBO = { total: 50, legs: 6 };
|
|
10297
10684
|
function SetNumbersTool({ grid, strings, streaming, onSend, onClose }) {
|
|
@@ -10300,15 +10687,15 @@ function SetNumbersTool({ grid, strings, streaming, onSend, onClose }) {
|
|
|
10300
10687
|
const totals = comboTotals(grid);
|
|
10301
10688
|
const legChoices = comboLegChoices(grid);
|
|
10302
10689
|
const count = FIXED_SINGLES_COUNT;
|
|
10303
|
-
const [maxPrice, setMaxPrice] = (0,
|
|
10304
|
-
const [minPrice, setMinPrice] = (0,
|
|
10305
|
-
const [start] = (0,
|
|
10306
|
-
const [total, setTotal] = (0,
|
|
10307
|
-
const [legs, setLegs] = (0,
|
|
10308
|
-
const [bigStart] = (0,
|
|
10309
|
-
const [bigTotal, setBigTotal] = (0,
|
|
10310
|
-
const [bigLegs, setBigLegs] = (0,
|
|
10311
|
-
const [announcement, setAnnouncement] = (0,
|
|
10690
|
+
const [maxPrice, setMaxPrice] = (0, import_react66.useState)(() => startSingles(grid.singles, limits, START.maxPrice, count));
|
|
10691
|
+
const [minPrice, setMinPrice] = (0, import_react66.useState)(() => startSingles(grid.singlesFrom, floors, START.minPrice, count));
|
|
10692
|
+
const [start] = (0, import_react66.useState)(() => startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs));
|
|
10693
|
+
const [total, setTotal] = (0, import_react66.useState)(start.total);
|
|
10694
|
+
const [legs, setLegs] = (0, import_react66.useState)(start.legs);
|
|
10695
|
+
const [bigStart] = (0, import_react66.useState)(() => startCombo(grid, totals, legChoices, BIG_COMBO.total, BIG_COMBO.legs));
|
|
10696
|
+
const [bigTotal, setBigTotal] = (0, import_react66.useState)(bigStart.total);
|
|
10697
|
+
const [bigLegs, setBigLegs] = (0, import_react66.useState)(bigStart.legs);
|
|
10698
|
+
const [announcement, setAnnouncement] = (0, import_react66.useState)("");
|
|
10312
10699
|
const maxCell = findSingles(grid.singles, maxPrice, count);
|
|
10313
10700
|
const minCell = findSingles(grid.singlesFrom, minPrice, count);
|
|
10314
10701
|
const comboCell = findCombo(grid, total, legs);
|
|
@@ -10352,95 +10739,95 @@ function SetNumbersTool({ grid, strings, streaming, onSend, onClose }) {
|
|
|
10352
10739
|
const totalChoices = totals.map((v) => ({ value: v, text: v.toFixed(1), available: legChoices.some((n) => !!findCombo(grid, v, n)) }));
|
|
10353
10740
|
const legChoicesFor = (t) => legChoices.map((n) => ({ value: n, text: String(n), available: !!findCombo(grid, t, n) }));
|
|
10354
10741
|
const markets = grid.markets ?? [];
|
|
10355
|
-
const [marketIdx, setMarketIdx] = (0,
|
|
10742
|
+
const [marketIdx, setMarketIdx] = (0, import_react66.useState)(0);
|
|
10356
10743
|
const marketCell = markets[marketIdx] ?? null;
|
|
10357
10744
|
const marketLabels = markets.map((c) => strings.marketShort(c.marketDeveloperName, c.marketLabel, c.selectionLabel ?? null));
|
|
10358
10745
|
const singlesReady = (cell) => cell ? strings.readyCount(cell.picks.length) : strings.unavailable;
|
|
10359
10746
|
const comboReady = (cell) => cell ? strings.readyAt(cell.combo.total) : strings.unavailable;
|
|
10360
|
-
return /* @__PURE__ */ (0,
|
|
10361
|
-
/* @__PURE__ */ (0,
|
|
10747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(PresetToolModal, { title: strings.setNumbers, closeLabel: strings.close, onClose, children: [
|
|
10748
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
10362
10749
|
AskRow,
|
|
10363
10750
|
{
|
|
10364
10751
|
icon: "\u{1F3AF}",
|
|
10365
10752
|
ask: fillTemplate(strings.maxPriceRow, {
|
|
10366
10753
|
count: String(count),
|
|
10367
|
-
price: /* @__PURE__ */ (0,
|
|
10754
|
+
price: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(NumberSelect, { current: maxPrice.toFixed(2), choices: maxChoices, label: strings.maxPriceName, notToday: strings.notToday, onChoose: chooseMax })
|
|
10368
10755
|
}),
|
|
10369
10756
|
ready: singlesReady(maxCell),
|
|
10370
|
-
send: /* @__PURE__ */ (0,
|
|
10757
|
+
send: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(RoundSend, { label: strings.send, display: strings.maxPriceDisplay(count, maxPrice), disabled: !maxCell || streaming, onClick: () => {
|
|
10371
10758
|
if (maxCell) onSend(maxPriceAsk(maxCell, strings));
|
|
10372
10759
|
} })
|
|
10373
10760
|
}
|
|
10374
10761
|
),
|
|
10375
|
-
/* @__PURE__ */ (0,
|
|
10762
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
10376
10763
|
AskRow,
|
|
10377
10764
|
{
|
|
10378
10765
|
icon: "\u{1F4C8}",
|
|
10379
10766
|
ask: fillTemplate(strings.minPriceRow, {
|
|
10380
10767
|
count: String(count),
|
|
10381
|
-
price: /* @__PURE__ */ (0,
|
|
10768
|
+
price: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(NumberSelect, { current: minPrice.toFixed(2), choices: minChoices, label: strings.minPriceName, notToday: strings.notToday, onChoose: chooseMin })
|
|
10382
10769
|
}),
|
|
10383
10770
|
ready: singlesReady(minCell),
|
|
10384
|
-
send: /* @__PURE__ */ (0,
|
|
10771
|
+
send: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(RoundSend, { label: strings.send, display: strings.minPriceDisplay(count, minPrice), disabled: !minCell || streaming, onClick: () => {
|
|
10385
10772
|
if (minCell) onSend(minPriceAsk(minCell, strings));
|
|
10386
10773
|
} })
|
|
10387
10774
|
}
|
|
10388
10775
|
),
|
|
10389
|
-
/* @__PURE__ */ (0,
|
|
10776
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
10390
10777
|
AskRow,
|
|
10391
10778
|
{
|
|
10392
10779
|
icon: "\u2728",
|
|
10393
10780
|
ask: fillTemplate(strings.comboRow, {
|
|
10394
|
-
legs: /* @__PURE__ */ (0,
|
|
10395
|
-
total: /* @__PURE__ */ (0,
|
|
10781
|
+
legs: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(NumberSelect, { current: String(legs), choices: legChoicesFor(total), label: strings.matchesLabel, notToday: strings.notToday, lockEmpty: false, onChoose: chooseLegs }),
|
|
10782
|
+
total: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(NumberSelect, { current: total.toFixed(1), choices: totalChoices, label: strings.totalLabel, notToday: strings.notToday, onChoose: chooseTotal })
|
|
10396
10783
|
}),
|
|
10397
10784
|
ready: comboReady(comboCell),
|
|
10398
|
-
send: /* @__PURE__ */ (0,
|
|
10785
|
+
send: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(RoundSend, { label: strings.send, display: strings.comboDisplay(legs, total), disabled: !comboCell || streaming, onClick: () => {
|
|
10399
10786
|
if (comboCell) onSend(comboAsk(comboCell, strings));
|
|
10400
10787
|
} })
|
|
10401
10788
|
}
|
|
10402
10789
|
),
|
|
10403
|
-
/* @__PURE__ */ (0,
|
|
10790
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
10404
10791
|
AskRow,
|
|
10405
10792
|
{
|
|
10406
10793
|
icon: "\u{1F3C6}",
|
|
10407
10794
|
ask: fillTemplate(strings.bigComboRow, {
|
|
10408
|
-
legs: /* @__PURE__ */ (0,
|
|
10409
|
-
total: /* @__PURE__ */ (0,
|
|
10795
|
+
legs: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(NumberSelect, { current: String(bigLegs), choices: legChoicesFor(bigTotal), label: strings.matchesLabel, notToday: strings.notToday, lockEmpty: false, onChoose: chooseBigLegs }),
|
|
10796
|
+
total: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(NumberSelect, { current: bigTotal.toFixed(1), choices: totalChoices, label: strings.totalLabel, notToday: strings.notToday, onChoose: chooseBigTotal })
|
|
10410
10797
|
}),
|
|
10411
10798
|
ready: comboReady(bigCell),
|
|
10412
|
-
send: /* @__PURE__ */ (0,
|
|
10799
|
+
send: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(RoundSend, { label: strings.send, display: strings.comboDisplay(bigLegs, bigTotal), disabled: !bigCell || streaming, onClick: () => {
|
|
10413
10800
|
if (bigCell) onSend(comboAsk(bigCell, strings));
|
|
10414
10801
|
} })
|
|
10415
10802
|
}
|
|
10416
10803
|
),
|
|
10417
|
-
markets.length > 0 && /* @__PURE__ */ (0,
|
|
10804
|
+
markets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
10418
10805
|
AskRow,
|
|
10419
10806
|
{
|
|
10420
10807
|
icon: "\u26BD",
|
|
10421
10808
|
ask: fillTemplate(strings.marketRow, {
|
|
10422
|
-
market: /* @__PURE__ */ (0,
|
|
10809
|
+
market: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(ChoiceSelect, { currentIdx: marketIdx, sizeLabels: marketLabels, optionLabels: marketLabels, label: strings.marketName, onChoose: chooseMarket })
|
|
10423
10810
|
}),
|
|
10424
10811
|
ready: marketCell ? strings.readyCount(marketCell.count) : null,
|
|
10425
|
-
send: /* @__PURE__ */ (0,
|
|
10812
|
+
send: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(RoundSend, { label: strings.send, display: marketCell ? marketDisplay(marketCell, strings) : "", disabled: !marketCell || streaming, onClick: () => {
|
|
10426
10813
|
if (marketCell) onSend(marketAsk(marketCell, strings));
|
|
10427
10814
|
} })
|
|
10428
10815
|
}
|
|
10429
10816
|
),
|
|
10430
|
-
/* @__PURE__ */ (0,
|
|
10817
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("p", { className: "ss-w-vh", "aria-live": "polite", children: announcement })
|
|
10431
10818
|
] });
|
|
10432
10819
|
}
|
|
10433
10820
|
function BuildComboTool({ grid, strings, streaming, formatKickoff, initialTotal, initialLegs, onSend, onClose }) {
|
|
10434
10821
|
const totals = comboTotals(grid);
|
|
10435
10822
|
const legChoices = comboLegChoices(grid);
|
|
10436
|
-
const [start] = (0,
|
|
10437
|
-
const [total, setTotal] = (0,
|
|
10438
|
-
const [legs, setLegs] = (0,
|
|
10823
|
+
const [start] = (0, import_react66.useState)(() => initialTotal === void 0 ? startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs) : null);
|
|
10824
|
+
const [total, setTotal] = (0, import_react66.useState)(() => initialTotal !== void 0 ? nearest(totals, initialTotal) : start.total);
|
|
10825
|
+
const [legs, setLegs] = (0, import_react66.useState)(() => {
|
|
10439
10826
|
if (initialTotal === void 0) return initialLegs !== void 0 ? clampLegs(legChoices, initialLegs) : start.legs;
|
|
10440
10827
|
const from = initialLegs !== void 0 ? clampLegs(legChoices, initialLegs) : startValue(legChoices, START.comboLegs);
|
|
10441
10828
|
return legsForTotal(grid, nearest(totals, initialTotal), from);
|
|
10442
10829
|
});
|
|
10443
|
-
const [announcement, setAnnouncement] = (0,
|
|
10830
|
+
const [announcement, setAnnouncement] = (0, import_react66.useState)("");
|
|
10444
10831
|
const cell = findCombo(grid, total, legs);
|
|
10445
10832
|
const minLegs = legChoices[0] ?? legs;
|
|
10446
10833
|
const maxLegs = legChoices[legChoices.length - 1] ?? legs;
|
|
@@ -10451,29 +10838,29 @@ function BuildComboTool({ grid, strings, streaming, formatKickoff, initialTotal,
|
|
|
10451
10838
|
const d = strings.comboDisplay(nextLegs, nextTotal);
|
|
10452
10839
|
setAnnouncement(findCombo(grid, nextTotal, nextLegs) ? d : `${d}. ${strings.unavailable}`);
|
|
10453
10840
|
};
|
|
10454
|
-
const footer = /* @__PURE__ */ (0,
|
|
10841
|
+
const footer = /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(SendButton, { label: strings.send, display, disabled: !cell || streaming, onClick: () => {
|
|
10455
10842
|
if (cell) onSend(comboAsk(cell, strings));
|
|
10456
10843
|
} });
|
|
10457
|
-
return /* @__PURE__ */ (0,
|
|
10458
|
-
/* @__PURE__ */ (0,
|
|
10459
|
-
/* @__PURE__ */ (0,
|
|
10460
|
-
/* @__PURE__ */ (0,
|
|
10844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(PresetToolModal, { title: strings.buildCombo, closeLabel: strings.close, onClose, footer, children: [
|
|
10845
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "ss-w-tool-section", role: "group", "aria-label": strings.totalLabel, children: [
|
|
10846
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-label", "aria-hidden": "true", children: strings.totalLabel }),
|
|
10847
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "ss-w-tool-chips", children: totals.map((t) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("button", { type: "button", className: "ss-w-tool-chip", "aria-pressed": samePrice(t, total), onClick: () => choose(t, samePrice(t, total) ? legs : legsForTotal(grid, t, legs)), children: t.toFixed(1) }, t)) })
|
|
10461
10848
|
] }),
|
|
10462
|
-
/* @__PURE__ */ (0,
|
|
10463
|
-
/* @__PURE__ */ (0,
|
|
10464
|
-
/* @__PURE__ */ (0,
|
|
10465
|
-
/* @__PURE__ */ (0,
|
|
10466
|
-
/* @__PURE__ */ (0,
|
|
10467
|
-
/* @__PURE__ */ (0,
|
|
10849
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "ss-w-tool-section", role: "group", "aria-label": strings.matchesLabel, children: [
|
|
10850
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-label", "aria-hidden": "true", children: strings.matchesLabel }),
|
|
10851
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "ss-w-tool-stepper", children: [
|
|
10852
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("button", { type: "button", className: "ss-w-tool-step", "aria-label": strings.fewerMatches, disabled: legs <= minLegs, onClick: () => choose(total, legs - 1), children: "\u2212" }),
|
|
10853
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "ss-w-tool-count", children: legs }),
|
|
10854
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("button", { type: "button", className: "ss-w-tool-step", "aria-label": strings.moreMatches, disabled: legs >= maxLegs, onClick: () => choose(total, legs + 1), children: "+" })
|
|
10468
10855
|
] })
|
|
10469
10856
|
] }),
|
|
10470
|
-
cell ? /* @__PURE__ */ (0,
|
|
10471
|
-
/* @__PURE__ */ (0,
|
|
10857
|
+
cell ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(ComboPreview, { cell, formatKickoff }) : /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(Unavailable, { text: strings.unavailable }),
|
|
10858
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("p", { className: "ss-w-vh", "aria-live": "polite", children: announcement })
|
|
10472
10859
|
] });
|
|
10473
10860
|
}
|
|
10474
10861
|
|
|
10475
10862
|
// src/usePresetDial.ts
|
|
10476
|
-
var
|
|
10863
|
+
var import_react67 = require("react");
|
|
10477
10864
|
function sendInFlight(messages, isStreaming) {
|
|
10478
10865
|
const last = messages[messages.length - 1];
|
|
10479
10866
|
return isStreaming && !!last && last.role === "assistant" && !last.done && !last.isGreeting;
|
|
@@ -10487,25 +10874,25 @@ function lastUserId(messages) {
|
|
|
10487
10874
|
}
|
|
10488
10875
|
var SCROLL_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", " "]);
|
|
10489
10876
|
function usePresetDial({ layerRef, dialRef, dialButtonRef, messages, isStreaming, activeTab }) {
|
|
10490
|
-
const [expanded, setExpanded] = (0,
|
|
10491
|
-
const fold = (0,
|
|
10492
|
-
const toggle = (0,
|
|
10877
|
+
const [expanded, setExpanded] = (0, import_react67.useState)(() => !sendInFlight(messages, isStreaming));
|
|
10878
|
+
const fold = (0, import_react67.useCallback)(() => setExpanded(false), []);
|
|
10879
|
+
const toggle = (0, import_react67.useCallback)(() => setExpanded((e) => !e), []);
|
|
10493
10880
|
const currentUserId = lastUserId(messages);
|
|
10494
|
-
const userIdRef = (0,
|
|
10495
|
-
(0,
|
|
10881
|
+
const userIdRef = (0, import_react67.useRef)(currentUserId);
|
|
10882
|
+
(0, import_react67.useEffect)(() => {
|
|
10496
10883
|
if (currentUserId === userIdRef.current) return;
|
|
10497
10884
|
userIdRef.current = currentUserId;
|
|
10498
10885
|
setExpanded(false);
|
|
10499
10886
|
}, [currentUserId]);
|
|
10500
|
-
const tabRef = (0,
|
|
10501
|
-
(0,
|
|
10887
|
+
const tabRef = (0, import_react67.useRef)(activeTab);
|
|
10888
|
+
(0, import_react67.useEffect)(() => {
|
|
10502
10889
|
if (activeTab === tabRef.current) return;
|
|
10503
10890
|
tabRef.current = activeTab;
|
|
10504
10891
|
setExpanded(false);
|
|
10505
10892
|
}, [activeTab]);
|
|
10506
|
-
const expandedRef = (0,
|
|
10893
|
+
const expandedRef = (0, import_react67.useRef)(expanded);
|
|
10507
10894
|
expandedRef.current = expanded;
|
|
10508
|
-
(0,
|
|
10895
|
+
(0, import_react67.useEffect)(() => {
|
|
10509
10896
|
const onEscape = (e) => {
|
|
10510
10897
|
const dial = dialRef.current;
|
|
10511
10898
|
if (e.key !== "Escape" || !dial || !e.composedPath().includes(dial)) return;
|
|
@@ -10518,7 +10905,7 @@ function usePresetDial({ layerRef, dialRef, dialButtonRef, messages, isStreaming
|
|
|
10518
10905
|
window.addEventListener("keydown", onEscape, true);
|
|
10519
10906
|
return () => window.removeEventListener("keydown", onEscape, true);
|
|
10520
10907
|
}, [dialRef, dialButtonRef]);
|
|
10521
|
-
(0,
|
|
10908
|
+
(0, import_react67.useEffect)(() => {
|
|
10522
10909
|
if (!expanded) return;
|
|
10523
10910
|
const layer = layerRef.current;
|
|
10524
10911
|
const inDial = (e) => {
|
|
@@ -10570,11 +10957,11 @@ function markToolSeen() {
|
|
|
10570
10957
|
}
|
|
10571
10958
|
|
|
10572
10959
|
// src/components/ChatPanel.tsx
|
|
10573
|
-
var
|
|
10960
|
+
var import_jsx_runtime105 = require("react/jsx-runtime");
|
|
10574
10961
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
10575
10962
|
function useIsModal() {
|
|
10576
|
-
const [modal, setModal] = (0,
|
|
10577
|
-
(0,
|
|
10963
|
+
const [modal, setModal] = (0, import_react68.useState)(false);
|
|
10964
|
+
(0, import_react68.useEffect)(() => {
|
|
10578
10965
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
10579
10966
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
10580
10967
|
const sync = () => setModal(mql.matches);
|
|
@@ -10588,12 +10975,12 @@ var HIDDEN_LAYER_STYLE = { position: "absolute", inset: 0, visibility: "hidden",
|
|
|
10588
10975
|
var SQUAD_LAYER_STYLE = { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 };
|
|
10589
10976
|
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, clubFixturesResult, clubStandingsResult, clubSquadResult, clubSquadStatsResult, clubPlayerDetailResult, loggedIn, conversation, presetGrid }) {
|
|
10590
10977
|
const { state, close, stop, send, reset } = controller;
|
|
10591
|
-
const [squadView, setSquadView] = (0,
|
|
10592
|
-
const [selectedPlayerId, setSelectedPlayerId] = (0,
|
|
10978
|
+
const [squadView, setSquadView] = (0, import_react68.useState)("roster");
|
|
10979
|
+
const [selectedPlayerId, setSelectedPlayerId] = (0, import_react68.useState)(null);
|
|
10593
10980
|
const clearPlayerDetail = clubPlayerDetailResult?.clear;
|
|
10594
10981
|
const fetchPlayerDetail = clubPlayerDetailResult?.fetch;
|
|
10595
|
-
const squadLayerRef = (0,
|
|
10596
|
-
const squadScrollRef = (0,
|
|
10982
|
+
const squadLayerRef = (0, import_react68.useRef)(null);
|
|
10983
|
+
const squadScrollRef = (0, import_react68.useRef)(null);
|
|
10597
10984
|
const selectPlayer = (playerId) => {
|
|
10598
10985
|
squadScrollRef.current = squadLayerRef.current?.querySelector(".ss-w-mon-list")?.scrollTop ?? null;
|
|
10599
10986
|
setSelectedPlayerId(playerId);
|
|
@@ -10603,20 +10990,20 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10603
10990
|
setSelectedPlayerId(null);
|
|
10604
10991
|
clearPlayerDetail?.();
|
|
10605
10992
|
};
|
|
10606
|
-
(0,
|
|
10993
|
+
(0, import_react68.useLayoutEffect)(() => {
|
|
10607
10994
|
if (selectedPlayerId !== null || squadScrollRef.current === null) return;
|
|
10608
10995
|
const list = squadLayerRef.current?.querySelector(".ss-w-mon-list");
|
|
10609
10996
|
if (list) list.scrollTop = squadScrollRef.current;
|
|
10610
10997
|
squadScrollRef.current = null;
|
|
10611
10998
|
}, [selectedPlayerId]);
|
|
10612
10999
|
const activeTab = monitor?.activeTab;
|
|
10613
|
-
(0,
|
|
11000
|
+
(0, import_react68.useEffect)(() => {
|
|
10614
11001
|
if (activeTab === "squad" || selectedPlayerId === null) return;
|
|
10615
11002
|
setSelectedPlayerId(null);
|
|
10616
11003
|
clearPlayerDetail?.();
|
|
10617
11004
|
}, [activeTab, selectedPlayerId, clearPlayerDetail]);
|
|
10618
11005
|
const isModal = useIsModal();
|
|
10619
|
-
(0,
|
|
11006
|
+
(0, import_react68.useEffect)(() => {
|
|
10620
11007
|
const onKey = (e) => {
|
|
10621
11008
|
if (e.key === "Escape") close();
|
|
10622
11009
|
};
|
|
@@ -10632,19 +11019,19 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10632
11019
|
monitor?.setActiveTab("chat");
|
|
10633
11020
|
send(text, { grounding });
|
|
10634
11021
|
};
|
|
10635
|
-
(0,
|
|
11022
|
+
(0, import_react68.useEffect)(() => {
|
|
10636
11023
|
if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
|
|
10637
11024
|
}, [monitor, state.isStreaming, state.messages.length]);
|
|
10638
11025
|
const onChatTab = !monitor || monitor.activeTab === "chat";
|
|
10639
|
-
const layerRef = (0,
|
|
10640
|
-
const dialRef = (0,
|
|
10641
|
-
const dialButtonRef = (0,
|
|
10642
|
-
const inputRef = (0,
|
|
10643
|
-
const limitRef = (0,
|
|
10644
|
-
const typedSendRef = (0,
|
|
10645
|
-
const focusAfterCloseRef = (0,
|
|
10646
|
-
const [tool, setTool] = (0,
|
|
10647
|
-
const [toolSeen, setToolSeen] = (0,
|
|
11026
|
+
const layerRef = (0, import_react68.useRef)(null);
|
|
11027
|
+
const dialRef = (0, import_react68.useRef)(null);
|
|
11028
|
+
const dialButtonRef = (0, import_react68.useRef)(null);
|
|
11029
|
+
const inputRef = (0, import_react68.useRef)(null);
|
|
11030
|
+
const limitRef = (0, import_react68.useRef)(null);
|
|
11031
|
+
const typedSendRef = (0, import_react68.useRef)(false);
|
|
11032
|
+
const focusAfterCloseRef = (0, import_react68.useRef)(null);
|
|
11033
|
+
const [tool, setTool] = (0, import_react68.useState)(null);
|
|
11034
|
+
const [toolSeen, setToolSeen] = (0, import_react68.useState)(readToolSeen);
|
|
10648
11035
|
const dial = usePresetDial({
|
|
10649
11036
|
layerRef,
|
|
10650
11037
|
dialRef,
|
|
@@ -10656,53 +11043,53 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10656
11043
|
const { fold } = dial;
|
|
10657
11044
|
const paused = isPaused(state.limit);
|
|
10658
11045
|
const showDial = !!presetGrid && onChatTab && !tool && !paused;
|
|
10659
|
-
(0,
|
|
11046
|
+
(0, import_react68.useEffect)(() => {
|
|
10660
11047
|
if (paused) setTool(null);
|
|
10661
11048
|
}, [paused]);
|
|
10662
|
-
(0,
|
|
11049
|
+
(0, import_react68.useEffect)(() => {
|
|
10663
11050
|
if (!paused) return;
|
|
10664
11051
|
if (typedSendRef.current) limitRef.current?.focus();
|
|
10665
11052
|
typedSendRef.current = false;
|
|
10666
11053
|
}, [paused]);
|
|
10667
|
-
const openTool = (0,
|
|
11054
|
+
const openTool = (0, import_react68.useCallback)((next) => {
|
|
10668
11055
|
fold();
|
|
10669
11056
|
markToolSeen();
|
|
10670
11057
|
setToolSeen(true);
|
|
10671
11058
|
setTool(next);
|
|
10672
11059
|
}, [fold]);
|
|
10673
|
-
const onPill = (0,
|
|
10674
|
-
const toolsValue = (0,
|
|
11060
|
+
const onPill = (0, import_react68.useCallback)((kind) => openTool(kind === "numbers" ? { kind: "numbers" } : { kind: "combo" }), [openTool]);
|
|
11061
|
+
const toolsValue = (0, import_react68.useMemo)(
|
|
10675
11062
|
() => presetGrid && !paused ? { openBuilder: (total, legs) => openTool({ kind: "combo", total, legs }), changeLabel: ui.presets.changeCombo } : null,
|
|
10676
11063
|
[presetGrid, paused, openTool, ui.presets.changeCombo]
|
|
10677
11064
|
);
|
|
10678
|
-
const closeTool = (0,
|
|
11065
|
+
const closeTool = (0, import_react68.useCallback)(() => {
|
|
10679
11066
|
focusAfterCloseRef.current = "dial";
|
|
10680
11067
|
setTool(null);
|
|
10681
11068
|
}, []);
|
|
10682
|
-
const sendAsk = (0,
|
|
11069
|
+
const sendAsk = (0, import_react68.useCallback)((ask) => {
|
|
10683
11070
|
focusAfterCloseRef.current = "composer";
|
|
10684
11071
|
setTool(null);
|
|
10685
11072
|
monitor?.setActiveTab("chat");
|
|
10686
11073
|
send(ask.message, { displayText: ask.displayText, preset: ask.preset });
|
|
10687
11074
|
}, [monitor, send]);
|
|
10688
|
-
const formatKickoff = (0,
|
|
11075
|
+
const formatKickoff = (0, import_react68.useCallback)((kickoffUtc) => {
|
|
10689
11076
|
const k = ui.bettingKickoff(kickoffUtc);
|
|
10690
11077
|
return `${k.dayLabel} ${k.time}`;
|
|
10691
11078
|
}, [ui]);
|
|
10692
|
-
(0,
|
|
11079
|
+
(0, import_react68.useEffect)(() => {
|
|
10693
11080
|
if (tool) return;
|
|
10694
11081
|
const target = focusAfterCloseRef.current;
|
|
10695
11082
|
focusAfterCloseRef.current = null;
|
|
10696
11083
|
if (target === "dial") dialButtonRef.current?.focus();
|
|
10697
11084
|
else if (target === "composer") inputRef.current?.focus();
|
|
10698
11085
|
}, [tool]);
|
|
10699
|
-
(0,
|
|
11086
|
+
(0, import_react68.useEffect)(() => {
|
|
10700
11087
|
if (!tool || onChatTab && presetGrid) return;
|
|
10701
11088
|
focusAfterCloseRef.current = "composer";
|
|
10702
11089
|
setTool(null);
|
|
10703
11090
|
}, [tool, onChatTab, presetGrid]);
|
|
10704
|
-
return /* @__PURE__ */ (0,
|
|
10705
|
-
/* @__PURE__ */ (0,
|
|
11091
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
11092
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10706
11093
|
ChatHeader,
|
|
10707
11094
|
{
|
|
10708
11095
|
onClose: close,
|
|
@@ -10715,7 +11102,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10715
11102
|
moreOptionsLabel: ui.moreOptions
|
|
10716
11103
|
}
|
|
10717
11104
|
),
|
|
10718
|
-
monitor && /* @__PURE__ */ (0,
|
|
11105
|
+
monitor && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10719
11106
|
TabBar,
|
|
10720
11107
|
{
|
|
10721
11108
|
monitor,
|
|
@@ -10728,9 +11115,9 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10728
11115
|
clubEnabled: clubFixturesResult?.enabled ?? false
|
|
10729
11116
|
}
|
|
10730
11117
|
),
|
|
10731
|
-
/* @__PURE__ */ (0,
|
|
10732
|
-
/* @__PURE__ */ (0,
|
|
10733
|
-
showDial ? /* @__PURE__ */ (0,
|
|
11118
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { ref: layerRef, className: "ss-w-chat-layer", "data-dial": presetGrid ? "" : void 0, style: onChatTab ? void 0 : HIDDEN_LAYER_STYLE, children: [
|
|
11119
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(PresetToolsContext.Provider, { value: toolsValue, children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor }) }),
|
|
11120
|
+
showDial ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10734
11121
|
PresetSpeedDial,
|
|
10735
11122
|
{
|
|
10736
11123
|
expanded: dial.expanded,
|
|
@@ -10742,21 +11129,21 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10742
11129
|
buttonRef: dialButtonRef
|
|
10743
11130
|
}
|
|
10744
11131
|
) : null,
|
|
10745
|
-
tool && presetGrid && onChatTab && !paused ? tool.kind === "numbers" ? /* @__PURE__ */ (0,
|
|
11132
|
+
tool && presetGrid && onChatTab && !paused ? tool.kind === "numbers" ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(SetNumbersTool, { grid: presetGrid, strings: ui.presets, streaming: state.isStreaming, onSend: sendAsk, onClose: closeTool }) : /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(BuildComboTool, { grid: presetGrid, strings: ui.presets, streaming: state.isStreaming, formatKickoff, initialTotal: tool.total, initialLegs: tool.legs, onSend: sendAsk, onClose: closeTool }) : null
|
|
10746
11133
|
] }),
|
|
10747
|
-
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0,
|
|
10748
|
-
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0,
|
|
10749
|
-
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0,
|
|
10750
|
-
monitor && monitor.activeTab === "fixtures" && /* @__PURE__ */ (0,
|
|
10751
|
-
monitor && monitor.activeTab === "standings" && /* @__PURE__ */ (0,
|
|
10752
|
-
monitor && monitor.activeTab === "squad" && /* @__PURE__ */ (0,
|
|
10753
|
-
/* @__PURE__ */ (0,
|
|
11134
|
+
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(TodayPanel, { discovery, ui, monitor }),
|
|
11135
|
+
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(MatchesPanel, { monitor, ui, slip, onAsk: paused ? void 0 : handleAsk }),
|
|
11136
|
+
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(OddsPanel, { monitor, ui, slip }),
|
|
11137
|
+
monitor && monitor.activeTab === "fixtures" && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Fixtures, { fixtures: clubFixturesResult?.fixtures ?? [], loading: clubFixturesResult?.loading ?? false, ui }),
|
|
11138
|
+
monitor && monitor.activeTab === "standings" && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Standings, { standings: clubStandingsResult?.data ?? null, loading: clubStandingsResult?.loading ?? false, ui }),
|
|
11139
|
+
monitor && monitor.activeTab === "squad" && /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
|
|
11140
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10754
11141
|
"div",
|
|
10755
11142
|
{
|
|
10756
11143
|
ref: squadLayerRef,
|
|
10757
11144
|
style: selectedPlayerId === null ? SQUAD_LAYER_STYLE : HIDDEN_LAYER_STYLE,
|
|
10758
11145
|
"aria-hidden": selectedPlayerId !== null ? true : void 0,
|
|
10759
|
-
children: /* @__PURE__ */ (0,
|
|
11146
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10760
11147
|
Squad,
|
|
10761
11148
|
{
|
|
10762
11149
|
squad: clubSquadResult?.data ?? null,
|
|
@@ -10766,14 +11153,17 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10766
11153
|
onToggleView: () => setSquadView((v) => v === "roster" ? "stats" : "roster"),
|
|
10767
11154
|
stats: clubSquadStatsResult?.data ?? null,
|
|
10768
11155
|
statsLoading: clubSquadStatsResult?.loading ?? false,
|
|
11156
|
+
seasonName: clubSquadStatsResult?.seasonName ?? null,
|
|
11157
|
+
competitionName: clubSquadStatsResult?.competitionName ?? null,
|
|
11158
|
+
matchesPlayed: clubSquadStatsResult?.matchesPlayed ?? null,
|
|
10769
11159
|
onSelectPlayer: selectPlayer
|
|
10770
11160
|
}
|
|
10771
11161
|
)
|
|
10772
11162
|
}
|
|
10773
11163
|
),
|
|
10774
|
-
selectedPlayerId !== null && /* @__PURE__ */ (0,
|
|
11164
|
+
selectedPlayerId !== null && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(PlayerDetail, { detail: clubPlayerDetailResult?.data ?? null, loading: clubPlayerDetailResult?.loading ?? false, ui, seasonName: clubSquadStatsResult?.seasonName ?? null, onClose: closePlayer })
|
|
10775
11165
|
] }),
|
|
10776
|
-
monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0,
|
|
11166
|
+
monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10777
11167
|
GamesPanel,
|
|
10778
11168
|
{
|
|
10779
11169
|
loggedIn: !!loggedIn,
|
|
@@ -10788,9 +11178,9 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10788
11178
|
}
|
|
10789
11179
|
}
|
|
10790
11180
|
),
|
|
10791
|
-
(!monitor || monitor.activeTab !== "games") && /* @__PURE__ */ (0,
|
|
10792
|
-
/* @__PURE__ */ (0,
|
|
10793
|
-
paused ? null : /* @__PURE__ */ (0,
|
|
11181
|
+
(!monitor || monitor.activeTab !== "games") && /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
|
|
11182
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)("div", { ref: limitRef, className: "ss-w-limit", role: "status", tabIndex: -1, children: state.limit ? limitText(state.limit, ui) : null }),
|
|
11183
|
+
paused ? null : /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
10794
11184
|
ChatInput,
|
|
10795
11185
|
{
|
|
10796
11186
|
ref: inputRef,
|
|
@@ -10809,9 +11199,9 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
10809
11199
|
}
|
|
10810
11200
|
|
|
10811
11201
|
// src/components/HostEventsProvider.tsx
|
|
10812
|
-
var
|
|
11202
|
+
var import_jsx_runtime106 = require("react/jsx-runtime");
|
|
10813
11203
|
function HostEventsProvider({ value, children }) {
|
|
10814
|
-
return /* @__PURE__ */ (0,
|
|
11204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(SlipStateContext.Provider, { value: value.slipState, children });
|
|
10815
11205
|
}
|
|
10816
11206
|
|
|
10817
11207
|
// src/styles/css.generated.ts
|
|
@@ -10822,7 +11212,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
10822
11212
|
--ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;
|
|
10823
11213
|
--ss-w-ink: #14181d; --ss-w-faint: #6b7580; --ss-w-line: #e4e8ec;
|
|
10824
11214
|
--ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;
|
|
10825
|
-
--ss-w-pos: #1aa563; --ss-w-neg: #e0524b;
|
|
11215
|
+
--ss-w-pos: #1aa563; --ss-w-neg: #e0524b; --ss-w-warn: #c07a00;
|
|
10826
11216
|
--ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;
|
|
10827
11217
|
--ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;
|
|
10828
11218
|
--ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;
|
|
@@ -10834,7 +11224,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
10834
11224
|
--ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;
|
|
10835
11225
|
--ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;
|
|
10836
11226
|
--ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;
|
|
10837
|
-
--ss-w-pos: #37c891; --ss-w-neg: #f0655d;
|
|
11227
|
+
--ss-w-pos: #37c891; --ss-w-neg: #f0655d; --ss-w-warn: #e0a030;
|
|
10838
11228
|
--ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;
|
|
10839
11229
|
--ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;
|
|
10840
11230
|
}
|
|
@@ -10843,7 +11233,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
10843
11233
|
--ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;
|
|
10844
11234
|
--ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;
|
|
10845
11235
|
--ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;
|
|
10846
|
-
--ss-w-pos: #37c891; --ss-w-neg: #f0655d;
|
|
11236
|
+
--ss-w-pos: #37c891; --ss-w-neg: #f0655d; --ss-w-warn: #e0a030;
|
|
10847
11237
|
--ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;
|
|
10848
11238
|
--ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;
|
|
10849
11239
|
}
|
|
@@ -11974,7 +12364,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
11974
12364
|
.ss-w-sq-name { font-size: 13px; font-weight: 600; color: var(--ss-w-ink); }
|
|
11975
12365
|
.ss-w-sq-name { flex: 1; min-width: 0; }
|
|
11976
12366
|
.ss-w-sq-name-1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
11977
|
-
.ss-w-sq-seg { display: flex;
|
|
12367
|
+
.ss-w-sq-seg { display: flex; gap: 2px; padding: 2px; border-radius: var(--ss-w-radius); background: var(--ss-w-track); }
|
|
11978
12368
|
.ss-w-sq-seg-btn { flex: 1; padding: 5px 8px; border: 0; border-radius: calc(var(--ss-w-radius) - 2px); background: transparent; font: inherit; font-size: 12px; font-weight: 600; color: var(--ss-w-faint); cursor: pointer; }
|
|
11979
12369
|
.ss-w-sq-seg-btn[aria-pressed="true"] { background: var(--ss-w-panel); color: var(--ss-w-ink); }
|
|
11980
12370
|
.ss-w-sq-seg-btn:focus-visible, .ss-w-sq-tap:focus-visible, .ss-w-pd-back:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 1px; }
|
|
@@ -11982,15 +12372,95 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
11982
12372
|
.ss-w-sq-col { flex: none; width: 40px; text-align: center; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
11983
12373
|
.ss-w-sq-head { border-bottom: 0; padding-bottom: 0; }
|
|
11984
12374
|
.ss-w-sq-head .ss-w-sq-col { font-size: 10px; font-weight: 700; color: var(--ss-w-faint); }
|
|
11985
|
-
.ss-w-
|
|
11986
|
-
.ss-w-
|
|
11987
|
-
.ss-w-
|
|
11988
|
-
.ss-w-
|
|
11989
|
-
.ss-w-
|
|
11990
|
-
.ss-w-
|
|
11991
|
-
.ss-w-
|
|
11992
|
-
.ss-w-
|
|
11993
|
-
.ss-w-
|
|
12375
|
+
.ss-w-sq-stats { padding-top: 10px; gap: 10px; }
|
|
12376
|
+
.ss-w-sq-card { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; }
|
|
12377
|
+
.ss-w-sq-stats .ss-w-sq-row { display: grid; grid-template-columns: 1fr 26px 30px 36px 20px 20px 20px 20px 36px; gap: 0; padding: 7px 10px; font-size: 11px; }
|
|
12378
|
+
.ss-w-sq-card > :last-child { border-bottom: 0; }
|
|
12379
|
+
.ss-w-sq-pos, .ss-w-sq-c20, .ss-w-sq-c30, .ss-w-sq-c36 { text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 11px; font-weight: 400; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
12380
|
+
.ss-w-sq-stats .ss-w-sq-head { padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: var(--ss-w-faint); }
|
|
12381
|
+
.ss-w-sq-stats .ss-w-sq-head > span { font-size: 9px; font-weight: 700; color: var(--ss-w-faint); }
|
|
12382
|
+
.ss-w-sq-player { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
12383
|
+
.ss-w-sq-badge { flex: none; width: 18px; height: 18px; border-radius: 6px; background: var(--ss-w-track); color: var(--ss-w-faint); font-size: 9px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
|
|
12384
|
+
.ss-w-sq-stats .ss-w-sq-name { font-size: 11px; }
|
|
12385
|
+
.ss-w-sq-rtg { font-weight: 700; }
|
|
12386
|
+
.ss-w-sq-rtg-none { color: var(--ss-w-faint); font-weight: 400; }
|
|
12387
|
+
.ss-w-sq-stats .ss-w-pos-ink { color: var(--ss-w-pos); font-weight: 700; }
|
|
12388
|
+
.ss-w-sq-foot { padding: 0 2px; font-size: 10.5px; color: var(--ss-w-faint); }
|
|
12389
|
+
.ss-w-sq-bar { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 10px 14px 0; }
|
|
12390
|
+
.ss-w-sq-bar .ss-w-sq-seg { margin: 0; }
|
|
12391
|
+
.ss-w-sq-bar .ss-w-sq-seg:only-child { flex: 1; }
|
|
12392
|
+
.ss-w-sq-bar .ss-w-sq-seg:not(:only-child) { flex: none; }
|
|
12393
|
+
.ss-w-sq-eyebrow { flex: 1; min-width: 0; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); }
|
|
12394
|
+
@media (max-width: 429px) { .ss-w-sq-badge { display: none; } }
|
|
12395
|
+
@media (max-width: 359px) {
|
|
12396
|
+
.ss-w-sq-yr { display: none; }
|
|
12397
|
+
.ss-w-sq-stats .ss-w-sq-row { grid-template-columns: 1fr 26px 30px 36px 20px 20px 36px; }
|
|
12398
|
+
}
|
|
12399
|
+
.ss-w-pd-bar { flex: none; display: flex; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--ss-w-line); line-height: normal; }
|
|
12400
|
+
.ss-w-pd-back { display: flex; align-items: center; gap: 2px; min-height: 32px; padding: 8px 8px 8px 0; margin: -8px 0; border: 0; background: transparent; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ss-w-faint); cursor: pointer; }
|
|
12401
|
+
.ss-w-pd-back:hover { color: var(--ss-w-ink); }
|
|
12402
|
+
.ss-w-mon-list.ss-w-pd-list { padding: 16px; gap: 14px; line-height: normal; }
|
|
12403
|
+
.ss-w-pd-card { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; }
|
|
12404
|
+
.ss-w-pd-faint { color: var(--ss-w-faint); }
|
|
12405
|
+
.ss-w-pd-profile { display: flex; gap: 12px; padding: 14px; }
|
|
12406
|
+
.ss-w-pd-photo { flex: none; border-radius: 50%; border: 1px solid var(--ss-w-line); background: var(--ss-w-bubble); object-fit: cover; }
|
|
12407
|
+
.ss-w-pd-avatar { display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--ss-w-ink); }
|
|
12408
|
+
.ss-w-pd-profile-main { flex: 1; min-width: 0; }
|
|
12409
|
+
.ss-w-pd-name { font-size: 16px; font-weight: 800; color: var(--ss-w-ink); overflow-wrap: break-word; }
|
|
12410
|
+
.ss-w-pd-sub { margin-top: 1px; font-size: 12px; color: var(--ss-w-faint); }
|
|
12411
|
+
/* Two columns as on the board, collapsing to one when a column would drop under 80px (narrow phones). */
|
|
12412
|
+
.ss-w-pd-bio { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(80px, calc((100% - 10px) / 2)), 1fr)); gap: 4px 10px; margin-top: 10px; font-size: 11.5px; }
|
|
12413
|
+
.ss-w-pd-bio-item { min-width: 0; overflow-wrap: break-word; }
|
|
12414
|
+
.ss-w-pd-pitch { position: relative; flex: none; width: 56px; height: 76px; border: 1px solid var(--ss-w-line); border-radius: 6px; background: var(--ss-w-track); }
|
|
12415
|
+
.ss-w-pd-pitch-dot { position: absolute; width: 11px; height: 11px; border-radius: 50%; background: var(--ss-w-accent); border: 2px solid var(--ss-w-nav); transform: translate(-50%, -50%); }
|
|
12416
|
+
.ss-w-pd-avail { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 14px; }
|
|
12417
|
+
.ss-w-pd-avail-text { min-width: 0; }
|
|
12418
|
+
.ss-w-pd-avail-next { font-size: 12.5px; font-weight: 700; }
|
|
12419
|
+
.ss-w-pd-avail-note { margin-top: 1px; font-size: 11px; color: var(--ss-w-faint); }
|
|
12420
|
+
.ss-w-pd-pill { flex: none; padding: 4px 10px; border-radius: 999px; font-size: 11px; font-weight: 700; white-space: nowrap; }
|
|
12421
|
+
.ss-w-pd-pill--pos, .ss-w-pd-chip--pos { background: color-mix(in srgb, var(--ss-w-pos) 14%, transparent); color: var(--ss-w-pos); }
|
|
12422
|
+
.ss-w-pd-pill--warn, .ss-w-pd-chip--warn { background: color-mix(in srgb, var(--ss-w-warn) 14%, transparent); color: var(--ss-w-warn); }
|
|
12423
|
+
.ss-w-pd-pill--neg, .ss-w-pd-chip--neg { background: color-mix(in srgb, var(--ss-w-neg) 14%, transparent); color: var(--ss-w-neg); }
|
|
12424
|
+
.ss-w-pd-pill--draw { background: var(--ss-w-track); color: var(--ss-w-faint); }
|
|
12425
|
+
.ss-w-pd-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding: 0 2px; }
|
|
12426
|
+
.ss-w-pd-eyebrow--block { margin-bottom: 8px; }
|
|
12427
|
+
.ss-w-pd-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
|
|
12428
|
+
.ss-w-pd-tile { min-width: 0; padding: 10px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; }
|
|
12429
|
+
.ss-w-pd-tile-label { font-size: 10.5px; color: var(--ss-w-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
12430
|
+
.ss-w-pd-tile-value { margin-top: 2px; font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; }
|
|
12431
|
+
.ss-w-pd-pos-ink { color: var(--ss-w-pos); }
|
|
12432
|
+
/* Below 360px the board's 10px tile padding clips "Matches"/"Minutes" (43px) in a ~34px label box. */
|
|
12433
|
+
@media (max-width: 359px) {
|
|
12434
|
+
.ss-w-pd-tiles { gap: 6px; }
|
|
12435
|
+
.ss-w-pd-tile { padding: 10px 6px; }
|
|
12436
|
+
}
|
|
12437
|
+
.ss-w-pd-perf-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 2px; }
|
|
12438
|
+
.ss-w-pd-perf-head .ss-w-pd-eyebrow { flex: 1; min-width: 0; }
|
|
12439
|
+
.ss-w-pd-seg { flex: none; display: flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--ss-w-track); }
|
|
12440
|
+
.ss-w-pd-seg-btn { padding: 5px 12px; border: 0; border-radius: 999px; background: transparent; font: inherit; font-size: 11.5px; font-weight: 700; line-height: normal; white-space: nowrap; color: var(--ss-w-faint); cursor: pointer; }
|
|
12441
|
+
.ss-w-pd-seg-btn[aria-pressed="true"] { background: var(--ss-w-nav); color: #fff; }
|
|
12442
|
+
.ss-w-pd-seg-btn:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 1px; }
|
|
12443
|
+
.ss-w-pd-perf-sub { margin-bottom: 10px; font-size: 11px; color: var(--ss-w-faint); }
|
|
12444
|
+
.ss-w-pd-perf-head + .ss-w-pd-perf-cards { margin-top: 10px; }
|
|
12445
|
+
.ss-w-pd-perf-cards { display: flex; flex-direction: column; gap: 8px; }
|
|
12446
|
+
.ss-w-pd-perf-card { padding: 14px; }
|
|
12447
|
+
.ss-w-pd-perf-group { margin-bottom: 10px; font-size: 12.5px; font-weight: 700; }
|
|
12448
|
+
.ss-w-pd-bar-row + .ss-w-pd-bar-row { margin-top: 12px; }
|
|
12449
|
+
.ss-w-pd-bar-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 5px; font-size: 12.5px; }
|
|
12450
|
+
.ss-w-pd-bar-label { min-width: 0; overflow-wrap: break-word; }
|
|
12451
|
+
.ss-w-pd-bar-value { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }
|
|
12452
|
+
.ss-w-pd-track { height: 6px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; }
|
|
12453
|
+
.ss-w-pd-fill { height: 100%; border-radius: 999px; }
|
|
12454
|
+
.ss-w-pd-fill--pos { background: var(--ss-w-pos); }
|
|
12455
|
+
.ss-w-pd-fill--warn { background: var(--ss-w-warn); }
|
|
12456
|
+
.ss-w-pd-fill--neg { background: var(--ss-w-neg); }
|
|
12457
|
+
.ss-w-pd-match { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto auto; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ss-w-line); }
|
|
12458
|
+
.ss-w-pd-match:last-child { border-bottom: none; }
|
|
12459
|
+
.ss-w-pd-match-date { font-size: 10.5px; color: var(--ss-w-faint); }
|
|
12460
|
+
.ss-w-pd-match-opp { font-size: 12.5px; font-weight: 600; overflow-wrap: break-word; }
|
|
12461
|
+
.ss-w-pd-match-sub { margin-top: 1px; font-size: 10.5px; color: var(--ss-w-faint); }
|
|
12462
|
+
.ss-w-pd-chip-empty { min-width: 30px; }
|
|
12463
|
+
.ss-w-pd-chip { min-width: 30px; padding: 3px 0; border-radius: 6px; text-align: center; font-size: 11.5px; font-weight: 800; font-variant-numeric: tabular-nums; }
|
|
11994
12464
|
.ss-w-rec-list { margin: 0; padding: 0; list-style: none; }
|
|
11995
12465
|
.ss-w-rec-value { flex: none; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
11996
12466
|
.ss-w-rec-since { font-size: 12px; color: var(--ss-w-faint); }
|
|
@@ -12597,7 +13067,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
12597
13067
|
`;
|
|
12598
13068
|
|
|
12599
13069
|
// src/StatsWidget.tsx
|
|
12600
|
-
var
|
|
13070
|
+
var import_jsx_runtime107 = require("react/jsx-runtime");
|
|
12601
13071
|
function buildClient(props) {
|
|
12602
13072
|
try {
|
|
12603
13073
|
if ("client" in props && props.client) {
|
|
@@ -12622,24 +13092,24 @@ function injectStyles(root) {
|
|
|
12622
13092
|
function StatsWidget(props) {
|
|
12623
13093
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
12624
13094
|
const cfg = props.config;
|
|
12625
|
-
const built = (0,
|
|
12626
|
-
const logger = (0,
|
|
13095
|
+
const built = (0, import_react69.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
13096
|
+
const logger = (0, import_react69.useMemo)(
|
|
12627
13097
|
() => built ? built.client.createEventLogger({
|
|
12628
13098
|
operatorUserId: cfg?.userContext?.operatorUserId,
|
|
12629
13099
|
anonymousUserId: cfg?.userContext?.anonymousUserId
|
|
12630
13100
|
}) : null,
|
|
12631
13101
|
[built?.client]
|
|
12632
13102
|
);
|
|
12633
|
-
const ui = (0,
|
|
12634
|
-
const rootRef = (0,
|
|
12635
|
-
const introDoneRef = (0,
|
|
12636
|
-
const markIntroDone = (0,
|
|
13103
|
+
const ui = (0, import_react69.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
13104
|
+
const rootRef = (0, import_react69.useRef)(null);
|
|
13105
|
+
const introDoneRef = (0, import_react69.useRef)(false);
|
|
13106
|
+
const markIntroDone = (0, import_react69.useCallback)(() => {
|
|
12637
13107
|
introDoneRef.current = true;
|
|
12638
13108
|
}, []);
|
|
12639
13109
|
const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
|
|
12640
13110
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
|
|
12641
|
-
const [hasToday, setHasToday] = (0,
|
|
12642
|
-
const liveCardWatches = (0,
|
|
13111
|
+
const [hasToday, setHasToday] = (0, import_react69.useState)(false);
|
|
13112
|
+
const liveCardWatches = (0, import_react69.useMemo)(() => {
|
|
12643
13113
|
const seen = /* @__PURE__ */ new Set();
|
|
12644
13114
|
const out = [];
|
|
12645
13115
|
for (const msg of controller.state.messages) {
|
|
@@ -12665,19 +13135,19 @@ function StatsWidget(props) {
|
|
|
12665
13135
|
});
|
|
12666
13136
|
const operatorUserId = cfg?.userContext?.operatorUserId;
|
|
12667
13137
|
const anonymousUserId = cfg?.userContext?.anonymousUserId;
|
|
12668
|
-
const getSchedule = (0,
|
|
13138
|
+
const getSchedule = (0, import_react69.useCallback)(
|
|
12669
13139
|
(localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) : Promise.resolve(null),
|
|
12670
13140
|
[built, operatorUserId, anonymousUserId]
|
|
12671
13141
|
);
|
|
12672
|
-
const postLeagueStar = (0,
|
|
13142
|
+
const postLeagueStar = (0, import_react69.useCallback)(
|
|
12673
13143
|
(competitionId, starred) => built ? built.conversation.starLeague(competitionId, starred, operatorUserId, anonymousUserId) : Promise.resolve(null),
|
|
12674
13144
|
[built, operatorUserId, anonymousUserId]
|
|
12675
13145
|
);
|
|
12676
|
-
const getStates = (0,
|
|
13146
|
+
const getStates = (0, import_react69.useCallback)(
|
|
12677
13147
|
(matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
|
|
12678
13148
|
[built]
|
|
12679
13149
|
);
|
|
12680
|
-
const pinnedMatchIds = (0,
|
|
13150
|
+
const pinnedMatchIds = (0, import_react69.useMemo)(
|
|
12681
13151
|
() => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
|
|
12682
13152
|
[monitor.pins]
|
|
12683
13153
|
);
|
|
@@ -12692,11 +13162,11 @@ function StatsWidget(props) {
|
|
|
12692
13162
|
pinnedMatchIds
|
|
12693
13163
|
});
|
|
12694
13164
|
const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
|
|
12695
|
-
(0,
|
|
13165
|
+
(0, import_react69.useEffect)(() => {
|
|
12696
13166
|
setHasToday(todayHasContent);
|
|
12697
13167
|
}, [todayHasContent]);
|
|
12698
|
-
const prevLiveSnapshotRef = (0,
|
|
12699
|
-
(0,
|
|
13168
|
+
const prevLiveSnapshotRef = (0, import_react69.useRef)(monitor.snapshot);
|
|
13169
|
+
(0, import_react69.useEffect)(() => {
|
|
12700
13170
|
const snap = monitor.snapshot;
|
|
12701
13171
|
if (!snap || snap === prevLiveSnapshotRef.current) return;
|
|
12702
13172
|
prevLiveSnapshotRef.current = snap;
|
|
@@ -12736,14 +13206,14 @@ function StatsWidget(props) {
|
|
|
12736
13206
|
const clubSquadResult = useClubSquad(built?.conversation ?? null, { activeTab: monitor.activeTab, enabled: clubFixturesResult.enabled });
|
|
12737
13207
|
const clubSquadStatsResult = useClubSquadStats(built?.conversation ?? null, { activeTab: monitor.activeTab, enabled: clubFixturesResult.enabled });
|
|
12738
13208
|
const clubPlayerDetailResult = useClubPlayerDetail(built?.conversation ?? null);
|
|
12739
|
-
const getPricePresets = (0,
|
|
13209
|
+
const getPricePresets = (0, import_react69.useCallback)(
|
|
12740
13210
|
(locale2) => built ? built.conversation.getPricePresets(locale2, { pool: "open" }) : Promise.resolve(null),
|
|
12741
13211
|
[built]
|
|
12742
13212
|
);
|
|
12743
13213
|
const presetGrid = usePresetGrid({ getPricePresets, isOpen: controller.state.isOpen, locale: ui.presets.lang });
|
|
12744
13214
|
const markTodayActivity = monitor.markTodayActivity;
|
|
12745
|
-
const prevLiveCountRef = (0,
|
|
12746
|
-
(0,
|
|
13215
|
+
const prevLiveCountRef = (0, import_react69.useRef)(0);
|
|
13216
|
+
(0, import_react69.useEffect)(() => {
|
|
12747
13217
|
const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
|
|
12748
13218
|
prevLiveCountRef.current = discovery.liveCount;
|
|
12749
13219
|
if (rose) markTodayActivity();
|
|
@@ -12757,7 +13227,7 @@ function StatsWidget(props) {
|
|
|
12757
13227
|
closePanel: controller.close
|
|
12758
13228
|
});
|
|
12759
13229
|
const markAdded = hostEvents.markAdded;
|
|
12760
|
-
const slip = (0,
|
|
13230
|
+
const slip = (0, import_react69.useMemo)(
|
|
12761
13231
|
() => {
|
|
12762
13232
|
const handler = props.config?.onAddToSlip;
|
|
12763
13233
|
return {
|
|
@@ -12776,7 +13246,7 @@ function StatsWidget(props) {
|
|
|
12776
13246
|
},
|
|
12777
13247
|
[props.config?.onAddToSlip, controller.state.conversationId, markAdded]
|
|
12778
13248
|
);
|
|
12779
|
-
const onDashboardTap = (0,
|
|
13249
|
+
const onDashboardTap = (0, import_react69.useMemo)(
|
|
12780
13250
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
|
|
12781
13251
|
[built, logger]
|
|
12782
13252
|
);
|
|
@@ -12793,11 +13263,11 @@ function StatsWidget(props) {
|
|
|
12793
13263
|
})
|
|
12794
13264
|
}));
|
|
12795
13265
|
const conversationId = controller.state.conversationId ?? void 0;
|
|
12796
|
-
(0,
|
|
13266
|
+
(0, import_react69.useEffect)(() => {
|
|
12797
13267
|
if (!logger) return;
|
|
12798
13268
|
logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
|
|
12799
13269
|
}, [logger, operatorUserId, anonymousUserId, conversationId]);
|
|
12800
|
-
(0,
|
|
13270
|
+
(0, import_react69.useEffect)(() => {
|
|
12801
13271
|
if (!logger) return;
|
|
12802
13272
|
logger.resume();
|
|
12803
13273
|
const onHide = () => {
|
|
@@ -12815,14 +13285,14 @@ function StatsWidget(props) {
|
|
|
12815
13285
|
logger.dispose();
|
|
12816
13286
|
};
|
|
12817
13287
|
}, [logger]);
|
|
12818
|
-
(0,
|
|
13288
|
+
(0, import_react69.useEffect)(() => {
|
|
12819
13289
|
if (!built || !ui.injectStyles) return;
|
|
12820
13290
|
const node = rootRef.current?.getRootNode();
|
|
12821
13291
|
if (node) injectStyles(node);
|
|
12822
13292
|
}, [built, ui.injectStyles]);
|
|
12823
13293
|
if (!built) return null;
|
|
12824
13294
|
const attrs = themeAttrs(ui);
|
|
12825
|
-
return /* @__PURE__ */ (0,
|
|
13295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(HostEventsProvider, { value: hostEvents, children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("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__ */ (0, import_jsx_runtime107.jsx)(
|
|
12826
13296
|
ChatPanel,
|
|
12827
13297
|
{
|
|
12828
13298
|
controller,
|
|
@@ -12842,7 +13312,7 @@ function StatsWidget(props) {
|
|
|
12842
13312
|
conversation: built?.conversation ?? null,
|
|
12843
13313
|
presetGrid
|
|
12844
13314
|
}
|
|
12845
|
-
) : /* @__PURE__ */ (0,
|
|
13315
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12846
13316
|
ChatFab,
|
|
12847
13317
|
{
|
|
12848
13318
|
label: ui.launcherLabel,
|