@sensiblestats/widget-react 0.11.0 → 0.12.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 +13 -0
- package/dist/index.cjs +126 -105
- 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 +126 -105
- package/dist/index.js.map +1 -1
- package/dist/styles.css +7 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -213,6 +213,9 @@ function toInsightVM(insight) {
|
|
|
213
213
|
const fixture = home && away ? `${home} vs ${away}` : void 0;
|
|
214
214
|
const competition = str(insight.competitionName);
|
|
215
215
|
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;
|
|
216
|
+
const previousValue = insight.odds?.previousValue;
|
|
217
|
+
const previous = typeof previousValue === "number" && Number.isFinite(previousValue) ? previousValue : void 0;
|
|
218
|
+
const direction = insight.odds?.movementDirection === "shortened" || insight.odds?.movementDirection === "drifted" ? insight.odds.movementDirection : void 0;
|
|
216
219
|
return {
|
|
217
220
|
id: str(insight.insightId) ?? `${str(insight.ruleId) ?? "insight"}:${num(insight.matchId) ?? ""}`,
|
|
218
221
|
market,
|
|
@@ -232,7 +235,9 @@ function toInsightVM(insight) {
|
|
|
232
235
|
matchOddsId,
|
|
233
236
|
addToSlipEnabled: insight.addToSlipEnabled === true,
|
|
234
237
|
oddsDecimal: typeof oddsValue === "number" && Number.isFinite(oddsValue) ? oddsValue : void 0,
|
|
235
|
-
quotedAtUtc: str(insight.odds?.quotedAtUtc)
|
|
238
|
+
quotedAtUtc: str(insight.odds?.quotedAtUtc),
|
|
239
|
+
previousOdds: previous !== void 0 && direction !== void 0 ? previous.toFixed(2) : void 0,
|
|
240
|
+
movementDirection: previous !== void 0 && direction !== void 0 ? direction : void 0
|
|
236
241
|
};
|
|
237
242
|
}
|
|
238
243
|
function toSlipSelection(vm, conversationId) {
|
|
@@ -721,20 +726,41 @@ function AddToSlipButton({ it, slip, ui }) {
|
|
|
721
726
|
return /* @__PURE__ */ jsx8(SlipButton, { selection, shownOdds: it.odds ?? "", marketName: it.market, slip, ui });
|
|
722
727
|
}
|
|
723
728
|
|
|
724
|
-
// src/components/
|
|
729
|
+
// src/components/OddsMovementBadge.tsx
|
|
725
730
|
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
731
|
+
function OddsMovementBadge({
|
|
732
|
+
previous,
|
|
733
|
+
current,
|
|
734
|
+
direction,
|
|
735
|
+
ui
|
|
736
|
+
}) {
|
|
737
|
+
if (previous === void 0 || direction === void 0) return null;
|
|
738
|
+
const directionWord = direction === "shortened" ? ui?.oddsShortened ?? "shortened" : ui?.oddsDrifted ?? "drifted";
|
|
739
|
+
const label = ui?.oddsMoved?.(previous, current, directionWord) ?? `was ${previous}, now ${current}, ${directionWord}`;
|
|
740
|
+
return (
|
|
741
|
+
// Strikethrough is invisible to screen readers, so the whole was/now/direction sentence rides
|
|
742
|
+
// on one aria-label and the visual glyphs are hidden from the accessibility tree.
|
|
743
|
+
/* @__PURE__ */ jsxs6("span", { className: "ss-w-move", role: "img", "aria-label": label, children: [
|
|
744
|
+
/* @__PURE__ */ jsx9("span", { className: "ss-w-move-prev", "aria-hidden": "true", children: previous }),
|
|
745
|
+
/* @__PURE__ */ jsx9("span", { className: "ss-w-move-arrow", "aria-hidden": "true", children: direction === "shortened" ? "\u25BC" : "\u25B2" })
|
|
746
|
+
] })
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// src/components/BettingInsightList.tsx
|
|
751
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
726
752
|
function StatRows2({ stats }) {
|
|
727
|
-
return /* @__PURE__ */
|
|
728
|
-
/* @__PURE__ */
|
|
729
|
-
/* @__PURE__ */
|
|
753
|
+
return /* @__PURE__ */ jsx10("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-row", children: [
|
|
754
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
755
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-row-num", children: s.value })
|
|
730
756
|
] }, `${s.label}:${s.value}`)) });
|
|
731
757
|
}
|
|
732
758
|
function ScopedStats({ scopes }) {
|
|
733
759
|
const [active, setActive] = useState3(0);
|
|
734
760
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
735
|
-
return /* @__PURE__ */
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
761
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-scoped", children: [
|
|
762
|
+
/* @__PURE__ */ jsx10("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx10("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
763
|
+
/* @__PURE__ */ jsx10(StatRows2, { stats: current.stats }, current.key)
|
|
738
764
|
] });
|
|
739
765
|
}
|
|
740
766
|
function StatsDisclosure({ it, ui }) {
|
|
@@ -742,8 +768,8 @@ function StatsDisclosure({ it, ui }) {
|
|
|
742
768
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
743
769
|
const hasStats = hasScopes || it.stats.length > 0;
|
|
744
770
|
if (!hasStats) return null;
|
|
745
|
-
return /* @__PURE__ */
|
|
746
|
-
/* @__PURE__ */
|
|
771
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-stats", children: [
|
|
772
|
+
/* @__PURE__ */ jsxs7(
|
|
747
773
|
"button",
|
|
748
774
|
{
|
|
749
775
|
type: "button",
|
|
@@ -751,131 +777,123 @@ function StatsDisclosure({ it, ui }) {
|
|
|
751
777
|
"aria-expanded": open,
|
|
752
778
|
onClick: () => setOpen((v) => !v),
|
|
753
779
|
children: [
|
|
754
|
-
/* @__PURE__ */
|
|
755
|
-
/* @__PURE__ */
|
|
780
|
+
/* @__PURE__ */ jsx10("span", { children: open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats" }),
|
|
781
|
+
/* @__PURE__ */ jsx10("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
|
|
756
782
|
]
|
|
757
783
|
}
|
|
758
784
|
),
|
|
759
|
-
open ? hasScopes ? /* @__PURE__ */
|
|
785
|
+
open ? hasScopes ? /* @__PURE__ */ jsx10(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ jsx10(StatRows2, { stats: it.stats }) : null
|
|
760
786
|
] });
|
|
761
787
|
}
|
|
762
788
|
function InsightCard({ it, ui, slip }) {
|
|
763
789
|
const live = it.isLive || it.phase === "live";
|
|
764
|
-
return /* @__PURE__ */
|
|
765
|
-
live ? /* @__PURE__ */
|
|
766
|
-
/* @__PURE__ */
|
|
790
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-binsight", children: [
|
|
791
|
+
live ? /* @__PURE__ */ jsx10("div", { className: "ss-w-bi-status", children: /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-live", children: [
|
|
792
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
767
793
|
ui?.liveLabel ?? "Live"
|
|
768
794
|
] }) }) : null,
|
|
769
|
-
/* @__PURE__ */
|
|
770
|
-
/* @__PURE__ */
|
|
771
|
-
/* @__PURE__ */
|
|
772
|
-
it.selection ? /* @__PURE__ */
|
|
773
|
-
it.fixture || it.competition ? /* @__PURE__ */
|
|
774
|
-
it.fixture ? /* @__PURE__ */
|
|
775
|
-
it.competition ? /* @__PURE__ */
|
|
795
|
+
/* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-head", children: [
|
|
796
|
+
/* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-mkt", children: [
|
|
797
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-market", children: it.market }),
|
|
798
|
+
it.selection ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-sel", children: it.selection }) : null,
|
|
799
|
+
it.fixture || it.competition ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-match", children: [
|
|
800
|
+
it.fixture ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-fixture", children: it.fixture }) : null,
|
|
801
|
+
it.competition ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-comp", children: it.competition }) : null
|
|
776
802
|
] }) : null
|
|
777
803
|
] }),
|
|
778
|
-
/* @__PURE__ */
|
|
779
|
-
it.odds ? /* @__PURE__ */
|
|
780
|
-
/* @__PURE__ */
|
|
781
|
-
/* @__PURE__ */
|
|
782
|
-
|
|
804
|
+
/* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-action", children: [
|
|
805
|
+
it.odds ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-odds", children: [
|
|
806
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-odds-cap", children: ui?.oddsLabel ?? "Odds" }),
|
|
807
|
+
/* @__PURE__ */ jsx10("b", { children: it.odds }),
|
|
808
|
+
/* @__PURE__ */ jsx10(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
|
|
809
|
+
it.bookmaker ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
|
|
783
810
|
] }) : null,
|
|
784
|
-
/* @__PURE__ */
|
|
811
|
+
/* @__PURE__ */ jsx10(AddToSlipButton, { it, slip, ui })
|
|
785
812
|
] })
|
|
786
813
|
] }),
|
|
787
|
-
it.text ? /* @__PURE__ */
|
|
788
|
-
/* @__PURE__ */
|
|
789
|
-
it.disclaimer ? /* @__PURE__ */
|
|
814
|
+
it.text ? /* @__PURE__ */ jsx10("p", { className: "ss-w-bi-text", children: it.text }) : null,
|
|
815
|
+
/* @__PURE__ */ jsx10(StatsDisclosure, { it, ui }),
|
|
816
|
+
it.disclaimer ? /* @__PURE__ */ jsx10("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
790
817
|
] });
|
|
791
818
|
}
|
|
792
819
|
function BettingInsightList({ insights, ui, slip }) {
|
|
793
820
|
if (!insights || insights.length === 0) return null;
|
|
794
|
-
return /* @__PURE__ */
|
|
821
|
+
return /* @__PURE__ */ jsx10("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ jsx10(InsightCard, { it, ui, slip }, it.id)) });
|
|
795
822
|
}
|
|
796
823
|
|
|
797
824
|
// src/components/MarketOddsCardList.tsx
|
|
798
825
|
import { useState as useState4 } from "react";
|
|
799
|
-
import { jsx as
|
|
826
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
800
827
|
function OddsRow({ vm, row, ui, slip }) {
|
|
801
828
|
const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
/* @__PURE__ */
|
|
806
|
-
row.
|
|
807
|
-
// Strikethrough is invisible to screen readers, so the whole was/now/direction sentence
|
|
808
|
-
// rides on one aria-label and the visual glyphs are hidden from the accessibility tree.
|
|
809
|
-
/* @__PURE__ */ jsxs7("span", { className: "ss-w-mo-move", role: "img", "aria-label": movementLabel, children: [
|
|
810
|
-
/* @__PURE__ */ jsx10("span", { className: "ss-w-mo-prev", "aria-hidden": "true", children: row.previousOdds }),
|
|
811
|
-
/* @__PURE__ */ jsx10("span", { className: "ss-w-mo-arrow", "aria-hidden": "true", children: row.movementDirection === "shortened" ? "\u25BC" : "\u25B2" })
|
|
812
|
-
] })
|
|
813
|
-
) : null,
|
|
814
|
-
/* @__PURE__ */ jsx10("span", { className: "ss-w-mo-price", children: row.odds }),
|
|
815
|
-
/* @__PURE__ */ jsx10(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
|
|
829
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-row", children: [
|
|
830
|
+
/* @__PURE__ */ jsx11("span", { className: "ss-w-mo-sel", children: row.selection }),
|
|
831
|
+
/* @__PURE__ */ jsx11(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
|
|
832
|
+
/* @__PURE__ */ jsx11("span", { className: "ss-w-mo-price", children: row.odds }),
|
|
833
|
+
/* @__PURE__ */ jsx11(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
|
|
816
834
|
] });
|
|
817
835
|
}
|
|
818
836
|
function MarketOddsCard({ vm, ui, slip }) {
|
|
819
837
|
const [open, setOpen] = useState4(false);
|
|
820
|
-
return /* @__PURE__ */
|
|
821
|
-
/* @__PURE__ */
|
|
822
|
-
/* @__PURE__ */
|
|
823
|
-
/* @__PURE__ */
|
|
838
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ss-w-mocard", children: [
|
|
839
|
+
/* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-head", children: [
|
|
840
|
+
/* @__PURE__ */ jsx11("span", { className: "ss-w-mo-market", children: vm.market }),
|
|
841
|
+
/* @__PURE__ */ jsx11("span", { className: "ss-w-mo-tag", children: ui?.marketPrices ?? "Market prices" })
|
|
824
842
|
] }),
|
|
825
|
-
vm.fixture || vm.competition ? /* @__PURE__ */
|
|
826
|
-
vm.fixture ? /* @__PURE__ */
|
|
827
|
-
vm.competition ? /* @__PURE__ */
|
|
843
|
+
vm.fixture || vm.competition ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-fixture", children: [
|
|
844
|
+
vm.fixture ? /* @__PURE__ */ jsx11("span", { children: vm.fixture }) : null,
|
|
845
|
+
vm.competition ? /* @__PURE__ */ jsx11("span", { className: "ss-w-mo-comp", children: vm.competition }) : null
|
|
828
846
|
] }) : null,
|
|
829
|
-
/* @__PURE__ */
|
|
830
|
-
vm.mainRows.map((row) => /* @__PURE__ */
|
|
831
|
-
open ? vm.moreRows.map((row) => /* @__PURE__ */
|
|
847
|
+
/* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-rows", children: [
|
|
848
|
+
vm.mainRows.map((row) => /* @__PURE__ */ jsx11(OddsRow, { vm, row, ui, slip }, row.key)),
|
|
849
|
+
open ? vm.moreRows.map((row) => /* @__PURE__ */ jsx11(OddsRow, { vm, row, ui, slip }, row.key)) : null
|
|
832
850
|
] }),
|
|
833
|
-
vm.moreRows.length > 0 ? /* @__PURE__ */
|
|
834
|
-
/* @__PURE__ */
|
|
835
|
-
/* @__PURE__ */
|
|
851
|
+
vm.moreRows.length > 0 ? /* @__PURE__ */ jsxs8("button", { type: "button", className: "ss-w-bi-toggle", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
|
|
852
|
+
/* @__PURE__ */ jsx11("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
|
|
853
|
+
/* @__PURE__ */ jsx11("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
|
|
836
854
|
] }) : null,
|
|
837
|
-
vm.bookmaker ? /* @__PURE__ */
|
|
838
|
-
vm.disclaimer ? /* @__PURE__ */
|
|
855
|
+
vm.bookmaker ? /* @__PURE__ */ jsx11("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ jsx11("span", { children: vm.bookmaker }) }) : null,
|
|
856
|
+
vm.disclaimer ? /* @__PURE__ */ jsx11("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
|
|
839
857
|
] });
|
|
840
858
|
}
|
|
841
859
|
function MarketOddsCardList({ cards, ui, slip }) {
|
|
842
860
|
if (!cards || cards.length === 0) return null;
|
|
843
|
-
return /* @__PURE__ */
|
|
861
|
+
return /* @__PURE__ */ jsx11("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ jsx11(MarketOddsCard, { vm, ui, slip }, vm.id)) });
|
|
844
862
|
}
|
|
845
863
|
|
|
846
864
|
// src/components/ActionButtons.tsx
|
|
847
|
-
import { Fragment, jsx as
|
|
865
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
848
866
|
function ActionButtons({ actions, loading, disabled, onAct }) {
|
|
849
867
|
if (actions.length === 0 && !loading) return null;
|
|
850
|
-
return /* @__PURE__ */
|
|
851
|
-
actions.map((a, i) => /* @__PURE__ */
|
|
852
|
-
actions.length === 0 && loading ? /* @__PURE__ */
|
|
853
|
-
/* @__PURE__ */
|
|
854
|
-
/* @__PURE__ */
|
|
868
|
+
return /* @__PURE__ */ jsxs9("div", { className: "ss-w-actions", children: [
|
|
869
|
+
actions.map((a, i) => /* @__PURE__ */ jsx12("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
|
|
870
|
+
actions.length === 0 && loading ? /* @__PURE__ */ jsxs9(Fragment, { children: [
|
|
871
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-abtn-shimmer" }),
|
|
872
|
+
/* @__PURE__ */ jsx12("span", { className: "ss-w-abtn-shimmer" })
|
|
855
873
|
] }) : null
|
|
856
874
|
] });
|
|
857
875
|
}
|
|
858
876
|
|
|
859
877
|
// src/components/ChatMessage.tsx
|
|
860
|
-
import { jsx as
|
|
878
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
861
879
|
function ChatMessage({ message, disabled, onAct, ui, slip }) {
|
|
862
880
|
if (message.role === "user") {
|
|
863
|
-
return /* @__PURE__ */
|
|
881
|
+
return /* @__PURE__ */ jsx13("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ jsx13("div", { className: "ss-w-bubble", children: message.text }) });
|
|
864
882
|
}
|
|
865
|
-
return /* @__PURE__ */
|
|
866
|
-
message.text ? /* @__PURE__ */
|
|
867
|
-
/* @__PURE__ */
|
|
868
|
-
/* @__PURE__ */
|
|
869
|
-
/* @__PURE__ */
|
|
870
|
-
/* @__PURE__ */
|
|
883
|
+
return /* @__PURE__ */ jsxs10("div", { className: "ss-w-msg ss-w-bot", children: [
|
|
884
|
+
message.text ? /* @__PURE__ */ jsx13(Markdown, { text: message.text }) : null,
|
|
885
|
+
/* @__PURE__ */ jsx13(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
|
|
886
|
+
/* @__PURE__ */ jsx13(BettingInsightList, { insights: message.insights, ui, slip }),
|
|
887
|
+
/* @__PURE__ */ jsx13(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
|
|
888
|
+
/* @__PURE__ */ jsx13(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
|
|
871
889
|
] });
|
|
872
890
|
}
|
|
873
891
|
|
|
874
892
|
// src/components/IntentChips.tsx
|
|
875
|
-
import { jsx as
|
|
893
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
876
894
|
function IntentChips({ chips, onPick }) {
|
|
877
895
|
if (chips.length === 0) return null;
|
|
878
|
-
return /* @__PURE__ */
|
|
896
|
+
return /* @__PURE__ */ jsx14("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx14("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
|
|
879
897
|
}
|
|
880
898
|
|
|
881
899
|
// src/scroll.ts
|
|
@@ -885,7 +903,7 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
|
|
|
885
903
|
}
|
|
886
904
|
|
|
887
905
|
// src/components/MessageList.tsx
|
|
888
|
-
import { jsx as
|
|
906
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
889
907
|
function MessageList({ controller, ui, slip }) {
|
|
890
908
|
const { state, send } = controller;
|
|
891
909
|
const listRef = useRef2(null);
|
|
@@ -895,7 +913,7 @@ function MessageList({ controller, ui, slip }) {
|
|
|
895
913
|
if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
|
|
896
914
|
}, [state.messages, state.status]);
|
|
897
915
|
const empty = state.messages.length === 0;
|
|
898
|
-
return /* @__PURE__ */
|
|
916
|
+
return /* @__PURE__ */ jsxs11(
|
|
899
917
|
"div",
|
|
900
918
|
{
|
|
901
919
|
className: "ss-w-list",
|
|
@@ -905,7 +923,7 @@ function MessageList({ controller, ui, slip }) {
|
|
|
905
923
|
if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
|
|
906
924
|
},
|
|
907
925
|
children: [
|
|
908
|
-
state.messages.map((m) => /* @__PURE__ */
|
|
926
|
+
state.messages.map((m) => /* @__PURE__ */ jsx15(
|
|
909
927
|
ChatMessage,
|
|
910
928
|
{
|
|
911
929
|
message: m,
|
|
@@ -916,15 +934,15 @@ function MessageList({ controller, ui, slip }) {
|
|
|
916
934
|
},
|
|
917
935
|
m.id
|
|
918
936
|
)),
|
|
919
|
-
state.isStreaming && state.actionsLoading ? /* @__PURE__ */
|
|
937
|
+
state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx15(ActionButtons, { actions: [], loading: true, onAct: () => {
|
|
920
938
|
} }) : null,
|
|
921
|
-
state.status ? /* @__PURE__ */
|
|
922
|
-
state.error ? /* @__PURE__ */
|
|
923
|
-
/* @__PURE__ */
|
|
924
|
-
/* @__PURE__ */
|
|
939
|
+
state.status ? /* @__PURE__ */ jsx15("div", { className: "ss-w-status", children: state.status }) : null,
|
|
940
|
+
state.error ? /* @__PURE__ */ jsxs11("div", { className: "ss-w-error", role: "alert", children: [
|
|
941
|
+
/* @__PURE__ */ jsx15("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
942
|
+
/* @__PURE__ */ jsx15("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
925
943
|
] }) : null,
|
|
926
|
-
empty ? /* @__PURE__ */
|
|
927
|
-
/* @__PURE__ */
|
|
944
|
+
empty ? /* @__PURE__ */ jsx15(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
945
|
+
/* @__PURE__ */ jsx15("div", { ref: endRef })
|
|
928
946
|
]
|
|
929
947
|
}
|
|
930
948
|
);
|
|
@@ -932,7 +950,7 @@ function MessageList({ controller, ui, slip }) {
|
|
|
932
950
|
|
|
933
951
|
// src/components/ChatInput.tsx
|
|
934
952
|
import { useState as useState5 } from "react";
|
|
935
|
-
import { jsx as
|
|
953
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
936
954
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
937
955
|
const [value, setValue] = useState5("");
|
|
938
956
|
const submit = () => {
|
|
@@ -947,14 +965,14 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
947
965
|
submit();
|
|
948
966
|
}
|
|
949
967
|
};
|
|
950
|
-
return /* @__PURE__ */
|
|
951
|
-
/* @__PURE__ */
|
|
952
|
-
streaming ? /* @__PURE__ */
|
|
968
|
+
return /* @__PURE__ */ jsxs12("div", { className: "ss-w-input", children: [
|
|
969
|
+
/* @__PURE__ */ jsx16("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
|
|
970
|
+
streaming ? /* @__PURE__ */ jsx16("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ jsx16("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ jsx16("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ jsx16(SendIcon, {}) })
|
|
953
971
|
] });
|
|
954
972
|
}
|
|
955
973
|
|
|
956
974
|
// src/components/ChatPanel.tsx
|
|
957
|
-
import { jsx as
|
|
975
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
958
976
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
959
977
|
function useIsModal() {
|
|
960
978
|
const [modal, setModal] = useState6(false);
|
|
@@ -978,10 +996,10 @@ function ChatPanel({ controller, ui, slip }) {
|
|
|
978
996
|
window.addEventListener("keydown", onKey);
|
|
979
997
|
return () => window.removeEventListener("keydown", onKey);
|
|
980
998
|
}, [close]);
|
|
981
|
-
return /* @__PURE__ */
|
|
982
|
-
/* @__PURE__ */
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
/* @__PURE__ */
|
|
999
|
+
return /* @__PURE__ */ jsxs13("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
1000
|
+
/* @__PURE__ */ jsx17(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
|
|
1001
|
+
/* @__PURE__ */ jsx17(MessageList, { controller, ui, slip }),
|
|
1002
|
+
/* @__PURE__ */ jsx17(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
985
1003
|
] });
|
|
986
1004
|
}
|
|
987
1005
|
|
|
@@ -1170,10 +1188,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1170
1188
|
.ss-w-mo-price { margin-left: auto; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; color: var(--ss-w-accent); }
|
|
1171
1189
|
/* Movement: BOTH directions share --ss-w-faint on purpose. Green-good/red-bad would frame a
|
|
1172
1190
|
shortening price as a discount, which inverts what it actually means for the bettor. */
|
|
1173
|
-
.ss-w-
|
|
1174
|
-
.ss-w-
|
|
1175
|
-
.ss-w-
|
|
1176
|
-
|
|
1191
|
+
.ss-w-move { display: inline-flex; align-items: baseline; gap: 4px; color: var(--ss-w-faint); }
|
|
1192
|
+
.ss-w-move-prev { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 12px; text-decoration: line-through; }
|
|
1193
|
+
.ss-w-move-arrow { font-size: 9px; line-height: 1; }
|
|
1194
|
+
/* margin-left:auto is row layout, not badge styling -- it belongs to the market-odds row, which is
|
|
1195
|
+
a flex row, and must NOT follow the badge into the insight card's odds column. */
|
|
1196
|
+
.ss-w-mo-row .ss-w-move { margin-left: auto; }
|
|
1197
|
+
.ss-w-mo-row .ss-w-move + .ss-w-mo-price { margin-left: 0; }
|
|
1177
1198
|
.ss-w-mo-row .ss-w-slip { margin: 0; }
|
|
1178
1199
|
.ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }
|
|
1179
1200
|
|
|
@@ -1214,7 +1235,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1214
1235
|
`;
|
|
1215
1236
|
|
|
1216
1237
|
// src/StatsWidget.tsx
|
|
1217
|
-
import { jsx as
|
|
1238
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
1218
1239
|
function buildClient(props) {
|
|
1219
1240
|
try {
|
|
1220
1241
|
if ("client" in props && props.client) {
|
|
@@ -1263,7 +1284,7 @@ function StatsWidget(props) {
|
|
|
1263
1284
|
}, [built, ui.injectStyles]);
|
|
1264
1285
|
if (!built) return null;
|
|
1265
1286
|
const attrs = themeAttrs(ui);
|
|
1266
|
-
return /* @__PURE__ */
|
|
1287
|
+
return /* @__PURE__ */ jsx18("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__ */ jsx18(ChatPanel, { controller, ui, slip }) : /* @__PURE__ */ jsx18(
|
|
1267
1288
|
ChatFab,
|
|
1268
1289
|
{
|
|
1269
1290
|
label: ui.launcherLabel,
|