@sensiblestats/widget-react 0.18.0 → 0.20.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 +17 -0
- package/dist/index.cjs +348 -285
- 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 +291 -228
- package/dist/index.js.map +1 -1
- package/dist/styles.css +24 -22
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/StatsWidget.tsx
|
|
39
|
-
var
|
|
39
|
+
var import_react13 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/kickoff.ts
|
|
@@ -472,7 +472,13 @@ function toMarketOddsVM(card) {
|
|
|
472
472
|
id: `${typeof card.matchId === "number" ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ""}`,
|
|
473
473
|
market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? "",
|
|
474
474
|
fixture: home && away ? `${home} vs ${away}` : void 0,
|
|
475
|
+
homeTeamName: home,
|
|
476
|
+
awayTeamName: away,
|
|
477
|
+
homeCrest: str(card.homeTeamImagePath),
|
|
478
|
+
awayCrest: str(card.awayTeamImagePath),
|
|
479
|
+
competitionCrest: str(card.competitionImagePath),
|
|
475
480
|
competition: str(card.competitionName),
|
|
481
|
+
kickoffUtc: str(card.kickoffUtc),
|
|
476
482
|
bookmaker: rows.map((r) => str(r.bookmakerName)).find(Boolean),
|
|
477
483
|
updatedAt: updated.length > 0 ? updated[updated.length - 1] : void 0,
|
|
478
484
|
isLive: rows.some((r) => r.isLive === true),
|
|
@@ -619,21 +625,42 @@ function reducer(state, action) {
|
|
|
619
625
|
}
|
|
620
626
|
|
|
621
627
|
// src/useChatStream.ts
|
|
628
|
+
var STREAM_FALLBACK_TIMEOUT_MS = 3e4;
|
|
622
629
|
function useChatStream(conversation, starterTexts, greetingMessage) {
|
|
623
630
|
const seed = (0, import_react.useMemo)(() => initialState(starterTexts.map(chipFromText)), []);
|
|
624
631
|
const [state, dispatch] = (0, import_react.useReducer)(reducer, seed);
|
|
625
632
|
const idRef = (0, import_react.useRef)(0);
|
|
626
633
|
const handleRef = (0, import_react.useRef)(null);
|
|
634
|
+
const fallbackTimerRef = (0, import_react.useRef)(null);
|
|
627
635
|
const stateRef = (0, import_react.useRef)(state);
|
|
628
636
|
stateRef.current = state;
|
|
629
637
|
const greetedRef = (0, import_react.useRef)(false);
|
|
630
638
|
const nextId = () => `m${idRef.current++}`;
|
|
639
|
+
const clearFallbackTimer = (0, import_react.useCallback)(() => {
|
|
640
|
+
if (fallbackTimerRef.current != null) {
|
|
641
|
+
clearTimeout(fallbackTimerRef.current);
|
|
642
|
+
fallbackTimerRef.current = null;
|
|
643
|
+
}
|
|
644
|
+
}, []);
|
|
645
|
+
const armFallbackTimer = (0, import_react.useCallback)((onFire) => {
|
|
646
|
+
clearFallbackTimer();
|
|
647
|
+
fallbackTimerRef.current = setTimeout(() => {
|
|
648
|
+
fallbackTimerRef.current = null;
|
|
649
|
+
handleRef.current?.cancel();
|
|
650
|
+
handleRef.current = null;
|
|
651
|
+
onFire();
|
|
652
|
+
}, STREAM_FALLBACK_TIMEOUT_MS);
|
|
653
|
+
}, [clearFallbackTimer]);
|
|
631
654
|
const consume = (0, import_react.useCallback)((handle, onError) => {
|
|
632
655
|
;
|
|
633
656
|
(async () => {
|
|
634
657
|
try {
|
|
635
|
-
for await (const event of handle)
|
|
658
|
+
for await (const event of handle) {
|
|
659
|
+
dispatch({ kind: "EVENT", event });
|
|
660
|
+
if (event.type === "turn_complete" || event.type === "error") clearFallbackTimer();
|
|
661
|
+
}
|
|
636
662
|
} catch (err) {
|
|
663
|
+
if (handleRef.current === handle) clearFallbackTimer();
|
|
637
664
|
if (err instanceof import_widget_sdk3.WidgetSdkError) onError(err);
|
|
638
665
|
else if (err?.name === "AbortError") {
|
|
639
666
|
} else throw err;
|
|
@@ -641,18 +668,23 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
|
|
|
641
668
|
if (handleRef.current === handle) handleRef.current = null;
|
|
642
669
|
}
|
|
643
670
|
})();
|
|
644
|
-
}, []);
|
|
671
|
+
}, [clearFallbackTimer]);
|
|
645
672
|
const run = (0, import_react.useCallback)((input, displayText) => {
|
|
646
673
|
handleRef.current?.cancel();
|
|
674
|
+
clearFallbackTimer();
|
|
647
675
|
dispatch({ kind: "USER_SENT", input, userId: nextId(), assistantId: nextId(), displayText });
|
|
648
676
|
const handle = conversation.send(input);
|
|
649
677
|
handleRef.current = handle;
|
|
678
|
+
armFallbackTimer(() => {
|
|
679
|
+
dispatch({ kind: "STOP" });
|
|
680
|
+
dispatch({ kind: "STREAM_ERROR", error: new import_widget_sdk3.WidgetSdkError("No response received in time", "timeout") });
|
|
681
|
+
});
|
|
650
682
|
consume(handle, (err) => dispatch({ kind: "STREAM_ERROR", error: err }));
|
|
651
|
-
}, [conversation, consume]);
|
|
683
|
+
}, [conversation, consume, clearFallbackTimer, armFallbackTimer]);
|
|
652
684
|
const send = (0, import_react.useCallback)((text, opts) => {
|
|
653
685
|
const trimmed = text.trim();
|
|
654
686
|
if (!trimmed) return;
|
|
655
|
-
run({ message: trimmed, actionId: opts?.actionId,
|
|
687
|
+
run({ message: trimmed, actionId: opts?.actionId, actionRef: opts?.actionRef }, opts?.displayText);
|
|
656
688
|
}, [run]);
|
|
657
689
|
const retry = (0, import_react.useCallback)(() => {
|
|
658
690
|
const last = stateRef.current.lastUserInput;
|
|
@@ -664,25 +696,29 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
|
|
|
664
696
|
greetedRef.current = true;
|
|
665
697
|
try {
|
|
666
698
|
handleRef.current?.cancel();
|
|
699
|
+
clearFallbackTimer();
|
|
667
700
|
dispatch({ kind: "GREETING_SENT", assistantId: nextId() });
|
|
668
701
|
const handle = conversation.send({ message });
|
|
669
702
|
handleRef.current = handle;
|
|
703
|
+
armFallbackTimer(() => dispatch({ kind: "STOP" }));
|
|
670
704
|
consume(handle, () => dispatch({ kind: "STOP" }));
|
|
671
705
|
} catch {
|
|
672
706
|
dispatch({ kind: "STOP" });
|
|
673
707
|
}
|
|
674
|
-
}, [greetingMessage, conversation, consume]);
|
|
708
|
+
}, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer]);
|
|
675
709
|
const open = (0, import_react.useCallback)(() => dispatch({ kind: "OPEN" }), []);
|
|
676
710
|
const close = (0, import_react.useCallback)(() => {
|
|
677
711
|
handleRef.current?.cancel();
|
|
678
712
|
handleRef.current = null;
|
|
713
|
+
clearFallbackTimer();
|
|
679
714
|
dispatch({ kind: "CLOSE" });
|
|
680
|
-
}, []);
|
|
715
|
+
}, [clearFallbackTimer]);
|
|
681
716
|
const stop = (0, import_react.useCallback)(() => {
|
|
682
717
|
handleRef.current?.cancel();
|
|
683
718
|
handleRef.current = null;
|
|
719
|
+
clearFallbackTimer();
|
|
684
720
|
dispatch({ kind: "STOP" });
|
|
685
|
-
}, []);
|
|
721
|
+
}, [clearFallbackTimer]);
|
|
686
722
|
const toggle = (0, import_react.useCallback)(() => {
|
|
687
723
|
if (stateRef.current.isOpen) close();
|
|
688
724
|
else open();
|
|
@@ -748,7 +784,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
748
784
|
}
|
|
749
785
|
|
|
750
786
|
// src/components/ChatPanel.tsx
|
|
751
|
-
var
|
|
787
|
+
var import_react12 = require("react");
|
|
752
788
|
|
|
753
789
|
// src/components/ChatHeader.tsx
|
|
754
790
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -761,7 +797,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
761
797
|
}
|
|
762
798
|
|
|
763
799
|
// src/components/MessageList.tsx
|
|
764
|
-
var
|
|
800
|
+
var import_react10 = require("react");
|
|
765
801
|
|
|
766
802
|
// src/components/Markdown.tsx
|
|
767
803
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -881,7 +917,7 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
881
917
|
}
|
|
882
918
|
|
|
883
919
|
// src/components/BettingInsightList.tsx
|
|
884
|
-
var
|
|
920
|
+
var import_react6 = require("react");
|
|
885
921
|
|
|
886
922
|
// src/components/AddToSlipButton.tsx
|
|
887
923
|
var import_react4 = require("react");
|
|
@@ -1004,53 +1040,64 @@ function OddsMovementBadge({
|
|
|
1004
1040
|
] });
|
|
1005
1041
|
}
|
|
1006
1042
|
|
|
1007
|
-
// src/components/
|
|
1043
|
+
// src/components/Crest.tsx
|
|
1044
|
+
var import_react5 = require("react");
|
|
1008
1045
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1046
|
+
function initials2(name) {
|
|
1047
|
+
return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
|
|
1048
|
+
}
|
|
1049
|
+
function Crest2({ url, name, kind }) {
|
|
1050
|
+
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
1051
|
+
const [failed, setFailed] = (0, import_react5.useState)(false);
|
|
1052
|
+
if (url && !failed) {
|
|
1053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1054
|
+
}
|
|
1055
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// src/components/BettingInsightList.tsx
|
|
1059
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1009
1060
|
function StatRows2({ stats }) {
|
|
1010
|
-
return /* @__PURE__ */ (0,
|
|
1011
|
-
/* @__PURE__ */ (0,
|
|
1012
|
-
/* @__PURE__ */ (0,
|
|
1061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-row", children: [
|
|
1062
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
1063
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
1013
1064
|
] }, `${s.label}:${s.value}`)) });
|
|
1014
1065
|
}
|
|
1015
1066
|
function ScopedStats({ scopes }) {
|
|
1016
|
-
const [active, setActive] = (0,
|
|
1067
|
+
const [active, setActive] = (0, import_react6.useState)(0);
|
|
1017
1068
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
1018
|
-
return /* @__PURE__ */ (0,
|
|
1019
|
-
/* @__PURE__ */ (0,
|
|
1020
|
-
/* @__PURE__ */ (0,
|
|
1069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-scoped", children: [
|
|
1070
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StatRows2, { stats: current.stats }, current.key)
|
|
1021
1072
|
] });
|
|
1022
1073
|
}
|
|
1023
1074
|
function hasStatsContent(it) {
|
|
1024
1075
|
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
1025
1076
|
}
|
|
1026
|
-
function
|
|
1027
|
-
|
|
1028
|
-
}
|
|
1029
|
-
function Crest2({ url, name, kind }) {
|
|
1030
|
-
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
1031
|
-
if (url) return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cls, style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" });
|
|
1032
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
|
|
1033
|
-
}
|
|
1034
|
-
function StatsDisclosure({ it, ui }) {
|
|
1035
|
-
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
1077
|
+
function ReasonStrip({ it, ui }) {
|
|
1078
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
1036
1079
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
1037
1080
|
const hasStats = hasStatsContent(it);
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1081
|
+
const hasText = !!it.text;
|
|
1082
|
+
if (!hasText && !hasStats) return null;
|
|
1083
|
+
const expandable = hasStats || (it.text?.length ?? 0) > 90;
|
|
1084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-reason", children: [
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-reason-body", children: [
|
|
1087
|
+
hasText ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
|
|
1088
|
+
open && hasStats ? hasScopes ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StatRows2, { stats: it.stats }) : null
|
|
1089
|
+
] }),
|
|
1090
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1041
1091
|
"button",
|
|
1042
1092
|
{
|
|
1043
1093
|
type: "button",
|
|
1044
|
-
className: "ss-w-bi-
|
|
1094
|
+
className: "ss-w-bi-expand",
|
|
1045
1095
|
"aria-expanded": open,
|
|
1096
|
+
"aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
|
|
1046
1097
|
onClick: () => setOpen((v) => !v),
|
|
1047
|
-
children:
|
|
1048
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats" }),
|
|
1049
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
|
|
1050
|
-
]
|
|
1098
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
|
|
1051
1099
|
}
|
|
1052
|
-
)
|
|
1053
|
-
open ? hasScopes ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StatRows2, { stats: it.stats }) : null
|
|
1100
|
+
) : null
|
|
1054
1101
|
] });
|
|
1055
1102
|
}
|
|
1056
1103
|
function InsightCard({ it, ui, slip }) {
|
|
@@ -1058,105 +1105,119 @@ function InsightCard({ it, ui, slip }) {
|
|
|
1058
1105
|
const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : void 0;
|
|
1059
1106
|
const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName;
|
|
1060
1107
|
const showHeader = !!it.competition || live || !!kickoff;
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
/* @__PURE__ */ (0,
|
|
1066
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-comp", children: it.competition })
|
|
1108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-binsight", children: [
|
|
1109
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-header", children: [
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-header-left", children: it.competition ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
1111
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
|
|
1112
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-comp", children: it.competition })
|
|
1067
1113
|
] }) : null }),
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1069
|
-
live ? /* @__PURE__ */ (0,
|
|
1070
|
-
/* @__PURE__ */ (0,
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-header-right", children: [
|
|
1115
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-live", children: [
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1071
1117
|
ui?.liveLabel ?? "Live"
|
|
1072
1118
|
] }) : null,
|
|
1073
|
-
kickoff ? /* @__PURE__ */ (0,
|
|
1119
|
+
kickoff ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-kick", children: [
|
|
1074
1120
|
kickoff.dayLabel,
|
|
1075
1121
|
" ",
|
|
1076
1122
|
kickoff.time
|
|
1077
1123
|
] }) : null
|
|
1078
1124
|
] })
|
|
1079
1125
|
] }) : null,
|
|
1080
|
-
/* @__PURE__ */ (0,
|
|
1081
|
-
/* @__PURE__ */ (0,
|
|
1082
|
-
/* @__PURE__ */ (0,
|
|
1083
|
-
/* @__PURE__ */ (0,
|
|
1084
|
-
/* @__PURE__ */ (0,
|
|
1085
|
-
/* @__PURE__ */ (0,
|
|
1086
|
-
/* @__PURE__ */ (0,
|
|
1087
|
-
] }) : it.fixture ? /* @__PURE__ */ (0,
|
|
1088
|
-
/* @__PURE__ */ (0,
|
|
1089
|
-
/* @__PURE__ */ (0,
|
|
1090
|
-
/* @__PURE__ */ (0,
|
|
1091
|
-
it.selection ? /* @__PURE__ */ (0,
|
|
1126
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-body", children: [
|
|
1127
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-bi-fixture", children: hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
1128
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
|
|
1130
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1131
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
|
|
1132
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
|
|
1133
|
+
] }) : it.fixture ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
|
|
1134
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-action", children: [
|
|
1135
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-mkt", children: [
|
|
1136
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-market", children: it.market }),
|
|
1137
|
+
it.selection ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-sel", children: it.selection }) : null
|
|
1092
1138
|
] }),
|
|
1093
|
-
it.isMarketFloor ? /* @__PURE__ */ (0,
|
|
1094
|
-
it.odds ? /* @__PURE__ */ (0,
|
|
1095
|
-
/* @__PURE__ */ (0,
|
|
1096
|
-
/* @__PURE__ */ (0,
|
|
1097
|
-
/* @__PURE__ */ (0,
|
|
1098
|
-
it.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
|
|
1139
|
+
it.isMarketFloor ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
|
|
1140
|
+
it.odds ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-odds", children: [
|
|
1141
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("b", { children: it.odds }),
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
|
|
1143
|
+
it.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
|
|
1099
1144
|
] }) : null,
|
|
1100
|
-
/* @__PURE__ */ (0,
|
|
1145
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AddToSlipButton, { it, slip, ui })
|
|
1101
1146
|
] })
|
|
1102
1147
|
] }),
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-reason-body", children: [
|
|
1106
|
-
it.text ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "ss-w-bi-text", children: it.text }) : null,
|
|
1107
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StatsDisclosure, { it, ui })
|
|
1108
|
-
] })
|
|
1109
|
-
] }) : null,
|
|
1110
|
-
it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ReasonStrip, { it, ui }),
|
|
1149
|
+
it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
1111
1150
|
] });
|
|
1112
1151
|
}
|
|
1113
1152
|
function BettingInsightList({ insights, ui, slip }) {
|
|
1114
1153
|
if (!insights || insights.length === 0) return null;
|
|
1115
|
-
return /* @__PURE__ */ (0,
|
|
1154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(InsightCard, { it, ui, slip }, it.id)) });
|
|
1116
1155
|
}
|
|
1117
1156
|
|
|
1118
1157
|
// src/components/MarketOddsCardList.tsx
|
|
1119
|
-
var
|
|
1120
|
-
var
|
|
1158
|
+
var import_react7 = require("react");
|
|
1159
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1121
1160
|
function OddsRow({ vm, row, ui, slip }) {
|
|
1122
1161
|
const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
|
|
1123
|
-
return /* @__PURE__ */ (0,
|
|
1124
|
-
/* @__PURE__ */ (0,
|
|
1125
|
-
/* @__PURE__ */ (0,
|
|
1126
|
-
/* @__PURE__ */ (0,
|
|
1127
|
-
/* @__PURE__ */ (0,
|
|
1162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-row", children: [
|
|
1163
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-sel", children: row.selection }),
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-price", children: row.odds }),
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
|
|
1128
1167
|
] });
|
|
1129
1168
|
}
|
|
1130
1169
|
function MarketOddsCard({ vm, ui, slip }) {
|
|
1131
|
-
const [open, setOpen] = (0,
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1170
|
+
const [open, setOpen] = (0, import_react7.useState)(false);
|
|
1171
|
+
const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
|
|
1172
|
+
const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
|
|
1173
|
+
const showHeader = !!vm.competition || vm.isLive || !!kickoff;
|
|
1174
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mocard", children: [
|
|
1175
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-header", children: [
|
|
1176
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1177
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
|
|
1178
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-comp", children: vm.competition })
|
|
1179
|
+
] }) : null }),
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-header-right", children: [
|
|
1181
|
+
vm.isLive ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-live", children: [
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1183
|
+
ui?.liveLabel ?? "Live"
|
|
1184
|
+
] }) : null,
|
|
1185
|
+
kickoff ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-kick", children: [
|
|
1186
|
+
kickoff.dayLabel,
|
|
1187
|
+
" ",
|
|
1188
|
+
kickoff.time
|
|
1189
|
+
] }) : null
|
|
1190
|
+
] })
|
|
1140
1191
|
] }) : null,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1142
|
-
|
|
1143
|
-
|
|
1192
|
+
hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-sub", children: [
|
|
1193
|
+
hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-fixture", children: [
|
|
1194
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
|
|
1195
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
|
|
1196
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1197
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
|
|
1198
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
|
|
1199
|
+
] }) : vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
|
|
1200
|
+
vm.market ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-market", children: vm.market }) : null
|
|
1201
|
+
] }) : null,
|
|
1202
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-rows", children: [
|
|
1203
|
+
vm.mainRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsRow, { vm, row, ui, slip }, row.key)),
|
|
1204
|
+
open ? vm.moreRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsRow, { vm, row, ui, slip }, row.key)) : null
|
|
1144
1205
|
] }),
|
|
1145
|
-
vm.moreRows.length > 0 ? /* @__PURE__ */ (0,
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1147
|
-
/* @__PURE__ */ (0,
|
|
1206
|
+
vm.moreRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", className: "ss-w-mo-more", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
|
|
1207
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
|
|
1208
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `ss-w-mo-more-chev${open ? " ss-w-mo-more-chev-up" : ""}`, "aria-hidden": "true" })
|
|
1148
1209
|
] }) : null,
|
|
1149
|
-
vm.bookmaker ? /* @__PURE__ */ (0,
|
|
1150
|
-
vm.disclaimer ? /* @__PURE__ */ (0,
|
|
1210
|
+
vm.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: vm.bookmaker }) }) : null,
|
|
1211
|
+
vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
|
|
1151
1212
|
] });
|
|
1152
1213
|
}
|
|
1153
1214
|
function MarketOddsCardList({ cards, ui, slip }) {
|
|
1154
1215
|
if (!cards || cards.length === 0) return null;
|
|
1155
|
-
return /* @__PURE__ */ (0,
|
|
1216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarketOddsCard, { vm, ui, slip }, vm.id)) });
|
|
1156
1217
|
}
|
|
1157
1218
|
|
|
1158
1219
|
// src/components/OddsMovementCard.tsx
|
|
1159
|
-
var
|
|
1220
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1160
1221
|
function directionWord(vm, ui) {
|
|
1161
1222
|
if (vm.direction === "shortened") return ui?.oddsShortened ?? "shortened";
|
|
1162
1223
|
if (vm.direction === "drifted") return ui?.oddsDrifted ?? "drifted";
|
|
@@ -1166,18 +1227,18 @@ function OddsMovementCard({ vm, ui }) {
|
|
|
1166
1227
|
const word = directionWord(vm, ui);
|
|
1167
1228
|
const drift = word ? `, ${word}` : "";
|
|
1168
1229
|
const aria = ui?.chartAria ? ui.chartAria(vm.opening, vm.current, word, vm.windowHours) : `Price movement over the last ${vm.windowHours} hours: opened at ${vm.opening}, currently ${vm.current}${drift}.`;
|
|
1169
|
-
return /* @__PURE__ */ (0,
|
|
1170
|
-
/* @__PURE__ */ (0,
|
|
1171
|
-
/* @__PURE__ */ (0,
|
|
1172
|
-
/* @__PURE__ */ (0,
|
|
1230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-omcard", children: [
|
|
1231
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-head", children: [
|
|
1232
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-market", children: vm.market }),
|
|
1233
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" })
|
|
1173
1234
|
] }),
|
|
1174
|
-
vm.fixture ? /* @__PURE__ */ (0,
|
|
1175
|
-
/* @__PURE__ */ (0,
|
|
1176
|
-
vm.competition ? /* @__PURE__ */ (0,
|
|
1235
|
+
vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-fixture", children: [
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: vm.fixture }),
|
|
1237
|
+
vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-comp", children: vm.competition }) : null
|
|
1177
1238
|
] }) : null,
|
|
1178
|
-
/* @__PURE__ */ (0,
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1180
|
-
vm.geometry === null ? /* @__PURE__ */ (0,
|
|
1239
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-sel", children: vm.selection }),
|
|
1240
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
|
|
1241
|
+
vm.geometry === null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-empty", children: vm.observationCount === 1 ? ui?.singlePricePoint ?? "Only one price recorded so far for this selection." : ui?.notEnoughHistory ?? "No price history recorded yet for this selection." }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1181
1242
|
"svg",
|
|
1182
1243
|
{
|
|
1183
1244
|
className: "ss-w-om-chart",
|
|
@@ -1186,83 +1247,83 @@ function OddsMovementCard({ vm, ui }) {
|
|
|
1186
1247
|
role: "img",
|
|
1187
1248
|
"aria-label": aria,
|
|
1188
1249
|
children: [
|
|
1189
|
-
vm.geometry.gridlines.map((g) => /* @__PURE__ */ (0,
|
|
1190
|
-
/* @__PURE__ */ (0,
|
|
1191
|
-
/* @__PURE__ */ (0,
|
|
1250
|
+
vm.geometry.gridlines.map((g) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("g", { children: [
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("line", { className: "ss-w-om-grid", x1: 40, y1: g.y, x2: CHART_VIEW_W - 8, y2: g.y }),
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-ylab", x: 34, y: g.y + 3, textAnchor: "end", children: g.price.toFixed(2) })
|
|
1192
1253
|
] }, g.price)),
|
|
1193
|
-
/* @__PURE__ */ (0,
|
|
1194
|
-
vm.geometry.markers.map((m, i) => /* @__PURE__ */ (0,
|
|
1195
|
-
ui?.chartTimeLabel ? /* @__PURE__ */ (0,
|
|
1196
|
-
/* @__PURE__ */ (0,
|
|
1197
|
-
/* @__PURE__ */ (0,
|
|
1198
|
-
] }) : /* @__PURE__ */ (0,
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
|
|
1255
|
+
vm.geometry.markers.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
|
|
1256
|
+
ui?.chartTimeLabel ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
1257
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
|
|
1258
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
|
|
1259
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
|
|
1199
1260
|
]
|
|
1200
1261
|
}
|
|
1201
1262
|
),
|
|
1202
|
-
/* @__PURE__ */ (0,
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-foot", children: [
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
|
|
1204
1265
|
ui?.openingLabel ?? "Opening",
|
|
1205
1266
|
" ",
|
|
1206
|
-
/* @__PURE__ */ (0,
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: vm.opening })
|
|
1207
1268
|
] }),
|
|
1208
|
-
/* @__PURE__ */ (0,
|
|
1269
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
|
|
1209
1270
|
ui?.currentLabel ?? "Current",
|
|
1210
1271
|
" ",
|
|
1211
|
-
/* @__PURE__ */ (0,
|
|
1272
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: vm.current })
|
|
1212
1273
|
] })
|
|
1213
1274
|
] }),
|
|
1214
|
-
vm.bookmaker ? /* @__PURE__ */ (0,
|
|
1215
|
-
vm.excludedCount > 0 ? /* @__PURE__ */ (0,
|
|
1216
|
-
vm.isSuspended ? /* @__PURE__ */ (0,
|
|
1217
|
-
vm.disclaimer ? /* @__PURE__ */ (0,
|
|
1275
|
+
vm.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-foot", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: vm.bookmaker }) }) : null,
|
|
1276
|
+
vm.excludedCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-excl", children: ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.` }) : null,
|
|
1277
|
+
vm.isSuspended ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-susp", children: ui?.selectionSuspended ?? "This selection is not currently available to bet." }) : null,
|
|
1278
|
+
vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
|
|
1218
1279
|
] });
|
|
1219
1280
|
}
|
|
1220
1281
|
function OddsMovementCardList({ cards, ui }) {
|
|
1221
1282
|
if (!cards || cards.length === 0) return null;
|
|
1222
|
-
return /* @__PURE__ */ (0,
|
|
1283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-omcards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OddsMovementCard, { vm, ui }, vm.id)) });
|
|
1223
1284
|
}
|
|
1224
1285
|
|
|
1225
1286
|
// src/components/ActionButtons.tsx
|
|
1226
|
-
var
|
|
1287
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1227
1288
|
function ActionButtons({ actions, loading, disabled, onAct }) {
|
|
1228
1289
|
if (actions.length === 0 && !loading) return null;
|
|
1229
|
-
return /* @__PURE__ */ (0,
|
|
1230
|
-
actions.map((a, i) => /* @__PURE__ */ (0,
|
|
1231
|
-
actions.length === 0 && loading ? /* @__PURE__ */ (0,
|
|
1232
|
-
/* @__PURE__ */ (0,
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-actions", children: [
|
|
1291
|
+
actions.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
|
|
1292
|
+
actions.length === 0 && loading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
1293
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-abtn-shimmer" }),
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-abtn-shimmer" })
|
|
1234
1295
|
] }) : null
|
|
1235
1296
|
] });
|
|
1236
1297
|
}
|
|
1237
1298
|
|
|
1238
1299
|
// src/components/dashboard/DashboardTile.tsx
|
|
1239
|
-
var
|
|
1300
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1240
1301
|
var MAX_CRESTS = 3;
|
|
1241
1302
|
function DashboardTile({ tile, onTap }) {
|
|
1242
1303
|
const spanClass = tile.span === "full" ? "ss-w-dash-tile--full" : "ss-w-dash-tile--half";
|
|
1243
1304
|
const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS);
|
|
1244
1305
|
const hasMeta = Boolean(tile.badgeText) || crests.length > 0;
|
|
1245
|
-
return /* @__PURE__ */ (0,
|
|
1246
|
-
/* @__PURE__ */ (0,
|
|
1247
|
-
/* @__PURE__ */ (0,
|
|
1248
|
-
/* @__PURE__ */ (0,
|
|
1249
|
-
tile.subtitle ? /* @__PURE__ */ (0,
|
|
1306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: `ss-w-dash-tile ${spanClass}`, onClick: onTap, children: [
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DashboardIcon, { name: tile.icon }) }),
|
|
1308
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "ss-w-dash-tile-body", children: [
|
|
1309
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-title", children: tile.title }),
|
|
1310
|
+
tile.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
|
|
1250
1311
|
hasMeta ? (
|
|
1251
1312
|
// Badge + crests sit on their own row, below the title, instead of sharing the
|
|
1252
1313
|
// icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone
|
|
1253
1314
|
// (~70px) left the title column at ~22px and forced character-by-character wrapping.
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1255
|
-
tile.badgeText ? /* @__PURE__ */ (0,
|
|
1256
|
-
crests.length > 0 ? /* @__PURE__ */ (0,
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "ss-w-dash-tile-meta", children: [
|
|
1316
|
+
tile.badgeText ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
|
|
1317
|
+
crests.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-crests", children: crests.map((url, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-crest", style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" }, `${url}-${i}`)) }) : null
|
|
1257
1318
|
] })
|
|
1258
1319
|
) : null
|
|
1259
1320
|
] }),
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1321
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronIcon, {}) })
|
|
1261
1322
|
] });
|
|
1262
1323
|
}
|
|
1263
1324
|
|
|
1264
1325
|
// src/components/dashboard/GreetingDashboard.tsx
|
|
1265
|
-
var
|
|
1326
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1266
1327
|
var LAYOUT_CLASSES = {
|
|
1267
1328
|
market: "ss-w-dash--market",
|
|
1268
1329
|
goal: "ss-w-dash--goal",
|
|
@@ -1272,75 +1333,75 @@ function layoutClass(layout) {
|
|
|
1272
1333
|
return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout) ? LAYOUT_CLASSES[layout] : LAYOUT_CLASSES.goal;
|
|
1273
1334
|
}
|
|
1274
1335
|
function GreetingDashboard({ dashboard, onTap }) {
|
|
1275
|
-
return /* @__PURE__ */ (0,
|
|
1276
|
-
/* @__PURE__ */ (0,
|
|
1277
|
-
/* @__PURE__ */ (0,
|
|
1278
|
-
dashboard.subtitle ? /* @__PURE__ */ (0,
|
|
1336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: `ss-w-dash ${layoutClass(dashboard.layout)}`, children: [
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-dash-head", children: [
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-title", children: dashboard.title }),
|
|
1339
|
+
dashboard.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
|
|
1279
1340
|
] }),
|
|
1280
|
-
/* @__PURE__ */ (0,
|
|
1281
|
-
dashboard.footerTip ? /* @__PURE__ */ (0,
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-dash-grid", children: dashboard.tiles.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DashboardTile, { tile: t, onTap: () => onTap(t, i) }, `${t.title}-${i}`)) }),
|
|
1342
|
+
dashboard.footerTip ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
|
|
1282
1343
|
] });
|
|
1283
1344
|
}
|
|
1284
1345
|
|
|
1285
1346
|
// src/components/club-dashboard/GreetingHeaderBlock.tsx
|
|
1286
|
-
var
|
|
1347
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1287
1348
|
function GreetingHeaderBlock({ block }) {
|
|
1288
|
-
return /* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
|
|
1350
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
|
|
1291
1352
|
] });
|
|
1292
1353
|
}
|
|
1293
1354
|
|
|
1294
1355
|
// src/components/club-dashboard/FixtureHeroBlock.tsx
|
|
1295
|
-
var
|
|
1296
|
-
var
|
|
1356
|
+
var import_react8 = require("react");
|
|
1357
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1297
1358
|
function initials3(name) {
|
|
1298
1359
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
1299
1360
|
}
|
|
1300
1361
|
function Crest3({ url, name }) {
|
|
1301
|
-
const [broken, setBroken] = (0,
|
|
1362
|
+
const [broken, setBroken] = (0, import_react8.useState)(false);
|
|
1302
1363
|
if (!url || broken) {
|
|
1303
|
-
return /* @__PURE__ */ (0,
|
|
1364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
|
|
1304
1365
|
}
|
|
1305
|
-
return /* @__PURE__ */ (0,
|
|
1366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
|
|
1306
1367
|
}
|
|
1307
1368
|
function FixtureHeroBlock({
|
|
1308
1369
|
block,
|
|
1309
1370
|
ui,
|
|
1310
1371
|
onAction
|
|
1311
1372
|
}) {
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1314
|
-
/* @__PURE__ */ (0,
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1316
|
-
/* @__PURE__ */ (0,
|
|
1317
|
-
/* @__PURE__ */ (0,
|
|
1318
|
-
/* @__PURE__ */ (0,
|
|
1373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-tie", children: [
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
|
|
1377
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
|
|
1379
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.awayCrestUrl, name: block.awayName })
|
|
1319
1380
|
] }),
|
|
1320
|
-
/* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
block.venue ? /* @__PURE__ */ (0,
|
|
1323
|
-
block.competition ? /* @__PURE__ */ (0,
|
|
1381
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
|
|
1383
|
+
block.venue ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
|
|
1384
|
+
block.competition ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
|
|
1324
1385
|
] }),
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
1386
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaLabel, { actionRef: block.ctaActionRef }), children: block.ctaLabel })
|
|
1326
1387
|
] });
|
|
1327
1388
|
}
|
|
1328
1389
|
|
|
1329
1390
|
// src/components/club-dashboard/FormGuideBlock.tsx
|
|
1330
|
-
var
|
|
1391
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1331
1392
|
function FormGuideBlock({ block }) {
|
|
1332
1393
|
if (block.rows.length === 0) return null;
|
|
1333
|
-
return /* @__PURE__ */ (0,
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
|
|
1335
1396
|
row.name,
|
|
1336
1397
|
row.position != null ? ` #${row.position}` : ""
|
|
1337
1398
|
] }),
|
|
1338
|
-
/* @__PURE__ */ (0,
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
|
|
1339
1400
|
] }, row.name)) });
|
|
1340
1401
|
}
|
|
1341
1402
|
|
|
1342
1403
|
// src/components/club-dashboard/MatchPreviewBlock.tsx
|
|
1343
|
-
var
|
|
1404
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1344
1405
|
function MatchPreviewBlock({
|
|
1345
1406
|
block,
|
|
1346
1407
|
ui,
|
|
@@ -1348,31 +1409,31 @@ function MatchPreviewBlock({
|
|
|
1348
1409
|
}) {
|
|
1349
1410
|
if (block.facts.length === 0) return null;
|
|
1350
1411
|
const heading = ui.clubMatchPreviewHeading;
|
|
1351
|
-
return /* @__PURE__ */ (0,
|
|
1352
|
-
/* @__PURE__ */ (0,
|
|
1412
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-cdash-lines", children: [
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1353
1414
|
block.facts.map(
|
|
1354
|
-
(f, i) => f.
|
|
1415
|
+
(f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1355
1416
|
"button",
|
|
1356
1417
|
{
|
|
1357
1418
|
type: "button",
|
|
1358
1419
|
className: "ss-w-cdash-fact",
|
|
1359
|
-
onClick: () => onAction(f.
|
|
1420
|
+
onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
|
|
1360
1421
|
children: [
|
|
1361
1422
|
f.sentence,
|
|
1362
|
-
f.label ? /* @__PURE__ */ (0,
|
|
1423
|
+
f.label ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
|
|
1363
1424
|
" ",
|
|
1364
1425
|
f.label
|
|
1365
1426
|
] }) : null
|
|
1366
1427
|
]
|
|
1367
1428
|
},
|
|
1368
1429
|
i
|
|
1369
|
-
) : /* @__PURE__ */ (0,
|
|
1430
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: f.sentence }, i)
|
|
1370
1431
|
)
|
|
1371
1432
|
] });
|
|
1372
1433
|
}
|
|
1373
1434
|
|
|
1374
1435
|
// src/components/club-dashboard/TeamDnaBlock.tsx
|
|
1375
|
-
var
|
|
1436
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1376
1437
|
function TeamDnaBlock({
|
|
1377
1438
|
block,
|
|
1378
1439
|
ui,
|
|
@@ -1380,32 +1441,32 @@ function TeamDnaBlock({
|
|
|
1380
1441
|
}) {
|
|
1381
1442
|
if (block.facts.length === 0) return null;
|
|
1382
1443
|
const heading = ui.clubTeamDnaHeading;
|
|
1383
|
-
return /* @__PURE__ */ (0,
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-lines", children: [
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1385
1446
|
block.facts.map(
|
|
1386
|
-
(f, i) => f.
|
|
1447
|
+
(f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
1387
1448
|
"button",
|
|
1388
1449
|
{
|
|
1389
1450
|
type: "button",
|
|
1390
1451
|
className: "ss-w-cdash-fact",
|
|
1391
|
-
onClick: () => onAction(f.
|
|
1452
|
+
onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
|
|
1392
1453
|
children: [
|
|
1393
1454
|
f.sentence,
|
|
1394
|
-
f.label ? /* @__PURE__ */ (0,
|
|
1455
|
+
f.label ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
|
|
1395
1456
|
" ",
|
|
1396
1457
|
f.label
|
|
1397
1458
|
] }) : null
|
|
1398
1459
|
]
|
|
1399
1460
|
},
|
|
1400
1461
|
i
|
|
1401
|
-
) : /* @__PURE__ */ (0,
|
|
1462
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: f.sentence }, i)
|
|
1402
1463
|
)
|
|
1403
1464
|
] });
|
|
1404
1465
|
}
|
|
1405
1466
|
|
|
1406
1467
|
// src/components/club-dashboard/CountdownBlock.tsx
|
|
1407
|
-
var
|
|
1408
|
-
var
|
|
1468
|
+
var import_react9 = require("react");
|
|
1469
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1409
1470
|
var DAY_MS = 24 * 3600 * 1e3;
|
|
1410
1471
|
function pad2(n) {
|
|
1411
1472
|
return String(n).padStart(2, "0");
|
|
@@ -1418,8 +1479,8 @@ function splitRemaining(remainingMs) {
|
|
|
1418
1479
|
return { h: pad2(h), m: pad2(m), s: pad2(s) };
|
|
1419
1480
|
}
|
|
1420
1481
|
function CountdownBlock({ block, ui }) {
|
|
1421
|
-
const [remainingMs, setRemainingMs] = (0,
|
|
1422
|
-
(0,
|
|
1482
|
+
const [remainingMs, setRemainingMs] = (0, import_react9.useState)(() => block.kickoffUnix * 1e3 - Date.now());
|
|
1483
|
+
(0, import_react9.useEffect)(() => {
|
|
1423
1484
|
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1424
1485
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
1425
1486
|
const id = setInterval(() => {
|
|
@@ -1430,30 +1491,30 @@ function CountdownBlock({ block, ui }) {
|
|
|
1430
1491
|
if (remainingMs <= 0) return null;
|
|
1431
1492
|
if (remainingMs > DAY_MS) return null;
|
|
1432
1493
|
const { h, m, s } = splitRemaining(remainingMs);
|
|
1433
|
-
return /* @__PURE__ */ (0,
|
|
1434
|
-
/* @__PURE__ */ (0,
|
|
1435
|
-
/* @__PURE__ */ (0,
|
|
1494
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
|
|
1496
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
|
|
1436
1497
|
"h",
|
|
1437
1498
|
" ",
|
|
1438
|
-
/* @__PURE__ */ (0,
|
|
1499
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
|
|
1439
1500
|
"m",
|
|
1440
1501
|
" ",
|
|
1441
|
-
/* @__PURE__ */ (0,
|
|
1502
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
|
|
1442
1503
|
"s"
|
|
1443
1504
|
] }),
|
|
1444
|
-
/* @__PURE__ */ (0,
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
|
|
1445
1506
|
] });
|
|
1446
1507
|
}
|
|
1447
1508
|
|
|
1448
1509
|
// src/components/club-dashboard/ClubDashboard.tsx
|
|
1449
|
-
var
|
|
1510
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1450
1511
|
var CLUB_BLOCK_REGISTRY = {
|
|
1451
|
-
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0,
|
|
1452
|
-
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0,
|
|
1453
|
-
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0,
|
|
1454
|
-
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0,
|
|
1455
|
-
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0,
|
|
1456
|
-
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0,
|
|
1512
|
+
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingHeaderBlock, { block }) : null,
|
|
1513
|
+
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
|
|
1514
|
+
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FormGuideBlock, { block, ui }) : null,
|
|
1515
|
+
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
|
|
1516
|
+
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
|
|
1517
|
+
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CountdownBlock, { block, ui }) : null
|
|
1457
1518
|
};
|
|
1458
1519
|
function ClubDashboard({
|
|
1459
1520
|
dashboard,
|
|
@@ -1461,39 +1522,39 @@ function ClubDashboard({
|
|
|
1461
1522
|
onAction
|
|
1462
1523
|
}) {
|
|
1463
1524
|
if (!dashboard.blocks.length) return null;
|
|
1464
|
-
return /* @__PURE__ */ (0,
|
|
1525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
|
|
1465
1526
|
const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
|
|
1466
1527
|
if (!Comp) {
|
|
1467
1528
|
console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
|
|
1468
1529
|
return null;
|
|
1469
1530
|
}
|
|
1470
|
-
return /* @__PURE__ */ (0,
|
|
1531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Comp, { block, ui, onAction }) }, i);
|
|
1471
1532
|
}) });
|
|
1472
1533
|
}
|
|
1473
1534
|
|
|
1474
1535
|
// src/components/ChatMessage.tsx
|
|
1475
|
-
var
|
|
1536
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1476
1537
|
function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
|
|
1477
1538
|
if (message.role === "user") {
|
|
1478
|
-
return /* @__PURE__ */ (0,
|
|
1539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
|
|
1479
1540
|
}
|
|
1480
|
-
return /* @__PURE__ */ (0,
|
|
1481
|
-
message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0,
|
|
1482
|
-
message.greetingDashboard ? /* @__PURE__ */ (0,
|
|
1483
|
-
message.clubDashboard && ui ? /* @__PURE__ */ (0,
|
|
1484
|
-
/* @__PURE__ */ (0,
|
|
1485
|
-
/* @__PURE__ */ (0,
|
|
1486
|
-
/* @__PURE__ */ (0,
|
|
1487
|
-
/* @__PURE__ */ (0,
|
|
1488
|
-
/* @__PURE__ */ (0,
|
|
1541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
1542
|
+
message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Markdown, { text: message.text }) : null,
|
|
1543
|
+
message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
|
|
1544
|
+
message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
|
|
1545
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
1546
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
|
|
1547
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
|
|
1548
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
|
|
1549
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
1489
1550
|
] });
|
|
1490
1551
|
}
|
|
1491
1552
|
|
|
1492
1553
|
// src/components/IntentChips.tsx
|
|
1493
|
-
var
|
|
1554
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1494
1555
|
function IntentChips({ chips, onPick }) {
|
|
1495
1556
|
if (chips.length === 0) return null;
|
|
1496
|
-
return /* @__PURE__ */ (0,
|
|
1557
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
1497
1558
|
}
|
|
1498
1559
|
|
|
1499
1560
|
// src/scroll.ts
|
|
@@ -1503,18 +1564,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
1503
1564
|
}
|
|
1504
1565
|
|
|
1505
1566
|
// src/components/MessageList.tsx
|
|
1506
|
-
var
|
|
1567
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1507
1568
|
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
1508
1569
|
const { state, send } = controller;
|
|
1509
|
-
const listRef = (0,
|
|
1510
|
-
const endRef = (0,
|
|
1511
|
-
const pinnedRef = (0,
|
|
1512
|
-
(0,
|
|
1570
|
+
const listRef = (0, import_react10.useRef)(null);
|
|
1571
|
+
const endRef = (0, import_react10.useRef)(null);
|
|
1572
|
+
const pinnedRef = (0, import_react10.useRef)(true);
|
|
1573
|
+
(0, import_react10.useEffect)(() => {
|
|
1513
1574
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
1514
1575
|
}, [state.messages, state.status]);
|
|
1515
1576
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
1516
1577
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
|
|
1517
|
-
return /* @__PURE__ */ (0,
|
|
1578
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1518
1579
|
"div",
|
|
1519
1580
|
{
|
|
1520
1581
|
className: "ss-w-list",
|
|
@@ -1524,7 +1585,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1524
1585
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
1525
1586
|
},
|
|
1526
1587
|
children: [
|
|
1527
|
-
state.messages.map((m) => /* @__PURE__ */ (0,
|
|
1588
|
+
state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1528
1589
|
ChatMessage,
|
|
1529
1590
|
{
|
|
1530
1591
|
message: m,
|
|
@@ -1534,31 +1595,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1534
1595
|
send(tile.actionValue, { displayText: tile.title });
|
|
1535
1596
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
1536
1597
|
},
|
|
1537
|
-
onClubAction: (
|
|
1598
|
+
onClubAction: (label, opts) => send(label, { actionRef: opts.actionRef }),
|
|
1538
1599
|
ui,
|
|
1539
1600
|
slip
|
|
1540
1601
|
},
|
|
1541
1602
|
m.id
|
|
1542
1603
|
)),
|
|
1543
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0,
|
|
1604
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
1544
1605
|
} }) : null,
|
|
1545
|
-
state.status ? /* @__PURE__ */ (0,
|
|
1546
|
-
state.error ? /* @__PURE__ */ (0,
|
|
1547
|
-
/* @__PURE__ */ (0,
|
|
1548
|
-
/* @__PURE__ */ (0,
|
|
1606
|
+
state.status ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
|
|
1607
|
+
state.error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
|
|
1608
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
1609
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
1549
1610
|
] }) : null,
|
|
1550
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0,
|
|
1551
|
-
/* @__PURE__ */ (0,
|
|
1611
|
+
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
1612
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: endRef })
|
|
1552
1613
|
]
|
|
1553
1614
|
}
|
|
1554
1615
|
);
|
|
1555
1616
|
}
|
|
1556
1617
|
|
|
1557
1618
|
// src/components/ChatInput.tsx
|
|
1558
|
-
var
|
|
1559
|
-
var
|
|
1619
|
+
var import_react11 = require("react");
|
|
1620
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1560
1621
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
1561
|
-
const [value, setValue] = (0,
|
|
1622
|
+
const [value, setValue] = (0, import_react11.useState)("");
|
|
1562
1623
|
const submit = () => {
|
|
1563
1624
|
const t = value.trim();
|
|
1564
1625
|
if (!t) return;
|
|
@@ -1571,18 +1632,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
1571
1632
|
submit();
|
|
1572
1633
|
}
|
|
1573
1634
|
};
|
|
1574
|
-
return /* @__PURE__ */ (0,
|
|
1575
|
-
/* @__PURE__ */ (0,
|
|
1576
|
-
streaming ? /* @__PURE__ */ (0,
|
|
1635
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-input", children: [
|
|
1636
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
1637
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SendIcon, {}) })
|
|
1577
1638
|
] });
|
|
1578
1639
|
}
|
|
1579
1640
|
|
|
1580
1641
|
// src/components/ChatPanel.tsx
|
|
1581
|
-
var
|
|
1642
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1582
1643
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
1583
1644
|
function useIsModal() {
|
|
1584
|
-
const [modal, setModal] = (0,
|
|
1585
|
-
(0,
|
|
1645
|
+
const [modal, setModal] = (0, import_react12.useState)(false);
|
|
1646
|
+
(0, import_react12.useEffect)(() => {
|
|
1586
1647
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1587
1648
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
1588
1649
|
const sync = () => setModal(mql.matches);
|
|
@@ -1595,17 +1656,17 @@ function useIsModal() {
|
|
|
1595
1656
|
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
1596
1657
|
const { state, close, stop, send } = controller;
|
|
1597
1658
|
const isModal = useIsModal();
|
|
1598
|
-
(0,
|
|
1659
|
+
(0, import_react12.useEffect)(() => {
|
|
1599
1660
|
const onKey = (e) => {
|
|
1600
1661
|
if (e.key === "Escape") close();
|
|
1601
1662
|
};
|
|
1602
1663
|
window.addEventListener("keydown", onKey);
|
|
1603
1664
|
return () => window.removeEventListener("keydown", onKey);
|
|
1604
1665
|
}, [close]);
|
|
1605
|
-
return /* @__PURE__ */ (0,
|
|
1606
|
-
/* @__PURE__ */ (0,
|
|
1607
|
-
/* @__PURE__ */ (0,
|
|
1608
|
-
/* @__PURE__ */ (0,
|
|
1666
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
1667
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
|
|
1669
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
1609
1670
|
] });
|
|
1610
1671
|
}
|
|
1611
1672
|
|
|
@@ -1653,7 +1714,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1653
1714
|
.ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }
|
|
1654
1715
|
|
|
1655
1716
|
/* panel */
|
|
1656
|
-
.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(
|
|
1717
|
+
.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(460px, calc(100vw - 40px)); height: min(640px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }
|
|
1657
1718
|
.ss-w-root[data-ss-w-pos="right"] .ss-w-panel { right: var(--ss-w-offset-x); }
|
|
1658
1719
|
.ss-w-root[data-ss-w-pos="left"] .ss-w-panel { left: var(--ss-w-offset-x); }
|
|
1659
1720
|
@media (max-width: 639px) {
|
|
@@ -1756,9 +1817,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1756
1817
|
.ss-w-bi-floor { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; align-self: flex-start; flex: none; }
|
|
1757
1818
|
|
|
1758
1819
|
/* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */
|
|
1759
|
-
.ss-w-bi-comp-logo { width:
|
|
1760
|
-
.ss-w-bi-crest { width:
|
|
1761
|
-
.ss-w-bi-crest-mono { display: grid; place-items: center; font-size:
|
|
1820
|
+
.ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
|
|
1821
|
+
.ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
|
|
1822
|
+
.ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 10px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
|
|
1762
1823
|
|
|
1763
1824
|
/* row 2: crest-flanked fixture on the left, boxed action panel on the right */
|
|
1764
1825
|
.ss-w-bi-body { display: flex; align-items: center; gap: 10px; }
|
|
@@ -1766,16 +1827,16 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1766
1827
|
.ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1767
1828
|
.ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }
|
|
1768
1829
|
.ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1769
|
-
.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items:
|
|
1770
|
-
.ss-w-bi-action .ss-w-slip
|
|
1830
|
+
.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 0; }
|
|
1831
|
+
.ss-w-bi-action .ss-w-slip { width: 100%; }
|
|
1832
|
+
.ss-w-bi-action .ss-w-slip > button { flex: 1; width: 100%; text-align: center; border-radius: 8px; }
|
|
1771
1833
|
/* The action column is narrow; let its toast size to its own text and anchor to the card's right edge instead of being clipped to the button width. */
|
|
1772
1834
|
.ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
|
|
1773
|
-
.ss-w-bi-mkt { display: flex; flex-direction: column; gap:
|
|
1774
|
-
.ss-w-bi-market { font-size:
|
|
1775
|
-
.ss-w-bi-sel { font-size:
|
|
1776
|
-
.ss-w-bi-odds { flex: none; display: flex;
|
|
1777
|
-
.ss-w-bi-odds
|
|
1778
|
-
.ss-w-bi-odds b { font-size: 19px; font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.1; }
|
|
1835
|
+
.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; align-items: flex-end; text-align: right; }
|
|
1836
|
+
.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--ss-w-faint); white-space: nowrap; }
|
|
1837
|
+
.ss-w-bi-sel { font-size: 11px; line-height: 1.25; color: var(--ss-w-faint); }
|
|
1838
|
+
.ss-w-bi-odds { flex: none; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }
|
|
1839
|
+
.ss-w-bi-odds b { font-size: 23px; font-family: ui-monospace, monospace; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.05; }
|
|
1779
1840
|
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
1780
1841
|
|
|
1781
1842
|
/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
|
|
@@ -1789,11 +1850,11 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1789
1850
|
}
|
|
1790
1851
|
.ss-w-bi-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }
|
|
1791
1852
|
.ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
|
|
1792
|
-
.ss-w-bi-
|
|
1793
|
-
.ss-w-bi-
|
|
1794
|
-
.ss-w-bi-
|
|
1795
|
-
.ss-w-bi-
|
|
1796
|
-
.ss-w-bi-
|
|
1853
|
+
.ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
1854
|
+
.ss-w-bi-expand { flex: none; align-self: center; display: grid; place-items: center; width: 22px; height: 22px; margin: -2px -4px -2px 0; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; }
|
|
1855
|
+
.ss-w-bi-expand:hover { color: var(--ss-w-ink); }
|
|
1856
|
+
.ss-w-bi-arrow { width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-top: 1.6px solid currentColor; transform: rotate(45deg); transition: transform .15s ease; }
|
|
1857
|
+
.ss-w-bi-arrow-open { transform: rotate(135deg); }
|
|
1797
1858
|
.ss-w-bi-rows { display: flex; flex-direction: column; }
|
|
1798
1859
|
.ss-w-bi-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 5px 0; border-top: 1px solid var(--ss-w-line); }
|
|
1799
1860
|
.ss-w-bi-row:first-child { border-top: none; }
|
|
@@ -1808,11 +1869,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1808
1869
|
/* market odds card */
|
|
1809
1870
|
.ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
|
|
1810
1871
|
.ss-w-mocard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }
|
|
1811
|
-
.ss-w-mo-
|
|
1812
|
-
.ss-w-mo-
|
|
1813
|
-
.ss-w-mo-
|
|
1814
|
-
.ss-w-mo-
|
|
1815
|
-
.ss-w-mo-
|
|
1872
|
+
.ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
|
|
1873
|
+
.ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1874
|
+
.ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }
|
|
1875
|
+
.ss-w-mo-more { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11.5px; font-weight: 600; padding: 2px 0; cursor: pointer; }
|
|
1876
|
+
.ss-w-mo-more:hover { text-decoration: underline; }
|
|
1877
|
+
.ss-w-mo-more-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }
|
|
1878
|
+
.ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }
|
|
1816
1879
|
.ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }
|
|
1817
1880
|
.ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }
|
|
1818
1881
|
.ss-w-mo-row:last-child { border-bottom: none; }
|
|
@@ -1998,7 +2061,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1998
2061
|
`;
|
|
1999
2062
|
|
|
2000
2063
|
// src/StatsWidget.tsx
|
|
2001
|
-
var
|
|
2064
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
2002
2065
|
function buildClient(props) {
|
|
2003
2066
|
try {
|
|
2004
2067
|
if ("client" in props && props.client) {
|
|
@@ -2023,11 +2086,11 @@ function injectStyles(root) {
|
|
|
2023
2086
|
function StatsWidget(props) {
|
|
2024
2087
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
2025
2088
|
const cfg = props.config;
|
|
2026
|
-
const built = (0,
|
|
2027
|
-
const ui = (0,
|
|
2028
|
-
const rootRef = (0,
|
|
2089
|
+
const built = (0, import_react13.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
2090
|
+
const ui = (0, import_react13.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
2091
|
+
const rootRef = (0, import_react13.useRef)(null);
|
|
2029
2092
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
2030
|
-
const slip = (0,
|
|
2093
|
+
const slip = (0, import_react13.useMemo)(
|
|
2031
2094
|
() => ({
|
|
2032
2095
|
onAddToSlip: props.config?.onAddToSlip,
|
|
2033
2096
|
conversationId: controller.state.conversationId ?? void 0,
|
|
@@ -2040,18 +2103,18 @@ function StatsWidget(props) {
|
|
|
2040
2103
|
}),
|
|
2041
2104
|
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
2042
2105
|
);
|
|
2043
|
-
const onDashboardTap = (0,
|
|
2106
|
+
const onDashboardTap = (0, import_react13.useMemo)(
|
|
2044
2107
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
2045
2108
|
[built]
|
|
2046
2109
|
);
|
|
2047
|
-
(0,
|
|
2110
|
+
(0, import_react13.useEffect)(() => {
|
|
2048
2111
|
if (!built || !ui.injectStyles) return;
|
|
2049
2112
|
const node = rootRef.current?.getRootNode();
|
|
2050
2113
|
if (node) injectStyles(node);
|
|
2051
2114
|
}, [built, ui.injectStyles]);
|
|
2052
2115
|
if (!built) return null;
|
|
2053
2116
|
const attrs = themeAttrs(ui);
|
|
2054
|
-
return /* @__PURE__ */ (0,
|
|
2117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2055
2118
|
ChatFab,
|
|
2056
2119
|
{
|
|
2057
2120
|
label: ui.launcherLabel,
|