@sensiblestats/widget-react 0.2.1 → 0.3.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 +11 -0
- package/dist/index.cjs +53 -36
- 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 +53 -36
- package/dist/index.js.map +1 -1
- package/dist/styles.css +7 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -114,8 +114,7 @@ function toCardVM(card) {
|
|
|
114
114
|
name: card.canonicalName,
|
|
115
115
|
image: str(card.imagePath) ?? str(card.imageUrl) ?? str(card.image_url) ?? str(card.logoUrl) ?? str(card.logo),
|
|
116
116
|
sub: str(card.subtitle) ?? str(card.teamName) ?? str(card.leagueName) ?? str(card.position),
|
|
117
|
-
stats: readStats(card)
|
|
118
|
-
query: card.canonicalName
|
|
117
|
+
stats: readStats(card)
|
|
119
118
|
};
|
|
120
119
|
}
|
|
121
120
|
function toActionVM(action) {
|
|
@@ -288,9 +287,6 @@ function SendIcon() {
|
|
|
288
287
|
function CloseIcon() {
|
|
289
288
|
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { fill: "none", d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2" }) });
|
|
290
289
|
}
|
|
291
|
-
function ChevronIcon() {
|
|
292
|
-
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { fill: "none", stroke: "currentColor", strokeWidth: "2", d: "M9 6l6 6-6 6" }) });
|
|
293
|
-
}
|
|
294
290
|
|
|
295
291
|
// src/components/GreetingBubble.tsx
|
|
296
292
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
@@ -349,13 +345,13 @@ var MAX_VISIBLE = 3;
|
|
|
349
345
|
function initials(name) {
|
|
350
346
|
return name.split(/\s+/).slice(0, 2).map((w) => w[0] ?? "").join("").toUpperCase();
|
|
351
347
|
}
|
|
352
|
-
function EntityCardList({ cards, disabled,
|
|
348
|
+
function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMoreLabel = (n) => `Show ${n} more` }) {
|
|
353
349
|
const [expanded, setExpanded] = useState(false);
|
|
354
350
|
if (cards.length === 0) return null;
|
|
355
351
|
const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE);
|
|
356
352
|
const overflow = cards.length - MAX_VISIBLE;
|
|
357
353
|
return /* @__PURE__ */ jsxs4("div", { className: "ss-w-cards", children: [
|
|
358
|
-
visible.map((c) => /* @__PURE__ */ jsxs4("
|
|
354
|
+
visible.map((c) => /* @__PURE__ */ jsxs4("div", { className: "ss-w-ecard", "data-kind": c.kind, children: [
|
|
359
355
|
/* @__PURE__ */ jsx6(
|
|
360
356
|
"span",
|
|
361
357
|
{
|
|
@@ -372,8 +368,7 @@ function EntityCardList({ cards, disabled, onSelect, showLessLabel = "Show less"
|
|
|
372
368
|
c.stats.map((s) => /* @__PURE__ */ jsxs4("span", { className: "ss-w-stat", children: [
|
|
373
369
|
/* @__PURE__ */ jsx6("b", { children: s.value }),
|
|
374
370
|
/* @__PURE__ */ jsx6("span", { children: s.label })
|
|
375
|
-
] }, s.label))
|
|
376
|
-
/* @__PURE__ */ jsx6("span", { className: "ss-w-chev", children: /* @__PURE__ */ jsx6(ChevronIcon, {}) })
|
|
371
|
+
] }, s.label))
|
|
377
372
|
] }, c.id)),
|
|
378
373
|
overflow > 0 ? /* @__PURE__ */ jsx6("button", { type: "button", className: "ss-w-cards-more", disabled, onClick: () => setExpanded((v) => !v), children: expanded ? showLessLabel : showMoreLabel(overflow) }) : null
|
|
379
374
|
] });
|
|
@@ -394,13 +389,13 @@ function ActionButtons({ actions, loading, disabled, onAct }) {
|
|
|
394
389
|
|
|
395
390
|
// src/components/ChatMessage.tsx
|
|
396
391
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
397
|
-
function ChatMessage({ message, disabled, onAct,
|
|
392
|
+
function ChatMessage({ message, disabled, onAct, ui }) {
|
|
398
393
|
if (message.role === "user") {
|
|
399
394
|
return /* @__PURE__ */ jsx8("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ jsx8("div", { className: "ss-w-bubble", children: message.text }) });
|
|
400
395
|
}
|
|
401
396
|
return /* @__PURE__ */ jsxs6("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
402
397
|
message.text ? /* @__PURE__ */ jsx8(Markdown, { text: message.text }) : null,
|
|
403
|
-
/* @__PURE__ */ jsx8(EntityCardList, { cards: message.cards, disabled,
|
|
398
|
+
/* @__PURE__ */ jsx8(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
404
399
|
/* @__PURE__ */ jsx8(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
405
400
|
] });
|
|
406
401
|
}
|
|
@@ -412,37 +407,55 @@ function IntentChips({ chips, onPick }) {
|
|
|
412
407
|
return /* @__PURE__ */ jsx9("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx9("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
413
408
|
}
|
|
414
409
|
|
|
410
|
+
// src/scroll.ts
|
|
411
|
+
var PIN_THRESHOLD = 48;
|
|
412
|
+
function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
413
|
+
return el.scrollHeight - el.scrollTop - el.clientHeight <= threshold;
|
|
414
|
+
}
|
|
415
|
+
|
|
415
416
|
// src/components/MessageList.tsx
|
|
416
417
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
417
418
|
function MessageList({ controller, ui }) {
|
|
418
419
|
const { state, send } = controller;
|
|
420
|
+
const listRef = useRef2(null);
|
|
419
421
|
const endRef = useRef2(null);
|
|
422
|
+
const pinnedRef = useRef2(true);
|
|
420
423
|
useEffect2(() => {
|
|
421
|
-
endRef.current?.scrollIntoView({ block: "end" });
|
|
424
|
+
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
422
425
|
}, [state.messages, state.status]);
|
|
423
426
|
const empty = state.messages.length === 0;
|
|
424
|
-
return /* @__PURE__ */ jsxs7(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
ui
|
|
427
|
+
return /* @__PURE__ */ jsxs7(
|
|
428
|
+
"div",
|
|
429
|
+
{
|
|
430
|
+
className: "ss-w-list",
|
|
431
|
+
"aria-live": "polite",
|
|
432
|
+
ref: listRef,
|
|
433
|
+
onScroll: () => {
|
|
434
|
+
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
433
435
|
},
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
436
|
+
children: [
|
|
437
|
+
state.messages.map((m) => /* @__PURE__ */ jsx10(
|
|
438
|
+
ChatMessage,
|
|
439
|
+
{
|
|
440
|
+
message: m,
|
|
441
|
+
disabled: state.isStreaming,
|
|
442
|
+
onAct: (a) => send(a.message, { actionId: a.actionId, displayText: a.label }),
|
|
443
|
+
ui
|
|
444
|
+
},
|
|
445
|
+
m.id
|
|
446
|
+
)),
|
|
447
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx10(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
448
|
+
} }) : null,
|
|
449
|
+
state.status ? /* @__PURE__ */ jsx10("div", { className: "ss-w-status", children: state.status }) : null,
|
|
450
|
+
state.error ? /* @__PURE__ */ jsxs7("div", { className: "ss-w-error", role: "alert", children: [
|
|
451
|
+
/* @__PURE__ */ jsx10("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
452
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
453
|
+
] }) : null,
|
|
454
|
+
empty ? /* @__PURE__ */ jsx10(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
455
|
+
/* @__PURE__ */ jsx10("div", { ref: endRef })
|
|
456
|
+
]
|
|
457
|
+
}
|
|
458
|
+
);
|
|
446
459
|
}
|
|
447
460
|
|
|
448
461
|
// src/components/ChatInput.tsx
|
|
@@ -580,7 +593,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
580
593
|
|
|
581
594
|
/* entity cards */
|
|
582
595
|
.ss-w-cards { display: flex; flex-direction: column; gap: 7px; }
|
|
583
|
-
.ss-w-ecard { display: flex; align-items: center; gap: 11px; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 11px; text-align: left;
|
|
596
|
+
.ss-w-ecard { display: flex; align-items: center; gap: 11px; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 11px; text-align: left; }
|
|
584
597
|
.ss-w-thumb { width: 40px; height: 40px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 13px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; }
|
|
585
598
|
.ss-w-thumb.ss-w-team { border-radius: 10px; }
|
|
586
599
|
.ss-w-ecard[data-kind="player"] .ss-w-thumb { background-color: var(--ss-w-accent); }
|
|
@@ -591,10 +604,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
591
604
|
.ss-w-stat { margin-left: auto; text-align: center; }
|
|
592
605
|
.ss-w-stat b { display: block; font-variant-numeric: tabular-nums; }
|
|
593
606
|
.ss-w-stat span { font-size: 9px; text-transform: uppercase; color: var(--ss-w-faint); }
|
|
594
|
-
.ss-w-chev { color: var(--ss-w-faint); font-size: 16px; display: grid; place-items: center; }
|
|
595
607
|
.ss-w-cards-more { align-self: flex-start; font-size: 11.5px; font-weight: 560; color: var(--ss-w-accent); background: none; border: none; cursor: pointer; padding: 3px 2px; }
|
|
596
608
|
.ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }
|
|
597
|
-
.ss-w-
|
|
609
|
+
.ss-w-cards-more:disabled { opacity: .5; cursor: default; }
|
|
598
610
|
|
|
599
611
|
/* action buttons */
|
|
600
612
|
.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
|
|
@@ -611,6 +623,11 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
611
623
|
.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }
|
|
612
624
|
.ss-w-textarea { flex: 1; resize: none; border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; font: inherit; color: inherit; background: var(--ss-w-panel); max-height: 96px; }
|
|
613
625
|
.ss-w-textarea:disabled { opacity: .55; cursor: not-allowed; }
|
|
626
|
+
/* iOS Safari zooms the page when a focused field's font-size is < 16px. Bump it
|
|
627
|
+
on touch devices only, so the desktop 13px design is unchanged. */
|
|
628
|
+
@media (pointer: coarse) {
|
|
629
|
+
.ss-w-textarea { font-size: 16px; }
|
|
630
|
+
}
|
|
614
631
|
.ss-w-send { width: 36px; height: 36px; flex: none; border: none; border-radius: 50%; background: var(--ss-w-accent); color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 16px; }
|
|
615
632
|
.ss-w-stop-glyph { width: 11px; height: 11px; background: currentColor; border-radius: 2px; }
|
|
616
633
|
|