@sensiblestats/widget-react 0.26.1 → 0.27.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 +12 -0
- package/dist/index.cjs +106 -89
- 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 +106 -89
- package/dist/index.js.map +1 -1
- package/dist/styles.css +28 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -816,8 +816,15 @@ function initials(name) {
|
|
|
816
816
|
function shortSeason(season) {
|
|
817
817
|
return season.replace(/\d{4}/g, (year) => year.slice(2));
|
|
818
818
|
}
|
|
819
|
-
function Crest({ image }) {
|
|
820
|
-
return /* @__PURE__ */ jsx6(
|
|
819
|
+
function Crest({ image, label }) {
|
|
820
|
+
return /* @__PURE__ */ jsx6(
|
|
821
|
+
"span",
|
|
822
|
+
{
|
|
823
|
+
className: "ss-w-ecard-crest",
|
|
824
|
+
style: { backgroundImage: `url(${image})` },
|
|
825
|
+
...label ? { role: "img", title: label, "aria-label": label } : { "aria-hidden": "true" }
|
|
826
|
+
}
|
|
827
|
+
);
|
|
821
828
|
}
|
|
822
829
|
function FormBar({ w, d, l }) {
|
|
823
830
|
if (w + d + l === 0) return null;
|
|
@@ -827,73 +834,73 @@ function FormBar({ w, d, l }) {
|
|
|
827
834
|
l > 0 ? /* @__PURE__ */ jsx6("span", { className: "ss-w-form-l", style: { flexGrow: l } }) : null
|
|
828
835
|
] });
|
|
829
836
|
}
|
|
830
|
-
function
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard-
|
|
834
|
-
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-
|
|
835
|
-
|
|
836
|
-
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-rval", children: s.value })
|
|
837
|
-
] }, s.label);
|
|
838
|
-
}) });
|
|
839
|
-
}
|
|
840
|
-
function CardBody({ c }) {
|
|
841
|
-
const [active, setActive] = useState(0);
|
|
842
|
-
if (c.scopes.length === 0) return null;
|
|
843
|
-
const season = c.season ? /* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-season", children: shortSeason(c.season) }) : null;
|
|
844
|
-
if (c.scopes.length === 1) {
|
|
845
|
-
const only = c.scopes[0];
|
|
846
|
-
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard-body", children: [
|
|
847
|
-
/* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard-tabs ss-w-ecard-tabs-static", children: [
|
|
848
|
-
/* @__PURE__ */ jsxs4("span", { className: "ss-w-ecard-lead", title: only.label, children: [
|
|
849
|
-
only.image ? /* @__PURE__ */ jsx6(Crest, { image: only.image }) : null,
|
|
850
|
-
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-lead-txt", children: only.label })
|
|
851
|
-
] }),
|
|
852
|
-
season
|
|
853
|
-
] }),
|
|
854
|
-
/* @__PURE__ */ jsx6(StatRows, { stats: only.stats })
|
|
837
|
+
function StatCellView({ s }) {
|
|
838
|
+
const m = RECORD_RE.exec(s.value);
|
|
839
|
+
if (m) {
|
|
840
|
+
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard-cell", children: [
|
|
841
|
+
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-cval", children: /* @__PURE__ */ jsx6(FormBar, { w: Number(m[1]), d: Number(m[2]), l: Number(m[3]) }) }),
|
|
842
|
+
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-clabel", children: s.value })
|
|
855
843
|
] });
|
|
856
844
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
/* @__PURE__ */
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
845
|
+
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard-cell", children: [
|
|
846
|
+
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-cval", children: s.value }),
|
|
847
|
+
/* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-clabel", children: s.label })
|
|
848
|
+
] });
|
|
849
|
+
}
|
|
850
|
+
function StatStrip({ stats }) {
|
|
851
|
+
if (stats.length === 0) return null;
|
|
852
|
+
const cols = Math.min(stats.length, 4);
|
|
853
|
+
return /* @__PURE__ */ jsx6("div", { className: "ss-w-ecard-strip", style: { gridTemplateColumns: `repeat(${cols}, 1fr)` }, children: stats.map((s) => /* @__PURE__ */ jsx6(StatCellView, { s }, s.label + s.value)) });
|
|
854
|
+
}
|
|
855
|
+
function CardHeader({ c, showScopeCrest }) {
|
|
856
|
+
const onlyScope = c.scopes.length === 1 ? c.scopes[0] : null;
|
|
857
|
+
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard-hd", children: [
|
|
858
|
+
/* @__PURE__ */ jsx6(
|
|
859
|
+
"span",
|
|
860
|
+
{
|
|
861
|
+
className: c.kind === "team" ? "ss-w-thumb ss-w-team" : "ss-w-thumb",
|
|
862
|
+
style: c.image ? { backgroundImage: `url(${c.image})` } : void 0,
|
|
863
|
+
children: c.image ? "" : initials(c.name)
|
|
864
|
+
}
|
|
865
|
+
),
|
|
866
|
+
/* @__PURE__ */ jsxs4("span", { className: "ss-w-ecard-idtext", children: [
|
|
867
|
+
/* @__PURE__ */ jsx6("span", { className: "ss-w-nm", children: c.name }),
|
|
868
|
+
c.sub ? /* @__PURE__ */ jsx6("span", { className: "ss-w-sub", children: c.sub }) : null
|
|
875
869
|
] }),
|
|
876
|
-
/* @__PURE__ */
|
|
870
|
+
/* @__PURE__ */ jsxs4("span", { className: "ss-w-ecard-meta", children: [
|
|
871
|
+
showScopeCrest && onlyScope?.image ? /* @__PURE__ */ jsx6(Crest, { image: onlyScope.image, label: onlyScope.label }) : null,
|
|
872
|
+
c.season ? /* @__PURE__ */ jsx6("span", { className: "ss-w-ecard-season", children: shortSeason(c.season) }) : null
|
|
873
|
+
] })
|
|
877
874
|
] });
|
|
878
875
|
}
|
|
876
|
+
function ScopeTabs({ scopes, active, onSelect }) {
|
|
877
|
+
return /* @__PURE__ */ jsx6("div", { className: "ss-w-ecard-scopes", role: "tablist", children: scopes.map((s, i) => /* @__PURE__ */ jsx6(
|
|
878
|
+
"button",
|
|
879
|
+
{
|
|
880
|
+
type: "button",
|
|
881
|
+
role: "tab",
|
|
882
|
+
className: "ss-w-ecard-scope",
|
|
883
|
+
"aria-selected": i === active,
|
|
884
|
+
"aria-label": s.label,
|
|
885
|
+
title: s.label,
|
|
886
|
+
onClick: () => onSelect(i),
|
|
887
|
+
children: s.image ? /* @__PURE__ */ jsx6(Crest, { image: s.image }) : s.label
|
|
888
|
+
},
|
|
889
|
+
String(s.competitionId ?? "all")
|
|
890
|
+
)) });
|
|
891
|
+
}
|
|
879
892
|
function EntityCardItem({ c }) {
|
|
893
|
+
const [active, setActive] = useState(0);
|
|
880
894
|
const hasBody = c.scopes.length > 0;
|
|
881
|
-
|
|
882
|
-
/* @__PURE__ */
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
),
|
|
891
|
-
/* @__PURE__ */ jsxs4("span", { className: "ss-w-ecard-idtext", children: [
|
|
892
|
-
/* @__PURE__ */ jsx6("span", { className: "ss-w-nm", children: c.name }),
|
|
893
|
-
c.sub ? /* @__PURE__ */ jsx6("span", { className: "ss-w-sub", children: c.sub }) : null
|
|
894
|
-
] })
|
|
895
|
-
] }),
|
|
896
|
-
/* @__PURE__ */ jsx6(CardBody, { c })
|
|
895
|
+
if (!hasBody) {
|
|
896
|
+
return /* @__PURE__ */ jsx6("div", { className: "ss-w-ecard ss-w-ecard-bare", "data-kind": c.kind, children: /* @__PURE__ */ jsx6(CardHeader, { c, showScopeCrest: false }) });
|
|
897
|
+
}
|
|
898
|
+
const multi = c.scopes.length > 1;
|
|
899
|
+
const scope = c.scopes[multi ? c.scopes[active] ? active : 0 : 0];
|
|
900
|
+
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard", "data-kind": c.kind, children: [
|
|
901
|
+
/* @__PURE__ */ jsx6(CardHeader, { c, showScopeCrest: !multi }),
|
|
902
|
+
multi ? /* @__PURE__ */ jsx6(ScopeTabs, { scopes: c.scopes, active, onSelect: setActive }) : null,
|
|
903
|
+
/* @__PURE__ */ jsx6(StatStrip, { stats: scope.stats })
|
|
897
904
|
] });
|
|
898
905
|
}
|
|
899
906
|
function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMoreLabel = (n) => `Show ${n} more` }) {
|
|
@@ -1048,7 +1055,7 @@ function Crest2({ url, name, kind }) {
|
|
|
1048
1055
|
|
|
1049
1056
|
// src/components/BettingInsightList.tsx
|
|
1050
1057
|
import { Fragment, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1051
|
-
function
|
|
1058
|
+
function StatRows({ stats }) {
|
|
1052
1059
|
return /* @__PURE__ */ jsx11("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-row", children: [
|
|
1053
1060
|
/* @__PURE__ */ jsx11("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
1054
1061
|
/* @__PURE__ */ jsx11("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
@@ -1059,7 +1066,7 @@ function ScopedStats({ scopes }) {
|
|
|
1059
1066
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
1060
1067
|
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-scoped", children: [
|
|
1061
1068
|
/* @__PURE__ */ jsx11("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx11("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
1062
|
-
/* @__PURE__ */ jsx11(
|
|
1069
|
+
/* @__PURE__ */ jsx11(StatRows, { stats: current.stats }, current.key)
|
|
1063
1070
|
] });
|
|
1064
1071
|
}
|
|
1065
1072
|
function hasStatsContent(it) {
|
|
@@ -1076,7 +1083,7 @@ function ReasonStrip({ it, ui }) {
|
|
|
1076
1083
|
/* @__PURE__ */ jsx11("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1077
1084
|
/* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason-body", children: [
|
|
1078
1085
|
hasText ? /* @__PURE__ */ jsx11("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
|
|
1079
|
-
open && hasStats ? hasScopes ? /* @__PURE__ */ jsx11(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ jsx11(
|
|
1086
|
+
open && hasStats ? hasScopes ? /* @__PURE__ */ jsx11(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ jsx11(StatRows, { stats: it.stats }) : null
|
|
1080
1087
|
] }),
|
|
1081
1088
|
expandable ? /* @__PURE__ */ jsx11(
|
|
1082
1089
|
"button",
|
|
@@ -1852,14 +1859,17 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1852
1859
|
const anchoredTurnRef = useRef3(null);
|
|
1853
1860
|
useEffect5(() => {
|
|
1854
1861
|
const anchor = turnAnchor(state.messages);
|
|
1862
|
+
const list = listRef.current;
|
|
1855
1863
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
1856
1864
|
anchoredTurnRef.current = anchor.turnId;
|
|
1865
|
+
if (endRef.current && list) endRef.current.style.height = `${list.clientHeight}px`;
|
|
1857
1866
|
pinnedRef.current = false;
|
|
1858
|
-
|
|
1867
|
+
list?.querySelector(`[data-msg-id="${anchor.anchorId}"]`)?.scrollIntoView({ block: "start" });
|
|
1859
1868
|
return;
|
|
1860
1869
|
}
|
|
1870
|
+
if (!state.isStreaming && endRef.current) endRef.current.style.height = "";
|
|
1861
1871
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
1862
|
-
}, [state.messages, state.status]);
|
|
1872
|
+
}, [state.messages, state.status, state.isStreaming]);
|
|
1863
1873
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
1864
1874
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && (m.greetingDashboard || m.clubFanDashboard));
|
|
1865
1875
|
return /* @__PURE__ */ jsxs35(
|
|
@@ -1895,7 +1905,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1895
1905
|
/* @__PURE__ */ jsx40("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
1896
1906
|
] }) : null,
|
|
1897
1907
|
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ jsx40(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
1898
|
-
/* @__PURE__ */ jsx40("div", { ref: endRef })
|
|
1908
|
+
/* @__PURE__ */ jsx40("div", { ref: endRef, className: "ss-w-turn-spacer", "aria-hidden": "true" })
|
|
1899
1909
|
]
|
|
1900
1910
|
}
|
|
1901
1911
|
);
|
|
@@ -2017,6 +2027,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2017
2027
|
|
|
2018
2028
|
/* messages */
|
|
2019
2029
|
.ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; scroll-padding-top: 14px; }
|
|
2030
|
+
/* Transient bottom spacer: reserves a viewport of room below a new turn so its
|
|
2031
|
+
top can be scrolled into view while the reply is still streaming in. Height is
|
|
2032
|
+
set imperatively and flex must not shrink it away. */
|
|
2033
|
+
.ss-w-turn-spacer { flex: none; }
|
|
2020
2034
|
.ss-w-msg { display: flex; }
|
|
2021
2035
|
.ss-w-user { justify-content: flex-end; }
|
|
2022
2036
|
.ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }
|
|
@@ -2044,10 +2058,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2044
2058
|
/* entity cards */
|
|
2045
2059
|
.ss-w-cards { display: flex; flex-direction: column; gap: 8px; }
|
|
2046
2060
|
|
|
2047
|
-
/*
|
|
2048
|
-
.ss-w-ecard { display:
|
|
2061
|
+
/* Entity card: identity header row over a horizontal stat strip */
|
|
2062
|
+
.ss-w-ecard { display: flex; flex-direction: column; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; text-align: left; }
|
|
2049
2063
|
|
|
2050
|
-
.ss-w-ecard-id { display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; padding: 13px 10px; border-right: 1px solid var(--ss-w-line); background: linear-gradient(158deg, var(--ss-w-bubble), color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-bubble))); }
|
|
2051
2064
|
.ss-w-ecard-idtext { display: flex; flex-direction: column; gap: 1px; min-width: 0; max-width: 100%; }
|
|
2052
2065
|
.ss-w-thumb { width: 54px; height: 54px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 16px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; box-shadow: 0 1px 3px rgba(0,0,0,.14); }
|
|
2053
2066
|
.ss-w-thumb.ss-w-team { border-radius: 12px; }
|
|
@@ -2057,27 +2070,31 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2057
2070
|
|
|
2058
2071
|
/* bare card (no stat scopes): simple avatar + name row */
|
|
2059
2072
|
.ss-w-ecard-bare { display: flex; align-items: center; }
|
|
2060
|
-
.ss-w-ecard-bare .ss-w-ecard-
|
|
2061
|
-
|
|
2062
|
-
.ss-w-ecard-
|
|
2063
|
-
|
|
2064
|
-
.ss-w-ecard-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
.ss-w-ecard-
|
|
2070
|
-
.ss-w-ecard-
|
|
2071
|
-
.ss-w-ecard-
|
|
2072
|
-
.ss-w-ecard-
|
|
2073
|
+
.ss-w-ecard-bare .ss-w-ecard-hd { padding: 10px 12px; }
|
|
2074
|
+
|
|
2075
|
+
.ss-w-ecard-hd { display: flex; align-items: center; gap: 11px; padding: 11px 13px; }
|
|
2076
|
+
.ss-w-ecard-hd .ss-w-thumb { width: 40px; height: 40px; font-size: 13px; box-shadow: none; }
|
|
2077
|
+
.ss-w-ecard-hd .ss-w-thumb.ss-w-team { border-radius: 10px; }
|
|
2078
|
+
.ss-w-ecard-meta { display: inline-flex; align-items: center; gap: 7px; flex: none; align-self: flex-start; margin-left: auto; }
|
|
2079
|
+
.ss-w-ecard-meta .ss-w-ecard-season { margin: 0; }
|
|
2080
|
+
|
|
2081
|
+
/* scope tabs: reuse the underline pattern, relocated above the strip */
|
|
2082
|
+
.ss-w-ecard-scopes { display: flex; align-items: stretch; gap: 2px; padding: 0 11px; border-top: 1px solid var(--ss-w-line); flex-wrap: wrap; }
|
|
2083
|
+
.ss-w-ecard-scope { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 7px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; }
|
|
2084
|
+
.ss-w-ecard-scope[aria-selected="true"] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }
|
|
2085
|
+
.ss-w-ecard-scope .ss-w-ecard-crest { width: 14px; height: 14px; }
|
|
2086
|
+
.ss-w-ecard-scopes + .ss-w-ecard-strip { border-top: none; }
|
|
2087
|
+
|
|
2073
2088
|
.ss-w-ecard-crest { width: 15px; height: 15px; flex: none; display: block; border-radius: 4px; background-size: cover; background-position: center; }
|
|
2074
2089
|
.ss-w-ecard-season { flex: none; margin-left: auto; align-self: center; margin-bottom: 5px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }
|
|
2075
|
-
.ss-w-ecard-tabs-static .ss-w-ecard-season { margin-bottom: 4px; }
|
|
2076
2090
|
|
|
2077
|
-
|
|
2078
|
-
.ss-w-ecard-
|
|
2079
|
-
.ss-w-ecard-
|
|
2080
|
-
.ss-w-ecard-
|
|
2091
|
+
/* stat strip: 1px gap over a line-colored ground paints hairlines between cells, wrap-safe */
|
|
2092
|
+
.ss-w-ecard-strip { display: grid; gap: 1px; background: var(--ss-w-line); border-top: 1px solid var(--ss-w-line); }
|
|
2093
|
+
.ss-w-ecard-cell { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 4px; padding: 10px 4px 11px; background: var(--ss-w-panel); }
|
|
2094
|
+
.ss-w-ecard-cval { height: 20px; display: flex; align-items: center; font-size: 17px; font-weight: 720; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
|
|
2095
|
+
.ss-w-ecard-cval .ss-w-form { width: 42px; }
|
|
2096
|
+
.ss-w-ecard-clabel { font-size: 9px; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-faint); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
2097
|
+
|
|
2081
2098
|
.ss-w-form { justify-self: end; display: flex; height: 6px; width: 48px; border-radius: 4px; overflow: hidden; gap: 2px; }
|
|
2082
2099
|
.ss-w-form span { display: block; border-radius: 2px; }
|
|
2083
2100
|
.ss-w-form-w { background: var(--ss-w-pos); }
|