@sensiblestats/widget-react 0.14.1 → 0.16.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 +277 -57
- 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 +269 -49
- package/dist/index.js.map +1 -1
- package/dist/styles.css +37 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @sensiblestats/widget-react
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 399d6bf: Label market-floor betting insight cards with a distinct "Market price · not a value pick" pill, so a screenshot of one can never read as a recommendation. Older servers that never send `isMarketFloor` render cards exactly as before.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [399d6bf]
|
|
12
|
+
- @sensiblestats/widget-sdk@0.14.0
|
|
13
|
+
|
|
14
|
+
## 0.15.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- Render the Club Match-Day dashboard (typed blocks: greeting header, fixture hero, form guide, match preview, team DNA, countdown) delivered on `turn_complete.clubDashboard`.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- @sensiblestats/widget-sdk@0.13.0
|
|
24
|
+
|
|
3
25
|
## 0.14.1
|
|
4
26
|
|
|
5
27
|
### Patch 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_react12 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/i18n.ts
|
|
@@ -57,6 +57,7 @@ var STRINGS = {
|
|
|
57
57
|
hideStats: "Hide stats",
|
|
58
58
|
oddsLabel: "Odds",
|
|
59
59
|
liveLabel: "Live",
|
|
60
|
+
marketFloorLabel: "Market price \xB7 not a value pick",
|
|
60
61
|
addToSlip: "Add to slip",
|
|
61
62
|
marketPrices: "Market prices",
|
|
62
63
|
moreLines: "More lines",
|
|
@@ -79,6 +80,12 @@ var STRINGS = {
|
|
|
79
80
|
const drift = direction ? `, ${direction}` : "";
|
|
80
81
|
return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`;
|
|
81
82
|
},
|
|
83
|
+
clubMatchPreviewHeading: "Match preview",
|
|
84
|
+
clubTeamDnaHeading: "How they play",
|
|
85
|
+
clubFormHeading: "Recent form",
|
|
86
|
+
clubCountdownLabel: "Countdown to kick-off",
|
|
87
|
+
clubKickoff: (ms) => new Intl.DateTimeFormat("en-GB", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
|
|
88
|
+
clubKickoffAria: (ms) => `Kick-off ${new Intl.DateTimeFormat("en-GB", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }).format(new Date(ms))}`,
|
|
82
89
|
inSlip: "In slip",
|
|
83
90
|
slipAdded: (n) => n === void 0 ? "Added to slip" : `Added to slip (${n} selection${n === 1 ? "" : "s"})`,
|
|
84
91
|
slipDuplicate: "Already in your slip",
|
|
@@ -104,6 +111,7 @@ var STRINGS = {
|
|
|
104
111
|
hideStats: "\u0130statistikleri gizle",
|
|
105
112
|
oddsLabel: "Oran",
|
|
106
113
|
liveLabel: "Canl\u0131",
|
|
114
|
+
marketFloorLabel: "Piyasa oran\u0131 \xB7 de\u011Fer bahsi de\u011Fil",
|
|
107
115
|
addToSlip: "Kupona ekle",
|
|
108
116
|
marketPrices: "Piyasa fiyatlar\u0131",
|
|
109
117
|
moreLines: "Di\u011Fer \xE7izgiler",
|
|
@@ -126,6 +134,12 @@ var STRINGS = {
|
|
|
126
134
|
const drift = direction ? `, ${direction}` : "";
|
|
127
135
|
return `Son ${span} i\xE7indeki oran hareketi: ${opening} ile a\xE7\u0131ld\u0131, \u015Fu anda ${current}${drift}.`;
|
|
128
136
|
},
|
|
137
|
+
clubMatchPreviewHeading: "Ma\xE7 \xF6nizlemesi",
|
|
138
|
+
clubTeamDnaHeading: "Nas\u0131l oynuyorlar",
|
|
139
|
+
clubFormHeading: "Son form",
|
|
140
|
+
clubCountdownLabel: "Ba\u015Flama vuru\u015Funa kalan",
|
|
141
|
+
clubKickoff: (ms) => new Intl.DateTimeFormat("tr-TR", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
|
|
142
|
+
clubKickoffAria: (ms) => `Ba\u015Flama vuru\u015Fu ${new Intl.DateTimeFormat("tr-TR", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }).format(new Date(ms))}`,
|
|
129
143
|
inSlip: "Kuponda",
|
|
130
144
|
slipAdded: (n) => n === void 0 ? "Kupona eklendi" : `Kupona eklendi (${n} se\xE7im)`,
|
|
131
145
|
slipDuplicate: "Bu se\xE7im kuponunuzda zaten var",
|
|
@@ -168,6 +182,7 @@ function normalizeUi(cfg) {
|
|
|
168
182
|
hideStats: strings.hideStats,
|
|
169
183
|
oddsLabel: strings.oddsLabel,
|
|
170
184
|
liveLabel: strings.liveLabel,
|
|
185
|
+
marketFloorLabel: strings.marketFloorLabel,
|
|
171
186
|
marketPrices: strings.marketPrices,
|
|
172
187
|
moreLines: strings.moreLines,
|
|
173
188
|
hideLines: strings.hideLines,
|
|
@@ -185,6 +200,12 @@ function normalizeUi(cfg) {
|
|
|
185
200
|
excludedSuspended: strings.excludedSuspended,
|
|
186
201
|
chartTimeLabel: strings.chartTimeLabel,
|
|
187
202
|
chartAria: strings.chartAria,
|
|
203
|
+
clubMatchPreviewHeading: strings.clubMatchPreviewHeading,
|
|
204
|
+
clubTeamDnaHeading: strings.clubTeamDnaHeading,
|
|
205
|
+
clubFormHeading: strings.clubFormHeading,
|
|
206
|
+
clubCountdownLabel: strings.clubCountdownLabel,
|
|
207
|
+
clubKickoff: strings.clubKickoff,
|
|
208
|
+
clubKickoffAria: strings.clubKickoffAria,
|
|
188
209
|
addToSlip: strings.addToSlip,
|
|
189
210
|
inSlip: strings.inSlip,
|
|
190
211
|
slipAdded: strings.slipAdded,
|
|
@@ -378,6 +399,7 @@ function toInsightVM(insight) {
|
|
|
378
399
|
matchId: typeof insight.matchId === "number" ? insight.matchId : 0,
|
|
379
400
|
matchOddsId,
|
|
380
401
|
addToSlipEnabled: insight.addToSlipEnabled === true,
|
|
402
|
+
isMarketFloor: insight.isMarketFloor === true,
|
|
381
403
|
oddsDecimal: typeof oddsValue === "number" && Number.isFinite(oddsValue) ? oddsValue : void 0,
|
|
382
404
|
quotedAtUtc: str(insight.odds?.quotedAtUtc),
|
|
383
405
|
previousOdds: previous !== void 0 && direction !== void 0 ? previous.toFixed(2) : void 0,
|
|
@@ -531,7 +553,8 @@ function applyEvent(state, event) {
|
|
|
531
553
|
messages: mapActive(state, (t) => ({
|
|
532
554
|
...t,
|
|
533
555
|
done: true,
|
|
534
|
-
greetingDashboard: event.data.dashboard ?? void 0
|
|
556
|
+
greetingDashboard: event.data.dashboard ?? void 0,
|
|
557
|
+
clubDashboard: event.data.clubDashboard ?? void 0
|
|
535
558
|
}))
|
|
536
559
|
};
|
|
537
560
|
}
|
|
@@ -698,7 +721,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
698
721
|
}
|
|
699
722
|
|
|
700
723
|
// src/components/ChatPanel.tsx
|
|
701
|
-
var
|
|
724
|
+
var import_react11 = require("react");
|
|
702
725
|
|
|
703
726
|
// src/components/ChatHeader.tsx
|
|
704
727
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -711,7 +734,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
711
734
|
}
|
|
712
735
|
|
|
713
736
|
// src/components/MessageList.tsx
|
|
714
|
-
var
|
|
737
|
+
var import_react9 = require("react");
|
|
715
738
|
|
|
716
739
|
// src/components/Markdown.tsx
|
|
717
740
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -995,10 +1018,13 @@ function StatsDisclosure({ it, ui }) {
|
|
|
995
1018
|
function InsightCard({ it, ui, slip }) {
|
|
996
1019
|
const live = it.isLive || it.phase === "live";
|
|
997
1020
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-binsight", children: [
|
|
998
|
-
live
|
|
999
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
1000
|
-
|
|
1001
|
-
|
|
1021
|
+
live || it.isMarketFloor ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-status", children: [
|
|
1022
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-live", children: [
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1024
|
+
ui?.liveLabel ?? "Live"
|
|
1025
|
+
] }) : null,
|
|
1026
|
+
it.isMarketFloor ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null
|
|
1027
|
+
] }) : null,
|
|
1002
1028
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-head", children: [
|
|
1003
1029
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-mkt", children: [
|
|
1004
1030
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-market", children: it.market }),
|
|
@@ -1195,28 +1221,184 @@ function GreetingDashboard({ dashboard, onTap }) {
|
|
|
1195
1221
|
] });
|
|
1196
1222
|
}
|
|
1197
1223
|
|
|
1198
|
-
// src/components/
|
|
1224
|
+
// src/components/club-dashboard/GreetingHeaderBlock.tsx
|
|
1199
1225
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1200
|
-
function
|
|
1226
|
+
function GreetingHeaderBlock({ block }) {
|
|
1227
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
|
|
1228
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
|
|
1229
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
|
|
1230
|
+
] });
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
// src/components/club-dashboard/FixtureHeroBlock.tsx
|
|
1234
|
+
var import_react7 = require("react");
|
|
1235
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1236
|
+
function initials2(name) {
|
|
1237
|
+
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
1238
|
+
}
|
|
1239
|
+
function Crest2({ url, name }) {
|
|
1240
|
+
const [broken, setBroken] = (0, import_react7.useState)(false);
|
|
1241
|
+
if (!url || broken) {
|
|
1242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials2(name) });
|
|
1243
|
+
}
|
|
1244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
|
|
1245
|
+
}
|
|
1246
|
+
function FixtureHeroBlock({
|
|
1247
|
+
block,
|
|
1248
|
+
ui,
|
|
1249
|
+
onAction
|
|
1250
|
+
}) {
|
|
1251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-tie", children: [
|
|
1253
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: block.homeCrestUrl, name: block.homeName }),
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
|
|
1256
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
|
|
1257
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: block.awayCrestUrl, name: block.awayName })
|
|
1258
|
+
] }),
|
|
1259
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
|
|
1260
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
|
|
1261
|
+
block.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
|
|
1262
|
+
block.competition ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
|
|
1263
|
+
] }),
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, block.ctaLabel), children: block.ctaLabel })
|
|
1265
|
+
] });
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// src/components/club-dashboard/FormGuideBlock.tsx
|
|
1269
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1270
|
+
function FormGuideBlock({ block }) {
|
|
1271
|
+
if (block.rows.length === 0) return null;
|
|
1272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
|
|
1273
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
|
|
1274
|
+
row.name,
|
|
1275
|
+
row.position != null ? ` #${row.position}` : ""
|
|
1276
|
+
] }),
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
|
|
1278
|
+
] }, row.name)) });
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// src/components/club-dashboard/MatchPreviewBlock.tsx
|
|
1282
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1283
|
+
function MatchPreviewBlock({
|
|
1284
|
+
block,
|
|
1285
|
+
ui,
|
|
1286
|
+
onAction
|
|
1287
|
+
}) {
|
|
1288
|
+
if (block.lines.length === 0) return null;
|
|
1289
|
+
const heading = ui.clubMatchPreviewHeading;
|
|
1290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1292
|
+
block.lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { children: line }, i))
|
|
1293
|
+
] });
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// src/components/club-dashboard/TeamDnaBlock.tsx
|
|
1297
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1298
|
+
function TeamDnaBlock({
|
|
1299
|
+
block,
|
|
1300
|
+
ui,
|
|
1301
|
+
onAction
|
|
1302
|
+
}) {
|
|
1303
|
+
if (block.lines.length === 0) return null;
|
|
1304
|
+
const heading = ui.clubTeamDnaHeading;
|
|
1305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
|
|
1306
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
|
|
1307
|
+
block.lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: line }, i))
|
|
1308
|
+
] });
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// src/components/club-dashboard/CountdownBlock.tsx
|
|
1312
|
+
var import_react8 = require("react");
|
|
1313
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1314
|
+
var DAY_MS = 24 * 3600 * 1e3;
|
|
1315
|
+
function pad2(n) {
|
|
1316
|
+
return String(n).padStart(2, "0");
|
|
1317
|
+
}
|
|
1318
|
+
function splitRemaining(remainingMs) {
|
|
1319
|
+
const totalSeconds = Math.max(0, Math.floor(remainingMs / 1e3));
|
|
1320
|
+
const h = Math.floor(totalSeconds / 3600);
|
|
1321
|
+
const m = Math.floor(totalSeconds % 3600 / 60);
|
|
1322
|
+
const s = totalSeconds % 60;
|
|
1323
|
+
return { h: pad2(h), m: pad2(m), s: pad2(s) };
|
|
1324
|
+
}
|
|
1325
|
+
function CountdownBlock({ block, ui }) {
|
|
1326
|
+
const [remainingMs, setRemainingMs] = (0, import_react8.useState)(() => block.kickoffUnix * 1e3 - Date.now());
|
|
1327
|
+
(0, import_react8.useEffect)(() => {
|
|
1328
|
+
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1329
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
1330
|
+
const id = setInterval(() => {
|
|
1331
|
+
setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
|
|
1332
|
+
}, 1e3);
|
|
1333
|
+
return () => clearInterval(id);
|
|
1334
|
+
}, [block.kickoffUnix]);
|
|
1335
|
+
if (remainingMs <= 0) return null;
|
|
1336
|
+
if (remainingMs > DAY_MS) return null;
|
|
1337
|
+
const { h, m, s } = splitRemaining(remainingMs);
|
|
1338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
|
|
1340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
|
|
1341
|
+
"h",
|
|
1342
|
+
" ",
|
|
1343
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
|
|
1344
|
+
"m",
|
|
1345
|
+
" ",
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
|
|
1347
|
+
"s"
|
|
1348
|
+
] }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
|
|
1350
|
+
] });
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
// src/components/club-dashboard/ClubDashboard.tsx
|
|
1354
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1355
|
+
var CLUB_BLOCK_REGISTRY = {
|
|
1356
|
+
greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GreetingHeaderBlock, { block }) : null,
|
|
1357
|
+
fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
|
|
1358
|
+
formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FormGuideBlock, { block, ui }) : null,
|
|
1359
|
+
matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
|
|
1360
|
+
teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
|
|
1361
|
+
countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CountdownBlock, { block, ui }) : null
|
|
1362
|
+
};
|
|
1363
|
+
function ClubDashboard({
|
|
1364
|
+
dashboard,
|
|
1365
|
+
ui,
|
|
1366
|
+
onAction
|
|
1367
|
+
}) {
|
|
1368
|
+
if (!dashboard.blocks.length) return null;
|
|
1369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
|
|
1370
|
+
const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
|
|
1371
|
+
if (!Comp) {
|
|
1372
|
+
console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
|
|
1373
|
+
return null;
|
|
1374
|
+
}
|
|
1375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp, { block, ui, onAction }) }, i);
|
|
1376
|
+
}) });
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// src/components/ChatMessage.tsx
|
|
1380
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1381
|
+
function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
|
|
1201
1382
|
if (message.role === "user") {
|
|
1202
|
-
return /* @__PURE__ */ (0,
|
|
1383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
|
|
1203
1384
|
}
|
|
1204
|
-
return /* @__PURE__ */ (0,
|
|
1205
|
-
message.text && !message.greetingDashboard ? /* @__PURE__ */ (0,
|
|
1206
|
-
message.greetingDashboard ? /* @__PURE__ */ (0,
|
|
1207
|
-
/* @__PURE__ */ (0,
|
|
1208
|
-
/* @__PURE__ */ (0,
|
|
1209
|
-
/* @__PURE__ */ (0,
|
|
1210
|
-
/* @__PURE__ */ (0,
|
|
1211
|
-
/* @__PURE__ */ (0,
|
|
1385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
1386
|
+
message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Markdown, { text: message.text }) : null,
|
|
1387
|
+
message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
|
|
1388
|
+
message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
|
|
1389
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
1390
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
|
|
1391
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
|
|
1393
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
1212
1394
|
] });
|
|
1213
1395
|
}
|
|
1214
1396
|
|
|
1215
1397
|
// src/components/IntentChips.tsx
|
|
1216
|
-
var
|
|
1398
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1217
1399
|
function IntentChips({ chips, onPick }) {
|
|
1218
1400
|
if (chips.length === 0) return null;
|
|
1219
|
-
return /* @__PURE__ */ (0,
|
|
1401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
1220
1402
|
}
|
|
1221
1403
|
|
|
1222
1404
|
// src/scroll.ts
|
|
@@ -1226,18 +1408,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
1226
1408
|
}
|
|
1227
1409
|
|
|
1228
1410
|
// src/components/MessageList.tsx
|
|
1229
|
-
var
|
|
1411
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1230
1412
|
function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
1231
1413
|
const { state, send } = controller;
|
|
1232
|
-
const listRef = (0,
|
|
1233
|
-
const endRef = (0,
|
|
1234
|
-
const pinnedRef = (0,
|
|
1235
|
-
(0,
|
|
1414
|
+
const listRef = (0, import_react9.useRef)(null);
|
|
1415
|
+
const endRef = (0, import_react9.useRef)(null);
|
|
1416
|
+
const pinnedRef = (0, import_react9.useRef)(true);
|
|
1417
|
+
(0, import_react9.useEffect)(() => {
|
|
1236
1418
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
1237
1419
|
}, [state.messages, state.status]);
|
|
1238
1420
|
const hasUserMessage = state.messages.some((m) => m.role === "user");
|
|
1239
1421
|
const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
|
|
1240
|
-
return /* @__PURE__ */ (0,
|
|
1422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1241
1423
|
"div",
|
|
1242
1424
|
{
|
|
1243
1425
|
className: "ss-w-list",
|
|
@@ -1247,7 +1429,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1247
1429
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
1248
1430
|
},
|
|
1249
1431
|
children: [
|
|
1250
|
-
state.messages.map((m) => /* @__PURE__ */ (0,
|
|
1432
|
+
state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1251
1433
|
ChatMessage,
|
|
1252
1434
|
{
|
|
1253
1435
|
message: m,
|
|
@@ -1257,30 +1439,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
|
|
|
1257
1439
|
send(tile.actionValue, { displayText: tile.title });
|
|
1258
1440
|
if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
|
|
1259
1441
|
},
|
|
1442
|
+
onClubAction: (actionValue, displayText) => send(actionValue, { displayText }),
|
|
1260
1443
|
ui,
|
|
1261
1444
|
slip
|
|
1262
1445
|
},
|
|
1263
1446
|
m.id
|
|
1264
1447
|
)),
|
|
1265
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0,
|
|
1448
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
1266
1449
|
} }) : null,
|
|
1267
|
-
state.status ? /* @__PURE__ */ (0,
|
|
1268
|
-
state.error ? /* @__PURE__ */ (0,
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1450
|
+
state.status ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
|
|
1451
|
+
state.error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
|
|
1452
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
1453
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
1271
1454
|
] }) : null,
|
|
1272
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0,
|
|
1273
|
-
/* @__PURE__ */ (0,
|
|
1455
|
+
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: endRef })
|
|
1274
1457
|
]
|
|
1275
1458
|
}
|
|
1276
1459
|
);
|
|
1277
1460
|
}
|
|
1278
1461
|
|
|
1279
1462
|
// src/components/ChatInput.tsx
|
|
1280
|
-
var
|
|
1281
|
-
var
|
|
1463
|
+
var import_react10 = require("react");
|
|
1464
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1282
1465
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
1283
|
-
const [value, setValue] = (0,
|
|
1466
|
+
const [value, setValue] = (0, import_react10.useState)("");
|
|
1284
1467
|
const submit = () => {
|
|
1285
1468
|
const t = value.trim();
|
|
1286
1469
|
if (!t) return;
|
|
@@ -1293,18 +1476,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
1293
1476
|
submit();
|
|
1294
1477
|
}
|
|
1295
1478
|
};
|
|
1296
|
-
return /* @__PURE__ */ (0,
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1298
|
-
streaming ? /* @__PURE__ */ (0,
|
|
1479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-input", children: [
|
|
1480
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
1481
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendIcon, {}) })
|
|
1299
1482
|
] });
|
|
1300
1483
|
}
|
|
1301
1484
|
|
|
1302
1485
|
// src/components/ChatPanel.tsx
|
|
1303
|
-
var
|
|
1486
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1304
1487
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
1305
1488
|
function useIsModal() {
|
|
1306
|
-
const [modal, setModal] = (0,
|
|
1307
|
-
(0,
|
|
1489
|
+
const [modal, setModal] = (0, import_react11.useState)(false);
|
|
1490
|
+
(0, import_react11.useEffect)(() => {
|
|
1308
1491
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1309
1492
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
1310
1493
|
const sync = () => setModal(mql.matches);
|
|
@@ -1317,17 +1500,17 @@ function useIsModal() {
|
|
|
1317
1500
|
function ChatPanel({ controller, ui, slip, onDashboardTap }) {
|
|
1318
1501
|
const { state, close, stop, send } = controller;
|
|
1319
1502
|
const isModal = useIsModal();
|
|
1320
|
-
(0,
|
|
1503
|
+
(0, import_react11.useEffect)(() => {
|
|
1321
1504
|
const onKey = (e) => {
|
|
1322
1505
|
if (e.key === "Escape") close();
|
|
1323
1506
|
};
|
|
1324
1507
|
window.addEventListener("keydown", onKey);
|
|
1325
1508
|
return () => window.removeEventListener("keydown", onKey);
|
|
1326
1509
|
}, [close]);
|
|
1327
|
-
return /* @__PURE__ */ (0,
|
|
1328
|
-
/* @__PURE__ */ (0,
|
|
1329
|
-
/* @__PURE__ */ (0,
|
|
1330
|
-
/* @__PURE__ */ (0,
|
|
1510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
1512
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
|
|
1513
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
1331
1514
|
] });
|
|
1332
1515
|
}
|
|
1333
1516
|
|
|
@@ -1471,6 +1654,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1471
1654
|
.ss-w-bi-comp { font-size: 10.5px; color: var(--ss-w-faint); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1472
1655
|
.ss-w-bi-live { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #fff; background: #c0392b; border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; gap: 4px; flex: none; }
|
|
1473
1656
|
.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }
|
|
1657
|
+
.ss-w-bi-floor { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; flex: none; }
|
|
1474
1658
|
.ss-w-bi-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
1475
1659
|
.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
1476
1660
|
.ss-w-bi-market { font-size: 15px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }
|
|
@@ -1652,10 +1836,46 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1652
1836
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }
|
|
1653
1837
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }
|
|
1654
1838
|
.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }
|
|
1839
|
+
|
|
1840
|
+
/* club match-day dashboard */
|
|
1841
|
+
.ss-w-cdash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
|
|
1842
|
+
.ss-w-cdash-block { display: flex; flex-direction: column; }
|
|
1843
|
+
|
|
1844
|
+
.ss-w-cdash-greeting { display: flex; flex-direction: column; gap: 2px; }
|
|
1845
|
+
.ss-w-cdash-greeting-title { font-weight: 700; font-size: 14px; color: var(--ss-w-ink); }
|
|
1846
|
+
.ss-w-cdash-greeting-subtitle { font-size: 11.5px; color: var(--ss-w-faint); }
|
|
1847
|
+
|
|
1848
|
+
.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; }
|
|
1849
|
+
.ss-w-cdash-tie { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
|
|
1850
|
+
.ss-w-cdash-team { font-weight: 650; font-size: 13px; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
|
|
1851
|
+
.ss-w-cdash-vs { font-size: 11px; color: var(--ss-w-faint); font-weight: 600; }
|
|
1852
|
+
.ss-w-cdash-crest { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--ss-w-bubble); }
|
|
1853
|
+
.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)); }
|
|
1854
|
+
.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); }
|
|
1855
|
+
.ss-w-cdash-kickoff { font-weight: 700; color: var(--ss-w-ink); }
|
|
1856
|
+
.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; }
|
|
1857
|
+
|
|
1858
|
+
.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; }
|
|
1859
|
+
.ss-w-cdash-form-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
1860
|
+
.ss-w-cdash-form-name { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
|
|
1861
|
+
.ss-w-cdash-form-pills { flex: none; display: flex; align-items: center; gap: 3px; }
|
|
1862
|
+
.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; }
|
|
1863
|
+
.ss-w-cdash-pill--w { background: color-mix(in srgb, var(--ss-w-pos) 88%, black); }
|
|
1864
|
+
.ss-w-cdash-pill--d { background: var(--ss-w-faint); }
|
|
1865
|
+
.ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
|
|
1866
|
+
|
|
1867
|
+
.ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px; font: inherit; cursor: pointer; }
|
|
1868
|
+
.ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
|
|
1869
|
+
.ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); }
|
|
1870
|
+
|
|
1871
|
+
.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; }
|
|
1872
|
+
.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); }
|
|
1873
|
+
.ss-w-cdash-cd-h, .ss-w-cdash-cd-m, .ss-w-cdash-cd-s { color: var(--ss-w-accent); }
|
|
1874
|
+
.ss-w-cdash-cd-label { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }
|
|
1655
1875
|
`;
|
|
1656
1876
|
|
|
1657
1877
|
// src/StatsWidget.tsx
|
|
1658
|
-
var
|
|
1878
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1659
1879
|
function buildClient(props) {
|
|
1660
1880
|
try {
|
|
1661
1881
|
if ("client" in props && props.client) {
|
|
@@ -1680,11 +1900,11 @@ function injectStyles(root) {
|
|
|
1680
1900
|
function StatsWidget(props) {
|
|
1681
1901
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
1682
1902
|
const cfg = props.config;
|
|
1683
|
-
const built = (0,
|
|
1684
|
-
const ui = (0,
|
|
1685
|
-
const rootRef = (0,
|
|
1903
|
+
const built = (0, import_react12.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
1904
|
+
const ui = (0, import_react12.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
1905
|
+
const rootRef = (0, import_react12.useRef)(null);
|
|
1686
1906
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
1687
|
-
const slip = (0,
|
|
1907
|
+
const slip = (0, import_react12.useMemo)(
|
|
1688
1908
|
() => ({
|
|
1689
1909
|
onAddToSlip: props.config?.onAddToSlip,
|
|
1690
1910
|
conversationId: controller.state.conversationId ?? void 0,
|
|
@@ -1697,18 +1917,18 @@ function StatsWidget(props) {
|
|
|
1697
1917
|
}),
|
|
1698
1918
|
[props.config?.onAddToSlip, controller.state.conversationId, built]
|
|
1699
1919
|
);
|
|
1700
|
-
const onDashboardTap = (0,
|
|
1920
|
+
const onDashboardTap = (0, import_react12.useMemo)(
|
|
1701
1921
|
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
1702
1922
|
[built]
|
|
1703
1923
|
);
|
|
1704
|
-
(0,
|
|
1924
|
+
(0, import_react12.useEffect)(() => {
|
|
1705
1925
|
if (!built || !ui.injectStyles) return;
|
|
1706
1926
|
const node = rootRef.current?.getRootNode();
|
|
1707
1927
|
if (node) injectStyles(node);
|
|
1708
1928
|
}, [built, ui.injectStyles]);
|
|
1709
1929
|
if (!built) return null;
|
|
1710
1930
|
const attrs = themeAttrs(ui);
|
|
1711
|
-
return /* @__PURE__ */ (0,
|
|
1931
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1712
1932
|
ChatFab,
|
|
1713
1933
|
{
|
|
1714
1934
|
label: ui.launcherLabel,
|