@sensiblestats/widget-react 0.79.0 → 0.80.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 +11 -0
- package/dist/index.cjs +130 -33
- 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 +124 -27
- package/dist/index.js.map +1 -1
- package/dist/styles.css +4 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @sensiblestats/widget-react
|
|
2
2
|
|
|
3
|
+
## 0.80.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Show the brand's limit message: LimitError for limit refusals, the limit_notice capability, and a status line that replaces the composer while the assistant is paused.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @sensiblestats/widget-sdk@0.51.0
|
|
13
|
+
|
|
3
14
|
## 0.79.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
38
38
|
|
|
39
39
|
// src/StatsWidget.tsx
|
|
40
40
|
var import_react57 = require("react");
|
|
41
|
-
var
|
|
41
|
+
var import_widget_sdk6 = require("@sensiblestats/widget-sdk");
|
|
42
42
|
|
|
43
43
|
// src/kickoff.ts
|
|
44
44
|
function formatBettingKickoff(kickoffUtc, ui, locale, now = /* @__PURE__ */ new Date()) {
|
|
@@ -68,6 +68,9 @@ var STRINGS = {
|
|
|
68
68
|
dismissGreeting: "Dismiss",
|
|
69
69
|
somethingWentWrong: "Something went wrong.",
|
|
70
70
|
retry: "Retry",
|
|
71
|
+
limitDailyCap: "You've asked all your questions for today. You can ask again tomorrow.",
|
|
72
|
+
limitQuotaExhausted: "The assistant can't take new questions right now. Please try again later.",
|
|
73
|
+
limitAssistantPaused: "The assistant isn't available right now. Please try again later.",
|
|
71
74
|
showLess: "Show less",
|
|
72
75
|
showMore: (n) => `Show ${n} more`,
|
|
73
76
|
allMarkets: (n) => `All markets (${n})`,
|
|
@@ -417,6 +420,9 @@ var STRINGS = {
|
|
|
417
420
|
dismissGreeting: "Kapat",
|
|
418
421
|
somethingWentWrong: "Bir \u015Feyler ters gitti.",
|
|
419
422
|
retry: "Tekrar dene",
|
|
423
|
+
limitDailyCap: "Bug\xFCnl\xFCk sorular\u0131n\u0131 tamamlad\u0131n. Yar\u0131n yeniden sorabilirsin.",
|
|
424
|
+
limitQuotaExhausted: "Asistan \u015Fu an yeni soru alam\u0131yor. L\xFCtfen daha sonra tekrar dene.",
|
|
425
|
+
limitAssistantPaused: "Asistan \u015Fu an kullan\u0131lam\u0131yor. L\xFCtfen daha sonra tekrar dene.",
|
|
420
426
|
showLess: "Daha az g\xF6ster",
|
|
421
427
|
showMore: (n) => `${n} tane daha g\xF6ster`,
|
|
422
428
|
allMarkets: (n) => `T\xFCm bahisler (${n})`,
|
|
@@ -795,6 +801,9 @@ function normalizeUi(cfg) {
|
|
|
795
801
|
dismissGreeting: strings.dismissGreeting,
|
|
796
802
|
somethingWentWrong: strings.somethingWentWrong,
|
|
797
803
|
retry: strings.retry,
|
|
804
|
+
limitDailyCap: strings.limitDailyCap,
|
|
805
|
+
limitQuotaExhausted: strings.limitQuotaExhausted,
|
|
806
|
+
limitAssistantPaused: strings.limitAssistantPaused,
|
|
798
807
|
showLess: strings.showLess,
|
|
799
808
|
showMore: strings.showMore,
|
|
800
809
|
allMarkets: strings.allMarkets,
|
|
@@ -1738,10 +1747,55 @@ function themeAttrs(ui) {
|
|
|
1738
1747
|
|
|
1739
1748
|
// src/useChatStream.ts
|
|
1740
1749
|
var import_react3 = require("react");
|
|
1741
|
-
var
|
|
1750
|
+
var import_widget_sdk4 = require("@sensiblestats/widget-sdk");
|
|
1742
1751
|
|
|
1743
1752
|
// src/reducer.ts
|
|
1753
|
+
var import_widget_sdk3 = require("@sensiblestats/widget-sdk");
|
|
1754
|
+
|
|
1755
|
+
// src/limit.ts
|
|
1744
1756
|
var import_widget_sdk2 = require("@sensiblestats/widget-sdk");
|
|
1757
|
+
var LIMIT_TIMER_MAX_MS = 60 * 60 * 1e3;
|
|
1758
|
+
var ZONED = /(?:Z|[+-]\d{2}:?\d{2})$/i;
|
|
1759
|
+
function build(code, message, resetsAt, retryAfterSeconds) {
|
|
1760
|
+
return {
|
|
1761
|
+
code,
|
|
1762
|
+
paused: code === "assistant_paused",
|
|
1763
|
+
message: message?.trim() || null,
|
|
1764
|
+
resetsAt: resetsAt ?? null,
|
|
1765
|
+
retryAfterSeconds: typeof retryAfterSeconds === "number" && Number.isFinite(retryAfterSeconds) ? retryAfterSeconds : null
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
function limitFromEvent(data) {
|
|
1769
|
+
return (0, import_widget_sdk2.isLimitCode)(data.code) ? build(data.code, data.message, data.resetsAt, data.retryAfterSeconds) : null;
|
|
1770
|
+
}
|
|
1771
|
+
function limitFromError(error) {
|
|
1772
|
+
return error instanceof import_widget_sdk2.LimitError ? build(error.limitCode, error.limitMessage, error.resetsAt, error.retryAfter) : null;
|
|
1773
|
+
}
|
|
1774
|
+
function isLimitNotice(data) {
|
|
1775
|
+
return data.terminal === false && (0, import_widget_sdk2.isLimitCode)(data.code);
|
|
1776
|
+
}
|
|
1777
|
+
function isPaused(limit) {
|
|
1778
|
+
return limit?.paused === true;
|
|
1779
|
+
}
|
|
1780
|
+
function limitText(limit, ui) {
|
|
1781
|
+
if (limit.message) return limit.message;
|
|
1782
|
+
switch (limit.code) {
|
|
1783
|
+
case "daily_cap":
|
|
1784
|
+
return ui.limitDailyCap;
|
|
1785
|
+
case "quota_exhausted":
|
|
1786
|
+
return ui.limitQuotaExhausted;
|
|
1787
|
+
case "assistant_paused":
|
|
1788
|
+
return ui.limitAssistantPaused;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
function limitDelayMs(limit, nowMs) {
|
|
1792
|
+
const retry = limit.retryAfterSeconds;
|
|
1793
|
+
if (retry != null && Number.isFinite(retry) && retry >= 0) return Math.min(retry * 1e3, LIMIT_TIMER_MAX_MS);
|
|
1794
|
+
const at = limit.resetsAt ? Date.parse(ZONED.test(limit.resetsAt) ? limit.resetsAt : `${limit.resetsAt}Z`) : Number.NaN;
|
|
1795
|
+
return Number.isNaN(at) ? null : Math.min(Math.max(at - nowMs, 0), LIMIT_TIMER_MAX_MS);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// src/reducer.ts
|
|
1745
1799
|
var POPUP_MAX = 160;
|
|
1746
1800
|
function markAwaitingLiveUpdate(messages, held = []) {
|
|
1747
1801
|
if (!messages.some((m) => m.role === "assistant" && m.marketOdds.some((vm) => vm.live != null))) return messages;
|
|
@@ -1759,12 +1813,18 @@ function markAwaitingLiveUpdate(messages, held = []) {
|
|
|
1759
1813
|
});
|
|
1760
1814
|
}
|
|
1761
1815
|
function initialState(starters) {
|
|
1762
|
-
return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, starters, configuredStarters: starters, error: null, lastUserInput: null, lastDisplayText: null, popupText: null, conversationId: null };
|
|
1816
|
+
return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, starters, configuredStarters: starters, error: null, lastUserInput: null, lastDisplayText: null, popupText: null, conversationId: null, limit: null };
|
|
1763
1817
|
}
|
|
1764
1818
|
function activeTurn(state) {
|
|
1765
1819
|
const last = state.messages[state.messages.length - 1];
|
|
1766
1820
|
return last && last.role === "assistant" && !last.done ? last : null;
|
|
1767
1821
|
}
|
|
1822
|
+
function settleRefused(state, limit) {
|
|
1823
|
+
return { ...state, limit, error: null, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) };
|
|
1824
|
+
}
|
|
1825
|
+
function isPlainInput(input) {
|
|
1826
|
+
return !!input && !input.actionRef && !input.actionId && !input.grounding && !input.preset;
|
|
1827
|
+
}
|
|
1768
1828
|
function mapActive(state, fn) {
|
|
1769
1829
|
const last = state.messages[state.messages.length - 1];
|
|
1770
1830
|
if (!last || last.role !== "assistant" || last.done) return state.messages;
|
|
@@ -1804,6 +1864,7 @@ function applyEvent(state, event) {
|
|
|
1804
1864
|
case "turn_complete": {
|
|
1805
1865
|
const active = activeTurn(state);
|
|
1806
1866
|
const greetingLine = event.data.clubFanDashboard?.greeting?.trim() || (active?.text.trim() ?? "");
|
|
1867
|
+
const clearsLimit = !active?.isGreeting && isPlainInput(state.lastUserInput);
|
|
1807
1868
|
const popupText = active?.isGreeting && !state.isOpen && greetingLine ? greetingLine.slice(0, POPUP_MAX) : state.popupText;
|
|
1808
1869
|
return {
|
|
1809
1870
|
...state,
|
|
@@ -1811,6 +1872,7 @@ function applyEvent(state, event) {
|
|
|
1811
1872
|
status: null,
|
|
1812
1873
|
actionsLoading: false,
|
|
1813
1874
|
popupText,
|
|
1875
|
+
limit: clearsLimit ? null : state.limit,
|
|
1814
1876
|
conversationId: event.data.conversationId ?? state.conversationId,
|
|
1815
1877
|
messages: mapActive(state, (t) => ({
|
|
1816
1878
|
...t,
|
|
@@ -1821,6 +1883,9 @@ function applyEvent(state, event) {
|
|
|
1821
1883
|
};
|
|
1822
1884
|
}
|
|
1823
1885
|
case "error": {
|
|
1886
|
+
const limit = limitFromEvent(event.data);
|
|
1887
|
+
if (limit && event.data.terminal === false) return { ...state, limit };
|
|
1888
|
+
if (limit) return settleRefused(state, limit);
|
|
1824
1889
|
const suppress = activeTurn(state)?.isGreeting === true;
|
|
1825
1890
|
return { ...state, error: suppress ? state.error : event.data, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) };
|
|
1826
1891
|
}
|
|
@@ -1845,7 +1910,7 @@ function reducer(state, action) {
|
|
|
1845
1910
|
case "DISMISS_POPUP":
|
|
1846
1911
|
return { ...state, popupText: null };
|
|
1847
1912
|
case "RESET":
|
|
1848
|
-
return { ...initialState(state.configuredStarters), isOpen: state.isOpen };
|
|
1913
|
+
return { ...initialState(state.configuredStarters), isOpen: state.isOpen, limit: state.limit };
|
|
1849
1914
|
case "RESTORE":
|
|
1850
1915
|
return {
|
|
1851
1916
|
...state,
|
|
@@ -1859,8 +1924,13 @@ function reducer(state, action) {
|
|
|
1859
1924
|
};
|
|
1860
1925
|
case "EVENT":
|
|
1861
1926
|
return applyEvent(state, action.event);
|
|
1862
|
-
case "STREAM_ERROR":
|
|
1927
|
+
case "STREAM_ERROR": {
|
|
1928
|
+
const limit = limitFromError(action.error);
|
|
1929
|
+
if (limit) return settleRefused(state, limit);
|
|
1863
1930
|
return { ...state, error: action.error, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) };
|
|
1931
|
+
}
|
|
1932
|
+
case "LIMIT_EXPIRED":
|
|
1933
|
+
return { ...state, limit: null };
|
|
1864
1934
|
case "STOP":
|
|
1865
1935
|
return { ...state, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) };
|
|
1866
1936
|
case "UPDATE_LIVE_CARD": {
|
|
@@ -2033,7 +2103,7 @@ function clearConversation(storageKey) {
|
|
|
2033
2103
|
}
|
|
2034
2104
|
|
|
2035
2105
|
// src/presets.ts
|
|
2036
|
-
var CLIENT_CAPABILITIES = ["price_presets", "price_presets_open"];
|
|
2106
|
+
var CLIENT_CAPABILITIES = ["price_presets", "price_presets_open", "limit_notice"];
|
|
2037
2107
|
var PRICE_TILE_PREFIX = "goal-preset-";
|
|
2038
2108
|
function isPriceTile(tile) {
|
|
2039
2109
|
const id = tile.signal?.entityId;
|
|
@@ -2131,11 +2201,11 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
2131
2201
|
try {
|
|
2132
2202
|
for await (const event of handle) {
|
|
2133
2203
|
dispatch({ kind: "EVENT", event });
|
|
2134
|
-
if (event.type === "turn_complete" || event.type === "error") clearFallbackTimer();
|
|
2204
|
+
if (event.type === "turn_complete" || event.type === "error" && !isLimitNotice(event.data)) clearFallbackTimer();
|
|
2135
2205
|
}
|
|
2136
2206
|
} catch (err) {
|
|
2137
2207
|
if (handleRef.current === handle) clearFallbackTimer();
|
|
2138
|
-
if (err instanceof
|
|
2208
|
+
if (err instanceof import_widget_sdk4.WidgetSdkError) onError(err);
|
|
2139
2209
|
else if (err?.name === "AbortError") {
|
|
2140
2210
|
} else throw err;
|
|
2141
2211
|
} finally {
|
|
@@ -2144,6 +2214,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
2144
2214
|
})();
|
|
2145
2215
|
}, [clearFallbackTimer]);
|
|
2146
2216
|
const run = (0, import_react3.useCallback)((input, displayText) => {
|
|
2217
|
+
if (isPaused(stateRef.current.limit)) return;
|
|
2147
2218
|
handleRef.current?.cancel();
|
|
2148
2219
|
clearFallbackTimer();
|
|
2149
2220
|
dispatch({ kind: "USER_SENT", input, userId: nextId(), assistantId: nextId(), displayText });
|
|
@@ -2151,7 +2222,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
2151
2222
|
handleRef.current = handle;
|
|
2152
2223
|
armFallbackTimer(() => {
|
|
2153
2224
|
dispatch({ kind: "STOP" });
|
|
2154
|
-
dispatch({ kind: "STREAM_ERROR", error: new
|
|
2225
|
+
dispatch({ kind: "STREAM_ERROR", error: new import_widget_sdk4.WidgetSdkError("No response received in time", "timeout") });
|
|
2155
2226
|
});
|
|
2156
2227
|
consume(handle, (err) => dispatch({ kind: "STREAM_ERROR", error: err }));
|
|
2157
2228
|
}, [conversation, consume, clearFallbackTimer, armFallbackTimer]);
|
|
@@ -2191,6 +2262,13 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
2191
2262
|
greetedRef.current = true;
|
|
2192
2263
|
fireGreeting();
|
|
2193
2264
|
}, [fireGreeting]);
|
|
2265
|
+
(0, import_react3.useEffect)(() => {
|
|
2266
|
+
if (!state.limit) return;
|
|
2267
|
+
const delay = limitDelayMs(state.limit, Date.now());
|
|
2268
|
+
if (delay === null) return;
|
|
2269
|
+
const timer = setTimeout(() => dispatch({ kind: "LIMIT_EXPIRED" }), delay);
|
|
2270
|
+
return () => clearTimeout(timer);
|
|
2271
|
+
}, [state.limit]);
|
|
2194
2272
|
(0, import_react3.useEffect)(() => {
|
|
2195
2273
|
if (boot.stale && storageKey) clearConversation(storageKey);
|
|
2196
2274
|
}, []);
|
|
@@ -3533,7 +3611,7 @@ var import_react20 = require("react");
|
|
|
3533
3611
|
|
|
3534
3612
|
// src/slipAdd.ts
|
|
3535
3613
|
var import_react18 = require("react");
|
|
3536
|
-
var
|
|
3614
|
+
var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
|
|
3537
3615
|
|
|
3538
3616
|
// src/slipStateContext.ts
|
|
3539
3617
|
var import_react17 = require("react");
|
|
@@ -3562,7 +3640,7 @@ function useSlipAdd(slip, ui) {
|
|
|
3562
3640
|
}
|
|
3563
3641
|
try {
|
|
3564
3642
|
const raw = await withTimeout(Promise.resolve(handler(selection)));
|
|
3565
|
-
if (raw != null && !(0,
|
|
3643
|
+
if (raw != null && !(0, import_widget_sdk5.isAddToSlipResult)(raw)) throw new Error("malformed add-to-slip result");
|
|
3566
3644
|
const result = raw ?? void 0;
|
|
3567
3645
|
if (marketDeveloperName !== void 0) {
|
|
3568
3646
|
log?.log({
|
|
@@ -5381,7 +5459,7 @@ function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
5381
5459
|
ChatMessage,
|
|
5382
5460
|
{
|
|
5383
5461
|
message: m,
|
|
5384
|
-
disabled: state.isStreaming,
|
|
5462
|
+
disabled: state.isStreaming || isPaused(state.limit),
|
|
5385
5463
|
onAct: (a) => send(a.message, { actionId: a.actionId, actionRef: a.actionRef, displayText: a.label }),
|
|
5386
5464
|
onTap: (tile, index) => {
|
|
5387
5465
|
const displayText = tileDisplayText(tile);
|
|
@@ -5401,7 +5479,7 @@ function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
5401
5479
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
|
|
5402
5480
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
|
|
5403
5481
|
] }) : null,
|
|
5404
|
-
!hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
5482
|
+
!hasUserMessage && !hasDashboard && !isPaused(state.limit) ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
|
|
5405
5483
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { ref: endRef, className: "ss-w-turn-spacer", "aria-hidden": "true" })
|
|
5406
5484
|
]
|
|
5407
5485
|
}
|
|
@@ -9374,6 +9452,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
9374
9452
|
return () => window.removeEventListener("keydown", onKey);
|
|
9375
9453
|
}, [close]);
|
|
9376
9454
|
const handleSend = (text) => {
|
|
9455
|
+
typedSendRef.current = true;
|
|
9377
9456
|
monitor?.setActiveTab("chat");
|
|
9378
9457
|
send(text);
|
|
9379
9458
|
};
|
|
@@ -9389,6 +9468,8 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
9389
9468
|
const dialRef = (0, import_react56.useRef)(null);
|
|
9390
9469
|
const dialButtonRef = (0, import_react56.useRef)(null);
|
|
9391
9470
|
const inputRef = (0, import_react56.useRef)(null);
|
|
9471
|
+
const limitRef = (0, import_react56.useRef)(null);
|
|
9472
|
+
const typedSendRef = (0, import_react56.useRef)(false);
|
|
9392
9473
|
const focusAfterCloseRef = (0, import_react56.useRef)(null);
|
|
9393
9474
|
const [tool, setTool] = (0, import_react56.useState)(null);
|
|
9394
9475
|
const [toolSeen, setToolSeen] = (0, import_react56.useState)(readToolSeen);
|
|
@@ -9401,7 +9482,16 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
9401
9482
|
activeTab: monitor?.activeTab ?? "chat"
|
|
9402
9483
|
});
|
|
9403
9484
|
const { fold } = dial;
|
|
9404
|
-
const
|
|
9485
|
+
const paused = isPaused(state.limit);
|
|
9486
|
+
const showDial = !!presetGrid && onChatTab && !tool && !paused;
|
|
9487
|
+
(0, import_react56.useEffect)(() => {
|
|
9488
|
+
if (paused) setTool(null);
|
|
9489
|
+
}, [paused]);
|
|
9490
|
+
(0, import_react56.useEffect)(() => {
|
|
9491
|
+
if (!paused) return;
|
|
9492
|
+
if (typedSendRef.current) limitRef.current?.focus();
|
|
9493
|
+
typedSendRef.current = false;
|
|
9494
|
+
}, [paused]);
|
|
9405
9495
|
const openTool = (0, import_react56.useCallback)((next) => {
|
|
9406
9496
|
fold();
|
|
9407
9497
|
markToolSeen();
|
|
@@ -9410,8 +9500,8 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
9410
9500
|
}, [fold]);
|
|
9411
9501
|
const onPill = (0, import_react56.useCallback)((kind) => openTool(kind === "numbers" ? { kind: "numbers" } : { kind: "combo" }), [openTool]);
|
|
9412
9502
|
const toolsValue = (0, import_react56.useMemo)(
|
|
9413
|
-
() => presetGrid ? { openBuilder: (total, legs) => openTool({ kind: "combo", total, legs }), changeLabel: ui.presets.changeCombo } : null,
|
|
9414
|
-
[presetGrid, openTool, ui.presets.changeCombo]
|
|
9503
|
+
() => presetGrid && !paused ? { openBuilder: (total, legs) => openTool({ kind: "combo", total, legs }), changeLabel: ui.presets.changeCombo } : null,
|
|
9504
|
+
[presetGrid, paused, openTool, ui.presets.changeCombo]
|
|
9415
9505
|
);
|
|
9416
9506
|
const closeTool = (0, import_react56.useCallback)(() => {
|
|
9417
9507
|
focusAfterCloseRef.current = "dial";
|
|
@@ -9479,10 +9569,10 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
9479
9569
|
buttonRef: dialButtonRef
|
|
9480
9570
|
}
|
|
9481
9571
|
) : null,
|
|
9482
|
-
tool && presetGrid && onChatTab ? tool.kind === "numbers" ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(SetNumbersTool, { grid: presetGrid, strings: ui.presets, streaming: state.isStreaming, onSend: sendAsk, onClose: closeTool }) : /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(BuildComboTool, { grid: presetGrid, strings: ui.presets, streaming: state.isStreaming, formatKickoff, initialTotal: tool.total, initialLegs: tool.legs, onSend: sendAsk, onClose: closeTool }) : null
|
|
9572
|
+
tool && presetGrid && onChatTab && !paused ? tool.kind === "numbers" ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(SetNumbersTool, { grid: presetGrid, strings: ui.presets, streaming: state.isStreaming, onSend: sendAsk, onClose: closeTool }) : /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(BuildComboTool, { grid: presetGrid, strings: ui.presets, streaming: state.isStreaming, formatKickoff, initialTotal: tool.total, initialLegs: tool.legs, onSend: sendAsk, onClose: closeTool }) : null
|
|
9483
9573
|
] }),
|
|
9484
9574
|
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(TodayPanel, { discovery, ui, monitor }),
|
|
9485
|
-
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(MatchesPanel, { monitor, ui, slip, onAsk: handleAsk }),
|
|
9575
|
+
monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(MatchesPanel, { monitor, ui, slip, onAsk: paused ? void 0 : handleAsk }),
|
|
9486
9576
|
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(OddsPanel, { monitor, ui, slip }),
|
|
9487
9577
|
monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
9488
9578
|
GamesPanel,
|
|
@@ -9508,20 +9598,23 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
|
|
|
9508
9598
|
ui
|
|
9509
9599
|
}
|
|
9510
9600
|
),
|
|
9511
|
-
(!monitor || monitor.activeTab !== "games" && monitor.activeTab !== "leaderboard") && /* @__PURE__ */ (0, import_jsx_runtime95.
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9601
|
+
(!monitor || monitor.activeTab !== "games" && monitor.activeTab !== "leaderboard") && /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(import_jsx_runtime95.Fragment, { children: [
|
|
9602
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("div", { ref: limitRef, className: "ss-w-limit", role: "status", tabIndex: -1, children: state.limit ? limitText(state.limit, ui) : null }),
|
|
9603
|
+
paused ? null : /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
9604
|
+
ChatInput,
|
|
9605
|
+
{
|
|
9606
|
+
ref: inputRef,
|
|
9607
|
+
placeholder: ui.placeholder,
|
|
9608
|
+
streaming: state.isStreaming,
|
|
9609
|
+
onSend: handleSend,
|
|
9610
|
+
onStop: stop,
|
|
9611
|
+
stopLabel: ui.stopResponse,
|
|
9612
|
+
sendLabel: ui.sendMessage,
|
|
9613
|
+
disabled: !!tool,
|
|
9614
|
+
onType: fold
|
|
9615
|
+
}
|
|
9616
|
+
)
|
|
9617
|
+
] })
|
|
9525
9618
|
] });
|
|
9526
9619
|
}
|
|
9527
9620
|
|
|
@@ -10119,6 +10212,10 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
10119
10212
|
|
|
10120
10213
|
/* input */
|
|
10121
10214
|
.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }
|
|
10215
|
+
.ss-w-limit { padding: 10px 12px; border-top: 1px solid var(--ss-w-line); font-size: 13px; line-height: 1.4; color: var(--ss-w-ink); overflow-wrap: anywhere; }
|
|
10216
|
+
.ss-w-limit:empty { padding: 0; border-top: 0; }
|
|
10217
|
+
.ss-w-limit:focus { outline: none; }
|
|
10218
|
+
.ss-w-limit:not(:empty) + .ss-w-input { border-top: none; }
|
|
10122
10219
|
.ss-w-textarea { flex: 1; resize: none; border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; font: inherit; color: inherit; background: var(--ss-w-panel); max-height: 96px; }
|
|
10123
10220
|
.ss-w-textarea:disabled { opacity: .55; cursor: not-allowed; }
|
|
10124
10221
|
/* iOS Safari zooms the page when a focused field's font-size is < 16px. Bump it
|
|
@@ -11217,7 +11314,7 @@ function buildClient(props) {
|
|
|
11217
11314
|
return { client: props.client, conversation: props.client.conversation() };
|
|
11218
11315
|
}
|
|
11219
11316
|
const cfg = props.config;
|
|
11220
|
-
const client = new
|
|
11317
|
+
const client = new import_widget_sdk6.StatsWidgetClient(toClientOptions(cfg));
|
|
11221
11318
|
return { client, conversation: client.conversation(toUserContext(cfg)) };
|
|
11222
11319
|
} catch (err) {
|
|
11223
11320
|
console.error("[StatsWidget] failed to initialize:", err instanceof Error ? err.message : err);
|