@sensiblestats/widget-react 0.4.0 → 0.6.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 +30 -0
- package/dist/index.cjs +100 -39
- 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 +88 -27
- package/dist/index.js.map +1 -1
- package/dist/styles.css +24 -10
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @sensiblestats/widget-react
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Show competition name on betting insight cards. This shipped to master in
|
|
8
|
+
`6d629e6b` but never reached npm because the version wasn't bumped, so the
|
|
9
|
+
release workflow's `--tolerate-republish` skipped every package. This changeset
|
|
10
|
+
bumps all three so the change actually publishes (widget-embed re-bundles
|
|
11
|
+
widget-react, so it must be republished too).
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
- @sensiblestats/widget-sdk@0.5.0
|
|
17
|
+
|
|
18
|
+
## 0.5.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- Redesigned betting-insight card with scoped supporting stats.
|
|
23
|
+
|
|
24
|
+
- **widget-sdk:** extend `BettingInsight` with `homeTeamName`, `awayTeamName`, and `scopes` (`{ key, label, stats }[]`), so consumers can type the fixture line and the per-scope stat sets (this league / all competitions / head-to-head) the server now streams.
|
|
25
|
+
- **widget-react:** rebuild the betting card around the new payload — a phase-aware live/pre-match status line with the fixture, a promoted market with clearly labeled odds (and an optional bookmaker name), and scope chips that switch the supporting stats in place (shown only when ≥2 scopes are present, otherwise flat stat rows with a "show more" expander). The responsible-gambling disclaimer always renders. Type scale and spacing match the surrounding chat cards.
|
|
26
|
+
- **widget-embed:** rebuild against `@sensiblestats/widget-react` so the hosted embed renders the redesigned card.
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
- @sensiblestats/widget-sdk@0.4.0
|
|
32
|
+
|
|
3
33
|
## 0.4.0
|
|
4
34
|
|
|
5
35
|
### 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_react7 = require("react");
|
|
40
40
|
var import_widget_sdk3 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/i18n.ts
|
|
@@ -52,7 +52,9 @@ var STRINGS = {
|
|
|
52
52
|
somethingWentWrong: "Something went wrong.",
|
|
53
53
|
retry: "Retry",
|
|
54
54
|
showLess: "Show less",
|
|
55
|
-
showMore: (n) => `Show ${n} more
|
|
55
|
+
showMore: (n) => `Show ${n} more`,
|
|
56
|
+
oddsLabel: "Odds",
|
|
57
|
+
liveLabel: "Live"
|
|
56
58
|
},
|
|
57
59
|
tr: {
|
|
58
60
|
launcherLabel: "SensibleStats ile sohbet et",
|
|
@@ -65,7 +67,9 @@ var STRINGS = {
|
|
|
65
67
|
somethingWentWrong: "Bir \u015Feyler ters gitti.",
|
|
66
68
|
retry: "Tekrar dene",
|
|
67
69
|
showLess: "Daha az g\xF6ster",
|
|
68
|
-
showMore: (n) => `${n} tane daha g\xF6ster
|
|
70
|
+
showMore: (n) => `${n} tane daha g\xF6ster`,
|
|
71
|
+
oddsLabel: "Oran",
|
|
72
|
+
liveLabel: "Canl\u0131"
|
|
69
73
|
}
|
|
70
74
|
};
|
|
71
75
|
function resolveLocaleStrings(locale) {
|
|
@@ -95,7 +99,9 @@ function normalizeUi(cfg) {
|
|
|
95
99
|
somethingWentWrong: strings.somethingWentWrong,
|
|
96
100
|
retry: strings.retry,
|
|
97
101
|
showLess: strings.showLess,
|
|
98
|
-
showMore: strings.showMore
|
|
102
|
+
showMore: strings.showMore,
|
|
103
|
+
oddsLabel: strings.oddsLabel,
|
|
104
|
+
liveLabel: strings.liveLabel
|
|
99
105
|
};
|
|
100
106
|
}
|
|
101
107
|
function toClientOptions(cfg) {
|
|
@@ -175,6 +181,11 @@ function toInsightVM(insight) {
|
|
|
175
181
|
const selection = [str(insight.selectionLabel), str(insight.line)].filter(Boolean).join(" ") || void 0;
|
|
176
182
|
const value = insight.odds?.value;
|
|
177
183
|
const odds = typeof value === "number" && Number.isFinite(value) ? value.toFixed(2) : void 0;
|
|
184
|
+
const home = str(insight.homeTeamName);
|
|
185
|
+
const away = str(insight.awayTeamName);
|
|
186
|
+
const fixture = home && away ? `${home} vs ${away}` : void 0;
|
|
187
|
+
const competition = str(insight.competitionName);
|
|
188
|
+
const scopes = Array.isArray(insight.scopes) ? insight.scopes.map((s) => ({ key: str(s.key), label: str(s.label), stats: readStatCells(s.stats) })).filter((s) => !!s.key && !!s.label) : void 0;
|
|
178
189
|
return {
|
|
179
190
|
id: str(insight.insightId) ?? `${str(insight.ruleId) ?? "insight"}:${num(insight.matchId) ?? ""}`,
|
|
180
191
|
market,
|
|
@@ -183,6 +194,10 @@ function toInsightVM(insight) {
|
|
|
183
194
|
// The wire payload carries bookmakerId (not a name); render a name only if one is present.
|
|
184
195
|
bookmaker: str(insight.odds?.bookmakerName),
|
|
185
196
|
isLive: insight.odds?.isLive === true,
|
|
197
|
+
phase: str(insight.phase),
|
|
198
|
+
fixture,
|
|
199
|
+
competition,
|
|
200
|
+
scopes,
|
|
186
201
|
text: str(insight.text) ?? "",
|
|
187
202
|
stats: readStatCells(insight.stats),
|
|
188
203
|
disclaimer: str(insight.disclaimer)
|
|
@@ -369,7 +384,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
|
|
|
369
384
|
}
|
|
370
385
|
|
|
371
386
|
// src/components/ChatPanel.tsx
|
|
372
|
-
var
|
|
387
|
+
var import_react6 = require("react");
|
|
373
388
|
|
|
374
389
|
// src/components/ChatHeader.tsx
|
|
375
390
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -382,7 +397,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
|
|
|
382
397
|
}
|
|
383
398
|
|
|
384
399
|
// src/components/MessageList.tsx
|
|
385
|
-
var
|
|
400
|
+
var import_react4 = require("react");
|
|
386
401
|
|
|
387
402
|
// src/components/Markdown.tsx
|
|
388
403
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -436,28 +451,60 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
436
451
|
}
|
|
437
452
|
|
|
438
453
|
// src/components/BettingInsightList.tsx
|
|
454
|
+
var import_react3 = require("react");
|
|
439
455
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
456
|
+
var MAX_ROWS = 3;
|
|
457
|
+
function StatRows({ stats, ui }) {
|
|
458
|
+
const [expanded, setExpanded] = (0, import_react3.useState)(false);
|
|
459
|
+
const shown = expanded ? stats : stats.slice(0, MAX_ROWS);
|
|
460
|
+
const overflow = stats.length - MAX_ROWS;
|
|
461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ss-w-bi-rows", children: [
|
|
462
|
+
shown.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ss-w-bi-row", children: [
|
|
463
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-row-dots", "aria-hidden": "true" }),
|
|
465
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
466
|
+
] }, `${s.label}:${s.value}`)),
|
|
467
|
+
overflow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "ss-w-bi-more", onClick: () => setExpanded((v) => !v), children: expanded ? ui?.showLess ?? "Show less" : (ui?.showMore ?? ((n) => `Show ${n} more`))(overflow) }) : null
|
|
468
|
+
] });
|
|
469
|
+
}
|
|
470
|
+
function ScopedStats({ scopes, ui }) {
|
|
471
|
+
const [active, setActive] = (0, import_react3.useState)(0);
|
|
472
|
+
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ss-w-bi-scoped", children: [
|
|
474
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
475
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatRows, { stats: current.stats, ui }, current.key)
|
|
476
|
+
] });
|
|
477
|
+
}
|
|
478
|
+
function InsightCard({ it, ui }) {
|
|
479
|
+
const live = it.isLive || it.phase === "live";
|
|
480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ss-w-binsight", children: [
|
|
481
|
+
live || it.fixture || it.competition ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ss-w-bi-status", children: [
|
|
482
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "ss-w-bi-live", children: [
|
|
483
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
484
|
+
ui?.liveLabel ?? "Live"
|
|
485
|
+
] }) : null,
|
|
486
|
+
it.fixture ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-fixture", children: it.fixture }) : null,
|
|
487
|
+
it.competition ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-comp", children: it.competition }) : null
|
|
488
|
+
] }) : null,
|
|
443
489
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ss-w-bi-head", children: [
|
|
444
490
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "ss-w-bi-mkt", children: [
|
|
445
491
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-market", children: it.market }),
|
|
446
492
|
it.selection ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-sel", children: it.selection }) : null
|
|
447
493
|
] }),
|
|
448
494
|
it.odds ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "ss-w-bi-odds", children: [
|
|
449
|
-
|
|
495
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-odds-cap", children: ui?.oddsLabel ?? "Odds" }),
|
|
450
496
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("b", { children: it.odds }),
|
|
451
497
|
it.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
|
|
452
498
|
] }) : null
|
|
453
499
|
] }),
|
|
454
500
|
it.text ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "ss-w-bi-text", children: it.text }) : null,
|
|
455
|
-
it.
|
|
456
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("b", { children: s.value }),
|
|
457
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: s.label })
|
|
458
|
-
] }, `${s.label}:${s.value}`)) }) : null,
|
|
501
|
+
it.scopes && it.scopes.length >= 2 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ScopedStats, { scopes: it.scopes, ui }) : it.stats.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatRows, { stats: it.stats, ui }) : null,
|
|
459
502
|
it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
460
|
-
] }
|
|
503
|
+
] });
|
|
504
|
+
}
|
|
505
|
+
function BettingInsightList({ insights, ui }) {
|
|
506
|
+
if (!insights || insights.length === 0) return null;
|
|
507
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(InsightCard, { it, ui }, it.id)) });
|
|
461
508
|
}
|
|
462
509
|
|
|
463
510
|
// src/components/ActionButtons.tsx
|
|
@@ -482,7 +529,7 @@ function ChatMessage({ message, disabled, onAct, ui }) {
|
|
|
482
529
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
483
530
|
message.text ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Markdown, { text: message.text }) : null,
|
|
484
531
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
485
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(BettingInsightList, { insights: message.insights }),
|
|
532
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(BettingInsightList, { insights: message.insights, ui }),
|
|
486
533
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
487
534
|
] });
|
|
488
535
|
}
|
|
@@ -504,10 +551,10 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
504
551
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
505
552
|
function MessageList({ controller, ui }) {
|
|
506
553
|
const { state, send } = controller;
|
|
507
|
-
const listRef = (0,
|
|
508
|
-
const endRef = (0,
|
|
509
|
-
const pinnedRef = (0,
|
|
510
|
-
(0,
|
|
554
|
+
const listRef = (0, import_react4.useRef)(null);
|
|
555
|
+
const endRef = (0, import_react4.useRef)(null);
|
|
556
|
+
const pinnedRef = (0, import_react4.useRef)(true);
|
|
557
|
+
(0, import_react4.useEffect)(() => {
|
|
511
558
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
512
559
|
}, [state.messages, state.status]);
|
|
513
560
|
const empty = state.messages.length === 0;
|
|
@@ -546,10 +593,10 @@ function MessageList({ controller, ui }) {
|
|
|
546
593
|
}
|
|
547
594
|
|
|
548
595
|
// src/components/ChatInput.tsx
|
|
549
|
-
var
|
|
596
|
+
var import_react5 = require("react");
|
|
550
597
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
551
598
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
552
|
-
const [value, setValue] = (0,
|
|
599
|
+
const [value, setValue] = (0, import_react5.useState)("");
|
|
553
600
|
const submit = () => {
|
|
554
601
|
const t = value.trim();
|
|
555
602
|
if (!t) return;
|
|
@@ -572,8 +619,8 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
572
619
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
573
620
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
574
621
|
function useIsModal() {
|
|
575
|
-
const [modal, setModal] = (0,
|
|
576
|
-
(0,
|
|
622
|
+
const [modal, setModal] = (0, import_react6.useState)(false);
|
|
623
|
+
(0, import_react6.useEffect)(() => {
|
|
577
624
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
578
625
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
579
626
|
const sync = () => setModal(mql.matches);
|
|
@@ -586,7 +633,7 @@ function useIsModal() {
|
|
|
586
633
|
function ChatPanel({ controller, ui }) {
|
|
587
634
|
const { state, close, stop, send } = controller;
|
|
588
635
|
const isModal = useIsModal();
|
|
589
|
-
(0,
|
|
636
|
+
(0, import_react6.useEffect)(() => {
|
|
590
637
|
const onKey = (e) => {
|
|
591
638
|
if (e.key === "Escape") close();
|
|
592
639
|
};
|
|
@@ -698,19 +745,33 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
698
745
|
/* betting insights */
|
|
699
746
|
.ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }
|
|
700
747
|
.ss-w-binsight { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }
|
|
748
|
+
.ss-w-bi-status { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
749
|
+
.ss-w-bi-fixture { font-size: 11px; color: var(--ss-w-ink); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
750
|
+
.ss-w-bi-comp { font-size: 10.5px; color: var(--ss-w-faint); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
751
|
+
.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; }
|
|
752
|
+
.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }
|
|
701
753
|
.ss-w-bi-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
702
|
-
.ss-w-bi-mkt { display: flex; flex-direction: column; min-width: 0; }
|
|
703
|
-
.ss-w-bi-market { font-size:
|
|
704
|
-
.ss-w-bi-sel { font-
|
|
705
|
-
.ss-w-bi-odds { margin-left: auto; display: flex; align-items: center;
|
|
706
|
-
.ss-w-bi-odds
|
|
707
|
-
.ss-w-bi-
|
|
708
|
-
.ss-w-bi-
|
|
754
|
+
.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
|
|
755
|
+
.ss-w-bi-market { font-size: 13px; font-weight: 660; line-height: 1.3; color: var(--ss-w-ink); }
|
|
756
|
+
.ss-w-bi-sel { font-size: 11px; line-height: 1.3; color: var(--ss-w-faint); }
|
|
757
|
+
.ss-w-bi-odds { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 24%, var(--ss-w-line)); border-radius: 8px; padding: 3px 9px; min-width: 56px; }
|
|
758
|
+
.ss-w-bi-odds-cap { font-size: 8px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ss-w-faint); }
|
|
759
|
+
.ss-w-bi-odds b { font-size: 15px; font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.15; }
|
|
760
|
+
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
709
761
|
.ss-w-bi-text { font-size: 12px; color: var(--ss-w-ink); }
|
|
710
|
-
.ss-w-bi-
|
|
711
|
-
.ss-w-bi-
|
|
712
|
-
.ss-w-bi-
|
|
762
|
+
.ss-w-bi-rows { display: flex; flex-direction: column; }
|
|
763
|
+
.ss-w-bi-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; border-top: 1px solid var(--ss-w-line); }
|
|
764
|
+
.ss-w-bi-row:first-child { border-top: none; }
|
|
765
|
+
.ss-w-bi-row-lbl { font-size: 11px; color: var(--ss-w-faint); min-width: 0; }
|
|
766
|
+
.ss-w-bi-row-dots { flex: 1; border-bottom: 1px dotted var(--ss-w-line); transform: translateY(-3px); min-width: 12px; }
|
|
767
|
+
.ss-w-bi-row-num { font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 12.5px; flex: none; color: var(--ss-w-ink); }
|
|
768
|
+
.ss-w-bi-more { align-self: flex-start; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11px; font-weight: 560; padding: 2px 0; cursor: pointer; }
|
|
769
|
+
.ss-w-bi-more:hover { text-decoration: underline; }
|
|
713
770
|
.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }
|
|
771
|
+
.ss-w-bi-scoped { display: flex; flex-direction: column; gap: 6px; }
|
|
772
|
+
.ss-w-bi-scopes { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
|
|
773
|
+
.ss-w-bi-chip { font-size: 11px; font-weight: 550; border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 3px 10px; color: var(--ss-w-ink); background: var(--ss-w-bubble); cursor: pointer; }
|
|
774
|
+
.ss-w-bi-chip[aria-pressed="true"] { color: #fff; background: var(--ss-w-accent); border-color: var(--ss-w-accent); }
|
|
714
775
|
|
|
715
776
|
/* action buttons */
|
|
716
777
|
.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
|
|
@@ -766,11 +827,11 @@ function injectStyles(root) {
|
|
|
766
827
|
function StatsWidget(props) {
|
|
767
828
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
768
829
|
const cfg = props.config;
|
|
769
|
-
const built = (0,
|
|
770
|
-
const ui = (0,
|
|
771
|
-
const rootRef = (0,
|
|
830
|
+
const built = (0, import_react7.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
831
|
+
const ui = (0, import_react7.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
832
|
+
const rootRef = (0, import_react7.useRef)(null);
|
|
772
833
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
|
|
773
|
-
(0,
|
|
834
|
+
(0, import_react7.useEffect)(() => {
|
|
774
835
|
if (!built || !ui.injectStyles) return;
|
|
775
836
|
const node = rootRef.current?.getRootNode();
|
|
776
837
|
if (node) injectStyles(node);
|