@sensiblestats/widget-react 0.29.2 → 0.29.4
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 +14 -0
- package/dist/index.cjs +246 -108
- 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 +227 -89
- package/dist/index.js.map +1 -1
- package/dist/styles.css +74 -29
- 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_react19 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/kickoff.ts
|
|
@@ -876,7 +876,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
876
876
|
}
|
|
877
877
|
|
|
878
878
|
// src/components/ChatPanel.tsx
|
|
879
|
-
var
|
|
879
|
+
var import_react18 = require("react");
|
|
880
880
|
|
|
881
881
|
// src/components/ChatHeader.tsx
|
|
882
882
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -889,7 +889,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
889
889
|
}
|
|
890
890
|
|
|
891
891
|
// src/components/MessageList.tsx
|
|
892
|
-
var
|
|
892
|
+
var import_react16 = require("react");
|
|
893
893
|
|
|
894
894
|
// src/components/Markdown.tsx
|
|
895
895
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -1469,17 +1469,20 @@ function resultClass(result) {
|
|
|
1469
1469
|
function FormStrip({ form }) {
|
|
1470
1470
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-form", children: form.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: `ss-w-fandash-form-pill ${resultClass(r)}`, children: r }, `${r}-${i}`)) });
|
|
1471
1471
|
}
|
|
1472
|
-
function FormRow({ name, form }) {
|
|
1472
|
+
function FormRow({ name, form, crestUrl }) {
|
|
1473
1473
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-formrow", children: [
|
|
1474
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.
|
|
1474
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-formrow-team", children: [
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: crestUrl ?? void 0, name, kind: "team" }),
|
|
1476
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-formrow-name", children: name })
|
|
1477
|
+
] }),
|
|
1475
1478
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormStrip, { form })
|
|
1476
1479
|
] });
|
|
1477
1480
|
}
|
|
1478
|
-
function FixtureCard({ card
|
|
1481
|
+
function FixtureCard({ card }) {
|
|
1479
1482
|
const { data } = card;
|
|
1480
1483
|
const h2h = data.h2H;
|
|
1481
1484
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1482
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-fixture", children: [
|
|
1483
1486
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-eyebrow", children: [
|
|
1484
1487
|
card.title,
|
|
1485
1488
|
" \xB7 ",
|
|
@@ -1497,22 +1500,18 @@ function FixtureCard({ card, onTap }) {
|
|
|
1497
1500
|
] })
|
|
1498
1501
|
] }),
|
|
1499
1502
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-meta", children: [
|
|
1500
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
data.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-metarow", children: [
|
|
1505
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-metakey", children: data.venueLabel }),
|
|
1506
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-metaval", children: data.venue })
|
|
1503
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-kickoff", children: data.kickoffLabel }),
|
|
1504
|
+
data.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-fixture-venue", children: [
|
|
1505
|
+
" \xB7 ",
|
|
1506
|
+
data.venue
|
|
1507
1507
|
] }) : null
|
|
1508
|
-
] })
|
|
1509
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1508
|
+
] })
|
|
1510
1509
|
] }),
|
|
1511
1510
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-lastfive", children: [
|
|
1512
1511
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-eyebrow", children: data.formLabel }),
|
|
1513
1512
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-form", children: [
|
|
1514
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormRow, { name: data.homeName, form: data.homeForm }),
|
|
1515
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormRow, { name: data.awayName, form: data.awayForm })
|
|
1513
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormRow, { name: data.homeName, form: data.homeForm, crestUrl: data.homeCrestUrl }),
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormRow, { name: data.awayName, form: data.awayForm, crestUrl: data.awayCrestUrl })
|
|
1516
1515
|
] })
|
|
1517
1516
|
] }),
|
|
1518
1517
|
h2h || data.fact ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-h2h", children: [
|
|
@@ -1582,16 +1581,19 @@ function CountdownCard({ card }) {
|
|
|
1582
1581
|
}
|
|
1583
1582
|
|
|
1584
1583
|
// src/components/dashboard/InjuriesCard.tsx
|
|
1584
|
+
var import_react10 = require("react");
|
|
1585
1585
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1586
|
+
var SHOWN = 3;
|
|
1586
1587
|
function ColHead({ name, crestUrl }) {
|
|
1587
1588
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-fandash-injuries-col-head", children: [
|
|
1588
1589
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Crest2, { url: crestUrl ?? void 0, name, kind: "team" }),
|
|
1589
1590
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injuries-col-head-name", children: name })
|
|
1590
1591
|
] });
|
|
1591
1592
|
}
|
|
1592
|
-
function InjuryList({ rows, emptyLabel }) {
|
|
1593
|
+
function InjuryList({ rows, emptyLabel, limit }) {
|
|
1593
1594
|
if (rows.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injuries-empty", children: emptyLabel });
|
|
1594
|
-
|
|
1595
|
+
const shown = limit === void 0 ? rows : rows.slice(0, limit);
|
|
1596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "ss-w-fandash-injury-list", children: shown.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: "ss-w-fandash-injury-row", children: [
|
|
1595
1597
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injury-name", children: r.playerName }),
|
|
1596
1598
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-fandash-injury-meta", children: [
|
|
1597
1599
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injury-status", children: r.status }),
|
|
@@ -1600,21 +1602,36 @@ function InjuryList({ rows, emptyLabel }) {
|
|
|
1600
1602
|
] })
|
|
1601
1603
|
] }, `${r.playerName}-${i}`)) });
|
|
1602
1604
|
}
|
|
1603
|
-
function InjuriesCard({ card }) {
|
|
1605
|
+
function InjuriesCard({ card, ui }) {
|
|
1604
1606
|
const { data } = card;
|
|
1607
|
+
const [expanded, setExpanded] = (0, import_react10.useState)(false);
|
|
1608
|
+
const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
|
|
1609
|
+
const limit = expanded ? void 0 : SHOWN;
|
|
1610
|
+
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
1611
|
+
const showLess = ui?.showLess ?? "Show less";
|
|
1605
1612
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-injuries", children: [
|
|
1606
1613
|
card.title ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
1607
1614
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-injuries-cols", children: [
|
|
1608
1615
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-injuries-col", children: [
|
|
1609
1616
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColHead, { name: data.oursName, crestUrl: data.oursCrestUrl }),
|
|
1610
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InjuryList, { rows: data.ours, emptyLabel: data.emptyLabel })
|
|
1617
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InjuryList, { rows: data.ours, emptyLabel: data.emptyLabel, limit })
|
|
1611
1618
|
] }),
|
|
1612
1619
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-fandash-injuries-divider" }),
|
|
1613
1620
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-injuries-col", children: [
|
|
1614
1621
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColHead, { name: data.theirsName, crestUrl: data.theirsCrestUrl }),
|
|
1615
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InjuryList, { rows: data.theirs, emptyLabel: data.emptyLabel })
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InjuryList, { rows: data.theirs, emptyLabel: data.emptyLabel, limit })
|
|
1616
1623
|
] })
|
|
1617
|
-
] })
|
|
1624
|
+
] }),
|
|
1625
|
+
hidden > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1626
|
+
"button",
|
|
1627
|
+
{
|
|
1628
|
+
type: "button",
|
|
1629
|
+
className: "ss-w-fandash-injuries-more",
|
|
1630
|
+
"aria-expanded": expanded,
|
|
1631
|
+
onClick: () => setExpanded((v) => !v),
|
|
1632
|
+
children: expanded ? showLess : showMore(hidden)
|
|
1633
|
+
}
|
|
1634
|
+
) : null
|
|
1618
1635
|
] });
|
|
1619
1636
|
}
|
|
1620
1637
|
|
|
@@ -1691,21 +1708,60 @@ function LinksCard({ card }) {
|
|
|
1691
1708
|
}
|
|
1692
1709
|
|
|
1693
1710
|
// src/components/dashboard/PostMatchResultCard.tsx
|
|
1711
|
+
var import_react11 = require("react");
|
|
1694
1712
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1713
|
+
function initials3(name) {
|
|
1714
|
+
return name.trim().slice(0, 3).toUpperCase();
|
|
1715
|
+
}
|
|
1716
|
+
function PostMatchCrest({
|
|
1717
|
+
url,
|
|
1718
|
+
name,
|
|
1719
|
+
side
|
|
1720
|
+
}) {
|
|
1721
|
+
const [failed, setFailed] = (0, import_react11.useState)(false);
|
|
1722
|
+
const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
|
|
1723
|
+
if (url && !failed) {
|
|
1724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1725
|
+
}
|
|
1726
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `${cls} ss-w-fandash-postmatch-crest--fallback`, "aria-hidden": "true", children: initials3(name) });
|
|
1727
|
+
}
|
|
1695
1728
|
function PostMatchResultCard({ card }) {
|
|
1696
1729
|
const { data } = card;
|
|
1730
|
+
const homeWon = data.homeScore >= data.awayScore;
|
|
1731
|
+
const awayWon = data.awayScore >= data.homeScore;
|
|
1697
1732
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-postmatch-result", children: [
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className:
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.
|
|
1704
|
-
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-postmatch-top", children: [
|
|
1734
|
+
card.title ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "ss-w-fandash-postmatch-pill", children: card.title }) : null,
|
|
1735
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `ss-w-fandash-postmatch-tag ss-w-fandash-postmatch-tag--${data.outcome}`, children: data.resultLabel })
|
|
1736
|
+
] }),
|
|
1737
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-postmatch-main", children: [
|
|
1738
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--home", children: [
|
|
1739
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PostMatchCrest, { url: data.homeCrestUrl, name: data.homeName, side: "home" }),
|
|
1740
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "ss-w-fandash-postmatch-team-name", children: data.homeName })
|
|
1741
|
+
] }),
|
|
1742
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-postmatch-score-main", children: [
|
|
1743
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1744
|
+
"span",
|
|
1745
|
+
{
|
|
1746
|
+
className: `ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${homeWon ? "win" : "lose"}`,
|
|
1747
|
+
children: data.homeScore
|
|
1748
|
+
}
|
|
1749
|
+
),
|
|
1750
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "ss-w-fandash-postmatch-score-sep", children: "\u2013" }),
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1752
|
+
"span",
|
|
1753
|
+
{
|
|
1754
|
+
className: `ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${awayWon ? "win" : "lose"}`,
|
|
1755
|
+
children: data.awayScore
|
|
1756
|
+
}
|
|
1757
|
+
)
|
|
1758
|
+
] }),
|
|
1759
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--away", children: [
|
|
1760
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PostMatchCrest, { url: data.awayCrestUrl, name: data.awayName, side: "away" }),
|
|
1761
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "ss-w-fandash-postmatch-team-name", children: data.awayName })
|
|
1762
|
+
] })
|
|
1705
1763
|
] }),
|
|
1706
1764
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash-postmatch-meta", children: [
|
|
1707
|
-
data.resultLabel,
|
|
1708
|
-
" \xB7 ",
|
|
1709
1765
|
data.kickoffLabel,
|
|
1710
1766
|
data.competition ? ` \xB7 ${data.competition}` : ""
|
|
1711
1767
|
] })
|
|
@@ -1717,38 +1773,75 @@ var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
|
1717
1773
|
function PostMatchGoalsCard({ card, onTap }) {
|
|
1718
1774
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-goals", onClick: () => onTap(card), children: [
|
|
1719
1775
|
card.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
1720
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "ss-w-fandash-postmatch-goal-list", children: card.data.goals.map((g, i) => /* @__PURE__ */ (0, import_jsx_runtime26.
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "ss-w-fandash-postmatch-goal-list", children: card.data.goals.map((g, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("li", { className: g.scoredByClub ? "ss-w-fandash-postmatch-goal ss-w-fandash-postmatch-goal--club" : "ss-w-fandash-postmatch-goal", children: [
|
|
1777
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ss-w-fandash-postmatch-goal-ball" }),
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: g.text })
|
|
1779
|
+
] }, `${g.text}-${i}`)) }),
|
|
1721
1780
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1722
1781
|
] });
|
|
1723
1782
|
}
|
|
1724
1783
|
|
|
1725
1784
|
// src/components/dashboard/PostMatchStatsCard.tsx
|
|
1726
1785
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1786
|
+
function splitWidths(homeNum, awayNum) {
|
|
1787
|
+
const total = homeNum + awayNum;
|
|
1788
|
+
if (total <= 0) return { home: "50%", away: "50%" };
|
|
1789
|
+
const homePct = Math.round(homeNum / total * 1e3) / 10;
|
|
1790
|
+
return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` };
|
|
1791
|
+
}
|
|
1727
1792
|
function PostMatchStatsCard({ card, onTap }) {
|
|
1793
|
+
const { data } = card;
|
|
1728
1794
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-stats", onClick: () => onTap(card), children: [
|
|
1729
1795
|
card.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
1730
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ss-w-fandash-postmatch-stat-rows", children:
|
|
1731
|
-
const leftValue =
|
|
1732
|
-
const rightValue =
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1796
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ss-w-fandash-postmatch-stat-rows", children: data.rows.map((r, i) => {
|
|
1797
|
+
const leftValue = data.clubIsHome ? r.clubValue : r.oppValue;
|
|
1798
|
+
const rightValue = data.clubIsHome ? r.oppValue : r.clubValue;
|
|
1799
|
+
const homeNum = data.clubIsHome ? r.clubNum : r.oppNum;
|
|
1800
|
+
const awayNum = data.clubIsHome ? r.oppNum : r.clubNum;
|
|
1801
|
+
const { home, away } = splitWidths(homeNum, awayNum);
|
|
1802
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-fandash-postmatch-stat", children: [
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-fandash-postmatch-stat-row", children: [
|
|
1804
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--home", children: leftValue }),
|
|
1805
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-postmatch-stat-label", children: r.label }),
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--away", children: rightValue })
|
|
1807
|
+
] }),
|
|
1808
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-fandash-postmatch-stat-bar", children: [
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-postmatch-stat-bar-home", style: { width: home } }),
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-postmatch-stat-bar-away", style: { width: away } })
|
|
1811
|
+
] })
|
|
1737
1812
|
] }, `${r.label}-${i}`);
|
|
1738
1813
|
}) }),
|
|
1814
|
+
data.rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-fandash-postmatch-legend", children: [
|
|
1815
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "ss-w-fandash-postmatch-legend-item", children: [
|
|
1816
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("i", { className: "ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--home" }),
|
|
1817
|
+
data.homeName
|
|
1818
|
+
] }),
|
|
1819
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "ss-w-fandash-postmatch-legend-item", children: [
|
|
1820
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("i", { className: "ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--away" }),
|
|
1821
|
+
data.awayName
|
|
1822
|
+
] })
|
|
1823
|
+
] }) : null,
|
|
1739
1824
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1740
1825
|
] });
|
|
1741
1826
|
}
|
|
1742
1827
|
|
|
1743
1828
|
// src/components/dashboard/PostMatchTopPerformerCard.tsx
|
|
1744
1829
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1830
|
+
function initials4(playerName) {
|
|
1831
|
+
const words = playerName.trim().split(/\s+/).filter(Boolean);
|
|
1832
|
+
if (words.length === 0) return "?";
|
|
1833
|
+
const first = words[0].charAt(0);
|
|
1834
|
+
const last = words[words.length - 1].charAt(0);
|
|
1835
|
+
return (words.length > 1 ? `${first}${last}` : first).toUpperCase();
|
|
1836
|
+
}
|
|
1745
1837
|
function PostMatchTopPerformerCard({ card, onTap }) {
|
|
1746
1838
|
const { data } = card;
|
|
1747
1839
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-performer", onClick: () => onTap(card), children: [
|
|
1748
1840
|
card.title ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
|
|
1749
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "ss-w-fandash-postmatch-
|
|
1750
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-postmatch-
|
|
1751
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-postmatch-
|
|
1841
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "ss-w-fandash-postmatch-perf-row", children: [
|
|
1842
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-postmatch-perf-avatar", "aria-hidden": "true", children: initials4(data.playerName) }),
|
|
1843
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-postmatch-perf-name", children: data.playerName }),
|
|
1844
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-postmatch-perf-rating", children: data.ratingLabel })
|
|
1752
1845
|
] }),
|
|
1753
1846
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
|
|
1754
1847
|
] });
|
|
@@ -1824,10 +1917,10 @@ function RestingFormCard({ card }) {
|
|
|
1824
1917
|
}
|
|
1825
1918
|
|
|
1826
1919
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
1827
|
-
var
|
|
1920
|
+
var import_react13 = require("react");
|
|
1828
1921
|
|
|
1829
1922
|
// src/useLiveClock.ts
|
|
1830
|
-
var
|
|
1923
|
+
var import_react12 = require("react");
|
|
1831
1924
|
var TICK_MS = 6e4;
|
|
1832
1925
|
var MAX_LIVE_TICK_MINUTES = 15;
|
|
1833
1926
|
function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
@@ -1836,10 +1929,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
|
1836
1929
|
return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
|
|
1837
1930
|
}
|
|
1838
1931
|
function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
1839
|
-
const [displayMinute, setDisplayMinute] = (0,
|
|
1932
|
+
const [displayMinute, setDisplayMinute] = (0, import_react12.useState)(
|
|
1840
1933
|
() => computeDisplayMinute(minute, clockRunning, receivedAtMs)
|
|
1841
1934
|
);
|
|
1842
|
-
(0,
|
|
1935
|
+
(0, import_react12.useEffect)(() => {
|
|
1843
1936
|
setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
|
|
1844
1937
|
if (!clockRunning) return;
|
|
1845
1938
|
const id = window.setInterval(() => {
|
|
@@ -1852,16 +1945,16 @@ function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
|
1852
1945
|
|
|
1853
1946
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
1854
1947
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1855
|
-
function
|
|
1948
|
+
function initials5(name) {
|
|
1856
1949
|
return name.trim().slice(0, 3).toUpperCase();
|
|
1857
1950
|
}
|
|
1858
1951
|
function LiveCrest({ url, name, side }) {
|
|
1859
|
-
const [failed, setFailed] = (0,
|
|
1952
|
+
const [failed, setFailed] = (0, import_react13.useState)(false);
|
|
1860
1953
|
const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
|
|
1861
1954
|
if (url && !failed) {
|
|
1862
1955
|
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1863
1956
|
}
|
|
1864
|
-
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: `${cls} ss-w-fandash-live-crest--fallback`, "aria-hidden": "true", children:
|
|
1957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: `${cls} ss-w-fandash-live-crest--fallback`, "aria-hidden": "true", children: initials5(name) });
|
|
1865
1958
|
}
|
|
1866
1959
|
function scorersLine(goalEvents) {
|
|
1867
1960
|
if (!goalEvents || goalEvents.length === 0) return null;
|
|
@@ -1875,7 +1968,7 @@ function LiveScoreCard({
|
|
|
1875
1968
|
}) {
|
|
1876
1969
|
const { data } = card;
|
|
1877
1970
|
const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
|
|
1878
|
-
const seedRef = (0,
|
|
1971
|
+
const seedRef = (0, import_react13.useRef)(null);
|
|
1879
1972
|
if (!seedRef.current || seedRef.current.key !== seedKey) {
|
|
1880
1973
|
seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
|
|
1881
1974
|
}
|
|
@@ -1915,9 +2008,9 @@ function LiveScoreCard({
|
|
|
1915
2008
|
}
|
|
1916
2009
|
|
|
1917
2010
|
// src/components/dashboard/LiveTimelineCard.tsx
|
|
1918
|
-
var
|
|
2011
|
+
var import_react14 = require("react");
|
|
1919
2012
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1920
|
-
var
|
|
2013
|
+
var SHOWN2 = 3;
|
|
1921
2014
|
function EventIcon({ type }) {
|
|
1922
2015
|
if (type === "goal") {
|
|
1923
2016
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "ss-w-fandash-live-tl-ico ss-w-fandash-live-tl-ico--goal", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "ss-w-fandash-live-tl-ball" }) });
|
|
@@ -1957,12 +2050,12 @@ function EventRow({ e }) {
|
|
|
1957
2050
|
] });
|
|
1958
2051
|
}
|
|
1959
2052
|
function LiveTimelineCard({ card, ui }) {
|
|
1960
|
-
const [expanded, setExpanded] = (0,
|
|
2053
|
+
const [expanded, setExpanded] = (0, import_react14.useState)(false);
|
|
1961
2054
|
const events = card.data.events;
|
|
1962
2055
|
if (!events || events.length === 0) return null;
|
|
1963
2056
|
const sorted = [...events].sort((a, b) => b.minute - a.minute);
|
|
1964
|
-
const rest = sorted.length -
|
|
1965
|
-
const shown = expanded ? sorted : sorted.slice(0,
|
|
2057
|
+
const rest = sorted.length - SHOWN2;
|
|
2058
|
+
const shown = expanded ? sorted : sorted.slice(0, SHOWN2);
|
|
1966
2059
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
1967
2060
|
const showLess = ui?.showLess ?? "Show less";
|
|
1968
2061
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-live-timeline", children: [
|
|
@@ -1982,7 +2075,7 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
1982
2075
|
}
|
|
1983
2076
|
|
|
1984
2077
|
// src/components/dashboard/MomentumWave.tsx
|
|
1985
|
-
var
|
|
2078
|
+
var import_react15 = require("react");
|
|
1986
2079
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1987
2080
|
var WIDTH = 270;
|
|
1988
2081
|
var HEIGHT = 56;
|
|
@@ -2005,7 +2098,7 @@ function MomentumWave({
|
|
|
2005
2098
|
}) {
|
|
2006
2099
|
if (points.length === 0) return null;
|
|
2007
2100
|
const { area, line, lastX, lastY } = buildPaths(points);
|
|
2008
|
-
const clipId = (0,
|
|
2101
|
+
const clipId = (0, import_react15.useId)();
|
|
2009
2102
|
const topClipId = `${clipId}-top`;
|
|
2010
2103
|
const bottomClipId = `${clipId}-bottom`;
|
|
2011
2104
|
const topClass = clubIsHome ? "ss-w-fandash-live-mom-home" : "ss-w-fandash-live-mom-away";
|
|
@@ -2038,7 +2131,7 @@ function MomentumWave({
|
|
|
2038
2131
|
|
|
2039
2132
|
// src/components/dashboard/LiveStatsCard.tsx
|
|
2040
2133
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2041
|
-
function
|
|
2134
|
+
function splitWidths2(homeNum, awayNum) {
|
|
2042
2135
|
const total = homeNum + awayNum;
|
|
2043
2136
|
if (total <= 0) return { home: "50%", away: "50%" };
|
|
2044
2137
|
const homePct = Math.round(homeNum / total * 1e3) / 10;
|
|
@@ -2053,7 +2146,7 @@ function LiveStatsCard({ card }) {
|
|
|
2053
2146
|
const awayValue = data.clubIsHome ? r.oppValue : r.clubValue;
|
|
2054
2147
|
const homeNum = data.clubIsHome ? r.clubNum : r.oppNum;
|
|
2055
2148
|
const awayNum = data.clubIsHome ? r.oppNum : r.clubNum;
|
|
2056
|
-
const { home, away } =
|
|
2149
|
+
const { home, away } = splitWidths2(homeNum, awayNum);
|
|
2057
2150
|
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "ss-w-fandash-live-stat", children: [
|
|
2058
2151
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "ss-w-fandash-live-stat-row", children: [
|
|
2059
2152
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--home", children: homeValue }),
|
|
@@ -2099,11 +2192,11 @@ function ClubFanDashboard({ dashboard, onTap, ui }) {
|
|
|
2099
2192
|
function FanDashboardCard({ card, onTap, ui, goalEvents }) {
|
|
2100
2193
|
switch (card.cardType) {
|
|
2101
2194
|
case "fixture":
|
|
2102
|
-
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FixtureCard, { card
|
|
2195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FixtureCard, { card });
|
|
2103
2196
|
case "countdown":
|
|
2104
2197
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(CountdownCard, { card });
|
|
2105
2198
|
case "injuries":
|
|
2106
|
-
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(InjuriesCard, { card });
|
|
2199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(InjuriesCard, { card, ui });
|
|
2107
2200
|
case "reasonToBet":
|
|
2108
2201
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReasonToBetCard, { card });
|
|
2109
2202
|
case "whereToWatch":
|
|
@@ -2187,11 +2280,11 @@ function turnAnchor(messages) {
|
|
|
2187
2280
|
}
|
|
2188
2281
|
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
2189
2282
|
const { state, send } = controller;
|
|
2190
|
-
const listRef = (0,
|
|
2191
|
-
const endRef = (0,
|
|
2192
|
-
const pinnedRef = (0,
|
|
2193
|
-
const anchoredTurnRef = (0,
|
|
2194
|
-
(0,
|
|
2283
|
+
const listRef = (0, import_react16.useRef)(null);
|
|
2284
|
+
const endRef = (0, import_react16.useRef)(null);
|
|
2285
|
+
const pinnedRef = (0, import_react16.useRef)(true);
|
|
2286
|
+
const anchoredTurnRef = (0, import_react16.useRef)(null);
|
|
2287
|
+
(0, import_react16.useEffect)(() => {
|
|
2195
2288
|
const anchor = turnAnchor(state.messages);
|
|
2196
2289
|
const list = listRef.current;
|
|
2197
2290
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
@@ -2246,10 +2339,10 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
2246
2339
|
}
|
|
2247
2340
|
|
|
2248
2341
|
// src/components/ChatInput.tsx
|
|
2249
|
-
var
|
|
2342
|
+
var import_react17 = require("react");
|
|
2250
2343
|
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2251
2344
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
2252
|
-
const [value, setValue] = (0,
|
|
2345
|
+
const [value, setValue] = (0, import_react17.useState)("");
|
|
2253
2346
|
const submit = () => {
|
|
2254
2347
|
const t = value.trim();
|
|
2255
2348
|
if (!t) return;
|
|
@@ -2272,8 +2365,8 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
2272
2365
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2273
2366
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
2274
2367
|
function useIsModal() {
|
|
2275
|
-
const [modal, setModal] = (0,
|
|
2276
|
-
(0,
|
|
2368
|
+
const [modal, setModal] = (0, import_react18.useState)(false);
|
|
2369
|
+
(0, import_react18.useEffect)(() => {
|
|
2277
2370
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
2278
2371
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
2279
2372
|
const sync = () => setModal(mql.matches);
|
|
@@ -2286,7 +2379,7 @@ function useIsModal() {
|
|
|
2286
2379
|
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
2287
2380
|
const { state, close, stop, send } = controller;
|
|
2288
2381
|
const isModal = useIsModal();
|
|
2289
|
-
(0,
|
|
2382
|
+
(0, import_react18.useEffect)(() => {
|
|
2290
2383
|
const onKey = (e) => {
|
|
2291
2384
|
if (e.key === "Escape") close();
|
|
2292
2385
|
};
|
|
@@ -2699,10 +2792,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2699
2792
|
.ss-w-fandash-fixture-team--away .ss-w-fandash-fixture-name { text-align: right; }
|
|
2700
2793
|
.ss-w-fandash-fixture-vs { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }
|
|
2701
2794
|
/* date + venue as labelled rows, so a long stadium name gets its own line to ellipsis in */
|
|
2702
|
-
.ss-w-fandash-fixture-meta {
|
|
2703
|
-
.ss-w-fandash-fixture-
|
|
2704
|
-
.ss-w-fandash-fixture-
|
|
2705
|
-
.ss-w-fandash-fixture-metaval { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
|
|
2795
|
+
.ss-w-fandash-fixture-meta { border-top: 1px solid var(--ss-w-line); padding-top: 10px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }
|
|
2796
|
+
.ss-w-fandash-fixture-kickoff { font-weight: 700; color: var(--ss-w-ink); }
|
|
2797
|
+
.ss-w-fandash-fixture-venue { font-weight: 600; }
|
|
2706
2798
|
.ss-w-fandash-fact { font-size: 12px; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 8px; padding: 6px 8px; }
|
|
2707
2799
|
/* each head-to-head figure sits on its own shaded tile, so the grid gap separates wins/draws/losses */
|
|
2708
2800
|
.ss-w-fandash-h2h .ss-w-fandash-split-cell { background: var(--ss-w-bubble); border-radius: 10px; padding: 12px 6px; }
|
|
@@ -2712,7 +2804,12 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2712
2804
|
/* last-five: one row per side, team name left, form pills right */
|
|
2713
2805
|
.ss-w-fandash-fixture-form { display: flex; flex-direction: column; gap: 5px; }
|
|
2714
2806
|
.ss-w-fandash-formrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
2807
|
+
.ss-w-fandash-formrow-team { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
2808
|
+
.ss-w-fandash-formrow-team .ss-w-bi-crest { width: 20px; height: 20px; }
|
|
2809
|
+
.ss-w-fandash-formrow-team .ss-w-bi-crest-mono { font-size: 9px; }
|
|
2715
2810
|
.ss-w-fandash-formrow-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 600; }
|
|
2811
|
+
.ss-w-fandash-injuries-more { margin-top: 10px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }
|
|
2812
|
+
.ss-w-fandash-injuries-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }
|
|
2716
2813
|
.ss-w-fandash-form { display: inline-flex; gap: 3px; flex: none; }
|
|
2717
2814
|
.ss-w-fandash-form-pill {
|
|
2718
2815
|
display: inline-grid; place-items: center; width: 16px; height: 16px;
|
|
@@ -2776,35 +2873,76 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2776
2873
|
.ss-w-fandash-link-label { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }
|
|
2777
2874
|
.ss-w-fandash-link-chevron { flex: none; width: 12px; height: 12px; color: var(--ss-w-accent); }
|
|
2778
2875
|
|
|
2779
|
-
/* post-match result: full-time scoreboard
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
.ss-w-fandash-postmatch-
|
|
2784
|
-
.ss-w-fandash-postmatch-
|
|
2785
|
-
.ss-w-fandash-postmatch-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
.ss-w-fandash-postmatch-
|
|
2789
|
-
.ss-w-fandash-postmatch-
|
|
2876
|
+
/* post-match result: full-time scoreboard, mirroring the live card's crest + big-score treatment.
|
|
2877
|
+
A neutral "Full time" pill sits left of a coloured Win/Draw/Loss tag; the 3-column main row
|
|
2878
|
+
(home crest+name | score | away crest+name, away reversed) puts the winner's score in full ink
|
|
2879
|
+
and the loser's dimmed; a centered meta line sits under a divider. */
|
|
2880
|
+
.ss-w-fandash-postmatch-top { display: flex; align-items: center; gap: 8px; margin-bottom: 15px; }
|
|
2881
|
+
.ss-w-fandash-postmatch-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 6px; padding: 3px 8px; }
|
|
2882
|
+
.ss-w-fandash-postmatch-tag { margin-left: auto; flex: none; font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
|
|
2883
|
+
.ss-w-fandash-postmatch-tag--win { color: var(--ss-w-pos); }
|
|
2884
|
+
.ss-w-fandash-postmatch-tag--loss { color: var(--ss-w-neg); }
|
|
2885
|
+
.ss-w-fandash-postmatch-tag--draw { color: var(--ss-w-faint); }
|
|
2886
|
+
.ss-w-fandash-postmatch-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }
|
|
2887
|
+
.ss-w-fandash-postmatch-side { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
2888
|
+
.ss-w-fandash-postmatch-side--away { flex-direction: row-reverse; text-align: right; }
|
|
2889
|
+
.ss-w-fandash-postmatch-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }
|
|
2890
|
+
.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--home { background: var(--ss-w-home); }
|
|
2891
|
+
.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--away { background: var(--ss-w-away); }
|
|
2892
|
+
.ss-w-fandash-postmatch-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }
|
|
2893
|
+
.ss-w-fandash-postmatch-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; }
|
|
2894
|
+
.ss-w-fandash-postmatch-score-value--win { color: var(--ss-w-ink); }
|
|
2895
|
+
.ss-w-fandash-postmatch-score-value--lose { color: var(--ss-w-faint); }
|
|
2896
|
+
.ss-w-fandash-postmatch-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }
|
|
2897
|
+
.ss-w-fandash-postmatch-meta { margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--ss-w-line); font-size: 12px; color: var(--ss-w-faint); text-align: center; }
|
|
2898
|
+
|
|
2899
|
+
/* post-match goals: a football-ball icon per goal (mirrors the live timeline ball, duplicated here
|
|
2900
|
+
under the postmatch prefix), text dimmed for opponent goals and picked out in full ink + bold
|
|
2901
|
+
for the club's own goals */
|
|
2902
|
+
.ss-w-fandash-postmatch-goal-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }
|
|
2903
|
+
.ss-w-fandash-postmatch-goal { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ss-w-faint); }
|
|
2904
|
+
.ss-w-fandash-postmatch-goal-ball { width: 11px; height: 11px; flex: none; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }
|
|
2790
2905
|
.ss-w-fandash-postmatch-goal--club { color: var(--ss-w-ink); font-weight: 650; }
|
|
2791
2906
|
|
|
2792
|
-
/* post-match stats:
|
|
2793
|
-
|
|
2794
|
-
|
|
2907
|
+
/* post-match stats: home value / stat label / away value, oriented by venue (u316), each row now
|
|
2908
|
+
backed by a home/away split bar -- the big upgrade from plain text -- plus a legend. Mirrors
|
|
2909
|
+
LiveStatsCard's split-bar treatment under the postmatch-prefixed classes; the shared
|
|
2910
|
+
--ss-w-home/--ss-w-away/--ss-w-track tokens are defined above. */
|
|
2911
|
+
.ss-w-fandash-postmatch-stat-rows { display: flex; flex-direction: column; gap: 15px; }
|
|
2912
|
+
.ss-w-fandash-postmatch-stat { display: flex; flex-direction: column; gap: 7px; }
|
|
2913
|
+
.ss-w-fandash-postmatch-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }
|
|
2795
2914
|
.ss-w-fandash-postmatch-stat-value { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
2796
|
-
.ss-w-fandash-postmatch-stat-
|
|
2915
|
+
.ss-w-fandash-postmatch-stat-value--home { color: var(--ss-w-home); }
|
|
2916
|
+
.ss-w-fandash-postmatch-stat-value--away { color: var(--ss-w-away); text-align: right; }
|
|
2797
2917
|
.ss-w-fandash-postmatch-stat-label { font-size: 10.5px; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
.ss-w-fandash-postmatch-
|
|
2801
|
-
.ss-w-fandash-postmatch-
|
|
2802
|
-
.ss-w-fandash-postmatch-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
.ss-w-fandash-postmatch-
|
|
2806
|
-
|
|
2807
|
-
|
|
2918
|
+
.ss-w-fandash-postmatch-stat-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }
|
|
2919
|
+
.ss-w-fandash-postmatch-stat-bar-home { height: 100%; background: var(--ss-w-home); }
|
|
2920
|
+
.ss-w-fandash-postmatch-stat-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }
|
|
2921
|
+
.ss-w-fandash-postmatch-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }
|
|
2922
|
+
.ss-w-fandash-postmatch-legend-item { display: inline-flex; align-items: center; gap: 6px; }
|
|
2923
|
+
.ss-w-fandash-postmatch-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
|
|
2924
|
+
.ss-w-fandash-postmatch-legend-swatch--home { background: var(--ss-w-home); }
|
|
2925
|
+
.ss-w-fandash-postmatch-legend-swatch--away { background: var(--ss-w-away); }
|
|
2926
|
+
|
|
2927
|
+
/* post-match top performer (full mockup treatment): gradient initials avatar + name + a
|
|
2928
|
+
prominent rating chip. Avatar gradient reuses the --ss-w-away token, same pairing as the live
|
|
2929
|
+
crest fallback; "?" renders through the same avatar span when the name is blank. */
|
|
2930
|
+
.ss-w-fandash-postmatch-perf-row { display: flex; align-items: center; gap: 12px; }
|
|
2931
|
+
.ss-w-fandash-postmatch-perf-avatar {
|
|
2932
|
+
flex: none; width: 42px; height: 42px; border-radius: 50%;
|
|
2933
|
+
display: grid; place-items: center;
|
|
2934
|
+
font-size: 14px; font-weight: 800; color: #fff;
|
|
2935
|
+
background: linear-gradient(135deg, var(--ss-w-away), color-mix(in srgb, var(--ss-w-away) 55%, #000));
|
|
2936
|
+
}
|
|
2937
|
+
.ss-w-fandash-postmatch-perf-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; }
|
|
2938
|
+
.ss-w-fandash-postmatch-perf-rating { margin-left: auto; flex: none; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 11px; }
|
|
2939
|
+
|
|
2940
|
+
/* post-match next (v1, modest): whenLabel is already a complete localized phrase (opponent +
|
|
2941
|
+
venue + kickoff) composed server-side, so this card renders just that one line -- dressed up
|
|
2942
|
+
with an accent rule rather than a duplicated opponent line. The richer opponent-headline/venue-
|
|
2943
|
+
chip/crest layout from the mockup needs a server field split and is deferred. */
|
|
2944
|
+
.ss-w-fandash-postmatch-next-row { display: flex; align-items: center; gap: 10px; border-left: 3px solid var(--ss-w-accent); padding-left: 10px; }
|
|
2945
|
+
.ss-w-fandash-postmatch-next-when { font-size: 13.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.3; }
|
|
2808
2946
|
|
|
2809
2947
|
/* resting next: the between-matches fixture teaser -- when-label left, competition badge right */
|
|
2810
2948
|
.ss-w-fandash-resting-next-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
@@ -2931,11 +3069,11 @@ function injectStyles(root) {
|
|
|
2931
3069
|
function StatsWidget(props) {
|
|
2932
3070
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
2933
3071
|
const cfg = props.config;
|
|
2934
|
-
const built = (0,
|
|
2935
|
-
const ui = (0,
|
|
2936
|
-
const rootRef = (0,
|
|
3072
|
+
const built = (0, import_react19.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
3073
|
+
const ui = (0, import_react19.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
3074
|
+
const rootRef = (0, import_react19.useRef)(null);
|
|
2937
3075
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
2938
|
-
const slip = (0,
|
|
3076
|
+
const slip = (0, import_react19.useMemo)(
|
|
2939
3077
|
() => ({
|
|
2940
3078
|
onAddToSlip: props.config?.onAddToSlip,
|
|
2941
3079
|
conversationId: controller.state.conversationId ?? void 0,
|
|
@@ -2948,11 +3086,11 @@ function StatsWidget(props) {
|
|
|
2948
3086
|
}),
|
|
2949
3087
|
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
2950
3088
|
);
|
|
2951
|
-
const onDashboardTap = (0,
|
|
3089
|
+
const onDashboardTap = (0, import_react19.useMemo)(
|
|
2952
3090
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
2953
3091
|
[built]
|
|
2954
3092
|
);
|
|
2955
|
-
(0,
|
|
3093
|
+
(0, import_react19.useEffect)(() => {
|
|
2956
3094
|
if (!built || !ui.injectStyles) return;
|
|
2957
3095
|
const node = rootRef.current?.getRootNode();
|
|
2958
3096
|
if (node) injectStyles(node);
|