@sensiblestats/widget-react 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/index.cjs +296 -132
- 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 +350 -186
- package/dist/index.js.map +1 -1
- package/dist/styles.css +51 -2
- 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_react12 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/i18n.ts
|
|
@@ -79,6 +79,12 @@ var STRINGS = {
|
|
|
79
79
|
const drift = direction ? `, ${direction}` : "";
|
|
80
80
|
return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`;
|
|
81
81
|
},
|
|
82
|
+
clubMatchPreviewHeading: "Match preview",
|
|
83
|
+
clubTeamDnaHeading: "How they play",
|
|
84
|
+
clubFormHeading: "Recent form",
|
|
85
|
+
clubCountdownLabel: "Countdown to kick-off",
|
|
86
|
+
clubKickoff: (ms) => new Intl.DateTimeFormat("en-GB", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
|
|
87
|
+
clubKickoffAria: (ms) => `Kick-off ${new Intl.DateTimeFormat("en-GB", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }).format(new Date(ms))}`,
|
|
82
88
|
inSlip: "In slip",
|
|
83
89
|
slipAdded: (n) => n === void 0 ? "Added to slip" : `Added to slip (${n} selection${n === 1 ? "" : "s"})`,
|
|
84
90
|
slipDuplicate: "Already in your slip",
|
|
@@ -126,6 +132,12 @@ var STRINGS = {
|
|
|
126
132
|
const drift = direction ? `, ${direction}` : "";
|
|
127
133
|
return `Son ${span} i\xE7indeki oran hareketi: ${opening} ile a\xE7\u0131ld\u0131, \u015Fu anda ${current}${drift}.`;
|
|
128
134
|
},
|
|
135
|
+
clubMatchPreviewHeading: "Ma\xE7 \xF6nizlemesi",
|
|
136
|
+
clubTeamDnaHeading: "Nas\u0131l oynuyorlar",
|
|
137
|
+
clubFormHeading: "Son form",
|
|
138
|
+
clubCountdownLabel: "Ba\u015Flama vuru\u015Funa kalan",
|
|
139
|
+
clubKickoff: (ms) => new Intl.DateTimeFormat("tr-TR", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
|
|
140
|
+
clubKickoffAria: (ms) => `Ba\u015Flama vuru\u015Fu ${new Intl.DateTimeFormat("tr-TR", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }).format(new Date(ms))}`,
|
|
129
141
|
inSlip: "Kuponda",
|
|
130
142
|
slipAdded: (n) => n === void 0 ? "Kupona eklendi" : `Kupona eklendi (${n} se\xE7im)`,
|
|
131
143
|
slipDuplicate: "Bu se\xE7im kuponunuzda zaten var",
|
|
@@ -185,6 +197,12 @@ function normalizeUi(cfg) {
|
|
|
185
197
|
excludedSuspended: strings.excludedSuspended,
|
|
186
198
|
chartTimeLabel: strings.chartTimeLabel,
|
|
187
199
|
chartAria: strings.chartAria,
|
|
200
|
+
clubMatchPreviewHeading: strings.clubMatchPreviewHeading,
|
|
201
|
+
clubTeamDnaHeading: strings.clubTeamDnaHeading,
|
|
202
|
+
clubFormHeading: strings.clubFormHeading,
|
|
203
|
+
clubCountdownLabel: strings.clubCountdownLabel,
|
|
204
|
+
clubKickoff: strings.clubKickoff,
|
|
205
|
+
clubKickoffAria: strings.clubKickoffAria,
|
|
188
206
|
addToSlip: strings.addToSlip,
|
|
189
207
|
inSlip: strings.inSlip,
|
|
190
208
|
slipAdded: strings.slipAdded,
|
|
@@ -531,7 +549,8 @@ function applyEvent(state, event) {
|
|
|
531
549
|
messages: mapActive(state, (t) => ({
|
|
532
550
|
...t,
|
|
533
551
|
done: true,
|
|
534
|
-
greetingDashboard: event.data.dashboard ?? void 0
|
|
552
|
+
greetingDashboard: event.data.dashboard ?? void 0,
|
|
553
|
+
clubDashboard: event.data.clubDashboard ?? void 0
|
|
535
554
|
}))
|
|
536
555
|
};
|
|
537
556
|
}
|
|
@@ -655,88 +674,27 @@ function SendIcon() {
|
|
|
655
674
|
function CloseIcon() {
|
|
656
675
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2" }) });
|
|
657
676
|
}
|
|
658
|
-
function FootballIcon() {
|
|
659
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
660
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
661
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M12 7l3.5 2.5-1.3 4.1H9.8L8.5 9.5z" })
|
|
662
|
-
] });
|
|
663
|
-
}
|
|
664
|
-
function GoalNetIcon() {
|
|
665
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
666
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "5", width: "18", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
667
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1", d: "M3 9h18M3 13h18M8 5v12M16 5v12" })
|
|
668
|
-
] });
|
|
669
|
-
}
|
|
670
|
-
function BttsIcon() {
|
|
671
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
672
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "12", r: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
673
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "16", cy: "12", r: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
|
|
674
|
-
] });
|
|
675
|
-
}
|
|
676
|
-
function CardIcon() {
|
|
677
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "6", y: "3", width: "12", height: "18", rx: "1.5", fill: "currentColor" }) });
|
|
678
|
-
}
|
|
679
|
-
function CornerFlagIcon() {
|
|
680
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
681
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.6", d: "M6 21V4" }),
|
|
682
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M6 4l11 3.5L6 11z" })
|
|
683
|
-
] });
|
|
684
|
-
}
|
|
685
|
-
function PlayerIcon() {
|
|
686
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
687
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "7", r: "3.2", fill: "currentColor" }),
|
|
688
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M5 20c0-4 3-6.5 7-6.5s7 2.5 7 6.5z" })
|
|
689
|
-
] });
|
|
690
|
-
}
|
|
691
|
-
function TargetIcon() {
|
|
692
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
693
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
694
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
695
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "1.4", fill: "currentColor" })
|
|
696
|
-
] });
|
|
697
|
-
}
|
|
698
|
-
function TrophyIcon() {
|
|
699
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
|
|
700
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M7 3h10v4a5 5 0 0 1-5 5 5 5 0 0 1-5-5zM9 15h6v3H9zM7 19h10v2H7z" }),
|
|
701
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.4", d: "M7 5H4v2a3 3 0 0 0 3 3M17 5h3v2a3 3 0 0 1-3 3" })
|
|
702
|
-
] });
|
|
703
|
-
}
|
|
704
|
-
function ChartLineIcon() {
|
|
705
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", d: "M4 17l5-6 4 3 7-9" }) });
|
|
706
|
-
}
|
|
707
|
-
function ChartBarIcon() {
|
|
708
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M5 12h3v8H5zM10.5 7h3v13h-3zM16 15h3v5h-3z" }) });
|
|
709
|
-
}
|
|
710
|
-
function ChatIcon() {
|
|
711
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.6", d: "M4 5h16v11H9l-4 4z" }) });
|
|
712
|
-
}
|
|
713
|
-
function FireIcon() {
|
|
714
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M12 2c1 3-2 4-2 7a3 3 0 0 0 6 0c1 1 2 2.5 2 4.5A6 6 0 0 1 6 14c0-4 3-5 3-9 1 1 1.5 2 1.5 3C11.5 6 11 4 12 2z" }) });
|
|
715
|
-
}
|
|
716
|
-
function SparkleIcon() {
|
|
717
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M12 2l1.6 6.4L20 10l-6.4 1.6L12 18l-1.6-6.4L4 10l6.4-1.6z" }) });
|
|
718
|
-
}
|
|
719
677
|
function ChevronIcon() {
|
|
720
678
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
|
|
721
679
|
}
|
|
722
|
-
var
|
|
723
|
-
football:
|
|
724
|
-
"goal-net":
|
|
725
|
-
btts:
|
|
726
|
-
card:
|
|
727
|
-
"corner-flag":
|
|
728
|
-
player:
|
|
729
|
-
target:
|
|
730
|
-
trophy:
|
|
731
|
-
"chart-line":
|
|
732
|
-
"chart-bar":
|
|
733
|
-
chat:
|
|
734
|
-
fire:
|
|
735
|
-
sparkle:
|
|
680
|
+
var DASHBOARD_EMOJI = {
|
|
681
|
+
football: "\u26BD",
|
|
682
|
+
"goal-net": "\u{1F945}",
|
|
683
|
+
btts: "\u{1F91D}",
|
|
684
|
+
card: "\u{1F7E8}",
|
|
685
|
+
"corner-flag": "\u{1F6A9}",
|
|
686
|
+
player: "\u{1F464}",
|
|
687
|
+
target: "\u{1F3AF}",
|
|
688
|
+
trophy: "\u{1F3C6}",
|
|
689
|
+
"chart-line": "\u{1F4C8}",
|
|
690
|
+
"chart-bar": "\u{1F4CA}",
|
|
691
|
+
chat: "\u{1F4AC}",
|
|
692
|
+
fire: "\u{1F525}",
|
|
693
|
+
sparkle: "\u2728"
|
|
736
694
|
};
|
|
737
695
|
function DashboardIcon({ name }) {
|
|
738
|
-
const
|
|
739
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
696
|
+
const glyph = Object.prototype.hasOwnProperty.call(DASHBOARD_EMOJI, name) ? DASHBOARD_EMOJI[name] : DASHBOARD_EMOJI.target;
|
|
697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ss-w-dash-emoji", "aria-hidden": "true", children: glyph });
|
|
740
698
|
}
|
|
741
699
|
|
|
742
700
|
// src/components/GreetingBubble.tsx
|
|
@@ -759,7 +717,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
759
717
|
}
|
|
760
718
|
|
|
761
719
|
// src/components/ChatPanel.tsx
|
|
762
|
-
var
|
|
720
|
+
var import_react11 = require("react");
|
|
763
721
|
|
|
764
722
|
// src/components/ChatHeader.tsx
|
|
765
723
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -772,7 +730,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
772
730
|
}
|
|
773
731
|
|
|
774
732
|
// src/components/MessageList.tsx
|
|
775
|
-
var
|
|
733
|
+
var import_react9 = require("react");
|
|
776
734
|
|
|
777
735
|
// src/components/Markdown.tsx
|
|
778
736
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -1256,28 +1214,184 @@ function GreetingDashboard({ dashboard, onTap }) {
|
|
|
1256
1214
|
] });
|
|
1257
1215
|
}
|
|
1258
1216
|
|
|
1259
|
-
// src/components/
|
|
1217
|
+
// src/components/club-dashboard/GreetingHeaderBlock.tsx
|
|
1260
1218
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1261
|
-
function
|
|
1219
|
+
function GreetingHeaderBlock({ block }) {
|
|
1220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
|
|
1221
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
|
|
1223
|
+
] });
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
// src/components/club-dashboard/FixtureHeroBlock.tsx
|
|
1227
|
+
var import_react7 = require("react");
|
|
1228
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1229
|
+
function initials2(name) {
|
|
1230
|
+
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
1231
|
+
}
|
|
1232
|
+
function Crest2({ url, name }) {
|
|
1233
|
+
const [broken, setBroken] = (0, import_react7.useState)(false);
|
|
1234
|
+
if (!url || broken) {
|
|
1235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials2(name) });
|
|
1236
|
+
}
|
|
1237
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
|
|
1238
|
+
}
|
|
1239
|
+
function FixtureHeroBlock({
|
|
1240
|
+
block,
|
|
1241
|
+
ui,
|
|
1242
|
+
onAction
|
|
1243
|
+
}) {
|
|
1244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
|
|
1245
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-tie", children: [
|
|
1246
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: block.homeCrestUrl, name: block.homeName }),
|
|
1247
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
|
|
1248
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: block.awayCrestUrl, name: block.awayName })
|
|
1251
|
+
] }),
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
|
|
1253
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
|
|
1254
|
+
block.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
|
|
1255
|
+
block.competition ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
|
|
1256
|
+
] }),
|
|
1257
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, block.ctaLabel), children: block.ctaLabel })
|
|
1258
|
+
] });
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
// src/components/club-dashboard/FormGuideBlock.tsx
|
|
1262
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1263
|
+
function FormGuideBlock({ block }) {
|
|
1264
|
+
if (block.rows.length === 0) return null;
|
|
1265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
|
|
1266
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
|
|
1267
|
+
row.name,
|
|
1268
|
+
row.position != null ? ` #${row.position}` : ""
|
|
1269
|
+
] }),
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
|
|
1271
|
+
] }, row.name)) });
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// src/components/club-dashboard/MatchPreviewBlock.tsx
|
|
1275
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1276
|
+
function MatchPreviewBlock({
|
|
1277
|
+
block,
|
|
1278
|
+
ui,
|
|
1279
|
+
onAction
|
|
1280
|
+
}) {
|
|
1281
|
+
if (block.lines.length === 0) return null;
|
|
1282
|
+
const heading = ui.clubMatchPreviewHeading;
|
|
1283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
|
|
1284
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1285
|
+
block.lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { children: line }, i))
|
|
1286
|
+
] });
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// src/components/club-dashboard/TeamDnaBlock.tsx
|
|
1290
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1291
|
+
function TeamDnaBlock({
|
|
1292
|
+
block,
|
|
1293
|
+
ui,
|
|
1294
|
+
onAction
|
|
1295
|
+
}) {
|
|
1296
|
+
if (block.lines.length === 0) return null;
|
|
1297
|
+
const heading = ui.clubTeamDnaHeading;
|
|
1298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
|
|
1299
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1300
|
+
block.lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: line }, i))
|
|
1301
|
+
] });
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// src/components/club-dashboard/CountdownBlock.tsx
|
|
1305
|
+
var import_react8 = require("react");
|
|
1306
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1307
|
+
var DAY_MS = 24 * 3600 * 1e3;
|
|
1308
|
+
function pad2(n) {
|
|
1309
|
+
return String(n).padStart(2, "0");
|
|
1310
|
+
}
|
|
1311
|
+
function splitRemaining(remainingMs) {
|
|
1312
|
+
const totalSeconds = Math.max(0, Math.floor(remainingMs / 1e3));
|
|
1313
|
+
const h = Math.floor(totalSeconds / 3600);
|
|
1314
|
+
const m = Math.floor(totalSeconds % 3600 / 60);
|
|
1315
|
+
const s = totalSeconds % 60;
|
|
1316
|
+
return { h: pad2(h), m: pad2(m), s: pad2(s) };
|
|
1317
|
+
}
|
|
1318
|
+
function CountdownBlock({ block, ui }) {
|
|
1319
|
+
const [remainingMs, setRemainingMs] = (0, import_react8.useState)(() => block.kickoffUnix * 1e3 - Date.now());
|
|
1320
|
+
(0, import_react8.useEffect)(() => {
|
|
1321
|
+
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1322
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
1323
|
+
const id = setInterval(() => {
|
|
1324
|
+
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1325
|
+
}, 1e3);
|
|
1326
|
+
return () => clearInterval(id);
|
|
1327
|
+
}, [block.kickoffUnix]);
|
|
1328
|
+
if (remainingMs <= 0) return null;
|
|
1329
|
+
if (remainingMs > DAY_MS) return null;
|
|
1330
|
+
const { h, m, s } = splitRemaining(remainingMs);
|
|
1331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
|
|
1333
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
|
|
1334
|
+
"h",
|
|
1335
|
+
" ",
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
|
|
1337
|
+
"m",
|
|
1338
|
+
" ",
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
|
|
1340
|
+
"s"
|
|
1341
|
+
] }),
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
|
|
1343
|
+
] });
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
// src/components/club-dashboard/ClubDashboard.tsx
|
|
1347
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1348
|
+
var CLUB_BLOCK_REGISTRY = {
|
|
1349
|
+
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GreetingHeaderBlock, { block }) : null,
|
|
1350
|
+
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
|
|
1351
|
+
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FormGuideBlock, { block, ui }) : null,
|
|
1352
|
+
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
|
|
1353
|
+
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
|
|
1354
|
+
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CountdownBlock, { block, ui }) : null
|
|
1355
|
+
};
|
|
1356
|
+
function ClubDashboard({
|
|
1357
|
+
dashboard,
|
|
1358
|
+
ui,
|
|
1359
|
+
onAction
|
|
1360
|
+
}) {
|
|
1361
|
+
if (!dashboard.blocks.length) return null;
|
|
1362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
|
|
1363
|
+
const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
|
|
1364
|
+
if (!Comp) {
|
|
1365
|
+
console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
|
|
1366
|
+
return null;
|
|
1367
|
+
}
|
|
1368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp, { block, ui, onAction }) }, i);
|
|
1369
|
+
}) });
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
// src/components/ChatMessage.tsx
|
|
1373
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1374
|
+
function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
|
|
1262
1375
|
if (message.role === "user") {
|
|
1263
|
-
return /* @__PURE__ */ (0,
|
|
1376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
|
|
1264
1377
|
}
|
|
1265
|
-
return /* @__PURE__ */ (0,
|
|
1266
|
-
message.text ? /* @__PURE__ */ (0,
|
|
1267
|
-
message.greetingDashboard ? /* @__PURE__ */ (0,
|
|
1268
|
-
/* @__PURE__ */ (0,
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1271
|
-
/* @__PURE__ */ (0,
|
|
1272
|
-
/* @__PURE__ */ (0,
|
|
1378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
1379
|
+
message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Markdown, { text: message.text }) : null,
|
|
1380
|
+
message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
|
|
1381
|
+
message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
|
|
1384
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
|
|
1385
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
|
|
1386
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
1273
1387
|
] });
|
|
1274
1388
|
}
|
|
1275
1389
|
|
|
1276
1390
|
// src/components/IntentChips.tsx
|
|
1277
|
-
var
|
|
1391
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1278
1392
|
function IntentChips({ chips, onPick }) {
|
|
1279
1393
|
if (chips.length === 0) return null;
|
|
1280
|
-
return /* @__PURE__ */ (0,
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
1281
1395
|
}
|
|
1282
1396
|
|
|
1283
1397
|
// src/scroll.ts
|
|
@@ -1287,18 +1401,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
1287
1401
|
}
|
|
1288
1402
|
|
|
1289
1403
|
// src/components/MessageList.tsx
|
|
1290
|
-
var
|
|
1404
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1291
1405
|
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
1292
1406
|
const { state, send } = controller;
|
|
1293
|
-
const listRef = (0,
|
|
1294
|
-
const endRef = (0,
|
|
1295
|
-
const pinnedRef = (0,
|
|
1296
|
-
(0,
|
|
1407
|
+
const listRef = (0, import_react9.useRef)(null);
|
|
1408
|
+
const endRef = (0, import_react9.useRef)(null);
|
|
1409
|
+
const pinnedRef = (0, import_react9.useRef)(true);
|
|
1410
|
+
(0, import_react9.useEffect)(() => {
|
|
1297
1411
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
1298
1412
|
}, [state.messages, state.status]);
|
|
1299
1413
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
1300
1414
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
|
|
1301
|
-
return /* @__PURE__ */ (0,
|
|
1415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1302
1416
|
"div",
|
|
1303
1417
|
{
|
|
1304
1418
|
className: "ss-w-list",
|
|
@@ -1308,7 +1422,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1308
1422
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
1309
1423
|
},
|
|
1310
1424
|
children: [
|
|
1311
|
-
state.messages.map((m) => /* @__PURE__ */ (0,
|
|
1425
|
+
state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1312
1426
|
ChatMessage,
|
|
1313
1427
|
{
|
|
1314
1428
|
message: m,
|
|
@@ -1318,30 +1432,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1318
1432
|
send(tile.actionValue, { displayText: tile.title });
|
|
1319
1433
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
1320
1434
|
},
|
|
1435
|
+
onClubAction: (actionValue, displayText) => send(actionValue, { displayText }),
|
|
1321
1436
|
ui,
|
|
1322
1437
|
slip
|
|
1323
1438
|
},
|
|
1324
1439
|
m.id
|
|
1325
1440
|
)),
|
|
1326
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0,
|
|
1441
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
1327
1442
|
} }) : null,
|
|
1328
|
-
state.status ? /* @__PURE__ */ (0,
|
|
1329
|
-
state.error ? /* @__PURE__ */ (0,
|
|
1330
|
-
/* @__PURE__ */ (0,
|
|
1331
|
-
/* @__PURE__ */ (0,
|
|
1443
|
+
state.status ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
|
|
1444
|
+
state.error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
1332
1447
|
] }) : null,
|
|
1333
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0,
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1448
|
+
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
1449
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: endRef })
|
|
1335
1450
|
]
|
|
1336
1451
|
}
|
|
1337
1452
|
);
|
|
1338
1453
|
}
|
|
1339
1454
|
|
|
1340
1455
|
// src/components/ChatInput.tsx
|
|
1341
|
-
var
|
|
1342
|
-
var
|
|
1456
|
+
var import_react10 = require("react");
|
|
1457
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1343
1458
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
1344
|
-
const [value, setValue] = (0,
|
|
1459
|
+
const [value, setValue] = (0, import_react10.useState)("");
|
|
1345
1460
|
const submit = () => {
|
|
1346
1461
|
const t = value.trim();
|
|
1347
1462
|
if (!t) return;
|
|
@@ -1354,18 +1469,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
1354
1469
|
submit();
|
|
1355
1470
|
}
|
|
1356
1471
|
};
|
|
1357
|
-
return /* @__PURE__ */ (0,
|
|
1358
|
-
/* @__PURE__ */ (0,
|
|
1359
|
-
streaming ? /* @__PURE__ */ (0,
|
|
1472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-input", children: [
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
1474
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendIcon, {}) })
|
|
1360
1475
|
] });
|
|
1361
1476
|
}
|
|
1362
1477
|
|
|
1363
1478
|
// src/components/ChatPanel.tsx
|
|
1364
|
-
var
|
|
1479
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1365
1480
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
1366
1481
|
function useIsModal() {
|
|
1367
|
-
const [modal, setModal] = (0,
|
|
1368
|
-
(0,
|
|
1482
|
+
const [modal, setModal] = (0, import_react11.useState)(false);
|
|
1483
|
+
(0, import_react11.useEffect)(() => {
|
|
1369
1484
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1370
1485
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
1371
1486
|
const sync = () => setModal(mql.matches);
|
|
@@ -1378,17 +1493,17 @@ function useIsModal() {
|
|
|
1378
1493
|
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
1379
1494
|
const { state, close, stop, send } = controller;
|
|
1380
1495
|
const isModal = useIsModal();
|
|
1381
|
-
(0,
|
|
1496
|
+
(0, import_react11.useEffect)(() => {
|
|
1382
1497
|
const onKey = (e) => {
|
|
1383
1498
|
if (e.key === "Escape") close();
|
|
1384
1499
|
};
|
|
1385
1500
|
window.addEventListener("keydown", onKey);
|
|
1386
1501
|
return () => window.removeEventListener("keydown", onKey);
|
|
1387
1502
|
}, [close]);
|
|
1388
|
-
return /* @__PURE__ */ (0,
|
|
1389
|
-
/* @__PURE__ */ (0,
|
|
1390
|
-
/* @__PURE__ */ (0,
|
|
1391
|
-
/* @__PURE__ */ (0,
|
|
1503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
|
|
1506
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
1392
1507
|
] });
|
|
1393
1508
|
}
|
|
1394
1509
|
|
|
@@ -1665,7 +1780,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1665
1780
|
min-width: 0; /* the panel is min(400px, 100vw - 40px): without this,
|
|
1666
1781
|
a long Turkish title blows the column out */
|
|
1667
1782
|
}
|
|
1668
|
-
.ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width:
|
|
1783
|
+
.ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width: 28px; height: 28px; font-size: 22px; }
|
|
1784
|
+
.ss-w-dash-emoji { line-height: 1; }
|
|
1669
1785
|
.ss-w-dash-tile-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; }
|
|
1670
1786
|
.ss-w-dash-tile-title { min-width: 0; font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }
|
|
1671
1787
|
.ss-w-dash-tile-subtitle { min-width: 0; font-size: 11.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }
|
|
@@ -1695,15 +1811,63 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1695
1811
|
.ss-w-dash--goal .ss-w-dash-grid { grid-template-columns: 1fr; }
|
|
1696
1812
|
.ss-w-dash--goal .ss-w-dash-tile { border-radius: 999px; padding: 10px 14px; }
|
|
1697
1813
|
|
|
1698
|
-
/* Discovery: tinted bento cards.
|
|
1814
|
+
/* Discovery: tinted bento cards. Stacked (icon over text) so a two- or three-word title gets
|
|
1815
|
+
the tile's full width instead of the ~100px left of a horizontal icon+chevron -- that narrow
|
|
1816
|
+
column was wrapping "Most interesting angles" onto three lines. The chevron is dropped (the
|
|
1817
|
+
whole card is the tap target) and the badge + crest row is forced onto one line. */
|
|
1818
|
+
.ss-w-dash--discovery .ss-w-dash-tile { flex-direction: column; align-items: stretch; gap: 8px; }
|
|
1819
|
+
.ss-w-dash--discovery .ss-w-dash-tile-icon { align-self: flex-start; width: 32px; height: 32px; font-size: 26px; }
|
|
1820
|
+
.ss-w-dash--discovery .ss-w-dash-tile-chevron { display: none; }
|
|
1821
|
+
/* The full-span trends tile has the whole panel width, so its icon and title sit on one row
|
|
1822
|
+
(horizontal, centre-aligned) rather than stacking like the narrow half tiles. */
|
|
1823
|
+
.ss-w-dash--discovery .ss-w-dash-tile--full { flex-direction: row; align-items: center; }
|
|
1824
|
+
.ss-w-dash--discovery .ss-w-dash-tile--full .ss-w-dash-tile-icon { align-self: center; }
|
|
1825
|
+
.ss-w-dash--discovery .ss-w-dash-tile-meta { flex-wrap: nowrap; }
|
|
1826
|
+
.ss-w-dash--discovery .ss-w-dash-tile-crest { width: 22px; height: 22px; }
|
|
1699
1827
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: #eef8f1; }
|
|
1700
1828
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }
|
|
1701
1829
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }
|
|
1702
1830
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }
|
|
1831
|
+
|
|
1832
|
+
/* club match-day dashboard */
|
|
1833
|
+
.ss-w-cdash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
|
|
1834
|
+
.ss-w-cdash-block { display: flex; flex-direction: column; }
|
|
1835
|
+
|
|
1836
|
+
.ss-w-cdash-greeting { display: flex; flex-direction: column; gap: 2px; }
|
|
1837
|
+
.ss-w-cdash-greeting-title { font-weight: 700; font-size: 14px; color: var(--ss-w-ink); }
|
|
1838
|
+
.ss-w-cdash-greeting-subtitle { font-size: 11.5px; color: var(--ss-w-faint); }
|
|
1839
|
+
|
|
1840
|
+
.ss-w-cdash-fixture { display: flex; flex-direction: column; align-items: center; gap: 8px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 12px; text-align: center; }
|
|
1841
|
+
.ss-w-cdash-tie { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
|
|
1842
|
+
.ss-w-cdash-team { font-weight: 650; font-size: 13px; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
|
|
1843
|
+
.ss-w-cdash-vs { font-size: 11px; color: var(--ss-w-faint); font-weight: 600; }
|
|
1844
|
+
.ss-w-cdash-crest { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--ss-w-bubble); }
|
|
1845
|
+
.ss-w-cdash-crest--fallback { display: grid; place-items: center; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
|
|
1846
|
+
.ss-w-cdash-fixture-meta { display: flex; align-items: center; justify-content: center; gap: 6px; flex-wrap: wrap; font-size: 11px; color: var(--ss-w-faint); }
|
|
1847
|
+
.ss-w-cdash-kickoff { font-weight: 700; color: var(--ss-w-ink); }
|
|
1848
|
+
.ss-w-cdash-cta { font: inherit; font-weight: 700; font-size: 12px; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: none; border-radius: 999px; padding: 8px 18px; cursor: pointer; }
|
|
1849
|
+
|
|
1850
|
+
.ss-w-cdash-form { display: flex; flex-direction: column; gap: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; }
|
|
1851
|
+
.ss-w-cdash-form-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
1852
|
+
.ss-w-cdash-form-name { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
|
|
1853
|
+
.ss-w-cdash-form-pills { flex: none; display: flex; align-items: center; gap: 3px; }
|
|
1854
|
+
.ss-w-cdash-pill { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; font-size: 9.5px; font-weight: 700; color: #fff; }
|
|
1855
|
+
.ss-w-cdash-pill--w { background: color-mix(in srgb, var(--ss-w-pos) 88%, black); }
|
|
1856
|
+
.ss-w-cdash-pill--d { background: var(--ss-w-faint); }
|
|
1857
|
+
.ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
|
|
1858
|
+
|
|
1859
|
+
.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; font: inherit; cursor: pointer; }
|
|
1860
|
+
.ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
|
|
1861
|
+
.ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); }
|
|
1862
|
+
|
|
1863
|
+
.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; }
|
|
1864
|
+
.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); }
|
|
1865
|
+
.ss-w-cdash-cd-h, .ss-w-cdash-cd-m, .ss-w-cdash-cd-s { color: var(--ss-w-accent); }
|
|
1866
|
+
.ss-w-cdash-cd-label { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }
|
|
1703
1867
|
`;
|
|
1704
1868
|
|
|
1705
1869
|
// src/StatsWidget.tsx
|
|
1706
|
-
var
|
|
1870
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1707
1871
|
function buildClient(props) {
|
|
1708
1872
|
try {
|
|
1709
1873
|
if ("client" in props && props.client) {
|
|
@@ -1728,11 +1892,11 @@ function injectStyles(root) {
|
|
|
1728
1892
|
function StatsWidget(props) {
|
|
1729
1893
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
1730
1894
|
const cfg = props.config;
|
|
1731
|
-
const built = (0,
|
|
1732
|
-
const ui = (0,
|
|
1733
|
-
const rootRef = (0,
|
|
1895
|
+
const built = (0, import_react12.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
1896
|
+
const ui = (0, import_react12.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
1897
|
+
const rootRef = (0, import_react12.useRef)(null);
|
|
1734
1898
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
1735
|
-
const slip = (0,
|
|
1899
|
+
const slip = (0, import_react12.useMemo)(
|
|
1736
1900
|
() => ({
|
|
1737
1901
|
onAddToSlip: props.config?.onAddToSlip,
|
|
1738
1902
|
conversationId: controller.state.conversationId ?? void 0,
|
|
@@ -1745,18 +1909,18 @@ function StatsWidget(props) {
|
|
|
1745
1909
|
}),
|
|
1746
1910
|
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
1747
1911
|
);
|
|
1748
|
-
const onDashboardTap = (0,
|
|
1912
|
+
const onDashboardTap = (0, import_react12.useMemo)(
|
|
1749
1913
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
1750
1914
|
[built]
|
|
1751
1915
|
);
|
|
1752
|
-
(0,
|
|
1916
|
+
(0, import_react12.useEffect)(() => {
|
|
1753
1917
|
if (!built || !ui.injectStyles) return;
|
|
1754
1918
|
const node = rootRef.current?.getRootNode();
|
|
1755
1919
|
if (node) injectStyles(node);
|
|
1756
1920
|
}, [built, ui.injectStyles]);
|
|
1757
1921
|
if (!built) return null;
|
|
1758
1922
|
const attrs = themeAttrs(ui);
|
|
1759
|
-
return /* @__PURE__ */ (0,
|
|
1923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.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_runtime28.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1760
1924
|
ChatFab,
|
|
1761
1925
|
{
|
|
1762
1926
|
label: ui.launcherLabel,
|