@sensiblestats/widget-react 0.31.1 → 0.32.1

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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @sensiblestats/widget-react
2
2
 
3
+ ## 0.32.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix market-odds and odds-movement rows doubling the line for localized selections that already embed it (e.g. TR "2.5 Üst" rendering as "2.5 Üst 2.5"). Extracts the dedupe guard already used by betting-insight cards into a shared helper so all three selection/line join sites stay in sync.
8
+
9
+ ## 0.32.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Crest images on market-odds cards and restructured Odds-tab context line with pre-match kickoff pill layout.
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @sensiblestats/widget-sdk@0.28.0
19
+
3
20
  ## 0.31.1
4
21
 
5
22
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -118,7 +118,8 @@ var STRINGS = {
118
118
  graceNote: "Unpins on next open \xB7 or in 4 h",
119
119
  suspendedLabel: "Suspended",
120
120
  fullTimeLabel: "Full time",
121
- inSlipLabel: "In slip"
121
+ inSlipLabel: "In slip",
122
+ oddsUnavailable: "Odds unavailable right now"
122
123
  },
123
124
  tr: {
124
125
  launcherLabel: "SensibleStats ile sohbet et",
@@ -185,7 +186,8 @@ var STRINGS = {
185
186
  graceNote: "Bir sonraki a\xE7\u0131l\u0131\u015Fta kald\u0131r\u0131l\u0131r \xB7 en ge\xE7 4 saat",
186
187
  suspendedLabel: "Ask\u0131da",
187
188
  fullTimeLabel: "Ma\xE7 sonu",
188
- inSlipLabel: "Kuponda"
189
+ inSlipLabel: "Kuponda",
190
+ oddsUnavailable: "Oranlar \u015Fu anda kullan\u0131lam\u0131yor"
189
191
  }
190
192
  };
191
193
  function resolveLocaleStrings(locale) {
@@ -265,7 +267,8 @@ function normalizeUi(cfg) {
265
267
  graceNote: strings.graceNote,
266
268
  suspendedLabel: strings.suspendedLabel,
267
269
  fullTimeLabel: strings.fullTimeLabel,
268
- inSlipLabel: strings.inSlipLabel
270
+ inSlipLabel: strings.inSlipLabel,
271
+ oddsUnavailable: strings.oddsUnavailable
269
272
  };
270
273
  }
271
274
  function toClientOptions(cfg) {
@@ -446,9 +449,15 @@ function toChipVM(intent) {
446
449
  function chipFromText(text) {
447
450
  return { text };
448
451
  }
452
+ function joinSelection(label, line) {
453
+ if (label && line && label.includes(line)) return label;
454
+ return [label, line].filter(Boolean).join(" ") || void 0;
455
+ }
449
456
  function toInsightVM(insight) {
450
457
  const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? "";
451
- const selection = [str(insight.selectionLabel), str(insight.line)].filter(Boolean).join(" ") || void 0;
458
+ const selectionLabel = str(insight.selectionLabel);
459
+ const selectionLine = str(insight.line);
460
+ const selection = joinSelection(selectionLabel, selectionLine);
452
461
  const value = insight.odds?.value;
453
462
  const odds = typeof value === "number" && Number.isFinite(value) ? value.toFixed(2) : void 0;
454
463
  const oddsValue = insight.odds?.value;
@@ -511,7 +520,7 @@ function toSlipSelection(vm, conversationId) {
511
520
  function toMarketOddsVM(card) {
512
521
  const rows = Array.isArray(card.rows) ? card.rows : [];
513
522
  const toRow = (r, i) => {
514
- const selection = [str(r.selectionLabel), str(r.line)].filter(Boolean).join(" ");
523
+ const selection = joinSelection(str(r.selectionLabel), str(r.line)) ?? "";
515
524
  const price = typeof r.price === "number" && Number.isFinite(r.price) ? r.price : void 0;
516
525
  const previous = typeof r.previousPrice === "number" && Number.isFinite(r.previousPrice) ? r.previousPrice : void 0;
517
526
  const direction = r.movementDirection === "shortened" || r.movementDirection === "drifted" ? r.movementDirection : void 0;
@@ -570,7 +579,7 @@ function toOddsMovementVM(card) {
570
579
  const current = asNumber(card.currentPrice);
571
580
  const home = str(card.homeTeamName);
572
581
  const away = str(card.awayTeamName);
573
- const selection = [str(card.selectionLabel), str(card.line)].filter(Boolean).join(" ");
582
+ const selection = joinSelection(str(card.selectionLabel), str(card.line)) ?? "";
574
583
  const bookmakerId = typeof card.bookmakerId === "number" ? card.bookmakerId : "";
575
584
  return {
576
585
  id: `${typeof card.matchId === "number" ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ""}:${selection}:${bookmakerId}`,
@@ -2917,18 +2926,24 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
2917
2926
  // src/components/MonitorTabs.tsx
2918
2927
  var import_jsx_runtime46 = require("react/jsx-runtime");
2919
2928
  function ContextLine({ m, monitor, ui }) {
2929
+ const kick = m.kickoffUtc ? ui.bettingKickoff(m.kickoffUtc) : void 0;
2920
2930
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mk-ctx", children: [
2921
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Crest2, { kind: "team", name: m.homeTeamName ?? void 0 }),
2922
- m.phase !== "preMatch" && typeof m.homeScore === "number" && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("b", { children: [
2931
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
2932
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Crest2, { kind: "team", url: m.homeCrestUrl ?? void 0, name: m.homeTeamName ?? void 0 }),
2933
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-name", children: m.homeTeamName })
2934
+ ] }),
2935
+ m.phase === "preMatch" ? kick && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-pill", children: [
2936
+ kick.dayLabel,
2937
+ " ",
2938
+ kick.time
2939
+ ] }) : typeof m.homeScore === "number" && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("b", { children: [
2923
2940
  m.homeScore,
2924
2941
  "\u2013",
2925
2942
  m.awayScore
2926
2943
  ] }),
2927
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Crest2, { kind: "team", name: m.awayTeamName ?? void 0 }),
2928
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-name", children: [
2929
- m.homeTeamName,
2930
- " v ",
2931
- m.awayTeamName
2944
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
2945
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-name", children: m.awayTeamName }),
2946
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Crest2, { kind: "team", url: m.awayCrestUrl ?? void 0, name: m.awayTeamName ?? void 0 })
2932
2947
  ] }),
2933
2948
  m.minuteLabel && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
2934
2949
  /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mk-ctx-right", children: [
@@ -2981,7 +2996,8 @@ function OddsPanel({ monitor, ui, slip }) {
2981
2996
  inSlipIds: monitor.inSlip
2982
2997
  }
2983
2998
  ),
2984
- m.history && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui })
2999
+ m.history && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3000
+ !m.card && !m.history && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
2985
3001
  ] }, m.key)) });
2986
3002
  }
2987
3003
 
@@ -3769,9 +3785,14 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3769
3785
  .ss-w-mk-ctx b { flex: none; white-space: nowrap; }
3770
3786
  /* the context line's fixture name stays single-line (the two-line clamp is for the match card) */
3771
3787
  .ss-w-mk-ctx .ss-w-mon-name { display: block; white-space: nowrap; text-overflow: ellipsis; }
3788
+ .ss-w-mk-ctx-side { display: flex; align-items: center; gap: 6px; min-width: 0; }
3772
3789
  .ss-w-mk-ctx-right { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }
3773
3790
  /* flex:1 keeps the composer pinned to the panel bottom when a tab is empty */
3774
3791
  .ss-w-mon-empty { flex: 1; padding: 24px 16px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }
3792
+ /* Per-pin unavailable state: the pin's context line still rendered above (score, name, unpin), but
3793
+ the pin has neither a card nor history (compose-time rescue failed) -- a small inline note beats
3794
+ a bare context line with nothing under it. */
3795
+ .ss-w-mon-empty-card { padding: 8px 0 2px; font-size: 12px; color: var(--ss-w-faint); }
3775
3796
  .ss-w-mon-inslip { display: inline-flex; flex: none; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-pos); }
3776
3797
  .ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }
3777
3798
  .ss-w-mon-oddspin[data-settled] .ss-w-mo-price,