@sensiblestats/widget-react 0.17.0 → 0.19.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 +347 -277
- 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 +294 -224
- package/dist/index.js.map +1 -1
- package/dist/styles.css +29 -24
- 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),
|
|
@@ -652,7 +658,7 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
|
|
|
652
658
|
const send = (0, import_react.useCallback)((text, opts) => {
|
|
653
659
|
const trimmed = text.trim();
|
|
654
660
|
if (!trimmed) return;
|
|
655
|
-
run({ message: trimmed, actionId: opts?.actionId }, opts?.displayText);
|
|
661
|
+
run({ message: trimmed, actionId: opts?.actionId, grounding: opts?.grounding }, opts?.displayText);
|
|
656
662
|
}, [run]);
|
|
657
663
|
const retry = (0, import_react.useCallback)(() => {
|
|
658
664
|
const last = stateRef.current.lastUserInput;
|
|
@@ -748,7 +754,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
748
754
|
}
|
|
749
755
|
|
|
750
756
|
// src/components/ChatPanel.tsx
|
|
751
|
-
var
|
|
757
|
+
var import_react12 = require("react");
|
|
752
758
|
|
|
753
759
|
// src/components/ChatHeader.tsx
|
|
754
760
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -761,7 +767,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
761
767
|
}
|
|
762
768
|
|
|
763
769
|
// src/components/MessageList.tsx
|
|
764
|
-
var
|
|
770
|
+
var import_react10 = require("react");
|
|
765
771
|
|
|
766
772
|
// src/components/Markdown.tsx
|
|
767
773
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -881,7 +887,7 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
881
887
|
}
|
|
882
888
|
|
|
883
889
|
// src/components/BettingInsightList.tsx
|
|
884
|
-
var
|
|
890
|
+
var import_react6 = require("react");
|
|
885
891
|
|
|
886
892
|
// src/components/AddToSlipButton.tsx
|
|
887
893
|
var import_react4 = require("react");
|
|
@@ -1004,53 +1010,64 @@ function OddsMovementBadge({
|
|
|
1004
1010
|
] });
|
|
1005
1011
|
}
|
|
1006
1012
|
|
|
1007
|
-
// src/components/
|
|
1013
|
+
// src/components/Crest.tsx
|
|
1014
|
+
var import_react5 = require("react");
|
|
1008
1015
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1016
|
+
function initials2(name) {
|
|
1017
|
+
return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
|
|
1018
|
+
}
|
|
1019
|
+
function Crest2({ url, name, kind }) {
|
|
1020
|
+
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
1021
|
+
const [failed, setFailed] = (0, import_react5.useState)(false);
|
|
1022
|
+
if (url && !failed) {
|
|
1023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1024
|
+
}
|
|
1025
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// src/components/BettingInsightList.tsx
|
|
1029
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1009
1030
|
function StatRows2({ stats }) {
|
|
1010
|
-
return /* @__PURE__ */ (0,
|
|
1011
|
-
/* @__PURE__ */ (0,
|
|
1012
|
-
/* @__PURE__ */ (0,
|
|
1031
|
+
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: [
|
|
1032
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
1013
1034
|
] }, `${s.label}:${s.value}`)) });
|
|
1014
1035
|
}
|
|
1015
1036
|
function ScopedStats({ scopes }) {
|
|
1016
|
-
const [active, setActive] = (0,
|
|
1037
|
+
const [active, setActive] = (0, import_react6.useState)(0);
|
|
1017
1038
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
1018
|
-
return /* @__PURE__ */ (0,
|
|
1019
|
-
/* @__PURE__ */ (0,
|
|
1020
|
-
/* @__PURE__ */ (0,
|
|
1039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-scoped", children: [
|
|
1040
|
+
/* @__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)) }),
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StatRows2, { stats: current.stats }, current.key)
|
|
1021
1042
|
] });
|
|
1022
1043
|
}
|
|
1023
1044
|
function hasStatsContent(it) {
|
|
1024
1045
|
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
1025
1046
|
}
|
|
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);
|
|
1047
|
+
function ReasonStrip({ it, ui }) {
|
|
1048
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
1036
1049
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
1037
1050
|
const hasStats = hasStatsContent(it);
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1051
|
+
const hasText = !!it.text;
|
|
1052
|
+
if (!hasText && !hasStats) return null;
|
|
1053
|
+
const expandable = hasStats || (it.text?.length ?? 0) > 90;
|
|
1054
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-reason", children: [
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-reason-body", children: [
|
|
1057
|
+
hasText ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
|
|
1058
|
+
open && hasStats ? hasScopes ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StatRows2, { stats: it.stats }) : null
|
|
1059
|
+
] }),
|
|
1060
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1041
1061
|
"button",
|
|
1042
1062
|
{
|
|
1043
1063
|
type: "button",
|
|
1044
|
-
className: "ss-w-bi-
|
|
1064
|
+
className: "ss-w-bi-expand",
|
|
1045
1065
|
"aria-expanded": open,
|
|
1066
|
+
"aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
|
|
1046
1067
|
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
|
-
]
|
|
1068
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
|
|
1051
1069
|
}
|
|
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
|
|
1070
|
+
) : null
|
|
1054
1071
|
] });
|
|
1055
1072
|
}
|
|
1056
1073
|
function InsightCard({ it, ui, slip }) {
|
|
@@ -1058,105 +1075,119 @@ function InsightCard({ it, ui, slip }) {
|
|
|
1058
1075
|
const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : void 0;
|
|
1059
1076
|
const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName;
|
|
1060
1077
|
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 })
|
|
1078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-binsight", children: [
|
|
1079
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-header", children: [
|
|
1080
|
+
/* @__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: [
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
|
|
1082
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-comp", children: it.competition })
|
|
1067
1083
|
] }) : null }),
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1069
|
-
live ? /* @__PURE__ */ (0,
|
|
1070
|
-
/* @__PURE__ */ (0,
|
|
1084
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-header-right", children: [
|
|
1085
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-live", children: [
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1071
1087
|
ui?.liveLabel ?? "Live"
|
|
1072
1088
|
] }) : null,
|
|
1073
|
-
kickoff ? /* @__PURE__ */ (0,
|
|
1089
|
+
kickoff ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-kick", children: [
|
|
1074
1090
|
kickoff.dayLabel,
|
|
1075
1091
|
" ",
|
|
1076
1092
|
kickoff.time
|
|
1077
1093
|
] }) : null
|
|
1078
1094
|
] })
|
|
1079
1095
|
] }) : 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,
|
|
1096
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-body", children: [
|
|
1097
|
+
/* @__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: [
|
|
1098
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
|
|
1099
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
|
|
1100
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1101
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
|
|
1102
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
|
|
1103
|
+
] }) : it.fixture ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
|
|
1104
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-action", children: [
|
|
1105
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-mkt", children: [
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-market", children: it.market }),
|
|
1107
|
+
it.selection ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-sel", children: it.selection }) : null
|
|
1092
1108
|
] }),
|
|
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
|
|
1109
|
+
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,
|
|
1110
|
+
it.odds ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-odds", children: [
|
|
1111
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("b", { children: it.odds }),
|
|
1112
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
|
|
1113
|
+
it.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
|
|
1099
1114
|
] }) : null,
|
|
1100
|
-
/* @__PURE__ */ (0,
|
|
1115
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AddToSlipButton, { it, slip, ui })
|
|
1101
1116
|
] })
|
|
1102
1117
|
] }),
|
|
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
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ReasonStrip, { it, ui }),
|
|
1119
|
+
it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
1111
1120
|
] });
|
|
1112
1121
|
}
|
|
1113
1122
|
function BettingInsightList({ insights, ui, slip }) {
|
|
1114
1123
|
if (!insights || insights.length === 0) return null;
|
|
1115
|
-
return /* @__PURE__ */ (0,
|
|
1124
|
+
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
1125
|
}
|
|
1117
1126
|
|
|
1118
1127
|
// src/components/MarketOddsCardList.tsx
|
|
1119
|
-
var
|
|
1120
|
-
var
|
|
1128
|
+
var import_react7 = require("react");
|
|
1129
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1121
1130
|
function OddsRow({ vm, row, ui, slip }) {
|
|
1122
1131
|
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,
|
|
1132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-row", children: [
|
|
1133
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-sel", children: row.selection }),
|
|
1134
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
|
|
1135
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-price", children: row.odds }),
|
|
1136
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
|
|
1128
1137
|
] });
|
|
1129
1138
|
}
|
|
1130
1139
|
function MarketOddsCard({ vm, ui, slip }) {
|
|
1131
|
-
const [open, setOpen] = (0,
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
+
const [open, setOpen] = (0, import_react7.useState)(false);
|
|
1141
|
+
const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
|
|
1142
|
+
const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
|
|
1143
|
+
const showHeader = !!vm.competition || vm.isLive || !!kickoff;
|
|
1144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mocard", children: [
|
|
1145
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-header", children: [
|
|
1146
|
+
/* @__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: [
|
|
1147
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-comp", children: vm.competition })
|
|
1149
|
+
] }) : null }),
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-header-right", children: [
|
|
1151
|
+
vm.isLive ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-live", children: [
|
|
1152
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1153
|
+
ui?.liveLabel ?? "Live"
|
|
1154
|
+
] }) : null,
|
|
1155
|
+
kickoff ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-kick", children: [
|
|
1156
|
+
kickoff.dayLabel,
|
|
1157
|
+
" ",
|
|
1158
|
+
kickoff.time
|
|
1159
|
+
] }) : null
|
|
1160
|
+
] })
|
|
1140
1161
|
] }) : null,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1142
|
-
|
|
1143
|
-
|
|
1162
|
+
hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-sub", children: [
|
|
1163
|
+
hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-fixture", children: [
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
|
|
1168
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
|
|
1169
|
+
] }) : vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
|
|
1170
|
+
vm.market ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-market", children: vm.market }) : null
|
|
1171
|
+
] }) : null,
|
|
1172
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-rows", children: [
|
|
1173
|
+
vm.mainRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsRow, { vm, row, ui, slip }, row.key)),
|
|
1174
|
+
open ? vm.moreRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsRow, { vm, row, ui, slip }, row.key)) : null
|
|
1144
1175
|
] }),
|
|
1145
|
-
vm.moreRows.length > 0 ? /* @__PURE__ */ (0,
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1147
|
-
/* @__PURE__ */ (0,
|
|
1176
|
+
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: [
|
|
1177
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
|
|
1178
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `ss-w-mo-more-chev${open ? " ss-w-mo-more-chev-up" : ""}`, "aria-hidden": "true" })
|
|
1148
1179
|
] }) : null,
|
|
1149
|
-
vm.bookmaker ? /* @__PURE__ */ (0,
|
|
1150
|
-
vm.disclaimer ? /* @__PURE__ */ (0,
|
|
1180
|
+
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,
|
|
1181
|
+
vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
|
|
1151
1182
|
] });
|
|
1152
1183
|
}
|
|
1153
1184
|
function MarketOddsCardList({ cards, ui, slip }) {
|
|
1154
1185
|
if (!cards || cards.length === 0) return null;
|
|
1155
|
-
return /* @__PURE__ */ (0,
|
|
1186
|
+
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
1187
|
}
|
|
1157
1188
|
|
|
1158
1189
|
// src/components/OddsMovementCard.tsx
|
|
1159
|
-
var
|
|
1190
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1160
1191
|
function directionWord(vm, ui) {
|
|
1161
1192
|
if (vm.direction === "shortened") return ui?.oddsShortened ?? "shortened";
|
|
1162
1193
|
if (vm.direction === "drifted") return ui?.oddsDrifted ?? "drifted";
|
|
@@ -1166,18 +1197,18 @@ function OddsMovementCard({ vm, ui }) {
|
|
|
1166
1197
|
const word = directionWord(vm, ui);
|
|
1167
1198
|
const drift = word ? `, ${word}` : "";
|
|
1168
1199
|
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,
|
|
1200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-omcard", children: [
|
|
1201
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-head", children: [
|
|
1202
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-market", children: vm.market }),
|
|
1203
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" })
|
|
1173
1204
|
] }),
|
|
1174
|
-
vm.fixture ? /* @__PURE__ */ (0,
|
|
1175
|
-
/* @__PURE__ */ (0,
|
|
1176
|
-
vm.competition ? /* @__PURE__ */ (0,
|
|
1205
|
+
vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-fixture", children: [
|
|
1206
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: vm.fixture }),
|
|
1207
|
+
vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-comp", children: vm.competition }) : null
|
|
1177
1208
|
] }) : null,
|
|
1178
|
-
/* @__PURE__ */ (0,
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1180
|
-
vm.geometry === null ? /* @__PURE__ */ (0,
|
|
1209
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-sel", children: vm.selection }),
|
|
1210
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
|
|
1211
|
+
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
1212
|
"svg",
|
|
1182
1213
|
{
|
|
1183
1214
|
className: "ss-w-om-chart",
|
|
@@ -1186,83 +1217,83 @@ function OddsMovementCard({ vm, ui }) {
|
|
|
1186
1217
|
role: "img",
|
|
1187
1218
|
"aria-label": aria,
|
|
1188
1219
|
children: [
|
|
1189
|
-
vm.geometry.gridlines.map((g) => /* @__PURE__ */ (0,
|
|
1190
|
-
/* @__PURE__ */ (0,
|
|
1191
|
-
/* @__PURE__ */ (0,
|
|
1220
|
+
vm.geometry.gridlines.map((g) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("g", { children: [
|
|
1221
|
+
/* @__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 }),
|
|
1222
|
+
/* @__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
1223
|
] }, 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,
|
|
1224
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
|
|
1225
|
+
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)),
|
|
1226
|
+
ui?.chartTimeLabel ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
1227
|
+
/* @__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) }),
|
|
1228
|
+
/* @__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) })
|
|
1229
|
+
] }) : /* @__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
1230
|
]
|
|
1200
1231
|
}
|
|
1201
1232
|
),
|
|
1202
|
-
/* @__PURE__ */ (0,
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1233
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-foot", children: [
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
|
|
1204
1235
|
ui?.openingLabel ?? "Opening",
|
|
1205
1236
|
" ",
|
|
1206
|
-
/* @__PURE__ */ (0,
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: vm.opening })
|
|
1207
1238
|
] }),
|
|
1208
|
-
/* @__PURE__ */ (0,
|
|
1239
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
|
|
1209
1240
|
ui?.currentLabel ?? "Current",
|
|
1210
1241
|
" ",
|
|
1211
|
-
/* @__PURE__ */ (0,
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: vm.current })
|
|
1212
1243
|
] })
|
|
1213
1244
|
] }),
|
|
1214
|
-
vm.bookmaker ? /* @__PURE__ */ (0,
|
|
1215
|
-
vm.excludedCount > 0 ? /* @__PURE__ */ (0,
|
|
1216
|
-
vm.isSuspended ? /* @__PURE__ */ (0,
|
|
1217
|
-
vm.disclaimer ? /* @__PURE__ */ (0,
|
|
1245
|
+
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,
|
|
1246
|
+
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,
|
|
1247
|
+
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,
|
|
1248
|
+
vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
|
|
1218
1249
|
] });
|
|
1219
1250
|
}
|
|
1220
1251
|
function OddsMovementCardList({ cards, ui }) {
|
|
1221
1252
|
if (!cards || cards.length === 0) return null;
|
|
1222
|
-
return /* @__PURE__ */ (0,
|
|
1253
|
+
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
1254
|
}
|
|
1224
1255
|
|
|
1225
1256
|
// src/components/ActionButtons.tsx
|
|
1226
|
-
var
|
|
1257
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1227
1258
|
function ActionButtons({ actions, loading, disabled, onAct }) {
|
|
1228
1259
|
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,
|
|
1260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-actions", children: [
|
|
1261
|
+
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}`)),
|
|
1262
|
+
actions.length === 0 && loading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-abtn-shimmer" }),
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-abtn-shimmer" })
|
|
1234
1265
|
] }) : null
|
|
1235
1266
|
] });
|
|
1236
1267
|
}
|
|
1237
1268
|
|
|
1238
1269
|
// src/components/dashboard/DashboardTile.tsx
|
|
1239
|
-
var
|
|
1270
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1240
1271
|
var MAX_CRESTS = 3;
|
|
1241
1272
|
function DashboardTile({ tile, onTap }) {
|
|
1242
1273
|
const spanClass = tile.span === "full" ? "ss-w-dash-tile--full" : "ss-w-dash-tile--half";
|
|
1243
1274
|
const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS);
|
|
1244
1275
|
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,
|
|
1276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: `ss-w-dash-tile ${spanClass}`, onClick: onTap, children: [
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DashboardIcon, { name: tile.icon }) }),
|
|
1278
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "ss-w-dash-tile-body", children: [
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-title", children: tile.title }),
|
|
1280
|
+
tile.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
|
|
1250
1281
|
hasMeta ? (
|
|
1251
1282
|
// Badge + crests sit on their own row, below the title, instead of sharing the
|
|
1252
1283
|
// icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone
|
|
1253
1284
|
// (~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,
|
|
1285
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "ss-w-dash-tile-meta", children: [
|
|
1286
|
+
tile.badgeText ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
|
|
1287
|
+
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
1288
|
] })
|
|
1258
1289
|
) : null
|
|
1259
1290
|
] }),
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronIcon, {}) })
|
|
1261
1292
|
] });
|
|
1262
1293
|
}
|
|
1263
1294
|
|
|
1264
1295
|
// src/components/dashboard/GreetingDashboard.tsx
|
|
1265
|
-
var
|
|
1296
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1266
1297
|
var LAYOUT_CLASSES = {
|
|
1267
1298
|
market: "ss-w-dash--market",
|
|
1268
1299
|
goal: "ss-w-dash--goal",
|
|
@@ -1272,106 +1303,140 @@ function layoutClass(layout) {
|
|
|
1272
1303
|
return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout) ? LAYOUT_CLASSES[layout] : LAYOUT_CLASSES.goal;
|
|
1273
1304
|
}
|
|
1274
1305
|
function GreetingDashboard({ dashboard, onTap }) {
|
|
1275
|
-
return /* @__PURE__ */ (0,
|
|
1276
|
-
/* @__PURE__ */ (0,
|
|
1277
|
-
/* @__PURE__ */ (0,
|
|
1278
|
-
dashboard.subtitle ? /* @__PURE__ */ (0,
|
|
1306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: `ss-w-dash ${layoutClass(dashboard.layout)}`, children: [
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-dash-head", children: [
|
|
1308
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-title", children: dashboard.title }),
|
|
1309
|
+
dashboard.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
|
|
1279
1310
|
] }),
|
|
1280
|
-
/* @__PURE__ */ (0,
|
|
1281
|
-
dashboard.footerTip ? /* @__PURE__ */ (0,
|
|
1311
|
+
/* @__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}`)) }),
|
|
1312
|
+
dashboard.footerTip ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
|
|
1282
1313
|
] });
|
|
1283
1314
|
}
|
|
1284
1315
|
|
|
1285
1316
|
// src/components/club-dashboard/GreetingHeaderBlock.tsx
|
|
1286
|
-
var
|
|
1317
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1287
1318
|
function GreetingHeaderBlock({ block }) {
|
|
1288
|
-
return /* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
|
|
1320
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
|
|
1321
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
|
|
1291
1322
|
] });
|
|
1292
1323
|
}
|
|
1293
1324
|
|
|
1294
1325
|
// src/components/club-dashboard/FixtureHeroBlock.tsx
|
|
1295
|
-
var
|
|
1296
|
-
var
|
|
1326
|
+
var import_react8 = require("react");
|
|
1327
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1297
1328
|
function initials3(name) {
|
|
1298
1329
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
1299
1330
|
}
|
|
1300
1331
|
function Crest3({ url, name }) {
|
|
1301
|
-
const [broken, setBroken] = (0,
|
|
1332
|
+
const [broken, setBroken] = (0, import_react8.useState)(false);
|
|
1302
1333
|
if (!url || broken) {
|
|
1303
|
-
return /* @__PURE__ */ (0,
|
|
1334
|
+
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
1335
|
}
|
|
1305
|
-
return /* @__PURE__ */ (0,
|
|
1336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
|
|
1306
1337
|
}
|
|
1307
1338
|
function FixtureHeroBlock({
|
|
1308
1339
|
block,
|
|
1309
1340
|
ui,
|
|
1310
1341
|
onAction
|
|
1311
1342
|
}) {
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1314
|
-
/* @__PURE__ */ (0,
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1316
|
-
/* @__PURE__ */ (0,
|
|
1317
|
-
/* @__PURE__ */ (0,
|
|
1318
|
-
/* @__PURE__ */ (0,
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
|
|
1344
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-tie", children: [
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.awayCrestUrl, name: block.awayName })
|
|
1319
1350
|
] }),
|
|
1320
|
-
/* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
block.venue ? /* @__PURE__ */ (0,
|
|
1323
|
-
block.competition ? /* @__PURE__ */ (0,
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
|
|
1353
|
+
block.venue ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
|
|
1354
|
+
block.competition ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
|
|
1324
1355
|
] }),
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, void 0, block.ctaLabel), children: block.ctaLabel })
|
|
1326
1357
|
] });
|
|
1327
1358
|
}
|
|
1328
1359
|
|
|
1329
1360
|
// src/components/club-dashboard/FormGuideBlock.tsx
|
|
1330
|
-
var
|
|
1361
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1331
1362
|
function FormGuideBlock({ block }) {
|
|
1332
1363
|
if (block.rows.length === 0) return null;
|
|
1333
|
-
return /* @__PURE__ */ (0,
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1364
|
+
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: [
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
|
|
1335
1366
|
row.name,
|
|
1336
1367
|
row.position != null ? ` #${row.position}` : ""
|
|
1337
1368
|
] }),
|
|
1338
|
-
/* @__PURE__ */ (0,
|
|
1369
|
+
/* @__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
1370
|
] }, row.name)) });
|
|
1340
1371
|
}
|
|
1341
1372
|
|
|
1342
1373
|
// src/components/club-dashboard/MatchPreviewBlock.tsx
|
|
1343
|
-
var
|
|
1374
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1344
1375
|
function MatchPreviewBlock({
|
|
1345
1376
|
block,
|
|
1346
1377
|
ui,
|
|
1347
1378
|
onAction
|
|
1348
1379
|
}) {
|
|
1349
|
-
if (block.
|
|
1380
|
+
if (block.facts.length === 0) return null;
|
|
1350
1381
|
const heading = ui.clubMatchPreviewHeading;
|
|
1351
|
-
return /* @__PURE__ */ (0,
|
|
1352
|
-
/* @__PURE__ */ (0,
|
|
1353
|
-
block.
|
|
1382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-cdash-lines", children: [
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1384
|
+
block.facts.map(
|
|
1385
|
+
(f, i) => f.entityRef ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1386
|
+
"button",
|
|
1387
|
+
{
|
|
1388
|
+
type: "button",
|
|
1389
|
+
className: "ss-w-cdash-fact",
|
|
1390
|
+
onClick: () => onAction(f.question ?? f.sentence, { ...f.entityRef, subject: f.sentence, personaHint: "club" }),
|
|
1391
|
+
children: [
|
|
1392
|
+
f.sentence,
|
|
1393
|
+
f.label ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
|
|
1394
|
+
" ",
|
|
1395
|
+
f.label
|
|
1396
|
+
] }) : null
|
|
1397
|
+
]
|
|
1398
|
+
},
|
|
1399
|
+
i
|
|
1400
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: f.sentence }, i)
|
|
1401
|
+
)
|
|
1354
1402
|
] });
|
|
1355
1403
|
}
|
|
1356
1404
|
|
|
1357
1405
|
// src/components/club-dashboard/TeamDnaBlock.tsx
|
|
1358
|
-
var
|
|
1406
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1359
1407
|
function TeamDnaBlock({
|
|
1360
1408
|
block,
|
|
1361
1409
|
ui,
|
|
1362
1410
|
onAction
|
|
1363
1411
|
}) {
|
|
1364
|
-
if (block.
|
|
1412
|
+
if (block.facts.length === 0) return null;
|
|
1365
1413
|
const heading = ui.clubTeamDnaHeading;
|
|
1366
|
-
return /* @__PURE__ */ (0,
|
|
1367
|
-
/* @__PURE__ */ (0,
|
|
1368
|
-
block.
|
|
1414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-lines", children: [
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1416
|
+
block.facts.map(
|
|
1417
|
+
(f, i) => f.entityRef ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
1418
|
+
"button",
|
|
1419
|
+
{
|
|
1420
|
+
type: "button",
|
|
1421
|
+
className: "ss-w-cdash-fact",
|
|
1422
|
+
onClick: () => onAction(f.question ?? f.sentence, { ...f.entityRef, subject: f.sentence, personaHint: "club" }),
|
|
1423
|
+
children: [
|
|
1424
|
+
f.sentence,
|
|
1425
|
+
f.label ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
|
|
1426
|
+
" ",
|
|
1427
|
+
f.label
|
|
1428
|
+
] }) : null
|
|
1429
|
+
]
|
|
1430
|
+
},
|
|
1431
|
+
i
|
|
1432
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: f.sentence }, i)
|
|
1433
|
+
)
|
|
1369
1434
|
] });
|
|
1370
1435
|
}
|
|
1371
1436
|
|
|
1372
1437
|
// src/components/club-dashboard/CountdownBlock.tsx
|
|
1373
|
-
var
|
|
1374
|
-
var
|
|
1438
|
+
var import_react9 = require("react");
|
|
1439
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1375
1440
|
var DAY_MS = 24 * 3600 * 1e3;
|
|
1376
1441
|
function pad2(n) {
|
|
1377
1442
|
return String(n).padStart(2, "0");
|
|
@@ -1384,8 +1449,8 @@ function splitRemaining(remainingMs) {
|
|
|
1384
1449
|
return { h: pad2(h), m: pad2(m), s: pad2(s) };
|
|
1385
1450
|
}
|
|
1386
1451
|
function CountdownBlock({ block, ui }) {
|
|
1387
|
-
const [remainingMs, setRemainingMs] = (0,
|
|
1388
|
-
(0,
|
|
1452
|
+
const [remainingMs, setRemainingMs] = (0, import_react9.useState)(() => block.kickoffUnix * 1e3 - Date.now());
|
|
1453
|
+
(0, import_react9.useEffect)(() => {
|
|
1389
1454
|
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1390
1455
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
1391
1456
|
const id = setInterval(() => {
|
|
@@ -1396,30 +1461,30 @@ function CountdownBlock({ block, ui }) {
|
|
|
1396
1461
|
if (remainingMs <= 0) return null;
|
|
1397
1462
|
if (remainingMs > DAY_MS) return null;
|
|
1398
1463
|
const { h, m, s } = splitRemaining(remainingMs);
|
|
1399
|
-
return /* @__PURE__ */ (0,
|
|
1400
|
-
/* @__PURE__ */ (0,
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
1464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
|
|
1465
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
|
|
1402
1467
|
"h",
|
|
1403
1468
|
" ",
|
|
1404
|
-
/* @__PURE__ */ (0,
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
|
|
1405
1470
|
"m",
|
|
1406
1471
|
" ",
|
|
1407
|
-
/* @__PURE__ */ (0,
|
|
1472
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
|
|
1408
1473
|
"s"
|
|
1409
1474
|
] }),
|
|
1410
|
-
/* @__PURE__ */ (0,
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
|
|
1411
1476
|
] });
|
|
1412
1477
|
}
|
|
1413
1478
|
|
|
1414
1479
|
// src/components/club-dashboard/ClubDashboard.tsx
|
|
1415
|
-
var
|
|
1480
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1416
1481
|
var CLUB_BLOCK_REGISTRY = {
|
|
1417
|
-
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0,
|
|
1418
|
-
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0,
|
|
1419
|
-
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0,
|
|
1420
|
-
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0,
|
|
1421
|
-
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0,
|
|
1422
|
-
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0,
|
|
1482
|
+
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingHeaderBlock, { block }) : null,
|
|
1483
|
+
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
|
|
1484
|
+
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FormGuideBlock, { block, ui }) : null,
|
|
1485
|
+
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
|
|
1486
|
+
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
|
|
1487
|
+
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CountdownBlock, { block, ui }) : null
|
|
1423
1488
|
};
|
|
1424
1489
|
function ClubDashboard({
|
|
1425
1490
|
dashboard,
|
|
@@ -1427,39 +1492,39 @@ function ClubDashboard({
|
|
|
1427
1492
|
onAction
|
|
1428
1493
|
}) {
|
|
1429
1494
|
if (!dashboard.blocks.length) return null;
|
|
1430
|
-
return /* @__PURE__ */ (0,
|
|
1495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
|
|
1431
1496
|
const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
|
|
1432
1497
|
if (!Comp) {
|
|
1433
1498
|
console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
|
|
1434
1499
|
return null;
|
|
1435
1500
|
}
|
|
1436
|
-
return /* @__PURE__ */ (0,
|
|
1501
|
+
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);
|
|
1437
1502
|
}) });
|
|
1438
1503
|
}
|
|
1439
1504
|
|
|
1440
1505
|
// src/components/ChatMessage.tsx
|
|
1441
|
-
var
|
|
1506
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1442
1507
|
function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
|
|
1443
1508
|
if (message.role === "user") {
|
|
1444
|
-
return /* @__PURE__ */ (0,
|
|
1509
|
+
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 }) });
|
|
1445
1510
|
}
|
|
1446
|
-
return /* @__PURE__ */ (0,
|
|
1447
|
-
message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0,
|
|
1448
|
-
message.greetingDashboard ? /* @__PURE__ */ (0,
|
|
1449
|
-
message.clubDashboard && ui ? /* @__PURE__ */ (0,
|
|
1450
|
-
/* @__PURE__ */ (0,
|
|
1451
|
-
/* @__PURE__ */ (0,
|
|
1452
|
-
/* @__PURE__ */ (0,
|
|
1453
|
-
/* @__PURE__ */ (0,
|
|
1454
|
-
/* @__PURE__ */ (0,
|
|
1511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
1512
|
+
message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Markdown, { text: message.text }) : null,
|
|
1513
|
+
message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
|
|
1514
|
+
message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
|
|
1515
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
1516
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
|
|
1517
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
|
|
1518
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
|
|
1519
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
1455
1520
|
] });
|
|
1456
1521
|
}
|
|
1457
1522
|
|
|
1458
1523
|
// src/components/IntentChips.tsx
|
|
1459
|
-
var
|
|
1524
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1460
1525
|
function IntentChips({ chips, onPick }) {
|
|
1461
1526
|
if (chips.length === 0) return null;
|
|
1462
|
-
return /* @__PURE__ */ (0,
|
|
1527
|
+
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}`)) });
|
|
1463
1528
|
}
|
|
1464
1529
|
|
|
1465
1530
|
// src/scroll.ts
|
|
@@ -1469,18 +1534,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
1469
1534
|
}
|
|
1470
1535
|
|
|
1471
1536
|
// src/components/MessageList.tsx
|
|
1472
|
-
var
|
|
1537
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1473
1538
|
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
1474
1539
|
const { state, send } = controller;
|
|
1475
|
-
const listRef = (0,
|
|
1476
|
-
const endRef = (0,
|
|
1477
|
-
const pinnedRef = (0,
|
|
1478
|
-
(0,
|
|
1540
|
+
const listRef = (0, import_react10.useRef)(null);
|
|
1541
|
+
const endRef = (0, import_react10.useRef)(null);
|
|
1542
|
+
const pinnedRef = (0, import_react10.useRef)(true);
|
|
1543
|
+
(0, import_react10.useEffect)(() => {
|
|
1479
1544
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
1480
1545
|
}, [state.messages, state.status]);
|
|
1481
1546
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
1482
1547
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
|
|
1483
|
-
return /* @__PURE__ */ (0,
|
|
1548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1484
1549
|
"div",
|
|
1485
1550
|
{
|
|
1486
1551
|
className: "ss-w-list",
|
|
@@ -1490,7 +1555,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1490
1555
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
1491
1556
|
},
|
|
1492
1557
|
children: [
|
|
1493
|
-
state.messages.map((m) => /* @__PURE__ */ (0,
|
|
1558
|
+
state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1494
1559
|
ChatMessage,
|
|
1495
1560
|
{
|
|
1496
1561
|
message: m,
|
|
@@ -1500,31 +1565,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1500
1565
|
send(tile.actionValue, { displayText: tile.title });
|
|
1501
1566
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
1502
1567
|
},
|
|
1503
|
-
onClubAction: (
|
|
1568
|
+
onClubAction: (message, grounding, displayText) => send(message, { grounding, displayText: displayText ?? message }),
|
|
1504
1569
|
ui,
|
|
1505
1570
|
slip
|
|
1506
1571
|
},
|
|
1507
1572
|
m.id
|
|
1508
1573
|
)),
|
|
1509
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0,
|
|
1574
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
1510
1575
|
} }) : null,
|
|
1511
|
-
state.status ? /* @__PURE__ */ (0,
|
|
1512
|
-
state.error ? /* @__PURE__ */ (0,
|
|
1513
|
-
/* @__PURE__ */ (0,
|
|
1514
|
-
/* @__PURE__ */ (0,
|
|
1576
|
+
state.status ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
|
|
1577
|
+
state.error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
|
|
1578
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
1579
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
1515
1580
|
] }) : null,
|
|
1516
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0,
|
|
1517
|
-
/* @__PURE__ */ (0,
|
|
1581
|
+
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
1582
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: endRef })
|
|
1518
1583
|
]
|
|
1519
1584
|
}
|
|
1520
1585
|
);
|
|
1521
1586
|
}
|
|
1522
1587
|
|
|
1523
1588
|
// src/components/ChatInput.tsx
|
|
1524
|
-
var
|
|
1525
|
-
var
|
|
1589
|
+
var import_react11 = require("react");
|
|
1590
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1526
1591
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
1527
|
-
const [value, setValue] = (0,
|
|
1592
|
+
const [value, setValue] = (0, import_react11.useState)("");
|
|
1528
1593
|
const submit = () => {
|
|
1529
1594
|
const t = value.trim();
|
|
1530
1595
|
if (!t) return;
|
|
@@ -1537,18 +1602,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
1537
1602
|
submit();
|
|
1538
1603
|
}
|
|
1539
1604
|
};
|
|
1540
|
-
return /* @__PURE__ */ (0,
|
|
1541
|
-
/* @__PURE__ */ (0,
|
|
1542
|
-
streaming ? /* @__PURE__ */ (0,
|
|
1605
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-input", children: [
|
|
1606
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
1607
|
+
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, {}) })
|
|
1543
1608
|
] });
|
|
1544
1609
|
}
|
|
1545
1610
|
|
|
1546
1611
|
// src/components/ChatPanel.tsx
|
|
1547
|
-
var
|
|
1612
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1548
1613
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
1549
1614
|
function useIsModal() {
|
|
1550
|
-
const [modal, setModal] = (0,
|
|
1551
|
-
(0,
|
|
1615
|
+
const [modal, setModal] = (0, import_react12.useState)(false);
|
|
1616
|
+
(0, import_react12.useEffect)(() => {
|
|
1552
1617
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1553
1618
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
1554
1619
|
const sync = () => setModal(mql.matches);
|
|
@@ -1561,17 +1626,17 @@ function useIsModal() {
|
|
|
1561
1626
|
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
1562
1627
|
const { state, close, stop, send } = controller;
|
|
1563
1628
|
const isModal = useIsModal();
|
|
1564
|
-
(0,
|
|
1629
|
+
(0, import_react12.useEffect)(() => {
|
|
1565
1630
|
const onKey = (e) => {
|
|
1566
1631
|
if (e.key === "Escape") close();
|
|
1567
1632
|
};
|
|
1568
1633
|
window.addEventListener("keydown", onKey);
|
|
1569
1634
|
return () => window.removeEventListener("keydown", onKey);
|
|
1570
1635
|
}, [close]);
|
|
1571
|
-
return /* @__PURE__ */ (0,
|
|
1572
|
-
/* @__PURE__ */ (0,
|
|
1573
|
-
/* @__PURE__ */ (0,
|
|
1574
|
-
/* @__PURE__ */ (0,
|
|
1636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
|
|
1639
|
+
/* @__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 })
|
|
1575
1640
|
] });
|
|
1576
1641
|
}
|
|
1577
1642
|
|
|
@@ -1619,7 +1684,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1619
1684
|
.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; }
|
|
1620
1685
|
|
|
1621
1686
|
/* panel */
|
|
1622
|
-
.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(
|
|
1687
|
+
.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); }
|
|
1623
1688
|
.ss-w-root[data-ss-w-pos="right"] .ss-w-panel { right: var(--ss-w-offset-x); }
|
|
1624
1689
|
.ss-w-root[data-ss-w-pos="left"] .ss-w-panel { left: var(--ss-w-offset-x); }
|
|
1625
1690
|
@media (max-width: 639px) {
|
|
@@ -1722,9 +1787,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1722
1787
|
.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; }
|
|
1723
1788
|
|
|
1724
1789
|
/* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */
|
|
1725
|
-
.ss-w-bi-comp-logo { width:
|
|
1726
|
-
.ss-w-bi-crest { width:
|
|
1727
|
-
.ss-w-bi-crest-mono { display: grid; place-items: center; font-size:
|
|
1790
|
+
.ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
|
|
1791
|
+
.ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
|
|
1792
|
+
.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)); }
|
|
1728
1793
|
|
|
1729
1794
|
/* row 2: crest-flanked fixture on the left, boxed action panel on the right */
|
|
1730
1795
|
.ss-w-bi-body { display: flex; align-items: center; gap: 10px; }
|
|
@@ -1732,16 +1797,16 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1732
1797
|
.ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1733
1798
|
.ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }
|
|
1734
1799
|
.ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1735
|
-
.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items:
|
|
1736
|
-
.ss-w-bi-action .ss-w-slip
|
|
1800
|
+
.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 0; }
|
|
1801
|
+
.ss-w-bi-action .ss-w-slip { width: 100%; }
|
|
1802
|
+
.ss-w-bi-action .ss-w-slip > button { flex: 1; width: 100%; text-align: center; border-radius: 8px; }
|
|
1737
1803
|
/* 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. */
|
|
1738
1804
|
.ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
|
|
1739
|
-
.ss-w-bi-mkt { display: flex; flex-direction: column; gap:
|
|
1740
|
-
.ss-w-bi-market { font-size:
|
|
1741
|
-
.ss-w-bi-sel { font-size:
|
|
1742
|
-
.ss-w-bi-odds { flex: none; display: flex;
|
|
1743
|
-
.ss-w-bi-odds
|
|
1744
|
-
.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; }
|
|
1805
|
+
.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; align-items: flex-end; text-align: right; }
|
|
1806
|
+
.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--ss-w-faint); white-space: nowrap; }
|
|
1807
|
+
.ss-w-bi-sel { font-size: 11px; line-height: 1.25; color: var(--ss-w-faint); }
|
|
1808
|
+
.ss-w-bi-odds { flex: none; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }
|
|
1809
|
+
.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; }
|
|
1745
1810
|
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
1746
1811
|
|
|
1747
1812
|
/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
|
|
@@ -1755,11 +1820,11 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1755
1820
|
}
|
|
1756
1821
|
.ss-w-bi-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }
|
|
1757
1822
|
.ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
|
|
1758
|
-
.ss-w-bi-
|
|
1759
|
-
.ss-w-bi-
|
|
1760
|
-
.ss-w-bi-
|
|
1761
|
-
.ss-w-bi-
|
|
1762
|
-
.ss-w-bi-
|
|
1823
|
+
.ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
1824
|
+
.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; }
|
|
1825
|
+
.ss-w-bi-expand:hover { color: var(--ss-w-ink); }
|
|
1826
|
+
.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; }
|
|
1827
|
+
.ss-w-bi-arrow-open { transform: rotate(135deg); }
|
|
1763
1828
|
.ss-w-bi-rows { display: flex; flex-direction: column; }
|
|
1764
1829
|
.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); }
|
|
1765
1830
|
.ss-w-bi-row:first-child { border-top: none; }
|
|
@@ -1774,11 +1839,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1774
1839
|
/* market odds card */
|
|
1775
1840
|
.ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
|
|
1776
1841
|
.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; }
|
|
1777
|
-
.ss-w-mo-
|
|
1778
|
-
.ss-w-mo-
|
|
1779
|
-
.ss-w-mo-
|
|
1780
|
-
.ss-w-mo-
|
|
1781
|
-
.ss-w-mo-
|
|
1842
|
+
.ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
|
|
1843
|
+
.ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1844
|
+
.ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }
|
|
1845
|
+
.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; }
|
|
1846
|
+
.ss-w-mo-more:hover { text-decoration: underline; }
|
|
1847
|
+
.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; }
|
|
1848
|
+
.ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }
|
|
1782
1849
|
.ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }
|
|
1783
1850
|
.ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }
|
|
1784
1851
|
.ss-w-mo-row:last-child { border-bottom: none; }
|
|
@@ -1950,9 +2017,12 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1950
2017
|
.ss-w-cdash-pill--d { background: var(--ss-w-faint); }
|
|
1951
2018
|
.ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
|
|
1952
2019
|
|
|
1953
|
-
.ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px;
|
|
2020
|
+
.ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px; }
|
|
1954
2021
|
.ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
|
|
1955
|
-
.ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); }
|
|
2022
|
+
.ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); margin: 0; }
|
|
2023
|
+
.ss-w-cdash-fact { display: block; width: 100%; text-align: left; font: inherit; font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); background: none; border: none; padding: 0; cursor: pointer; }
|
|
2024
|
+
.ss-w-cdash-fact:hover, .ss-w-cdash-fact:focus-visible { color: var(--ss-w-accent); text-decoration: underline; }
|
|
2025
|
+
.ss-w-cdash-fact-label { font-size: 11px; font-weight: 700; color: var(--ss-w-accent); }
|
|
1956
2026
|
|
|
1957
2027
|
.ss-w-cdash-cd { display: flex; flex-direction: column; align-items: center; gap: 4px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; text-align: center; }
|
|
1958
2028
|
.ss-w-cdash-cd-clock { display: flex; align-items: baseline; justify-content: center; gap: 2px; font-variant-numeric: tabular-nums; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-weight: 700; font-size: 18px; color: var(--ss-w-ink); }
|
|
@@ -1961,7 +2031,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1961
2031
|
`;
|
|
1962
2032
|
|
|
1963
2033
|
// src/StatsWidget.tsx
|
|
1964
|
-
var
|
|
2034
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1965
2035
|
function buildClient(props) {
|
|
1966
2036
|
try {
|
|
1967
2037
|
if ("client" in props && props.client) {
|
|
@@ -1986,11 +2056,11 @@ function injectStyles(root) {
|
|
|
1986
2056
|
function StatsWidget(props) {
|
|
1987
2057
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
1988
2058
|
const cfg = props.config;
|
|
1989
|
-
const built = (0,
|
|
1990
|
-
const ui = (0,
|
|
1991
|
-
const rootRef = (0,
|
|
2059
|
+
const built = (0, import_react13.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
2060
|
+
const ui = (0, import_react13.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
2061
|
+
const rootRef = (0, import_react13.useRef)(null);
|
|
1992
2062
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
1993
|
-
const slip = (0,
|
|
2063
|
+
const slip = (0, import_react13.useMemo)(
|
|
1994
2064
|
() => ({
|
|
1995
2065
|
onAddToSlip: props.config?.onAddToSlip,
|
|
1996
2066
|
conversationId: controller.state.conversationId ?? void 0,
|
|
@@ -2003,18 +2073,18 @@ function StatsWidget(props) {
|
|
|
2003
2073
|
}),
|
|
2004
2074
|
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
2005
2075
|
);
|
|
2006
|
-
const onDashboardTap = (0,
|
|
2076
|
+
const onDashboardTap = (0, import_react13.useMemo)(
|
|
2007
2077
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
2008
2078
|
[built]
|
|
2009
2079
|
);
|
|
2010
|
-
(0,
|
|
2080
|
+
(0, import_react13.useEffect)(() => {
|
|
2011
2081
|
if (!built || !ui.injectStyles) return;
|
|
2012
2082
|
const node = rootRef.current?.getRootNode();
|
|
2013
2083
|
if (node) injectStyles(node);
|
|
2014
2084
|
}, [built, ui.injectStyles]);
|
|
2015
2085
|
if (!built) return null;
|
|
2016
2086
|
const attrs = themeAttrs(ui);
|
|
2017
|
-
return /* @__PURE__ */ (0,
|
|
2087
|
+
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)(
|
|
2018
2088
|
ChatFab,
|
|
2019
2089
|
{
|
|
2020
2090
|
label: ui.launcherLabel,
|