@sensiblestats/widget-react 0.48.0 → 0.48.2

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/dist/index.js CHANGED
@@ -1498,56 +1498,22 @@ function writeSchedule(operatorId, localDate, payload, nowMs) {
1498
1498
  }
1499
1499
 
1500
1500
  // src/dueSet.ts
1501
- var WINDOW_MS = 3.5 * 36e5;
1501
+ var TERMINAL_PHASES = /* @__PURE__ */ new Set(["fullTime", "postponed"]);
1502
1502
  function dueMatchIds(groups, states, nowMs) {
1503
1503
  const due = /* @__PURE__ */ new Set();
1504
1504
  for (const group of groups) {
1505
1505
  for (const match of group.matches) {
1506
- const sinceKickoff = nowMs - match.kickoffUnix * 1e3;
1507
- if (sinceKickoff >= 0 && sinceKickoff <= WINDOW_MS) due.add(match.matchId);
1508
- if (states[match.matchId]?.phase === "live") due.add(match.matchId);
1506
+ if (nowMs - match.kickoffUnix * 1e3 < 0) continue;
1507
+ const phase = states[match.matchId]?.phase;
1508
+ if (phase !== void 0 && TERMINAL_PHASES.has(phase)) continue;
1509
+ due.add(match.matchId);
1509
1510
  }
1510
1511
  }
1511
1512
  return [...due];
1512
1513
  }
1513
1514
 
1514
- // src/liveClock.ts
1515
- var STALE_READING_MS = 5 * 6e4;
1516
- function parseMinute(label) {
1517
- if (!label) return null;
1518
- const plus = /^(\d+)\+(\d+)'$/.exec(label);
1519
- if (plus) return Number(plus[1]) + Number(plus[2]);
1520
- const plain = /^(\d+)'$/.exec(label);
1521
- return plain ? Number(plain[1]) : null;
1522
- }
1523
- function readingAgeMs(state, nowMs) {
1524
- if (!state?.stateAsOfUtc) return null;
1525
- const t = Date.parse(state.stateAsOfUtc);
1526
- return Number.isNaN(t) ? null : Math.max(0, nowMs - t);
1527
- }
1528
- function isReadingStale(state, nowMs) {
1529
- if (state?.isHalfTime) return false;
1530
- const age = readingAgeMs(state, nowMs);
1531
- return age !== null && age > STALE_READING_MS;
1532
- }
1533
- function displayMinute(state, nowMs) {
1534
- if (!state || state.phase !== "live") return null;
1535
- if (state.isHalfTime) return null;
1536
- if (isReadingStale(state, nowMs)) return null;
1537
- const base = parseMinute(state.minuteLabel);
1538
- if (base === null) return null;
1539
- const age = readingAgeMs(state, nowMs);
1540
- if (age === null) return state.minuteLabel ?? null;
1541
- const advanced = base + Math.floor(age / 6e4);
1542
- return `${advanced}'`;
1543
- }
1544
- function isTreatedLive(state, pollStale, nowMs) {
1545
- return state?.phase === "live" && !pollStale && !isReadingStale(state, nowMs);
1546
- }
1547
-
1548
1515
  // src/useMatchDiscovery.ts
1549
1516
  var POLL_MS = 6e4;
1550
- var CLOCK_MS = 1e4;
1551
1517
  var ROLLOVER_CHECK_MS = 6e4;
1552
1518
  var STALE_AFTER_FAILURES = 2;
1553
1519
  function localDateOf(now) {
@@ -1560,7 +1526,6 @@ function useMatchDiscovery(opts) {
1560
1526
  const [groups, setGroups] = useState2([]);
1561
1527
  const [states, setStates] = useState2({});
1562
1528
  const [failures, setFailures] = useState2(0);
1563
- const [nowMs, setNowMs] = useState2(() => Date.now());
1564
1529
  const [expanded, setExpanded] = useState2({});
1565
1530
  const [touched, setTouched] = useState2({});
1566
1531
  const groupsRef = useRef4(groups);
@@ -1638,21 +1603,16 @@ function useMatchDiscovery(opts) {
1638
1603
  }, POLL_MS);
1639
1604
  return () => clearInterval(id);
1640
1605
  }, [opts.isOpen, tick, groups]);
1641
- useEffect4(() => {
1642
- if (!opts.isOpen) return;
1643
- const id = setInterval(() => setNowMs(Date.now()), CLOCK_MS);
1644
- return () => clearInterval(id);
1645
- }, [opts.isOpen]);
1646
1606
  const stale = failures >= STALE_AFTER_FAILURES;
1647
1607
  const liveCount = useMemo2(
1648
- () => stale ? 0 : Object.values(states).filter((s) => s.phase === "live" && !isReadingStale(s, nowMs)).length,
1649
- [states, stale, nowMs]
1608
+ () => stale ? 0 : Object.values(states).filter((s) => s.phase === "live").length,
1609
+ [states, stale]
1650
1610
  );
1651
1611
  const toggleGroup = useCallback3((competitionId) => {
1652
1612
  setTouched((prev) => ({ ...prev, [competitionId]: true }));
1653
1613
  setExpanded((prev) => ({ ...prev, [competitionId]: !prev[competitionId] }));
1654
1614
  }, []);
1655
- return { groups, states, nowMs, liveCount, stale, expanded, toggleGroup, _tick: tick };
1615
+ return { groups, states, liveCount, stale, expanded, toggleGroup, _tick: tick };
1656
1616
  }
1657
1617
 
1658
1618
  // src/eventLogContext.ts
@@ -3010,7 +2970,7 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
3010
2970
  return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
3011
2971
  }
3012
2972
  function useLiveClock(minute, clockRunning, receivedAtMs) {
3013
- const [displayMinute2, setDisplayMinute] = useState15(
2973
+ const [displayMinute, setDisplayMinute] = useState15(
3014
2974
  () => computeDisplayMinute(minute, clockRunning, receivedAtMs)
3015
2975
  );
3016
2976
  useEffect9(() => {
@@ -3021,7 +2981,7 @@ function useLiveClock(minute, clockRunning, receivedAtMs) {
3021
2981
  }, TICK_MS);
3022
2982
  return () => window.clearInterval(id);
3023
2983
  }, [minute, clockRunning, receivedAtMs]);
3024
- return displayMinute2;
2984
+ return displayMinute;
3025
2985
  }
3026
2986
 
3027
2987
  // src/components/dashboard/LiveScoreCard.tsx
@@ -3053,7 +3013,7 @@ function LiveScoreCard({
3053
3013
  if (!seedRef.current || seedRef.current.key !== seedKey) {
3054
3014
  seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
3055
3015
  }
3056
- const displayMinute2 = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs);
3016
+ const displayMinute = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs);
3057
3017
  const minuteSuffix = data.minuteLabel.replace(/^\d+/, "");
3058
3018
  const scorers = scorersLine(goalEvents);
3059
3019
  return /* @__PURE__ */ jsxs32("div", { className: "ss-w-fandash-card ss-w-fandash-live-score", children: [
@@ -3063,7 +3023,7 @@ function LiveScoreCard({
3063
3023
  /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
3064
3024
  data.statusLabel
3065
3025
  ] }),
3066
- /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-minute", children: `${displayMinute2}${minuteSuffix}` }),
3026
+ /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-minute", children: `${displayMinute}${minuteSuffix}` }),
3067
3027
  data.competition ? /* @__PURE__ */ jsx36("span", { className: "ss-w-fandash-live-competition", children: data.competition }) : null
3068
3028
  ] }),
3069
3029
  /* @__PURE__ */ jsxs32("div", { className: "ss-w-fandash-live-main", children: [
@@ -3745,11 +3705,10 @@ function Side({ name, crest }) {
3745
3705
  /* @__PURE__ */ jsx49("span", { className: "ss-w-drow-nm", children: name })
3746
3706
  ] });
3747
3707
  }
3748
- function FixtureRow({ match, state, stale, nowMs, ui, monitor }) {
3749
- const readingStale = isReadingStale(state, nowMs);
3750
- const isLive = state?.phase === "live" && !stale && !readingStale;
3708
+ function FixtureRow({ match, state, stale, ui, monitor }) {
3709
+ const isLive = state?.phase === "live" && !stale;
3751
3710
  const hasScore = (state?.phase === "live" || state?.phase === "fullTime") && typeof state.homeScore === "number" && typeof state.awayScore === "number";
3752
- const ticked = displayMinute(state, nowMs);
3711
+ const ticked = state?.phase === "live" ? state.minuteLabel ?? null : null;
3753
3712
  const isFinished = state?.phase === "fullTime";
3754
3713
  const when = state?.isHalfTime && !stale ? ui.halfTime : isLive ? ticked ?? "\u2014" : state?.phase === "live" ? "\u2014" : isFinished ? ui.fullTime : kickoffLabel(match.kickoffUnix);
3755
3714
  const pin = { kind: "match", matchId: match.matchId };
@@ -3765,10 +3724,15 @@ function FixtureRow({ match, state, stale, nowMs, ui, monitor }) {
3765
3724
  ] });
3766
3725
  }
3767
3726
 
3727
+ // src/liveClock.ts
3728
+ function isTreatedLive(state, pollStale) {
3729
+ return state?.phase === "live" && !pollStale;
3730
+ }
3731
+
3768
3732
  // src/components/CompetitionGroup.tsx
3769
3733
  import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
3770
- function CompetitionGroup({ group, open, onToggle, states, stale, nowMs, ui, monitor, disambiguate = false }) {
3771
- const own = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale, nowMs));
3734
+ function CompetitionGroup({ group, open, onToggle, states, stale, ui, monitor, disambiguate = false }) {
3735
+ const own = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale));
3772
3736
  const hasLive = own.length !== group.matches.length;
3773
3737
  if (own.length === 0) {
3774
3738
  return null;
@@ -3787,15 +3751,15 @@ function CompetitionGroup({ group, open, onToggle, states, stale, nowMs, ui, mon
3787
3751
  ] }),
3788
3752
  /* @__PURE__ */ jsx50("span", { className: "ss-w-grp-count", children: own.length })
3789
3753
  ] }),
3790
- open && /* @__PURE__ */ jsx50("div", { className: "ss-w-grp-body", children: own.map((m) => /* @__PURE__ */ jsx50(FixtureRow, { match: m, state: states[m.matchId], stale, nowMs, ui, monitor }, m.matchId)) })
3754
+ open && /* @__PURE__ */ jsx50("div", { className: "ss-w-grp-body", children: own.map((m) => /* @__PURE__ */ jsx50(FixtureRow, { match: m, state: states[m.matchId], stale, ui, monitor }, m.matchId)) })
3791
3755
  ] });
3792
3756
  }
3793
3757
 
3794
3758
  // src/components/TodayPanel.tsx
3795
3759
  import { Fragment as Fragment7, jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
3796
3760
  function TodayPanel({ discovery, ui, monitor }) {
3797
- const { groups, states, nowMs, stale, expanded, toggleGroup } = discovery;
3798
- const liveRows = stale ? [] : groups.flatMap((group) => group.matches.filter((m) => isTreatedLive(states[m.matchId], stale, nowMs)).map((match) => ({ match, rank: group.rank }))).sort((a, b) => a.rank - b.rank);
3761
+ const { groups, states, stale, expanded, toggleGroup } = discovery;
3762
+ const liveRows = stale ? [] : groups.flatMap((group) => group.matches.filter((m) => isTreatedLive(states[m.matchId], stale)).map((match) => ({ match, rank: group.rank }))).sort((a, b) => a.rank - b.rank);
3799
3763
  const nameCounts = groups.reduce((acc, g) => {
3800
3764
  acc[g.competitionName] = (acc[g.competitionName] ?? 0) + 1;
3801
3765
  return acc;
@@ -3813,7 +3777,6 @@ function TodayPanel({ discovery, ui, monitor }) {
3813
3777
  match,
3814
3778
  state: states[match.matchId],
3815
3779
  stale,
3816
- nowMs,
3817
3780
  ui,
3818
3781
  monitor
3819
3782
  },
@@ -3829,7 +3792,6 @@ function TodayPanel({ discovery, ui, monitor }) {
3829
3792
  disambiguate: (nameCounts[group.competitionName] ?? 0) > 1,
3830
3793
  states,
3831
3794
  stale,
3832
- nowMs,
3833
3795
  ui,
3834
3796
  monitor
3835
3797
  },