@sensiblestats/widget-react 0.20.0 → 0.22.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 +53 -302
- 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 +45 -294
- package/dist/index.js.map +1 -1
- package/dist/styles.css +0 -39
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @sensiblestats/widget-react
|
|
2
2
|
|
|
3
|
+
## 0.22.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Remove club match-day dashboard renderers and SDK types. The server no longer emits the `clubDashboard` block; the corresponding widget renderers, CSS, and SDK type union are stripped in this forward bump.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @sensiblestats/widget-sdk@0.19.0
|
|
13
|
+
|
|
14
|
+
## 0.21.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- Match Preview card: deterministic matchPreviewCard block type (sdk) + renderer (react).
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- @sensiblestats/widget-sdk@0.18.0
|
|
24
|
+
|
|
3
25
|
## 0.20.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
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_react11 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/kickoff.ts
|
|
@@ -92,12 +92,6 @@ var STRINGS = {
|
|
|
92
92
|
const drift = direction ? `, ${direction}` : "";
|
|
93
93
|
return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`;
|
|
94
94
|
},
|
|
95
|
-
clubMatchPreviewHeading: "Match preview",
|
|
96
|
-
clubTeamDnaHeading: "How they play",
|
|
97
|
-
clubFormHeading: "Recent form",
|
|
98
|
-
clubCountdownLabel: "Countdown to kick-off",
|
|
99
|
-
clubKickoff: (ms) => new Intl.DateTimeFormat("en-GB", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
|
|
100
|
-
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))}`,
|
|
101
95
|
inSlip: "In slip",
|
|
102
96
|
slipAdded: (n) => n === void 0 ? "Added to slip" : `Added to slip (${n} selection${n === 1 ? "" : "s"})`,
|
|
103
97
|
slipDuplicate: "Already in your slip",
|
|
@@ -149,12 +143,6 @@ var STRINGS = {
|
|
|
149
143
|
const drift = direction ? `, ${direction}` : "";
|
|
150
144
|
return `Son ${span} i\xE7indeki oran hareketi: ${opening} ile a\xE7\u0131ld\u0131, \u015Fu anda ${current}${drift}.`;
|
|
151
145
|
},
|
|
152
|
-
clubMatchPreviewHeading: "Ma\xE7 \xF6nizlemesi",
|
|
153
|
-
clubTeamDnaHeading: "Nas\u0131l oynuyorlar",
|
|
154
|
-
clubFormHeading: "Son form",
|
|
155
|
-
clubCountdownLabel: "Ba\u015Flama vuru\u015Funa kalan",
|
|
156
|
-
clubKickoff: (ms) => new Intl.DateTimeFormat("tr-TR", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
|
|
157
|
-
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))}`,
|
|
158
146
|
inSlip: "Kuponda",
|
|
159
147
|
slipAdded: (n) => n === void 0 ? "Kupona eklendi" : `Kupona eklendi (${n} se\xE7im)`,
|
|
160
148
|
slipDuplicate: "Bu se\xE7im kuponunuzda zaten var",
|
|
@@ -218,12 +206,6 @@ function normalizeUi(cfg) {
|
|
|
218
206
|
excludedSuspended: strings.excludedSuspended,
|
|
219
207
|
chartTimeLabel: strings.chartTimeLabel,
|
|
220
208
|
chartAria: strings.chartAria,
|
|
221
|
-
clubMatchPreviewHeading: strings.clubMatchPreviewHeading,
|
|
222
|
-
clubTeamDnaHeading: strings.clubTeamDnaHeading,
|
|
223
|
-
clubFormHeading: strings.clubFormHeading,
|
|
224
|
-
clubCountdownLabel: strings.clubCountdownLabel,
|
|
225
|
-
clubKickoff: strings.clubKickoff,
|
|
226
|
-
clubKickoffAria: strings.clubKickoffAria,
|
|
227
209
|
addToSlip: strings.addToSlip,
|
|
228
210
|
inSlip: strings.inSlip,
|
|
229
211
|
slipAdded: strings.slipAdded,
|
|
@@ -586,8 +568,7 @@ function applyEvent(state, event) {
|
|
|
586
568
|
messages: mapActive(state, (t) => ({
|
|
587
569
|
...t,
|
|
588
570
|
done: true,
|
|
589
|
-
greetingDashboard: event.data.dashboard ?? void 0
|
|
590
|
-
clubDashboard: event.data.clubDashboard ?? void 0
|
|
571
|
+
greetingDashboard: event.data.dashboard ?? void 0
|
|
591
572
|
}))
|
|
592
573
|
};
|
|
593
574
|
}
|
|
@@ -784,7 +765,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
784
765
|
}
|
|
785
766
|
|
|
786
767
|
// src/components/ChatPanel.tsx
|
|
787
|
-
var
|
|
768
|
+
var import_react10 = require("react");
|
|
788
769
|
|
|
789
770
|
// src/components/ChatHeader.tsx
|
|
790
771
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -797,7 +778,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
797
778
|
}
|
|
798
779
|
|
|
799
780
|
// src/components/MessageList.tsx
|
|
800
|
-
var
|
|
781
|
+
var import_react8 = require("react");
|
|
801
782
|
|
|
802
783
|
// src/components/Markdown.tsx
|
|
803
784
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -1343,218 +1324,28 @@ function GreetingDashboard({ dashboard, onTap }) {
|
|
|
1343
1324
|
] });
|
|
1344
1325
|
}
|
|
1345
1326
|
|
|
1346
|
-
// src/components/club-dashboard/GreetingHeaderBlock.tsx
|
|
1347
|
-
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1348
|
-
function GreetingHeaderBlock({ block }) {
|
|
1349
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
|
|
1350
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
|
|
1351
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
|
|
1352
|
-
] });
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
// src/components/club-dashboard/FixtureHeroBlock.tsx
|
|
1356
|
-
var import_react8 = require("react");
|
|
1357
|
-
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1358
|
-
function initials3(name) {
|
|
1359
|
-
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
1360
|
-
}
|
|
1361
|
-
function Crest3({ url, name }) {
|
|
1362
|
-
const [broken, setBroken] = (0, import_react8.useState)(false);
|
|
1363
|
-
if (!url || broken) {
|
|
1364
|
-
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
|
|
1365
|
-
}
|
|
1366
|
-
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
|
|
1367
|
-
}
|
|
1368
|
-
function FixtureHeroBlock({
|
|
1369
|
-
block,
|
|
1370
|
-
ui,
|
|
1371
|
-
onAction
|
|
1372
|
-
}) {
|
|
1373
|
-
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
|
|
1374
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-tie", children: [
|
|
1375
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
|
|
1376
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
|
|
1377
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
|
|
1378
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
|
|
1379
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.awayCrestUrl, name: block.awayName })
|
|
1380
|
-
] }),
|
|
1381
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
|
|
1382
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
|
|
1383
|
-
block.venue ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
|
|
1384
|
-
block.competition ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
|
|
1385
|
-
] }),
|
|
1386
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaLabel, { actionRef: block.ctaActionRef }), children: block.ctaLabel })
|
|
1387
|
-
] });
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
// src/components/club-dashboard/FormGuideBlock.tsx
|
|
1391
|
-
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1392
|
-
function FormGuideBlock({ block }) {
|
|
1393
|
-
if (block.rows.length === 0) return null;
|
|
1394
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
|
|
1395
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
|
|
1396
|
-
row.name,
|
|
1397
|
-
row.position != null ? ` #${row.position}` : ""
|
|
1398
|
-
] }),
|
|
1399
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
|
|
1400
|
-
] }, row.name)) });
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
// src/components/club-dashboard/MatchPreviewBlock.tsx
|
|
1404
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1405
|
-
function MatchPreviewBlock({
|
|
1406
|
-
block,
|
|
1407
|
-
ui,
|
|
1408
|
-
onAction
|
|
1409
|
-
}) {
|
|
1410
|
-
if (block.facts.length === 0) return null;
|
|
1411
|
-
const heading = ui.clubMatchPreviewHeading;
|
|
1412
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-cdash-lines", children: [
|
|
1413
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1414
|
-
block.facts.map(
|
|
1415
|
-
(f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1416
|
-
"button",
|
|
1417
|
-
{
|
|
1418
|
-
type: "button",
|
|
1419
|
-
className: "ss-w-cdash-fact",
|
|
1420
|
-
onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
|
|
1421
|
-
children: [
|
|
1422
|
-
f.sentence,
|
|
1423
|
-
f.label ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
|
|
1424
|
-
" ",
|
|
1425
|
-
f.label
|
|
1426
|
-
] }) : null
|
|
1427
|
-
]
|
|
1428
|
-
},
|
|
1429
|
-
i
|
|
1430
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: f.sentence }, i)
|
|
1431
|
-
)
|
|
1432
|
-
] });
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
// src/components/club-dashboard/TeamDnaBlock.tsx
|
|
1436
|
-
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1437
|
-
function TeamDnaBlock({
|
|
1438
|
-
block,
|
|
1439
|
-
ui,
|
|
1440
|
-
onAction
|
|
1441
|
-
}) {
|
|
1442
|
-
if (block.facts.length === 0) return null;
|
|
1443
|
-
const heading = ui.clubTeamDnaHeading;
|
|
1444
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-lines", children: [
|
|
1445
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1446
|
-
block.facts.map(
|
|
1447
|
-
(f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
1448
|
-
"button",
|
|
1449
|
-
{
|
|
1450
|
-
type: "button",
|
|
1451
|
-
className: "ss-w-cdash-fact",
|
|
1452
|
-
onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
|
|
1453
|
-
children: [
|
|
1454
|
-
f.sentence,
|
|
1455
|
-
f.label ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
|
|
1456
|
-
" ",
|
|
1457
|
-
f.label
|
|
1458
|
-
] }) : null
|
|
1459
|
-
]
|
|
1460
|
-
},
|
|
1461
|
-
i
|
|
1462
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: f.sentence }, i)
|
|
1463
|
-
)
|
|
1464
|
-
] });
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
// src/components/club-dashboard/CountdownBlock.tsx
|
|
1468
|
-
var import_react9 = require("react");
|
|
1469
|
-
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1470
|
-
var DAY_MS = 24 * 3600 * 1e3;
|
|
1471
|
-
function pad2(n) {
|
|
1472
|
-
return String(n).padStart(2, "0");
|
|
1473
|
-
}
|
|
1474
|
-
function splitRemaining(remainingMs) {
|
|
1475
|
-
const totalSeconds = Math.max(0, Math.floor(remainingMs / 1e3));
|
|
1476
|
-
const h = Math.floor(totalSeconds / 3600);
|
|
1477
|
-
const m = Math.floor(totalSeconds % 3600 / 60);
|
|
1478
|
-
const s = totalSeconds % 60;
|
|
1479
|
-
return { h: pad2(h), m: pad2(m), s: pad2(s) };
|
|
1480
|
-
}
|
|
1481
|
-
function CountdownBlock({ block, ui }) {
|
|
1482
|
-
const [remainingMs, setRemainingMs] = (0, import_react9.useState)(() => block.kickoffUnix * 1e3 - Date.now());
|
|
1483
|
-
(0, import_react9.useEffect)(() => {
|
|
1484
|
-
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1485
|
-
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
1486
|
-
const id = setInterval(() => {
|
|
1487
|
-
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1488
|
-
}, 1e3);
|
|
1489
|
-
return () => clearInterval(id);
|
|
1490
|
-
}, [block.kickoffUnix]);
|
|
1491
|
-
if (remainingMs <= 0) return null;
|
|
1492
|
-
if (remainingMs > DAY_MS) return null;
|
|
1493
|
-
const { h, m, s } = splitRemaining(remainingMs);
|
|
1494
|
-
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
|
|
1495
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
|
|
1496
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
|
|
1497
|
-
"h",
|
|
1498
|
-
" ",
|
|
1499
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
|
|
1500
|
-
"m",
|
|
1501
|
-
" ",
|
|
1502
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
|
|
1503
|
-
"s"
|
|
1504
|
-
] }),
|
|
1505
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
|
|
1506
|
-
] });
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
|
-
// src/components/club-dashboard/ClubDashboard.tsx
|
|
1510
|
-
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1511
|
-
var CLUB_BLOCK_REGISTRY = {
|
|
1512
|
-
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingHeaderBlock, { block }) : null,
|
|
1513
|
-
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
|
|
1514
|
-
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FormGuideBlock, { block, ui }) : null,
|
|
1515
|
-
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
|
|
1516
|
-
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
|
|
1517
|
-
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CountdownBlock, { block, ui }) : null
|
|
1518
|
-
};
|
|
1519
|
-
function ClubDashboard({
|
|
1520
|
-
dashboard,
|
|
1521
|
-
ui,
|
|
1522
|
-
onAction
|
|
1523
|
-
}) {
|
|
1524
|
-
if (!dashboard.blocks.length) return null;
|
|
1525
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
|
|
1526
|
-
const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
|
|
1527
|
-
if (!Comp) {
|
|
1528
|
-
console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
|
|
1529
|
-
return null;
|
|
1530
|
-
}
|
|
1531
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Comp, { block, ui, onAction }) }, i);
|
|
1532
|
-
}) });
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
1327
|
// src/components/ChatMessage.tsx
|
|
1536
|
-
var
|
|
1537
|
-
function ChatMessage({ message, disabled, onAct, onTap,
|
|
1328
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1329
|
+
function ChatMessage({ message, disabled, onAct, onTap, ui, slip }) {
|
|
1538
1330
|
if (message.role === "user") {
|
|
1539
|
-
return /* @__PURE__ */ (0,
|
|
1331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
|
|
1540
1332
|
}
|
|
1541
|
-
return /* @__PURE__ */ (0,
|
|
1542
|
-
message.text && !message.greetingDashboard
|
|
1543
|
-
message.greetingDashboard ? /* @__PURE__ */ (0,
|
|
1544
|
-
|
|
1545
|
-
/* @__PURE__ */ (0,
|
|
1546
|
-
/* @__PURE__ */ (0,
|
|
1547
|
-
/* @__PURE__ */ (0,
|
|
1548
|
-
/* @__PURE__ */ (0,
|
|
1549
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
1334
|
+
message.text && !message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Markdown, { text: message.text }) : null,
|
|
1335
|
+
message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
|
|
1340
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
1550
1341
|
] });
|
|
1551
1342
|
}
|
|
1552
1343
|
|
|
1553
1344
|
// src/components/IntentChips.tsx
|
|
1554
|
-
var
|
|
1345
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1555
1346
|
function IntentChips({ chips, onPick }) {
|
|
1556
1347
|
if (chips.length === 0) return null;
|
|
1557
|
-
return /* @__PURE__ */ (0,
|
|
1348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
1558
1349
|
}
|
|
1559
1350
|
|
|
1560
1351
|
// src/scroll.ts
|
|
@@ -1564,18 +1355,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
1564
1355
|
}
|
|
1565
1356
|
|
|
1566
1357
|
// src/components/MessageList.tsx
|
|
1567
|
-
var
|
|
1358
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1568
1359
|
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
1569
1360
|
const { state, send } = controller;
|
|
1570
|
-
const listRef = (0,
|
|
1571
|
-
const endRef = (0,
|
|
1572
|
-
const pinnedRef = (0,
|
|
1573
|
-
(0,
|
|
1361
|
+
const listRef = (0, import_react8.useRef)(null);
|
|
1362
|
+
const endRef = (0, import_react8.useRef)(null);
|
|
1363
|
+
const pinnedRef = (0, import_react8.useRef)(true);
|
|
1364
|
+
(0, import_react8.useEffect)(() => {
|
|
1574
1365
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
1575
1366
|
}, [state.messages, state.status]);
|
|
1576
1367
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
1577
1368
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
|
|
1578
|
-
return /* @__PURE__ */ (0,
|
|
1369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
1579
1370
|
"div",
|
|
1580
1371
|
{
|
|
1581
1372
|
className: "ss-w-list",
|
|
@@ -1585,7 +1376,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1585
1376
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
1586
1377
|
},
|
|
1587
1378
|
children: [
|
|
1588
|
-
state.messages.map((m) => /* @__PURE__ */ (0,
|
|
1379
|
+
state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1589
1380
|
ChatMessage,
|
|
1590
1381
|
{
|
|
1591
1382
|
message: m,
|
|
@@ -1595,31 +1386,30 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1595
1386
|
send(tile.actionValue, { displayText: tile.title });
|
|
1596
1387
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
1597
1388
|
},
|
|
1598
|
-
onClubAction: (label, opts) => send(label, { actionRef: opts.actionRef }),
|
|
1599
1389
|
ui,
|
|
1600
1390
|
slip
|
|
1601
1391
|
},
|
|
1602
1392
|
m.id
|
|
1603
1393
|
)),
|
|
1604
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0,
|
|
1394
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
1605
1395
|
} }) : null,
|
|
1606
|
-
state.status ? /* @__PURE__ */ (0,
|
|
1607
|
-
state.error ? /* @__PURE__ */ (0,
|
|
1608
|
-
/* @__PURE__ */ (0,
|
|
1609
|
-
/* @__PURE__ */ (0,
|
|
1396
|
+
state.status ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
|
|
1397
|
+
state.error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
|
|
1398
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
1610
1400
|
] }) : null,
|
|
1611
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0,
|
|
1612
|
-
/* @__PURE__ */ (0,
|
|
1401
|
+
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
1402
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { ref: endRef })
|
|
1613
1403
|
]
|
|
1614
1404
|
}
|
|
1615
1405
|
);
|
|
1616
1406
|
}
|
|
1617
1407
|
|
|
1618
1408
|
// src/components/ChatInput.tsx
|
|
1619
|
-
var
|
|
1620
|
-
var
|
|
1409
|
+
var import_react9 = require("react");
|
|
1410
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1621
1411
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
1622
|
-
const [value, setValue] = (0,
|
|
1412
|
+
const [value, setValue] = (0, import_react9.useState)("");
|
|
1623
1413
|
const submit = () => {
|
|
1624
1414
|
const t = value.trim();
|
|
1625
1415
|
if (!t) return;
|
|
@@ -1632,18 +1422,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
1632
1422
|
submit();
|
|
1633
1423
|
}
|
|
1634
1424
|
};
|
|
1635
|
-
return /* @__PURE__ */ (0,
|
|
1636
|
-
/* @__PURE__ */ (0,
|
|
1637
|
-
streaming ? /* @__PURE__ */ (0,
|
|
1425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-input", children: [
|
|
1426
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
1427
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SendIcon, {}) })
|
|
1638
1428
|
] });
|
|
1639
1429
|
}
|
|
1640
1430
|
|
|
1641
1431
|
// src/components/ChatPanel.tsx
|
|
1642
|
-
var
|
|
1432
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1643
1433
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
1644
1434
|
function useIsModal() {
|
|
1645
|
-
const [modal, setModal] = (0,
|
|
1646
|
-
(0,
|
|
1435
|
+
const [modal, setModal] = (0, import_react10.useState)(false);
|
|
1436
|
+
(0, import_react10.useEffect)(() => {
|
|
1647
1437
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1648
1438
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
1649
1439
|
const sync = () => setModal(mql.matches);
|
|
@@ -1656,17 +1446,17 @@ function useIsModal() {
|
|
|
1656
1446
|
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
1657
1447
|
const { state, close, stop, send } = controller;
|
|
1658
1448
|
const isModal = useIsModal();
|
|
1659
|
-
(0,
|
|
1449
|
+
(0, import_react10.useEffect)(() => {
|
|
1660
1450
|
const onKey = (e) => {
|
|
1661
1451
|
if (e.key === "Escape") close();
|
|
1662
1452
|
};
|
|
1663
1453
|
window.addEventListener("keydown", onKey);
|
|
1664
1454
|
return () => window.removeEventListener("keydown", onKey);
|
|
1665
1455
|
}, [close]);
|
|
1666
|
-
return /* @__PURE__ */ (0,
|
|
1667
|
-
/* @__PURE__ */ (0,
|
|
1668
|
-
/* @__PURE__ */ (0,
|
|
1669
|
-
/* @__PURE__ */ (0,
|
|
1456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
1670
1460
|
] });
|
|
1671
1461
|
}
|
|
1672
1462
|
|
|
@@ -2019,49 +1809,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
2019
1809
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }
|
|
2020
1810
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }
|
|
2021
1811
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }
|
|
2022
|
-
|
|
2023
|
-
/* club match-day dashboard */
|
|
2024
|
-
.ss-w-cdash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
|
|
2025
|
-
.ss-w-cdash-block { display: flex; flex-direction: column; }
|
|
2026
|
-
|
|
2027
|
-
.ss-w-cdash-greeting { display: flex; flex-direction: column; gap: 2px; }
|
|
2028
|
-
.ss-w-cdash-greeting-title { font-weight: 700; font-size: 14px; color: var(--ss-w-ink); }
|
|
2029
|
-
.ss-w-cdash-greeting-subtitle { font-size: 11.5px; color: var(--ss-w-faint); }
|
|
2030
|
-
|
|
2031
|
-
.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; }
|
|
2032
|
-
.ss-w-cdash-tie { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
|
|
2033
|
-
.ss-w-cdash-team { font-weight: 650; font-size: 13px; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
|
|
2034
|
-
.ss-w-cdash-vs { font-size: 11px; color: var(--ss-w-faint); font-weight: 600; }
|
|
2035
|
-
.ss-w-cdash-crest { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--ss-w-bubble); }
|
|
2036
|
-
.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)); }
|
|
2037
|
-
.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); }
|
|
2038
|
-
.ss-w-cdash-kickoff { font-weight: 700; color: var(--ss-w-ink); }
|
|
2039
|
-
.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; }
|
|
2040
|
-
|
|
2041
|
-
.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; }
|
|
2042
|
-
.ss-w-cdash-form-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
2043
|
-
.ss-w-cdash-form-name { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
|
|
2044
|
-
.ss-w-cdash-form-pills { flex: none; display: flex; align-items: center; gap: 3px; }
|
|
2045
|
-
.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; }
|
|
2046
|
-
.ss-w-cdash-pill--w { background: color-mix(in srgb, var(--ss-w-pos) 88%, black); }
|
|
2047
|
-
.ss-w-cdash-pill--d { background: var(--ss-w-faint); }
|
|
2048
|
-
.ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
|
|
2049
|
-
|
|
2050
|
-
.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; }
|
|
2051
|
-
.ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
|
|
2052
|
-
.ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); margin: 0; }
|
|
2053
|
-
.ss-w-cdash-fact { display: block; width: 100%; text-align: left; font: inherit; font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); background: none; border: none; padding: 0; cursor: pointer; }
|
|
2054
|
-
.ss-w-cdash-fact:hover, .ss-w-cdash-fact:focus-visible { color: var(--ss-w-accent); text-decoration: underline; }
|
|
2055
|
-
.ss-w-cdash-fact-label { font-size: 11px; font-weight: 700; color: var(--ss-w-accent); }
|
|
2056
|
-
|
|
2057
|
-
.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; }
|
|
2058
|
-
.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); }
|
|
2059
|
-
.ss-w-cdash-cd-h, .ss-w-cdash-cd-m, .ss-w-cdash-cd-s { color: var(--ss-w-accent); }
|
|
2060
|
-
.ss-w-cdash-cd-label { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }
|
|
2061
1812
|
`;
|
|
2062
1813
|
|
|
2063
1814
|
// src/StatsWidget.tsx
|
|
2064
|
-
var
|
|
1815
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2065
1816
|
function buildClient(props) {
|
|
2066
1817
|
try {
|
|
2067
1818
|
if ("client" in props && props.client) {
|
|
@@ -2086,11 +1837,11 @@ function injectStyles(root) {
|
|
|
2086
1837
|
function StatsWidget(props) {
|
|
2087
1838
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
2088
1839
|
const cfg = props.config;
|
|
2089
|
-
const built = (0,
|
|
2090
|
-
const ui = (0,
|
|
2091
|
-
const rootRef = (0,
|
|
1840
|
+
const built = (0, import_react11.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
1841
|
+
const ui = (0, import_react11.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
1842
|
+
const rootRef = (0, import_react11.useRef)(null);
|
|
2092
1843
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
2093
|
-
const slip = (0,
|
|
1844
|
+
const slip = (0, import_react11.useMemo)(
|
|
2094
1845
|
() => ({
|
|
2095
1846
|
onAddToSlip: props.config?.onAddToSlip,
|
|
2096
1847
|
conversationId: controller.state.conversationId ?? void 0,
|
|
@@ -2103,18 +1854,18 @@ function StatsWidget(props) {
|
|
|
2103
1854
|
}),
|
|
2104
1855
|
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
2105
1856
|
);
|
|
2106
|
-
const onDashboardTap = (0,
|
|
1857
|
+
const onDashboardTap = (0, import_react11.useMemo)(
|
|
2107
1858
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
2108
1859
|
[built]
|
|
2109
1860
|
);
|
|
2110
|
-
(0,
|
|
1861
|
+
(0, import_react11.useEffect)(() => {
|
|
2111
1862
|
if (!built || !ui.injectStyles) return;
|
|
2112
1863
|
const node = rootRef.current?.getRootNode();
|
|
2113
1864
|
if (node) injectStyles(node);
|
|
2114
1865
|
}, [built, ui.injectStyles]);
|
|
2115
1866
|
if (!built) return null;
|
|
2116
1867
|
const attrs = themeAttrs(ui);
|
|
2117
|
-
return /* @__PURE__ */ (0,
|
|
1868
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.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_runtime22.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2118
1869
|
ChatFab,
|
|
2119
1870
|
{
|
|
2120
1871
|
label: ui.launcherLabel,
|