@burdenoff/website-sdk 2026.922.4 → 2026.922.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/explore.d.mts +23 -1
- package/dist/components/explore.d.ts +23 -1
- package/dist/components/explore.js +709 -39
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +711 -42
- package/dist/components/explore.mjs.map +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +356 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +354 -1
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +720 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +719 -50
- package/dist/index.mjs.map +1 -1
- package/dist/{use-explore-chat-CNEdKBc1.d.ts → use-progressive-reveal-BfU_IHip.d.ts} +35 -1
- package/dist/{use-explore-chat-Dgm-jf96.d.mts → use-progressive-reveal-Ha3gYPfs.d.mts} +35 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { createContext, useMemo, useContext, useState, useCallback, useLayoutEffect, useRef, useEffect, useId, version } from 'react';
|
|
2
|
+
import { createContext, useMemo, useContext, useState, useCallback, useLayoutEffect, useRef, useEffect, useId, version, Children, isValidElement, cloneElement } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import { Instagram, Youtube, Facebook, Github, Linkedin, Twitter, Mail, Phone, MapPin, Clock, Send, CheckCircle, Upload, Globe, ChevronDown, Search, Rocket, ArrowRight, Download, ImageIcon, ChevronRight, Maximize2, Check, ArrowLeft, Sparkles, RotateCcw, Link2, History, Trash2, Paperclip, X, Mic, Square, ArrowUp, Info, ChevronLeft, BookOpenText, Layers, TriangleAlert, FileText, ExternalLink, Copy, ThumbsUp, ThumbsDown } from 'lucide-react';
|
|
4
|
+
import { Instagram, Youtube, Facebook, Github, Linkedin, Twitter, Mail, Phone, MapPin, Clock, Send, CheckCircle, Upload, Globe, ChevronDown, Search, Rocket, ArrowRight, Download, ImageIcon, ChevronRight, Maximize2, Check, ArrowLeft, Sparkles, RotateCcw, Link2, History, Trash2, Paperclip, X, Mic, Square, ArrowUp, Info, ChevronLeft, BookOpenText, Layers, TriangleAlert, FileText, ExternalLink, Copy, ThumbsUp, ThumbsDown, Volume2 } from 'lucide-react';
|
|
5
5
|
import ReCAPTCHA4 from 'react-google-recaptcha';
|
|
6
6
|
import { toast } from 'sonner';
|
|
7
7
|
import { Helmet } from 'react-helmet-async';
|
|
@@ -2408,16 +2408,16 @@ function useRateLimit(maxAttempts, windowMinutes) {
|
|
|
2408
2408
|
}
|
|
2409
2409
|
}, [maxAttempts]);
|
|
2410
2410
|
function recordAttempt() {
|
|
2411
|
-
const
|
|
2411
|
+
const now2 = Date.now();
|
|
2412
2412
|
const state = rateLimitRef.current;
|
|
2413
|
-
if (state &&
|
|
2413
|
+
if (state && now2 > state.resetTime) {
|
|
2414
2414
|
rateLimitRef.current = null;
|
|
2415
2415
|
}
|
|
2416
2416
|
const current = rateLimitRef.current;
|
|
2417
2417
|
if (!current) {
|
|
2418
2418
|
rateLimitRef.current = {
|
|
2419
2419
|
attempts: 1,
|
|
2420
|
-
resetTime:
|
|
2420
|
+
resetTime: now2 + windowMinutes * 60 * 1e3
|
|
2421
2421
|
};
|
|
2422
2422
|
return false;
|
|
2423
2423
|
}
|
|
@@ -3512,16 +3512,16 @@ function useRateLimit2(maxAttempts, windowMinutes) {
|
|
|
3512
3512
|
const [isLimited, setIsLimited] = useState(false);
|
|
3513
3513
|
const [resetTime, setResetTime] = useState(null);
|
|
3514
3514
|
function recordAttempt() {
|
|
3515
|
-
const
|
|
3515
|
+
const now2 = Date.now();
|
|
3516
3516
|
const state = rateLimitRef.current;
|
|
3517
|
-
if (state &&
|
|
3517
|
+
if (state && now2 > state.resetTime) {
|
|
3518
3518
|
rateLimitRef.current = null;
|
|
3519
3519
|
}
|
|
3520
3520
|
const current = rateLimitRef.current;
|
|
3521
3521
|
if (!current) {
|
|
3522
3522
|
rateLimitRef.current = {
|
|
3523
3523
|
attempts: 1,
|
|
3524
|
-
resetTime:
|
|
3524
|
+
resetTime: now2 + windowMinutes * 60 * 1e3
|
|
3525
3525
|
};
|
|
3526
3526
|
return false;
|
|
3527
3527
|
}
|
|
@@ -4555,8 +4555,8 @@ function LaunchCountdown({
|
|
|
4555
4555
|
launchedMessage = "We have launched!",
|
|
4556
4556
|
className
|
|
4557
4557
|
}) {
|
|
4558
|
-
const [
|
|
4559
|
-
const remainingMs = launchDate -
|
|
4558
|
+
const [now2, setNow] = useState(() => Date.now());
|
|
4559
|
+
const remainingMs = launchDate - now2;
|
|
4560
4560
|
const hasLaunched = remainingMs <= 0;
|
|
4561
4561
|
useEffect(() => {
|
|
4562
4562
|
if (hasLaunched) return;
|
|
@@ -5980,6 +5980,9 @@ var EN = {
|
|
|
5980
5980
|
conceptAskQuestion: "How does {title} work in {product}?",
|
|
5981
5981
|
copyAnswer: "Copy answer",
|
|
5982
5982
|
copyFailed: "Couldn't copy",
|
|
5983
|
+
readAloud: "Read aloud",
|
|
5984
|
+
stopReading: "Stop reading",
|
|
5985
|
+
answerTable: "Table",
|
|
5983
5986
|
groundedIn: "What this answer is based on",
|
|
5984
5987
|
sourceCountOne: "1 source",
|
|
5985
5988
|
sourceCountMany: "{count} sources",
|
|
@@ -6062,6 +6065,9 @@ var ZH = {
|
|
|
6062
6065
|
conceptAskQuestion: "{product} \u7684 {title} \u662F\u600E\u4E48\u8FD0\u4F5C\u7684\uFF1F",
|
|
6063
6066
|
copyAnswer: "\u590D\u5236\u56DE\u7B54",
|
|
6064
6067
|
copyFailed: "\u590D\u5236\u5931\u8D25",
|
|
6068
|
+
readAloud: "\u6717\u8BFB",
|
|
6069
|
+
stopReading: "\u505C\u6B62\u6717\u8BFB",
|
|
6070
|
+
answerTable: "\u8868\u683C",
|
|
6065
6071
|
groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
|
|
6066
6072
|
sourceCountOne: "1 \u4E2A\u6765\u6E90",
|
|
6067
6073
|
sourceCountMany: "{count} \u4E2A\u6765\u6E90",
|
|
@@ -6140,6 +6146,9 @@ var HI = {
|
|
|
6140
6146
|
conceptAskQuestion: "{product} \u092E\u0947\u0902 {title} \u0915\u0948\u0938\u0947 \u0915\u093E\u092E \u0915\u0930\u0924\u093E \u0939\u0948?",
|
|
6141
6147
|
copyAnswer: "\u0909\u0924\u094D\u0924\u0930 \u0915\u0949\u092A\u0940 \u0915\u0930\u0947\u0902",
|
|
6142
6148
|
copyFailed: "\u0915\u0949\u092A\u0940 \u0928\u0939\u0940\u0902 \u0939\u094B \u0938\u0915\u093E",
|
|
6149
|
+
readAloud: "\u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0947\u0902",
|
|
6150
|
+
stopReading: "\u092A\u0922\u093C\u0928\u093E \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6151
|
+
answerTable: "\u0924\u093E\u0932\u093F\u0915\u093E",
|
|
6143
6152
|
groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
|
|
6144
6153
|
sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
|
|
6145
6154
|
sourceCountMany: "{count} \u0938\u094D\u0930\u094B\u0924",
|
|
@@ -6222,6 +6231,9 @@ var ES = {
|
|
|
6222
6231
|
conceptAskQuestion: "\xBFC\xF3mo funciona {title} en {product}?",
|
|
6223
6232
|
copyAnswer: "Copiar respuesta",
|
|
6224
6233
|
copyFailed: "No se pudo copiar",
|
|
6234
|
+
readAloud: "Leer en voz alta",
|
|
6235
|
+
stopReading: "Dejar de leer",
|
|
6236
|
+
answerTable: "Tabla",
|
|
6225
6237
|
groundedIn: "En qu\xE9 se basa esta respuesta",
|
|
6226
6238
|
sourceCountOne: "1 fuente",
|
|
6227
6239
|
sourceCountMany: "{count} fuentes",
|
|
@@ -6304,6 +6316,9 @@ var AR = {
|
|
|
6304
6316
|
conceptAskQuestion: "\u0643\u064A\u0641 \u064A\u0639\u0645\u0644 {title} \u0641\u064A {product}\u061F",
|
|
6305
6317
|
copyAnswer: "\u0646\u0633\u062E \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6306
6318
|
copyFailed: "\u062A\u0639\u0630\u0651\u0631 \u0627\u0644\u0646\u0633\u062E",
|
|
6319
|
+
readAloud: "\u0627\u0642\u0631\u0623 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D",
|
|
6320
|
+
stopReading: "\u0625\u064A\u0642\u0627\u0641 \u0627\u0644\u0642\u0631\u0627\u0621\u0629",
|
|
6321
|
+
answerTable: "\u062C\u062F\u0648\u0644",
|
|
6307
6322
|
groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6308
6323
|
sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
|
|
6309
6324
|
sourceCountMany: "{count} \u0645\u0635\u0627\u062F\u0631",
|
|
@@ -6386,6 +6401,9 @@ var TA = {
|
|
|
6386
6401
|
conceptAskQuestion: "{product} \u0B87\u0BB2\u0BCD {title} \u0B8E\u0BAA\u0BCD\u0BAA\u0B9F\u0BBF \u0BB5\u0BC7\u0BB2\u0BC8 \u0B9A\u0BC6\u0BAF\u0BCD\u0B95\u0BBF\u0BB1\u0BA4\u0BC1?",
|
|
6387
6402
|
copyAnswer: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1",
|
|
6388
6403
|
copyFailed: "\u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8",
|
|
6404
|
+
readAloud: "\u0B9A\u0BA4\u0BCD\u0BA4\u0BAE\u0BBE\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF",
|
|
6405
|
+
stopReading: "\u0BAA\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0BA4\u0BC8 \u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1",
|
|
6406
|
+
answerTable: "\u0B85\u0B9F\u0BCD\u0B9F\u0BB5\u0BA3\u0BC8",
|
|
6389
6407
|
groundedIn: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B8E\u0BA4\u0BC8 \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BA4\u0BC1",
|
|
6390
6408
|
sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
|
|
6391
6409
|
sourceCountMany: "{count} \u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
@@ -6417,6 +6435,17 @@ var STRINGS = {
|
|
|
6417
6435
|
ar: AR,
|
|
6418
6436
|
ta: TA
|
|
6419
6437
|
};
|
|
6438
|
+
var SPEECH_TAGS = {
|
|
6439
|
+
en: "en-US",
|
|
6440
|
+
zh: "zh-CN",
|
|
6441
|
+
hi: "hi-IN",
|
|
6442
|
+
es: "es-ES",
|
|
6443
|
+
ar: "ar-SA",
|
|
6444
|
+
ta: "ta-IN"
|
|
6445
|
+
};
|
|
6446
|
+
function speechLocaleOf(locale) {
|
|
6447
|
+
return SPEECH_TAGS[locale];
|
|
6448
|
+
}
|
|
6420
6449
|
function resolveExploreLocale(explicit) {
|
|
6421
6450
|
const candidates = [
|
|
6422
6451
|
explicit,
|
|
@@ -7924,6 +7953,224 @@ function makeOptimisticId() {
|
|
|
7924
7953
|
optimisticCounter += 1;
|
|
7925
7954
|
return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
|
|
7926
7955
|
}
|
|
7956
|
+
var DRAIN_TARGET_MS = 1200;
|
|
7957
|
+
var MIN_CHARS_PER_SECOND = 90;
|
|
7958
|
+
var MAX_CHARS_PER_SECOND = 2200;
|
|
7959
|
+
var MAX_STEP_MS = 250;
|
|
7960
|
+
var COMMIT_INTERVAL_MS = 45;
|
|
7961
|
+
var FALLBACK_STEP_MS = 50;
|
|
7962
|
+
var FENCE = /^ {0,3}(?:```|~~~)/;
|
|
7963
|
+
var TABLE_ROW = /^ {0,3}\|/;
|
|
7964
|
+
var EMPTY_BLOCK_MARKER = /^ {0,3}(?:[-+>]|#{1,6}|\d{1,9}[.)])\s*$/;
|
|
7965
|
+
function isWordCharacter(char) {
|
|
7966
|
+
return char !== void 0 && /[\p{L}\p{N}]/u.test(char);
|
|
7967
|
+
}
|
|
7968
|
+
function clamp(value, min, max) {
|
|
7969
|
+
return Math.min(Math.max(value, min), max);
|
|
7970
|
+
}
|
|
7971
|
+
function now() {
|
|
7972
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
7973
|
+
}
|
|
7974
|
+
function isHighSurrogate(code) {
|
|
7975
|
+
return code >= 55296 && code <= 56319;
|
|
7976
|
+
}
|
|
7977
|
+
function safeInlineEnd(line) {
|
|
7978
|
+
let codeSpan = null;
|
|
7979
|
+
let link = null;
|
|
7980
|
+
const emphasis = [];
|
|
7981
|
+
let at = 0;
|
|
7982
|
+
while (at < line.length) {
|
|
7983
|
+
const char = line[at] ?? "";
|
|
7984
|
+
if (char === "\\") {
|
|
7985
|
+
at += 2;
|
|
7986
|
+
continue;
|
|
7987
|
+
}
|
|
7988
|
+
if (char === "`") {
|
|
7989
|
+
let run = 1;
|
|
7990
|
+
while (line[at + run] === "`") run += 1;
|
|
7991
|
+
codeSpan = codeSpan === null ? at : null;
|
|
7992
|
+
at += run;
|
|
7993
|
+
continue;
|
|
7994
|
+
}
|
|
7995
|
+
if (codeSpan !== null) {
|
|
7996
|
+
at += 1;
|
|
7997
|
+
continue;
|
|
7998
|
+
}
|
|
7999
|
+
if (char === "[") {
|
|
8000
|
+
if (link === null) link = line[at - 1] === "!" ? at - 1 : at;
|
|
8001
|
+
at += 1;
|
|
8002
|
+
continue;
|
|
8003
|
+
}
|
|
8004
|
+
if (char === "]") {
|
|
8005
|
+
if (link !== null && line[at + 1] !== "(") link = null;
|
|
8006
|
+
at += 1;
|
|
8007
|
+
continue;
|
|
8008
|
+
}
|
|
8009
|
+
if (char === ")") {
|
|
8010
|
+
link = null;
|
|
8011
|
+
at += 1;
|
|
8012
|
+
continue;
|
|
8013
|
+
}
|
|
8014
|
+
if (char === "*" || char === "_" || char === "~") {
|
|
8015
|
+
let run = 1;
|
|
8016
|
+
while (line[at + run] === char) run += 1;
|
|
8017
|
+
const start = at;
|
|
8018
|
+
at += run;
|
|
8019
|
+
const before = line[start - 1];
|
|
8020
|
+
const after = line[start + run];
|
|
8021
|
+
if (run < 2) continue;
|
|
8022
|
+
if (char === "_" && isWordCharacter(before) && isWordCharacter(after)) {
|
|
8023
|
+
continue;
|
|
8024
|
+
}
|
|
8025
|
+
const marker = char.repeat(run);
|
|
8026
|
+
const open2 = emphasis.findIndex((entry) => entry.marker === marker);
|
|
8027
|
+
if (open2 !== -1) {
|
|
8028
|
+
emphasis.splice(open2, 1);
|
|
8029
|
+
continue;
|
|
8030
|
+
}
|
|
8031
|
+
if (after !== void 0 && /\s/.test(after)) continue;
|
|
8032
|
+
emphasis.push({ marker, start });
|
|
8033
|
+
continue;
|
|
8034
|
+
}
|
|
8035
|
+
at += 1;
|
|
8036
|
+
}
|
|
8037
|
+
const open = [codeSpan, link, emphasis[0]?.start ?? null].filter(
|
|
8038
|
+
(value) => value !== null
|
|
8039
|
+
);
|
|
8040
|
+
return open.length === 0 ? line.length : Math.min(...open);
|
|
8041
|
+
}
|
|
8042
|
+
function revealBoundary(text, limit) {
|
|
8043
|
+
if (limit <= 0) return 0;
|
|
8044
|
+
const caughtUp = limit >= text.length;
|
|
8045
|
+
const head = caughtUp ? text : text.slice(0, limit);
|
|
8046
|
+
const lineStart = head.lastIndexOf("\n") + 1;
|
|
8047
|
+
const line = head.slice(lineStart);
|
|
8048
|
+
let fenceStart = null;
|
|
8049
|
+
let tableStart = null;
|
|
8050
|
+
let tableRows = 0;
|
|
8051
|
+
let at = 0;
|
|
8052
|
+
while (at < lineStart) {
|
|
8053
|
+
const breakAt = head.indexOf("\n", at);
|
|
8054
|
+
const end = breakAt === -1 ? lineStart : breakAt;
|
|
8055
|
+
const row = head.slice(at, end);
|
|
8056
|
+
if (fenceStart !== null) {
|
|
8057
|
+
if (FENCE.test(row)) fenceStart = null;
|
|
8058
|
+
} else if (FENCE.test(row)) {
|
|
8059
|
+
fenceStart = at;
|
|
8060
|
+
} else if (TABLE_ROW.test(row)) {
|
|
8061
|
+
if (tableStart === null) {
|
|
8062
|
+
tableStart = at;
|
|
8063
|
+
tableRows = 0;
|
|
8064
|
+
}
|
|
8065
|
+
tableRows += 1;
|
|
8066
|
+
} else if (tableStart !== null) {
|
|
8067
|
+
tableStart = null;
|
|
8068
|
+
tableRows = 0;
|
|
8069
|
+
}
|
|
8070
|
+
at = end + 1;
|
|
8071
|
+
}
|
|
8072
|
+
if (fenceStart === null) {
|
|
8073
|
+
const lastIsRow = TABLE_ROW.test(line);
|
|
8074
|
+
if (lastIsRow && tableStart === null) {
|
|
8075
|
+
tableStart = lineStart;
|
|
8076
|
+
tableRows = 0;
|
|
8077
|
+
} else if (!lastIsRow && line !== "") {
|
|
8078
|
+
tableStart = null;
|
|
8079
|
+
tableRows = 0;
|
|
8080
|
+
}
|
|
8081
|
+
if (tableStart !== null && tableRows < 2) return tableStart;
|
|
8082
|
+
}
|
|
8083
|
+
if (caughtUp) return text.length;
|
|
8084
|
+
if (fenceStart !== null) return fenceStart;
|
|
8085
|
+
if (TABLE_ROW.test(line)) return lineStart;
|
|
8086
|
+
if (EMPTY_BLOCK_MARKER.test(line)) return lineStart;
|
|
8087
|
+
const cut = lineStart + safeInlineEnd(line);
|
|
8088
|
+
return isHighSurrogate(text.charCodeAt(cut - 1)) ? cut - 1 : cut;
|
|
8089
|
+
}
|
|
8090
|
+
function prefersReducedMotion() {
|
|
8091
|
+
if (typeof window === "undefined") return true;
|
|
8092
|
+
try {
|
|
8093
|
+
return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
8094
|
+
} catch {
|
|
8095
|
+
return false;
|
|
8096
|
+
}
|
|
8097
|
+
}
|
|
8098
|
+
function useProgressiveReveal(text, settled) {
|
|
8099
|
+
const [, setFrame] = useState(0);
|
|
8100
|
+
const [reduced] = useState(prefersReducedMotion);
|
|
8101
|
+
const immediate = settled || reduced;
|
|
8102
|
+
const textRef = useRef(text);
|
|
8103
|
+
const cursorRef = useRef(immediate ? text.length : 0);
|
|
8104
|
+
const cutRef = useRef(immediate ? text.length : 0);
|
|
8105
|
+
const committedRef = useRef(0);
|
|
8106
|
+
if (text !== textRef.current) {
|
|
8107
|
+
const revealed = textRef.current.slice(0, Math.floor(cursorRef.current));
|
|
8108
|
+
if (revealed !== "" && !text.startsWith(revealed)) {
|
|
8109
|
+
cursorRef.current = text.length;
|
|
8110
|
+
}
|
|
8111
|
+
cursorRef.current = Math.min(cursorRef.current, text.length);
|
|
8112
|
+
cutRef.current = Math.min(cutRef.current, text.length);
|
|
8113
|
+
textRef.current = text;
|
|
8114
|
+
}
|
|
8115
|
+
if (immediate) cursorRef.current = text.length;
|
|
8116
|
+
const cut = immediate ? text.length : Math.max(
|
|
8117
|
+
cutRef.current,
|
|
8118
|
+
revealBoundary(text, Math.floor(cursorRef.current))
|
|
8119
|
+
);
|
|
8120
|
+
cutRef.current = cut;
|
|
8121
|
+
useEffect(() => {
|
|
8122
|
+
if (immediate) return;
|
|
8123
|
+
if (cursorRef.current >= text.length) return;
|
|
8124
|
+
let cancelled = false;
|
|
8125
|
+
let cancelStep = null;
|
|
8126
|
+
let previous = now();
|
|
8127
|
+
const commit = (at, force) => {
|
|
8128
|
+
if (!force && at - committedRef.current < COMMIT_INTERVAL_MS) return;
|
|
8129
|
+
committedRef.current = at;
|
|
8130
|
+
setFrame((value) => value + 1);
|
|
8131
|
+
};
|
|
8132
|
+
const step = () => {
|
|
8133
|
+
cancelStep = null;
|
|
8134
|
+
if (cancelled) return;
|
|
8135
|
+
const at = now();
|
|
8136
|
+
const elapsed = clamp(at - previous, 0, MAX_STEP_MS);
|
|
8137
|
+
previous = at;
|
|
8138
|
+
const length = textRef.current.length;
|
|
8139
|
+
const pending = length - cursorRef.current;
|
|
8140
|
+
if (pending <= 0) {
|
|
8141
|
+
commit(at, true);
|
|
8142
|
+
return;
|
|
8143
|
+
}
|
|
8144
|
+
const perSecond = clamp(
|
|
8145
|
+
pending / (DRAIN_TARGET_MS / 1e3),
|
|
8146
|
+
MIN_CHARS_PER_SECOND,
|
|
8147
|
+
MAX_CHARS_PER_SECOND
|
|
8148
|
+
);
|
|
8149
|
+
cursorRef.current = Math.min(
|
|
8150
|
+
length,
|
|
8151
|
+
cursorRef.current + perSecond * elapsed / 1e3
|
|
8152
|
+
);
|
|
8153
|
+
const done = cursorRef.current >= length;
|
|
8154
|
+
commit(at, done);
|
|
8155
|
+
if (!done) schedule();
|
|
8156
|
+
};
|
|
8157
|
+
const schedule = () => {
|
|
8158
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
8159
|
+
const id2 = window.requestAnimationFrame(step);
|
|
8160
|
+
cancelStep = () => window.cancelAnimationFrame(id2);
|
|
8161
|
+
return;
|
|
8162
|
+
}
|
|
8163
|
+
const id = setTimeout(step, FALLBACK_STEP_MS);
|
|
8164
|
+
cancelStep = () => clearTimeout(id);
|
|
8165
|
+
};
|
|
8166
|
+
schedule();
|
|
8167
|
+
return () => {
|
|
8168
|
+
cancelled = true;
|
|
8169
|
+
cancelStep?.();
|
|
8170
|
+
};
|
|
8171
|
+
}, [text, immediate]);
|
|
8172
|
+
return text.slice(0, cut);
|
|
8173
|
+
}
|
|
7927
8174
|
function getRecognitionCtor() {
|
|
7928
8175
|
if (typeof window === "undefined") return null;
|
|
7929
8176
|
const w = window;
|
|
@@ -8142,6 +8389,141 @@ function useSpeechInput({
|
|
|
8142
8389
|
);
|
|
8143
8390
|
return { supported, listening, interim, error, start, stop, toggle };
|
|
8144
8391
|
}
|
|
8392
|
+
var SILENT_FAILURE_MS = 1500;
|
|
8393
|
+
function speechPlatform() {
|
|
8394
|
+
if (typeof window === "undefined") return null;
|
|
8395
|
+
const scope = window;
|
|
8396
|
+
const synth = scope.speechSynthesis;
|
|
8397
|
+
const Utterance = scope.SpeechSynthesisUtterance;
|
|
8398
|
+
if (!synth || typeof synth.speak !== "function") return null;
|
|
8399
|
+
if (typeof Utterance !== "function") return null;
|
|
8400
|
+
return { synth, Utterance };
|
|
8401
|
+
}
|
|
8402
|
+
function normaliseTag(tag) {
|
|
8403
|
+
return tag.trim().toLowerCase().replace(/_/g, "-");
|
|
8404
|
+
}
|
|
8405
|
+
function primaryOf(tag) {
|
|
8406
|
+
return normaliseTag(tag).split("-")[0] ?? "";
|
|
8407
|
+
}
|
|
8408
|
+
function pickVoice(voices, lang) {
|
|
8409
|
+
const wanted = normaliseTag(lang);
|
|
8410
|
+
if (wanted === "") return null;
|
|
8411
|
+
const primary = primaryOf(wanted);
|
|
8412
|
+
const exact = voices.filter((voice) => normaliseTag(voice.lang) === wanted);
|
|
8413
|
+
const related = voices.filter((voice) => primaryOf(voice.lang) === primary);
|
|
8414
|
+
return exact.find((voice) => voice.default) ?? exact[0] ?? related.find((voice) => voice.default) ?? related[0] ?? null;
|
|
8415
|
+
}
|
|
8416
|
+
var activeOwner = null;
|
|
8417
|
+
var activeStop = null;
|
|
8418
|
+
function stopSpeaking() {
|
|
8419
|
+
activeStop?.();
|
|
8420
|
+
}
|
|
8421
|
+
function useSpeechOutput({
|
|
8422
|
+
lang
|
|
8423
|
+
} = {}) {
|
|
8424
|
+
const [available, setAvailable] = useState(() => speechPlatform() !== null);
|
|
8425
|
+
const [speaking, setSpeaking] = useState(false);
|
|
8426
|
+
const utteranceRef = useRef(null);
|
|
8427
|
+
const watchdogRef = useRef(null);
|
|
8428
|
+
const ownerRef = useRef({});
|
|
8429
|
+
const stopRef = useRef(() => void 0);
|
|
8430
|
+
const langRef = useRef(lang);
|
|
8431
|
+
langRef.current = lang;
|
|
8432
|
+
const clearWatchdog = useCallback(() => {
|
|
8433
|
+
if (watchdogRef.current === null) return;
|
|
8434
|
+
clearTimeout(watchdogRef.current);
|
|
8435
|
+
watchdogRef.current = null;
|
|
8436
|
+
}, []);
|
|
8437
|
+
const settle = useCallback(() => {
|
|
8438
|
+
clearWatchdog();
|
|
8439
|
+
utteranceRef.current = null;
|
|
8440
|
+
if (activeOwner === ownerRef.current) {
|
|
8441
|
+
activeOwner = null;
|
|
8442
|
+
activeStop = null;
|
|
8443
|
+
}
|
|
8444
|
+
setSpeaking(false);
|
|
8445
|
+
}, [clearWatchdog]);
|
|
8446
|
+
const stop = useCallback(() => {
|
|
8447
|
+
const owned = utteranceRef.current !== null;
|
|
8448
|
+
settle();
|
|
8449
|
+
if (owned) speechPlatform()?.synth.cancel();
|
|
8450
|
+
}, [settle]);
|
|
8451
|
+
stopRef.current = stop;
|
|
8452
|
+
const speak = useCallback(
|
|
8453
|
+
(text) => {
|
|
8454
|
+
const platform = speechPlatform();
|
|
8455
|
+
if (!platform) {
|
|
8456
|
+
setAvailable(false);
|
|
8457
|
+
return;
|
|
8458
|
+
}
|
|
8459
|
+
const spoken = text.trim();
|
|
8460
|
+
if (spoken === "") return;
|
|
8461
|
+
if (activeStop && activeOwner !== ownerRef.current) activeStop();
|
|
8462
|
+
platform.synth.cancel();
|
|
8463
|
+
const utterance = new platform.Utterance(spoken);
|
|
8464
|
+
const wanted = langRef.current;
|
|
8465
|
+
if (wanted !== void 0 && wanted !== "") {
|
|
8466
|
+
const voice = pickVoice(platform.synth.getVoices(), wanted);
|
|
8467
|
+
utterance.lang = voice?.lang ?? wanted;
|
|
8468
|
+
if (voice) utterance.voice = voice;
|
|
8469
|
+
}
|
|
8470
|
+
const mine = () => utteranceRef.current === utterance;
|
|
8471
|
+
utterance.onstart = () => {
|
|
8472
|
+
if (!mine()) return;
|
|
8473
|
+
clearWatchdog();
|
|
8474
|
+
setSpeaking(true);
|
|
8475
|
+
};
|
|
8476
|
+
utterance.onend = () => {
|
|
8477
|
+
if (!mine()) return;
|
|
8478
|
+
settle();
|
|
8479
|
+
};
|
|
8480
|
+
utterance.onerror = (event) => {
|
|
8481
|
+
if (!mine()) return;
|
|
8482
|
+
const code = typeof event?.error === "string" ? event.error : "";
|
|
8483
|
+
settle();
|
|
8484
|
+
if (code !== "interrupted" && code !== "canceled") setAvailable(false);
|
|
8485
|
+
};
|
|
8486
|
+
utteranceRef.current = utterance;
|
|
8487
|
+
activeOwner = ownerRef.current;
|
|
8488
|
+
activeStop = () => {
|
|
8489
|
+
stopRef.current();
|
|
8490
|
+
};
|
|
8491
|
+
setSpeaking(true);
|
|
8492
|
+
platform.synth.speak(utterance);
|
|
8493
|
+
clearWatchdog();
|
|
8494
|
+
watchdogRef.current = setTimeout(() => {
|
|
8495
|
+
watchdogRef.current = null;
|
|
8496
|
+
if (!mine()) return;
|
|
8497
|
+
if (platform.synth.speaking) return;
|
|
8498
|
+
settle();
|
|
8499
|
+
setAvailable(false);
|
|
8500
|
+
}, SILENT_FAILURE_MS);
|
|
8501
|
+
},
|
|
8502
|
+
[clearWatchdog, settle]
|
|
8503
|
+
);
|
|
8504
|
+
const toggle = useCallback(
|
|
8505
|
+
(text) => {
|
|
8506
|
+
if (speaking) stop();
|
|
8507
|
+
else speak(text);
|
|
8508
|
+
},
|
|
8509
|
+
[speak, speaking, stop]
|
|
8510
|
+
);
|
|
8511
|
+
useEffect(() => {
|
|
8512
|
+
if (!speaking || typeof window === "undefined") return;
|
|
8513
|
+
const onHide = () => {
|
|
8514
|
+
stopRef.current();
|
|
8515
|
+
};
|
|
8516
|
+
window.addEventListener("pagehide", onHide);
|
|
8517
|
+
return () => window.removeEventListener("pagehide", onHide);
|
|
8518
|
+
}, [speaking]);
|
|
8519
|
+
useEffect(
|
|
8520
|
+
() => () => {
|
|
8521
|
+
stopRef.current();
|
|
8522
|
+
},
|
|
8523
|
+
[]
|
|
8524
|
+
);
|
|
8525
|
+
return { supported: available, speaking, speak, stop, toggle };
|
|
8526
|
+
}
|
|
8145
8527
|
var SWIPE_THRESHOLD = 40;
|
|
8146
8528
|
function useSwipe({
|
|
8147
8529
|
onSwipeLeft,
|
|
@@ -8409,6 +8791,115 @@ var EXPLORE_CSS = `
|
|
|
8409
8791
|
height: auto;
|
|
8410
8792
|
}
|
|
8411
8793
|
|
|
8794
|
+
/* ---- Comparison and pricing tables ----------------------------------------------------
|
|
8795
|
+
The harness emits a comparison, and a set of plans, as a GFM table whose FIRST column is
|
|
8796
|
+
the subject \u2014 the product, or the plan (CONTRACT.md \xA77). Two things have to be true of it:
|
|
8797
|
+
the page must not scroll sideways because of it, and it has to be readable on a 320px
|
|
8798
|
+
phone, which a four-column grid of 1px borders is not.
|
|
8799
|
+
|
|
8800
|
+
Wide: a contained scroller. \`max-width: 100%\` keeps the box inside the bubble and
|
|
8801
|
+
\`overflow-x: auto\` keeps the columns inside the box, so the widest possible table still
|
|
8802
|
+
cannot widen the document. \`overscroll-behavior-x: contain\` stops a swipe that runs out
|
|
8803
|
+
of table from chaining to the page \u2014 the same rule the transcript needed. */
|
|
8804
|
+
.boff-explore-body .boff-explore-table {
|
|
8805
|
+
max-width: 100%;
|
|
8806
|
+
overflow-x: auto;
|
|
8807
|
+
overscroll-behavior-x: contain;
|
|
8808
|
+
margin: 0.75rem 0;
|
|
8809
|
+
border: 1px solid hsl(var(--border));
|
|
8810
|
+
border-radius: 0.75rem;
|
|
8811
|
+
background-color: hsl(var(--card));
|
|
8812
|
+
}
|
|
8813
|
+
.boff-explore-body .boff-explore-table:focus-visible {
|
|
8814
|
+
outline: 2px solid hsl(var(--ring));
|
|
8815
|
+
outline-offset: 2px;
|
|
8816
|
+
}
|
|
8817
|
+
.boff-explore-body .boff-explore-table table {
|
|
8818
|
+
/* Beats the blanket \`display: block\` above, which is the unwrapped fallback. */
|
|
8819
|
+
display: table;
|
|
8820
|
+
width: 100%;
|
|
8821
|
+
max-width: none;
|
|
8822
|
+
margin: 0;
|
|
8823
|
+
border-collapse: collapse;
|
|
8824
|
+
font-size: 0.8125rem;
|
|
8825
|
+
}
|
|
8826
|
+
.boff-explore-body .boff-explore-table th,
|
|
8827
|
+
.boff-explore-body .boff-explore-table td {
|
|
8828
|
+
border: 0;
|
|
8829
|
+
border-top: 1px solid hsl(var(--border));
|
|
8830
|
+
padding: 0.5rem 0.75rem;
|
|
8831
|
+
/* \`start\`, never \`left\`: the page root carries dir="rtl" in Arabic, and a left-aligned
|
|
8832
|
+
table there reads against the grain of every other line on the page. */
|
|
8833
|
+
text-align: start;
|
|
8834
|
+
vertical-align: top;
|
|
8835
|
+
overflow-wrap: anywhere;
|
|
8836
|
+
/* Prices in a column line up under each other instead of drifting by digit width. */
|
|
8837
|
+
font-variant-numeric: tabular-nums;
|
|
8838
|
+
min-width: 6rem;
|
|
8839
|
+
}
|
|
8840
|
+
.boff-explore-body .boff-explore-table thead th {
|
|
8841
|
+
border-top: 0;
|
|
8842
|
+
background-color: hsl(var(--muted));
|
|
8843
|
+
color: hsl(var(--foreground));
|
|
8844
|
+
font-weight: 600;
|
|
8845
|
+
white-space: nowrap;
|
|
8846
|
+
}
|
|
8847
|
+
/* The first column is what the row is ABOUT \u2014 the product, or the plan name. Reading it as
|
|
8848
|
+
the row's heading is what makes a price list scannable rather than a grid of strings. */
|
|
8849
|
+
.boff-explore-body .boff-explore-table tbody td:first-child {
|
|
8850
|
+
font-weight: 600;
|
|
8851
|
+
color: hsl(var(--card-foreground));
|
|
8852
|
+
}
|
|
8853
|
+
|
|
8854
|
+
/* Narrow: one card per row. Each cell prints its own column heading, so a value is never
|
|
8855
|
+
stranded without the question it answers, and the subject cell becomes the card's title.
|
|
8856
|
+
A media query rather than a measured width \u2014 these pages are serialised post-hydration,
|
|
8857
|
+
so anything measured here would ship to every phone as static HTML. */
|
|
8858
|
+
@media (max-width: 30rem) {
|
|
8859
|
+
.boff-explore-body .boff-explore-table {
|
|
8860
|
+
overflow-x: visible;
|
|
8861
|
+
}
|
|
8862
|
+
.boff-explore-body .boff-explore-table table,
|
|
8863
|
+
.boff-explore-body .boff-explore-table tbody,
|
|
8864
|
+
.boff-explore-body .boff-explore-table tr,
|
|
8865
|
+
.boff-explore-body .boff-explore-table td {
|
|
8866
|
+
display: block;
|
|
8867
|
+
width: 100%;
|
|
8868
|
+
min-width: 0;
|
|
8869
|
+
}
|
|
8870
|
+
.boff-explore-body .boff-explore-table thead {
|
|
8871
|
+
display: none;
|
|
8872
|
+
}
|
|
8873
|
+
.boff-explore-body .boff-explore-table tr {
|
|
8874
|
+
border-top: 1px solid hsl(var(--border));
|
|
8875
|
+
padding: 0.5rem 0;
|
|
8876
|
+
}
|
|
8877
|
+
.boff-explore-body .boff-explore-table tr:first-child {
|
|
8878
|
+
border-top: 0;
|
|
8879
|
+
}
|
|
8880
|
+
.boff-explore-body .boff-explore-table td {
|
|
8881
|
+
border: 0;
|
|
8882
|
+
padding: 0.125rem 0.75rem;
|
|
8883
|
+
}
|
|
8884
|
+
.boff-explore-body .boff-explore-table td[data-label]::before {
|
|
8885
|
+
content: attr(data-label);
|
|
8886
|
+
display: block;
|
|
8887
|
+
font-size: 0.6875rem;
|
|
8888
|
+
font-weight: 600;
|
|
8889
|
+
text-transform: uppercase;
|
|
8890
|
+
letter-spacing: 0.04em;
|
|
8891
|
+
color: hsl(var(--muted-foreground));
|
|
8892
|
+
}
|
|
8893
|
+
.boff-explore-body .boff-explore-table tbody td:first-child {
|
|
8894
|
+
font-size: 0.9375rem;
|
|
8895
|
+
padding-bottom: 0.25rem;
|
|
8896
|
+
}
|
|
8897
|
+
.boff-explore-body .boff-explore-table tbody td:first-child::before {
|
|
8898
|
+
/* The plan's own name is the heading here; repeating "Plan" over it says nothing. */
|
|
8899
|
+
display: none;
|
|
8900
|
+
}
|
|
8901
|
+
}
|
|
8902
|
+
|
|
8412
8903
|
/* ---- Ambient backdrop -----------------------------------------------------------------
|
|
8413
8904
|
Two very low-opacity radial washes behind the welcome state, drifting slowly. Painted on
|
|
8414
8905
|
a pseudo-element with pointer-events:none so it can never intercept a click \u2014 a
|
|
@@ -8580,7 +9071,7 @@ function isOwnElement(el, root) {
|
|
|
8580
9071
|
function visualViewportHeight() {
|
|
8581
9072
|
return window.visualViewport?.height ?? window.innerHeight;
|
|
8582
9073
|
}
|
|
8583
|
-
function
|
|
9074
|
+
function clamp2(value, min, max) {
|
|
8584
9075
|
return Math.min(Math.max(value, min), max);
|
|
8585
9076
|
}
|
|
8586
9077
|
function isRestoredNavigation() {
|
|
@@ -8730,11 +9221,80 @@ function summariseReferences(references, origins, productNames) {
|
|
|
8730
9221
|
};
|
|
8731
9222
|
}
|
|
8732
9223
|
var CODE_FENCE = /^\s*(?:```|~~~)/;
|
|
8733
|
-
|
|
9224
|
+
var TABLE_ROW_LINE = /^\s{0,3}\|/;
|
|
9225
|
+
var TABLE_DELIMITER_ROW = /^\s{0,3}\|[\s:|-]*-[\s:|-]*$/;
|
|
9226
|
+
function readableLine(raw, mode) {
|
|
9227
|
+
let line = raw;
|
|
9228
|
+
line = line.replace(/!\[[^\]]*\]\([^)\s]*(?:\s+"[^"]*")?\)/g, "");
|
|
9229
|
+
line = mode === "speech" ? (
|
|
9230
|
+
// A voice reading "h-t-t-p-s colon slash slash…" mid-sentence is noise, and the
|
|
9231
|
+
// prompt asks for two to five links in every answer. The label IS the words.
|
|
9232
|
+
line.replace(/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, "$1")
|
|
9233
|
+
) : line.replace(/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, "$1 ($2)");
|
|
9234
|
+
line = mode === "speech" ? line.replace(/<(https?:\/\/[^>\s]+)>/g, "") : line.replace(/<(https?:\/\/[^>\s]+)>/g, "$1");
|
|
9235
|
+
line = line.replace(/^\s{0,3}#{1,6}\s+/, "");
|
|
9236
|
+
line = line.replace(/^\s{0,3}>\s?/, "");
|
|
9237
|
+
if (/^\s{0,3}([-*_])[ \t]*(?:\1[ \t]*){2,}$/.test(line)) return "";
|
|
9238
|
+
line = line.replace(/`([^`]+)`/g, "$1");
|
|
9239
|
+
line = line.replace(/\*\*([^*]+)\*\*/g, "$1");
|
|
9240
|
+
line = line.replace(/__([^_]+)__/g, "$1");
|
|
9241
|
+
line = line.replace(/(^|[^*\w])\*([^*\n]+)\*(?![*\w])/g, "$1$2");
|
|
9242
|
+
line = line.replace(/(^|[^_\w])_([^_\n]+)_(?![_\w])/g, "$1$2");
|
|
9243
|
+
return line.replace(/[ \t]+$/, "");
|
|
9244
|
+
}
|
|
9245
|
+
function tableCells(row) {
|
|
9246
|
+
const trimmed = row.trim();
|
|
9247
|
+
const cells = [];
|
|
9248
|
+
let cell = "";
|
|
9249
|
+
for (let at = 0; at < trimmed.length; at += 1) {
|
|
9250
|
+
const char = trimmed[at] ?? "";
|
|
9251
|
+
if (char === "\\") {
|
|
9252
|
+
cell += char + (trimmed[at + 1] ?? "");
|
|
9253
|
+
at += 1;
|
|
9254
|
+
continue;
|
|
9255
|
+
}
|
|
9256
|
+
if (char === "|") {
|
|
9257
|
+
cells.push(cell.trim());
|
|
9258
|
+
cell = "";
|
|
9259
|
+
continue;
|
|
9260
|
+
}
|
|
9261
|
+
cell += char;
|
|
9262
|
+
}
|
|
9263
|
+
cells.push(cell.trim());
|
|
9264
|
+
if (trimmed.startsWith("|") && cells[0] === "") cells.shift();
|
|
9265
|
+
if (trimmed.endsWith("|") && cells[cells.length - 1] === "") cells.pop();
|
|
9266
|
+
return cells;
|
|
9267
|
+
}
|
|
9268
|
+
function asSentence(text) {
|
|
9269
|
+
return /[.!?]$/.test(text) ? text : `${text}.`;
|
|
9270
|
+
}
|
|
9271
|
+
function spokenTable(rows) {
|
|
9272
|
+
if (rows.length < 2 || !TABLE_DELIMITER_ROW.test(rows[1] ?? "")) return rows;
|
|
9273
|
+
const labels = tableCells(rows[0] ?? "");
|
|
9274
|
+
const spoken = [];
|
|
9275
|
+
for (const row of rows.slice(2)) {
|
|
9276
|
+
const parts = [];
|
|
9277
|
+
tableCells(row).forEach((value, column) => {
|
|
9278
|
+
if (value === "") return;
|
|
9279
|
+
const label = column === 0 ? "" : labels[column] ?? "";
|
|
9280
|
+
parts.push(label === "" ? value : `${label}: ${value}`);
|
|
9281
|
+
});
|
|
9282
|
+
if (parts.length > 0) spoken.push(asSentence(parts.join(". ")));
|
|
9283
|
+
}
|
|
9284
|
+
return spoken;
|
|
9285
|
+
}
|
|
9286
|
+
function readableText(markdown, mode) {
|
|
8734
9287
|
const lines = [];
|
|
8735
9288
|
let inFence = false;
|
|
9289
|
+
let table = [];
|
|
9290
|
+
const flushTable = () => {
|
|
9291
|
+
if (table.length === 0) return;
|
|
9292
|
+
for (const line of spokenTable(table)) lines.push(readableLine(line, mode));
|
|
9293
|
+
table = [];
|
|
9294
|
+
};
|
|
8736
9295
|
for (const raw of markdown.split("\n")) {
|
|
8737
9296
|
if (CODE_FENCE.test(raw)) {
|
|
9297
|
+
flushTable();
|
|
8738
9298
|
inFence = !inFence;
|
|
8739
9299
|
continue;
|
|
8740
9300
|
}
|
|
@@ -8742,33 +9302,30 @@ function answerPlainText(markdown) {
|
|
|
8742
9302
|
lines.push(raw);
|
|
8743
9303
|
continue;
|
|
8744
9304
|
}
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
line = line.replace(/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, "$1 ($2)");
|
|
8748
|
-
line = line.replace(/<(https?:\/\/[^>\s]+)>/g, "$1");
|
|
8749
|
-
line = line.replace(/^\s{0,3}#{1,6}\s+/, "");
|
|
8750
|
-
line = line.replace(/^\s{0,3}>\s?/, "");
|
|
8751
|
-
if (/^\s{0,3}([-*_])[ \t]*(?:\1[ \t]*){2,}$/.test(line)) {
|
|
8752
|
-
lines.push("");
|
|
9305
|
+
if (mode === "speech" && TABLE_ROW_LINE.test(raw)) {
|
|
9306
|
+
table.push(raw);
|
|
8753
9307
|
continue;
|
|
8754
9308
|
}
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
line = line.replace(/__([^_]+)__/g, "$1");
|
|
8758
|
-
line = line.replace(/(^|[^*\w])\*([^*\n]+)\*(?![*\w])/g, "$1$2");
|
|
8759
|
-
line = line.replace(/(^|[^_\w])_([^_\n]+)_(?![_\w])/g, "$1$2");
|
|
8760
|
-
lines.push(line.replace(/[ \t]+$/, ""));
|
|
9309
|
+
flushTable();
|
|
9310
|
+
lines.push(readableLine(raw, mode));
|
|
8761
9311
|
}
|
|
9312
|
+
flushTable();
|
|
8762
9313
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
8763
9314
|
}
|
|
8764
|
-
|
|
9315
|
+
function answerPlainText(markdown) {
|
|
9316
|
+
return readableText(markdown, "clipboard");
|
|
9317
|
+
}
|
|
9318
|
+
function answerSpeechText(markdown) {
|
|
9319
|
+
return readableText(markdown, "speech");
|
|
9320
|
+
}
|
|
9321
|
+
var AnswerScopeContext = createContext(null);
|
|
8765
9322
|
var InsideLinkContext = createContext(false);
|
|
8766
9323
|
function AnswerLink(props) {
|
|
8767
9324
|
return /* @__PURE__ */ jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsx(MarkdownLink, { ...props }) });
|
|
8768
9325
|
}
|
|
8769
9326
|
var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
|
|
8770
9327
|
function InlineConceptImage({ src, alt }) {
|
|
8771
|
-
const scope = useContext(
|
|
9328
|
+
const scope = useContext(AnswerScopeContext);
|
|
8772
9329
|
const insideLink = useContext(InsideLinkContext);
|
|
8773
9330
|
if (!scope || !scope.enabled || !isInlineImageAllowed(src, scope.origins) || scope.failed.has(src)) {
|
|
8774
9331
|
return null;
|
|
@@ -8816,9 +9373,70 @@ function InlineConceptImage({ src, alt }) {
|
|
|
8816
9373
|
}
|
|
8817
9374
|
) });
|
|
8818
9375
|
}
|
|
9376
|
+
function markdownText(node) {
|
|
9377
|
+
if (!node) return "";
|
|
9378
|
+
if (typeof node.value === "string") return node.value;
|
|
9379
|
+
return (node.children ?? []).map(markdownText).join("");
|
|
9380
|
+
}
|
|
9381
|
+
function hasHeaderCells(node) {
|
|
9382
|
+
return (node?.children ?? []).some((cell) => cell.tagName === "th");
|
|
9383
|
+
}
|
|
9384
|
+
function findHeaderRow(node) {
|
|
9385
|
+
for (const child of node?.children ?? []) {
|
|
9386
|
+
if (child.tagName === "tr" && hasHeaderCells(child)) return child;
|
|
9387
|
+
const nested = findHeaderRow(child);
|
|
9388
|
+
if (nested !== null) return nested;
|
|
9389
|
+
}
|
|
9390
|
+
return null;
|
|
9391
|
+
}
|
|
9392
|
+
function tableColumnLabels(node) {
|
|
9393
|
+
const row = findHeaderRow(node);
|
|
9394
|
+
if (row === null) return [];
|
|
9395
|
+
return (row.children ?? []).filter((cell) => cell.tagName === "th").map((cell) => markdownText(cell).trim());
|
|
9396
|
+
}
|
|
9397
|
+
var TableColumnsContext = createContext([]);
|
|
9398
|
+
function AnswerTable({ node, children }) {
|
|
9399
|
+
const scope = useContext(AnswerScopeContext);
|
|
9400
|
+
const table = /* @__PURE__ */ jsx(TableColumnsContext.Provider, { value: tableColumnLabels(node), children: /* @__PURE__ */ jsx("table", { children }) });
|
|
9401
|
+
if (!scope) return table;
|
|
9402
|
+
return /* @__PURE__ */ jsx(
|
|
9403
|
+
"div",
|
|
9404
|
+
{
|
|
9405
|
+
"data-boff-explore": "table",
|
|
9406
|
+
role: "region",
|
|
9407
|
+
"aria-label": scope.strings.answerTable,
|
|
9408
|
+
tabIndex: 0,
|
|
9409
|
+
className: "boff-explore-table",
|
|
9410
|
+
children: table
|
|
9411
|
+
}
|
|
9412
|
+
);
|
|
9413
|
+
}
|
|
9414
|
+
function AnswerTableRow({
|
|
9415
|
+
node,
|
|
9416
|
+
children,
|
|
9417
|
+
...props
|
|
9418
|
+
}) {
|
|
9419
|
+
const labels = useContext(TableColumnsContext);
|
|
9420
|
+
if (labels.length === 0 || hasHeaderCells(node)) {
|
|
9421
|
+
return /* @__PURE__ */ jsx("tr", { ...props, children });
|
|
9422
|
+
}
|
|
9423
|
+
let column = 0;
|
|
9424
|
+
const cells = Children.map(children, (cell) => {
|
|
9425
|
+
if (!isValidElement(cell)) return cell;
|
|
9426
|
+
const label = labels[column] ?? "";
|
|
9427
|
+
column += 1;
|
|
9428
|
+
if (label === "") return cell;
|
|
9429
|
+
return cloneElement(cell, {
|
|
9430
|
+
"data-label": label
|
|
9431
|
+
});
|
|
9432
|
+
});
|
|
9433
|
+
return /* @__PURE__ */ jsx("tr", { ...props, children: cells });
|
|
9434
|
+
}
|
|
8819
9435
|
var ANSWER_MARKDOWN_COMPONENTS = {
|
|
8820
9436
|
a: AnswerLink,
|
|
8821
|
-
img: InlineConceptImage
|
|
9437
|
+
img: InlineConceptImage,
|
|
9438
|
+
table: AnswerTable,
|
|
9439
|
+
tr: AnswerTableRow
|
|
8822
9440
|
};
|
|
8823
9441
|
function ReferenceCard({
|
|
8824
9442
|
reference,
|
|
@@ -9207,9 +9825,42 @@ function ProvenanceChips({
|
|
|
9207
9825
|
);
|
|
9208
9826
|
}
|
|
9209
9827
|
var COPY_FEEDBACK_MS = 2500;
|
|
9828
|
+
var ANSWER_ACTION_PILL = "inline-flex max-w-full items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
|
|
9829
|
+
var ANSWER_ACTION_IDLE = "border-border bg-card text-muted-foreground hover:border-primary/40 hover:bg-accent hover:text-foreground";
|
|
9830
|
+
var ANSWER_ACTION_ACTIVE = "border-primary/40 bg-accent text-primary";
|
|
9831
|
+
function ReadAloudButton({
|
|
9832
|
+
strings: T,
|
|
9833
|
+
text,
|
|
9834
|
+
lang
|
|
9835
|
+
}) {
|
|
9836
|
+
const speech = useSpeechOutput({ lang });
|
|
9837
|
+
if (!speech.supported) return null;
|
|
9838
|
+
const label = speech.speaking ? T.stopReading : T.readAloud;
|
|
9839
|
+
return /* @__PURE__ */ jsxs(
|
|
9840
|
+
"button",
|
|
9841
|
+
{
|
|
9842
|
+
"data-boff-explore": "read-aloud",
|
|
9843
|
+
"data-speaking": speech.speaking ? "true" : "false",
|
|
9844
|
+
type: "button",
|
|
9845
|
+
title: label,
|
|
9846
|
+
"aria-pressed": speech.speaking,
|
|
9847
|
+
onClick: () => speech.toggle(text),
|
|
9848
|
+
className: cn(
|
|
9849
|
+
ANSWER_ACTION_PILL,
|
|
9850
|
+
speech.speaking ? ANSWER_ACTION_ACTIVE : ANSWER_ACTION_IDLE
|
|
9851
|
+
),
|
|
9852
|
+
children: [
|
|
9853
|
+
/* @__PURE__ */ jsx(Volume2, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }),
|
|
9854
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: label })
|
|
9855
|
+
]
|
|
9856
|
+
}
|
|
9857
|
+
);
|
|
9858
|
+
}
|
|
9210
9859
|
function AnswerActions({
|
|
9211
9860
|
strings: T,
|
|
9212
|
-
text
|
|
9861
|
+
text,
|
|
9862
|
+
speechText,
|
|
9863
|
+
speechLang
|
|
9213
9864
|
}) {
|
|
9214
9865
|
const [outcome, setOutcome] = useState("idle");
|
|
9215
9866
|
const resetRef = useRef(null);
|
|
@@ -9252,9 +9903,8 @@ function AnswerActions({
|
|
|
9252
9903
|
void copy();
|
|
9253
9904
|
},
|
|
9254
9905
|
className: cn(
|
|
9255
|
-
|
|
9256
|
-
"
|
|
9257
|
-
outcome === "failed" ? "border-destructive/40 bg-card text-destructive" : "border-border bg-card text-muted-foreground hover:border-primary/40 hover:bg-accent hover:text-foreground"
|
|
9906
|
+
ANSWER_ACTION_PILL,
|
|
9907
|
+
outcome === "failed" ? "border-destructive/40 bg-card text-destructive" : ANSWER_ACTION_IDLE
|
|
9258
9908
|
),
|
|
9259
9909
|
children: [
|
|
9260
9910
|
outcome === "copied" ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }),
|
|
@@ -9262,6 +9912,7 @@ function AnswerActions({
|
|
|
9262
9912
|
]
|
|
9263
9913
|
}
|
|
9264
9914
|
),
|
|
9915
|
+
/* @__PURE__ */ jsx(ReadAloudButton, { strings: T, text: speechText, lang: speechLang }),
|
|
9265
9916
|
/* @__PURE__ */ jsx("span", { "data-boff-explore": "copy-status", role: "status", className: "sr-only", children: outcome === "idle" ? "" : label })
|
|
9266
9917
|
]
|
|
9267
9918
|
}
|
|
@@ -9313,6 +9964,7 @@ function AssistantBubble({
|
|
|
9313
9964
|
activity,
|
|
9314
9965
|
imageOrigins,
|
|
9315
9966
|
productNames,
|
|
9967
|
+
speechLang,
|
|
9316
9968
|
onNavigate,
|
|
9317
9969
|
anchorRef,
|
|
9318
9970
|
onFollow,
|
|
@@ -9323,6 +9975,7 @@ function AssistantBubble({
|
|
|
9323
9975
|
const body = message.content || message.partialContent || "";
|
|
9324
9976
|
const failed = message.status === "FAILED";
|
|
9325
9977
|
const completed = message.status === "COMPLETED";
|
|
9978
|
+
const visible = useProgressiveReveal(body, !streaming);
|
|
9326
9979
|
const [failedImages, setFailedImages] = useState(
|
|
9327
9980
|
() => /* @__PURE__ */ new Set()
|
|
9328
9981
|
);
|
|
@@ -9331,7 +9984,7 @@ function AssistantBubble({
|
|
|
9331
9984
|
(current) => current.has(src) ? current : new Set(current).add(src)
|
|
9332
9985
|
);
|
|
9333
9986
|
}, []);
|
|
9334
|
-
const
|
|
9987
|
+
const answerScope = useMemo(
|
|
9335
9988
|
() => ({
|
|
9336
9989
|
strings: T,
|
|
9337
9990
|
enabled: completed,
|
|
@@ -9349,6 +10002,10 @@ function AssistantBubble({
|
|
|
9349
10002
|
() => answerPlainText(message.content),
|
|
9350
10003
|
[message.content]
|
|
9351
10004
|
);
|
|
10005
|
+
const speechText = useMemo(
|
|
10006
|
+
() => answerSpeechText(message.content),
|
|
10007
|
+
[message.content]
|
|
10008
|
+
);
|
|
9352
10009
|
const grounded = completed && message.answered !== false;
|
|
9353
10010
|
return /* @__PURE__ */ jsxs(
|
|
9354
10011
|
"div",
|
|
@@ -9395,8 +10052,8 @@ function AssistantBubble({
|
|
|
9395
10052
|
]
|
|
9396
10053
|
}
|
|
9397
10054
|
) : null,
|
|
9398
|
-
|
|
9399
|
-
/* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsx(
|
|
10055
|
+
visible ? /* @__PURE__ */ jsxs("div", { className: "rounded-2xl rounded-tl-md border border-border bg-card px-4 py-3 shadow-sm", children: [
|
|
10056
|
+
/* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsx(AnswerScopeContext.Provider, { value: answerScope, children: /* @__PURE__ */ jsx(Markdown, { components: ANSWER_MARKDOWN_COMPONENTS, children: visible }) }) }),
|
|
9400
10057
|
streaming ? /* @__PURE__ */ jsx("span", { className: "boff-explore-caret", "aria-hidden": "true" }) : null
|
|
9401
10058
|
] }) : null,
|
|
9402
10059
|
grounded && provenance.total > 0 ? /* @__PURE__ */ jsx(ProvenanceChips, { strings: T, provenance }) : null,
|
|
@@ -9439,7 +10096,15 @@ function AssistantBubble({
|
|
|
9439
10096
|
question
|
|
9440
10097
|
)) })
|
|
9441
10098
|
] }) : null,
|
|
9442
|
-
completed && copyText !== "" ? /* @__PURE__ */ jsx(
|
|
10099
|
+
completed && copyText !== "" ? /* @__PURE__ */ jsx(
|
|
10100
|
+
AnswerActions,
|
|
10101
|
+
{
|
|
10102
|
+
strings: T,
|
|
10103
|
+
text: copyText,
|
|
10104
|
+
speechText,
|
|
10105
|
+
speechLang
|
|
10106
|
+
}
|
|
10107
|
+
) : null,
|
|
9443
10108
|
completed && onFeedback ? /* @__PURE__ */ jsx(
|
|
9444
10109
|
AnswerFeedback,
|
|
9445
10110
|
{
|
|
@@ -9673,7 +10338,7 @@ function ConceptStrip({
|
|
|
9673
10338
|
"div",
|
|
9674
10339
|
{
|
|
9675
10340
|
"data-boff-explore": "concept-strip-block",
|
|
9676
|
-
className: "boff-explore-rise boff-explore-rise-
|
|
10341
|
+
className: "boff-explore-rise boff-explore-rise-1 mt-6",
|
|
9677
10342
|
children: [
|
|
9678
10343
|
/* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: T.conceptStripTitle }),
|
|
9679
10344
|
/* @__PURE__ */ jsx(
|
|
@@ -9863,6 +10528,15 @@ function WelcomeState({
|
|
|
9863
10528
|
/* @__PURE__ */ jsx("h1", { className: "mt-4 text-balance break-words text-2xl font-bold tracking-tight sm:text-4xl", children: title }),
|
|
9864
10529
|
/* @__PURE__ */ jsx("p", { className: "mx-auto mt-2.5 max-w-2xl text-pretty text-sm leading-relaxed text-muted-foreground sm:text-lg", children: body })
|
|
9865
10530
|
] }),
|
|
10531
|
+
/* @__PURE__ */ jsx(
|
|
10532
|
+
ConceptStrip,
|
|
10533
|
+
{
|
|
10534
|
+
strings: T,
|
|
10535
|
+
highlights: conceptHighlights,
|
|
10536
|
+
onAsk: onPrompt,
|
|
10537
|
+
disabled
|
|
10538
|
+
}
|
|
10539
|
+
),
|
|
9866
10540
|
/* @__PURE__ */ jsx("ul", { className: "boff-explore-rise boff-explore-rise-1 mt-6 grid grid-cols-3 gap-2 sm:mt-7 sm:gap-2.5", children: CAPABILITIES.map(({ icon: Icon, body: capBody }, i) => /* @__PURE__ */ jsxs(
|
|
9867
10541
|
"li",
|
|
9868
10542
|
{
|
|
@@ -9887,15 +10561,6 @@ function WelcomeState({
|
|
|
9887
10561
|
}
|
|
9888
10562
|
)
|
|
9889
10563
|
] }) : null,
|
|
9890
|
-
/* @__PURE__ */ jsx(
|
|
9891
|
-
ConceptStrip,
|
|
9892
|
-
{
|
|
9893
|
-
strings: T,
|
|
9894
|
-
highlights: conceptHighlights,
|
|
9895
|
-
onAsk: onPrompt,
|
|
9896
|
-
disabled
|
|
9897
|
-
}
|
|
9898
|
-
),
|
|
9899
10564
|
products.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "boff-explore-rise boff-explore-rise-3 mt-6", children: [
|
|
9900
10565
|
/* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: T.focusProduct }),
|
|
9901
10566
|
/* @__PURE__ */ jsx(
|
|
@@ -9933,6 +10598,7 @@ function ExplorePage({
|
|
|
9933
10598
|
);
|
|
9934
10599
|
const T = useMemo(() => exploreStrings(activeLocale), [activeLocale]);
|
|
9935
10600
|
const rtl = isRtlLocale(activeLocale);
|
|
10601
|
+
const speechLang = speechLocaleOf(activeLocale);
|
|
9936
10602
|
const {
|
|
9937
10603
|
phase,
|
|
9938
10604
|
catalog,
|
|
@@ -10037,11 +10703,11 @@ function ExplorePage({
|
|
|
10037
10703
|
const layoutHeight = window.innerHeight;
|
|
10038
10704
|
if (layoutHeight === 0) return;
|
|
10039
10705
|
const top = Math.round(
|
|
10040
|
-
|
|
10706
|
+
clamp2(el.getBoundingClientRect().top, 0, layoutHeight)
|
|
10041
10707
|
);
|
|
10042
10708
|
const viewport = window.visualViewport;
|
|
10043
10709
|
const inset = viewport ? Math.round(
|
|
10044
|
-
|
|
10710
|
+
clamp2(
|
|
10045
10711
|
layoutHeight - viewport.height - viewport.offsetTop,
|
|
10046
10712
|
0,
|
|
10047
10713
|
layoutHeight
|
|
@@ -10322,6 +10988,7 @@ function ExplorePage({
|
|
|
10322
10988
|
const text = draft.trim();
|
|
10323
10989
|
if (!text || overLimit || busy || !canSend) return;
|
|
10324
10990
|
stopDictation();
|
|
10991
|
+
stopSpeaking();
|
|
10325
10992
|
setDraft("");
|
|
10326
10993
|
stickToBottomRef.current = true;
|
|
10327
10994
|
void send(text, toPayload(stagedRef.current));
|
|
@@ -10332,6 +10999,7 @@ function ExplorePage({
|
|
|
10332
10999
|
const sendPrompt = useCallback(
|
|
10333
11000
|
(prompt) => {
|
|
10334
11001
|
if (!canSend || busy) return;
|
|
11002
|
+
stopSpeaking();
|
|
10335
11003
|
setDraft("");
|
|
10336
11004
|
stickToBottomRef.current = true;
|
|
10337
11005
|
void send(prompt, toPayload(stagedRef.current));
|
|
@@ -10567,6 +11235,7 @@ function ExplorePage({
|
|
|
10567
11235
|
activity,
|
|
10568
11236
|
imageOrigins,
|
|
10569
11237
|
productNames,
|
|
11238
|
+
speechLang,
|
|
10570
11239
|
onNavigate,
|
|
10571
11240
|
anchorRef: message.id === latestAssistantId ? latestAssistantRef : void 0,
|
|
10572
11241
|
onFollow: (kind, url) => recordClick(message.id, kind, url),
|
|
@@ -15528,6 +16197,6 @@ function StoreProductDetailPage({
|
|
|
15528
16197
|
] });
|
|
15529
16198
|
}
|
|
15530
16199
|
|
|
15531
|
-
export { BlogListPage, BlogPostPage, Button, CONCEPTS_PATH, CONCEPT_ILLUSTRATION_NOTICE, CONCEPT_PATH_PREFIX, CareersApplyForm, CareersSubmissionForm, CaseStudiesListPage, CaseStudyPage, ChangelogPage, ConceptDetailPage, ConceptsPage, ContactPage, ContentRenderer, ContractsPage, DEFAULT_CONTACT_CATEGORIES, DEFAULT_EXPLORE_EXAMPLE_PROMPTS, ECOSYSTEM_PRODUCTS, EXPLORE_CATALOG_QUERY, EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS, EXPLORE_LOCALES, EXPLORE_MESSAGE_QUERY, EXPLORE_RECAPTCHA_ACTION, ElectronDownloadLink, ExploreCta, ExplorePage, FALLBACK_EXPLORE_LIMITS, Input, Label, LaunchCountdown, Markdown, NewsletterForm, NewsletterPage, PageHead, PartnersPage, PressKitPage, PricingPage, PricingSection, ProblemsSolvedSection, ProductCard, ProductProvider, ResourceLinks, RybbitAnalytics, SEND_EXPLORE_MESSAGE_MUTATION, Select, SocialLinks, StarRating, StoreBrowsePage, StoreHomePage, StoreProductDetailPage, Textarea, TypeBadge, UnsubscribePage, WaitlistForm, WaitlistPage, WebSDKClient, WebSDKProvider, WebsiteSwitcher, buttonVariants, classifyExploreError, cn, conceptPath, detectElectronPlatform, fetchPublicJobPosting, fetchPublicJobPostings, fetchPublicJobPostingsForSubmission, formatDownloads, formatPrice2 as formatPrice, getConceptBySlug, getRecaptchaV3Token, isValidUrl, loadRecaptchaV3, useContentPage, useContentPages, useExploreChat, useProduct, useProductConfig, usePublicJobPosting, usePublicJobPostings, usePublicJobPostingsForSubmission, useWebSDK, useWebSDKConfig };
|
|
16200
|
+
export { BlogListPage, BlogPostPage, Button, CONCEPTS_PATH, CONCEPT_ILLUSTRATION_NOTICE, CONCEPT_PATH_PREFIX, CareersApplyForm, CareersSubmissionForm, CaseStudiesListPage, CaseStudyPage, ChangelogPage, ConceptDetailPage, ConceptsPage, ContactPage, ContentRenderer, ContractsPage, DEFAULT_CONTACT_CATEGORIES, DEFAULT_EXPLORE_EXAMPLE_PROMPTS, ECOSYSTEM_PRODUCTS, EXPLORE_CATALOG_QUERY, EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS, EXPLORE_LOCALES, EXPLORE_MESSAGE_QUERY, EXPLORE_RECAPTCHA_ACTION, ElectronDownloadLink, ExploreCta, ExplorePage, FALLBACK_EXPLORE_LIMITS, Input, Label, LaunchCountdown, Markdown, NewsletterForm, NewsletterPage, PageHead, PartnersPage, PressKitPage, PricingPage, PricingSection, ProblemsSolvedSection, ProductCard, ProductProvider, ResourceLinks, RybbitAnalytics, SEND_EXPLORE_MESSAGE_MUTATION, Select, SocialLinks, StarRating, StoreBrowsePage, StoreHomePage, StoreProductDetailPage, Textarea, TypeBadge, UnsubscribePage, WaitlistForm, WaitlistPage, WebSDKClient, WebSDKProvider, WebsiteSwitcher, buttonVariants, classifyExploreError, cn, conceptPath, detectElectronPlatform, fetchPublicJobPosting, fetchPublicJobPostings, fetchPublicJobPostingsForSubmission, formatDownloads, formatPrice2 as formatPrice, getConceptBySlug, getRecaptchaV3Token, isValidUrl, loadRecaptchaV3, speechLocaleOf, stopSpeaking, useContentPage, useContentPages, useExploreChat, useProduct, useProductConfig, useProgressiveReveal, usePublicJobPosting, usePublicJobPostings, usePublicJobPostingsForSubmission, useSpeechOutput, useWebSDK, useWebSDKConfig };
|
|
15532
16201
|
//# sourceMappingURL=index.mjs.map
|
|
15533
16202
|
//# sourceMappingURL=index.mjs.map
|