@sensiblestats/widget-react 0.37.1 → 0.37.3

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,17 @@
1
1
  # @sensiblestats/widget-react
2
2
 
3
+ ## 0.37.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Odds tab: show a single market-odds card per pin instead of a card-inside-a-card. The fixture/date is no longer duplicated — each pinned market renders one betting card (competition, fixture, market, odds) with the unpin in its own header, plus a slim live strip (score, minute, suspended/settled) shown only for in-play markets and hidden for pre-match. The unpin threads the exact stored pin key so it always removes the right pin.
8
+
9
+ ## 0.37.2
10
+
11
+ ### Patch Changes
12
+
13
+ - Match odds accordion: add a per-row market pin. Each accordion market row now shows the PinToggle on the right of its header (visible collapsed or expanded); tapping pins that market ({kind:'market', matchId, marketDeveloperName}) to the Odds tab, mirroring the pin on chat betting cards. The row header splits into an expand button + the pin button so the two actions stay independent.
14
+
3
15
  ## 0.37.1
4
16
 
5
17
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -1801,7 +1801,7 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
1801
1801
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1802
1802
  ] });
1803
1803
  }
1804
- function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader }) {
1804
+ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }) {
1805
1805
  const [open, setOpen] = (0, import_react12.useState)(false);
1806
1806
  const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
1807
1807
  const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
@@ -1829,7 +1829,7 @@ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader }) {
1829
1829
  {
1830
1830
  ui,
1831
1831
  monitor,
1832
- pin: { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
1832
+ pin: pinRef ?? { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
1833
1833
  }
1834
1834
  ) : null
1835
1835
  ] })
@@ -1857,9 +1857,9 @@ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader }) {
1857
1857
  vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1858
1858
  ] });
1859
1859
  }
1860
- function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds, hideHeader }) {
1860
+ function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds, hideHeader, pinRef }) {
1861
1861
  if (!cards || cards.length === 0) return null;
1862
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds, hideHeader }, vm.id)) });
1862
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }, vm.id)) });
1863
1863
  }
1864
1864
 
1865
1865
  // src/components/OddsMovementCard.tsx
@@ -2980,20 +2980,31 @@ function MarketAccordion({ match, monitor, ui, slip }) {
2980
2980
  const key = `${match.matchId}:${m.marketDeveloperName}`;
2981
2981
  const entry = monitor.marketOdds[key];
2982
2982
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: isOpen ? "ss-w-acc-row ss-w-acc-row-open" : "ss-w-acc-row", children: [
2983
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
2984
- "button",
2985
- {
2986
- type: "button",
2987
- className: "ss-w-acc-head",
2988
- onClick: () => monitor.toggleMarket(match.matchId, m.marketDeveloperName),
2989
- children: [
2990
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-chevron", children: isOpen ? "\u25BE" : "\u25B8" }),
2991
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-label", children: m.marketLabel }),
2992
- m.hasInsight && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-badge", children: "\u2605" }),
2993
- m.suspended && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-susp", children: ui.accordionSuspended })
2994
- ]
2995
- }
2996
- ),
2983
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-acc-head", children: [
2984
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
2985
+ "button",
2986
+ {
2987
+ type: "button",
2988
+ className: "ss-w-acc-toggle",
2989
+ "aria-expanded": isOpen,
2990
+ onClick: () => monitor.toggleMarket(match.matchId, m.marketDeveloperName),
2991
+ children: [
2992
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-chevron", children: isOpen ? "\u25BE" : "\u25B8" }),
2993
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-label", children: m.marketLabel }),
2994
+ m.hasInsight && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-badge", children: "\u2605" }),
2995
+ m.suspended && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-susp", children: ui.accordionSuspended })
2996
+ ]
2997
+ }
2998
+ ),
2999
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3000
+ PinToggle,
3001
+ {
3002
+ ui,
3003
+ monitor,
3004
+ pin: { kind: "market", matchId: match.matchId, marketDeveloperName: m.marketDeveloperName }
3005
+ }
3006
+ )
3007
+ ] }),
2997
3008
  isOpen && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-acc-panel", children: [
2998
3009
  entry?.error && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2999
3010
  "div",
@@ -3133,36 +3144,24 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
3133
3144
 
3134
3145
  // src/components/MonitorTabs.tsx
3135
3146
  var import_jsx_runtime48 = require("react/jsx-runtime");
3136
- function ContextLine({ m, monitor, ui }) {
3137
- const kick = m.kickoffUtc ? ui.bettingKickoff(m.kickoffUtc) : void 0;
3138
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mk-ctx", children: [
3139
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
3140
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Crest2, { kind: "team", url: m.homeCrestUrl ?? void 0, name: m.homeTeamName ?? void 0 }),
3141
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-name", children: m.homeTeamName })
3142
- ] }),
3143
- m.phase === "preMatch" ? kick && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mon-pill", children: [
3144
- kick.dayLabel,
3147
+ function OddsLiveStrip({ m, ui }) {
3148
+ const showScore = m.phase !== "preMatch" && typeof m.homeScore === "number";
3149
+ const stale = m.status === "stale";
3150
+ if (!showScore && !m.minuteLabel && !(m.isSuspended && !m.isSettled) && !m.isSettled && !stale) return null;
3151
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mk-live", children: [
3152
+ showScore && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("b", { className: "ss-w-mk-live-score", children: [
3153
+ m.homeTeamName,
3145
3154
  " ",
3146
- kick.time
3147
- ] }) : typeof m.homeScore === "number" && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("b", { children: [
3148
3155
  m.homeScore,
3149
3156
  "\u2013",
3150
- m.awayScore
3151
- ] }),
3152
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
3153
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-name", children: m.awayTeamName }),
3154
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Crest2, { kind: "team", url: m.awayCrestUrl ?? void 0, name: m.awayTeamName ?? void 0 })
3157
+ m.awayScore,
3158
+ " ",
3159
+ m.awayTeamName
3155
3160
  ] }),
3156
3161
  m.minuteLabel && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
3157
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mk-ctx-right", children: [
3158
- m.isSuspended && !m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
3159
- m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3160
- m.status === "stale" && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) }),
3161
- (() => {
3162
- const pin = monitor.pins.find((p) => p.key === m.key);
3163
- return pin ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PinToggle, { ui, monitor, pin }) : null;
3164
- })()
3165
- ] })
3162
+ m.isSuspended && !m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
3163
+ m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3164
+ stale && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) })
3166
3165
  ] });
3167
3166
  }
3168
3167
  function MatchesPanel({ monitor, ui, slip }) {
@@ -3195,20 +3194,25 @@ function withSinceViewMovement(vm, prev) {
3195
3194
  function OddsPanel({ monitor, ui, slip }) {
3196
3195
  const markets = (monitor.snapshot?.markets ?? []).filter((m) => monitor.pins.some((p) => p.key === m.key));
3197
3196
  if (markets.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-empty", children: ui.emptyOddsTab });
3198
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-list", children: markets.map((m) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
3199
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ContextLine, { m, monitor, ui }),
3200
- m.card && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3201
- MarketOddsCardList,
3202
- {
3203
- cards: [withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])],
3204
- ui,
3205
- slip,
3206
- inSlipIds: monitor.inSlip
3207
- }
3208
- ),
3209
- m.history && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3210
- !m.card && !m.history && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
3211
- ] }, m.key)) });
3197
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-list", children: markets.map((m) => {
3198
+ const pin = monitor.pins.find((p) => p.key === m.key);
3199
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
3200
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(OddsLiveStrip, { m, ui }),
3201
+ m.card && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3202
+ MarketOddsCardList,
3203
+ {
3204
+ cards: [withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])],
3205
+ ui,
3206
+ slip,
3207
+ monitor,
3208
+ pinRef: pin ?? void 0,
3209
+ inSlipIds: monitor.inSlip
3210
+ }
3211
+ ),
3212
+ m.history && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3213
+ !m.card && !m.history && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
3214
+ ] }, m.key);
3215
+ }) });
3212
3216
  }
3213
3217
 
3214
3218
  // src/components/ChatPanel.tsx
@@ -4048,7 +4052,11 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
4048
4052
  a bare context line with nothing under it. */
4049
4053
  .ss-w-mon-empty-card { padding: 8px 0 2px; font-size: 12px; color: var(--ss-w-faint); }
4050
4054
  .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); }
4051
- .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); }
4055
+ /* Odds-tab item is bare: the visible card is the market-odds card itself (no outer wrapper card),
4056
+ with an optional slim live strip above it. */
4057
+ .ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 8px; }
4058
+ .ss-w-mk-live { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 0 2px; font-size: 11.5px; color: var(--ss-w-faint); }
4059
+ .ss-w-mk-live-score { color: var(--ss-w-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
4052
4060
  .ss-w-mon-oddspin[data-settled] .ss-w-mo-price,
4053
4061
  .ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }
4054
4062
 
@@ -4058,11 +4066,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
4058
4066
  .ss-w-mon-item { display: flex; flex-direction: column; gap: 10px; }
4059
4067
  .ss-w-acc { display: flex; flex-direction: column; gap: 6px; }
4060
4068
  .ss-w-acc-row { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); overflow: hidden; }
4061
- .ss-w-acc-head { display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 11px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: var(--ss-w-ink); }
4062
- .ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; }
4063
- .ss-w-acc-label { font-size: 12.5px; font-weight: 600; }
4064
- .ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); }
4065
- .ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); }
4069
+ /* Row header: expand toggle (flex:1) + the market PinToggle as a sibling (no nested buttons). */
4070
+ .ss-w-acc-head { display: flex; align-items: center; gap: 8px; padding: 6px 9px 6px 11px; }
4071
+ .ss-w-acc-toggle { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: var(--ss-w-ink); padding: 5px 0; }
4072
+ .ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; flex: none; }
4073
+ .ss-w-acc-label { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4074
+ .ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); flex: none; }
4075
+ .ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); flex: none; }
4066
4076
  .ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }
4067
4077
  .ss-w-acc-insight { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }
4068
4078
  .ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }