@sensiblestats/widget-react 0.43.1 → 0.45.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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/StatsWidget.tsx
2
- import { useCallback as useCallback5, useEffect as useEffect11, useMemo as useMemo2, useRef as useRef8 } from "react";
2
+ import { useCallback as useCallback6, useEffect as useEffect12, useMemo as useMemo3, useRef as useRef9, useState as useState20 } from "react";
3
3
  import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
4
4
 
5
5
  // src/kickoff.ts
@@ -69,7 +69,7 @@ var STRINGS = {
69
69
  tomorrow: "Tomorrow",
70
70
  bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, "en", now),
71
71
  tabChat: "Chat",
72
- tabMatches: "Matches",
72
+ tabFollowing: "Following",
73
73
  tabOdds: "Odds",
74
74
  pinLabel: "Track odds",
75
75
  unpinLabel: "Stop tracking odds",
@@ -88,7 +88,10 @@ var STRINGS = {
88
88
  momentumLabel: "Momentum",
89
89
  accordionValueLabel: "Value",
90
90
  accordionRetry: "Couldn't load odds \u2014 tap to retry",
91
- accordionSuspended: "Suspended"
91
+ accordionSuspended: "Suspended",
92
+ tabToday: "Today",
93
+ sectionLive: "Live",
94
+ staleStates: "Live scores can't be updated \u2014 showing the last known state."
92
95
  },
93
96
  tr: {
94
97
  launcherLabel: "SensibleStats ile sohbet et",
@@ -143,7 +146,7 @@ var STRINGS = {
143
146
  tomorrow: "Yar\u0131n",
144
147
  bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, "tr", now),
145
148
  tabChat: "Sohbet",
146
- tabMatches: "Ma\xE7lar",
149
+ tabFollowing: "Takip",
147
150
  tabOdds: "Oranlar",
148
151
  pinLabel: "Oran\u0131 takip et",
149
152
  unpinLabel: "Oran takibini b\u0131rak",
@@ -162,7 +165,10 @@ var STRINGS = {
162
165
  momentumLabel: "Momentum",
163
166
  accordionValueLabel: "De\u011Fer",
164
167
  accordionRetry: "Oranlar y\xFCklenemedi \u2014 yeniden dene",
165
- accordionSuspended: "Ask\u0131da"
168
+ accordionSuspended: "Ask\u0131da",
169
+ tabToday: "Bug\xFCn",
170
+ sectionLive: "Canl\u0131",
171
+ staleStates: "Canl\u0131 skorlar g\xFCncellenemiyor \u2014 son bilinen durum g\xF6steriliyor."
166
172
  }
167
173
  };
168
174
  function resolveLocaleStrings(locale) {
@@ -236,8 +242,11 @@ function normalizeUi(cfg) {
236
242
  tomorrow: strings.tomorrow,
237
243
  bettingKickoff: strings.bettingKickoff,
238
244
  tabChat: strings.tabChat,
239
- tabMatches: strings.tabMatches,
245
+ tabFollowing: strings.tabFollowing,
240
246
  tabOdds: strings.tabOdds,
247
+ tabToday: strings.tabToday,
248
+ sectionLive: strings.sectionLive,
249
+ staleStates: strings.staleStates,
241
250
  pinLabel: strings.pinLabel,
242
251
  unpinLabel: strings.unpinLabel,
243
252
  matchPinLabel: strings.matchPinLabel,
@@ -279,6 +288,18 @@ function isTerminal(result) {
279
288
  if (result.status === "price_changed") return result.accepted;
280
289
  return result.status === "added" || result.status === "duplicate";
281
290
  }
291
+ function slipOutcome(result) {
292
+ if (!result) return "added";
293
+ switch (result.status) {
294
+ case "added":
295
+ case "duplicate":
296
+ return result.status;
297
+ case "price_changed":
298
+ return result.accepted ? "added" : "price_changed";
299
+ case "rejected":
300
+ return result.reason;
301
+ }
302
+ }
282
303
  function resultToToast(result, shownOdds, ui) {
283
304
  if (!result) return { kind: "success", text: ui.slipAdded };
284
305
  switch (result.status) {
@@ -300,8 +321,28 @@ import { ENTITY_TYPE_CODES } from "@sensiblestats/widget-sdk";
300
321
  function isSignalEntityType(value) {
301
322
  return Object.prototype.hasOwnProperty.call(ENTITY_TYPE_CODES, value);
302
323
  }
303
- function createDashboardTapSignal(sendSignal) {
324
+ function toWidgetEntityType(value) {
325
+ switch (value.toLowerCase()) {
326
+ case "match":
327
+ return "match";
328
+ case "team":
329
+ return "team";
330
+ case "player":
331
+ return "player";
332
+ case "competition":
333
+ return "competition";
334
+ case "market":
335
+ return "market";
336
+ default:
337
+ return null;
338
+ }
339
+ }
340
+ function createDashboardTapSignal(sendSignal, log) {
304
341
  return (tile, index, layout) => {
342
+ const widgetEntityType = toWidgetEntityType(tile.signal.entityType);
343
+ if (widgetEntityType) {
344
+ log?.log({ name: "tile_tap", entityType: widgetEntityType, entityId: tile.signal.entityId });
345
+ }
305
346
  if (!isSignalEntityType(tile.signal.entityType)) return;
306
347
  try {
307
348
  void sendSignal({
@@ -1146,6 +1187,7 @@ function useLiveMonitor(opts) {
1146
1187
  const [chatDot, setChatDot] = useState(false);
1147
1188
  const [matchesDot, setMatchesDot] = useState(false);
1148
1189
  const [oddsDot, setOddsDot] = useState(false);
1190
+ const [todayDot, setTodayDot] = useState(false);
1149
1191
  const [lastViewedPrices, setLastViewedPrices] = useState({});
1150
1192
  const [inSlip, setInSlip] = useState({});
1151
1193
  const [openMarket, setOpenMarket] = useState({});
@@ -1162,6 +1204,7 @@ function useLiveMonitor(opts) {
1162
1204
  openMarketRef.current = openMarket;
1163
1205
  const marketOddsRef = useRef3(marketOdds);
1164
1206
  marketOddsRef.current = marketOdds;
1207
+ const hasToday = opts.hasToday ?? false;
1165
1208
  const marketKey = (matchId, dev) => `${matchId}:${dev}`;
1166
1209
  const getMarketOddsRef = useRef3(opts.getMarketOdds);
1167
1210
  getMarketOddsRef.current = opts.getMarketOdds;
@@ -1216,7 +1259,7 @@ function useLiveMonitor(opts) {
1216
1259
  break;
1217
1260
  }
1218
1261
  }
1219
- if (sawNewGoalOrRed && activeTabRef.current !== "matches") setMatchesDot(true);
1262
+ if (sawNewGoalOrRed && activeTabRef.current !== "following") setMatchesDot(true);
1220
1263
  for (const m of next.matches) {
1221
1264
  if (!pinnedMatchIds.has(m.matchId)) continue;
1222
1265
  const first = m.availableMarkets?.[0];
@@ -1302,11 +1345,17 @@ function useLiveMonitor(opts) {
1302
1345
  prevPinsLengthRef.current = pins.length;
1303
1346
  if (pins.length === 0) {
1304
1347
  window.clearTimeout(timerRef.current);
1305
- setActiveTabState("chat");
1306
1348
  return;
1307
1349
  }
1308
1350
  if (wasEmpty) void tick();
1309
1351
  }, [pins.length, tick]);
1352
+ useEffect3(() => {
1353
+ const matchPins = pins.filter((p) => p.kind === "match").length;
1354
+ const marketPins = pins.length - matchPins;
1355
+ if (activeTab === "following" && matchPins === 0) setActiveTabState(hasToday ? "today" : "chat");
1356
+ if (activeTab === "odds" && marketPins === 0) setActiveTabState(hasToday ? "today" : "chat");
1357
+ if (activeTab === "today" && !hasToday) setActiveTabState("chat");
1358
+ }, [pins, activeTab, hasToday]);
1310
1359
  const prevIsOpenRef = useRef3(false);
1311
1360
  useEffect3(() => {
1312
1361
  const wasClosed = !prevIsOpenRef.current;
@@ -1327,7 +1376,8 @@ function useLiveMonitor(opts) {
1327
1376
  const setActiveTab = useCallback2((tab) => {
1328
1377
  setActiveTabState(tab);
1329
1378
  if (tab === "chat") setChatDot(false);
1330
- if (tab === "matches") {
1379
+ if (tab === "today") setTodayDot(false);
1380
+ if (tab === "following") {
1331
1381
  setMatchesDot(false);
1332
1382
  void tick();
1333
1383
  }
@@ -1347,6 +1397,9 @@ function useLiveMonitor(opts) {
1347
1397
  const togglePin = useCallback2((pin) => store.toggle(pin), [store]);
1348
1398
  const isPinned = useCallback2((key) => pinsRef.current.some((p) => p.key === key), []);
1349
1399
  const markChatActivity = useCallback2(() => setChatDot(true), []);
1400
+ const markTodayActivity = useCallback2(() => {
1401
+ if (activeTabRef.current !== "today") setTodayDot(true);
1402
+ }, []);
1350
1403
  const markInSlip = useCallback2((matchOddsId) => {
1351
1404
  setInSlip((prev) => prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true });
1352
1405
  }, []);
@@ -1362,6 +1415,8 @@ function useLiveMonitor(opts) {
1362
1415
  markChatActivity,
1363
1416
  matchesDot,
1364
1417
  oddsDot,
1418
+ todayDot,
1419
+ markTodayActivity,
1365
1420
  lastViewedPrices,
1366
1421
  inSlip,
1367
1422
  markInSlip,
@@ -1373,11 +1428,198 @@ function useLiveMonitor(opts) {
1373
1428
  };
1374
1429
  }
1375
1430
 
1431
+ // src/useMatchDiscovery.ts
1432
+ import { useCallback as useCallback3, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState2 } from "react";
1433
+
1434
+ // src/scheduleCache.ts
1435
+ var PREFIX = "ss-w-schedule:";
1436
+ var SCHEMA_VERSION = 1;
1437
+ var TTL_MS2 = 6 * 36e5;
1438
+ function scheduleCacheKey(operatorId, localDate) {
1439
+ return `${PREFIX}${operatorId}:${localDate}`;
1440
+ }
1441
+ function read(operatorId, localDate) {
1442
+ try {
1443
+ const raw = localStorage.getItem(scheduleCacheKey(operatorId, localDate));
1444
+ if (!raw) return null;
1445
+ const entry = JSON.parse(raw);
1446
+ if (entry.v !== SCHEMA_VERSION || !entry.payload) return null;
1447
+ return entry;
1448
+ } catch {
1449
+ return null;
1450
+ }
1451
+ }
1452
+ function readSchedule(operatorId, localDate, nowMs) {
1453
+ const entry = read(operatorId, localDate);
1454
+ if (!entry) return null;
1455
+ return nowMs - entry.at > TTL_MS2 ? null : entry.payload;
1456
+ }
1457
+ function readScheduleIgnoringTtl(operatorId, localDate) {
1458
+ return read(operatorId, localDate)?.payload ?? null;
1459
+ }
1460
+ function skeletonOnly(payload) {
1461
+ return {
1462
+ localDate: payload.localDate,
1463
+ groups: payload.groups.map((g) => ({
1464
+ competitionId: g.competitionId,
1465
+ competitionName: g.competitionName,
1466
+ competitionImagePath: g.competitionImagePath ?? null,
1467
+ rank: g.rank,
1468
+ expandedByDefault: g.expandedByDefault,
1469
+ matches: g.matches.map((m) => ({
1470
+ matchId: m.matchId,
1471
+ homeTeamName: m.homeTeamName,
1472
+ awayTeamName: m.awayTeamName,
1473
+ homeTeamImagePath: m.homeTeamImagePath ?? null,
1474
+ awayTeamImagePath: m.awayTeamImagePath ?? null,
1475
+ kickoffUnix: m.kickoffUnix
1476
+ }))
1477
+ }))
1478
+ };
1479
+ }
1480
+ function writeSchedule(operatorId, localDate, payload, nowMs) {
1481
+ const keep = scheduleCacheKey(operatorId, localDate);
1482
+ const mine = `${PREFIX}${operatorId}:`;
1483
+ try {
1484
+ for (let i = localStorage.length - 1; i >= 0; i--) {
1485
+ const key = localStorage.key(i);
1486
+ if (key && key.startsWith(mine) && key !== keep) localStorage.removeItem(key);
1487
+ }
1488
+ const entry = { v: SCHEMA_VERSION, at: nowMs, payload: skeletonOnly(payload) };
1489
+ localStorage.setItem(keep, JSON.stringify(entry));
1490
+ } catch {
1491
+ }
1492
+ }
1493
+
1494
+ // src/dueSet.ts
1495
+ var WINDOW_MS = 3.5 * 36e5;
1496
+ function dueMatchIds(groups, states, nowMs) {
1497
+ const due = /* @__PURE__ */ new Set();
1498
+ for (const group of groups) {
1499
+ for (const match of group.matches) {
1500
+ const sinceKickoff = nowMs - match.kickoffUnix * 1e3;
1501
+ if (sinceKickoff >= 0 && sinceKickoff <= WINDOW_MS) due.add(match.matchId);
1502
+ if (states[match.matchId]?.phase === "live") due.add(match.matchId);
1503
+ }
1504
+ }
1505
+ return [...due];
1506
+ }
1507
+
1508
+ // src/useMatchDiscovery.ts
1509
+ var POLL_MS = 6e4;
1510
+ var ROLLOVER_CHECK_MS = 6e4;
1511
+ var STALE_AFTER_FAILURES = 2;
1512
+ function localDateOf(now) {
1513
+ const y = now.getFullYear();
1514
+ const m = `${now.getMonth() + 1}`.padStart(2, "0");
1515
+ const d = `${now.getDate()}`.padStart(2, "0");
1516
+ return `${y}-${m}-${d}`;
1517
+ }
1518
+ function useMatchDiscovery(opts) {
1519
+ const [groups, setGroups] = useState2([]);
1520
+ const [states, setStates] = useState2({});
1521
+ const [failures, setFailures] = useState2(0);
1522
+ const [expanded, setExpanded] = useState2({});
1523
+ const [touched, setTouched] = useState2({});
1524
+ const groupsRef = useRef4(groups);
1525
+ groupsRef.current = groups;
1526
+ const statesRef = useRef4(states);
1527
+ statesRef.current = states;
1528
+ const getStatesRef = useRef4(opts.getStates);
1529
+ getStatesRef.current = opts.getStates;
1530
+ const pinnedKey = opts.pinnedMatchIds.join(",");
1531
+ const [localDate, setLocalDate] = useState2(() => localDateOf(/* @__PURE__ */ new Date()));
1532
+ useEffect4(() => {
1533
+ const id = setInterval(() => {
1534
+ const next = localDateOf(/* @__PURE__ */ new Date());
1535
+ setLocalDate((prev) => prev === next ? prev : next);
1536
+ }, ROLLOVER_CHECK_MS);
1537
+ return () => clearInterval(id);
1538
+ }, []);
1539
+ useEffect4(() => {
1540
+ let cancelled = false;
1541
+ const utcOffsetMinutes = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
1542
+ const cached = readSchedule(opts.operatorId, localDate, Date.now());
1543
+ if (cached) {
1544
+ if (!cancelled) setGroups(cached.groups);
1545
+ return () => {
1546
+ cancelled = true;
1547
+ };
1548
+ }
1549
+ void (async () => {
1550
+ try {
1551
+ const payload = await opts.getSchedule(localDate, utcOffsetMinutes);
1552
+ if (cancelled || !payload) return;
1553
+ writeSchedule(opts.operatorId, localDate, payload, Date.now());
1554
+ setGroups(payload.groups);
1555
+ } catch {
1556
+ const fallback = readScheduleIgnoringTtl(opts.operatorId, localDate);
1557
+ if (!cancelled && fallback) setGroups(fallback.groups);
1558
+ }
1559
+ })();
1560
+ return () => {
1561
+ cancelled = true;
1562
+ };
1563
+ }, [opts.operatorId, localDate]);
1564
+ useEffect4(() => {
1565
+ setExpanded((prev) => {
1566
+ const next = {};
1567
+ for (const group of groups) {
1568
+ const hasPin = group.matches.some((m) => opts.pinnedMatchIds.includes(m.matchId));
1569
+ const seeded = group.expandedByDefault || hasPin;
1570
+ next[group.competitionId] = touched[group.competitionId] ? prev[group.competitionId] ?? seeded : seeded;
1571
+ }
1572
+ return next;
1573
+ });
1574
+ }, [groups, pinnedKey, touched]);
1575
+ const tick = useCallback3(async () => {
1576
+ const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now());
1577
+ if (ids.length === 0) return;
1578
+ try {
1579
+ const payload = await getStatesRef.current(ids);
1580
+ if (!payload) return;
1581
+ setStates((prev) => {
1582
+ const next = { ...prev };
1583
+ for (const state of payload.states) next[state.matchId] = state;
1584
+ return next;
1585
+ });
1586
+ setFailures(0);
1587
+ } catch {
1588
+ setFailures((n) => n + 1);
1589
+ }
1590
+ }, []);
1591
+ useEffect4(() => {
1592
+ if (!opts.isOpen) return;
1593
+ void tick();
1594
+ const id = setInterval(() => {
1595
+ void tick();
1596
+ }, POLL_MS);
1597
+ return () => clearInterval(id);
1598
+ }, [opts.isOpen, tick, groups]);
1599
+ const stale = failures >= STALE_AFTER_FAILURES;
1600
+ const liveCount = useMemo2(
1601
+ () => stale ? 0 : Object.values(states).filter((s) => s.phase === "live").length,
1602
+ [states, stale]
1603
+ );
1604
+ const toggleGroup = useCallback3((competitionId) => {
1605
+ setTouched((prev) => ({ ...prev, [competitionId]: true }));
1606
+ setExpanded((prev) => ({ ...prev, [competitionId]: !prev[competitionId] }));
1607
+ }, []);
1608
+ return { groups, states, liveCount, stale, expanded, toggleGroup, _tick: tick };
1609
+ }
1610
+
1611
+ // src/eventLogContext.ts
1612
+ import { createContext, useContext } from "react";
1613
+ var EventLogContext = createContext(null);
1614
+ function useEventLog() {
1615
+ return useContext(EventLogContext);
1616
+ }
1617
+
1376
1618
  // src/components/ChatFab.tsx
1377
- import { useEffect as useEffect4, useRef as useRef4, useState as useState3 } from "react";
1619
+ import { useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
1378
1620
 
1379
1621
  // src/components/BrandMark.tsx
1380
- import { useState as useState2 } from "react";
1622
+ import { useState as useState3 } from "react";
1381
1623
 
1382
1624
  // src/assets/logo.ts
1383
1625
  var SS_LOGO_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0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";
@@ -1426,7 +1668,7 @@ function DashboardIcon({ name }) {
1426
1668
  // src/components/BrandMark.tsx
1427
1669
  import { jsx as jsx2 } from "react/jsx-runtime";
1428
1670
  function BrandMark({ logoUrl, className }) {
1429
- const [failed, setFailed] = useState2(false);
1671
+ const [failed, setFailed] = useState3(false);
1430
1672
  if (!logoUrl || failed) return /* @__PURE__ */ jsx2(SsMark, { className });
1431
1673
  return /* @__PURE__ */ jsx2("img", { className, src: logoUrl, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
1432
1674
  }
@@ -1451,9 +1693,9 @@ function GreetingBubble({ text, onOpen, onDismiss, dismissLabel = "Dismiss" }) {
1451
1693
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1452
1694
  function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = "Dismiss", introAllowed = false, onIntroStart }) {
1453
1695
  const bubble = popupText ?? greeting;
1454
- const [intro, setIntro] = useState3(false);
1455
- const armedRef = useRef4(introAllowed);
1456
- useEffect4(() => {
1696
+ const [intro, setIntro] = useState4(false);
1697
+ const armedRef = useRef5(introAllowed);
1698
+ useEffect5(() => {
1457
1699
  if (armedRef.current && bubble) {
1458
1700
  armedRef.current = false;
1459
1701
  setIntro(true);
@@ -1467,10 +1709,10 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
1467
1709
  }
1468
1710
 
1469
1711
  // src/components/ChatPanel.tsx
1470
- import { useEffect as useEffect10, useState as useState18 } from "react";
1712
+ import { useEffect as useEffect11, useState as useState19 } from "react";
1471
1713
 
1472
1714
  // src/components/ChatHeader.tsx
1473
- import { useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
1715
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
1474
1716
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1475
1717
  function ChatHeader({
1476
1718
  onClose,
@@ -1482,15 +1724,15 @@ function ChatHeader({
1482
1724
  newConversationLabel = "New conversation",
1483
1725
  moreOptionsLabel = "More options"
1484
1726
  }) {
1485
- const [menuOpen, setMenuOpen] = useState4(false);
1486
- const wrapRef = useRef5(null);
1487
- const kebabRef = useRef5(null);
1488
- const firstItemRef = useRef5(null);
1727
+ const [menuOpen, setMenuOpen] = useState5(false);
1728
+ const wrapRef = useRef6(null);
1729
+ const kebabRef = useRef6(null);
1730
+ const firstItemRef = useRef6(null);
1489
1731
  const hasMenu = !!(canReset && onNewConversation);
1490
- useEffect5(() => {
1732
+ useEffect6(() => {
1491
1733
  if (menuOpen) firstItemRef.current?.focus();
1492
1734
  }, [menuOpen]);
1493
- useEffect5(() => {
1735
+ useEffect6(() => {
1494
1736
  if (!menuOpen) return;
1495
1737
  const onPointer = (e) => {
1496
1738
  if (!wrapRef.current?.contains(e.target)) setMenuOpen(false);
@@ -1546,7 +1788,7 @@ function ChatHeader({
1546
1788
  }
1547
1789
 
1548
1790
  // src/components/MessageList.tsx
1549
- import { useEffect as useEffect9, useRef as useRef7 } from "react";
1791
+ import { useEffect as useEffect10, useRef as useRef8 } from "react";
1550
1792
 
1551
1793
  // src/components/Markdown.tsx
1552
1794
  import ReactMarkdown from "react-markdown";
@@ -1564,7 +1806,7 @@ function Markdown({ text }) {
1564
1806
  }
1565
1807
 
1566
1808
  // src/components/EntityCardList.tsx
1567
- import { useState as useState5 } from "react";
1809
+ import { useState as useState6 } from "react";
1568
1810
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1569
1811
  var MAX_VISIBLE = 3;
1570
1812
  var RECORD_RE = /^(\d+)-(\d+)-(\d+)$/;
@@ -1648,7 +1890,7 @@ function ScopeTabs({ scopes, active, onSelect }) {
1648
1890
  )) });
1649
1891
  }
1650
1892
  function EntityCardItem({ c }) {
1651
- const [active, setActive] = useState5(0);
1893
+ const [active, setActive] = useState6(0);
1652
1894
  const hasBody = c.scopes.length > 0;
1653
1895
  if (!hasBody) {
1654
1896
  return /* @__PURE__ */ jsx7("div", { className: "ss-w-ecard ss-w-ecard-bare", "data-kind": c.kind, children: /* @__PURE__ */ jsx7(CardHeader, { c, showScopeCrest: false }) });
@@ -1662,7 +1904,7 @@ function EntityCardItem({ c }) {
1662
1904
  ] });
1663
1905
  }
1664
1906
  function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMoreLabel = (n) => `Show ${n} more` }) {
1665
- const [expanded, setExpanded] = useState5(false);
1907
+ const [expanded, setExpanded] = useState6(false);
1666
1908
  if (cards.length === 0) return null;
1667
1909
  const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE);
1668
1910
  const overflow = cards.length - MAX_VISIBLE;
@@ -1673,18 +1915,18 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
1673
1915
  }
1674
1916
 
1675
1917
  // src/components/BettingInsightList.tsx
1676
- import { useState as useState9 } from "react";
1918
+ import { useState as useState10 } from "react";
1677
1919
 
1678
1920
  // src/components/AddToSlipButton.tsx
1679
- import { useCallback as useCallback3, useState as useState6 } from "react";
1921
+ import { useCallback as useCallback4, useState as useState7 } from "react";
1680
1922
  import { isAddToSlipResult } from "@sensiblestats/widget-sdk";
1681
1923
 
1682
1924
  // src/components/Toast.tsx
1683
- import { useEffect as useEffect6 } from "react";
1925
+ import { useEffect as useEffect7 } from "react";
1684
1926
  import { jsx as jsx8 } from "react/jsx-runtime";
1685
1927
  var DISMISS_MS = 4e3;
1686
1928
  function Toast({ toast, onDismiss }) {
1687
- useEffect6(() => {
1929
+ useEffect7(() => {
1688
1930
  if (!toast) return;
1689
1931
  const timer = setTimeout(onDismiss, DISMISS_MS);
1690
1932
  return () => clearTimeout(timer);
@@ -1701,19 +1943,32 @@ function withTimeout(value) {
1701
1943
  new Promise((_, reject) => setTimeout(() => reject(new Error("add-to-slip timed out")), ADD_TO_SLIP_TIMEOUT_MS))
1702
1944
  ]);
1703
1945
  }
1704
- function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
1705
- const [pending, setPending] = useState6(false);
1706
- const [settled, setSettled] = useState6(false);
1707
- const [toast, setToast] = useState6(null);
1708
- const dismiss = useCallback3(() => setToast(null), []);
1946
+ function SlipButton({ selection, shownOdds, marketName, marketDeveloperName, slip, ui }) {
1947
+ const [pending, setPending] = useState7(false);
1948
+ const [settled, setSettled] = useState7(false);
1949
+ const [toast, setToast] = useState7(null);
1950
+ const dismiss = useCallback4(() => setToast(null), []);
1951
+ const log = useEventLog();
1709
1952
  const handler = slip.onAddToSlip;
1710
1953
  if (!ui || !handler || !selection) return null;
1711
1954
  const onClick = async () => {
1712
1955
  setPending(true);
1956
+ if (marketDeveloperName !== void 0) {
1957
+ log?.log({ name: "slip_click", entityType: "market", marketDeveloperName, entityId: marketDeveloperName });
1958
+ }
1713
1959
  try {
1714
1960
  const raw = await withTimeout(Promise.resolve(handler(selection)));
1715
1961
  if (raw != null && !isAddToSlipResult(raw)) throw new Error("malformed add-to-slip result");
1716
1962
  const result = raw ?? void 0;
1963
+ if (marketDeveloperName !== void 0) {
1964
+ log?.log({
1965
+ name: "slip_result",
1966
+ entityType: "market",
1967
+ marketDeveloperName,
1968
+ entityId: marketDeveloperName,
1969
+ outcome: slipOutcome(result)
1970
+ });
1971
+ }
1717
1972
  setToast(resultToToast(result, shownOdds || selection.oddsDecimal.toFixed(2), ui));
1718
1973
  setSettled(isTerminal(result));
1719
1974
  if (wasAdded(result) && slip.onMarketClicked) {
@@ -1723,6 +1978,9 @@ function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
1723
1978
  }
1724
1979
  }
1725
1980
  } catch {
1981
+ if (marketDeveloperName !== void 0) {
1982
+ log?.log({ name: "slip_result", entityType: "market", marketDeveloperName, entityId: marketDeveloperName, outcome: "timeout" });
1983
+ }
1726
1984
  setToast({ kind: "error", text: ui.slipFailed });
1727
1985
  } finally {
1728
1986
  setPending(false);
@@ -1744,7 +2002,17 @@ function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
1744
2002
  }
1745
2003
  function AddToSlipButton({ it, slip, ui }) {
1746
2004
  const selection = it.addToSlipEnabled ? toSlipSelection(it, slip.conversationId) : null;
1747
- return /* @__PURE__ */ jsx9(SlipButton, { selection, shownOdds: it.odds ?? "", marketName: it.market, slip, ui });
2005
+ return /* @__PURE__ */ jsx9(
2006
+ SlipButton,
2007
+ {
2008
+ selection,
2009
+ shownOdds: it.odds ?? "",
2010
+ marketName: it.market,
2011
+ marketDeveloperName: it.marketDeveloperName,
2012
+ slip,
2013
+ ui
2014
+ }
2015
+ );
1748
2016
  }
1749
2017
 
1750
2018
  // src/components/OddsMovementBadge.tsx
@@ -1769,14 +2037,14 @@ function OddsMovementBadge({
1769
2037
  }
1770
2038
 
1771
2039
  // src/components/Crest.tsx
1772
- import { useState as useState7 } from "react";
2040
+ import { useState as useState8 } from "react";
1773
2041
  import { jsx as jsx11 } from "react/jsx-runtime";
1774
2042
  function initials2(name) {
1775
2043
  return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
1776
2044
  }
1777
2045
  function Crest2({ url, name, kind }) {
1778
2046
  const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
1779
- const [failed, setFailed] = useState7(false);
2047
+ const [failed, setFailed] = useState8(false);
1780
2048
  if (url && !failed) {
1781
2049
  return /* @__PURE__ */ jsx11("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
1782
2050
  }
@@ -1784,7 +2052,7 @@ function Crest2({ url, name, kind }) {
1784
2052
  }
1785
2053
 
1786
2054
  // src/components/PinToggle.tsx
1787
- import { useCallback as useCallback4, useState as useState8 } from "react";
2055
+ import { useCallback as useCallback5, useState as useState9 } from "react";
1788
2056
  import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1789
2057
  var PIN_GLYPHS = {
1790
2058
  pin: { viewBox: "0 0 24 24", strokeWidth: 1.4, transform: "scale(1.5)", d: "M9.5 1.5 14.5 6.5 13 8l-.5-.5-3 3 .3 2.2-1.4 1.4L5.6 11.3l-3.3 3.3-1-1 3.3-3.3L1.9 7.5l1.4-1.4 2.2.3 3-3L8 2.9z" },
@@ -1792,15 +2060,23 @@ var PIN_GLYPHS = {
1792
2060
  bookmark: { viewBox: "0 0 24 24", strokeWidth: 2, d: "M7 3h10a1.5 1.5 0 0 1 1.5 1.5V21l-6.5-3.6L5.5 21V4.5A1.5 1.5 0 0 1 7 3z" }
1793
2061
  };
1794
2062
  function PinToggle({ pin, monitor, ui }) {
1795
- const [toast, setToast] = useState8(null);
1796
- const dismiss = useCallback4(() => setToast(null), []);
2063
+ const [toast, setToast] = useState9(null);
2064
+ const dismiss = useCallback5(() => setToast(null), []);
2065
+ const log = useEventLog();
1797
2066
  if (!monitor || !monitor.enabled) return null;
1798
2067
  const key = pinKey(pin);
1799
2068
  const pinned = monitor.isPinned(key);
1800
2069
  const labels = pin.kind === "match" ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel } : { pin: ui.pinLabel, unpin: ui.unpinLabel };
1801
2070
  const onClick = () => {
1802
2071
  const result = monitor.togglePin({ ...pin, key });
1803
- if (result === "match_limit") {
2072
+ if ((result === "added" || result === "removed") && (pin.kind === "match" || pin.marketDeveloperName !== void 0)) {
2073
+ log?.log({
2074
+ name: result === "added" ? "pin_add" : "pin_remove",
2075
+ entityType: pin.kind === "match" ? "match" : "market",
2076
+ entityId: pin.kind === "match" ? String(pin.matchId) : pin.marketDeveloperName,
2077
+ marketDeveloperName: pin.marketDeveloperName
2078
+ });
2079
+ } else if (result === "match_limit") {
1804
2080
  setToast({ kind: "error", text: ui.matchLimitToast });
1805
2081
  } else if (result === "market_limit") {
1806
2082
  setToast({ kind: "error", text: ui.marketLimitToast });
@@ -1845,7 +2121,7 @@ function StatRows({ stats }) {
1845
2121
  ] }, `${s.label}:${s.value}`)) });
1846
2122
  }
1847
2123
  function ScopedStats({ scopes }) {
1848
- const [active, setActive] = useState9(0);
2124
+ const [active, setActive] = useState10(0);
1849
2125
  const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
1850
2126
  return /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-scoped", children: [
1851
2127
  /* @__PURE__ */ jsx13("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx13("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
@@ -1856,12 +2132,20 @@ function hasStatsContent(it) {
1856
2132
  return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
1857
2133
  }
1858
2134
  function ReasonStrip({ it, ui }) {
1859
- const [open, setOpen] = useState9(false);
2135
+ const [open, setOpen] = useState10(false);
2136
+ const log = useEventLog();
1860
2137
  const hasScopes = !!it.scopes && it.scopes.length >= 2;
1861
2138
  const hasStats = hasStatsContent(it);
1862
2139
  const hasText = !!it.text;
1863
2140
  if (!hasText && !hasStats) return null;
1864
2141
  const expandable = hasStats || (it.text?.length ?? 0) > 90;
2142
+ const onToggle = () => {
2143
+ setOpen((v) => {
2144
+ const next = !v;
2145
+ if (next) log?.log({ name: "insight_expand", entityType: "match", entityId: String(it.matchId) });
2146
+ return next;
2147
+ });
2148
+ };
1865
2149
  return /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-reason", children: [
1866
2150
  /* @__PURE__ */ jsx13("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
1867
2151
  /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-reason-body", children: [
@@ -1875,7 +2159,7 @@ function ReasonStrip({ it, ui }) {
1875
2159
  className: "ss-w-bi-expand",
1876
2160
  "aria-expanded": open,
1877
2161
  "aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
1878
- onClick: () => setOpen((v) => !v),
2162
+ onClick: onToggle,
1879
2163
  children: /* @__PURE__ */ jsx13("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
1880
2164
  }
1881
2165
  ) : null
@@ -1968,7 +2252,7 @@ function BettingInsightList({ insights, ui, slip, monitor }) {
1968
2252
  }
1969
2253
 
1970
2254
  // src/components/MarketOddsCardList.tsx
1971
- import { useState as useState10 } from "react";
2255
+ import { useState as useState11 } from "react";
1972
2256
  import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1973
2257
  function OddsRow({ vm, row, ui, slip, inSlipIds }) {
1974
2258
  const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
@@ -1981,11 +2265,11 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
1981
2265
  "\u2713 ",
1982
2266
  ui.inSlipLabel
1983
2267
  ] }) : null,
1984
- /* @__PURE__ */ jsx14(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
2268
+ /* @__PURE__ */ jsx14(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, marketDeveloperName: vm.marketDeveloperName, slip, ui })
1985
2269
  ] });
1986
2270
  }
1987
2271
  function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }) {
1988
- const [open, setOpen] = useState10(false);
2272
+ const [open, setOpen] = useState11(false);
1989
2273
  const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
1990
2274
  const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : void 0);
1991
2275
  const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
@@ -2288,7 +2572,7 @@ function FixtureCard({ card }) {
2288
2572
  }
2289
2573
 
2290
2574
  // src/components/dashboard/CountdownCard.tsx
2291
- import { Fragment as Fragment6, useEffect as useEffect7, useState as useState11 } from "react";
2575
+ import { Fragment as Fragment6, useEffect as useEffect8, useState as useState12 } from "react";
2292
2576
  import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
2293
2577
  var DAY_MS = 864e5;
2294
2578
  function remainingSegments(kickoffUnix, nowMs, withSeconds) {
@@ -2307,12 +2591,12 @@ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
2307
2591
  function CountdownCard({ card }) {
2308
2592
  const { data } = card;
2309
2593
  const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
2310
- const [nowMs, setNowMs] = useState11(() => Date.now());
2311
- const [reduced] = useState11(
2594
+ const [nowMs, setNowMs] = useState12(() => Date.now());
2595
+ const [reduced] = useState12(
2312
2596
  () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
2313
2597
  );
2314
2598
  const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
2315
- useEffect7(() => {
2599
+ useEffect8(() => {
2316
2600
  if (reduced) return;
2317
2601
  const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
2318
2602
  return () => window.clearInterval(id);
@@ -2331,7 +2615,7 @@ function CountdownCard({ card }) {
2331
2615
  }
2332
2616
 
2333
2617
  // src/components/dashboard/InjuriesCard.tsx
2334
- import { useState as useState12 } from "react";
2618
+ import { useState as useState13 } from "react";
2335
2619
  import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
2336
2620
  var SHOWN = 3;
2337
2621
  function ColHead({ name, crestUrl }) {
@@ -2354,7 +2638,7 @@ function InjuryList({ rows, emptyLabel, limit }) {
2354
2638
  }
2355
2639
  function InjuriesCard({ card, ui }) {
2356
2640
  const { data } = card;
2357
- const [expanded, setExpanded] = useState12(false);
2641
+ const [expanded, setExpanded] = useState13(false);
2358
2642
  const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
2359
2643
  const limit = expanded ? void 0 : SHOWN;
2360
2644
  const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
@@ -2458,7 +2742,7 @@ function LinksCard({ card }) {
2458
2742
  }
2459
2743
 
2460
2744
  // src/components/dashboard/PostMatchResultCard.tsx
2461
- import { useState as useState13 } from "react";
2745
+ import { useState as useState14 } from "react";
2462
2746
  import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
2463
2747
  function initials3(name) {
2464
2748
  return name.trim().slice(0, 3).toUpperCase();
@@ -2468,7 +2752,7 @@ function PostMatchCrest({
2468
2752
  name,
2469
2753
  side
2470
2754
  }) {
2471
- const [failed, setFailed] = useState13(false);
2755
+ const [failed, setFailed] = useState14(false);
2472
2756
  const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
2473
2757
  if (url && !failed) {
2474
2758
  return /* @__PURE__ */ jsx27("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
@@ -2667,10 +2951,10 @@ function RestingFormCard({ card }) {
2667
2951
  }
2668
2952
 
2669
2953
  // src/components/dashboard/LiveScoreCard.tsx
2670
- import { useRef as useRef6, useState as useState15 } from "react";
2954
+ import { useRef as useRef7, useState as useState16 } from "react";
2671
2955
 
2672
2956
  // src/useLiveClock.ts
2673
- import { useEffect as useEffect8, useState as useState14 } from "react";
2957
+ import { useEffect as useEffect9, useState as useState15 } from "react";
2674
2958
  var TICK_MS = 6e4;
2675
2959
  var MAX_LIVE_TICK_MINUTES = 15;
2676
2960
  function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
@@ -2679,10 +2963,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
2679
2963
  return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
2680
2964
  }
2681
2965
  function useLiveClock(minute, clockRunning, receivedAtMs) {
2682
- const [displayMinute, setDisplayMinute] = useState14(
2966
+ const [displayMinute, setDisplayMinute] = useState15(
2683
2967
  () => computeDisplayMinute(minute, clockRunning, receivedAtMs)
2684
2968
  );
2685
- useEffect8(() => {
2969
+ useEffect9(() => {
2686
2970
  setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
2687
2971
  if (!clockRunning) return;
2688
2972
  const id = window.setInterval(() => {
@@ -2699,7 +2983,7 @@ function initials5(name) {
2699
2983
  return name.trim().slice(0, 3).toUpperCase();
2700
2984
  }
2701
2985
  function LiveCrest({ url, name, side }) {
2702
- const [failed, setFailed] = useState15(false);
2986
+ const [failed, setFailed] = useState16(false);
2703
2987
  const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
2704
2988
  if (url && !failed) {
2705
2989
  return /* @__PURE__ */ jsx36("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
@@ -2718,7 +3002,7 @@ function LiveScoreCard({
2718
3002
  }) {
2719
3003
  const { data } = card;
2720
3004
  const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
2721
- const seedRef = useRef6(null);
3005
+ const seedRef = useRef7(null);
2722
3006
  if (!seedRef.current || seedRef.current.key !== seedKey) {
2723
3007
  seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
2724
3008
  }
@@ -2758,7 +3042,7 @@ function LiveScoreCard({
2758
3042
  }
2759
3043
 
2760
3044
  // src/components/dashboard/LiveTimelineCard.tsx
2761
- import { useState as useState16 } from "react";
3045
+ import { useState as useState17 } from "react";
2762
3046
  import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
2763
3047
  var SHOWN2 = 3;
2764
3048
  function EventIcon({ type }) {
@@ -2800,7 +3084,7 @@ function EventRow({ e }) {
2800
3084
  ] });
2801
3085
  }
2802
3086
  function LiveTimelineCard({ card, ui }) {
2803
- const [expanded, setExpanded] = useState16(false);
3087
+ const [expanded, setExpanded] = useState17(false);
2804
3088
  const events = card.data.events;
2805
3089
  if (!events || events.length === 0) return null;
2806
3090
  const sorted = [...events].sort((a, b) => b.minute - a.minute);
@@ -3040,11 +3324,11 @@ function turnAnchor(messages) {
3040
3324
  }
3041
3325
  function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
3042
3326
  const { state, send } = controller;
3043
- const listRef = useRef7(null);
3044
- const endRef = useRef7(null);
3045
- const pinnedRef = useRef7(true);
3046
- const anchoredTurnRef = useRef7(null);
3047
- useEffect9(() => {
3327
+ const listRef = useRef8(null);
3328
+ const endRef = useRef8(null);
3329
+ const pinnedRef = useRef8(true);
3330
+ const anchoredTurnRef = useRef8(null);
3331
+ useEffect10(() => {
3048
3332
  const anchor = turnAnchor(state.messages);
3049
3333
  const list = listRef.current;
3050
3334
  if (anchor && anchor.turnId !== anchoredTurnRef.current) {
@@ -3100,10 +3384,10 @@ function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
3100
3384
  }
3101
3385
 
3102
3386
  // src/components/ChatInput.tsx
3103
- import { useState as useState17 } from "react";
3387
+ import { useState as useState18 } from "react";
3104
3388
  import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
3105
3389
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
3106
- const [value, setValue] = useState17("");
3390
+ const [value, setValue] = useState18("");
3107
3391
  const submit = () => {
3108
3392
  const t = value.trim();
3109
3393
  if (!t) return;
@@ -3124,22 +3408,16 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
3124
3408
 
3125
3409
  // src/components/TabBar.tsx
3126
3410
  import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
3127
- var TABS = [
3128
- { tab: "chat", labelKey: "tabChat" },
3129
- { tab: "matches", labelKey: "tabMatches" },
3130
- { tab: "odds", labelKey: "tabOdds" }
3131
- ];
3132
- function TabBar({ monitor, ui, matchCount, oddsCount }) {
3133
- if (monitor.pins.length === 0) return null;
3134
- const counts = { chat: 0, matches: matchCount, odds: oddsCount };
3135
- const dots = {
3136
- chat: monitor.chatDot && monitor.activeTab !== "chat",
3137
- matches: monitor.matchesDot && monitor.activeTab !== "matches",
3138
- odds: monitor.oddsDot && monitor.activeTab !== "odds"
3139
- };
3140
- return /* @__PURE__ */ jsx45("div", { className: "ss-w-tabs", role: "tablist", children: TABS.map(({ tab, labelKey }) => {
3411
+ function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday }) {
3412
+ const tabs = [
3413
+ { tab: "chat", label: ui.tabChat, count: 0, dot: monitor.chatDot },
3414
+ ...hasToday ? [{ tab: "today", label: ui.tabToday, count: todayCount, dot: monitor.todayDot }] : [],
3415
+ ...matchCount > 0 ? [{ tab: "following", label: ui.tabFollowing, count: matchCount, dot: monitor.matchesDot }] : [],
3416
+ ...oddsCount > 0 ? [{ tab: "odds", label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : []
3417
+ ];
3418
+ if (tabs.length < 2) return null;
3419
+ return /* @__PURE__ */ jsx45("div", { className: "ss-w-tabs", role: "tablist", children: tabs.map(({ tab, label, count, dot }) => {
3141
3420
  const active = monitor.activeTab === tab;
3142
- const count = counts[tab];
3143
3421
  return /* @__PURE__ */ jsxs40(
3144
3422
  "button",
3145
3423
  {
@@ -3150,9 +3428,9 @@ function TabBar({ monitor, ui, matchCount, oddsCount }) {
3150
3428
  className: "ss-w-tab",
3151
3429
  onClick: () => monitor.setActiveTab(tab),
3152
3430
  children: [
3153
- ui[labelKey],
3431
+ label,
3154
3432
  count > 0 && /* @__PURE__ */ jsx45("span", { className: "ss-w-tab-count", children: count }),
3155
- dots[tab] && /* @__PURE__ */ jsx45("span", { className: "ss-w-tab-dot", "aria-hidden": "true" })
3433
+ dot && !active && /* @__PURE__ */ jsx45("span", { className: "ss-w-tab-dot", "aria-hidden": "true" })
3156
3434
  ]
3157
3435
  },
3158
3436
  tab
@@ -3313,6 +3591,7 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
3313
3591
  selection,
3314
3592
  shownOdds: typeof row.market.price === "number" ? row.market.price.toFixed(2) : "",
3315
3593
  marketName: row.market.marketLabel,
3594
+ marketDeveloperName: row.market.marketDeveloperName,
3316
3595
  slip,
3317
3596
  ui
3318
3597
  }
@@ -3407,12 +3686,96 @@ function OddsPanel({ monitor, ui, slip }) {
3407
3686
  }) });
3408
3687
  }
3409
3688
 
3410
- // src/components/ChatPanel.tsx
3689
+ // src/components/FixtureRow.tsx
3411
3690
  import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
3691
+ function kickoffLabel(kickoffUnix) {
3692
+ const d = new Date(kickoffUnix * 1e3);
3693
+ return `${`${d.getHours()}`.padStart(2, "0")}:${`${d.getMinutes()}`.padStart(2, "0")}`;
3694
+ }
3695
+ function Side({ name, crest }) {
3696
+ return /* @__PURE__ */ jsxs44("span", { className: "ss-w-drow-side", children: [
3697
+ crest ? /* @__PURE__ */ jsx49("img", { className: "ss-w-drow-crest", src: crest, alt: "" }) : null,
3698
+ /* @__PURE__ */ jsx49("span", { className: "ss-w-drow-nm", children: name })
3699
+ ] });
3700
+ }
3701
+ function FixtureRow({ match, state, stale, ui, monitor }) {
3702
+ const isLive = state?.phase === "live" && !stale;
3703
+ const hasScore = (state?.phase === "live" || state?.phase === "fullTime") && typeof state.homeScore === "number" && typeof state.awayScore === "number";
3704
+ const when = stale && state?.phase === "live" ? "\u2014" : isLive ? state?.minuteLabel ?? "\u2014" : kickoffLabel(match.kickoffUnix);
3705
+ return /* @__PURE__ */ jsxs44("div", { className: isLive ? "ss-w-drow ss-w-drow--live" : "ss-w-drow", children: [
3706
+ /* @__PURE__ */ jsx49("span", { className: isLive ? "ss-w-drow-when ss-w-drow-when--live" : "ss-w-drow-when", children: when }),
3707
+ /* @__PURE__ */ jsxs44("span", { className: "ss-w-drow-fx", children: [
3708
+ /* @__PURE__ */ jsx49(Side, { name: match.homeTeamName, crest: match.homeTeamImagePath }),
3709
+ /* @__PURE__ */ jsx49("span", { className: "ss-w-drow-dash", children: "\u2013" }),
3710
+ /* @__PURE__ */ jsx49(Side, { name: match.awayTeamName, crest: match.awayTeamImagePath })
3711
+ ] }),
3712
+ /* @__PURE__ */ jsx49("span", { className: hasScore ? "ss-w-drow-sc" : "ss-w-drow-sc ss-w-drow-sc--idle", children: hasScore ? `${state.homeScore}\u2013${state.awayScore}` : "\u2013" }),
3713
+ /* @__PURE__ */ jsx49(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
3714
+ ] });
3715
+ }
3716
+
3717
+ // src/components/CompetitionGroup.tsx
3718
+ import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
3719
+ function CompetitionGroup({ group, open, onToggle, states, stale, ui, monitor }) {
3720
+ const own = group.matches.filter((m) => states[m.matchId]?.phase !== "live" || stale);
3721
+ const hasLive = own.length !== group.matches.length;
3722
+ return /* @__PURE__ */ jsxs45("div", { className: "ss-w-grp", children: [
3723
+ /* @__PURE__ */ jsxs45("button", { type: "button", className: "ss-w-grp-head", "aria-expanded": open, onClick: onToggle, children: [
3724
+ /* @__PURE__ */ jsx50("span", { className: "ss-w-grp-chev", children: open ? "\u25BE" : "\u25B8" }),
3725
+ hasLive && /* @__PURE__ */ jsx50("span", { className: "ss-w-sec-dot", "aria-hidden": "true" }),
3726
+ /* @__PURE__ */ jsx50("span", { className: "ss-w-grp-name", children: group.competitionName }),
3727
+ /* @__PURE__ */ jsx50("span", { className: "ss-w-grp-count", children: own.length })
3728
+ ] }),
3729
+ 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)) })
3730
+ ] });
3731
+ }
3732
+
3733
+ // src/components/TodayPanel.tsx
3734
+ import { Fragment as Fragment7, jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
3735
+ function TodayPanel({ discovery, ui, monitor }) {
3736
+ const { groups, states, stale, expanded, toggleGroup } = discovery;
3737
+ const liveRows = stale ? [] : groups.flatMap((group) => group.matches.filter((m) => states[m.matchId]?.phase === "live").map((match) => ({ match, rank: group.rank }))).sort((a, b) => a.rank - b.rank);
3738
+ return /* @__PURE__ */ jsxs46("div", { className: "ss-w-mon-list", children: [
3739
+ stale && /* @__PURE__ */ jsx51("div", { className: "ss-w-stale", children: ui.staleStates }),
3740
+ liveRows.length > 0 && /* @__PURE__ */ jsxs46(Fragment7, { children: [
3741
+ /* @__PURE__ */ jsxs46("div", { className: "ss-w-sec-head", children: [
3742
+ /* @__PURE__ */ jsx51("span", { className: "ss-w-sec-dot", "aria-hidden": "true" }),
3743
+ ui.sectionLive
3744
+ ] }),
3745
+ /* @__PURE__ */ jsx51("div", { className: "ss-w-today-live", children: liveRows.map(({ match }) => /* @__PURE__ */ jsx51(
3746
+ FixtureRow,
3747
+ {
3748
+ match,
3749
+ state: states[match.matchId],
3750
+ stale,
3751
+ ui,
3752
+ monitor
3753
+ },
3754
+ match.matchId
3755
+ )) })
3756
+ ] }),
3757
+ groups.map((group) => /* @__PURE__ */ jsx51(
3758
+ CompetitionGroup,
3759
+ {
3760
+ group,
3761
+ open: expanded[group.competitionId] ?? group.expandedByDefault,
3762
+ onToggle: () => toggleGroup(group.competitionId),
3763
+ states,
3764
+ stale,
3765
+ ui,
3766
+ monitor
3767
+ },
3768
+ group.competitionId
3769
+ ))
3770
+ ] });
3771
+ }
3772
+
3773
+ // src/components/ChatPanel.tsx
3774
+ import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
3412
3775
  var FULLSCREEN_QUERY = "(max-width: 639px)";
3413
3776
  function useIsModal() {
3414
- const [modal, setModal] = useState18(false);
3415
- useEffect10(() => {
3777
+ const [modal, setModal] = useState19(false);
3778
+ useEffect11(() => {
3416
3779
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
3417
3780
  const mql = window.matchMedia(FULLSCREEN_QUERY);
3418
3781
  const sync = () => setModal(mql.matches);
@@ -3422,10 +3785,10 @@ function useIsModal() {
3422
3785
  }, []);
3423
3786
  return modal;
3424
3787
  }
3425
- function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3788
+ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery }) {
3426
3789
  const { state, close, stop, send, reset } = controller;
3427
3790
  const isModal = useIsModal();
3428
- useEffect10(() => {
3791
+ useEffect11(() => {
3429
3792
  const onKey = (e) => {
3430
3793
  if (e.key === "Escape") close();
3431
3794
  };
@@ -3436,11 +3799,11 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3436
3799
  monitor?.setActiveTab("chat");
3437
3800
  send(text);
3438
3801
  };
3439
- useEffect10(() => {
3802
+ useEffect11(() => {
3440
3803
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
3441
3804
  }, [monitor, state.isStreaming, state.messages.length]);
3442
- return /* @__PURE__ */ jsxs44("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
3443
- /* @__PURE__ */ jsx49(
3805
+ return /* @__PURE__ */ jsxs47("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
3806
+ /* @__PURE__ */ jsx52(
3444
3807
  ChatHeader,
3445
3808
  {
3446
3809
  onClose: close,
@@ -3453,25 +3816,28 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3453
3816
  moreOptionsLabel: ui.moreOptions
3454
3817
  }
3455
3818
  ),
3456
- monitor && /* @__PURE__ */ jsx49(
3819
+ monitor && /* @__PURE__ */ jsx52(
3457
3820
  TabBar,
3458
3821
  {
3459
3822
  monitor,
3460
3823
  ui,
3461
3824
  matchCount: monitor.pins.filter((p) => p.kind === "match").length,
3462
- oddsCount: monitor.pins.filter((p) => p.kind !== "match").length
3825
+ oddsCount: monitor.pins.filter((p) => p.kind !== "match").length,
3826
+ todayCount: discovery?.liveCount ?? 0,
3827
+ hasToday: (discovery?.groups.length ?? 0) > 0
3463
3828
  }
3464
3829
  ),
3465
- /* @__PURE__ */ jsx49(
3830
+ /* @__PURE__ */ jsx52(
3466
3831
  "div",
3467
3832
  {
3468
3833
  style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
3469
- children: /* @__PURE__ */ jsx49(MessageList, { controller, ui, slip, onDashboardTap, monitor })
3834
+ children: /* @__PURE__ */ jsx52(MessageList, { controller, ui, slip, onDashboardTap, monitor })
3470
3835
  }
3471
3836
  ),
3472
- monitor && monitor.activeTab === "matches" && /* @__PURE__ */ jsx49(MatchesPanel, { monitor, ui, slip }),
3473
- monitor && monitor.activeTab === "odds" && /* @__PURE__ */ jsx49(OddsPanel, { monitor, ui, slip }),
3474
- /* @__PURE__ */ jsx49(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
3837
+ monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ jsx52(TodayPanel, { discovery, ui, monitor }),
3838
+ monitor && monitor.activeTab === "following" && /* @__PURE__ */ jsx52(MatchesPanel, { monitor, ui, slip }),
3839
+ monitor && monitor.activeTab === "odds" && /* @__PURE__ */ jsx52(OddsPanel, { monitor, ui, slip }),
3840
+ /* @__PURE__ */ jsx52(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
3475
3841
  ] });
3476
3842
  }
3477
3843
 
@@ -4208,8 +4574,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
4208
4574
  .ss-w-fandash-live-legend-swatch--away { background: var(--ss-w-away); }
4209
4575
 
4210
4576
  /* live monitor tab bar: underline pattern mirrors .ss-w-ecard-scope; the unread dot uses --ss-w-neg */
4211
- .ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); }
4212
- .ss-w-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 9px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; }
4577
+ .ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); overflow-x: auto; scrollbar-width: none; }
4578
+ .ss-w-tabs::-webkit-scrollbar { display: none; }
4579
+ .ss-w-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 9px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; flex: none; white-space: nowrap; }
4213
4580
  .ss-w-tab[data-on] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }
4214
4581
  .ss-w-tab-count { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 999px; padding: 1px 6px; }
4215
4582
  .ss-w-tab[data-on] .ss-w-tab-count { color: var(--ss-w-accent); }
@@ -4298,10 +4665,41 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
4298
4665
  .ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }
4299
4666
  .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; }
4300
4667
  .ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }
4668
+
4669
+ /* ---- Today tab (u355) ---- */
4670
+ .ss-w-sec-head { display: flex; align-items: center; gap: 7px; padding: 2px 2px 0; font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }
4671
+ .ss-w-sec-head::after { content: ""; flex: 1; height: 1px; background: var(--ss-w-line); }
4672
+ .ss-w-sec-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }
4673
+ .ss-w-today-live { display: flex; flex-direction: column; gap: 2px; }
4674
+
4675
+ .ss-w-grp { border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; }
4676
+ .ss-w-grp-head { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 11px; background: var(--ss-w-bubble); border: none; font: inherit; color: var(--ss-w-ink); cursor: pointer; text-align: left; }
4677
+ .ss-w-grp-head:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }
4678
+ .ss-w-grp-chev { color: var(--ss-w-faint); font-size: 10px; flex: none; }
4679
+ .ss-w-grp-name { font-size: 12px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4680
+ .ss-w-grp-count { margin-left: auto; flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 999px; padding: 1px 7px; font-variant-numeric: tabular-nums; }
4681
+ .ss-w-grp-body { display: flex; flex-direction: column; padding: 2px 11px 6px; }
4682
+
4683
+ .ss-w-drow { display: grid; grid-template-columns: 42px minmax(0,1fr) auto 22px; align-items: center; gap: 9px; padding: 7px 0; border-bottom: 1px solid var(--ss-w-line); }
4684
+ .ss-w-drow:last-child { border-bottom: none; }
4685
+ .ss-w-drow-when { font-size: 11px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }
4686
+ .ss-w-drow-when--live { color: var(--ss-w-neg); }
4687
+ /* Each side ellipsises independently: a single joined string truncates the away team off the end,
4688
+ which is the u350 betting-card truncation one layer down. */
4689
+ .ss-w-drow-fx { display: flex; align-items: center; gap: 6px; min-width: 0; }
4690
+ .ss-w-drow-side { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1 1 0; }
4691
+ .ss-w-drow-nm { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4692
+ .ss-w-drow-dash { flex: none; color: var(--ss-w-faint); font-size: 11px; }
4693
+ .ss-w-drow-sc { font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
4694
+ .ss-w-drow-sc--idle { color: var(--ss-w-faint); font-weight: 600; }
4695
+ .ss-w-drow--live { background: color-mix(in srgb, var(--ss-w-neg) 5%, transparent); border-radius: 8px; padding: 7px 6px; margin: 0 -6px; border-bottom: none; }
4696
+ .ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }
4697
+
4698
+ .ss-w-stale { font-size: 11px; font-weight: 600; color: var(--ss-w-cta); background: color-mix(in srgb, var(--ss-w-cta) 12%, var(--ss-w-panel)); border-radius: 8px; padding: 6px 9px; }
4301
4699
  `;
4302
4700
 
4303
4701
  // src/StatsWidget.tsx
4304
- import { jsx as jsx50 } from "react/jsx-runtime";
4702
+ import { jsx as jsx53 } from "react/jsx-runtime";
4305
4703
  function buildClient(props) {
4306
4704
  try {
4307
4705
  if ("client" in props && props.client) {
@@ -4326,22 +4724,61 @@ function injectStyles(root) {
4326
4724
  function StatsWidget(props) {
4327
4725
  const injectedClient = "client" in props ? props.client : void 0;
4328
4726
  const cfg = props.config;
4329
- const built = useMemo2(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
4330
- const ui = useMemo2(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
4331
- const rootRef = useRef8(null);
4332
- const introDoneRef = useRef8(false);
4333
- const markIntroDone = useCallback5(() => {
4727
+ const built = useMemo3(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
4728
+ const logger = useMemo3(
4729
+ () => built ? built.client.createEventLogger({
4730
+ operatorUserId: cfg?.userContext?.operatorUserId,
4731
+ anonymousUserId: cfg?.userContext?.anonymousUserId
4732
+ }) : null,
4733
+ [built?.client]
4734
+ );
4735
+ const ui = useMemo3(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
4736
+ const rootRef = useRef9(null);
4737
+ const introDoneRef = useRef9(false);
4738
+ const markIntroDone = useCallback6(() => {
4334
4739
  introDoneRef.current = true;
4335
4740
  }, []);
4336
4741
  const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
4337
4742
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
4743
+ const [hasToday, setHasToday] = useState20(false);
4338
4744
  const monitor = useLiveMonitor({
4339
4745
  getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
4340
4746
  getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
4341
4747
  storageKey: `ss-w-pins:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`,
4342
- isOpen: controller.state.isOpen
4748
+ isOpen: controller.state.isOpen,
4749
+ hasToday
4343
4750
  });
4344
- const slip = useMemo2(
4751
+ const getSchedule = useCallback6(
4752
+ (localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),
4753
+ [built]
4754
+ );
4755
+ const getStates = useCallback6(
4756
+ (matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
4757
+ [built]
4758
+ );
4759
+ const pinnedMatchIds = useMemo3(
4760
+ () => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
4761
+ [monitor.pins]
4762
+ );
4763
+ const discovery = useMatchDiscovery({
4764
+ getSchedule,
4765
+ getStates,
4766
+ operatorId: cfg?.operatorId ?? "",
4767
+ isOpen: controller.state.isOpen,
4768
+ pinnedMatchIds
4769
+ });
4770
+ const todayHasContent = discovery.groups.length > 0;
4771
+ useEffect12(() => {
4772
+ setHasToday(todayHasContent);
4773
+ }, [todayHasContent]);
4774
+ const markTodayActivity = monitor.markTodayActivity;
4775
+ const prevLiveCountRef = useRef9(0);
4776
+ useEffect12(() => {
4777
+ const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
4778
+ prevLiveCountRef.current = discovery.liveCount;
4779
+ if (rose) markTodayActivity();
4780
+ }, [discovery.liveCount, markTodayActivity]);
4781
+ const slip = useMemo3(
4345
4782
  () => {
4346
4783
  const handler = props.config?.onAddToSlip;
4347
4784
  return {
@@ -4364,18 +4801,42 @@ function StatsWidget(props) {
4364
4801
  },
4365
4802
  [props.config?.onAddToSlip, controller.state.conversationId, built, monitor.markInSlip]
4366
4803
  );
4367
- const onDashboardTap = useMemo2(
4368
- () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
4369
- [built]
4804
+ const onDashboardTap = useMemo3(
4805
+ () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
4806
+ [built, logger]
4370
4807
  );
4371
- useEffect11(() => {
4808
+ const operatorUserId = cfg?.userContext?.operatorUserId;
4809
+ const anonymousUserId = cfg?.userContext?.anonymousUserId;
4810
+ const conversationId = controller.state.conversationId ?? void 0;
4811
+ useEffect12(() => {
4812
+ if (!logger) return;
4813
+ logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
4814
+ }, [logger, operatorUserId, anonymousUserId, conversationId]);
4815
+ useEffect12(() => {
4816
+ if (!logger) return;
4817
+ const onHide = () => {
4818
+ logger.flushOnHide();
4819
+ };
4820
+ const onVisibilityHide = () => {
4821
+ if (document.visibilityState === "hidden") logger.flushOnHide();
4822
+ };
4823
+ window.addEventListener("pagehide", onHide);
4824
+ document.addEventListener("visibilitychange", onVisibilityHide);
4825
+ return () => {
4826
+ window.removeEventListener("pagehide", onHide);
4827
+ document.removeEventListener("visibilitychange", onVisibilityHide);
4828
+ logger.flushOnHide();
4829
+ logger.dispose();
4830
+ };
4831
+ }, [logger]);
4832
+ useEffect12(() => {
4372
4833
  if (!built || !ui.injectStyles) return;
4373
4834
  const node = rootRef.current?.getRootNode();
4374
4835
  if (node) injectStyles(node);
4375
4836
  }, [built, ui.injectStyles]);
4376
4837
  if (!built) return null;
4377
4838
  const attrs = themeAttrs(ui);
4378
- return /* @__PURE__ */ jsx50("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__ */ jsx50(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0 }) : /* @__PURE__ */ jsx50(
4839
+ return /* @__PURE__ */ jsx53(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ jsx53("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__ */ jsx53(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0, discovery }) : /* @__PURE__ */ jsx53(
4379
4840
  ChatFab,
4380
4841
  {
4381
4842
  label: ui.launcherLabel,
@@ -4388,7 +4849,7 @@ function StatsWidget(props) {
4388
4849
  introAllowed: !introDoneRef.current,
4389
4850
  onIntroStart: markIntroDone
4390
4851
  }
4391
- ) });
4852
+ ) }) });
4392
4853
  }
4393
4854
  function emptyConversation() {
4394
4855
  return { send: () => {