@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/CHANGELOG.md +24 -0
- package/dist/index.cjs +585 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +582 -121
- package/dist/index.js.map +1 -1
- package/dist/styles.css +34 -2
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/StatsWidget.tsx
|
|
39
|
-
var
|
|
39
|
+
var import_react26 = require("react");
|
|
40
40
|
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
41
41
|
|
|
42
42
|
// src/kickoff.ts
|
|
@@ -106,7 +106,7 @@ var STRINGS = {
|
|
|
106
106
|
tomorrow: "Tomorrow",
|
|
107
107
|
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, "en", now),
|
|
108
108
|
tabChat: "Chat",
|
|
109
|
-
|
|
109
|
+
tabFollowing: "Following",
|
|
110
110
|
tabOdds: "Odds",
|
|
111
111
|
pinLabel: "Track odds",
|
|
112
112
|
unpinLabel: "Stop tracking odds",
|
|
@@ -125,7 +125,10 @@ var STRINGS = {
|
|
|
125
125
|
momentumLabel: "Momentum",
|
|
126
126
|
accordionValueLabel: "Value",
|
|
127
127
|
accordionRetry: "Couldn't load odds \u2014 tap to retry",
|
|
128
|
-
accordionSuspended: "Suspended"
|
|
128
|
+
accordionSuspended: "Suspended",
|
|
129
|
+
tabToday: "Today",
|
|
130
|
+
sectionLive: "Live",
|
|
131
|
+
staleStates: "Live scores can't be updated \u2014 showing the last known state."
|
|
129
132
|
},
|
|
130
133
|
tr: {
|
|
131
134
|
launcherLabel: "SensibleStats ile sohbet et",
|
|
@@ -180,7 +183,7 @@ var STRINGS = {
|
|
|
180
183
|
tomorrow: "Yar\u0131n",
|
|
181
184
|
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, "tr", now),
|
|
182
185
|
tabChat: "Sohbet",
|
|
183
|
-
|
|
186
|
+
tabFollowing: "Takip",
|
|
184
187
|
tabOdds: "Oranlar",
|
|
185
188
|
pinLabel: "Oran\u0131 takip et",
|
|
186
189
|
unpinLabel: "Oran takibini b\u0131rak",
|
|
@@ -199,7 +202,10 @@ var STRINGS = {
|
|
|
199
202
|
momentumLabel: "Momentum",
|
|
200
203
|
accordionValueLabel: "De\u011Fer",
|
|
201
204
|
accordionRetry: "Oranlar y\xFCklenemedi \u2014 yeniden dene",
|
|
202
|
-
accordionSuspended: "Ask\u0131da"
|
|
205
|
+
accordionSuspended: "Ask\u0131da",
|
|
206
|
+
tabToday: "Bug\xFCn",
|
|
207
|
+
sectionLive: "Canl\u0131",
|
|
208
|
+
staleStates: "Canl\u0131 skorlar g\xFCncellenemiyor \u2014 son bilinen durum g\xF6steriliyor."
|
|
203
209
|
}
|
|
204
210
|
};
|
|
205
211
|
function resolveLocaleStrings(locale) {
|
|
@@ -273,8 +279,11 @@ function normalizeUi(cfg) {
|
|
|
273
279
|
tomorrow: strings.tomorrow,
|
|
274
280
|
bettingKickoff: strings.bettingKickoff,
|
|
275
281
|
tabChat: strings.tabChat,
|
|
276
|
-
|
|
282
|
+
tabFollowing: strings.tabFollowing,
|
|
277
283
|
tabOdds: strings.tabOdds,
|
|
284
|
+
tabToday: strings.tabToday,
|
|
285
|
+
sectionLive: strings.sectionLive,
|
|
286
|
+
staleStates: strings.staleStates,
|
|
278
287
|
pinLabel: strings.pinLabel,
|
|
279
288
|
unpinLabel: strings.unpinLabel,
|
|
280
289
|
matchPinLabel: strings.matchPinLabel,
|
|
@@ -316,6 +325,18 @@ function isTerminal(result) {
|
|
|
316
325
|
if (result.status === "price_changed") return result.accepted;
|
|
317
326
|
return result.status === "added" || result.status === "duplicate";
|
|
318
327
|
}
|
|
328
|
+
function slipOutcome(result) {
|
|
329
|
+
if (!result) return "added";
|
|
330
|
+
switch (result.status) {
|
|
331
|
+
case "added":
|
|
332
|
+
case "duplicate":
|
|
333
|
+
return result.status;
|
|
334
|
+
case "price_changed":
|
|
335
|
+
return result.accepted ? "added" : "price_changed";
|
|
336
|
+
case "rejected":
|
|
337
|
+
return result.reason;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
319
340
|
function resultToToast(result, shownOdds, ui) {
|
|
320
341
|
if (!result) return { kind: "success", text: ui.slipAdded };
|
|
321
342
|
switch (result.status) {
|
|
@@ -337,8 +358,28 @@ var import_widget_sdk = require("@sensiblestats/widget-sdk");
|
|
|
337
358
|
function isSignalEntityType(value) {
|
|
338
359
|
return Object.prototype.hasOwnProperty.call(import_widget_sdk.ENTITY_TYPE_CODES, value);
|
|
339
360
|
}
|
|
340
|
-
function
|
|
361
|
+
function toWidgetEntityType(value) {
|
|
362
|
+
switch (value.toLowerCase()) {
|
|
363
|
+
case "match":
|
|
364
|
+
return "match";
|
|
365
|
+
case "team":
|
|
366
|
+
return "team";
|
|
367
|
+
case "player":
|
|
368
|
+
return "player";
|
|
369
|
+
case "competition":
|
|
370
|
+
return "competition";
|
|
371
|
+
case "market":
|
|
372
|
+
return "market";
|
|
373
|
+
default:
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function createDashboardTapSignal(sendSignal, log) {
|
|
341
378
|
return (tile, index, layout) => {
|
|
379
|
+
const widgetEntityType = toWidgetEntityType(tile.signal.entityType);
|
|
380
|
+
if (widgetEntityType) {
|
|
381
|
+
log?.log({ name: "tile_tap", entityType: widgetEntityType, entityId: tile.signal.entityId });
|
|
382
|
+
}
|
|
342
383
|
if (!isSignalEntityType(tile.signal.entityType)) return;
|
|
343
384
|
try {
|
|
344
385
|
void sendSignal({
|
|
@@ -1183,6 +1224,7 @@ function useLiveMonitor(opts) {
|
|
|
1183
1224
|
const [chatDot, setChatDot] = (0, import_react3.useState)(false);
|
|
1184
1225
|
const [matchesDot, setMatchesDot] = (0, import_react3.useState)(false);
|
|
1185
1226
|
const [oddsDot, setOddsDot] = (0, import_react3.useState)(false);
|
|
1227
|
+
const [todayDot, setTodayDot] = (0, import_react3.useState)(false);
|
|
1186
1228
|
const [lastViewedPrices, setLastViewedPrices] = (0, import_react3.useState)({});
|
|
1187
1229
|
const [inSlip, setInSlip] = (0, import_react3.useState)({});
|
|
1188
1230
|
const [openMarket, setOpenMarket] = (0, import_react3.useState)({});
|
|
@@ -1199,6 +1241,7 @@ function useLiveMonitor(opts) {
|
|
|
1199
1241
|
openMarketRef.current = openMarket;
|
|
1200
1242
|
const marketOddsRef = (0, import_react3.useRef)(marketOdds);
|
|
1201
1243
|
marketOddsRef.current = marketOdds;
|
|
1244
|
+
const hasToday = opts.hasToday ?? false;
|
|
1202
1245
|
const marketKey = (matchId, dev) => `${matchId}:${dev}`;
|
|
1203
1246
|
const getMarketOddsRef = (0, import_react3.useRef)(opts.getMarketOdds);
|
|
1204
1247
|
getMarketOddsRef.current = opts.getMarketOdds;
|
|
@@ -1253,7 +1296,7 @@ function useLiveMonitor(opts) {
|
|
|
1253
1296
|
break;
|
|
1254
1297
|
}
|
|
1255
1298
|
}
|
|
1256
|
-
if (sawNewGoalOrRed && activeTabRef.current !== "
|
|
1299
|
+
if (sawNewGoalOrRed && activeTabRef.current !== "following") setMatchesDot(true);
|
|
1257
1300
|
for (const m of next.matches) {
|
|
1258
1301
|
if (!pinnedMatchIds.has(m.matchId)) continue;
|
|
1259
1302
|
const first = m.availableMarkets?.[0];
|
|
@@ -1339,11 +1382,17 @@ function useLiveMonitor(opts) {
|
|
|
1339
1382
|
prevPinsLengthRef.current = pins.length;
|
|
1340
1383
|
if (pins.length === 0) {
|
|
1341
1384
|
window.clearTimeout(timerRef.current);
|
|
1342
|
-
setActiveTabState("chat");
|
|
1343
1385
|
return;
|
|
1344
1386
|
}
|
|
1345
1387
|
if (wasEmpty) void tick();
|
|
1346
1388
|
}, [pins.length, tick]);
|
|
1389
|
+
(0, import_react3.useEffect)(() => {
|
|
1390
|
+
const matchPins = pins.filter((p) => p.kind === "match").length;
|
|
1391
|
+
const marketPins = pins.length - matchPins;
|
|
1392
|
+
if (activeTab === "following" && matchPins === 0) setActiveTabState(hasToday ? "today" : "chat");
|
|
1393
|
+
if (activeTab === "odds" && marketPins === 0) setActiveTabState(hasToday ? "today" : "chat");
|
|
1394
|
+
if (activeTab === "today" && !hasToday) setActiveTabState("chat");
|
|
1395
|
+
}, [pins, activeTab, hasToday]);
|
|
1347
1396
|
const prevIsOpenRef = (0, import_react3.useRef)(false);
|
|
1348
1397
|
(0, import_react3.useEffect)(() => {
|
|
1349
1398
|
const wasClosed = !prevIsOpenRef.current;
|
|
@@ -1364,7 +1413,8 @@ function useLiveMonitor(opts) {
|
|
|
1364
1413
|
const setActiveTab = (0, import_react3.useCallback)((tab) => {
|
|
1365
1414
|
setActiveTabState(tab);
|
|
1366
1415
|
if (tab === "chat") setChatDot(false);
|
|
1367
|
-
if (tab === "
|
|
1416
|
+
if (tab === "today") setTodayDot(false);
|
|
1417
|
+
if (tab === "following") {
|
|
1368
1418
|
setMatchesDot(false);
|
|
1369
1419
|
void tick();
|
|
1370
1420
|
}
|
|
@@ -1384,6 +1434,9 @@ function useLiveMonitor(opts) {
|
|
|
1384
1434
|
const togglePin = (0, import_react3.useCallback)((pin) => store.toggle(pin), [store]);
|
|
1385
1435
|
const isPinned = (0, import_react3.useCallback)((key) => pinsRef.current.some((p) => p.key === key), []);
|
|
1386
1436
|
const markChatActivity = (0, import_react3.useCallback)(() => setChatDot(true), []);
|
|
1437
|
+
const markTodayActivity = (0, import_react3.useCallback)(() => {
|
|
1438
|
+
if (activeTabRef.current !== "today") setTodayDot(true);
|
|
1439
|
+
}, []);
|
|
1387
1440
|
const markInSlip = (0, import_react3.useCallback)((matchOddsId) => {
|
|
1388
1441
|
setInSlip((prev) => prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true });
|
|
1389
1442
|
}, []);
|
|
@@ -1399,6 +1452,8 @@ function useLiveMonitor(opts) {
|
|
|
1399
1452
|
markChatActivity,
|
|
1400
1453
|
matchesDot,
|
|
1401
1454
|
oddsDot,
|
|
1455
|
+
todayDot,
|
|
1456
|
+
markTodayActivity,
|
|
1402
1457
|
lastViewedPrices,
|
|
1403
1458
|
inSlip,
|
|
1404
1459
|
markInSlip,
|
|
@@ -1410,11 +1465,198 @@ function useLiveMonitor(opts) {
|
|
|
1410
1465
|
};
|
|
1411
1466
|
}
|
|
1412
1467
|
|
|
1413
|
-
// src/
|
|
1468
|
+
// src/useMatchDiscovery.ts
|
|
1469
|
+
var import_react4 = require("react");
|
|
1470
|
+
|
|
1471
|
+
// src/scheduleCache.ts
|
|
1472
|
+
var PREFIX = "ss-w-schedule:";
|
|
1473
|
+
var SCHEMA_VERSION = 1;
|
|
1474
|
+
var TTL_MS2 = 6 * 36e5;
|
|
1475
|
+
function scheduleCacheKey(operatorId, localDate) {
|
|
1476
|
+
return `${PREFIX}${operatorId}:${localDate}`;
|
|
1477
|
+
}
|
|
1478
|
+
function read(operatorId, localDate) {
|
|
1479
|
+
try {
|
|
1480
|
+
const raw = localStorage.getItem(scheduleCacheKey(operatorId, localDate));
|
|
1481
|
+
if (!raw) return null;
|
|
1482
|
+
const entry = JSON.parse(raw);
|
|
1483
|
+
if (entry.v !== SCHEMA_VERSION || !entry.payload) return null;
|
|
1484
|
+
return entry;
|
|
1485
|
+
} catch {
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
function readSchedule(operatorId, localDate, nowMs) {
|
|
1490
|
+
const entry = read(operatorId, localDate);
|
|
1491
|
+
if (!entry) return null;
|
|
1492
|
+
return nowMs - entry.at > TTL_MS2 ? null : entry.payload;
|
|
1493
|
+
}
|
|
1494
|
+
function readScheduleIgnoringTtl(operatorId, localDate) {
|
|
1495
|
+
return read(operatorId, localDate)?.payload ?? null;
|
|
1496
|
+
}
|
|
1497
|
+
function skeletonOnly(payload) {
|
|
1498
|
+
return {
|
|
1499
|
+
localDate: payload.localDate,
|
|
1500
|
+
groups: payload.groups.map((g) => ({
|
|
1501
|
+
competitionId: g.competitionId,
|
|
1502
|
+
competitionName: g.competitionName,
|
|
1503
|
+
competitionImagePath: g.competitionImagePath ?? null,
|
|
1504
|
+
rank: g.rank,
|
|
1505
|
+
expandedByDefault: g.expandedByDefault,
|
|
1506
|
+
matches: g.matches.map((m) => ({
|
|
1507
|
+
matchId: m.matchId,
|
|
1508
|
+
homeTeamName: m.homeTeamName,
|
|
1509
|
+
awayTeamName: m.awayTeamName,
|
|
1510
|
+
homeTeamImagePath: m.homeTeamImagePath ?? null,
|
|
1511
|
+
awayTeamImagePath: m.awayTeamImagePath ?? null,
|
|
1512
|
+
kickoffUnix: m.kickoffUnix
|
|
1513
|
+
}))
|
|
1514
|
+
}))
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
function writeSchedule(operatorId, localDate, payload, nowMs) {
|
|
1518
|
+
const keep = scheduleCacheKey(operatorId, localDate);
|
|
1519
|
+
const mine = `${PREFIX}${operatorId}:`;
|
|
1520
|
+
try {
|
|
1521
|
+
for (let i = localStorage.length - 1; i >= 0; i--) {
|
|
1522
|
+
const key = localStorage.key(i);
|
|
1523
|
+
if (key && key.startsWith(mine) && key !== keep) localStorage.removeItem(key);
|
|
1524
|
+
}
|
|
1525
|
+
const entry = { v: SCHEMA_VERSION, at: nowMs, payload: skeletonOnly(payload) };
|
|
1526
|
+
localStorage.setItem(keep, JSON.stringify(entry));
|
|
1527
|
+
} catch {
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
// src/dueSet.ts
|
|
1532
|
+
var WINDOW_MS = 3.5 * 36e5;
|
|
1533
|
+
function dueMatchIds(groups, states, nowMs) {
|
|
1534
|
+
const due = /* @__PURE__ */ new Set();
|
|
1535
|
+
for (const group of groups) {
|
|
1536
|
+
for (const match of group.matches) {
|
|
1537
|
+
const sinceKickoff = nowMs - match.kickoffUnix * 1e3;
|
|
1538
|
+
if (sinceKickoff >= 0 && sinceKickoff <= WINDOW_MS) due.add(match.matchId);
|
|
1539
|
+
if (states[match.matchId]?.phase === "live") due.add(match.matchId);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
return [...due];
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// src/useMatchDiscovery.ts
|
|
1546
|
+
var POLL_MS = 6e4;
|
|
1547
|
+
var ROLLOVER_CHECK_MS = 6e4;
|
|
1548
|
+
var STALE_AFTER_FAILURES = 2;
|
|
1549
|
+
function localDateOf(now) {
|
|
1550
|
+
const y = now.getFullYear();
|
|
1551
|
+
const m = `${now.getMonth() + 1}`.padStart(2, "0");
|
|
1552
|
+
const d = `${now.getDate()}`.padStart(2, "0");
|
|
1553
|
+
return `${y}-${m}-${d}`;
|
|
1554
|
+
}
|
|
1555
|
+
function useMatchDiscovery(opts) {
|
|
1556
|
+
const [groups, setGroups] = (0, import_react4.useState)([]);
|
|
1557
|
+
const [states, setStates] = (0, import_react4.useState)({});
|
|
1558
|
+
const [failures, setFailures] = (0, import_react4.useState)(0);
|
|
1559
|
+
const [expanded, setExpanded] = (0, import_react4.useState)({});
|
|
1560
|
+
const [touched, setTouched] = (0, import_react4.useState)({});
|
|
1561
|
+
const groupsRef = (0, import_react4.useRef)(groups);
|
|
1562
|
+
groupsRef.current = groups;
|
|
1563
|
+
const statesRef = (0, import_react4.useRef)(states);
|
|
1564
|
+
statesRef.current = states;
|
|
1565
|
+
const getStatesRef = (0, import_react4.useRef)(opts.getStates);
|
|
1566
|
+
getStatesRef.current = opts.getStates;
|
|
1567
|
+
const pinnedKey = opts.pinnedMatchIds.join(",");
|
|
1568
|
+
const [localDate, setLocalDate] = (0, import_react4.useState)(() => localDateOf(/* @__PURE__ */ new Date()));
|
|
1569
|
+
(0, import_react4.useEffect)(() => {
|
|
1570
|
+
const id = setInterval(() => {
|
|
1571
|
+
const next = localDateOf(/* @__PURE__ */ new Date());
|
|
1572
|
+
setLocalDate((prev) => prev === next ? prev : next);
|
|
1573
|
+
}, ROLLOVER_CHECK_MS);
|
|
1574
|
+
return () => clearInterval(id);
|
|
1575
|
+
}, []);
|
|
1576
|
+
(0, import_react4.useEffect)(() => {
|
|
1577
|
+
let cancelled = false;
|
|
1578
|
+
const utcOffsetMinutes = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
1579
|
+
const cached = readSchedule(opts.operatorId, localDate, Date.now());
|
|
1580
|
+
if (cached) {
|
|
1581
|
+
if (!cancelled) setGroups(cached.groups);
|
|
1582
|
+
return () => {
|
|
1583
|
+
cancelled = true;
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
void (async () => {
|
|
1587
|
+
try {
|
|
1588
|
+
const payload = await opts.getSchedule(localDate, utcOffsetMinutes);
|
|
1589
|
+
if (cancelled || !payload) return;
|
|
1590
|
+
writeSchedule(opts.operatorId, localDate, payload, Date.now());
|
|
1591
|
+
setGroups(payload.groups);
|
|
1592
|
+
} catch {
|
|
1593
|
+
const fallback = readScheduleIgnoringTtl(opts.operatorId, localDate);
|
|
1594
|
+
if (!cancelled && fallback) setGroups(fallback.groups);
|
|
1595
|
+
}
|
|
1596
|
+
})();
|
|
1597
|
+
return () => {
|
|
1598
|
+
cancelled = true;
|
|
1599
|
+
};
|
|
1600
|
+
}, [opts.operatorId, localDate]);
|
|
1601
|
+
(0, import_react4.useEffect)(() => {
|
|
1602
|
+
setExpanded((prev) => {
|
|
1603
|
+
const next = {};
|
|
1604
|
+
for (const group of groups) {
|
|
1605
|
+
const hasPin = group.matches.some((m) => opts.pinnedMatchIds.includes(m.matchId));
|
|
1606
|
+
const seeded = group.expandedByDefault || hasPin;
|
|
1607
|
+
next[group.competitionId] = touched[group.competitionId] ? prev[group.competitionId] ?? seeded : seeded;
|
|
1608
|
+
}
|
|
1609
|
+
return next;
|
|
1610
|
+
});
|
|
1611
|
+
}, [groups, pinnedKey, touched]);
|
|
1612
|
+
const tick = (0, import_react4.useCallback)(async () => {
|
|
1613
|
+
const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now());
|
|
1614
|
+
if (ids.length === 0) return;
|
|
1615
|
+
try {
|
|
1616
|
+
const payload = await getStatesRef.current(ids);
|
|
1617
|
+
if (!payload) return;
|
|
1618
|
+
setStates((prev) => {
|
|
1619
|
+
const next = { ...prev };
|
|
1620
|
+
for (const state of payload.states) next[state.matchId] = state;
|
|
1621
|
+
return next;
|
|
1622
|
+
});
|
|
1623
|
+
setFailures(0);
|
|
1624
|
+
} catch {
|
|
1625
|
+
setFailures((n) => n + 1);
|
|
1626
|
+
}
|
|
1627
|
+
}, []);
|
|
1628
|
+
(0, import_react4.useEffect)(() => {
|
|
1629
|
+
if (!opts.isOpen) return;
|
|
1630
|
+
void tick();
|
|
1631
|
+
const id = setInterval(() => {
|
|
1632
|
+
void tick();
|
|
1633
|
+
}, POLL_MS);
|
|
1634
|
+
return () => clearInterval(id);
|
|
1635
|
+
}, [opts.isOpen, tick, groups]);
|
|
1636
|
+
const stale = failures >= STALE_AFTER_FAILURES;
|
|
1637
|
+
const liveCount = (0, import_react4.useMemo)(
|
|
1638
|
+
() => stale ? 0 : Object.values(states).filter((s) => s.phase === "live").length,
|
|
1639
|
+
[states, stale]
|
|
1640
|
+
);
|
|
1641
|
+
const toggleGroup = (0, import_react4.useCallback)((competitionId) => {
|
|
1642
|
+
setTouched((prev) => ({ ...prev, [competitionId]: true }));
|
|
1643
|
+
setExpanded((prev) => ({ ...prev, [competitionId]: !prev[competitionId] }));
|
|
1644
|
+
}, []);
|
|
1645
|
+
return { groups, states, liveCount, stale, expanded, toggleGroup, _tick: tick };
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
// src/eventLogContext.ts
|
|
1414
1649
|
var import_react5 = require("react");
|
|
1650
|
+
var EventLogContext = (0, import_react5.createContext)(null);
|
|
1651
|
+
function useEventLog() {
|
|
1652
|
+
return (0, import_react5.useContext)(EventLogContext);
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
// src/components/ChatFab.tsx
|
|
1656
|
+
var import_react7 = require("react");
|
|
1415
1657
|
|
|
1416
1658
|
// src/components/BrandMark.tsx
|
|
1417
|
-
var
|
|
1659
|
+
var import_react6 = require("react");
|
|
1418
1660
|
|
|
1419
1661
|
// src/assets/logo.ts
|
|
1420
1662
|
var SS_LOGO_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0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";
|
|
@@ -1463,7 +1705,7 @@ function DashboardIcon({ name }) {
|
|
|
1463
1705
|
// src/components/BrandMark.tsx
|
|
1464
1706
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1465
1707
|
function BrandMark({ logoUrl, className }) {
|
|
1466
|
-
const [failed, setFailed] = (0,
|
|
1708
|
+
const [failed, setFailed] = (0, import_react6.useState)(false);
|
|
1467
1709
|
if (!logoUrl || failed) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SsMark, { className });
|
|
1468
1710
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { className, src: logoUrl, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1469
1711
|
}
|
|
@@ -1488,9 +1730,9 @@ function GreetingBubble({ text, onOpen, onDismiss, dismissLabel = "Dismiss" }) {
|
|
|
1488
1730
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1489
1731
|
function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = "Dismiss", introAllowed = false, onIntroStart }) {
|
|
1490
1732
|
const bubble = popupText ?? greeting;
|
|
1491
|
-
const [intro, setIntro] = (0,
|
|
1492
|
-
const armedRef = (0,
|
|
1493
|
-
(0,
|
|
1733
|
+
const [intro, setIntro] = (0, import_react7.useState)(false);
|
|
1734
|
+
const armedRef = (0, import_react7.useRef)(introAllowed);
|
|
1735
|
+
(0, import_react7.useEffect)(() => {
|
|
1494
1736
|
if (armedRef.current && bubble) {
|
|
1495
1737
|
armedRef.current = false;
|
|
1496
1738
|
setIntro(true);
|
|
@@ -1504,10 +1746,10 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
|
|
|
1504
1746
|
}
|
|
1505
1747
|
|
|
1506
1748
|
// src/components/ChatPanel.tsx
|
|
1507
|
-
var
|
|
1749
|
+
var import_react25 = require("react");
|
|
1508
1750
|
|
|
1509
1751
|
// src/components/ChatHeader.tsx
|
|
1510
|
-
var
|
|
1752
|
+
var import_react8 = require("react");
|
|
1511
1753
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1512
1754
|
function ChatHeader({
|
|
1513
1755
|
onClose,
|
|
@@ -1519,15 +1761,15 @@ function ChatHeader({
|
|
|
1519
1761
|
newConversationLabel = "New conversation",
|
|
1520
1762
|
moreOptionsLabel = "More options"
|
|
1521
1763
|
}) {
|
|
1522
|
-
const [menuOpen, setMenuOpen] = (0,
|
|
1523
|
-
const wrapRef = (0,
|
|
1524
|
-
const kebabRef = (0,
|
|
1525
|
-
const firstItemRef = (0,
|
|
1764
|
+
const [menuOpen, setMenuOpen] = (0, import_react8.useState)(false);
|
|
1765
|
+
const wrapRef = (0, import_react8.useRef)(null);
|
|
1766
|
+
const kebabRef = (0, import_react8.useRef)(null);
|
|
1767
|
+
const firstItemRef = (0, import_react8.useRef)(null);
|
|
1526
1768
|
const hasMenu = !!(canReset && onNewConversation);
|
|
1527
|
-
(0,
|
|
1769
|
+
(0, import_react8.useEffect)(() => {
|
|
1528
1770
|
if (menuOpen) firstItemRef.current?.focus();
|
|
1529
1771
|
}, [menuOpen]);
|
|
1530
|
-
(0,
|
|
1772
|
+
(0, import_react8.useEffect)(() => {
|
|
1531
1773
|
if (!menuOpen) return;
|
|
1532
1774
|
const onPointer = (e) => {
|
|
1533
1775
|
if (!wrapRef.current?.contains(e.target)) setMenuOpen(false);
|
|
@@ -1583,7 +1825,7 @@ function ChatHeader({
|
|
|
1583
1825
|
}
|
|
1584
1826
|
|
|
1585
1827
|
// src/components/MessageList.tsx
|
|
1586
|
-
var
|
|
1828
|
+
var import_react23 = require("react");
|
|
1587
1829
|
|
|
1588
1830
|
// src/components/Markdown.tsx
|
|
1589
1831
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
@@ -1601,7 +1843,7 @@ function Markdown({ text }) {
|
|
|
1601
1843
|
}
|
|
1602
1844
|
|
|
1603
1845
|
// src/components/EntityCardList.tsx
|
|
1604
|
-
var
|
|
1846
|
+
var import_react9 = require("react");
|
|
1605
1847
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1606
1848
|
var MAX_VISIBLE = 3;
|
|
1607
1849
|
var RECORD_RE = /^(\d+)-(\d+)-(\d+)$/;
|
|
@@ -1685,7 +1927,7 @@ function ScopeTabs({ scopes, active, onSelect }) {
|
|
|
1685
1927
|
)) });
|
|
1686
1928
|
}
|
|
1687
1929
|
function EntityCardItem({ c }) {
|
|
1688
|
-
const [active, setActive] = (0,
|
|
1930
|
+
const [active, setActive] = (0, import_react9.useState)(0);
|
|
1689
1931
|
const hasBody = c.scopes.length > 0;
|
|
1690
1932
|
if (!hasBody) {
|
|
1691
1933
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ss-w-ecard ss-w-ecard-bare", "data-kind": c.kind, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardHeader, { c, showScopeCrest: false }) });
|
|
@@ -1699,7 +1941,7 @@ function EntityCardItem({ c }) {
|
|
|
1699
1941
|
] });
|
|
1700
1942
|
}
|
|
1701
1943
|
function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMoreLabel = (n) => `Show ${n} more` }) {
|
|
1702
|
-
const [expanded, setExpanded] = (0,
|
|
1944
|
+
const [expanded, setExpanded] = (0, import_react9.useState)(false);
|
|
1703
1945
|
if (cards.length === 0) return null;
|
|
1704
1946
|
const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE);
|
|
1705
1947
|
const overflow = cards.length - MAX_VISIBLE;
|
|
@@ -1710,18 +1952,18 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
1710
1952
|
}
|
|
1711
1953
|
|
|
1712
1954
|
// src/components/BettingInsightList.tsx
|
|
1713
|
-
var
|
|
1955
|
+
var import_react14 = require("react");
|
|
1714
1956
|
|
|
1715
1957
|
// src/components/AddToSlipButton.tsx
|
|
1716
|
-
var
|
|
1958
|
+
var import_react11 = require("react");
|
|
1717
1959
|
var import_widget_sdk4 = require("@sensiblestats/widget-sdk");
|
|
1718
1960
|
|
|
1719
1961
|
// src/components/Toast.tsx
|
|
1720
|
-
var
|
|
1962
|
+
var import_react10 = require("react");
|
|
1721
1963
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1722
1964
|
var DISMISS_MS = 4e3;
|
|
1723
1965
|
function Toast({ toast, onDismiss }) {
|
|
1724
|
-
(0,
|
|
1966
|
+
(0, import_react10.useEffect)(() => {
|
|
1725
1967
|
if (!toast) return;
|
|
1726
1968
|
const timer = setTimeout(onDismiss, DISMISS_MS);
|
|
1727
1969
|
return () => clearTimeout(timer);
|
|
@@ -1738,19 +1980,32 @@ function withTimeout(value) {
|
|
|
1738
1980
|
new Promise((_, reject) => setTimeout(() => reject(new Error("add-to-slip timed out")), ADD_TO_SLIP_TIMEOUT_MS))
|
|
1739
1981
|
]);
|
|
1740
1982
|
}
|
|
1741
|
-
function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
|
|
1742
|
-
const [pending, setPending] = (0,
|
|
1743
|
-
const [settled, setSettled] = (0,
|
|
1744
|
-
const [toast, setToast] = (0,
|
|
1745
|
-
const dismiss = (0,
|
|
1983
|
+
function SlipButton({ selection, shownOdds, marketName, marketDeveloperName, slip, ui }) {
|
|
1984
|
+
const [pending, setPending] = (0, import_react11.useState)(false);
|
|
1985
|
+
const [settled, setSettled] = (0, import_react11.useState)(false);
|
|
1986
|
+
const [toast, setToast] = (0, import_react11.useState)(null);
|
|
1987
|
+
const dismiss = (0, import_react11.useCallback)(() => setToast(null), []);
|
|
1988
|
+
const log = useEventLog();
|
|
1746
1989
|
const handler = slip.onAddToSlip;
|
|
1747
1990
|
if (!ui || !handler || !selection) return null;
|
|
1748
1991
|
const onClick = async () => {
|
|
1749
1992
|
setPending(true);
|
|
1993
|
+
if (marketDeveloperName !== void 0) {
|
|
1994
|
+
log?.log({ name: "slip_click", entityType: "market", marketDeveloperName, entityId: marketDeveloperName });
|
|
1995
|
+
}
|
|
1750
1996
|
try {
|
|
1751
1997
|
const raw = await withTimeout(Promise.resolve(handler(selection)));
|
|
1752
1998
|
if (raw != null && !(0, import_widget_sdk4.isAddToSlipResult)(raw)) throw new Error("malformed add-to-slip result");
|
|
1753
1999
|
const result = raw ?? void 0;
|
|
2000
|
+
if (marketDeveloperName !== void 0) {
|
|
2001
|
+
log?.log({
|
|
2002
|
+
name: "slip_result",
|
|
2003
|
+
entityType: "market",
|
|
2004
|
+
marketDeveloperName,
|
|
2005
|
+
entityId: marketDeveloperName,
|
|
2006
|
+
outcome: slipOutcome(result)
|
|
2007
|
+
});
|
|
2008
|
+
}
|
|
1754
2009
|
setToast(resultToToast(result, shownOdds || selection.oddsDecimal.toFixed(2), ui));
|
|
1755
2010
|
setSettled(isTerminal(result));
|
|
1756
2011
|
if (wasAdded(result) && slip.onMarketClicked) {
|
|
@@ -1760,6 +2015,9 @@ function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
|
|
|
1760
2015
|
}
|
|
1761
2016
|
}
|
|
1762
2017
|
} catch {
|
|
2018
|
+
if (marketDeveloperName !== void 0) {
|
|
2019
|
+
log?.log({ name: "slip_result", entityType: "market", marketDeveloperName, entityId: marketDeveloperName, outcome: "timeout" });
|
|
2020
|
+
}
|
|
1763
2021
|
setToast({ kind: "error", text: ui.slipFailed });
|
|
1764
2022
|
} finally {
|
|
1765
2023
|
setPending(false);
|
|
@@ -1781,7 +2039,17 @@ function SlipButton({ selection, shownOdds, marketName, slip, ui }) {
|
|
|
1781
2039
|
}
|
|
1782
2040
|
function AddToSlipButton({ it, slip, ui }) {
|
|
1783
2041
|
const selection = it.addToSlipEnabled ? toSlipSelection(it, slip.conversationId) : null;
|
|
1784
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2043
|
+
SlipButton,
|
|
2044
|
+
{
|
|
2045
|
+
selection,
|
|
2046
|
+
shownOdds: it.odds ?? "",
|
|
2047
|
+
marketName: it.market,
|
|
2048
|
+
marketDeveloperName: it.marketDeveloperName,
|
|
2049
|
+
slip,
|
|
2050
|
+
ui
|
|
2051
|
+
}
|
|
2052
|
+
);
|
|
1785
2053
|
}
|
|
1786
2054
|
|
|
1787
2055
|
// src/components/OddsMovementBadge.tsx
|
|
@@ -1806,14 +2074,14 @@ function OddsMovementBadge({
|
|
|
1806
2074
|
}
|
|
1807
2075
|
|
|
1808
2076
|
// src/components/Crest.tsx
|
|
1809
|
-
var
|
|
2077
|
+
var import_react12 = require("react");
|
|
1810
2078
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1811
2079
|
function initials2(name) {
|
|
1812
2080
|
return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
|
|
1813
2081
|
}
|
|
1814
2082
|
function Crest2({ url, name, kind }) {
|
|
1815
2083
|
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
1816
|
-
const [failed, setFailed] = (0,
|
|
2084
|
+
const [failed, setFailed] = (0, import_react12.useState)(false);
|
|
1817
2085
|
if (url && !failed) {
|
|
1818
2086
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1819
2087
|
}
|
|
@@ -1821,7 +2089,7 @@ function Crest2({ url, name, kind }) {
|
|
|
1821
2089
|
}
|
|
1822
2090
|
|
|
1823
2091
|
// src/components/PinToggle.tsx
|
|
1824
|
-
var
|
|
2092
|
+
var import_react13 = require("react");
|
|
1825
2093
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1826
2094
|
var PIN_GLYPHS = {
|
|
1827
2095
|
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" },
|
|
@@ -1829,15 +2097,23 @@ var PIN_GLYPHS = {
|
|
|
1829
2097
|
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" }
|
|
1830
2098
|
};
|
|
1831
2099
|
function PinToggle({ pin, monitor, ui }) {
|
|
1832
|
-
const [toast, setToast] = (0,
|
|
1833
|
-
const dismiss = (0,
|
|
2100
|
+
const [toast, setToast] = (0, import_react13.useState)(null);
|
|
2101
|
+
const dismiss = (0, import_react13.useCallback)(() => setToast(null), []);
|
|
2102
|
+
const log = useEventLog();
|
|
1834
2103
|
if (!monitor || !monitor.enabled) return null;
|
|
1835
2104
|
const key = pinKey(pin);
|
|
1836
2105
|
const pinned = monitor.isPinned(key);
|
|
1837
2106
|
const labels = pin.kind === "match" ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel } : { pin: ui.pinLabel, unpin: ui.unpinLabel };
|
|
1838
2107
|
const onClick = () => {
|
|
1839
2108
|
const result = monitor.togglePin({ ...pin, key });
|
|
1840
|
-
if (result === "
|
|
2109
|
+
if ((result === "added" || result === "removed") && (pin.kind === "match" || pin.marketDeveloperName !== void 0)) {
|
|
2110
|
+
log?.log({
|
|
2111
|
+
name: result === "added" ? "pin_add" : "pin_remove",
|
|
2112
|
+
entityType: pin.kind === "match" ? "match" : "market",
|
|
2113
|
+
entityId: pin.kind === "match" ? String(pin.matchId) : pin.marketDeveloperName,
|
|
2114
|
+
marketDeveloperName: pin.marketDeveloperName
|
|
2115
|
+
});
|
|
2116
|
+
} else if (result === "match_limit") {
|
|
1841
2117
|
setToast({ kind: "error", text: ui.matchLimitToast });
|
|
1842
2118
|
} else if (result === "market_limit") {
|
|
1843
2119
|
setToast({ kind: "error", text: ui.marketLimitToast });
|
|
@@ -1882,7 +2158,7 @@ function StatRows({ stats }) {
|
|
|
1882
2158
|
] }, `${s.label}:${s.value}`)) });
|
|
1883
2159
|
}
|
|
1884
2160
|
function ScopedStats({ scopes }) {
|
|
1885
|
-
const [active, setActive] = (0,
|
|
2161
|
+
const [active, setActive] = (0, import_react14.useState)(0);
|
|
1886
2162
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
1887
2163
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-bi-scoped", children: [
|
|
1888
2164
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
@@ -1893,12 +2169,20 @@ function hasStatsContent(it) {
|
|
|
1893
2169
|
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
1894
2170
|
}
|
|
1895
2171
|
function ReasonStrip({ it, ui }) {
|
|
1896
|
-
const [open, setOpen] = (0,
|
|
2172
|
+
const [open, setOpen] = (0, import_react14.useState)(false);
|
|
2173
|
+
const log = useEventLog();
|
|
1897
2174
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
1898
2175
|
const hasStats = hasStatsContent(it);
|
|
1899
2176
|
const hasText = !!it.text;
|
|
1900
2177
|
if (!hasText && !hasStats) return null;
|
|
1901
2178
|
const expandable = hasStats || (it.text?.length ?? 0) > 90;
|
|
2179
|
+
const onToggle = () => {
|
|
2180
|
+
setOpen((v) => {
|
|
2181
|
+
const next = !v;
|
|
2182
|
+
if (next) log?.log({ name: "insight_expand", entityType: "match", entityId: String(it.matchId) });
|
|
2183
|
+
return next;
|
|
2184
|
+
});
|
|
2185
|
+
};
|
|
1902
2186
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-bi-reason", children: [
|
|
1903
2187
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1904
2188
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-bi-reason-body", children: [
|
|
@@ -1912,7 +2196,7 @@ function ReasonStrip({ it, ui }) {
|
|
|
1912
2196
|
className: "ss-w-bi-expand",
|
|
1913
2197
|
"aria-expanded": open,
|
|
1914
2198
|
"aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
|
|
1915
|
-
onClick:
|
|
2199
|
+
onClick: onToggle,
|
|
1916
2200
|
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
|
|
1917
2201
|
}
|
|
1918
2202
|
) : null
|
|
@@ -2005,7 +2289,7 @@ function BettingInsightList({ insights, ui, slip, monitor }) {
|
|
|
2005
2289
|
}
|
|
2006
2290
|
|
|
2007
2291
|
// src/components/MarketOddsCardList.tsx
|
|
2008
|
-
var
|
|
2292
|
+
var import_react15 = require("react");
|
|
2009
2293
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2010
2294
|
function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
2011
2295
|
const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
|
|
@@ -2018,11 +2302,11 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
|
2018
2302
|
"\u2713 ",
|
|
2019
2303
|
ui.inSlipLabel
|
|
2020
2304
|
] }) : null,
|
|
2021
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, marketDeveloperName: vm.marketDeveloperName, slip, ui })
|
|
2022
2306
|
] });
|
|
2023
2307
|
}
|
|
2024
2308
|
function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }) {
|
|
2025
|
-
const [open, setOpen] = (0,
|
|
2309
|
+
const [open, setOpen] = (0, import_react15.useState)(false);
|
|
2026
2310
|
const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
|
|
2027
2311
|
const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : void 0);
|
|
2028
2312
|
const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
|
|
@@ -2325,7 +2609,7 @@ function FixtureCard({ card }) {
|
|
|
2325
2609
|
}
|
|
2326
2610
|
|
|
2327
2611
|
// src/components/dashboard/CountdownCard.tsx
|
|
2328
|
-
var
|
|
2612
|
+
var import_react16 = require("react");
|
|
2329
2613
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2330
2614
|
var DAY_MS = 864e5;
|
|
2331
2615
|
function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
@@ -2344,12 +2628,12 @@ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
|
2344
2628
|
function CountdownCard({ card }) {
|
|
2345
2629
|
const { data } = card;
|
|
2346
2630
|
const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
|
|
2347
|
-
const [nowMs, setNowMs] = (0,
|
|
2348
|
-
const [reduced] = (0,
|
|
2631
|
+
const [nowMs, setNowMs] = (0, import_react16.useState)(() => Date.now());
|
|
2632
|
+
const [reduced] = (0, import_react16.useState)(
|
|
2349
2633
|
() => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
2350
2634
|
);
|
|
2351
2635
|
const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
|
|
2352
|
-
(0,
|
|
2636
|
+
(0, import_react16.useEffect)(() => {
|
|
2353
2637
|
if (reduced) return;
|
|
2354
2638
|
const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
|
|
2355
2639
|
return () => window.clearInterval(id);
|
|
@@ -2357,7 +2641,7 @@ function CountdownCard({ card }) {
|
|
|
2357
2641
|
const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced);
|
|
2358
2642
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "ss-w-fandash-card ss-w-fandash-countdown", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-fandash-countdown-top", children: [
|
|
2359
2643
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title ?? "Kick-off in" }),
|
|
2360
|
-
segments ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-fandash-countdown-clock", children: segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2644
|
+
segments ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-fandash-countdown-clock", children: segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react16.Fragment, { children: [
|
|
2361
2645
|
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-fandash-countdown-colon", children: ":" }) : null,
|
|
2362
2646
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-fandash-countdown-seg", children: [
|
|
2363
2647
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-fandash-countdown-value", children: s.value }),
|
|
@@ -2368,7 +2652,7 @@ function CountdownCard({ card }) {
|
|
|
2368
2652
|
}
|
|
2369
2653
|
|
|
2370
2654
|
// src/components/dashboard/InjuriesCard.tsx
|
|
2371
|
-
var
|
|
2655
|
+
var import_react17 = require("react");
|
|
2372
2656
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2373
2657
|
var SHOWN = 3;
|
|
2374
2658
|
function ColHead({ name, crestUrl }) {
|
|
@@ -2391,7 +2675,7 @@ function InjuryList({ rows, emptyLabel, limit }) {
|
|
|
2391
2675
|
}
|
|
2392
2676
|
function InjuriesCard({ card, ui }) {
|
|
2393
2677
|
const { data } = card;
|
|
2394
|
-
const [expanded, setExpanded] = (0,
|
|
2678
|
+
const [expanded, setExpanded] = (0, import_react17.useState)(false);
|
|
2395
2679
|
const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
|
|
2396
2680
|
const limit = expanded ? void 0 : SHOWN;
|
|
2397
2681
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
@@ -2495,7 +2779,7 @@ function LinksCard({ card }) {
|
|
|
2495
2779
|
}
|
|
2496
2780
|
|
|
2497
2781
|
// src/components/dashboard/PostMatchResultCard.tsx
|
|
2498
|
-
var
|
|
2782
|
+
var import_react18 = require("react");
|
|
2499
2783
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2500
2784
|
function initials3(name) {
|
|
2501
2785
|
return name.trim().slice(0, 3).toUpperCase();
|
|
@@ -2505,7 +2789,7 @@ function PostMatchCrest({
|
|
|
2505
2789
|
name,
|
|
2506
2790
|
side
|
|
2507
2791
|
}) {
|
|
2508
|
-
const [failed, setFailed] = (0,
|
|
2792
|
+
const [failed, setFailed] = (0, import_react18.useState)(false);
|
|
2509
2793
|
const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
|
|
2510
2794
|
if (url && !failed) {
|
|
2511
2795
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
@@ -2704,10 +2988,10 @@ function RestingFormCard({ card }) {
|
|
|
2704
2988
|
}
|
|
2705
2989
|
|
|
2706
2990
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
2707
|
-
var
|
|
2991
|
+
var import_react20 = require("react");
|
|
2708
2992
|
|
|
2709
2993
|
// src/useLiveClock.ts
|
|
2710
|
-
var
|
|
2994
|
+
var import_react19 = require("react");
|
|
2711
2995
|
var TICK_MS = 6e4;
|
|
2712
2996
|
var MAX_LIVE_TICK_MINUTES = 15;
|
|
2713
2997
|
function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
@@ -2716,10 +3000,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
|
2716
3000
|
return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
|
|
2717
3001
|
}
|
|
2718
3002
|
function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
2719
|
-
const [displayMinute, setDisplayMinute] = (0,
|
|
3003
|
+
const [displayMinute, setDisplayMinute] = (0, import_react19.useState)(
|
|
2720
3004
|
() => computeDisplayMinute(minute, clockRunning, receivedAtMs)
|
|
2721
3005
|
);
|
|
2722
|
-
(0,
|
|
3006
|
+
(0, import_react19.useEffect)(() => {
|
|
2723
3007
|
setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
|
|
2724
3008
|
if (!clockRunning) return;
|
|
2725
3009
|
const id = window.setInterval(() => {
|
|
@@ -2736,7 +3020,7 @@ function initials5(name) {
|
|
|
2736
3020
|
return name.trim().slice(0, 3).toUpperCase();
|
|
2737
3021
|
}
|
|
2738
3022
|
function LiveCrest({ url, name, side }) {
|
|
2739
|
-
const [failed, setFailed] = (0,
|
|
3023
|
+
const [failed, setFailed] = (0, import_react20.useState)(false);
|
|
2740
3024
|
const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
|
|
2741
3025
|
if (url && !failed) {
|
|
2742
3026
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
@@ -2755,7 +3039,7 @@ function LiveScoreCard({
|
|
|
2755
3039
|
}) {
|
|
2756
3040
|
const { data } = card;
|
|
2757
3041
|
const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
|
|
2758
|
-
const seedRef = (0,
|
|
3042
|
+
const seedRef = (0, import_react20.useRef)(null);
|
|
2759
3043
|
if (!seedRef.current || seedRef.current.key !== seedKey) {
|
|
2760
3044
|
seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
|
|
2761
3045
|
}
|
|
@@ -2795,7 +3079,7 @@ function LiveScoreCard({
|
|
|
2795
3079
|
}
|
|
2796
3080
|
|
|
2797
3081
|
// src/components/dashboard/LiveTimelineCard.tsx
|
|
2798
|
-
var
|
|
3082
|
+
var import_react21 = require("react");
|
|
2799
3083
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2800
3084
|
var SHOWN2 = 3;
|
|
2801
3085
|
function EventIcon({ type }) {
|
|
@@ -2837,7 +3121,7 @@ function EventRow({ e }) {
|
|
|
2837
3121
|
] });
|
|
2838
3122
|
}
|
|
2839
3123
|
function LiveTimelineCard({ card, ui }) {
|
|
2840
|
-
const [expanded, setExpanded] = (0,
|
|
3124
|
+
const [expanded, setExpanded] = (0, import_react21.useState)(false);
|
|
2841
3125
|
const events = card.data.events;
|
|
2842
3126
|
if (!events || events.length === 0) return null;
|
|
2843
3127
|
const sorted = [...events].sort((a, b) => b.minute - a.minute);
|
|
@@ -2862,7 +3146,7 @@ function LiveTimelineCard({ card, ui }) {
|
|
|
2862
3146
|
}
|
|
2863
3147
|
|
|
2864
3148
|
// src/components/dashboard/MomentumWave.tsx
|
|
2865
|
-
var
|
|
3149
|
+
var import_react22 = require("react");
|
|
2866
3150
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2867
3151
|
var WIDTH = 270;
|
|
2868
3152
|
var HEIGHT = 56;
|
|
@@ -2886,7 +3170,7 @@ function MomentumWave({
|
|
|
2886
3170
|
}) {
|
|
2887
3171
|
if (points.length === 0) return null;
|
|
2888
3172
|
const { area, line, lastLeftPct, lastTopPx } = buildPaths(points);
|
|
2889
|
-
const clipId = (0,
|
|
3173
|
+
const clipId = (0, import_react22.useId)();
|
|
2890
3174
|
const topClipId = `${clipId}-top`;
|
|
2891
3175
|
const bottomClipId = `${clipId}-bottom`;
|
|
2892
3176
|
const topClass = clubIsHome ? "ss-w-fandash-live-mom-home" : "ss-w-fandash-live-mom-away";
|
|
@@ -3077,11 +3361,11 @@ function turnAnchor(messages) {
|
|
|
3077
3361
|
}
|
|
3078
3362
|
function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
3079
3363
|
const { state, send } = controller;
|
|
3080
|
-
const listRef = (0,
|
|
3081
|
-
const endRef = (0,
|
|
3082
|
-
const pinnedRef = (0,
|
|
3083
|
-
const anchoredTurnRef = (0,
|
|
3084
|
-
(0,
|
|
3364
|
+
const listRef = (0, import_react23.useRef)(null);
|
|
3365
|
+
const endRef = (0, import_react23.useRef)(null);
|
|
3366
|
+
const pinnedRef = (0, import_react23.useRef)(true);
|
|
3367
|
+
const anchoredTurnRef = (0, import_react23.useRef)(null);
|
|
3368
|
+
(0, import_react23.useEffect)(() => {
|
|
3085
3369
|
const anchor = turnAnchor(state.messages);
|
|
3086
3370
|
const list = listRef.current;
|
|
3087
3371
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
@@ -3137,10 +3421,10 @@ function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
3137
3421
|
}
|
|
3138
3422
|
|
|
3139
3423
|
// src/components/ChatInput.tsx
|
|
3140
|
-
var
|
|
3424
|
+
var import_react24 = require("react");
|
|
3141
3425
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
3142
3426
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
3143
|
-
const [value, setValue] = (0,
|
|
3427
|
+
const [value, setValue] = (0, import_react24.useState)("");
|
|
3144
3428
|
const submit = () => {
|
|
3145
3429
|
const t = value.trim();
|
|
3146
3430
|
if (!t) return;
|
|
@@ -3161,22 +3445,16 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
3161
3445
|
|
|
3162
3446
|
// src/components/TabBar.tsx
|
|
3163
3447
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
]
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
chat: monitor.chatDot && monitor.activeTab !== "chat",
|
|
3174
|
-
matches: monitor.matchesDot && monitor.activeTab !== "matches",
|
|
3175
|
-
odds: monitor.oddsDot && monitor.activeTab !== "odds"
|
|
3176
|
-
};
|
|
3177
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "ss-w-tabs", role: "tablist", children: TABS.map(({ tab, labelKey }) => {
|
|
3448
|
+
function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday }) {
|
|
3449
|
+
const tabs = [
|
|
3450
|
+
{ tab: "chat", label: ui.tabChat, count: 0, dot: monitor.chatDot },
|
|
3451
|
+
...hasToday ? [{ tab: "today", label: ui.tabToday, count: todayCount, dot: monitor.todayDot }] : [],
|
|
3452
|
+
...matchCount > 0 ? [{ tab: "following", label: ui.tabFollowing, count: matchCount, dot: monitor.matchesDot }] : [],
|
|
3453
|
+
...oddsCount > 0 ? [{ tab: "odds", label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : []
|
|
3454
|
+
];
|
|
3455
|
+
if (tabs.length < 2) return null;
|
|
3456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "ss-w-tabs", role: "tablist", children: tabs.map(({ tab, label, count, dot }) => {
|
|
3178
3457
|
const active = monitor.activeTab === tab;
|
|
3179
|
-
const count = counts[tab];
|
|
3180
3458
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
3181
3459
|
"button",
|
|
3182
3460
|
{
|
|
@@ -3187,9 +3465,9 @@ function TabBar({ monitor, ui, matchCount, oddsCount }) {
|
|
|
3187
3465
|
className: "ss-w-tab",
|
|
3188
3466
|
onClick: () => monitor.setActiveTab(tab),
|
|
3189
3467
|
children: [
|
|
3190
|
-
|
|
3468
|
+
label,
|
|
3191
3469
|
count > 0 && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "ss-w-tab-count", children: count }),
|
|
3192
|
-
|
|
3470
|
+
dot && !active && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "ss-w-tab-dot", "aria-hidden": "true" })
|
|
3193
3471
|
]
|
|
3194
3472
|
},
|
|
3195
3473
|
tab
|
|
@@ -3350,6 +3628,7 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
|
|
|
3350
3628
|
selection,
|
|
3351
3629
|
shownOdds: typeof row.market.price === "number" ? row.market.price.toFixed(2) : "",
|
|
3352
3630
|
marketName: row.market.marketLabel,
|
|
3631
|
+
marketDeveloperName: row.market.marketDeveloperName,
|
|
3353
3632
|
slip,
|
|
3354
3633
|
ui
|
|
3355
3634
|
}
|
|
@@ -3444,12 +3723,96 @@ function OddsPanel({ monitor, ui, slip }) {
|
|
|
3444
3723
|
}) });
|
|
3445
3724
|
}
|
|
3446
3725
|
|
|
3447
|
-
// src/components/
|
|
3726
|
+
// src/components/FixtureRow.tsx
|
|
3448
3727
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3728
|
+
function kickoffLabel(kickoffUnix) {
|
|
3729
|
+
const d = new Date(kickoffUnix * 1e3);
|
|
3730
|
+
return `${`${d.getHours()}`.padStart(2, "0")}:${`${d.getMinutes()}`.padStart(2, "0")}`;
|
|
3731
|
+
}
|
|
3732
|
+
function Side({ name, crest }) {
|
|
3733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ss-w-drow-side", children: [
|
|
3734
|
+
crest ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("img", { className: "ss-w-drow-crest", src: crest, alt: "" }) : null,
|
|
3735
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "ss-w-drow-nm", children: name })
|
|
3736
|
+
] });
|
|
3737
|
+
}
|
|
3738
|
+
function FixtureRow({ match, state, stale, ui, monitor }) {
|
|
3739
|
+
const isLive = state?.phase === "live" && !stale;
|
|
3740
|
+
const hasScore = (state?.phase === "live" || state?.phase === "fullTime") && typeof state.homeScore === "number" && typeof state.awayScore === "number";
|
|
3741
|
+
const when = stale && state?.phase === "live" ? "\u2014" : isLive ? state?.minuteLabel ?? "\u2014" : kickoffLabel(match.kickoffUnix);
|
|
3742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: isLive ? "ss-w-drow ss-w-drow--live" : "ss-w-drow", children: [
|
|
3743
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: isLive ? "ss-w-drow-when ss-w-drow-when--live" : "ss-w-drow-when", children: when }),
|
|
3744
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ss-w-drow-fx", children: [
|
|
3745
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Side, { name: match.homeTeamName, crest: match.homeTeamImagePath }),
|
|
3746
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "ss-w-drow-dash", children: "\u2013" }),
|
|
3747
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Side, { name: match.awayTeamName, crest: match.awayTeamImagePath })
|
|
3748
|
+
] }),
|
|
3749
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: hasScore ? "ss-w-drow-sc" : "ss-w-drow-sc ss-w-drow-sc--idle", children: hasScore ? `${state.homeScore}\u2013${state.awayScore}` : "\u2013" }),
|
|
3750
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
|
|
3751
|
+
] });
|
|
3752
|
+
}
|
|
3753
|
+
|
|
3754
|
+
// src/components/CompetitionGroup.tsx
|
|
3755
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3756
|
+
function CompetitionGroup({ group, open, onToggle, states, stale, ui, monitor }) {
|
|
3757
|
+
const own = group.matches.filter((m) => states[m.matchId]?.phase !== "live" || stale);
|
|
3758
|
+
const hasLive = own.length !== group.matches.length;
|
|
3759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "ss-w-grp", children: [
|
|
3760
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("button", { type: "button", className: "ss-w-grp-head", "aria-expanded": open, onClick: onToggle, children: [
|
|
3761
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ss-w-grp-chev", children: open ? "\u25BE" : "\u25B8" }),
|
|
3762
|
+
hasLive && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ss-w-sec-dot", "aria-hidden": "true" }),
|
|
3763
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ss-w-grp-name", children: group.competitionName }),
|
|
3764
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ss-w-grp-count", children: own.length })
|
|
3765
|
+
] }),
|
|
3766
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "ss-w-grp-body", children: own.map((m) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(FixtureRow, { match: m, state: states[m.matchId], stale, ui, monitor }, m.matchId)) })
|
|
3767
|
+
] });
|
|
3768
|
+
}
|
|
3769
|
+
|
|
3770
|
+
// src/components/TodayPanel.tsx
|
|
3771
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3772
|
+
function TodayPanel({ discovery, ui, monitor }) {
|
|
3773
|
+
const { groups, states, stale, expanded, toggleGroup } = discovery;
|
|
3774
|
+
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);
|
|
3775
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "ss-w-mon-list", children: [
|
|
3776
|
+
stale && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "ss-w-stale", children: ui.staleStates }),
|
|
3777
|
+
liveRows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
3778
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "ss-w-sec-head", children: [
|
|
3779
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "ss-w-sec-dot", "aria-hidden": "true" }),
|
|
3780
|
+
ui.sectionLive
|
|
3781
|
+
] }),
|
|
3782
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "ss-w-today-live", children: liveRows.map(({ match }) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3783
|
+
FixtureRow,
|
|
3784
|
+
{
|
|
3785
|
+
match,
|
|
3786
|
+
state: states[match.matchId],
|
|
3787
|
+
stale,
|
|
3788
|
+
ui,
|
|
3789
|
+
monitor
|
|
3790
|
+
},
|
|
3791
|
+
match.matchId
|
|
3792
|
+
)) })
|
|
3793
|
+
] }),
|
|
3794
|
+
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3795
|
+
CompetitionGroup,
|
|
3796
|
+
{
|
|
3797
|
+
group,
|
|
3798
|
+
open: expanded[group.competitionId] ?? group.expandedByDefault,
|
|
3799
|
+
onToggle: () => toggleGroup(group.competitionId),
|
|
3800
|
+
states,
|
|
3801
|
+
stale,
|
|
3802
|
+
ui,
|
|
3803
|
+
monitor
|
|
3804
|
+
},
|
|
3805
|
+
group.competitionId
|
|
3806
|
+
))
|
|
3807
|
+
] });
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3810
|
+
// src/components/ChatPanel.tsx
|
|
3811
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3449
3812
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
3450
3813
|
function useIsModal() {
|
|
3451
|
-
const [modal, setModal] = (0,
|
|
3452
|
-
(0,
|
|
3814
|
+
const [modal, setModal] = (0, import_react25.useState)(false);
|
|
3815
|
+
(0, import_react25.useEffect)(() => {
|
|
3453
3816
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
3454
3817
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
3455
3818
|
const sync = () => setModal(mql.matches);
|
|
@@ -3459,10 +3822,10 @@ function useIsModal() {
|
|
|
3459
3822
|
}, []);
|
|
3460
3823
|
return modal;
|
|
3461
3824
|
}
|
|
3462
|
-
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
3825
|
+
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery }) {
|
|
3463
3826
|
const { state, close, stop, send, reset } = controller;
|
|
3464
3827
|
const isModal = useIsModal();
|
|
3465
|
-
(0,
|
|
3828
|
+
(0, import_react25.useEffect)(() => {
|
|
3466
3829
|
const onKey = (e) => {
|
|
3467
3830
|
if (e.key === "Escape") close();
|
|
3468
3831
|
};
|
|
@@ -3473,11 +3836,11 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
3473
3836
|
monitor?.setActiveTab("chat");
|
|
3474
3837
|
send(text);
|
|
3475
3838
|
};
|
|
3476
|
-
(0,
|
|
3839
|
+
(0, import_react25.useEffect)(() => {
|
|
3477
3840
|
if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
|
|
3478
3841
|
}, [monitor, state.isStreaming, state.messages.length]);
|
|
3479
|
-
return /* @__PURE__ */ (0,
|
|
3480
|
-
/* @__PURE__ */ (0,
|
|
3842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
3843
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3481
3844
|
ChatHeader,
|
|
3482
3845
|
{
|
|
3483
3846
|
onClose: close,
|
|
@@ -3490,25 +3853,28 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
3490
3853
|
moreOptionsLabel: ui.moreOptions
|
|
3491
3854
|
}
|
|
3492
3855
|
),
|
|
3493
|
-
monitor && /* @__PURE__ */ (0,
|
|
3856
|
+
monitor && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3494
3857
|
TabBar,
|
|
3495
3858
|
{
|
|
3496
3859
|
monitor,
|
|
3497
3860
|
ui,
|
|
3498
3861
|
matchCount: monitor.pins.filter((p) => p.kind === "match").length,
|
|
3499
|
-
oddsCount: monitor.pins.filter((p) => p.kind !== "match").length
|
|
3862
|
+
oddsCount: monitor.pins.filter((p) => p.kind !== "match").length,
|
|
3863
|
+
todayCount: discovery?.liveCount ?? 0,
|
|
3864
|
+
hasToday: (discovery?.groups.length ?? 0) > 0
|
|
3500
3865
|
}
|
|
3501
3866
|
),
|
|
3502
|
-
/* @__PURE__ */ (0,
|
|
3867
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3503
3868
|
"div",
|
|
3504
3869
|
{
|
|
3505
3870
|
style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
|
|
3506
|
-
children: /* @__PURE__ */ (0,
|
|
3871
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor })
|
|
3507
3872
|
}
|
|
3508
3873
|
),
|
|
3509
|
-
monitor && monitor.activeTab === "
|
|
3510
|
-
monitor && monitor.activeTab === "
|
|
3511
|
-
/* @__PURE__ */ (0,
|
|
3874
|
+
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(TodayPanel, { discovery, ui, monitor }),
|
|
3875
|
+
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(MatchesPanel, { monitor, ui, slip }),
|
|
3876
|
+
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(OddsPanel, { monitor, ui, slip }),
|
|
3877
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
3512
3878
|
] });
|
|
3513
3879
|
}
|
|
3514
3880
|
|
|
@@ -4245,8 +4611,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
4245
4611
|
.ss-w-fandash-live-legend-swatch--away { background: var(--ss-w-away); }
|
|
4246
4612
|
|
|
4247
4613
|
/* live monitor tab bar: underline pattern mirrors .ss-w-ecard-scope; the unread dot uses --ss-w-neg */
|
|
4248
|
-
.ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); }
|
|
4249
|
-
.ss-w-
|
|
4614
|
+
.ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); overflow-x: auto; scrollbar-width: none; }
|
|
4615
|
+
.ss-w-tabs::-webkit-scrollbar { display: none; }
|
|
4616
|
+
.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; }
|
|
4250
4617
|
.ss-w-tab[data-on] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }
|
|
4251
4618
|
.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; }
|
|
4252
4619
|
.ss-w-tab[data-on] .ss-w-tab-count { color: var(--ss-w-accent); }
|
|
@@ -4335,10 +4702,41 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
4335
4702
|
.ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }
|
|
4336
4703
|
.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; }
|
|
4337
4704
|
.ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }
|
|
4705
|
+
|
|
4706
|
+
/* ---- Today tab (u355) ---- */
|
|
4707
|
+
.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); }
|
|
4708
|
+
.ss-w-sec-head::after { content: ""; flex: 1; height: 1px; background: var(--ss-w-line); }
|
|
4709
|
+
.ss-w-sec-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }
|
|
4710
|
+
.ss-w-today-live { display: flex; flex-direction: column; gap: 2px; }
|
|
4711
|
+
|
|
4712
|
+
.ss-w-grp { border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; }
|
|
4713
|
+
.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; }
|
|
4714
|
+
.ss-w-grp-head:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }
|
|
4715
|
+
.ss-w-grp-chev { color: var(--ss-w-faint); font-size: 10px; flex: none; }
|
|
4716
|
+
.ss-w-grp-name { font-size: 12px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4717
|
+
.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; }
|
|
4718
|
+
.ss-w-grp-body { display: flex; flex-direction: column; padding: 2px 11px 6px; }
|
|
4719
|
+
|
|
4720
|
+
.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); }
|
|
4721
|
+
.ss-w-drow:last-child { border-bottom: none; }
|
|
4722
|
+
.ss-w-drow-when { font-size: 11px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }
|
|
4723
|
+
.ss-w-drow-when--live { color: var(--ss-w-neg); }
|
|
4724
|
+
/* Each side ellipsises independently: a single joined string truncates the away team off the end,
|
|
4725
|
+
which is the u350 betting-card truncation one layer down. */
|
|
4726
|
+
.ss-w-drow-fx { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
4727
|
+
.ss-w-drow-side { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1 1 0; }
|
|
4728
|
+
.ss-w-drow-nm { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4729
|
+
.ss-w-drow-dash { flex: none; color: var(--ss-w-faint); font-size: 11px; }
|
|
4730
|
+
.ss-w-drow-sc { font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
4731
|
+
.ss-w-drow-sc--idle { color: var(--ss-w-faint); font-weight: 600; }
|
|
4732
|
+
.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; }
|
|
4733
|
+
.ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }
|
|
4734
|
+
|
|
4735
|
+
.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; }
|
|
4338
4736
|
`;
|
|
4339
4737
|
|
|
4340
4738
|
// src/StatsWidget.tsx
|
|
4341
|
-
var
|
|
4739
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
4342
4740
|
function buildClient(props) {
|
|
4343
4741
|
try {
|
|
4344
4742
|
if ("client" in props && props.client) {
|
|
@@ -4363,22 +4761,61 @@ function injectStyles(root) {
|
|
|
4363
4761
|
function StatsWidget(props) {
|
|
4364
4762
|
const injectedClient = "client" in props ? props.client : void 0;
|
|
4365
4763
|
const cfg = props.config;
|
|
4366
|
-
const built = (0,
|
|
4367
|
-
const
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4764
|
+
const built = (0, import_react26.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
|
|
4765
|
+
const logger = (0, import_react26.useMemo)(
|
|
4766
|
+
() => built ? built.client.createEventLogger({
|
|
4767
|
+
operatorUserId: cfg?.userContext?.operatorUserId,
|
|
4768
|
+
anonymousUserId: cfg?.userContext?.anonymousUserId
|
|
4769
|
+
}) : null,
|
|
4770
|
+
[built?.client]
|
|
4771
|
+
);
|
|
4772
|
+
const ui = (0, import_react26.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
4773
|
+
const rootRef = (0, import_react26.useRef)(null);
|
|
4774
|
+
const introDoneRef = (0, import_react26.useRef)(false);
|
|
4775
|
+
const markIntroDone = (0, import_react26.useCallback)(() => {
|
|
4371
4776
|
introDoneRef.current = true;
|
|
4372
4777
|
}, []);
|
|
4373
4778
|
const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
|
|
4374
4779
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
|
|
4780
|
+
const [hasToday, setHasToday] = (0, import_react26.useState)(false);
|
|
4375
4781
|
const monitor = useLiveMonitor({
|
|
4376
4782
|
getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
|
|
4377
4783
|
getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
|
|
4378
4784
|
storageKey: `ss-w-pins:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`,
|
|
4379
|
-
isOpen: controller.state.isOpen
|
|
4785
|
+
isOpen: controller.state.isOpen,
|
|
4786
|
+
hasToday
|
|
4787
|
+
});
|
|
4788
|
+
const getSchedule = (0, import_react26.useCallback)(
|
|
4789
|
+
(localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),
|
|
4790
|
+
[built]
|
|
4791
|
+
);
|
|
4792
|
+
const getStates = (0, import_react26.useCallback)(
|
|
4793
|
+
(matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
|
|
4794
|
+
[built]
|
|
4795
|
+
);
|
|
4796
|
+
const pinnedMatchIds = (0, import_react26.useMemo)(
|
|
4797
|
+
() => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
|
|
4798
|
+
[monitor.pins]
|
|
4799
|
+
);
|
|
4800
|
+
const discovery = useMatchDiscovery({
|
|
4801
|
+
getSchedule,
|
|
4802
|
+
getStates,
|
|
4803
|
+
operatorId: cfg?.operatorId ?? "",
|
|
4804
|
+
isOpen: controller.state.isOpen,
|
|
4805
|
+
pinnedMatchIds
|
|
4380
4806
|
});
|
|
4381
|
-
const
|
|
4807
|
+
const todayHasContent = discovery.groups.length > 0;
|
|
4808
|
+
(0, import_react26.useEffect)(() => {
|
|
4809
|
+
setHasToday(todayHasContent);
|
|
4810
|
+
}, [todayHasContent]);
|
|
4811
|
+
const markTodayActivity = monitor.markTodayActivity;
|
|
4812
|
+
const prevLiveCountRef = (0, import_react26.useRef)(0);
|
|
4813
|
+
(0, import_react26.useEffect)(() => {
|
|
4814
|
+
const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
|
|
4815
|
+
prevLiveCountRef.current = discovery.liveCount;
|
|
4816
|
+
if (rose) markTodayActivity();
|
|
4817
|
+
}, [discovery.liveCount, markTodayActivity]);
|
|
4818
|
+
const slip = (0, import_react26.useMemo)(
|
|
4382
4819
|
() => {
|
|
4383
4820
|
const handler = props.config?.onAddToSlip;
|
|
4384
4821
|
return {
|
|
@@ -4401,18 +4838,42 @@ function StatsWidget(props) {
|
|
|
4401
4838
|
},
|
|
4402
4839
|
[props.config?.onAddToSlip, controller.state.conversationId, built, monitor.markInSlip]
|
|
4403
4840
|
);
|
|
4404
|
-
const onDashboardTap = (0,
|
|
4405
|
-
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
|
|
4406
|
-
[built]
|
|
4841
|
+
const onDashboardTap = (0, import_react26.useMemo)(
|
|
4842
|
+
() => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
|
|
4843
|
+
[built, logger]
|
|
4407
4844
|
);
|
|
4408
|
-
|
|
4845
|
+
const operatorUserId = cfg?.userContext?.operatorUserId;
|
|
4846
|
+
const anonymousUserId = cfg?.userContext?.anonymousUserId;
|
|
4847
|
+
const conversationId = controller.state.conversationId ?? void 0;
|
|
4848
|
+
(0, import_react26.useEffect)(() => {
|
|
4849
|
+
if (!logger) return;
|
|
4850
|
+
logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
|
|
4851
|
+
}, [logger, operatorUserId, anonymousUserId, conversationId]);
|
|
4852
|
+
(0, import_react26.useEffect)(() => {
|
|
4853
|
+
if (!logger) return;
|
|
4854
|
+
const onHide = () => {
|
|
4855
|
+
logger.flushOnHide();
|
|
4856
|
+
};
|
|
4857
|
+
const onVisibilityHide = () => {
|
|
4858
|
+
if (document.visibilityState === "hidden") logger.flushOnHide();
|
|
4859
|
+
};
|
|
4860
|
+
window.addEventListener("pagehide", onHide);
|
|
4861
|
+
document.addEventListener("visibilitychange", onVisibilityHide);
|
|
4862
|
+
return () => {
|
|
4863
|
+
window.removeEventListener("pagehide", onHide);
|
|
4864
|
+
document.removeEventListener("visibilitychange", onVisibilityHide);
|
|
4865
|
+
logger.flushOnHide();
|
|
4866
|
+
logger.dispose();
|
|
4867
|
+
};
|
|
4868
|
+
}, [logger]);
|
|
4869
|
+
(0, import_react26.useEffect)(() => {
|
|
4409
4870
|
if (!built || !ui.injectStyles) return;
|
|
4410
4871
|
const node = rootRef.current?.getRootNode();
|
|
4411
4872
|
if (node) injectStyles(node);
|
|
4412
4873
|
}, [built, ui.injectStyles]);
|
|
4413
4874
|
if (!built) return null;
|
|
4414
4875
|
const attrs = themeAttrs(ui);
|
|
4415
|
-
return /* @__PURE__ */ (0,
|
|
4876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("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__ */ (0, import_jsx_runtime53.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0, discovery }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4416
4877
|
ChatFab,
|
|
4417
4878
|
{
|
|
4418
4879
|
label: ui.launcherLabel,
|
|
@@ -4425,7 +4886,7 @@ function StatsWidget(props) {
|
|
|
4425
4886
|
introAllowed: !introDoneRef.current,
|
|
4426
4887
|
onIntroStart: markIntroDone
|
|
4427
4888
|
}
|
|
4428
|
-
) });
|
|
4889
|
+
) }) });
|
|
4429
4890
|
}
|
|
4430
4891
|
function emptyConversation() {
|
|
4431
4892
|
return { send: () => {
|