@burdenoff/website-sdk 2026.922.4 → 2026.923.1
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 +4 -158
- package/dist/components/explore.d.ts +4 -158
- package/dist/components/explore.js +1464 -263
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +1466 -266
- package/dist/components/explore.mjs.map +1 -1
- package/dist/explore-D25zoXy9.d.mts +240 -0
- package/dist/explore-I4QnY4J9.d.ts +240 -0
- package/dist/{explore-types-DvQPiL1t.d.mts → explore-types-B5sdOC5M.d.mts} +75 -2
- package/dist/{explore-types-DvQPiL1t.d.ts → explore-types-B5sdOC5M.d.ts} +75 -2
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +481 -8
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +479 -9
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +433 -25
- package/dist/index.d.ts +433 -25
- package/dist/index.js +2839 -409
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2817 -412
- package/dist/index.mjs.map +1 -1
- package/dist/{use-explore-chat-Dgm-jf96.d.mts → use-progressive-reveal-Cmy8bA7L.d.mts} +88 -7
- package/dist/{use-explore-chat-CNEdKBc1.d.ts → use-progressive-reveal-DHPGGxZu.d.ts} +88 -7
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -2438,16 +2438,16 @@ function useRateLimit(maxAttempts, windowMinutes) {
|
|
|
2438
2438
|
}
|
|
2439
2439
|
}, [maxAttempts]);
|
|
2440
2440
|
function recordAttempt() {
|
|
2441
|
-
const
|
|
2441
|
+
const now2 = Date.now();
|
|
2442
2442
|
const state = rateLimitRef.current;
|
|
2443
|
-
if (state &&
|
|
2443
|
+
if (state && now2 > state.resetTime) {
|
|
2444
2444
|
rateLimitRef.current = null;
|
|
2445
2445
|
}
|
|
2446
2446
|
const current = rateLimitRef.current;
|
|
2447
2447
|
if (!current) {
|
|
2448
2448
|
rateLimitRef.current = {
|
|
2449
2449
|
attempts: 1,
|
|
2450
|
-
resetTime:
|
|
2450
|
+
resetTime: now2 + windowMinutes * 60 * 1e3
|
|
2451
2451
|
};
|
|
2452
2452
|
return false;
|
|
2453
2453
|
}
|
|
@@ -3542,16 +3542,16 @@ function useRateLimit2(maxAttempts, windowMinutes) {
|
|
|
3542
3542
|
const [isLimited, setIsLimited] = React.useState(false);
|
|
3543
3543
|
const [resetTime, setResetTime] = React.useState(null);
|
|
3544
3544
|
function recordAttempt() {
|
|
3545
|
-
const
|
|
3545
|
+
const now2 = Date.now();
|
|
3546
3546
|
const state = rateLimitRef.current;
|
|
3547
|
-
if (state &&
|
|
3547
|
+
if (state && now2 > state.resetTime) {
|
|
3548
3548
|
rateLimitRef.current = null;
|
|
3549
3549
|
}
|
|
3550
3550
|
const current = rateLimitRef.current;
|
|
3551
3551
|
if (!current) {
|
|
3552
3552
|
rateLimitRef.current = {
|
|
3553
3553
|
attempts: 1,
|
|
3554
|
-
resetTime:
|
|
3554
|
+
resetTime: now2 + windowMinutes * 60 * 1e3
|
|
3555
3555
|
};
|
|
3556
3556
|
return false;
|
|
3557
3557
|
}
|
|
@@ -4585,8 +4585,8 @@ function LaunchCountdown({
|
|
|
4585
4585
|
launchedMessage = "We have launched!",
|
|
4586
4586
|
className
|
|
4587
4587
|
}) {
|
|
4588
|
-
const [
|
|
4589
|
-
const remainingMs = launchDate -
|
|
4588
|
+
const [now2, setNow] = React.useState(() => Date.now());
|
|
4589
|
+
const remainingMs = launchDate - now2;
|
|
4590
4590
|
const hasLaunched = remainingMs <= 0;
|
|
4591
4591
|
React.useEffect(() => {
|
|
4592
4592
|
if (hasLaunched) return;
|
|
@@ -5959,7 +5959,7 @@ var EN = {
|
|
|
5959
5959
|
showLess: "Show less",
|
|
5960
5960
|
sources: "Sources",
|
|
5961
5961
|
nextYouCouldAsk: "Next you could ask",
|
|
5962
|
-
placeholder: "Describe the problem
|
|
5962
|
+
placeholder: "Describe the problem\u2026",
|
|
5963
5963
|
placeholderProduct: "Describe a problem, or ask about {product}\u2026",
|
|
5964
5964
|
send: "Send",
|
|
5965
5965
|
stop: "Stop",
|
|
@@ -6000,6 +6000,20 @@ var EN = {
|
|
|
6000
6000
|
feedbackDismiss: "Dismiss",
|
|
6001
6001
|
feedbackThanks: "Thanks \u2014 that helps.",
|
|
6002
6002
|
feedbackNotSent: "That didn't send.",
|
|
6003
|
+
escalateOpen: "Talk to a person",
|
|
6004
|
+
escalateTitle: "Send this conversation to a person",
|
|
6005
|
+
escalateBody: "We'll pass the whole conversation on, so you don't have to type any of it again.",
|
|
6006
|
+
escalateEmailLabel: "Your email address",
|
|
6007
|
+
escalateEmailPlaceholder: "you@example.com",
|
|
6008
|
+
escalateNoteLabel: "Anything else a person should know? (optional)",
|
|
6009
|
+
escalateSubmit: "Send to a person",
|
|
6010
|
+
escalateSending: "Sending\u2026",
|
|
6011
|
+
escalateCancel: "Cancel",
|
|
6012
|
+
escalateInvalidEmail: "That doesn't look like an address we can reply to. Please check it.",
|
|
6013
|
+
escalateSent: "A person now has this conversation. We'll reply to {email}.",
|
|
6014
|
+
escalateRateLimited: "That's a lot of requests in a short time. Please try again in a few minutes.",
|
|
6015
|
+
escalateCaptcha: "We couldn't verify that you're human. Please try that again.",
|
|
6016
|
+
escalateFailed: "We couldn't pass that on just now. Please try again.",
|
|
6003
6017
|
prevSuggestion: "Previous suggestion",
|
|
6004
6018
|
nextSuggestion: "Next suggestion",
|
|
6005
6019
|
conceptIllustration: "Concept illustration",
|
|
@@ -6010,6 +6024,9 @@ var EN = {
|
|
|
6010
6024
|
conceptAskQuestion: "How does {title} work in {product}?",
|
|
6011
6025
|
copyAnswer: "Copy answer",
|
|
6012
6026
|
copyFailed: "Couldn't copy",
|
|
6027
|
+
readAloud: "Read aloud",
|
|
6028
|
+
stopReading: "Stop reading",
|
|
6029
|
+
answerTable: "Table",
|
|
6013
6030
|
groundedIn: "What this answer is based on",
|
|
6014
6031
|
sourceCountOne: "1 source",
|
|
6015
6032
|
sourceCountMany: "{count} sources",
|
|
@@ -6044,7 +6061,7 @@ var ZH = {
|
|
|
6044
6061
|
showLess: "\u6536\u8D77",
|
|
6045
6062
|
sources: "\u6765\u6E90",
|
|
6046
6063
|
nextYouCouldAsk: "\u4F60\u8FD8\u53EF\u4EE5\u95EE",
|
|
6047
|
-
placeholder: "\u63CF\u8FF0\u4F60\
|
|
6064
|
+
placeholder: "\u63CF\u8FF0\u4F60\u7684\u95EE\u9898\u2026",
|
|
6048
6065
|
placeholderProduct: "\u63CF\u8FF0\u95EE\u9898\uFF0C\u6216\u8BE2\u95EE {product}\u2026",
|
|
6049
6066
|
send: "\u53D1\u9001",
|
|
6050
6067
|
stop: "\u505C\u6B62",
|
|
@@ -6082,6 +6099,20 @@ var ZH = {
|
|
|
6082
6099
|
feedbackDismiss: "\u5173\u95ED",
|
|
6083
6100
|
feedbackThanks: "\u8C22\u8C22\uFF0C\u8FD9\u5BF9\u6211\u4EEC\u5F88\u6709\u5E2E\u52A9\u3002",
|
|
6084
6101
|
feedbackNotSent: "\u6CA1\u6709\u63D0\u4EA4\u6210\u529F\u3002",
|
|
6102
|
+
escalateOpen: "\u8054\u7CFB\u771F\u4EBA",
|
|
6103
|
+
escalateTitle: "\u628A\u8FD9\u6BB5\u5BF9\u8BDD\u8F6C\u7ED9\u771F\u4EBA",
|
|
6104
|
+
escalateBody: "\u6211\u4EEC\u4F1A\u628A\u6574\u6BB5\u5BF9\u8BDD\u4E00\u8D77\u8F6C\u8FC7\u53BB\uFF0C\u60A8\u4E0D\u7528\u518D\u91CD\u65B0\u6253\u4E00\u904D\u3002",
|
|
6105
|
+
escalateEmailLabel: "\u60A8\u7684\u90AE\u7BB1\u5730\u5740",
|
|
6106
|
+
escalateEmailPlaceholder: "you@example.com",
|
|
6107
|
+
escalateNoteLabel: "\u8FD8\u6709\u4EC0\u4E48\u9700\u8981\u544A\u8BC9\u6211\u4EEC\u7684\u5417\uFF1F\uFF08\u9009\u586B\uFF09",
|
|
6108
|
+
escalateSubmit: "\u8F6C\u7ED9\u771F\u4EBA",
|
|
6109
|
+
escalateSending: "\u6B63\u5728\u53D1\u9001\u2026",
|
|
6110
|
+
escalateCancel: "\u53D6\u6D88",
|
|
6111
|
+
escalateInvalidEmail: "\u8FD9\u4F3C\u4E4E\u4E0D\u662F\u4E00\u4E2A\u6211\u4EEC\u53EF\u4EE5\u56DE\u590D\u7684\u90AE\u7BB1\u5730\u5740\uFF0C\u8BF7\u68C0\u67E5\u4E00\u4E0B\u3002",
|
|
6112
|
+
escalateSent: "\u5DF2\u6709\u540C\u4E8B\u63A5\u624B\u8FD9\u6BB5\u5BF9\u8BDD\uFF0C\u6211\u4EEC\u4F1A\u56DE\u590D\u5230 {email}\u3002",
|
|
6113
|
+
escalateRateLimited: "\u77ED\u65F6\u95F4\u5185\u8BF7\u6C42\u8FC7\u591A\uFF0C\u8BF7\u51E0\u5206\u949F\u540E\u518D\u8BD5\u3002",
|
|
6114
|
+
escalateCaptcha: "\u6211\u4EEC\u65E0\u6CD5\u9A8C\u8BC1\u60A8\u662F\u771F\u4EBA\uFF0C\u8BF7\u518D\u8BD5\u4E00\u6B21\u3002",
|
|
6115
|
+
escalateFailed: "\u6682\u65F6\u65E0\u6CD5\u8F6C\u4EA4\uFF0C\u8BF7\u518D\u8BD5\u4E00\u6B21\u3002",
|
|
6085
6116
|
prevSuggestion: "\u4E0A\u4E00\u4E2A\u5EFA\u8BAE",
|
|
6086
6117
|
nextSuggestion: "\u4E0B\u4E00\u4E2A\u5EFA\u8BAE",
|
|
6087
6118
|
conceptIllustration: "\u6982\u5FF5\u793A\u610F\u56FE",
|
|
@@ -6092,6 +6123,9 @@ var ZH = {
|
|
|
6092
6123
|
conceptAskQuestion: "{product} \u7684 {title} \u662F\u600E\u4E48\u8FD0\u4F5C\u7684\uFF1F",
|
|
6093
6124
|
copyAnswer: "\u590D\u5236\u56DE\u7B54",
|
|
6094
6125
|
copyFailed: "\u590D\u5236\u5931\u8D25",
|
|
6126
|
+
readAloud: "\u6717\u8BFB",
|
|
6127
|
+
stopReading: "\u505C\u6B62\u6717\u8BFB",
|
|
6128
|
+
answerTable: "\u8868\u683C",
|
|
6095
6129
|
groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
|
|
6096
6130
|
sourceCountOne: "1 \u4E2A\u6765\u6E90",
|
|
6097
6131
|
sourceCountMany: "{count} \u4E2A\u6765\u6E90",
|
|
@@ -6122,7 +6156,7 @@ var HI = {
|
|
|
6122
6156
|
showLess: "\u0915\u092E \u0926\u093F\u0916\u093E\u090F\u0901",
|
|
6123
6157
|
sources: "\u0938\u094D\u0930\u094B\u0924",
|
|
6124
6158
|
nextYouCouldAsk: "\u0906\u0917\u0947 \u0906\u092A \u092A\u0942\u091B \u0938\u0915\u0924\u0947 \u0939\u0948\u0902",
|
|
6125
|
-
placeholder: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \
|
|
6159
|
+
placeholder: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u092C\u0924\u093E\u090F\u0902\u2026",
|
|
6126
6160
|
placeholderProduct: "\u0938\u092E\u0938\u094D\u092F\u093E \u092C\u0924\u093E\u090F\u0902, \u092F\u093E {product} \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902\u2026",
|
|
6127
6161
|
send: "\u092D\u0947\u091C\u0947\u0902",
|
|
6128
6162
|
stop: "\u0930\u094B\u0915\u0947\u0902",
|
|
@@ -6160,6 +6194,20 @@ var HI = {
|
|
|
6160
6194
|
feedbackDismiss: "\u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6161
6195
|
feedbackThanks: "\u0927\u0928\u094D\u092F\u0935\u093E\u0926, \u0907\u0938\u0938\u0947 \u092E\u0926\u0926 \u092E\u093F\u0932\u0924\u0940 \u0939\u0948\u0964",
|
|
6162
6196
|
feedbackNotSent: "\u092F\u0939 \u092D\u0947\u091C\u093E \u0928\u0939\u0940\u0902 \u091C\u093E \u0938\u0915\u093E\u0964",
|
|
6197
|
+
escalateOpen: "\u0915\u093F\u0938\u0940 \u0935\u094D\u092F\u0915\u094D\u0924\u093F \u0938\u0947 \u092C\u093E\u0924 \u0915\u0930\u0947\u0902",
|
|
6198
|
+
escalateTitle: "\u092F\u0939 \u092C\u093E\u0924\u091A\u0940\u0924 \u0915\u093F\u0938\u0940 \u0935\u094D\u092F\u0915\u094D\u0924\u093F \u0915\u094B \u092D\u0947\u091C\u0947\u0902",
|
|
6199
|
+
escalateBody: "\u0939\u092E \u092A\u0942\u0930\u0940 \u092C\u093E\u0924\u091A\u0940\u0924 \u0906\u0917\u0947 \u092D\u0947\u091C \u0926\u0947\u0902\u0917\u0947, \u0924\u093E\u0915\u093F \u0906\u092A\u0915\u094B \u0926\u094B\u092C\u093E\u0930\u093E \u0915\u0941\u091B \u0932\u093F\u0916\u0928\u093E \u0928 \u092A\u0921\u093C\u0947\u0964",
|
|
6200
|
+
escalateEmailLabel: "\u0906\u092A\u0915\u093E \u0908\u092E\u0947\u0932 \u092A\u0924\u093E",
|
|
6201
|
+
escalateEmailPlaceholder: "you@example.com",
|
|
6202
|
+
escalateNoteLabel: "\u0915\u094D\u092F\u093E \u0915\u0941\u091B \u0914\u0930 \u092C\u0924\u093E\u0928\u093E \u091A\u093E\u0939\u0947\u0902\u0917\u0947? (\u0935\u0948\u0915\u0932\u094D\u092A\u093F\u0915)",
|
|
6203
|
+
escalateSubmit: "\u0915\u093F\u0938\u0940 \u0935\u094D\u092F\u0915\u094D\u0924\u093F \u0915\u094B \u092D\u0947\u091C\u0947\u0902",
|
|
6204
|
+
escalateSending: "\u092D\u0947\u091C\u093E \u091C\u093E \u0930\u0939\u093E \u0939\u0948\u2026",
|
|
6205
|
+
escalateCancel: "\u0930\u0926\u094D\u0926 \u0915\u0930\u0947\u0902",
|
|
6206
|
+
escalateInvalidEmail: "\u092F\u0939 \u0910\u0938\u093E \u0908\u092E\u0947\u0932 \u092A\u0924\u093E \u0928\u0939\u0940\u0902 \u0932\u0917\u0924\u093E \u091C\u093F\u0938 \u092A\u0930 \u0939\u092E \u091C\u0935\u093E\u092C \u092D\u0947\u091C \u0938\u0915\u0947\u0902\u0964 \u0915\u0943\u092A\u092F\u093E \u091C\u093E\u0901\u091A \u0932\u0947\u0902\u0964",
|
|
6207
|
+
escalateSent: "\u0905\u092C \u092F\u0939 \u092C\u093E\u0924\u091A\u0940\u0924 \u090F\u0915 \u0935\u094D\u092F\u0915\u094D\u0924\u093F \u0915\u0947 \u092A\u093E\u0938 \u0939\u0948\u0964 \u0939\u092E {email} \u092A\u0930 \u091C\u0935\u093E\u092C \u0926\u0947\u0902\u0917\u0947\u0964",
|
|
6208
|
+
escalateRateLimited: "\u0925\u094B\u0921\u093C\u0947 \u0938\u092E\u092F \u092E\u0947\u0902 \u092C\u0939\u0941\u0924 \u0938\u093E\u0930\u0947 \u0905\u0928\u0941\u0930\u094B\u0927 \u0939\u094B \u0917\u090F\u0964 \u0915\u0943\u092A\u092F\u093E \u0915\u0941\u091B \u092E\u093F\u0928\u091F \u092C\u093E\u0926 \u0915\u094B\u0936\u093F\u0936 \u0915\u0930\u0947\u0902\u0964",
|
|
6209
|
+
escalateCaptcha: "\u0939\u092E \u092F\u0939 \u0938\u0924\u094D\u092F\u093E\u092A\u093F\u0924 \u0928\u0939\u0940\u0902 \u0915\u0930 \u0938\u0915\u0947 \u0915\u093F \u0906\u092A \u090F\u0915 \u0935\u094D\u092F\u0915\u094D\u0924\u093F \u0939\u0948\u0902\u0964 \u0915\u0943\u092A\u092F\u093E \u092B\u093F\u0930 \u0915\u094B\u0936\u093F\u0936 \u0915\u0930\u0947\u0902\u0964",
|
|
6210
|
+
escalateFailed: "\u0905\u092D\u0940 \u0907\u0938\u0947 \u0906\u0917\u0947 \u0928\u0939\u0940\u0902 \u092D\u0947\u091C\u093E \u091C\u093E \u0938\u0915\u093E\u0964 \u0915\u0943\u092A\u092F\u093E \u092B\u093F\u0930 \u0915\u094B\u0936\u093F\u0936 \u0915\u0930\u0947\u0902\u0964",
|
|
6163
6211
|
prevSuggestion: "\u092A\u093F\u091B\u0932\u093E \u0938\u0941\u091D\u093E\u0935",
|
|
6164
6212
|
nextSuggestion: "\u0905\u0917\u0932\u093E \u0938\u0941\u091D\u093E\u0935",
|
|
6165
6213
|
conceptIllustration: "\u0905\u0935\u0927\u093E\u0930\u0923\u093E \u091A\u093F\u0924\u094D\u0930\u0923",
|
|
@@ -6170,6 +6218,9 @@ var HI = {
|
|
|
6170
6218
|
conceptAskQuestion: "{product} \u092E\u0947\u0902 {title} \u0915\u0948\u0938\u0947 \u0915\u093E\u092E \u0915\u0930\u0924\u093E \u0939\u0948?",
|
|
6171
6219
|
copyAnswer: "\u0909\u0924\u094D\u0924\u0930 \u0915\u0949\u092A\u0940 \u0915\u0930\u0947\u0902",
|
|
6172
6220
|
copyFailed: "\u0915\u0949\u092A\u0940 \u0928\u0939\u0940\u0902 \u0939\u094B \u0938\u0915\u093E",
|
|
6221
|
+
readAloud: "\u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0947\u0902",
|
|
6222
|
+
stopReading: "\u092A\u0922\u093C\u0928\u093E \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6223
|
+
answerTable: "\u0924\u093E\u0932\u093F\u0915\u093E",
|
|
6173
6224
|
groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
|
|
6174
6225
|
sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
|
|
6175
6226
|
sourceCountMany: "{count} \u0938\u094D\u0930\u094B\u0924",
|
|
@@ -6204,7 +6255,7 @@ var ES = {
|
|
|
6204
6255
|
showLess: "Ver menos",
|
|
6205
6256
|
sources: "Fuentes",
|
|
6206
6257
|
nextYouCouldAsk: "Tambi\xE9n puedes preguntar",
|
|
6207
|
-
placeholder: "Describe el problema
|
|
6258
|
+
placeholder: "Describe el problema\u2026",
|
|
6208
6259
|
placeholderProduct: "Describe un problema o pregunta por {product}\u2026",
|
|
6209
6260
|
send: "Enviar",
|
|
6210
6261
|
stop: "Detener",
|
|
@@ -6242,6 +6293,20 @@ var ES = {
|
|
|
6242
6293
|
feedbackDismiss: "Cerrar",
|
|
6243
6294
|
feedbackThanks: "Gracias, nos sirve.",
|
|
6244
6295
|
feedbackNotSent: "No se ha podido enviar.",
|
|
6296
|
+
escalateOpen: "Hablar con una persona",
|
|
6297
|
+
escalateTitle: "Env\xEDa esta conversaci\xF3n a una persona",
|
|
6298
|
+
escalateBody: "Le pasaremos la conversaci\xF3n entera, as\xED no tienes que volver a escribirla.",
|
|
6299
|
+
escalateEmailLabel: "Tu direcci\xF3n de correo",
|
|
6300
|
+
escalateEmailPlaceholder: "tu@ejemplo.com",
|
|
6301
|
+
escalateNoteLabel: "\xBFAlgo m\xE1s que deber\xEDamos saber? (opcional)",
|
|
6302
|
+
escalateSubmit: "Enviar a una persona",
|
|
6303
|
+
escalateSending: "Enviando\u2026",
|
|
6304
|
+
escalateCancel: "Cancelar",
|
|
6305
|
+
escalateInvalidEmail: "No parece una direcci\xF3n a la que podamos responder. Rev\xEDsala, por favor.",
|
|
6306
|
+
escalateSent: "Una persona ya tiene esta conversaci\xF3n. Te responderemos a {email}.",
|
|
6307
|
+
escalateRateLimited: "Han sido muchas peticiones en poco tiempo. Int\xE9ntalo de nuevo en unos minutos.",
|
|
6308
|
+
escalateCaptcha: "No hemos podido verificar que eres una persona. Int\xE9ntalo de nuevo.",
|
|
6309
|
+
escalateFailed: "No hemos podido pasarlo ahora mismo. Int\xE9ntalo de nuevo.",
|
|
6245
6310
|
prevSuggestion: "Sugerencia anterior",
|
|
6246
6311
|
nextSuggestion: "Sugerencia siguiente",
|
|
6247
6312
|
conceptIllustration: "Ilustraci\xF3n del concepto",
|
|
@@ -6252,6 +6317,9 @@ var ES = {
|
|
|
6252
6317
|
conceptAskQuestion: "\xBFC\xF3mo funciona {title} en {product}?",
|
|
6253
6318
|
copyAnswer: "Copiar respuesta",
|
|
6254
6319
|
copyFailed: "No se pudo copiar",
|
|
6320
|
+
readAloud: "Leer en voz alta",
|
|
6321
|
+
stopReading: "Dejar de leer",
|
|
6322
|
+
answerTable: "Tabla",
|
|
6255
6323
|
groundedIn: "En qu\xE9 se basa esta respuesta",
|
|
6256
6324
|
sourceCountOne: "1 fuente",
|
|
6257
6325
|
sourceCountMany: "{count} fuentes",
|
|
@@ -6286,7 +6354,7 @@ var AR = {
|
|
|
6286
6354
|
showLess: "\u0639\u0631\u0636 \u0623\u0642\u0644",
|
|
6287
6355
|
sources: "\u0627\u0644\u0645\u0635\u0627\u062F\u0631",
|
|
6288
6356
|
nextYouCouldAsk: "\u064A\u0645\u0643\u0646\u0643 \u0623\u0646 \u062A\u0633\u0623\u0644 \u0628\u0639\u062F \u0630\u0644\u0643",
|
|
6289
|
-
placeholder: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629
|
|
6357
|
+
placeholder: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629\u2026",
|
|
6290
6358
|
placeholderProduct: "\u0635\u0641 \u0645\u0634\u0643\u0644\u062A\u0643 \u0623\u0648 \u0627\u0633\u0623\u0644 \u0639\u0646 {product}\u2026",
|
|
6291
6359
|
send: "\u0625\u0631\u0633\u0627\u0644",
|
|
6292
6360
|
stop: "\u0625\u064A\u0642\u0627\u0641",
|
|
@@ -6324,6 +6392,20 @@ var AR = {
|
|
|
6324
6392
|
feedbackDismiss: "\u0625\u063A\u0644\u0627\u0642",
|
|
6325
6393
|
feedbackThanks: "\u0634\u0643\u0631\u064B\u0627\u060C \u0647\u0630\u0627 \u064A\u0633\u0627\u0639\u062F\u0646\u0627.",
|
|
6326
6394
|
feedbackNotSent: "\u0644\u0645 \u064A\u062A\u0645 \u0627\u0644\u0625\u0631\u0633\u0627\u0644.",
|
|
6395
|
+
escalateOpen: "\u062A\u0648\u0627\u0635\u0644 \u0645\u0639 \u0634\u062E\u0635",
|
|
6396
|
+
escalateTitle: "\u0623\u0631\u0633\u0644 \u0647\u0630\u0647 \u0627\u0644\u0645\u062D\u0627\u062F\u062B\u0629 \u0625\u0644\u0649 \u0634\u062E\u0635",
|
|
6397
|
+
escalateBody: "\u0633\u0646\u0645\u0631\u0651\u0631 \u0627\u0644\u0645\u062D\u0627\u062F\u062B\u0629 \u0643\u0627\u0645\u0644\u0629\u060C \u062D\u062A\u0649 \u0644\u0627 \u062A\u0636\u0637\u0631 \u0625\u0644\u0649 \u0643\u062A\u0627\u0628\u062A\u0647\u0627 \u0645\u0646 \u062C\u062F\u064A\u062F.",
|
|
6398
|
+
escalateEmailLabel: "\u0628\u0631\u064A\u062F\u0643 \u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A",
|
|
6399
|
+
escalateEmailPlaceholder: "you@example.com",
|
|
6400
|
+
escalateNoteLabel: "\u0647\u0644 \u0645\u0646 \u0634\u064A\u0621 \u0622\u062E\u0631 \u064A\u0646\u0628\u063A\u064A \u0623\u0646 \u0646\u0639\u0631\u0641\u0647\u061F (\u0627\u062E\u062A\u064A\u0627\u0631\u064A)",
|
|
6401
|
+
escalateSubmit: "\u0625\u0631\u0633\u0627\u0644 \u0625\u0644\u0649 \u0634\u062E\u0635",
|
|
6402
|
+
escalateSending: "\u062C\u0627\u0631\u064D \u0627\u0644\u0625\u0631\u0633\u0627\u0644\u2026",
|
|
6403
|
+
escalateCancel: "\u0625\u0644\u063A\u0627\u0621",
|
|
6404
|
+
escalateInvalidEmail: "\u0644\u0627 \u064A\u0628\u062F\u0648 \u0647\u0630\u0627 \u0639\u0646\u0648\u0627\u0646\u064B\u0627 \u064A\u0645\u0643\u0646\u0646\u0627 \u0627\u0644\u0631\u062F \u0639\u0644\u064A\u0647. \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646\u0647.",
|
|
6405
|
+
escalateSent: "\u0623\u0635\u0628\u062D\u062A \u0647\u0630\u0647 \u0627\u0644\u0645\u062D\u0627\u062F\u062B\u0629 \u0644\u062F\u0649 \u0623\u062D\u062F \u0627\u0644\u0632\u0645\u0644\u0627\u0621. \u0633\u0646\u0631\u062F \u0639\u0644\u0649 {email}.",
|
|
6406
|
+
escalateRateLimited: "\u0637\u0644\u0628\u0627\u062A \u0643\u062B\u064A\u0631\u0629 \u062E\u0644\u0627\u0644 \u0648\u0642\u062A \u0642\u0635\u064A\u0631. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0628\u0639\u062F \u0628\u0636\u0639 \u062F\u0642\u0627\u0626\u0642.",
|
|
6407
|
+
escalateCaptcha: "\u062A\u0639\u0630\u0651\u0631 \u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u0623\u0646\u0643 \u0644\u0633\u062A \u0631\u0648\u0628\u0648\u062A\u064B\u0627. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
|
|
6408
|
+
escalateFailed: "\u062A\u0639\u0630\u0651\u0631 \u062A\u0645\u0631\u064A\u0631 \u0627\u0644\u0645\u062D\u0627\u062F\u062B\u0629 \u0627\u0644\u0622\u0646. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
|
|
6327
6409
|
prevSuggestion: "\u0627\u0644\u0627\u0642\u062A\u0631\u0627\u062D \u0627\u0644\u0633\u0627\u0628\u0642",
|
|
6328
6410
|
nextSuggestion: "\u0627\u0644\u0627\u0642\u062A\u0631\u0627\u062D \u0627\u0644\u062A\u0627\u0644\u064A",
|
|
6329
6411
|
conceptIllustration: "\u0631\u0633\u0645 \u062A\u0648\u0636\u064A\u062D\u064A \u0644\u0644\u0645\u0641\u0647\u0648\u0645",
|
|
@@ -6334,6 +6416,9 @@ var AR = {
|
|
|
6334
6416
|
conceptAskQuestion: "\u0643\u064A\u0641 \u064A\u0639\u0645\u0644 {title} \u0641\u064A {product}\u061F",
|
|
6335
6417
|
copyAnswer: "\u0646\u0633\u062E \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6336
6418
|
copyFailed: "\u062A\u0639\u0630\u0651\u0631 \u0627\u0644\u0646\u0633\u062E",
|
|
6419
|
+
readAloud: "\u0627\u0642\u0631\u0623 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D",
|
|
6420
|
+
stopReading: "\u0625\u064A\u0642\u0627\u0641 \u0627\u0644\u0642\u0631\u0627\u0621\u0629",
|
|
6421
|
+
answerTable: "\u062C\u062F\u0648\u0644",
|
|
6337
6422
|
groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6338
6423
|
sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
|
|
6339
6424
|
sourceCountMany: "{count} \u0645\u0635\u0627\u062F\u0631",
|
|
@@ -6368,7 +6453,7 @@ var TA = {
|
|
|
6368
6453
|
showLess: "\u0B95\u0BC1\u0BB1\u0BC8\u0BB5\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1",
|
|
6369
6454
|
sources: "\u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6370
6455
|
nextYouCouldAsk: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1 \u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD",
|
|
6371
|
-
placeholder: "\
|
|
6456
|
+
placeholder: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
|
|
6372
6457
|
placeholderProduct: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1 {product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
|
|
6373
6458
|
send: "\u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BC1",
|
|
6374
6459
|
stop: "\u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1",
|
|
@@ -6406,6 +6491,20 @@ var TA = {
|
|
|
6406
6491
|
feedbackDismiss: "\u0BAE\u0BC2\u0B9F\u0BC1",
|
|
6407
6492
|
feedbackThanks: "\u0BA8\u0BA9\u0BCD\u0BB1\u0BBF, \u0B87\u0BA4\u0BC1 \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0B89\u0BA4\u0BB5\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1.",
|
|
6408
6493
|
feedbackNotSent: "\u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
|
|
6494
|
+
escalateOpen: "\u0B92\u0BB0\u0BC1\u0BB5\u0BB0\u0BBF\u0B9F\u0BAE\u0BCD \u0BAA\u0BC7\u0B9A\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6495
|
+
escalateTitle: "\u0B87\u0BA8\u0BCD\u0BA4 \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B9F\u0BB2\u0BC8 \u0B92\u0BB0\u0BC1\u0BB5\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6496
|
+
escalateBody: "\u0BAE\u0BC1\u0BB4\u0BC1 \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B9F\u0BB2\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0BA8\u0BBE\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BBF\u0BB5\u0BBF\u0B9F\u0BC1\u0BB5\u0BCB\u0BAE\u0BCD; \u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0BA4\u0B9F\u0BCD\u0B9F\u0B9A\u0BCD\u0B9A\u0BC1 \u0B9A\u0BC6\u0BAF\u0BCD\u0BAF \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BBF\u0BAF\u0BA4\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
|
|
6497
|
+
escalateEmailLabel: "\u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAE\u0BBF\u0BA9\u0BCD\u0BA9\u0B9E\u0BCD\u0B9A\u0BB2\u0BCD \u0BAE\u0BC1\u0B95\u0BB5\u0BB0\u0BBF",
|
|
6498
|
+
escalateEmailPlaceholder: "you@example.com",
|
|
6499
|
+
escalateNoteLabel: "\u0BB5\u0BC7\u0BB1\u0BC1 \u0B8F\u0BA4\u0BC7\u0BA9\u0BC1\u0BAE\u0BCD \u0B9A\u0BCA\u0BB2\u0BCD\u0BB2 \u0BB5\u0BBF\u0BB0\u0BC1\u0BAE\u0BCD\u0BAA\u0BC1\u0B95\u0BBF\u0BB1\u0BC0\u0BB0\u0BCD\u0B95\u0BB3\u0BBE? (\u0BB5\u0BBF\u0BB0\u0BC1\u0BAA\u0BCD\u0BAA\u0BAE\u0BCD)",
|
|
6500
|
+
escalateSubmit: "\u0B92\u0BB0\u0BC1\u0BB5\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BC1",
|
|
6501
|
+
escalateSending: "\u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1\u2026",
|
|
6502
|
+
escalateCancel: "\u0BB0\u0BA4\u0BCD\u0BA4\u0BC1 \u0B9A\u0BC6\u0BAF\u0BCD",
|
|
6503
|
+
escalateInvalidEmail: "\u0B87\u0BA4\u0BC1 \u0BA8\u0BBE\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BB3\u0BBF\u0B95\u0BCD\u0B95\u0B95\u0BCD\u0B95\u0BC2\u0B9F\u0BBF\u0BAF \u0BAE\u0BBF\u0BA9\u0BCD\u0BA9\u0B9E\u0BCD\u0B9A\u0BB2\u0BCD \u0BAE\u0BC1\u0B95\u0BB5\u0BB0\u0BBF \u0BAA\u0BCB\u0BB2\u0BCD \u0BA4\u0BC6\u0BB0\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0B9A\u0BB0\u0BBF\u0BAA\u0BBE\u0BB0\u0BCD\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD.",
|
|
6504
|
+
escalateSent: "\u0B87\u0BA8\u0BCD\u0BA4 \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B9F\u0BB2\u0BCD \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B92\u0BB0\u0BC1\u0BB5\u0BB0\u0BBF\u0B9F\u0BAE\u0BCD \u0B89\u0BB3\u0BCD\u0BB3\u0BA4\u0BC1. {email} \u0BAE\u0BC1\u0B95\u0BB5\u0BB0\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BB3\u0BBF\u0BAA\u0BCD\u0BAA\u0BCB\u0BAE\u0BCD.",
|
|
6505
|
+
escalateRateLimited: "\u0B95\u0BC1\u0BB1\u0BC1\u0B95\u0BBF\u0BAF \u0BA8\u0BC7\u0BB0\u0BA4\u0BCD\u0BA4\u0BBF\u0BB2\u0BCD \u0B85\u0BA4\u0BBF\u0B95 \u0B95\u0BCB\u0BB0\u0BBF\u0B95\u0BCD\u0B95\u0BC8\u0B95\u0BB3\u0BCD. \u0B9A\u0BBF\u0BB2 \u0BA8\u0BBF\u0BAE\u0BBF\u0B9F\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B95\u0BB4\u0BBF\u0BA4\u0BCD\u0BA4\u0BC1 \u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD.",
|
|
6506
|
+
escalateCaptcha: "\u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAE\u0BA9\u0BBF\u0BA4\u0BB0\u0BCD \u0B8E\u0BA9\u0BCD\u0BAA\u0BA4\u0BC8 \u0B89\u0BB1\u0BC1\u0BA4\u0BBF\u0B9A\u0BC6\u0BAF\u0BCD\u0BAF \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD.",
|
|
6507
|
+
escalateFailed: "\u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD.",
|
|
6409
6508
|
prevSuggestion: "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA4\u0BC8\u0BAF \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8",
|
|
6410
6509
|
nextSuggestion: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4 \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8",
|
|
6411
6510
|
conceptIllustration: "\u0B95\u0BB0\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1 \u0BB5\u0BBF\u0BB3\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BAE\u0BCD",
|
|
@@ -6416,6 +6515,9 @@ var TA = {
|
|
|
6416
6515
|
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?",
|
|
6417
6516
|
copyAnswer: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1",
|
|
6418
6517
|
copyFailed: "\u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8",
|
|
6518
|
+
readAloud: "\u0B9A\u0BA4\u0BCD\u0BA4\u0BAE\u0BBE\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF",
|
|
6519
|
+
stopReading: "\u0BAA\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0BA4\u0BC8 \u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1",
|
|
6520
|
+
answerTable: "\u0B85\u0B9F\u0BCD\u0B9F\u0BB5\u0BA3\u0BC8",
|
|
6419
6521
|
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",
|
|
6420
6522
|
sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
|
|
6421
6523
|
sourceCountMany: "{count} \u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
@@ -6447,6 +6549,17 @@ var STRINGS = {
|
|
|
6447
6549
|
ar: AR,
|
|
6448
6550
|
ta: TA
|
|
6449
6551
|
};
|
|
6552
|
+
var SPEECH_TAGS = {
|
|
6553
|
+
en: "en-US",
|
|
6554
|
+
zh: "zh-CN",
|
|
6555
|
+
hi: "hi-IN",
|
|
6556
|
+
es: "es-ES",
|
|
6557
|
+
ar: "ar-SA",
|
|
6558
|
+
ta: "ta-IN"
|
|
6559
|
+
};
|
|
6560
|
+
function speechLocaleOf(locale) {
|
|
6561
|
+
return SPEECH_TAGS[locale];
|
|
6562
|
+
}
|
|
6450
6563
|
function resolveExploreLocale(explicit) {
|
|
6451
6564
|
const candidates = [
|
|
6452
6565
|
explicit,
|
|
@@ -6468,192 +6581,721 @@ function fill(template, values) {
|
|
|
6468
6581
|
return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
|
|
6469
6582
|
}
|
|
6470
6583
|
|
|
6471
|
-
// src/components/
|
|
6472
|
-
var
|
|
6473
|
-
"
|
|
6474
|
-
"
|
|
6475
|
-
"
|
|
6476
|
-
"
|
|
6477
|
-
"
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6584
|
+
// src/components/answers-i18n.ts
|
|
6585
|
+
var EN2 = {
|
|
6586
|
+
breadcrumbHome: "Home",
|
|
6587
|
+
answers: "Answers",
|
|
6588
|
+
indexHeading: "{product} answers",
|
|
6589
|
+
indexLead: "Questions about {product}, each answered by our own assistant from our published documentation \u2014 with links to the pages the answer came from.",
|
|
6590
|
+
seoIndexTitle: "Answers",
|
|
6591
|
+
seoIndexDescription: "Questions about {product}, answered from our published documentation, each with links to the pages the answer came from.",
|
|
6592
|
+
searchLabel: "Search questions",
|
|
6593
|
+
searchPlaceholder: "Search questions",
|
|
6594
|
+
filterByTopic: "Filter by topic",
|
|
6595
|
+
allTopics: "All",
|
|
6596
|
+
showingCount: "Showing {shown} of {total} questions",
|
|
6597
|
+
noMatchesTitle: "No questions match your filters",
|
|
6598
|
+
noMatchesBody: "Try a different search, or show every topic.",
|
|
6599
|
+
clearFilters: "Clear filters",
|
|
6600
|
+
noneYetTitle: "No answers published yet",
|
|
6601
|
+
noneYetBody: "{product} answers will appear here as they are published.",
|
|
6602
|
+
questionCountOne: "1 question",
|
|
6603
|
+
questionCountMany: "{count} questions",
|
|
6604
|
+
sourceCountOne: "1 source",
|
|
6605
|
+
sourceCountMany: "{count} sources",
|
|
6606
|
+
answerHeading: "Answer",
|
|
6607
|
+
sourcesHeading: "Sources",
|
|
6608
|
+
sourcesLead: "The pages this answer was drawn from.",
|
|
6609
|
+
aboutTitle: "About this answer",
|
|
6610
|
+
aboutBody: "Produced by our own assistant on {date} from our published documentation. The pages it drew on are linked under the answer. It is generated text, not a statement from a person \u2014 where it and a linked page disagree, the page is right.",
|
|
6611
|
+
answeredOn: "Answered {date}",
|
|
6612
|
+
topicsHeading: "Topics",
|
|
6613
|
+
relatedHeading: "Related questions",
|
|
6614
|
+
moreInTopic: "More in {topic}",
|
|
6615
|
+
previousQuestion: "Previous question",
|
|
6616
|
+
nextQuestion: "Next question",
|
|
6617
|
+
allAnswers: "All {product} answers",
|
|
6618
|
+
askYourOwn: "Ask your own question"
|
|
6619
|
+
};
|
|
6620
|
+
var ZH2 = {
|
|
6621
|
+
breadcrumbHome: "\u9996\u9875",
|
|
6622
|
+
answers: "\u95EE\u7B54",
|
|
6623
|
+
indexHeading: "{product} \u95EE\u7B54",
|
|
6624
|
+
indexLead: "\u5173\u4E8E {product} \u7684\u95EE\u9898\uFF0C\u6BCF\u4E2A\u56DE\u7B54\u90FD\u7531\u6211\u4EEC\u81EA\u5DF1\u7684\u52A9\u624B\u4F9D\u636E\u5DF2\u516C\u5F00\u7684\u6587\u6863\u751F\u6210\uFF0C\u5E76\u9644\u4E0A\u56DE\u7B54\u6240\u4F9D\u636E\u9875\u9762\u7684\u94FE\u63A5\u3002",
|
|
6625
|
+
seoIndexTitle: "\u95EE\u7B54",
|
|
6626
|
+
seoIndexDescription: "\u5173\u4E8E {product} \u7684\u95EE\u9898\uFF0C\u4F9D\u636E\u6211\u4EEC\u5DF2\u516C\u5F00\u7684\u6587\u6863\u4F5C\u7B54\uFF0C\u6BCF\u4E2A\u56DE\u7B54\u90FD\u9644\u6709\u6765\u6E90\u9875\u9762\u7684\u94FE\u63A5\u3002",
|
|
6627
|
+
searchLabel: "\u641C\u7D22\u95EE\u9898",
|
|
6628
|
+
searchPlaceholder: "\u641C\u7D22\u95EE\u9898",
|
|
6629
|
+
filterByTopic: "\u6309\u4E3B\u9898\u7B5B\u9009",
|
|
6630
|
+
allTopics: "\u5168\u90E8",
|
|
6631
|
+
showingCount: "\u663E\u793A {total} \u4E2A\u95EE\u9898\u4E2D\u7684 {shown} \u4E2A",
|
|
6632
|
+
noMatchesTitle: "\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u6761\u4EF6\u7684\u95EE\u9898",
|
|
6633
|
+
noMatchesBody: "\u6362\u4E2A\u641C\u7D22\u8BCD\uFF0C\u6216\u663E\u793A\u5168\u90E8\u4E3B\u9898\u3002",
|
|
6634
|
+
clearFilters: "\u6E05\u9664\u7B5B\u9009",
|
|
6635
|
+
noneYetTitle: "\u5C1A\u672A\u53D1\u5E03\u95EE\u7B54",
|
|
6636
|
+
noneYetBody: "{product} \u7684\u95EE\u7B54\u53D1\u5E03\u540E\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002",
|
|
6637
|
+
questionCountOne: "1 \u4E2A\u95EE\u9898",
|
|
6638
|
+
questionCountMany: "{count} \u4E2A\u95EE\u9898",
|
|
6639
|
+
sourceCountOne: "1 \u4E2A\u6765\u6E90",
|
|
6640
|
+
sourceCountMany: "{count} \u4E2A\u6765\u6E90",
|
|
6641
|
+
answerHeading: "\u56DE\u7B54",
|
|
6642
|
+
sourcesHeading: "\u6765\u6E90",
|
|
6643
|
+
sourcesLead: "\u672C\u56DE\u7B54\u6240\u4F9D\u636E\u7684\u9875\u9762\u3002",
|
|
6644
|
+
aboutTitle: "\u5173\u4E8E\u8FD9\u4E2A\u56DE\u7B54",
|
|
6645
|
+
aboutBody: "\u672C\u56DE\u7B54\u7531\u6211\u4EEC\u81EA\u5DF1\u7684\u52A9\u624B\u4E8E {date} \u4F9D\u636E\u5DF2\u516C\u5F00\u7684\u6587\u6863\u751F\u6210\uFF0C\u6240\u4F9D\u636E\u7684\u9875\u9762\u5217\u5728\u56DE\u7B54\u4E0B\u65B9\u3002\u8FD9\u662F\u81EA\u52A8\u751F\u6210\u7684\u6587\u672C\uFF0C\u5E76\u975E\u67D0\u4F4D\u540C\u4E8B\u7684\u8BF4\u6CD5\u2014\u2014\u5982\u679C\u5B83\u4E0E\u6240\u94FE\u63A5\u7684\u9875\u9762\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u4EE5\u9875\u9762\u4E3A\u51C6\u3002",
|
|
6646
|
+
answeredOn: "\u56DE\u7B54\u4E8E {date}",
|
|
6647
|
+
topicsHeading: "\u4E3B\u9898",
|
|
6648
|
+
relatedHeading: "\u76F8\u5173\u95EE\u9898",
|
|
6649
|
+
moreInTopic: "\u66F4\u591A\u300C{topic}\u300D\u95EE\u9898",
|
|
6650
|
+
previousQuestion: "\u4E0A\u4E00\u4E2A\u95EE\u9898",
|
|
6651
|
+
nextQuestion: "\u4E0B\u4E00\u4E2A\u95EE\u9898",
|
|
6652
|
+
allAnswers: "\u5168\u90E8 {product} \u95EE\u7B54",
|
|
6653
|
+
askYourOwn: "\u63D0\u51FA\u4F60\u7684\u95EE\u9898"
|
|
6654
|
+
};
|
|
6655
|
+
var HI2 = {
|
|
6656
|
+
breadcrumbHome: "\u0939\u094B\u092E",
|
|
6657
|
+
answers: "\u0909\u0924\u094D\u0924\u0930",
|
|
6658
|
+
indexHeading: "{product} \u0915\u0947 \u0909\u0924\u094D\u0924\u0930",
|
|
6659
|
+
indexLead: "{product} \u0938\u0947 \u091C\u0941\u0921\u093C\u0947 \u0938\u0935\u093E\u0932, \u091C\u093F\u0928\u0915\u093E \u0909\u0924\u094D\u0924\u0930 \u0939\u092E\u093E\u0930\u093E \u0905\u092A\u0928\u093E \u0938\u0939\u093E\u092F\u0915 \u0939\u092E\u093E\u0930\u0947 \u092A\u094D\u0930\u0915\u093E\u0936\u093F\u0924 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u0938\u0947 \u0926\u0947\u0924\u093E \u0939\u0948 \u2014 \u0914\u0930 \u091C\u093F\u0928 \u092A\u0928\u094D\u0928\u094B\u0902 \u0938\u0947 \u0909\u0924\u094D\u0924\u0930 \u0906\u092F\u093E, \u0909\u0928\u0915\u0947 \u0932\u093F\u0902\u0915 \u0938\u093E\u0925 \u092E\u0947\u0902 \u0939\u0948\u0902\u0964",
|
|
6660
|
+
seoIndexTitle: "\u0909\u0924\u094D\u0924\u0930",
|
|
6661
|
+
seoIndexDescription: "{product} \u0938\u0947 \u091C\u0941\u0921\u093C\u0947 \u0938\u0935\u093E\u0932\u094B\u0902 \u0915\u0947 \u0909\u0924\u094D\u0924\u0930, \u0939\u092E\u093E\u0930\u0947 \u092A\u094D\u0930\u0915\u093E\u0936\u093F\u0924 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u0938\u0947 \u2014 \u0939\u0930 \u0909\u0924\u094D\u0924\u0930 \u0915\u0947 \u0938\u093E\u0925 \u0938\u094D\u0930\u094B\u0924 \u092A\u0928\u094D\u0928\u094B\u0902 \u0915\u0947 \u0932\u093F\u0902\u0915\u0964",
|
|
6662
|
+
searchLabel: "\u0938\u0935\u093E\u0932 \u0916\u094B\u091C\u0947\u0902",
|
|
6663
|
+
searchPlaceholder: "\u0938\u0935\u093E\u0932 \u0916\u094B\u091C\u0947\u0902",
|
|
6664
|
+
filterByTopic: "\u0935\u093F\u0937\u092F \u0938\u0947 \u091B\u093E\u0901\u091F\u0947\u0902",
|
|
6665
|
+
allTopics: "\u0938\u092D\u0940",
|
|
6666
|
+
showingCount: "{total} \u092E\u0947\u0902 \u0938\u0947 {shown} \u0938\u0935\u093E\u0932 \u0926\u093F\u0916 \u0930\u0939\u0947 \u0939\u0948\u0902",
|
|
6667
|
+
noMatchesTitle: "\u0906\u092A\u0915\u0940 \u091B\u0901\u091F\u093E\u0908 \u0938\u0947 \u0915\u094B\u0908 \u0938\u0935\u093E\u0932 \u092E\u0947\u0932 \u0928\u0939\u0940\u0902 \u0916\u093E\u0924\u093E",
|
|
6668
|
+
noMatchesBody: "\u0915\u0941\u091B \u0914\u0930 \u0916\u094B\u091C\u0947\u0902, \u092F\u093E \u0938\u092D\u0940 \u0935\u093F\u0937\u092F \u0926\u093F\u0916\u093E\u090F\u0901\u0964",
|
|
6669
|
+
clearFilters: "\u091B\u0901\u091F\u093E\u0908 \u0939\u091F\u093E\u090F\u0901",
|
|
6670
|
+
noneYetTitle: "\u0905\u092D\u0940 \u0915\u094B\u0908 \u0909\u0924\u094D\u0924\u0930 \u092A\u094D\u0930\u0915\u093E\u0936\u093F\u0924 \u0928\u0939\u0940\u0902 \u0939\u0941\u0906",
|
|
6671
|
+
noneYetBody: "{product} \u0915\u0947 \u0909\u0924\u094D\u0924\u0930 \u092A\u094D\u0930\u0915\u093E\u0936\u093F\u0924 \u0939\u094B\u0924\u0947 \u0939\u0940 \u092F\u0939\u093E\u0901 \u0926\u093F\u0916\u0947\u0902\u0917\u0947\u0964",
|
|
6672
|
+
questionCountOne: "1 \u0938\u0935\u093E\u0932",
|
|
6673
|
+
questionCountMany: "{count} \u0938\u0935\u093E\u0932",
|
|
6674
|
+
sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
|
|
6675
|
+
sourceCountMany: "{count} \u0938\u094D\u0930\u094B\u0924",
|
|
6676
|
+
answerHeading: "\u0909\u0924\u094D\u0924\u0930",
|
|
6677
|
+
sourcesHeading: "\u0938\u094D\u0930\u094B\u0924",
|
|
6678
|
+
sourcesLead: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u091C\u093F\u0928 \u092A\u0928\u094D\u0928\u094B\u0902 \u0938\u0947 \u0932\u093F\u092F\u093E \u0917\u092F\u093E \u0939\u0948\u0964",
|
|
6679
|
+
aboutTitle: "\u0907\u0938 \u0909\u0924\u094D\u0924\u0930 \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902",
|
|
6680
|
+
aboutBody: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 {date} \u0915\u094B \u0939\u092E\u093E\u0930\u0947 \u0905\u092A\u0928\u0947 \u0938\u0939\u093E\u092F\u0915 \u0928\u0947 \u0939\u092E\u093E\u0930\u0947 \u092A\u094D\u0930\u0915\u093E\u0936\u093F\u0924 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u0938\u0947 \u0924\u0948\u092F\u093E\u0930 \u0915\u093F\u092F\u093E \u0925\u093E\u0964 \u091C\u093F\u0928 \u092A\u0928\u094D\u0928\u094B\u0902 \u0915\u093E \u0909\u092A\u092F\u094B\u0917 \u0939\u0941\u0906, \u0935\u0947 \u0909\u0924\u094D\u0924\u0930 \u0915\u0947 \u0928\u0940\u091A\u0947 \u0926\u093F\u090F \u0917\u090F \u0939\u0948\u0902\u0964 \u092F\u0939 \u0905\u092A\u0928\u0947-\u0906\u092A \u0924\u0948\u092F\u093E\u0930 \u0915\u093F\u092F\u093E \u0917\u092F\u093E \u092A\u093E\u0920 \u0939\u0948, \u0915\u093F\u0938\u0940 \u0935\u094D\u092F\u0915\u094D\u0924\u093F \u0915\u093E \u0915\u0925\u0928 \u0928\u0939\u0940\u0902 \u2014 \u0905\u0917\u0930 \u0907\u0938\u092E\u0947\u0902 \u0914\u0930 \u0932\u093F\u0902\u0915 \u0915\u093F\u090F \u0917\u090F \u092A\u0928\u094D\u0928\u0947 \u092E\u0947\u0902 \u092B\u093C\u0930\u094D\u0915\u093C \u0939\u094B, \u0924\u094B \u092A\u0928\u094D\u0928\u093E \u0938\u0939\u0940 \u0939\u0948\u0964",
|
|
6681
|
+
answeredOn: "{date} \u0915\u094B \u0909\u0924\u094D\u0924\u0930 \u0926\u093F\u092F\u093E \u0917\u092F\u093E",
|
|
6682
|
+
topicsHeading: "\u0935\u093F\u0937\u092F",
|
|
6683
|
+
relatedHeading: "\u0938\u0902\u092C\u0902\u0927\u093F\u0924 \u0938\u0935\u093E\u0932",
|
|
6684
|
+
moreInTopic: "{topic} \u092E\u0947\u0902 \u0914\u0930",
|
|
6685
|
+
previousQuestion: "\u092A\u093F\u091B\u0932\u093E \u0938\u0935\u093E\u0932",
|
|
6686
|
+
nextQuestion: "\u0905\u0917\u0932\u093E \u0938\u0935\u093E\u0932",
|
|
6687
|
+
allAnswers: "{product} \u0915\u0947 \u0938\u092D\u0940 \u0909\u0924\u094D\u0924\u0930",
|
|
6688
|
+
askYourOwn: "\u0905\u092A\u0928\u093E \u0938\u0935\u093E\u0932 \u092A\u0942\u091B\u0947\u0902"
|
|
6689
|
+
};
|
|
6690
|
+
var ES2 = {
|
|
6691
|
+
breadcrumbHome: "Inicio",
|
|
6692
|
+
answers: "Respuestas",
|
|
6693
|
+
indexHeading: "Respuestas sobre {product}",
|
|
6694
|
+
indexLead: "Preguntas sobre {product}, respondidas por nuestro propio asistente a partir de nuestra documentaci\xF3n publicada, con enlaces a las p\xE1ginas de las que sali\xF3 cada respuesta.",
|
|
6695
|
+
seoIndexTitle: "Respuestas",
|
|
6696
|
+
seoIndexDescription: "Preguntas sobre {product} respondidas a partir de nuestra documentaci\xF3n publicada, cada una con enlaces a las p\xE1ginas de origen.",
|
|
6697
|
+
searchLabel: "Buscar preguntas",
|
|
6698
|
+
searchPlaceholder: "Buscar preguntas",
|
|
6699
|
+
filterByTopic: "Filtrar por tema",
|
|
6700
|
+
allTopics: "Todas",
|
|
6701
|
+
showingCount: "Mostrando {shown} de {total} preguntas",
|
|
6702
|
+
noMatchesTitle: "Ninguna pregunta coincide con los filtros",
|
|
6703
|
+
noMatchesBody: "Prueba otra b\xFAsqueda o muestra todos los temas.",
|
|
6704
|
+
clearFilters: "Quitar filtros",
|
|
6705
|
+
noneYetTitle: "Todav\xEDa no hay respuestas publicadas",
|
|
6706
|
+
noneYetBody: "Las respuestas sobre {product} aparecer\xE1n aqu\xED a medida que se publiquen.",
|
|
6707
|
+
questionCountOne: "1 pregunta",
|
|
6708
|
+
questionCountMany: "{count} preguntas",
|
|
6709
|
+
sourceCountOne: "1 fuente",
|
|
6710
|
+
sourceCountMany: "{count} fuentes",
|
|
6711
|
+
answerHeading: "Respuesta",
|
|
6712
|
+
sourcesHeading: "Fuentes",
|
|
6713
|
+
sourcesLead: "Las p\xE1ginas de las que sali\xF3 esta respuesta.",
|
|
6714
|
+
aboutTitle: "Sobre esta respuesta",
|
|
6715
|
+
aboutBody: "La prepar\xF3 nuestro propio asistente el {date} a partir de nuestra documentaci\xF3n publicada. Las p\xE1ginas que utiliz\xF3 est\xE1n enlazadas debajo de la respuesta. Es texto generado, no la palabra de una persona: si la respuesta y una p\xE1gina enlazada no coinciden, manda la p\xE1gina.",
|
|
6716
|
+
answeredOn: "Respondida el {date}",
|
|
6717
|
+
topicsHeading: "Temas",
|
|
6718
|
+
relatedHeading: "Preguntas relacionadas",
|
|
6719
|
+
moreInTopic: "M\xE1s de {topic}",
|
|
6720
|
+
previousQuestion: "Pregunta anterior",
|
|
6721
|
+
nextQuestion: "Pregunta siguiente",
|
|
6722
|
+
allAnswers: "Todas las respuestas sobre {product}",
|
|
6723
|
+
askYourOwn: "Haz tu propia pregunta"
|
|
6724
|
+
};
|
|
6725
|
+
var AR2 = {
|
|
6726
|
+
breadcrumbHome: "\u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629",
|
|
6727
|
+
answers: "\u0627\u0644\u0625\u062C\u0627\u0628\u0627\u062A",
|
|
6728
|
+
indexHeading: "\u0625\u062C\u0627\u0628\u0627\u062A {product}",
|
|
6729
|
+
indexLead: "\u0623\u0633\u0626\u0644\u0629 \u062D\u0648\u0644 {product}\u060C \u064A\u062C\u064A\u0628 \u0639\u0646\u0647\u0627 \u0645\u0633\u0627\u0639\u062F\u0646\u0627 \u0627\u0639\u062A\u0645\u0627\u062F\u064B\u0627 \u0639\u0644\u0649 \u0648\u062B\u0627\u0626\u0642\u0646\u0627 \u0627\u0644\u0645\u0646\u0634\u0648\u0631\u0629\u060C \u0645\u0639 \u0631\u0648\u0627\u0628\u0637 \u0625\u0644\u0649 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062C\u0627\u0621\u062A \u0645\u0646\u0647\u0627 \u0643\u0644 \u0625\u062C\u0627\u0628\u0629.",
|
|
6730
|
+
seoIndexTitle: "\u0627\u0644\u0625\u062C\u0627\u0628\u0627\u062A",
|
|
6731
|
+
seoIndexDescription: "\u0623\u0633\u0626\u0644\u0629 \u062D\u0648\u0644 {product} \u0645\u064F\u062C\u0627\u0628 \u0639\u0646\u0647\u0627 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642\u0646\u0627 \u0627\u0644\u0645\u0646\u0634\u0648\u0631\u0629\u060C \u0645\u0639 \u0631\u0648\u0627\u0628\u0637 \u0625\u0644\u0649 \u0635\u0641\u062D\u0627\u062A \u0627\u0644\u0645\u0635\u062F\u0631 \u0644\u0643\u0644 \u0625\u062C\u0627\u0628\u0629.",
|
|
6732
|
+
searchLabel: "\u0627\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0623\u0633\u0626\u0644\u0629",
|
|
6733
|
+
searchPlaceholder: "\u0627\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0623\u0633\u0626\u0644\u0629",
|
|
6734
|
+
filterByTopic: "\u062A\u0635\u0641\u064A\u0629 \u062D\u0633\u0628 \u0627\u0644\u0645\u0648\u0636\u0648\u0639",
|
|
6735
|
+
allTopics: "\u0627\u0644\u0643\u0644",
|
|
6736
|
+
showingCount: "\u0639\u0631\u0636 {shown} \u0645\u0646 {total} \u0633\u0624\u0627\u0644\u064B\u0627",
|
|
6737
|
+
noMatchesTitle: "\u0644\u0627 \u062A\u0648\u062C\u062F \u0623\u0633\u0626\u0644\u0629 \u062A\u0637\u0627\u0628\u0642 \u0627\u0644\u062A\u0635\u0641\u064A\u0629",
|
|
6738
|
+
noMatchesBody: "\u062C\u0631\u0651\u0628 \u0628\u062D\u062B\u064B\u0627 \u0622\u062E\u0631\u060C \u0623\u0648 \u0627\u0639\u0631\u0636 \u0643\u0644 \u0627\u0644\u0645\u0648\u0627\u0636\u064A\u0639.",
|
|
6739
|
+
clearFilters: "\u0645\u0633\u062D \u0627\u0644\u062A\u0635\u0641\u064A\u0629",
|
|
6740
|
+
noneYetTitle: "\u0644\u0645 \u062A\u064F\u0646\u0634\u0631 \u0625\u062C\u0627\u0628\u0627\u062A \u0628\u0639\u062F",
|
|
6741
|
+
noneYetBody: "\u0633\u062A\u0638\u0647\u0631 \u0625\u062C\u0627\u0628\u0627\u062A {product} \u0647\u0646\u0627 \u0641\u0648\u0631 \u0646\u0634\u0631\u0647\u0627.",
|
|
6742
|
+
questionCountOne: "\u0633\u0624\u0627\u0644 \u0648\u0627\u062D\u062F",
|
|
6743
|
+
questionCountMany: "{count} \u0623\u0633\u0626\u0644\u0629",
|
|
6744
|
+
sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
|
|
6745
|
+
sourceCountMany: "{count} \u0645\u0635\u0627\u062F\u0631",
|
|
6746
|
+
answerHeading: "\u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6747
|
+
sourcesHeading: "\u0627\u0644\u0645\u0635\u0627\u062F\u0631",
|
|
6748
|
+
sourcesLead: "\u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u0627\u0633\u062A\u064F\u0645\u062F\u062A \u0645\u0646\u0647\u0627 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629.",
|
|
6749
|
+
aboutTitle: "\u0639\u0646 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6750
|
+
aboutBody: "\u0623\u0639\u062F\u0651\u0647\u0627 \u0645\u0633\u0627\u0639\u062F\u0646\u0627 \u0641\u064A {date} \u0627\u0639\u062A\u0645\u0627\u062F\u064B\u0627 \u0639\u0644\u0649 \u0648\u062B\u0627\u0626\u0642\u0646\u0627 \u0627\u0644\u0645\u0646\u0634\u0648\u0631\u0629\u060C \u0648\u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u0627\u0633\u062A\u0646\u062F \u0625\u0644\u064A\u0647\u0627 \u0645\u0630\u0643\u0648\u0631\u0629 \u0623\u0633\u0641\u0644 \u0627\u0644\u0625\u062C\u0627\u0628\u0629. \u0647\u0630\u0627 \u0646\u0635 \u0645\u064F\u0648\u0644\u064E\u0651\u062F \u0622\u0644\u064A\u064B\u0627 \u0648\u0644\u064A\u0633 \u0643\u0644\u0627\u0645 \u0634\u062E\u0635 \u2014 \u0648\u0625\u0630\u0627 \u0627\u062E\u062A\u0644\u0641 \u0645\u0639 \u0635\u0641\u062D\u0629 \u0645\u0631\u062A\u0628\u0637\u0629\u060C \u0641\u0627\u0644\u0635\u0641\u062D\u0629 \u0647\u064A \u0627\u0644\u0635\u062D\u064A\u062D\u0629.",
|
|
6751
|
+
answeredOn: "\u0623\u064F\u062C\u064A\u0628 \u0639\u0646\u0647 \u0641\u064A {date}",
|
|
6752
|
+
topicsHeading: "\u0627\u0644\u0645\u0648\u0627\u0636\u064A\u0639",
|
|
6753
|
+
relatedHeading: "\u0623\u0633\u0626\u0644\u0629 \u0630\u0627\u062A \u0635\u0644\u0629",
|
|
6754
|
+
moreInTopic: "\u0627\u0644\u0645\u0632\u064A\u062F \u0641\u064A {topic}",
|
|
6755
|
+
previousQuestion: "\u0627\u0644\u0633\u0624\u0627\u0644 \u0627\u0644\u0633\u0627\u0628\u0642",
|
|
6756
|
+
nextQuestion: "\u0627\u0644\u0633\u0624\u0627\u0644 \u0627\u0644\u062A\u0627\u0644\u064A",
|
|
6757
|
+
allAnswers: "\u0643\u0644 \u0625\u062C\u0627\u0628\u0627\u062A {product}",
|
|
6758
|
+
askYourOwn: "\u0627\u0637\u0631\u062D \u0633\u0624\u0627\u0644\u0643"
|
|
6759
|
+
};
|
|
6760
|
+
var TA2 = {
|
|
6761
|
+
breadcrumbHome: "\u0BAE\u0BC1\u0B95\u0BAA\u0BCD\u0BAA\u0BC1",
|
|
6762
|
+
answers: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6763
|
+
indexHeading: "{product} \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6764
|
+
indexLead: "{product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0BAF \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BCD \u2014 \u0B92\u0BB5\u0BCD\u0BB5\u0BCA\u0BA9\u0BCD\u0BB1\u0BC1\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BBF\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0B85\u0BB3\u0BBF\u0BA4\u0BCD\u0BA4 \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD, \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BB5\u0BA8\u0BCD\u0BA4 \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B87\u0BA3\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC1\u0B9F\u0BA9\u0BCD.",
|
|
6765
|
+
seoIndexTitle: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6766
|
+
seoIndexDescription: "{product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0BAF \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BBF\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD \u2014 \u0B92\u0BB5\u0BCD\u0BB5\u0BCA\u0BA9\u0BCD\u0BB1\u0BBF\u0BB2\u0BC1\u0BAE\u0BCD \u0BAE\u0BC2\u0BB2\u0BAA\u0BCD \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B87\u0BA3\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC1\u0B9F\u0BA9\u0BCD.",
|
|
6767
|
+
searchLabel: "\u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BC8\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6768
|
+
searchPlaceholder: "\u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BC8\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6769
|
+
filterByTopic: "\u0BA4\u0BB2\u0BC8\u0BAA\u0BCD\u0BAA\u0BBF\u0BA9\u0BCD\u0BAA\u0B9F\u0BBF \u0BB5\u0B9F\u0BBF\u0B95\u0B9F\u0BCD\u0B9F\u0BC1",
|
|
6770
|
+
allTopics: "\u0B85\u0BA9\u0BC8\u0BA4\u0BCD\u0BA4\u0BC1\u0BAE\u0BCD",
|
|
6771
|
+
showingCount: "{total} \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BBF\u0BB2\u0BCD {shown} \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1",
|
|
6772
|
+
noMatchesTitle: "\u0BB5\u0B9F\u0BBF\u0B95\u0B9F\u0BCD\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BC1\u0BAA\u0BCD \u0BAA\u0BCA\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF \u0B87\u0BB2\u0BCD\u0BB2\u0BC8",
|
|
6773
|
+
noMatchesBody: "\u0BB5\u0BC7\u0BB1\u0BC1 \u0B92\u0BA9\u0BCD\u0BB1\u0BC8\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1 \u0B8E\u0BB2\u0BCD\u0BB2\u0BBE\u0BA4\u0BCD \u0BA4\u0BB2\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
|
|
6774
|
+
clearFilters: "\u0BB5\u0B9F\u0BBF\u0B95\u0B9F\u0BCD\u0B9F\u0BB2\u0BC8 \u0BA8\u0BC0\u0B95\u0BCD\u0B95\u0BC1",
|
|
6775
|
+
noneYetTitle: "\u0B87\u0BA4\u0BC1\u0BB5\u0BB0\u0BC8 \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BBF\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8",
|
|
6776
|
+
noneYetBody: "{product} \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BBF\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0BAE\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B87\u0B99\u0BCD\u0B95\u0BC7 \u0BA4\u0BCB\u0BA9\u0BCD\u0BB1\u0BC1\u0BAE\u0BCD.",
|
|
6777
|
+
questionCountOne: "1 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF",
|
|
6778
|
+
questionCountMany: "{count} \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BCD",
|
|
6779
|
+
sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
|
|
6780
|
+
sourceCountMany: "{count} \u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6781
|
+
answerHeading: "\u0BAA\u0BA4\u0BBF\u0BB2\u0BCD",
|
|
6782
|
+
sourcesHeading: "\u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
6783
|
+
sourcesLead: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B8E\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
|
|
6784
|
+
aboutTitle: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF",
|
|
6785
|
+
aboutBody: "\u0B87\u0BA4\u0BC8 \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD {date} \u0B85\u0BA9\u0BCD\u0BB1\u0BC1 \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BBF\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0B89\u0BB0\u0BC1\u0BB5\u0BBE\u0B95\u0BCD\u0B95\u0BBF\u0BAF\u0BA4\u0BC1; \u0BAA\u0BAF\u0BA9\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BBF\u0BAF \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BC1\u0B95\u0BCD \u0B95\u0BC0\u0BB4\u0BC7 \u0B87\u0BA3\u0BC8\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BC1\u0BB3\u0BCD\u0BB3\u0BA9. \u0B87\u0BA4\u0BC1 \u0BA4\u0BBE\u0BA9\u0BBE\u0B95 \u0B89\u0BB0\u0BC1\u0BB5\u0BBE\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0B89\u0BB0\u0BC8, \u0B92\u0BB0\u0BC1 \u0BA8\u0BAA\u0BB0\u0BBF\u0BA9\u0BCD \u0B95\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 \u0B85\u0BB2\u0BCD\u0BB2 \u2014 \u0B87\u0BA4\u0BB1\u0BCD\u0B95\u0BC1\u0BAE\u0BCD \u0B87\u0BA3\u0BC8\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F \u0BAA\u0B95\u0BCD\u0B95\u0BA4\u0BCD\u0BA4\u0BBF\u0BB1\u0BCD\u0B95\u0BC1\u0BAE\u0BCD \u0BB5\u0BC7\u0BB1\u0BC1\u0BAA\u0BBE\u0B9F\u0BC1 \u0B87\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BBE\u0BB2\u0BCD, \u0BAA\u0B95\u0BCD\u0B95\u0BAE\u0BC7 \u0B9A\u0BB0\u0BBF.",
|
|
6786
|
+
answeredOn: "{date} \u0B85\u0BA9\u0BCD\u0BB1\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BB3\u0BBF\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1",
|
|
6787
|
+
topicsHeading: "\u0BA4\u0BB2\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD",
|
|
6788
|
+
relatedHeading: "\u0BA4\u0BCA\u0B9F\u0BB0\u0BCD\u0BAA\u0BC1\u0B9F\u0BC8\u0BAF \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0B95\u0BB3\u0BCD",
|
|
6789
|
+
moreInTopic: "{topic} \u0B87\u0BB2\u0BCD \u0BAE\u0BC7\u0BB2\u0BC1\u0BAE\u0BCD",
|
|
6790
|
+
previousQuestion: "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA4\u0BC8\u0BAF \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF",
|
|
6791
|
+
nextQuestion: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4 \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF",
|
|
6792
|
+
allAnswers: "{product} \u0B85\u0BA9\u0BC8\u0BA4\u0BCD\u0BA4\u0BC1\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BC1\u0BAE\u0BCD",
|
|
6793
|
+
askYourOwn: "\u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0BAF\u0BC8\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD"
|
|
6794
|
+
};
|
|
6795
|
+
var CHROME = {
|
|
6796
|
+
en: EN2,
|
|
6797
|
+
zh: ZH2,
|
|
6798
|
+
hi: HI2,
|
|
6799
|
+
es: ES2,
|
|
6800
|
+
ar: AR2,
|
|
6801
|
+
ta: TA2
|
|
6802
|
+
};
|
|
6803
|
+
function answerStrings(locale) {
|
|
6804
|
+
const chrome = CHROME[locale] ?? EN2;
|
|
6805
|
+
const explore = exploreStrings(locale);
|
|
6806
|
+
return {
|
|
6807
|
+
...chrome,
|
|
6808
|
+
answerTable: explore.answerTable,
|
|
6809
|
+
conceptIllustration: explore.conceptIllustration,
|
|
6810
|
+
opensInNewTab: explore.opensInNewTab
|
|
6811
|
+
};
|
|
6812
|
+
}
|
|
6813
|
+
var DATE_TAGS = {
|
|
6814
|
+
en: "en-GB",
|
|
6815
|
+
zh: "zh-CN",
|
|
6816
|
+
hi: "hi-IN",
|
|
6817
|
+
es: "es-ES",
|
|
6818
|
+
ar: "ar",
|
|
6819
|
+
ta: "ta-IN"
|
|
6820
|
+
};
|
|
6821
|
+
function formatAnswerDate(value, locale) {
|
|
6822
|
+
const at = new Date(value);
|
|
6823
|
+
if (Number.isNaN(at.getTime())) return "";
|
|
6824
|
+
try {
|
|
6825
|
+
return new Intl.DateTimeFormat(DATE_TAGS[locale] ?? "en-GB", {
|
|
6826
|
+
year: "numeric",
|
|
6827
|
+
month: "long",
|
|
6828
|
+
day: "numeric",
|
|
6829
|
+
timeZone: "UTC",
|
|
6830
|
+
numberingSystem: "latn"
|
|
6831
|
+
}).format(at);
|
|
6832
|
+
} catch {
|
|
6833
|
+
return value.slice(0, 10);
|
|
6496
6834
|
}
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6835
|
+
}
|
|
6836
|
+
|
|
6837
|
+
// src/components/answers-types.ts
|
|
6838
|
+
var PUBLISHED_ANSWER_FIELDS = {
|
|
6839
|
+
slug: true,
|
|
6840
|
+
order: true,
|
|
6841
|
+
question: true,
|
|
6842
|
+
answer: true,
|
|
6843
|
+
topic: true,
|
|
6844
|
+
summary: true,
|
|
6845
|
+
metaDescription: true,
|
|
6846
|
+
keywords: true,
|
|
6847
|
+
sources: true,
|
|
6848
|
+
related: true,
|
|
6849
|
+
answeredAt: true
|
|
6850
|
+
};
|
|
6851
|
+
var ANSWERS_PATH = "/answers";
|
|
6852
|
+
var ANSWER_PATH_PREFIX = "/answer";
|
|
6853
|
+
function answerPath(slug) {
|
|
6854
|
+
return `${ANSWER_PATH_PREFIX}/${encodeURIComponent(slug)}`;
|
|
6855
|
+
}
|
|
6856
|
+
function getAnswerBySlug(answers, slug) {
|
|
6857
|
+
if (!slug) return void 0;
|
|
6858
|
+
const wanted = slug.trim().toLowerCase();
|
|
6859
|
+
if (!wanted) return void 0;
|
|
6860
|
+
return answers.find((answer) => answer.slug === wanted);
|
|
6861
|
+
}
|
|
6862
|
+
function isPublishedSourceUrl(url) {
|
|
6863
|
+
let parsed;
|
|
6864
|
+
try {
|
|
6865
|
+
parsed = new URL(url);
|
|
6866
|
+
} catch {
|
|
6867
|
+
return false;
|
|
6502
6868
|
}
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6869
|
+
return parsed.protocol === "https:" && parsed.hostname !== "" && !parsed.username && !parsed.password;
|
|
6870
|
+
}
|
|
6871
|
+
function answerSourceHost(url) {
|
|
6872
|
+
try {
|
|
6873
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
6874
|
+
} catch {
|
|
6875
|
+
return "";
|
|
6510
6876
|
}
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6877
|
+
}
|
|
6878
|
+
var EXPLORE_ANSWER_CSS = `
|
|
6879
|
+
/* Nothing inside an answer may widen the page. Model output carries long URLs, code and
|
|
6880
|
+
tables \u2014 each of those overflows a phone by default, and one overflowing child makes the
|
|
6881
|
+
WHOLE document horizontally scrollable, not just the bubble. */
|
|
6882
|
+
.boff-explore-body,
|
|
6883
|
+
.boff-explore-body p,
|
|
6884
|
+
.boff-explore-body li,
|
|
6885
|
+
.boff-explore-body a,
|
|
6886
|
+
.boff-explore-body h1,
|
|
6887
|
+
.boff-explore-body h2,
|
|
6888
|
+
.boff-explore-body h3,
|
|
6889
|
+
/* h4-h6 as well: a published answer page pushes the model's own headings down a level or
|
|
6890
|
+
two so they nest under the page's, and a long unbroken word is no narrower for it. */
|
|
6891
|
+
.boff-explore-body h4,
|
|
6892
|
+
.boff-explore-body h5,
|
|
6893
|
+
.boff-explore-body h6 {
|
|
6894
|
+
overflow-wrap: anywhere;
|
|
6895
|
+
word-break: break-word;
|
|
6896
|
+
}
|
|
6897
|
+
.boff-explore-body pre {
|
|
6898
|
+
overflow-x: auto;
|
|
6899
|
+
max-width: 100%;
|
|
6900
|
+
}
|
|
6901
|
+
.boff-explore-body table {
|
|
6902
|
+
display: block;
|
|
6903
|
+
overflow-x: auto;
|
|
6904
|
+
max-width: 100%;
|
|
6905
|
+
}
|
|
6906
|
+
.boff-explore-body img {
|
|
6907
|
+
max-width: 100%;
|
|
6908
|
+
height: auto;
|
|
6909
|
+
}
|
|
6910
|
+
|
|
6911
|
+
/* ---- Comparison and pricing tables ----------------------------------------------------
|
|
6912
|
+
The harness emits a comparison, and a set of plans, as a GFM table whose FIRST column is
|
|
6913
|
+
the subject \u2014 the product, or the plan (CONTRACT.md \xA77). Two things have to be true of it:
|
|
6914
|
+
the page must not scroll sideways because of it, and it has to be readable on a 320px
|
|
6915
|
+
phone, which a four-column grid of 1px borders is not.
|
|
6916
|
+
|
|
6917
|
+
Wide: a contained scroller. \`max-width: 100%\` keeps the box inside the bubble and
|
|
6918
|
+
\`overflow-x: auto\` keeps the columns inside the box, so the widest possible table still
|
|
6919
|
+
cannot widen the document. \`overscroll-behavior-x: contain\` stops a swipe that runs out
|
|
6920
|
+
of table from chaining to the page \u2014 the same rule the transcript needed. */
|
|
6921
|
+
.boff-explore-body .boff-explore-table {
|
|
6922
|
+
max-width: 100%;
|
|
6923
|
+
overflow-x: auto;
|
|
6924
|
+
overscroll-behavior-x: contain;
|
|
6925
|
+
margin: 0.75rem 0;
|
|
6926
|
+
border: 1px solid hsl(var(--border));
|
|
6927
|
+
border-radius: 0.75rem;
|
|
6928
|
+
background-color: hsl(var(--card));
|
|
6929
|
+
}
|
|
6930
|
+
.boff-explore-body .boff-explore-table:focus-visible {
|
|
6931
|
+
outline: 2px solid hsl(var(--ring));
|
|
6932
|
+
outline-offset: 2px;
|
|
6933
|
+
}
|
|
6934
|
+
.boff-explore-body .boff-explore-table table {
|
|
6935
|
+
/* Beats the blanket \`display: block\` above, which is the unwrapped fallback. */
|
|
6936
|
+
display: table;
|
|
6937
|
+
width: 100%;
|
|
6938
|
+
max-width: none;
|
|
6939
|
+
margin: 0;
|
|
6940
|
+
border-collapse: collapse;
|
|
6941
|
+
font-size: 0.8125rem;
|
|
6942
|
+
}
|
|
6943
|
+
.boff-explore-body .boff-explore-table th,
|
|
6944
|
+
.boff-explore-body .boff-explore-table td {
|
|
6945
|
+
border: 0;
|
|
6946
|
+
border-top: 1px solid hsl(var(--border));
|
|
6947
|
+
padding: 0.5rem 0.75rem;
|
|
6948
|
+
/* \`start\`, never \`left\`: the page root carries dir="rtl" in Arabic, and a left-aligned
|
|
6949
|
+
table there reads against the grain of every other line on the page. */
|
|
6950
|
+
text-align: start;
|
|
6951
|
+
vertical-align: top;
|
|
6952
|
+
overflow-wrap: anywhere;
|
|
6953
|
+
/* Prices in a column line up under each other instead of drifting by digit width. */
|
|
6954
|
+
font-variant-numeric: tabular-nums;
|
|
6955
|
+
min-width: 6rem;
|
|
6956
|
+
}
|
|
6957
|
+
.boff-explore-body .boff-explore-table thead th {
|
|
6958
|
+
border-top: 0;
|
|
6959
|
+
background-color: hsl(var(--muted));
|
|
6960
|
+
color: hsl(var(--foreground));
|
|
6961
|
+
font-weight: 600;
|
|
6962
|
+
white-space: nowrap;
|
|
6963
|
+
}
|
|
6964
|
+
/* The first column is what the row is ABOUT \u2014 the product, or the plan name. Reading it as
|
|
6965
|
+
the row's heading is what makes a price list scannable rather than a grid of strings. */
|
|
6966
|
+
.boff-explore-body .boff-explore-table tbody td:first-child {
|
|
6967
|
+
font-weight: 600;
|
|
6968
|
+
color: hsl(var(--card-foreground));
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6971
|
+
/* Narrow: one card per row. Each cell prints its own column heading, so a value is never
|
|
6972
|
+
stranded without the question it answers, and the subject cell becomes the card's title.
|
|
6973
|
+
A media query rather than a measured width \u2014 these pages are serialised post-hydration,
|
|
6974
|
+
so anything measured here would ship to every phone as static HTML. */
|
|
6975
|
+
@media (max-width: 30rem) {
|
|
6976
|
+
.boff-explore-body .boff-explore-table {
|
|
6977
|
+
overflow-x: visible;
|
|
6525
6978
|
}
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
slug
|
|
6534
|
-
name
|
|
6535
|
-
tagline
|
|
6536
|
-
website
|
|
6537
|
-
}
|
|
6538
|
-
examplePrompts
|
|
6539
|
-
welcomeTitle
|
|
6540
|
-
welcomeBody
|
|
6541
|
-
limits {
|
|
6542
|
-
maxMessageLength
|
|
6543
|
-
maxTurnsPerConversation
|
|
6544
|
-
messagesPerDay
|
|
6545
|
-
historyTurns
|
|
6546
|
-
}
|
|
6547
|
-
captchaRequired
|
|
6548
|
-
recaptchaSiteKey`
|
|
6549
|
-
);
|
|
6550
|
-
var EXPLORE_CATALOG_HIGHLIGHT_FIELD = (
|
|
6551
|
-
/* GraphQL */
|
|
6552
|
-
`
|
|
6553
|
-
conceptHighlights {
|
|
6554
|
-
product
|
|
6555
|
-
productName
|
|
6556
|
-
title
|
|
6557
|
-
url
|
|
6558
|
-
imageUrl
|
|
6559
|
-
alt
|
|
6560
|
-
}`
|
|
6561
|
-
);
|
|
6562
|
-
function exploreCatalogDocument(extraFields) {
|
|
6563
|
-
return (
|
|
6564
|
-
/* GraphQL */
|
|
6565
|
-
`
|
|
6566
|
-
query ExploreCatalog($productSlug: String) {
|
|
6567
|
-
exploreCatalog(productSlug: $productSlug) {${EXPLORE_CATALOG_ESTABLISHED_FIELDS}${extraFields}
|
|
6568
|
-
}
|
|
6979
|
+
.boff-explore-body .boff-explore-table table,
|
|
6980
|
+
.boff-explore-body .boff-explore-table tbody,
|
|
6981
|
+
.boff-explore-body .boff-explore-table tr,
|
|
6982
|
+
.boff-explore-body .boff-explore-table td {
|
|
6983
|
+
display: block;
|
|
6984
|
+
width: 100%;
|
|
6985
|
+
min-width: 0;
|
|
6569
6986
|
}
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
}
|
|
6573
|
-
var EXPLORE_CATALOG_QUERY = exploreCatalogDocument(
|
|
6574
|
-
EXPLORE_CATALOG_HIGHLIGHT_FIELD
|
|
6575
|
-
);
|
|
6576
|
-
var EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS = exploreCatalogDocument("");
|
|
6577
|
-
var EXPLORE_MESSAGE_QUERY = (
|
|
6578
|
-
/* GraphQL */
|
|
6579
|
-
`
|
|
6580
|
-
query ExploreMessage($conversationToken: String!, $id: ID!) {
|
|
6581
|
-
exploreMessage(conversationToken: $conversationToken, id: $id) {
|
|
6582
|
-
${EXPLORE_OWN_MESSAGE_FIELDS}
|
|
6583
|
-
}
|
|
6987
|
+
.boff-explore-body .boff-explore-table thead {
|
|
6988
|
+
display: none;
|
|
6584
6989
|
}
|
|
6585
|
-
|
|
6586
|
-
);
|
|
6587
|
-
|
|
6588
|
-
/* GraphQL */
|
|
6589
|
-
`
|
|
6590
|
-
mutation SendExploreMessage($input: SendExploreMessageInput!) {
|
|
6591
|
-
sendExploreMessage(input: $input) {
|
|
6592
|
-
conversation {
|
|
6593
|
-
id
|
|
6594
|
-
token
|
|
6595
|
-
productSlug
|
|
6596
|
-
turnCount
|
|
6597
|
-
createdAt
|
|
6598
|
-
}
|
|
6599
|
-
userMessage {
|
|
6600
|
-
${EXPLORE_OWN_MESSAGE_FIELDS}
|
|
6601
|
-
}
|
|
6602
|
-
assistantMessage {
|
|
6603
|
-
${EXPLORE_OWN_MESSAGE_FIELDS}
|
|
6604
|
-
}
|
|
6605
|
-
remainingToday
|
|
6606
|
-
}
|
|
6990
|
+
.boff-explore-body .boff-explore-table tr {
|
|
6991
|
+
border-top: 1px solid hsl(var(--border));
|
|
6992
|
+
padding: 0.5rem 0;
|
|
6607
6993
|
}
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
var RECORD_EXPLORE_CLICK_MUTATION = (
|
|
6611
|
-
/* GraphQL */
|
|
6612
|
-
`
|
|
6613
|
-
mutation RecordExploreClick($input: RecordExploreClickInput!) {
|
|
6614
|
-
recordExploreClick(input: $input) {
|
|
6615
|
-
recorded
|
|
6616
|
-
}
|
|
6994
|
+
.boff-explore-body .boff-explore-table tr:first-child {
|
|
6995
|
+
border-top: 0;
|
|
6617
6996
|
}
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
/* GraphQL */
|
|
6622
|
-
`
|
|
6623
|
-
mutation SubmitExploreFeedback($input: SubmitExploreFeedbackInput!) {
|
|
6624
|
-
submitExploreFeedback(input: $input) {
|
|
6625
|
-
recorded
|
|
6626
|
-
feedback {
|
|
6627
|
-
rating
|
|
6628
|
-
reason
|
|
6629
|
-
comment
|
|
6630
|
-
createdAt
|
|
6631
|
-
}
|
|
6632
|
-
}
|
|
6997
|
+
.boff-explore-body .boff-explore-table td {
|
|
6998
|
+
border: 0;
|
|
6999
|
+
padding: 0.125rem 0.75rem;
|
|
6633
7000
|
}
|
|
6634
|
-
|
|
6635
|
-
);
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
shareToken
|
|
6643
|
-
}
|
|
7001
|
+
.boff-explore-body .boff-explore-table td[data-label]::before {
|
|
7002
|
+
content: attr(data-label);
|
|
7003
|
+
display: block;
|
|
7004
|
+
font-size: 0.6875rem;
|
|
7005
|
+
font-weight: 600;
|
|
7006
|
+
text-transform: uppercase;
|
|
7007
|
+
letter-spacing: 0.04em;
|
|
7008
|
+
color: hsl(var(--muted-foreground));
|
|
6644
7009
|
}
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
7010
|
+
.boff-explore-body .boff-explore-table tbody td:first-child {
|
|
7011
|
+
font-size: 0.9375rem;
|
|
7012
|
+
padding-bottom: 0.25rem;
|
|
7013
|
+
}
|
|
7014
|
+
.boff-explore-body .boff-explore-table tbody td:first-child::before {
|
|
7015
|
+
/* The plan's own name is the heading here; repeating "Plan" over it says nothing. */
|
|
7016
|
+
display: none;
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
7019
|
+
`;
|
|
7020
|
+
function ExploreAnswerStyles() {
|
|
7021
|
+
return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: EXPLORE_ANSWER_CSS } });
|
|
7022
|
+
}
|
|
7023
|
+
function inlineImageOrigins(products) {
|
|
7024
|
+
const origins = /* @__PURE__ */ new Set();
|
|
7025
|
+
for (const product of products) {
|
|
7026
|
+
let url;
|
|
7027
|
+
try {
|
|
7028
|
+
url = new URL(product.website);
|
|
7029
|
+
} catch {
|
|
7030
|
+
continue;
|
|
6653
7031
|
}
|
|
7032
|
+
if (url.protocol !== "https:") continue;
|
|
7033
|
+
const apex = url.hostname.replace(/^www\./, "");
|
|
7034
|
+
const port = url.port ? `:${url.port}` : "";
|
|
7035
|
+
origins.add(`https://${apex}${port}`);
|
|
7036
|
+
origins.add(`https://www.${apex}${port}`);
|
|
6654
7037
|
}
|
|
6655
|
-
|
|
6656
|
-
|
|
7038
|
+
return origins;
|
|
7039
|
+
}
|
|
7040
|
+
function isInlineImageAllowed(src, origins) {
|
|
7041
|
+
if (typeof src !== "string" || src === "") return false;
|
|
7042
|
+
let url;
|
|
7043
|
+
try {
|
|
7044
|
+
url = new URL(src);
|
|
7045
|
+
} catch {
|
|
7046
|
+
return false;
|
|
7047
|
+
}
|
|
7048
|
+
if (url.protocol !== "https:" || url.username || url.password) return false;
|
|
7049
|
+
return origins.has(url.origin);
|
|
7050
|
+
}
|
|
7051
|
+
var CODE_FENCE = /^\s*(?:```|~~~)/;
|
|
7052
|
+
var TABLE_ROW_LINE = /^\s{0,3}\|/;
|
|
7053
|
+
var TABLE_DELIMITER_ROW = /^\s{0,3}\|[\s:|-]*-[\s:|-]*$/;
|
|
7054
|
+
function readableLine(raw, mode) {
|
|
7055
|
+
let line = raw;
|
|
7056
|
+
line = line.replace(/!\[[^\]]*\]\([^)\s]*(?:\s+"[^"]*")?\)/g, "");
|
|
7057
|
+
line = mode === "speech" ? (
|
|
7058
|
+
// A voice reading "h-t-t-p-s colon slash slash…" mid-sentence is noise, and the
|
|
7059
|
+
// prompt asks for two to five links in every answer. The label IS the words.
|
|
7060
|
+
line.replace(/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, "$1")
|
|
7061
|
+
) : line.replace(/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, "$1 ($2)");
|
|
7062
|
+
line = mode === "speech" ? line.replace(/<(https?:\/\/[^>\s]+)>/g, "") : line.replace(/<(https?:\/\/[^>\s]+)>/g, "$1");
|
|
7063
|
+
line = line.replace(/^\s{0,3}#{1,6}\s+/, "");
|
|
7064
|
+
line = line.replace(/^\s{0,3}>\s?/, "");
|
|
7065
|
+
if (/^\s{0,3}([-*_])[ \t]*(?:\1[ \t]*){2,}$/.test(line)) return "";
|
|
7066
|
+
line = line.replace(/`([^`]+)`/g, "$1");
|
|
7067
|
+
line = line.replace(/\*\*([^*]+)\*\*/g, "$1");
|
|
7068
|
+
line = line.replace(/__([^_]+)__/g, "$1");
|
|
7069
|
+
line = line.replace(/(^|[^*\w])\*([^*\n]+)\*(?![*\w])/g, "$1$2");
|
|
7070
|
+
line = line.replace(/(^|[^_\w])_([^_\n]+)_(?![_\w])/g, "$1$2");
|
|
7071
|
+
return line.replace(/[ \t]+$/, "");
|
|
7072
|
+
}
|
|
7073
|
+
function tableCells(row) {
|
|
7074
|
+
const trimmed = row.trim();
|
|
7075
|
+
const cells = [];
|
|
7076
|
+
let cell = "";
|
|
7077
|
+
for (let at = 0; at < trimmed.length; at += 1) {
|
|
7078
|
+
const char = trimmed[at] ?? "";
|
|
7079
|
+
if (char === "\\") {
|
|
7080
|
+
cell += char + (trimmed[at + 1] ?? "");
|
|
7081
|
+
at += 1;
|
|
7082
|
+
continue;
|
|
7083
|
+
}
|
|
7084
|
+
if (char === "|") {
|
|
7085
|
+
cells.push(cell.trim());
|
|
7086
|
+
cell = "";
|
|
7087
|
+
continue;
|
|
7088
|
+
}
|
|
7089
|
+
cell += char;
|
|
7090
|
+
}
|
|
7091
|
+
cells.push(cell.trim());
|
|
7092
|
+
if (trimmed.startsWith("|") && cells[0] === "") cells.shift();
|
|
7093
|
+
if (trimmed.endsWith("|") && cells[cells.length - 1] === "") cells.pop();
|
|
7094
|
+
return cells;
|
|
7095
|
+
}
|
|
7096
|
+
function asSentence(text) {
|
|
7097
|
+
return /[.!?]$/.test(text) ? text : `${text}.`;
|
|
7098
|
+
}
|
|
7099
|
+
function spokenTable(rows) {
|
|
7100
|
+
if (rows.length < 2 || !TABLE_DELIMITER_ROW.test(rows[1] ?? "")) return rows;
|
|
7101
|
+
const labels = tableCells(rows[0] ?? "");
|
|
7102
|
+
const spoken = [];
|
|
7103
|
+
for (const row of rows.slice(2)) {
|
|
7104
|
+
const parts = [];
|
|
7105
|
+
tableCells(row).forEach((value, column) => {
|
|
7106
|
+
if (value === "") return;
|
|
7107
|
+
const label = column === 0 ? "" : labels[column] ?? "";
|
|
7108
|
+
parts.push(label === "" ? value : `${label}: ${value}`);
|
|
7109
|
+
});
|
|
7110
|
+
if (parts.length > 0) spoken.push(asSentence(parts.join(". ")));
|
|
7111
|
+
}
|
|
7112
|
+
return spoken;
|
|
7113
|
+
}
|
|
7114
|
+
function readableText(markdown, mode) {
|
|
7115
|
+
const lines = [];
|
|
7116
|
+
let inFence = false;
|
|
7117
|
+
let table = [];
|
|
7118
|
+
const flushTable = () => {
|
|
7119
|
+
if (table.length === 0) return;
|
|
7120
|
+
for (const line of spokenTable(table)) lines.push(readableLine(line, mode));
|
|
7121
|
+
table = [];
|
|
7122
|
+
};
|
|
7123
|
+
for (const raw of markdown.split("\n")) {
|
|
7124
|
+
if (CODE_FENCE.test(raw)) {
|
|
7125
|
+
flushTable();
|
|
7126
|
+
inFence = !inFence;
|
|
7127
|
+
continue;
|
|
7128
|
+
}
|
|
7129
|
+
if (inFence) {
|
|
7130
|
+
lines.push(raw);
|
|
7131
|
+
continue;
|
|
7132
|
+
}
|
|
7133
|
+
if (mode === "speech" && TABLE_ROW_LINE.test(raw)) {
|
|
7134
|
+
table.push(raw);
|
|
7135
|
+
continue;
|
|
7136
|
+
}
|
|
7137
|
+
flushTable();
|
|
7138
|
+
lines.push(readableLine(raw, mode));
|
|
7139
|
+
}
|
|
7140
|
+
flushTable();
|
|
7141
|
+
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
7142
|
+
}
|
|
7143
|
+
function answerPlainText(markdown) {
|
|
7144
|
+
return readableText(markdown, "clipboard");
|
|
7145
|
+
}
|
|
7146
|
+
function answerSpeechText(markdown) {
|
|
7147
|
+
return readableText(markdown, "speech");
|
|
7148
|
+
}
|
|
7149
|
+
var AnswerScopeContext = React.createContext(null);
|
|
7150
|
+
var InsideLinkContext = React.createContext(false);
|
|
7151
|
+
function AnswerLink(props) {
|
|
7152
|
+
return /* @__PURE__ */ jsxRuntime.jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownLink, { ...props }) });
|
|
7153
|
+
}
|
|
7154
|
+
var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
|
|
7155
|
+
function InlineConceptImage({ src, alt }) {
|
|
7156
|
+
const scope = React.useContext(AnswerScopeContext);
|
|
7157
|
+
const insideLink = React.useContext(InsideLinkContext);
|
|
7158
|
+
if (!scope || !scope.enabled || !isInlineImageAllowed(src, scope.origins) || scope.failed.has(src)) {
|
|
7159
|
+
return null;
|
|
7160
|
+
}
|
|
7161
|
+
const { strings: T, onFailed } = scope;
|
|
7162
|
+
const picture = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7163
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7164
|
+
"img",
|
|
7165
|
+
{
|
|
7166
|
+
src,
|
|
7167
|
+
alt: alt ?? "",
|
|
7168
|
+
loading: "lazy",
|
|
7169
|
+
decoding: "async",
|
|
7170
|
+
onError: () => onFailed(src),
|
|
7171
|
+
className: "block h-auto max-h-80 w-auto max-w-full object-contain"
|
|
7172
|
+
}
|
|
7173
|
+
),
|
|
7174
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7175
|
+
"span",
|
|
7176
|
+
{
|
|
7177
|
+
"aria-hidden": "true",
|
|
7178
|
+
className: "pointer-events-none absolute left-2 top-2 rounded-full border border-border bg-background/90 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-foreground shadow-sm",
|
|
7179
|
+
children: T.conceptIllustration
|
|
7180
|
+
}
|
|
7181
|
+
)
|
|
7182
|
+
] });
|
|
7183
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-boff-explore": "inline-image", className: "my-3 block", children: insideLink ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: INLINE_IMAGE_FRAME, children: picture }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7184
|
+
"a",
|
|
7185
|
+
{
|
|
7186
|
+
href: src,
|
|
7187
|
+
target: "_blank",
|
|
7188
|
+
rel: "noopener noreferrer",
|
|
7189
|
+
className: cn(
|
|
7190
|
+
INLINE_IMAGE_FRAME,
|
|
7191
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7192
|
+
),
|
|
7193
|
+
children: [
|
|
7194
|
+
picture,
|
|
7195
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
|
|
7196
|
+
"(",
|
|
7197
|
+
T.opensInNewTab,
|
|
7198
|
+
")"
|
|
7199
|
+
] })
|
|
7200
|
+
]
|
|
7201
|
+
}
|
|
7202
|
+
) });
|
|
7203
|
+
}
|
|
7204
|
+
function markdownText(node) {
|
|
7205
|
+
if (!node) return "";
|
|
7206
|
+
if (typeof node.value === "string") return node.value;
|
|
7207
|
+
return (node.children ?? []).map(markdownText).join("");
|
|
7208
|
+
}
|
|
7209
|
+
function hasHeaderCells(node) {
|
|
7210
|
+
return (node?.children ?? []).some((cell) => cell.tagName === "th");
|
|
7211
|
+
}
|
|
7212
|
+
function findHeaderRow(node) {
|
|
7213
|
+
for (const child of node?.children ?? []) {
|
|
7214
|
+
if (child.tagName === "tr" && hasHeaderCells(child)) return child;
|
|
7215
|
+
const nested = findHeaderRow(child);
|
|
7216
|
+
if (nested !== null) return nested;
|
|
7217
|
+
}
|
|
7218
|
+
return null;
|
|
7219
|
+
}
|
|
7220
|
+
function tableColumnLabels(node) {
|
|
7221
|
+
const row = findHeaderRow(node);
|
|
7222
|
+
if (row === null) return [];
|
|
7223
|
+
return (row.children ?? []).filter((cell) => cell.tagName === "th").map((cell) => markdownText(cell).trim());
|
|
7224
|
+
}
|
|
7225
|
+
var TableColumnsContext = React.createContext([]);
|
|
7226
|
+
function AnswerTable({ node, children }) {
|
|
7227
|
+
const scope = React.useContext(AnswerScopeContext);
|
|
7228
|
+
const table = /* @__PURE__ */ jsxRuntime.jsx(TableColumnsContext.Provider, { value: tableColumnLabels(node), children: /* @__PURE__ */ jsxRuntime.jsx("table", { children }) });
|
|
7229
|
+
if (!scope) return table;
|
|
7230
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7231
|
+
"div",
|
|
7232
|
+
{
|
|
7233
|
+
"data-boff-explore": "table",
|
|
7234
|
+
role: "region",
|
|
7235
|
+
"aria-label": scope.strings.answerTable,
|
|
7236
|
+
tabIndex: 0,
|
|
7237
|
+
className: "boff-explore-table",
|
|
7238
|
+
children: table
|
|
7239
|
+
}
|
|
7240
|
+
);
|
|
7241
|
+
}
|
|
7242
|
+
function AnswerTableRow({
|
|
7243
|
+
node,
|
|
7244
|
+
children,
|
|
7245
|
+
...props
|
|
7246
|
+
}) {
|
|
7247
|
+
const labels = React.useContext(TableColumnsContext);
|
|
7248
|
+
if (labels.length === 0 || hasHeaderCells(node)) {
|
|
7249
|
+
return /* @__PURE__ */ jsxRuntime.jsx("tr", { ...props, children });
|
|
7250
|
+
}
|
|
7251
|
+
let column = 0;
|
|
7252
|
+
const cells = React.Children.map(children, (cell) => {
|
|
7253
|
+
if (!React.isValidElement(cell)) return cell;
|
|
7254
|
+
const label = labels[column] ?? "";
|
|
7255
|
+
column += 1;
|
|
7256
|
+
if (label === "") return cell;
|
|
7257
|
+
return React.cloneElement(cell, {
|
|
7258
|
+
"data-label": label
|
|
7259
|
+
});
|
|
7260
|
+
});
|
|
7261
|
+
return /* @__PURE__ */ jsxRuntime.jsx("tr", { ...props, children: cells });
|
|
7262
|
+
}
|
|
7263
|
+
var ANSWER_MARKDOWN_COMPONENTS = {
|
|
7264
|
+
a: AnswerLink,
|
|
7265
|
+
img: InlineConceptImage,
|
|
7266
|
+
table: AnswerTable,
|
|
7267
|
+
tr: AnswerTableRow
|
|
7268
|
+
};
|
|
7269
|
+
function ExploreAnswerBody({
|
|
7270
|
+
children,
|
|
7271
|
+
strings,
|
|
7272
|
+
imageOrigins,
|
|
7273
|
+
enabled = true,
|
|
7274
|
+
components,
|
|
7275
|
+
className
|
|
7276
|
+
}) {
|
|
7277
|
+
const [failed, setFailed] = React.useState(() => /* @__PURE__ */ new Set());
|
|
7278
|
+
const onFailed = React.useCallback((src) => {
|
|
7279
|
+
setFailed(
|
|
7280
|
+
(current) => current.has(src) ? current : new Set(current).add(src)
|
|
7281
|
+
);
|
|
7282
|
+
}, []);
|
|
7283
|
+
const scope = React.useMemo(
|
|
7284
|
+
() => ({
|
|
7285
|
+
strings,
|
|
7286
|
+
enabled,
|
|
7287
|
+
origins: imageOrigins,
|
|
7288
|
+
failed,
|
|
7289
|
+
onFailed
|
|
7290
|
+
}),
|
|
7291
|
+
[strings, enabled, imageOrigins, failed, onFailed]
|
|
7292
|
+
);
|
|
7293
|
+
const overrides = React.useMemo(
|
|
7294
|
+
() => components ? { ...ANSWER_MARKDOWN_COMPONENTS, ...components } : ANSWER_MARKDOWN_COMPONENTS,
|
|
7295
|
+
[components]
|
|
7296
|
+
);
|
|
7297
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("boff-prose boff-explore-body min-w-0", className), children: /* @__PURE__ */ jsxRuntime.jsx(AnswerScopeContext.Provider, { value: scope, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { components: overrides, children }) }) });
|
|
7298
|
+
}
|
|
6657
7299
|
var PROSE_CSS = `
|
|
6658
7300
|
.boff-prose {
|
|
6659
7301
|
max-width: none;
|
|
@@ -6830,6 +7472,1130 @@ var PROSE_CSS = `
|
|
|
6830
7472
|
function ProseStyles() {
|
|
6831
7473
|
return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: PROSE_CSS } });
|
|
6832
7474
|
}
|
|
7475
|
+
var META_DESCRIPTION_LIMIT2 = 160;
|
|
7476
|
+
var TITLE_LIMIT = 100;
|
|
7477
|
+
var RELATED_LIMIT2 = 4;
|
|
7478
|
+
function normaliseSiteUrl2(siteUrl) {
|
|
7479
|
+
return siteUrl.trim().replace(/\/+$/, "");
|
|
7480
|
+
}
|
|
7481
|
+
function absoluteUrl2(base, path) {
|
|
7482
|
+
if (/^https?:\/\//i.test(path)) return path;
|
|
7483
|
+
return `${base}${path.startsWith("/") ? path : `/${path}`}`;
|
|
7484
|
+
}
|
|
7485
|
+
function sortByOrder2(answers) {
|
|
7486
|
+
return [...answers].sort(
|
|
7487
|
+
(a, b) => a.order - b.order || a.slug.localeCompare(b.slug)
|
|
7488
|
+
);
|
|
7489
|
+
}
|
|
7490
|
+
function clampText2(text, limit) {
|
|
7491
|
+
if (text.length <= limit) return text;
|
|
7492
|
+
const cut = text.slice(0, limit - 1);
|
|
7493
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
7494
|
+
return `${(lastSpace > 0 ? cut.slice(0, lastSpace) : cut).replace(/[\s,;:—–-]+$/, "")}\u2026`;
|
|
7495
|
+
}
|
|
7496
|
+
function questionCount(T, count) {
|
|
7497
|
+
return count === 1 ? T.questionCountOne : fill(T.questionCountMany, { count: String(count) });
|
|
7498
|
+
}
|
|
7499
|
+
function sourceCount(T, count) {
|
|
7500
|
+
return count === 1 ? T.sourceCountOne : fill(T.sourceCountMany, { count: String(count) });
|
|
7501
|
+
}
|
|
7502
|
+
function slugifyAnchor2(value) {
|
|
7503
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7504
|
+
}
|
|
7505
|
+
function publishableSources(sources) {
|
|
7506
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7507
|
+
const kept = [];
|
|
7508
|
+
for (const source of sources) {
|
|
7509
|
+
if (!isPublishedSourceUrl(source.url) || seen.has(source.url)) continue;
|
|
7510
|
+
seen.add(source.url);
|
|
7511
|
+
kept.push(source);
|
|
7512
|
+
}
|
|
7513
|
+
return kept;
|
|
7514
|
+
}
|
|
7515
|
+
function groupByTopic(ordered, topics) {
|
|
7516
|
+
const byName = /* @__PURE__ */ new Map();
|
|
7517
|
+
for (const answer of ordered) {
|
|
7518
|
+
const list = byName.get(answer.topic);
|
|
7519
|
+
if (list) list.push(answer);
|
|
7520
|
+
else byName.set(answer.topic, [answer]);
|
|
7521
|
+
}
|
|
7522
|
+
const described = [];
|
|
7523
|
+
for (const topic of topics ?? []) {
|
|
7524
|
+
const list = byName.get(topic.name);
|
|
7525
|
+
if (!list) continue;
|
|
7526
|
+
described.push({
|
|
7527
|
+
name: topic.name,
|
|
7528
|
+
description: topic.description,
|
|
7529
|
+
answers: list
|
|
7530
|
+
});
|
|
7531
|
+
byName.delete(topic.name);
|
|
7532
|
+
}
|
|
7533
|
+
for (const [name, list] of byName) {
|
|
7534
|
+
described.push({ name, description: "", answers: list });
|
|
7535
|
+
}
|
|
7536
|
+
const used = /* @__PURE__ */ new Set();
|
|
7537
|
+
return described.map((group) => {
|
|
7538
|
+
const base = `answers-${slugifyAnchor2(group.name) || "topic"}`;
|
|
7539
|
+
let anchor = base;
|
|
7540
|
+
for (let n = 2; used.has(anchor); n += 1) anchor = `${base}-${n}`;
|
|
7541
|
+
used.add(anchor);
|
|
7542
|
+
return { ...group, anchor };
|
|
7543
|
+
});
|
|
7544
|
+
}
|
|
7545
|
+
function searchTokens2(query) {
|
|
7546
|
+
return query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
7547
|
+
}
|
|
7548
|
+
function matchesSearch2(answer, tokens) {
|
|
7549
|
+
if (tokens.length === 0) return true;
|
|
7550
|
+
const haystack = [
|
|
7551
|
+
answer.question,
|
|
7552
|
+
answer.summary,
|
|
7553
|
+
answer.topic,
|
|
7554
|
+
...answer.keywords
|
|
7555
|
+
].join(" ").toLowerCase();
|
|
7556
|
+
return tokens.every((token) => haystack.includes(token));
|
|
7557
|
+
}
|
|
7558
|
+
function copyKey2(index, text) {
|
|
7559
|
+
return `${index}-${text}`;
|
|
7560
|
+
}
|
|
7561
|
+
function demoteHeading(Tag) {
|
|
7562
|
+
function DemotedHeading({
|
|
7563
|
+
node: _node,
|
|
7564
|
+
...props
|
|
7565
|
+
}) {
|
|
7566
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tag, { ...props });
|
|
7567
|
+
}
|
|
7568
|
+
DemotedHeading.displayName = `DemotedHeading(${Tag})`;
|
|
7569
|
+
return DemotedHeading;
|
|
7570
|
+
}
|
|
7571
|
+
var ANSWER_HEADING_SHIFT = {
|
|
7572
|
+
h1: demoteHeading("h3"),
|
|
7573
|
+
h2: demoteHeading("h3"),
|
|
7574
|
+
h3: demoteHeading("h4"),
|
|
7575
|
+
h4: demoteHeading("h5"),
|
|
7576
|
+
h5: demoteHeading("h6"),
|
|
7577
|
+
h6: demoteHeading("h6")
|
|
7578
|
+
};
|
|
7579
|
+
var ENGLISH_TEXT = { lang: "en" };
|
|
7580
|
+
function DefaultAnswerLink({
|
|
7581
|
+
href,
|
|
7582
|
+
className,
|
|
7583
|
+
children,
|
|
7584
|
+
"aria-label": ariaLabel
|
|
7585
|
+
}) {
|
|
7586
|
+
return /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, "aria-label": ariaLabel, children });
|
|
7587
|
+
}
|
|
7588
|
+
function AnswerCard({
|
|
7589
|
+
answer,
|
|
7590
|
+
strings: T,
|
|
7591
|
+
Link
|
|
7592
|
+
}) {
|
|
7593
|
+
const sources = publishableSources(answer.sources).length;
|
|
7594
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7595
|
+
Link,
|
|
7596
|
+
{
|
|
7597
|
+
href: answerPath(answer.slug),
|
|
7598
|
+
className: "group flex h-full flex-col gap-2 rounded-2xl border border-border bg-card p-5 text-card-foreground shadow-sm transition hover:-translate-y-0.5 hover:border-primary/40 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transform-none motion-reduce:transition-none",
|
|
7599
|
+
children: [
|
|
7600
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7601
|
+
"h3",
|
|
7602
|
+
{
|
|
7603
|
+
...ENGLISH_TEXT,
|
|
7604
|
+
className: "text-base font-semibold leading-snug text-card-foreground transition-colors group-hover:text-primary",
|
|
7605
|
+
children: answer.question
|
|
7606
|
+
}
|
|
7607
|
+
),
|
|
7608
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7609
|
+
"p",
|
|
7610
|
+
{
|
|
7611
|
+
...ENGLISH_TEXT,
|
|
7612
|
+
className: "line-clamp-3 text-sm leading-relaxed text-muted-foreground",
|
|
7613
|
+
children: answer.summary
|
|
7614
|
+
}
|
|
7615
|
+
),
|
|
7616
|
+
sources > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "mt-auto inline-flex items-center gap-1.5 pt-2 text-xs font-medium text-muted-foreground", children: [
|
|
7617
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookOpenText, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
7618
|
+
sourceCount(T, sources)
|
|
7619
|
+
] }) : null
|
|
7620
|
+
]
|
|
7621
|
+
}
|
|
7622
|
+
);
|
|
7623
|
+
}
|
|
7624
|
+
function FilterChip2({
|
|
7625
|
+
label,
|
|
7626
|
+
count,
|
|
7627
|
+
active,
|
|
7628
|
+
topic,
|
|
7629
|
+
onSelect
|
|
7630
|
+
}) {
|
|
7631
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7632
|
+
"button",
|
|
7633
|
+
{
|
|
7634
|
+
type: "button",
|
|
7635
|
+
"aria-pressed": active,
|
|
7636
|
+
"data-topic": topic,
|
|
7637
|
+
onClick: onSelect,
|
|
7638
|
+
className: cn(
|
|
7639
|
+
"inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7640
|
+
active ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-foreground hover:border-primary/40 hover:bg-muted"
|
|
7641
|
+
),
|
|
7642
|
+
children: [
|
|
7643
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
|
|
7644
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7645
|
+
"span",
|
|
7646
|
+
{
|
|
7647
|
+
className: cn(
|
|
7648
|
+
"rounded-full px-1.5 text-xs tabular-nums",
|
|
7649
|
+
active ? "bg-primary-foreground/20 text-primary-foreground" : "bg-muted text-muted-foreground"
|
|
7650
|
+
),
|
|
7651
|
+
children: count
|
|
7652
|
+
}
|
|
7653
|
+
)
|
|
7654
|
+
]
|
|
7655
|
+
}
|
|
7656
|
+
);
|
|
7657
|
+
}
|
|
7658
|
+
function AnswersPage({
|
|
7659
|
+
productName,
|
|
7660
|
+
siteUrl,
|
|
7661
|
+
answers,
|
|
7662
|
+
topics,
|
|
7663
|
+
cta,
|
|
7664
|
+
linkComponent,
|
|
7665
|
+
title,
|
|
7666
|
+
description,
|
|
7667
|
+
locale,
|
|
7668
|
+
className
|
|
7669
|
+
}) {
|
|
7670
|
+
const Link = linkComponent ?? DefaultAnswerLink;
|
|
7671
|
+
const base = normaliseSiteUrl2(siteUrl);
|
|
7672
|
+
const searchId = React.useId();
|
|
7673
|
+
const activeLocale = React.useMemo(() => resolveExploreLocale(locale), [locale]);
|
|
7674
|
+
const T = React.useMemo(() => answerStrings(activeLocale), [activeLocale]);
|
|
7675
|
+
const rtl = isRtlLocale(activeLocale);
|
|
7676
|
+
const ordered = React.useMemo(() => sortByOrder2(answers), [answers]);
|
|
7677
|
+
const groups = React.useMemo(
|
|
7678
|
+
() => groupByTopic(ordered, topics),
|
|
7679
|
+
[ordered, topics]
|
|
7680
|
+
);
|
|
7681
|
+
const [query, setQuery] = React.useState("");
|
|
7682
|
+
const [activeTopic, setActiveTopic] = React.useState(null);
|
|
7683
|
+
const hasAnswers = ordered.length > 0;
|
|
7684
|
+
const tokens = React.useMemo(() => searchTokens2(query), [query]);
|
|
7685
|
+
const searched = React.useMemo(
|
|
7686
|
+
() => ordered.filter((answer) => matchesSearch2(answer, tokens)),
|
|
7687
|
+
[ordered, tokens]
|
|
7688
|
+
);
|
|
7689
|
+
const countsByTopic = React.useMemo(() => {
|
|
7690
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7691
|
+
for (const answer of searched) {
|
|
7692
|
+
counts.set(answer.topic, (counts.get(answer.topic) ?? 0) + 1);
|
|
7693
|
+
}
|
|
7694
|
+
return counts;
|
|
7695
|
+
}, [searched]);
|
|
7696
|
+
const visibleGroups = React.useMemo(() => {
|
|
7697
|
+
const visible = new Set(
|
|
7698
|
+
searched.filter(
|
|
7699
|
+
(answer) => activeTopic === null || answer.topic === activeTopic
|
|
7700
|
+
)
|
|
7701
|
+
);
|
|
7702
|
+
return groups.map((group) => ({
|
|
7703
|
+
...group,
|
|
7704
|
+
answers: group.answers.filter((answer) => visible.has(answer))
|
|
7705
|
+
})).filter((group) => group.answers.length > 0);
|
|
7706
|
+
}, [groups, searched, activeTopic]);
|
|
7707
|
+
const visibleTotal = visibleGroups.reduce(
|
|
7708
|
+
(sum, group) => sum + group.answers.length,
|
|
7709
|
+
0
|
|
7710
|
+
);
|
|
7711
|
+
const filtering = tokens.length > 0 || activeTopic !== null;
|
|
7712
|
+
const clearFilters = React.useCallback(() => {
|
|
7713
|
+
setQuery("");
|
|
7714
|
+
setActiveTopic(null);
|
|
7715
|
+
}, []);
|
|
7716
|
+
const heading = title ?? fill(T.indexHeading, { product: productName });
|
|
7717
|
+
const metaDescription = description ?? clampText2(
|
|
7718
|
+
fill(T.seoIndexDescription, { product: productName }),
|
|
7719
|
+
META_DESCRIPTION_LIMIT2
|
|
7720
|
+
);
|
|
7721
|
+
const lead = description ?? fill(T.indexLead, { product: productName });
|
|
7722
|
+
const canonical = `${base}${ANSWERS_PATH}`;
|
|
7723
|
+
const structuredData = React.useMemo(
|
|
7724
|
+
() => [
|
|
7725
|
+
{
|
|
7726
|
+
"@context": "https://schema.org",
|
|
7727
|
+
"@type": "CollectionPage",
|
|
7728
|
+
name: heading,
|
|
7729
|
+
description: metaDescription,
|
|
7730
|
+
url: canonical,
|
|
7731
|
+
isPartOf: { "@type": "WebSite", name: productName, url: `${base}/` },
|
|
7732
|
+
mainEntity: {
|
|
7733
|
+
"@type": "ItemList",
|
|
7734
|
+
numberOfItems: ordered.length,
|
|
7735
|
+
itemListElement: ordered.map((answer, index) => ({
|
|
7736
|
+
"@type": "ListItem",
|
|
7737
|
+
position: index + 1,
|
|
7738
|
+
url: absoluteUrl2(base, answerPath(answer.slug)),
|
|
7739
|
+
name: answer.question
|
|
7740
|
+
}))
|
|
7741
|
+
}
|
|
7742
|
+
},
|
|
7743
|
+
{
|
|
7744
|
+
"@context": "https://schema.org",
|
|
7745
|
+
"@type": "BreadcrumbList",
|
|
7746
|
+
itemListElement: [
|
|
7747
|
+
{
|
|
7748
|
+
"@type": "ListItem",
|
|
7749
|
+
position: 1,
|
|
7750
|
+
name: T.breadcrumbHome,
|
|
7751
|
+
item: `${base}/`
|
|
7752
|
+
},
|
|
7753
|
+
{
|
|
7754
|
+
"@type": "ListItem",
|
|
7755
|
+
position: 2,
|
|
7756
|
+
name: T.answers,
|
|
7757
|
+
item: canonical
|
|
7758
|
+
}
|
|
7759
|
+
]
|
|
7760
|
+
}
|
|
7761
|
+
],
|
|
7762
|
+
[base, canonical, heading, metaDescription, ordered, productName, T]
|
|
7763
|
+
);
|
|
7764
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7765
|
+
"div",
|
|
7766
|
+
{
|
|
7767
|
+
"data-answers": "landing",
|
|
7768
|
+
"data-locale": activeLocale,
|
|
7769
|
+
dir: rtl ? "rtl" : void 0,
|
|
7770
|
+
className: cn("bg-background text-foreground", className),
|
|
7771
|
+
children: [
|
|
7772
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7773
|
+
PageHead,
|
|
7774
|
+
{
|
|
7775
|
+
title: T.seoIndexTitle,
|
|
7776
|
+
description: metaDescription,
|
|
7777
|
+
productName,
|
|
7778
|
+
keywords: [
|
|
7779
|
+
fill(T.indexHeading, { product: productName }),
|
|
7780
|
+
...groups.map((group) => group.name)
|
|
7781
|
+
].join(", "),
|
|
7782
|
+
url: canonical,
|
|
7783
|
+
structuredData
|
|
7784
|
+
}
|
|
7785
|
+
),
|
|
7786
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "border-b border-border bg-muted/30", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-6xl px-4 py-14 sm:px-6 sm:py-20 lg:px-8", children: [
|
|
7787
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold uppercase tracking-[0.2em] text-primary", children: T.answers }),
|
|
7788
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-3 max-w-3xl text-4xl font-bold tracking-tight text-foreground sm:text-5xl", children: heading }),
|
|
7789
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 max-w-2xl text-lg leading-relaxed text-muted-foreground", children: lead }),
|
|
7790
|
+
hasAnswers ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-6 text-sm text-muted-foreground", children: [
|
|
7791
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { className: "text-lg font-semibold text-foreground", children: ordered.length }),
|
|
7792
|
+
" ",
|
|
7793
|
+
questionCount(T, ordered.length)
|
|
7794
|
+
] }) : null,
|
|
7795
|
+
cta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 flex flex-wrap gap-3", children: cta }) : null
|
|
7796
|
+
] }) }),
|
|
7797
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-6xl px-4 pb-20 sm:px-6 lg:px-8", children: hasAnswers ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7798
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7799
|
+
"div",
|
|
7800
|
+
{
|
|
7801
|
+
role: "search",
|
|
7802
|
+
"data-answers": "filter",
|
|
7803
|
+
className: "flex flex-col gap-4 py-8",
|
|
7804
|
+
children: [
|
|
7805
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full max-w-md", children: [
|
|
7806
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7807
|
+
lucideReact.Search,
|
|
7808
|
+
{
|
|
7809
|
+
"aria-hidden": "true",
|
|
7810
|
+
className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"
|
|
7811
|
+
}
|
|
7812
|
+
),
|
|
7813
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: searchId, className: "sr-only", children: T.searchLabel }),
|
|
7814
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7815
|
+
"input",
|
|
7816
|
+
{
|
|
7817
|
+
id: searchId,
|
|
7818
|
+
type: "search",
|
|
7819
|
+
value: query,
|
|
7820
|
+
onChange: (event) => setQuery(event.target.value),
|
|
7821
|
+
placeholder: T.searchPlaceholder,
|
|
7822
|
+
autoComplete: "off",
|
|
7823
|
+
className: "h-10 w-full rounded-lg border border-border bg-background pl-9 pr-3 text-sm text-foreground shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7824
|
+
}
|
|
7825
|
+
)
|
|
7826
|
+
] }),
|
|
7827
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7828
|
+
"div",
|
|
7829
|
+
{
|
|
7830
|
+
role: "group",
|
|
7831
|
+
"aria-label": T.filterByTopic,
|
|
7832
|
+
className: "flex flex-wrap gap-2",
|
|
7833
|
+
children: [
|
|
7834
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7835
|
+
FilterChip2,
|
|
7836
|
+
{
|
|
7837
|
+
label: T.allTopics,
|
|
7838
|
+
topic: "all",
|
|
7839
|
+
count: searched.length,
|
|
7840
|
+
active: activeTopic === null,
|
|
7841
|
+
onSelect: () => setActiveTopic(null)
|
|
7842
|
+
}
|
|
7843
|
+
),
|
|
7844
|
+
groups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7845
|
+
FilterChip2,
|
|
7846
|
+
{
|
|
7847
|
+
label: group.name,
|
|
7848
|
+
topic: group.name,
|
|
7849
|
+
count: countsByTopic.get(group.name) ?? 0,
|
|
7850
|
+
active: activeTopic === group.name,
|
|
7851
|
+
onSelect: () => setActiveTopic(
|
|
7852
|
+
(current) => current === group.name ? null : group.name
|
|
7853
|
+
)
|
|
7854
|
+
},
|
|
7855
|
+
group.anchor
|
|
7856
|
+
))
|
|
7857
|
+
]
|
|
7858
|
+
}
|
|
7859
|
+
),
|
|
7860
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7861
|
+
"p",
|
|
7862
|
+
{
|
|
7863
|
+
"aria-live": "polite",
|
|
7864
|
+
className: filtering ? "text-sm text-muted-foreground" : "sr-only",
|
|
7865
|
+
children: fill(T.showingCount, {
|
|
7866
|
+
shown: String(visibleTotal),
|
|
7867
|
+
total: String(ordered.length)
|
|
7868
|
+
})
|
|
7869
|
+
}
|
|
7870
|
+
)
|
|
7871
|
+
]
|
|
7872
|
+
}
|
|
7873
|
+
),
|
|
7874
|
+
visibleTotal === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7875
|
+
"div",
|
|
7876
|
+
{
|
|
7877
|
+
"data-answers": "empty",
|
|
7878
|
+
className: "rounded-2xl border border-dashed border-border bg-muted/30 px-6 py-14 text-center",
|
|
7879
|
+
children: [
|
|
7880
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7881
|
+
lucideReact.Search,
|
|
7882
|
+
{
|
|
7883
|
+
"aria-hidden": "true",
|
|
7884
|
+
className: "mx-auto h-8 w-8 text-muted-foreground"
|
|
7885
|
+
}
|
|
7886
|
+
),
|
|
7887
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mt-4 text-lg font-semibold text-foreground", children: T.noMatchesTitle }),
|
|
7888
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: T.noMatchesBody }),
|
|
7889
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7890
|
+
"button",
|
|
7891
|
+
{
|
|
7892
|
+
type: "button",
|
|
7893
|
+
onClick: clearFilters,
|
|
7894
|
+
className: "mt-6 inline-flex items-center rounded-full border border-border bg-card px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7895
|
+
children: T.clearFilters
|
|
7896
|
+
}
|
|
7897
|
+
)
|
|
7898
|
+
]
|
|
7899
|
+
}
|
|
7900
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-14", children: visibleGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-labelledby": group.anchor, children: [
|
|
7901
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl", children: [
|
|
7902
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7903
|
+
"h2",
|
|
7904
|
+
{
|
|
7905
|
+
id: group.anchor,
|
|
7906
|
+
className: "scroll-mt-24 text-2xl font-semibold tracking-tight text-foreground",
|
|
7907
|
+
children: group.name
|
|
7908
|
+
}
|
|
7909
|
+
),
|
|
7910
|
+
group.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 leading-relaxed text-muted-foreground", children: group.description }) : null
|
|
7911
|
+
] }),
|
|
7912
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7913
|
+
"ul",
|
|
7914
|
+
{
|
|
7915
|
+
role: "list",
|
|
7916
|
+
className: "mt-6 grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3",
|
|
7917
|
+
children: group.answers.map((answer) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7918
|
+
"li",
|
|
7919
|
+
{
|
|
7920
|
+
"data-answers": "card",
|
|
7921
|
+
"data-slug": answer.slug,
|
|
7922
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AnswerCard, { answer, strings: T, Link })
|
|
7923
|
+
},
|
|
7924
|
+
answer.slug
|
|
7925
|
+
))
|
|
7926
|
+
}
|
|
7927
|
+
)
|
|
7928
|
+
] }, group.anchor)) })
|
|
7929
|
+
] }) : (
|
|
7930
|
+
// Nothing published yet: no filter bar with an "All 0" chip, and no empty state
|
|
7931
|
+
// that blames filters the visitor never set.
|
|
7932
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7933
|
+
"div",
|
|
7934
|
+
{
|
|
7935
|
+
"data-answers": "none",
|
|
7936
|
+
className: "mt-10 rounded-2xl border border-dashed border-border bg-muted/30 px-6 py-14 text-center",
|
|
7937
|
+
children: [
|
|
7938
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7939
|
+
lucideReact.Sparkles,
|
|
7940
|
+
{
|
|
7941
|
+
"aria-hidden": "true",
|
|
7942
|
+
className: "mx-auto h-8 w-8 text-muted-foreground"
|
|
7943
|
+
}
|
|
7944
|
+
),
|
|
7945
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mt-4 text-lg font-semibold text-foreground", children: T.noneYetTitle }),
|
|
7946
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: fill(T.noneYetBody, { product: productName }) })
|
|
7947
|
+
]
|
|
7948
|
+
}
|
|
7949
|
+
)
|
|
7950
|
+
) })
|
|
7951
|
+
]
|
|
7952
|
+
}
|
|
7953
|
+
);
|
|
7954
|
+
}
|
|
7955
|
+
var SECTION_HEADING2 = "scroll-mt-24 text-2xl font-semibold tracking-tight text-foreground";
|
|
7956
|
+
var CHIP2 = "inline-flex items-center rounded-full border border-border bg-muted/50 px-3 py-1 text-sm text-foreground";
|
|
7957
|
+
function ProvenanceNote({
|
|
7958
|
+
strings: T,
|
|
7959
|
+
date,
|
|
7960
|
+
className
|
|
7961
|
+
}) {
|
|
7962
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7963
|
+
"div",
|
|
7964
|
+
{
|
|
7965
|
+
role: "note",
|
|
7966
|
+
"aria-label": T.aboutTitle,
|
|
7967
|
+
"data-answers": "provenance",
|
|
7968
|
+
className: cn(
|
|
7969
|
+
"flex items-start gap-3 rounded-xl border border-primary/30 bg-primary/10 px-4 py-3 text-sm leading-relaxed text-foreground",
|
|
7970
|
+
className
|
|
7971
|
+
),
|
|
7972
|
+
children: [
|
|
7973
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7974
|
+
lucideReact.Info,
|
|
7975
|
+
{
|
|
7976
|
+
"aria-hidden": "true",
|
|
7977
|
+
className: "mt-0.5 h-4 w-4 shrink-0 text-primary"
|
|
7978
|
+
}
|
|
7979
|
+
),
|
|
7980
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
7981
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: T.aboutTitle }),
|
|
7982
|
+
" \u2014 ",
|
|
7983
|
+
fill(T.aboutBody, { date })
|
|
7984
|
+
] })
|
|
7985
|
+
]
|
|
7986
|
+
}
|
|
7987
|
+
);
|
|
7988
|
+
}
|
|
7989
|
+
function SourceLink({
|
|
7990
|
+
source,
|
|
7991
|
+
strings: T
|
|
7992
|
+
}) {
|
|
7993
|
+
const host = answerSourceHost(source.url);
|
|
7994
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7995
|
+
"a",
|
|
7996
|
+
{
|
|
7997
|
+
"data-answers": "source",
|
|
7998
|
+
href: source.url,
|
|
7999
|
+
target: "_blank",
|
|
8000
|
+
rel: "noopener noreferrer",
|
|
8001
|
+
className: "group flex h-full flex-col gap-1.5 rounded-xl border border-border bg-card p-4 text-card-foreground transition-colors hover:border-primary/40 hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8002
|
+
children: [
|
|
8003
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold leading-snug transition-colors group-hover:text-primary", children: source.title || host || source.url }),
|
|
8004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "mt-auto flex items-center gap-2 pt-1 text-xs text-muted-foreground", children: [
|
|
8005
|
+
source.product ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-secondary px-2 py-0.5 font-medium text-secondary-foreground", children: source.product }) : null,
|
|
8006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 items-center gap-1", children: [
|
|
8007
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { "aria-hidden": "true", className: "h-3 w-3 shrink-0" }),
|
|
8008
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: host })
|
|
8009
|
+
] })
|
|
8010
|
+
] }),
|
|
8011
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
|
|
8012
|
+
"(",
|
|
8013
|
+
T.opensInNewTab,
|
|
8014
|
+
")"
|
|
8015
|
+
] })
|
|
8016
|
+
]
|
|
8017
|
+
}
|
|
8018
|
+
);
|
|
8019
|
+
}
|
|
8020
|
+
function AnswerDetailPage(props) {
|
|
8021
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnswerDetail, { ...props }, props.answer.slug);
|
|
8022
|
+
}
|
|
8023
|
+
function AnswerDetail({
|
|
8024
|
+
productName,
|
|
8025
|
+
siteUrl,
|
|
8026
|
+
answer,
|
|
8027
|
+
answers,
|
|
8028
|
+
topics,
|
|
8029
|
+
imageOrigins,
|
|
8030
|
+
askHref = "/explore",
|
|
8031
|
+
cta,
|
|
8032
|
+
linkComponent,
|
|
8033
|
+
locale,
|
|
8034
|
+
className
|
|
8035
|
+
}) {
|
|
8036
|
+
const Link = linkComponent ?? DefaultAnswerLink;
|
|
8037
|
+
const base = normaliseSiteUrl2(siteUrl);
|
|
8038
|
+
const headingId = React.useId();
|
|
8039
|
+
const activeLocale = React.useMemo(() => resolveExploreLocale(locale), [locale]);
|
|
8040
|
+
const T = React.useMemo(() => answerStrings(activeLocale), [activeLocale]);
|
|
8041
|
+
const rtl = isRtlLocale(activeLocale);
|
|
8042
|
+
const dateLabel = React.useMemo(
|
|
8043
|
+
() => formatAnswerDate(answer.answeredAt, activeLocale),
|
|
8044
|
+
[answer.answeredAt, activeLocale]
|
|
8045
|
+
);
|
|
8046
|
+
const ordered = React.useMemo(() => sortByOrder2(answers), [answers]);
|
|
8047
|
+
const position = ordered.findIndex((item) => item.slug === answer.slug);
|
|
8048
|
+
const previous = position > 0 ? ordered[position - 1] : void 0;
|
|
8049
|
+
const next = position >= 0 && position < ordered.length - 1 ? ordered[position + 1] : void 0;
|
|
8050
|
+
const related = React.useMemo(() => {
|
|
8051
|
+
const bySlug = new Map(ordered.map((item) => [item.slug, item]));
|
|
8052
|
+
const curated = [...new Set(answer.related)].map((slug) => bySlug.get(slug)).filter(
|
|
8053
|
+
(item) => item !== void 0 && item.slug !== answer.slug
|
|
8054
|
+
);
|
|
8055
|
+
const list = curated.length > 0 ? curated : ordered.filter(
|
|
8056
|
+
(item) => item.topic === answer.topic && item.slug !== answer.slug
|
|
8057
|
+
);
|
|
8058
|
+
return list.slice(0, RELATED_LIMIT2);
|
|
8059
|
+
}, [answer, ordered]);
|
|
8060
|
+
const relatedIsCurated = answer.related.some(
|
|
8061
|
+
(slug) => related.some((item) => item.slug === slug)
|
|
8062
|
+
);
|
|
8063
|
+
const topicDescription = topics?.find(
|
|
8064
|
+
(topic) => topic.name === answer.topic
|
|
8065
|
+
)?.description;
|
|
8066
|
+
const sources = React.useMemo(
|
|
8067
|
+
() => publishableSources(answer.sources),
|
|
8068
|
+
[answer.sources]
|
|
8069
|
+
);
|
|
8070
|
+
const answerImageOrigins = React.useMemo(
|
|
8071
|
+
() => inlineImageOrigins([
|
|
8072
|
+
{ website: base },
|
|
8073
|
+
...sources.map((source) => ({ website: source.url })),
|
|
8074
|
+
...(imageOrigins ?? []).map((origin) => ({ website: origin }))
|
|
8075
|
+
]),
|
|
8076
|
+
[base, sources, imageOrigins]
|
|
8077
|
+
);
|
|
8078
|
+
const canonical = absoluteUrl2(base, answerPath(answer.slug));
|
|
8079
|
+
const answerText = React.useMemo(
|
|
8080
|
+
() => answerSpeechText(answer.answer),
|
|
8081
|
+
[answer.answer]
|
|
8082
|
+
);
|
|
8083
|
+
const structuredData = React.useMemo(
|
|
8084
|
+
() => [
|
|
8085
|
+
{
|
|
8086
|
+
"@context": "https://schema.org",
|
|
8087
|
+
"@type": "FAQPage",
|
|
8088
|
+
name: answer.question,
|
|
8089
|
+
description: answer.metaDescription,
|
|
8090
|
+
url: canonical,
|
|
8091
|
+
inLanguage: "en",
|
|
8092
|
+
isPartOf: { "@type": "WebSite", name: productName, url: `${base}/` },
|
|
8093
|
+
mainEntity: {
|
|
8094
|
+
"@type": "Question",
|
|
8095
|
+
name: answer.question,
|
|
8096
|
+
text: answer.question,
|
|
8097
|
+
answerCount: 1,
|
|
8098
|
+
acceptedAnswer: {
|
|
8099
|
+
"@type": "Answer",
|
|
8100
|
+
text: answerText,
|
|
8101
|
+
url: canonical,
|
|
8102
|
+
dateCreated: answer.answeredAt,
|
|
8103
|
+
// The organisation published it. Naming a person would be the one outright
|
|
8104
|
+
// false claim these pages could make.
|
|
8105
|
+
author: { "@type": "Organization", name: productName },
|
|
8106
|
+
...sources.length > 0 ? {
|
|
8107
|
+
citation: sources.map((source) => ({
|
|
8108
|
+
"@type": "WebPage",
|
|
8109
|
+
name: source.title,
|
|
8110
|
+
url: source.url
|
|
8111
|
+
}))
|
|
8112
|
+
} : {}
|
|
8113
|
+
}
|
|
8114
|
+
}
|
|
8115
|
+
},
|
|
8116
|
+
{
|
|
8117
|
+
"@context": "https://schema.org",
|
|
8118
|
+
"@type": "BreadcrumbList",
|
|
8119
|
+
itemListElement: [
|
|
8120
|
+
{
|
|
8121
|
+
"@type": "ListItem",
|
|
8122
|
+
position: 1,
|
|
8123
|
+
name: T.breadcrumbHome,
|
|
8124
|
+
item: `${base}/`
|
|
8125
|
+
},
|
|
8126
|
+
{
|
|
8127
|
+
"@type": "ListItem",
|
|
8128
|
+
position: 2,
|
|
8129
|
+
name: T.answers,
|
|
8130
|
+
item: `${base}${ANSWERS_PATH}`
|
|
8131
|
+
},
|
|
8132
|
+
{
|
|
8133
|
+
"@type": "ListItem",
|
|
8134
|
+
position: 3,
|
|
8135
|
+
name: answer.question,
|
|
8136
|
+
item: canonical
|
|
8137
|
+
}
|
|
8138
|
+
]
|
|
8139
|
+
}
|
|
8140
|
+
],
|
|
8141
|
+
[answer, answerText, base, canonical, productName, sources, T]
|
|
8142
|
+
);
|
|
8143
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8144
|
+
"article",
|
|
8145
|
+
{
|
|
8146
|
+
"data-answers": "detail",
|
|
8147
|
+
"data-slug": answer.slug,
|
|
8148
|
+
"data-locale": activeLocale,
|
|
8149
|
+
"aria-labelledby": headingId,
|
|
8150
|
+
dir: rtl ? "rtl" : void 0,
|
|
8151
|
+
className: cn("bg-background text-foreground", className),
|
|
8152
|
+
children: [
|
|
8153
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8154
|
+
PageHead,
|
|
8155
|
+
{
|
|
8156
|
+
title: clampText2(answer.question, TITLE_LIMIT),
|
|
8157
|
+
description: answer.metaDescription,
|
|
8158
|
+
productName,
|
|
8159
|
+
keywords: answer.keywords.join(", "),
|
|
8160
|
+
url: canonical,
|
|
8161
|
+
structuredData
|
|
8162
|
+
}
|
|
8163
|
+
),
|
|
8164
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProseStyles, {}),
|
|
8165
|
+
/* @__PURE__ */ jsxRuntime.jsx(ExploreAnswerStyles, {}),
|
|
8166
|
+
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "border-b border-border bg-muted/30", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-4xl px-4 pb-10 pt-8 sm:px-6 lg:px-8", children: [
|
|
8167
|
+
/* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground", children: [
|
|
8168
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "inline-flex items-center gap-1.5", children: [
|
|
8169
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8170
|
+
Link,
|
|
8171
|
+
{
|
|
8172
|
+
href: "/",
|
|
8173
|
+
className: "rounded hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8174
|
+
children: T.breadcrumbHome
|
|
8175
|
+
}
|
|
8176
|
+
),
|
|
8177
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
|
|
8178
|
+
] }),
|
|
8179
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "inline-flex items-center gap-1.5", children: [
|
|
8180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8181
|
+
Link,
|
|
8182
|
+
{
|
|
8183
|
+
href: ANSWERS_PATH,
|
|
8184
|
+
className: "rounded hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8185
|
+
children: T.answers
|
|
8186
|
+
}
|
|
8187
|
+
),
|
|
8188
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
|
|
8189
|
+
] }),
|
|
8190
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8191
|
+
"li",
|
|
8192
|
+
{
|
|
8193
|
+
"aria-current": "page",
|
|
8194
|
+
...ENGLISH_TEXT,
|
|
8195
|
+
className: "min-w-0 truncate text-foreground",
|
|
8196
|
+
children: answer.question
|
|
8197
|
+
}
|
|
8198
|
+
)
|
|
8199
|
+
] }) }),
|
|
8200
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 flex flex-wrap items-center gap-2", children: [
|
|
8201
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8202
|
+
"span",
|
|
8203
|
+
{
|
|
8204
|
+
"data-answers": "topic",
|
|
8205
|
+
title: topicDescription,
|
|
8206
|
+
className: "inline-flex items-center rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs font-semibold text-primary",
|
|
8207
|
+
children: answer.topic
|
|
8208
|
+
}
|
|
8209
|
+
),
|
|
8210
|
+
dateLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center rounded-full border border-border bg-background px-3 py-1 text-xs font-medium text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime: answer.answeredAt, children: fill(T.answeredOn, { date: dateLabel }) }) }) : null
|
|
8211
|
+
] }),
|
|
8212
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8213
|
+
"h1",
|
|
8214
|
+
{
|
|
8215
|
+
id: headingId,
|
|
8216
|
+
...ENGLISH_TEXT,
|
|
8217
|
+
className: "mt-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl",
|
|
8218
|
+
children: answer.question
|
|
8219
|
+
}
|
|
8220
|
+
),
|
|
8221
|
+
answer.summary ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8222
|
+
"p",
|
|
8223
|
+
{
|
|
8224
|
+
...ENGLISH_TEXT,
|
|
8225
|
+
className: "mt-4 text-lg leading-relaxed text-muted-foreground",
|
|
8226
|
+
children: answer.summary
|
|
8227
|
+
}
|
|
8228
|
+
) : null,
|
|
8229
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProvenanceNote, { strings: T, date: dateLabel, className: "mt-6" })
|
|
8230
|
+
] }) }),
|
|
8231
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-4xl px-4 py-12 sm:px-6 lg:px-8", children: [
|
|
8232
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-labelledby": `${headingId}-answer`, children: [
|
|
8233
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: `${headingId}-answer`, className: SECTION_HEADING2, children: T.answerHeading }),
|
|
8234
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-answers": "body", ...ENGLISH_TEXT, dir: "ltr", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8235
|
+
ExploreAnswerBody,
|
|
8236
|
+
{
|
|
8237
|
+
strings: T,
|
|
8238
|
+
imageOrigins: answerImageOrigins,
|
|
8239
|
+
components: ANSWER_HEADING_SHIFT,
|
|
8240
|
+
className: "mt-4",
|
|
8241
|
+
children: answer.answer
|
|
8242
|
+
}
|
|
8243
|
+
) })
|
|
8244
|
+
] }),
|
|
8245
|
+
sources.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8246
|
+
"section",
|
|
8247
|
+
{
|
|
8248
|
+
"aria-labelledby": `${headingId}-sources`,
|
|
8249
|
+
"data-answers": "sources",
|
|
8250
|
+
className: "mt-14",
|
|
8251
|
+
children: [
|
|
8252
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: `${headingId}-sources`, className: SECTION_HEADING2, children: T.sourcesHeading }),
|
|
8253
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-muted-foreground", children: T.sourcesLead }),
|
|
8254
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8255
|
+
"ul",
|
|
8256
|
+
{
|
|
8257
|
+
role: "list",
|
|
8258
|
+
className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
8259
|
+
children: sources.map((source) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(SourceLink, { source, strings: T }) }, source.url))
|
|
8260
|
+
}
|
|
8261
|
+
)
|
|
8262
|
+
]
|
|
8263
|
+
}
|
|
8264
|
+
) : null,
|
|
8265
|
+
answer.keywords.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-labelledby": `${headingId}-topics`, className: "mt-14", children: [
|
|
8266
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: `${headingId}-topics`, className: SECTION_HEADING2, children: T.topicsHeading }),
|
|
8267
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "mt-4 flex flex-wrap gap-2", children: answer.keywords.map((keyword, index) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: CHIP2, children: keyword }, copyKey2(index, keyword))) })
|
|
8268
|
+
] }) : null,
|
|
8269
|
+
related.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8270
|
+
"section",
|
|
8271
|
+
{
|
|
8272
|
+
"aria-labelledby": `${headingId}-related`,
|
|
8273
|
+
"data-answers": "related",
|
|
8274
|
+
className: "mt-14",
|
|
8275
|
+
children: [
|
|
8276
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: `${headingId}-related`, className: SECTION_HEADING2, children: relatedIsCurated ? T.relatedHeading : fill(T.moreInTopic, { topic: answer.topic }) }),
|
|
8277
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8278
|
+
"ul",
|
|
8279
|
+
{
|
|
8280
|
+
role: "list",
|
|
8281
|
+
className: "mt-6 grid grid-cols-1 gap-5 sm:grid-cols-2",
|
|
8282
|
+
children: related.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { "data-answers": "card", "data-slug": item.slug, children: /* @__PURE__ */ jsxRuntime.jsx(AnswerCard, { answer: item, strings: T, Link }) }, item.slug))
|
|
8283
|
+
}
|
|
8284
|
+
)
|
|
8285
|
+
]
|
|
8286
|
+
}
|
|
8287
|
+
) : null,
|
|
8288
|
+
previous || next ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8289
|
+
"nav",
|
|
8290
|
+
{
|
|
8291
|
+
"aria-label": `${T.previousQuestion} / ${T.nextQuestion}`,
|
|
8292
|
+
"data-answers": "pager",
|
|
8293
|
+
className: "mt-14 grid gap-4 sm:grid-cols-2",
|
|
8294
|
+
children: [
|
|
8295
|
+
previous ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8296
|
+
Link,
|
|
8297
|
+
{
|
|
8298
|
+
href: answerPath(previous.slug),
|
|
8299
|
+
className: "group flex items-center gap-3 rounded-2xl border border-border bg-card p-4 text-card-foreground transition-colors hover:border-primary/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8300
|
+
children: [
|
|
8301
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8302
|
+
lucideReact.ArrowLeft,
|
|
8303
|
+
{
|
|
8304
|
+
"aria-hidden": "true",
|
|
8305
|
+
className: "h-5 w-5 shrink-0 text-muted-foreground transition-colors group-hover:text-primary"
|
|
8306
|
+
}
|
|
8307
|
+
),
|
|
8308
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
|
|
8309
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs font-medium uppercase tracking-wide text-muted-foreground", children: T.previousQuestion }),
|
|
8310
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8311
|
+
"span",
|
|
8312
|
+
{
|
|
8313
|
+
...ENGLISH_TEXT,
|
|
8314
|
+
className: "block truncate font-semibold",
|
|
8315
|
+
children: previous.question
|
|
8316
|
+
}
|
|
8317
|
+
)
|
|
8318
|
+
] })
|
|
8319
|
+
]
|
|
8320
|
+
}
|
|
8321
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:block" }),
|
|
8322
|
+
next ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8323
|
+
Link,
|
|
8324
|
+
{
|
|
8325
|
+
href: answerPath(next.slug),
|
|
8326
|
+
className: "group flex items-center justify-end gap-3 rounded-2xl border border-border bg-card p-4 text-right text-card-foreground transition-colors hover:border-primary/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8327
|
+
children: [
|
|
8328
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
|
|
8329
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs font-medium uppercase tracking-wide text-muted-foreground", children: T.nextQuestion }),
|
|
8330
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8331
|
+
"span",
|
|
8332
|
+
{
|
|
8333
|
+
...ENGLISH_TEXT,
|
|
8334
|
+
className: "block truncate font-semibold",
|
|
8335
|
+
children: next.question
|
|
8336
|
+
}
|
|
8337
|
+
)
|
|
8338
|
+
] }),
|
|
8339
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8340
|
+
lucideReact.ArrowRight,
|
|
8341
|
+
{
|
|
8342
|
+
"aria-hidden": "true",
|
|
8343
|
+
className: "h-5 w-5 shrink-0 text-muted-foreground transition-colors group-hover:text-primary"
|
|
8344
|
+
}
|
|
8345
|
+
)
|
|
8346
|
+
]
|
|
8347
|
+
}
|
|
8348
|
+
) : null
|
|
8349
|
+
]
|
|
8350
|
+
}
|
|
8351
|
+
) : null,
|
|
8352
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-10 flex flex-wrap items-center gap-x-6 gap-y-3", children: [
|
|
8353
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8354
|
+
Link,
|
|
8355
|
+
{
|
|
8356
|
+
href: ANSWERS_PATH,
|
|
8357
|
+
className: "inline-flex items-center gap-2 rounded text-sm font-medium text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8358
|
+
children: [
|
|
8359
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": "true", className: "h-4 w-4" }),
|
|
8360
|
+
fill(T.allAnswers, { product: productName })
|
|
8361
|
+
]
|
|
8362
|
+
}
|
|
8363
|
+
),
|
|
8364
|
+
askHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8365
|
+
Link,
|
|
8366
|
+
{
|
|
8367
|
+
href: askHref,
|
|
8368
|
+
className: "inline-flex items-center gap-2 rounded text-sm font-medium text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8369
|
+
children: [
|
|
8370
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { "aria-hidden": "true", className: "h-4 w-4" }),
|
|
8371
|
+
T.askYourOwn
|
|
8372
|
+
]
|
|
8373
|
+
}
|
|
8374
|
+
) : null
|
|
8375
|
+
] })
|
|
8376
|
+
] }),
|
|
8377
|
+
cta ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8378
|
+
"section",
|
|
8379
|
+
{
|
|
8380
|
+
"data-answers": "cta",
|
|
8381
|
+
className: "border-t border-border bg-muted/30",
|
|
8382
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto flex max-w-4xl flex-wrap items-center gap-4 px-4 py-12 sm:px-6 lg:px-8", children: cta })
|
|
8383
|
+
}
|
|
8384
|
+
) : null
|
|
8385
|
+
]
|
|
8386
|
+
}
|
|
8387
|
+
);
|
|
8388
|
+
}
|
|
8389
|
+
|
|
8390
|
+
// src/components/explore-types.ts
|
|
8391
|
+
var EXPLORE_FEEDBACK_REASONS = [
|
|
8392
|
+
"INACCURATE",
|
|
8393
|
+
"INCOMPLETE",
|
|
8394
|
+
"OFF_TOPIC",
|
|
8395
|
+
"HARD_TO_FOLLOW",
|
|
8396
|
+
"OTHER"
|
|
8397
|
+
];
|
|
8398
|
+
var EXPLORE_MESSAGE_FIELDS = (
|
|
8399
|
+
/* GraphQL */
|
|
8400
|
+
`
|
|
8401
|
+
id
|
|
8402
|
+
conversationId
|
|
8403
|
+
role
|
|
8404
|
+
status
|
|
8405
|
+
content
|
|
8406
|
+
partialContent
|
|
8407
|
+
activity
|
|
8408
|
+
references {
|
|
8409
|
+
url
|
|
8410
|
+
title
|
|
8411
|
+
description
|
|
8412
|
+
product
|
|
8413
|
+
imageUrl
|
|
8414
|
+
index
|
|
8415
|
+
}
|
|
8416
|
+
ctas {
|
|
8417
|
+
kind
|
|
8418
|
+
label
|
|
8419
|
+
url
|
|
8420
|
+
product
|
|
8421
|
+
}
|
|
8422
|
+
followUps
|
|
8423
|
+
answered
|
|
8424
|
+
attachments {
|
|
8425
|
+
name
|
|
8426
|
+
mimeType
|
|
8427
|
+
size
|
|
8428
|
+
textExtracted
|
|
8429
|
+
}
|
|
8430
|
+
errorCode
|
|
8431
|
+
createdAt
|
|
8432
|
+
completedAt
|
|
8433
|
+
`
|
|
8434
|
+
);
|
|
8435
|
+
var EXPLORE_OWN_MESSAGE_FIELDS = (
|
|
8436
|
+
/* GraphQL */
|
|
8437
|
+
`
|
|
8438
|
+
${EXPLORE_MESSAGE_FIELDS}
|
|
8439
|
+
feedback {
|
|
8440
|
+
rating
|
|
8441
|
+
reason
|
|
8442
|
+
comment
|
|
8443
|
+
createdAt
|
|
8444
|
+
}
|
|
8445
|
+
`
|
|
8446
|
+
);
|
|
8447
|
+
var EXPLORE_CATALOG_ESTABLISHED_FIELDS = (
|
|
8448
|
+
/* GraphQL */
|
|
8449
|
+
`
|
|
8450
|
+
enabled
|
|
8451
|
+
products {
|
|
8452
|
+
slug
|
|
8453
|
+
name
|
|
8454
|
+
tagline
|
|
8455
|
+
website
|
|
8456
|
+
}
|
|
8457
|
+
examplePrompts
|
|
8458
|
+
welcomeTitle
|
|
8459
|
+
welcomeBody
|
|
8460
|
+
limits {
|
|
8461
|
+
maxMessageLength
|
|
8462
|
+
maxTurnsPerConversation
|
|
8463
|
+
messagesPerDay
|
|
8464
|
+
historyTurns
|
|
8465
|
+
}
|
|
8466
|
+
captchaRequired
|
|
8467
|
+
recaptchaSiteKey`
|
|
8468
|
+
);
|
|
8469
|
+
var EXPLORE_CATALOG_HIGHLIGHT_FIELD = (
|
|
8470
|
+
/* GraphQL */
|
|
8471
|
+
`
|
|
8472
|
+
conceptHighlights {
|
|
8473
|
+
product
|
|
8474
|
+
productName
|
|
8475
|
+
title
|
|
8476
|
+
url
|
|
8477
|
+
imageUrl
|
|
8478
|
+
alt
|
|
8479
|
+
}`
|
|
8480
|
+
);
|
|
8481
|
+
function exploreCatalogDocument(extraFields) {
|
|
8482
|
+
return (
|
|
8483
|
+
/* GraphQL */
|
|
8484
|
+
`
|
|
8485
|
+
query ExploreCatalog($productSlug: String) {
|
|
8486
|
+
exploreCatalog(productSlug: $productSlug) {${EXPLORE_CATALOG_ESTABLISHED_FIELDS}${extraFields}
|
|
8487
|
+
}
|
|
8488
|
+
}
|
|
8489
|
+
`
|
|
8490
|
+
);
|
|
8491
|
+
}
|
|
8492
|
+
var EXPLORE_CATALOG_QUERY = exploreCatalogDocument(
|
|
8493
|
+
EXPLORE_CATALOG_HIGHLIGHT_FIELD
|
|
8494
|
+
);
|
|
8495
|
+
var EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS = exploreCatalogDocument("");
|
|
8496
|
+
var EXPLORE_MESSAGE_QUERY = (
|
|
8497
|
+
/* GraphQL */
|
|
8498
|
+
`
|
|
8499
|
+
query ExploreMessage($conversationToken: String!, $id: ID!) {
|
|
8500
|
+
exploreMessage(conversationToken: $conversationToken, id: $id) {
|
|
8501
|
+
${EXPLORE_OWN_MESSAGE_FIELDS}
|
|
8502
|
+
}
|
|
8503
|
+
}
|
|
8504
|
+
`
|
|
8505
|
+
);
|
|
8506
|
+
var SEND_EXPLORE_MESSAGE_MUTATION = (
|
|
8507
|
+
/* GraphQL */
|
|
8508
|
+
`
|
|
8509
|
+
mutation SendExploreMessage($input: SendExploreMessageInput!) {
|
|
8510
|
+
sendExploreMessage(input: $input) {
|
|
8511
|
+
conversation {
|
|
8512
|
+
id
|
|
8513
|
+
token
|
|
8514
|
+
productSlug
|
|
8515
|
+
turnCount
|
|
8516
|
+
createdAt
|
|
8517
|
+
}
|
|
8518
|
+
userMessage {
|
|
8519
|
+
${EXPLORE_OWN_MESSAGE_FIELDS}
|
|
8520
|
+
}
|
|
8521
|
+
assistantMessage {
|
|
8522
|
+
${EXPLORE_OWN_MESSAGE_FIELDS}
|
|
8523
|
+
}
|
|
8524
|
+
remainingToday
|
|
8525
|
+
}
|
|
8526
|
+
}
|
|
8527
|
+
`
|
|
8528
|
+
);
|
|
8529
|
+
var RECORD_EXPLORE_CLICK_MUTATION = (
|
|
8530
|
+
/* GraphQL */
|
|
8531
|
+
`
|
|
8532
|
+
mutation RecordExploreClick($input: RecordExploreClickInput!) {
|
|
8533
|
+
recordExploreClick(input: $input) {
|
|
8534
|
+
recorded
|
|
8535
|
+
}
|
|
8536
|
+
}
|
|
8537
|
+
`
|
|
8538
|
+
);
|
|
8539
|
+
var SUBMIT_EXPLORE_FEEDBACK_MUTATION = (
|
|
8540
|
+
/* GraphQL */
|
|
8541
|
+
`
|
|
8542
|
+
mutation SubmitExploreFeedback($input: SubmitExploreFeedbackInput!) {
|
|
8543
|
+
submitExploreFeedback(input: $input) {
|
|
8544
|
+
recorded
|
|
8545
|
+
feedback {
|
|
8546
|
+
rating
|
|
8547
|
+
reason
|
|
8548
|
+
comment
|
|
8549
|
+
createdAt
|
|
8550
|
+
}
|
|
8551
|
+
}
|
|
8552
|
+
}
|
|
8553
|
+
`
|
|
8554
|
+
);
|
|
8555
|
+
var EXPLORE_FEEDBACK_COMMENT_SOFT_MAX = 500;
|
|
8556
|
+
var ESCALATE_EXPLORE_CONVERSATION_MUTATION = (
|
|
8557
|
+
/* GraphQL */
|
|
8558
|
+
`
|
|
8559
|
+
mutation EscalateExploreConversation(
|
|
8560
|
+
$input: EscalateExploreConversationInput!
|
|
8561
|
+
) {
|
|
8562
|
+
escalateExploreConversation(input: $input) {
|
|
8563
|
+
created
|
|
8564
|
+
escalation {
|
|
8565
|
+
email
|
|
8566
|
+
createdAt
|
|
8567
|
+
}
|
|
8568
|
+
}
|
|
8569
|
+
}
|
|
8570
|
+
`
|
|
8571
|
+
);
|
|
8572
|
+
var EXPLORE_ESCALATION_NOTE_SOFT_MAX = 2e3;
|
|
8573
|
+
var DELIVERABLE_EMAIL = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/;
|
|
8574
|
+
function looksLikeDeliverableEmail(value) {
|
|
8575
|
+
const trimmed = value.trim();
|
|
8576
|
+
if (trimmed.length === 0 || trimmed.length > 254) return false;
|
|
8577
|
+
return DELIVERABLE_EMAIL.test(trimmed);
|
|
8578
|
+
}
|
|
8579
|
+
var CREATE_EXPLORE_SHARE_LINK_MUTATION = (
|
|
8580
|
+
/* GraphQL */
|
|
8581
|
+
`
|
|
8582
|
+
mutation CreateExploreShareLink($conversationToken: String!) {
|
|
8583
|
+
createExploreShareLink(conversationToken: $conversationToken) {
|
|
8584
|
+
shareToken
|
|
8585
|
+
}
|
|
8586
|
+
}
|
|
8587
|
+
`
|
|
8588
|
+
);
|
|
8589
|
+
var EXPLORE_SHARED_CONVERSATION_QUERY = (
|
|
8590
|
+
/* GraphQL */
|
|
8591
|
+
`
|
|
8592
|
+
query ExploreSharedConversation($shareToken: String!) {
|
|
8593
|
+
exploreSharedConversation(shareToken: $shareToken) {
|
|
8594
|
+
${EXPLORE_MESSAGE_FIELDS}
|
|
8595
|
+
}
|
|
8596
|
+
}
|
|
8597
|
+
`
|
|
8598
|
+
);
|
|
6833
8599
|
|
|
6834
8600
|
// src/data/products.ts
|
|
6835
8601
|
var ECOSYSTEM_PRODUCTS = [
|
|
@@ -7176,6 +8942,25 @@ var VALIDATION_CODES = /* @__PURE__ */ new Set([
|
|
|
7176
8942
|
"CONVERSATION_LIMIT",
|
|
7177
8943
|
"INVALID_INPUT"
|
|
7178
8944
|
]);
|
|
8945
|
+
function escalateOutcomeForCode(code) {
|
|
8946
|
+
switch (code) {
|
|
8947
|
+
case "INVALID_EMAIL":
|
|
8948
|
+
return "invalid-email";
|
|
8949
|
+
case "RATE_LIMITED":
|
|
8950
|
+
case "HTTP_429":
|
|
8951
|
+
return "rate-limited";
|
|
8952
|
+
case "CAPTCHA_REQUIRED":
|
|
8953
|
+
case "CAPTCHA_FAILED":
|
|
8954
|
+
return "captcha";
|
|
8955
|
+
// The token owns nothing, or owns a different conversation. The server answers NOT_FOUND
|
|
8956
|
+
// rather than FORBIDDEN so the endpoint is not an oracle for whether a thread exists;
|
|
8957
|
+
// either way there is nothing this visitor can do about it, so it reads as a failure.
|
|
8958
|
+
case "NOT_FOUND":
|
|
8959
|
+
return "failed";
|
|
8960
|
+
default:
|
|
8961
|
+
return "failed";
|
|
8962
|
+
}
|
|
8963
|
+
}
|
|
7179
8964
|
function classifyExploreError(code, serverMessage) {
|
|
7180
8965
|
const c = code ?? "UNKNOWN";
|
|
7181
8966
|
if (RATE_LIMIT_CODES.has(c)) {
|
|
@@ -7342,6 +9127,7 @@ function useExploreChat(options = {}) {
|
|
|
7342
9127
|
onSend
|
|
7343
9128
|
} = options;
|
|
7344
9129
|
const client = useWebSDK();
|
|
9130
|
+
const { productId } = useWebSDKConfig();
|
|
7345
9131
|
const promptKey = JSON.stringify(examplePrompts ?? []);
|
|
7346
9132
|
const welcomeKey = JSON.stringify(fallbackWelcome ?? null);
|
|
7347
9133
|
const fallbackCatalog = React.useMemo(
|
|
@@ -7365,6 +9151,7 @@ function useExploreChat(options = {}) {
|
|
|
7365
9151
|
const pollGenerationRef = React.useRef(0);
|
|
7366
9152
|
const pollTimerRef = React.useRef(null);
|
|
7367
9153
|
const conversationTokenRef = React.useRef(null);
|
|
9154
|
+
const [hasConversation, setHasConversation] = React.useState(false);
|
|
7368
9155
|
const shareTokenRef = React.useRef(void 0);
|
|
7369
9156
|
if (shareTokenRef.current === void 0) {
|
|
7370
9157
|
shareTokenRef.current = readShareToken();
|
|
@@ -7379,6 +9166,10 @@ function useExploreChat(options = {}) {
|
|
|
7379
9166
|
);
|
|
7380
9167
|
const inFlightRef = React.useRef(false);
|
|
7381
9168
|
catalogRef.current = catalog;
|
|
9169
|
+
const rememberConversationToken = React.useCallback((token) => {
|
|
9170
|
+
conversationTokenRef.current = token;
|
|
9171
|
+
setHasConversation(token !== null);
|
|
9172
|
+
}, []);
|
|
7382
9173
|
const clearPollTimer = React.useCallback(() => {
|
|
7383
9174
|
if (pollTimerRef.current !== null) {
|
|
7384
9175
|
clearTimeout(pollTimerRef.current);
|
|
@@ -7445,7 +9236,7 @@ function useExploreChat(options = {}) {
|
|
|
7445
9236
|
setArchive(readArchive(storageKey));
|
|
7446
9237
|
const stored = readPersisted(storageKey);
|
|
7447
9238
|
if (stored) {
|
|
7448
|
-
|
|
9239
|
+
rememberConversationToken(stored.conversationToken);
|
|
7449
9240
|
focusProductRef.current = stored.focusProduct;
|
|
7450
9241
|
const settled = stored.messages.flatMap((m) => {
|
|
7451
9242
|
if (m.role !== "ASSISTANT") return [m];
|
|
@@ -7461,7 +9252,7 @@ function useExploreChat(options = {}) {
|
|
|
7461
9252
|
setTurnCount(turns);
|
|
7462
9253
|
}
|
|
7463
9254
|
setHydrated(true);
|
|
7464
|
-
}, [persist, storageKey]);
|
|
9255
|
+
}, [persist, rememberConversationToken, storageKey]);
|
|
7465
9256
|
React.useEffect(() => {
|
|
7466
9257
|
if (!persist || !hydrated || typeof window === "undefined") return;
|
|
7467
9258
|
try {
|
|
@@ -7654,7 +9445,7 @@ function useExploreChat(options = {}) {
|
|
|
7654
9445
|
setPhase(classified.kind === "rate-limit" ? "limited" : "error");
|
|
7655
9446
|
return;
|
|
7656
9447
|
}
|
|
7657
|
-
|
|
9448
|
+
rememberConversationToken(result.conversation.token);
|
|
7658
9449
|
turnCountRef.current = result.conversation.turnCount;
|
|
7659
9450
|
setTurnCount(result.conversation.turnCount);
|
|
7660
9451
|
setRemainingToday(result.remainingToday ?? null);
|
|
@@ -7680,7 +9471,14 @@ function useExploreChat(options = {}) {
|
|
|
7680
9471
|
setPhase("streaming");
|
|
7681
9472
|
startPolling(result.conversation.token, assistantMessage.id);
|
|
7682
9473
|
},
|
|
7683
|
-
[
|
|
9474
|
+
[
|
|
9475
|
+
client,
|
|
9476
|
+
locale,
|
|
9477
|
+
pageUrl,
|
|
9478
|
+
productSlug,
|
|
9479
|
+
rememberConversationToken,
|
|
9480
|
+
startPolling
|
|
9481
|
+
]
|
|
7684
9482
|
);
|
|
7685
9483
|
const send = React.useCallback(
|
|
7686
9484
|
async (message, attachments = []) => {
|
|
@@ -7797,7 +9595,7 @@ function useExploreChat(options = {}) {
|
|
|
7797
9595
|
);
|
|
7798
9596
|
cancelPolling();
|
|
7799
9597
|
inFlightRef.current = false;
|
|
7800
|
-
|
|
9598
|
+
rememberConversationToken(null);
|
|
7801
9599
|
lastSentTextRef.current = null;
|
|
7802
9600
|
lastSentAttachmentsRef.current = [];
|
|
7803
9601
|
turnCountRef.current = 0;
|
|
@@ -7812,7 +9610,7 @@ function useExploreChat(options = {}) {
|
|
|
7812
9610
|
} catch {
|
|
7813
9611
|
}
|
|
7814
9612
|
}
|
|
7815
|
-
}, [cancelPolling, storageKey]);
|
|
9613
|
+
}, [cancelPolling, rememberConversationToken, storageKey]);
|
|
7816
9614
|
const openConversation = React.useCallback(
|
|
7817
9615
|
(token) => {
|
|
7818
9616
|
const entry = readArchive(storageKey).find((e) => e.token === token);
|
|
@@ -7824,7 +9622,7 @@ function useExploreChat(options = {}) {
|
|
|
7824
9622
|
});
|
|
7825
9623
|
cancelPolling();
|
|
7826
9624
|
inFlightRef.current = false;
|
|
7827
|
-
|
|
9625
|
+
rememberConversationToken(entry.token);
|
|
7828
9626
|
turnCountRef.current = entry.messages.filter(
|
|
7829
9627
|
(m) => m.role === "USER"
|
|
7830
9628
|
).length;
|
|
@@ -7836,7 +9634,7 @@ function useExploreChat(options = {}) {
|
|
|
7836
9634
|
setPhase(catalogRef.current.enabled ? "ready" : "disabled");
|
|
7837
9635
|
setArchive(readArchive(storageKey));
|
|
7838
9636
|
},
|
|
7839
|
-
[cancelPolling, storageKey]
|
|
9637
|
+
[cancelPolling, rememberConversationToken, storageKey]
|
|
7840
9638
|
);
|
|
7841
9639
|
const deleteConversation = React.useCallback(
|
|
7842
9640
|
(token) => {
|
|
@@ -7925,6 +9723,69 @@ function useExploreChat(options = {}) {
|
|
|
7925
9723
|
},
|
|
7926
9724
|
[client]
|
|
7927
9725
|
);
|
|
9726
|
+
const escalate = React.useCallback(
|
|
9727
|
+
async (email, note) => {
|
|
9728
|
+
const token = conversationTokenRef.current;
|
|
9729
|
+
if (!token) {
|
|
9730
|
+
return { outcome: "no-conversation", email: null, createdAt: null };
|
|
9731
|
+
}
|
|
9732
|
+
const attempt = async (captchaAttempt) => {
|
|
9733
|
+
const activeCatalog = catalogRef.current;
|
|
9734
|
+
let recaptchaToken;
|
|
9735
|
+
if (activeCatalog.captchaRequired && activeCatalog.recaptchaSiteKey) {
|
|
9736
|
+
try {
|
|
9737
|
+
recaptchaToken = await getRecaptchaV3Token(
|
|
9738
|
+
activeCatalog.recaptchaSiteKey
|
|
9739
|
+
);
|
|
9740
|
+
} catch (err) {
|
|
9741
|
+
console.warn(
|
|
9742
|
+
"[WebSDK] reCAPTCHA v3 token could not be minted",
|
|
9743
|
+
err
|
|
9744
|
+
);
|
|
9745
|
+
}
|
|
9746
|
+
}
|
|
9747
|
+
const input = {
|
|
9748
|
+
conversationToken: token,
|
|
9749
|
+
email: email.trim(),
|
|
9750
|
+
note: note?.trim() ? note.trim() : null,
|
|
9751
|
+
...recaptchaToken ? { recaptchaToken } : {},
|
|
9752
|
+
...productId ? { productId } : {}
|
|
9753
|
+
};
|
|
9754
|
+
try {
|
|
9755
|
+
const res = await client.mutate(
|
|
9756
|
+
ESCALATE_EXPLORE_CONVERSATION_MUTATION,
|
|
9757
|
+
{ input }
|
|
9758
|
+
);
|
|
9759
|
+
const first = res?.errors?.[0];
|
|
9760
|
+
const result = res?.data?.escalateExploreConversation;
|
|
9761
|
+
if (first || !result) {
|
|
9762
|
+
const code = typeof first?.extensions?.code === "string" ? first.extensions.code : "ESCALATION_FAILED";
|
|
9763
|
+
if (code === "CAPTCHA_FAILED" && captchaAttempt === 0) {
|
|
9764
|
+
return attempt(1);
|
|
9765
|
+
}
|
|
9766
|
+
return {
|
|
9767
|
+
outcome: escalateOutcomeForCode(code),
|
|
9768
|
+
email: null,
|
|
9769
|
+
createdAt: null
|
|
9770
|
+
};
|
|
9771
|
+
}
|
|
9772
|
+
return {
|
|
9773
|
+
// `created: false` is the double-click, the retry, the reload. The handover
|
|
9774
|
+
// exists, so this is a success — and the address comes from the SERVER, because
|
|
9775
|
+
// on a repeat submit the reply goes to whatever the FIRST handover used.
|
|
9776
|
+
outcome: result.created ? "sent" : "already-handed-over",
|
|
9777
|
+
email: result.escalation?.email ?? null,
|
|
9778
|
+
createdAt: result.escalation?.createdAt ?? null
|
|
9779
|
+
};
|
|
9780
|
+
} catch {
|
|
9781
|
+
return { outcome: "failed", email: null, createdAt: null };
|
|
9782
|
+
}
|
|
9783
|
+
};
|
|
9784
|
+
return attempt(0);
|
|
9785
|
+
},
|
|
9786
|
+
[client, productId]
|
|
9787
|
+
);
|
|
9788
|
+
const canEscalate = hasConversation && !isSharedView;
|
|
7928
9789
|
return {
|
|
7929
9790
|
phase,
|
|
7930
9791
|
catalog,
|
|
@@ -7945,6 +9806,8 @@ function useExploreChat(options = {}) {
|
|
|
7945
9806
|
clearHistory,
|
|
7946
9807
|
recordClick,
|
|
7947
9808
|
submitFeedback,
|
|
9809
|
+
escalate,
|
|
9810
|
+
canEscalate,
|
|
7948
9811
|
createShareLink,
|
|
7949
9812
|
isSharedView
|
|
7950
9813
|
};
|
|
@@ -7954,6 +9817,224 @@ function makeOptimisticId() {
|
|
|
7954
9817
|
optimisticCounter += 1;
|
|
7955
9818
|
return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
|
|
7956
9819
|
}
|
|
9820
|
+
var DRAIN_TARGET_MS = 1200;
|
|
9821
|
+
var MIN_CHARS_PER_SECOND = 90;
|
|
9822
|
+
var MAX_CHARS_PER_SECOND = 2200;
|
|
9823
|
+
var MAX_STEP_MS = 250;
|
|
9824
|
+
var COMMIT_INTERVAL_MS = 45;
|
|
9825
|
+
var FALLBACK_STEP_MS = 50;
|
|
9826
|
+
var FENCE = /^ {0,3}(?:```|~~~)/;
|
|
9827
|
+
var TABLE_ROW = /^ {0,3}\|/;
|
|
9828
|
+
var EMPTY_BLOCK_MARKER = /^ {0,3}(?:[-+>]|#{1,6}|\d{1,9}[.)])\s*$/;
|
|
9829
|
+
function isWordCharacter(char) {
|
|
9830
|
+
return char !== void 0 && /[\p{L}\p{N}]/u.test(char);
|
|
9831
|
+
}
|
|
9832
|
+
function clamp(value, min, max) {
|
|
9833
|
+
return Math.min(Math.max(value, min), max);
|
|
9834
|
+
}
|
|
9835
|
+
function now() {
|
|
9836
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
9837
|
+
}
|
|
9838
|
+
function isHighSurrogate(code) {
|
|
9839
|
+
return code >= 55296 && code <= 56319;
|
|
9840
|
+
}
|
|
9841
|
+
function safeInlineEnd(line) {
|
|
9842
|
+
let codeSpan = null;
|
|
9843
|
+
let link = null;
|
|
9844
|
+
const emphasis = [];
|
|
9845
|
+
let at = 0;
|
|
9846
|
+
while (at < line.length) {
|
|
9847
|
+
const char = line[at] ?? "";
|
|
9848
|
+
if (char === "\\") {
|
|
9849
|
+
at += 2;
|
|
9850
|
+
continue;
|
|
9851
|
+
}
|
|
9852
|
+
if (char === "`") {
|
|
9853
|
+
let run = 1;
|
|
9854
|
+
while (line[at + run] === "`") run += 1;
|
|
9855
|
+
codeSpan = codeSpan === null ? at : null;
|
|
9856
|
+
at += run;
|
|
9857
|
+
continue;
|
|
9858
|
+
}
|
|
9859
|
+
if (codeSpan !== null) {
|
|
9860
|
+
at += 1;
|
|
9861
|
+
continue;
|
|
9862
|
+
}
|
|
9863
|
+
if (char === "[") {
|
|
9864
|
+
if (link === null) link = line[at - 1] === "!" ? at - 1 : at;
|
|
9865
|
+
at += 1;
|
|
9866
|
+
continue;
|
|
9867
|
+
}
|
|
9868
|
+
if (char === "]") {
|
|
9869
|
+
if (link !== null && line[at + 1] !== "(") link = null;
|
|
9870
|
+
at += 1;
|
|
9871
|
+
continue;
|
|
9872
|
+
}
|
|
9873
|
+
if (char === ")") {
|
|
9874
|
+
link = null;
|
|
9875
|
+
at += 1;
|
|
9876
|
+
continue;
|
|
9877
|
+
}
|
|
9878
|
+
if (char === "*" || char === "_" || char === "~") {
|
|
9879
|
+
let run = 1;
|
|
9880
|
+
while (line[at + run] === char) run += 1;
|
|
9881
|
+
const start = at;
|
|
9882
|
+
at += run;
|
|
9883
|
+
const before = line[start - 1];
|
|
9884
|
+
const after = line[start + run];
|
|
9885
|
+
if (run < 2) continue;
|
|
9886
|
+
if (char === "_" && isWordCharacter(before) && isWordCharacter(after)) {
|
|
9887
|
+
continue;
|
|
9888
|
+
}
|
|
9889
|
+
const marker = char.repeat(run);
|
|
9890
|
+
const open2 = emphasis.findIndex((entry) => entry.marker === marker);
|
|
9891
|
+
if (open2 !== -1) {
|
|
9892
|
+
emphasis.splice(open2, 1);
|
|
9893
|
+
continue;
|
|
9894
|
+
}
|
|
9895
|
+
if (after !== void 0 && /\s/.test(after)) continue;
|
|
9896
|
+
emphasis.push({ marker, start });
|
|
9897
|
+
continue;
|
|
9898
|
+
}
|
|
9899
|
+
at += 1;
|
|
9900
|
+
}
|
|
9901
|
+
const open = [codeSpan, link, emphasis[0]?.start ?? null].filter(
|
|
9902
|
+
(value) => value !== null
|
|
9903
|
+
);
|
|
9904
|
+
return open.length === 0 ? line.length : Math.min(...open);
|
|
9905
|
+
}
|
|
9906
|
+
function revealBoundary(text, limit) {
|
|
9907
|
+
if (limit <= 0) return 0;
|
|
9908
|
+
const caughtUp = limit >= text.length;
|
|
9909
|
+
const head = caughtUp ? text : text.slice(0, limit);
|
|
9910
|
+
const lineStart = head.lastIndexOf("\n") + 1;
|
|
9911
|
+
const line = head.slice(lineStart);
|
|
9912
|
+
let fenceStart = null;
|
|
9913
|
+
let tableStart = null;
|
|
9914
|
+
let tableRows = 0;
|
|
9915
|
+
let at = 0;
|
|
9916
|
+
while (at < lineStart) {
|
|
9917
|
+
const breakAt = head.indexOf("\n", at);
|
|
9918
|
+
const end = breakAt === -1 ? lineStart : breakAt;
|
|
9919
|
+
const row = head.slice(at, end);
|
|
9920
|
+
if (fenceStart !== null) {
|
|
9921
|
+
if (FENCE.test(row)) fenceStart = null;
|
|
9922
|
+
} else if (FENCE.test(row)) {
|
|
9923
|
+
fenceStart = at;
|
|
9924
|
+
} else if (TABLE_ROW.test(row)) {
|
|
9925
|
+
if (tableStart === null) {
|
|
9926
|
+
tableStart = at;
|
|
9927
|
+
tableRows = 0;
|
|
9928
|
+
}
|
|
9929
|
+
tableRows += 1;
|
|
9930
|
+
} else if (tableStart !== null) {
|
|
9931
|
+
tableStart = null;
|
|
9932
|
+
tableRows = 0;
|
|
9933
|
+
}
|
|
9934
|
+
at = end + 1;
|
|
9935
|
+
}
|
|
9936
|
+
if (fenceStart === null) {
|
|
9937
|
+
const lastIsRow = TABLE_ROW.test(line);
|
|
9938
|
+
if (lastIsRow && tableStart === null) {
|
|
9939
|
+
tableStart = lineStart;
|
|
9940
|
+
tableRows = 0;
|
|
9941
|
+
} else if (!lastIsRow && line !== "") {
|
|
9942
|
+
tableStart = null;
|
|
9943
|
+
tableRows = 0;
|
|
9944
|
+
}
|
|
9945
|
+
if (tableStart !== null && tableRows < 2) return tableStart;
|
|
9946
|
+
}
|
|
9947
|
+
if (caughtUp) return text.length;
|
|
9948
|
+
if (fenceStart !== null) return fenceStart;
|
|
9949
|
+
if (TABLE_ROW.test(line)) return lineStart;
|
|
9950
|
+
if (EMPTY_BLOCK_MARKER.test(line)) return lineStart;
|
|
9951
|
+
const cut = lineStart + safeInlineEnd(line);
|
|
9952
|
+
return isHighSurrogate(text.charCodeAt(cut - 1)) ? cut - 1 : cut;
|
|
9953
|
+
}
|
|
9954
|
+
function prefersReducedMotion() {
|
|
9955
|
+
if (typeof window === "undefined") return true;
|
|
9956
|
+
try {
|
|
9957
|
+
return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
9958
|
+
} catch {
|
|
9959
|
+
return false;
|
|
9960
|
+
}
|
|
9961
|
+
}
|
|
9962
|
+
function useProgressiveReveal(text, settled) {
|
|
9963
|
+
const [, setFrame] = React.useState(0);
|
|
9964
|
+
const [reduced] = React.useState(prefersReducedMotion);
|
|
9965
|
+
const immediate = settled || reduced;
|
|
9966
|
+
const textRef = React.useRef(text);
|
|
9967
|
+
const cursorRef = React.useRef(immediate ? text.length : 0);
|
|
9968
|
+
const cutRef = React.useRef(immediate ? text.length : 0);
|
|
9969
|
+
const committedRef = React.useRef(0);
|
|
9970
|
+
if (text !== textRef.current) {
|
|
9971
|
+
const revealed = textRef.current.slice(0, Math.floor(cursorRef.current));
|
|
9972
|
+
if (revealed !== "" && !text.startsWith(revealed)) {
|
|
9973
|
+
cursorRef.current = text.length;
|
|
9974
|
+
}
|
|
9975
|
+
cursorRef.current = Math.min(cursorRef.current, text.length);
|
|
9976
|
+
cutRef.current = Math.min(cutRef.current, text.length);
|
|
9977
|
+
textRef.current = text;
|
|
9978
|
+
}
|
|
9979
|
+
if (immediate) cursorRef.current = text.length;
|
|
9980
|
+
const cut = immediate ? text.length : Math.max(
|
|
9981
|
+
cutRef.current,
|
|
9982
|
+
revealBoundary(text, Math.floor(cursorRef.current))
|
|
9983
|
+
);
|
|
9984
|
+
cutRef.current = cut;
|
|
9985
|
+
React.useEffect(() => {
|
|
9986
|
+
if (immediate) return;
|
|
9987
|
+
if (cursorRef.current >= text.length) return;
|
|
9988
|
+
let cancelled = false;
|
|
9989
|
+
let cancelStep = null;
|
|
9990
|
+
let previous = now();
|
|
9991
|
+
const commit = (at, force) => {
|
|
9992
|
+
if (!force && at - committedRef.current < COMMIT_INTERVAL_MS) return;
|
|
9993
|
+
committedRef.current = at;
|
|
9994
|
+
setFrame((value) => value + 1);
|
|
9995
|
+
};
|
|
9996
|
+
const step = () => {
|
|
9997
|
+
cancelStep = null;
|
|
9998
|
+
if (cancelled) return;
|
|
9999
|
+
const at = now();
|
|
10000
|
+
const elapsed = clamp(at - previous, 0, MAX_STEP_MS);
|
|
10001
|
+
previous = at;
|
|
10002
|
+
const length = textRef.current.length;
|
|
10003
|
+
const pending = length - cursorRef.current;
|
|
10004
|
+
if (pending <= 0) {
|
|
10005
|
+
commit(at, true);
|
|
10006
|
+
return;
|
|
10007
|
+
}
|
|
10008
|
+
const perSecond = clamp(
|
|
10009
|
+
pending / (DRAIN_TARGET_MS / 1e3),
|
|
10010
|
+
MIN_CHARS_PER_SECOND,
|
|
10011
|
+
MAX_CHARS_PER_SECOND
|
|
10012
|
+
);
|
|
10013
|
+
cursorRef.current = Math.min(
|
|
10014
|
+
length,
|
|
10015
|
+
cursorRef.current + perSecond * elapsed / 1e3
|
|
10016
|
+
);
|
|
10017
|
+
const done = cursorRef.current >= length;
|
|
10018
|
+
commit(at, done);
|
|
10019
|
+
if (!done) schedule();
|
|
10020
|
+
};
|
|
10021
|
+
const schedule = () => {
|
|
10022
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
10023
|
+
const id2 = window.requestAnimationFrame(step);
|
|
10024
|
+
cancelStep = () => window.cancelAnimationFrame(id2);
|
|
10025
|
+
return;
|
|
10026
|
+
}
|
|
10027
|
+
const id = setTimeout(step, FALLBACK_STEP_MS);
|
|
10028
|
+
cancelStep = () => clearTimeout(id);
|
|
10029
|
+
};
|
|
10030
|
+
schedule();
|
|
10031
|
+
return () => {
|
|
10032
|
+
cancelled = true;
|
|
10033
|
+
cancelStep?.();
|
|
10034
|
+
};
|
|
10035
|
+
}, [text, immediate]);
|
|
10036
|
+
return text.slice(0, cut);
|
|
10037
|
+
}
|
|
7957
10038
|
function getRecognitionCtor() {
|
|
7958
10039
|
if (typeof window === "undefined") return null;
|
|
7959
10040
|
const w = window;
|
|
@@ -8172,6 +10253,141 @@ function useSpeechInput({
|
|
|
8172
10253
|
);
|
|
8173
10254
|
return { supported, listening, interim, error, start, stop, toggle };
|
|
8174
10255
|
}
|
|
10256
|
+
var SILENT_FAILURE_MS = 1500;
|
|
10257
|
+
function speechPlatform() {
|
|
10258
|
+
if (typeof window === "undefined") return null;
|
|
10259
|
+
const scope = window;
|
|
10260
|
+
const synth = scope.speechSynthesis;
|
|
10261
|
+
const Utterance = scope.SpeechSynthesisUtterance;
|
|
10262
|
+
if (!synth || typeof synth.speak !== "function") return null;
|
|
10263
|
+
if (typeof Utterance !== "function") return null;
|
|
10264
|
+
return { synth, Utterance };
|
|
10265
|
+
}
|
|
10266
|
+
function normaliseTag(tag) {
|
|
10267
|
+
return tag.trim().toLowerCase().replace(/_/g, "-");
|
|
10268
|
+
}
|
|
10269
|
+
function primaryOf(tag) {
|
|
10270
|
+
return normaliseTag(tag).split("-")[0] ?? "";
|
|
10271
|
+
}
|
|
10272
|
+
function pickVoice(voices, lang) {
|
|
10273
|
+
const wanted = normaliseTag(lang);
|
|
10274
|
+
if (wanted === "") return null;
|
|
10275
|
+
const primary = primaryOf(wanted);
|
|
10276
|
+
const exact = voices.filter((voice) => normaliseTag(voice.lang) === wanted);
|
|
10277
|
+
const related = voices.filter((voice) => primaryOf(voice.lang) === primary);
|
|
10278
|
+
return exact.find((voice) => voice.default) ?? exact[0] ?? related.find((voice) => voice.default) ?? related[0] ?? null;
|
|
10279
|
+
}
|
|
10280
|
+
var activeOwner = null;
|
|
10281
|
+
var activeStop = null;
|
|
10282
|
+
function stopSpeaking() {
|
|
10283
|
+
activeStop?.();
|
|
10284
|
+
}
|
|
10285
|
+
function useSpeechOutput({
|
|
10286
|
+
lang
|
|
10287
|
+
} = {}) {
|
|
10288
|
+
const [available, setAvailable] = React.useState(() => speechPlatform() !== null);
|
|
10289
|
+
const [speaking, setSpeaking] = React.useState(false);
|
|
10290
|
+
const utteranceRef = React.useRef(null);
|
|
10291
|
+
const watchdogRef = React.useRef(null);
|
|
10292
|
+
const ownerRef = React.useRef({});
|
|
10293
|
+
const stopRef = React.useRef(() => void 0);
|
|
10294
|
+
const langRef = React.useRef(lang);
|
|
10295
|
+
langRef.current = lang;
|
|
10296
|
+
const clearWatchdog = React.useCallback(() => {
|
|
10297
|
+
if (watchdogRef.current === null) return;
|
|
10298
|
+
clearTimeout(watchdogRef.current);
|
|
10299
|
+
watchdogRef.current = null;
|
|
10300
|
+
}, []);
|
|
10301
|
+
const settle = React.useCallback(() => {
|
|
10302
|
+
clearWatchdog();
|
|
10303
|
+
utteranceRef.current = null;
|
|
10304
|
+
if (activeOwner === ownerRef.current) {
|
|
10305
|
+
activeOwner = null;
|
|
10306
|
+
activeStop = null;
|
|
10307
|
+
}
|
|
10308
|
+
setSpeaking(false);
|
|
10309
|
+
}, [clearWatchdog]);
|
|
10310
|
+
const stop = React.useCallback(() => {
|
|
10311
|
+
const owned = utteranceRef.current !== null;
|
|
10312
|
+
settle();
|
|
10313
|
+
if (owned) speechPlatform()?.synth.cancel();
|
|
10314
|
+
}, [settle]);
|
|
10315
|
+
stopRef.current = stop;
|
|
10316
|
+
const speak = React.useCallback(
|
|
10317
|
+
(text) => {
|
|
10318
|
+
const platform = speechPlatform();
|
|
10319
|
+
if (!platform) {
|
|
10320
|
+
setAvailable(false);
|
|
10321
|
+
return;
|
|
10322
|
+
}
|
|
10323
|
+
const spoken = text.trim();
|
|
10324
|
+
if (spoken === "") return;
|
|
10325
|
+
if (activeStop && activeOwner !== ownerRef.current) activeStop();
|
|
10326
|
+
platform.synth.cancel();
|
|
10327
|
+
const utterance = new platform.Utterance(spoken);
|
|
10328
|
+
const wanted = langRef.current;
|
|
10329
|
+
if (wanted !== void 0 && wanted !== "") {
|
|
10330
|
+
const voice = pickVoice(platform.synth.getVoices(), wanted);
|
|
10331
|
+
utterance.lang = voice?.lang ?? wanted;
|
|
10332
|
+
if (voice) utterance.voice = voice;
|
|
10333
|
+
}
|
|
10334
|
+
const mine = () => utteranceRef.current === utterance;
|
|
10335
|
+
utterance.onstart = () => {
|
|
10336
|
+
if (!mine()) return;
|
|
10337
|
+
clearWatchdog();
|
|
10338
|
+
setSpeaking(true);
|
|
10339
|
+
};
|
|
10340
|
+
utterance.onend = () => {
|
|
10341
|
+
if (!mine()) return;
|
|
10342
|
+
settle();
|
|
10343
|
+
};
|
|
10344
|
+
utterance.onerror = (event) => {
|
|
10345
|
+
if (!mine()) return;
|
|
10346
|
+
const code = typeof event?.error === "string" ? event.error : "";
|
|
10347
|
+
settle();
|
|
10348
|
+
if (code !== "interrupted" && code !== "canceled") setAvailable(false);
|
|
10349
|
+
};
|
|
10350
|
+
utteranceRef.current = utterance;
|
|
10351
|
+
activeOwner = ownerRef.current;
|
|
10352
|
+
activeStop = () => {
|
|
10353
|
+
stopRef.current();
|
|
10354
|
+
};
|
|
10355
|
+
setSpeaking(true);
|
|
10356
|
+
platform.synth.speak(utterance);
|
|
10357
|
+
clearWatchdog();
|
|
10358
|
+
watchdogRef.current = setTimeout(() => {
|
|
10359
|
+
watchdogRef.current = null;
|
|
10360
|
+
if (!mine()) return;
|
|
10361
|
+
if (platform.synth.speaking) return;
|
|
10362
|
+
settle();
|
|
10363
|
+
setAvailable(false);
|
|
10364
|
+
}, SILENT_FAILURE_MS);
|
|
10365
|
+
},
|
|
10366
|
+
[clearWatchdog, settle]
|
|
10367
|
+
);
|
|
10368
|
+
const toggle = React.useCallback(
|
|
10369
|
+
(text) => {
|
|
10370
|
+
if (speaking) stop();
|
|
10371
|
+
else speak(text);
|
|
10372
|
+
},
|
|
10373
|
+
[speak, speaking, stop]
|
|
10374
|
+
);
|
|
10375
|
+
React.useEffect(() => {
|
|
10376
|
+
if (!speaking || typeof window === "undefined") return;
|
|
10377
|
+
const onHide = () => {
|
|
10378
|
+
stopRef.current();
|
|
10379
|
+
};
|
|
10380
|
+
window.addEventListener("pagehide", onHide);
|
|
10381
|
+
return () => window.removeEventListener("pagehide", onHide);
|
|
10382
|
+
}, [speaking]);
|
|
10383
|
+
React.useEffect(
|
|
10384
|
+
() => () => {
|
|
10385
|
+
stopRef.current();
|
|
10386
|
+
},
|
|
10387
|
+
[]
|
|
10388
|
+
);
|
|
10389
|
+
return { supported: available, speaking, speak, stop, toggle };
|
|
10390
|
+
}
|
|
8175
10391
|
var SWIPE_THRESHOLD = 40;
|
|
8176
10392
|
function useSwipe({
|
|
8177
10393
|
onSwipeLeft,
|
|
@@ -8412,33 +10628,6 @@ var EXPLORE_CSS = `
|
|
|
8412
10628
|
.boff-explore-fade { animation: none; }
|
|
8413
10629
|
}
|
|
8414
10630
|
|
|
8415
|
-
/* Nothing inside an answer may widen the page. Model output carries long URLs, code and
|
|
8416
|
-
tables \u2014 each of those overflows a phone by default, and one overflowing child makes the
|
|
8417
|
-
WHOLE document horizontally scrollable, not just the bubble. */
|
|
8418
|
-
.boff-explore-body,
|
|
8419
|
-
.boff-explore-body p,
|
|
8420
|
-
.boff-explore-body li,
|
|
8421
|
-
.boff-explore-body a,
|
|
8422
|
-
.boff-explore-body h1,
|
|
8423
|
-
.boff-explore-body h2,
|
|
8424
|
-
.boff-explore-body h3 {
|
|
8425
|
-
overflow-wrap: anywhere;
|
|
8426
|
-
word-break: break-word;
|
|
8427
|
-
}
|
|
8428
|
-
.boff-explore-body pre {
|
|
8429
|
-
overflow-x: auto;
|
|
8430
|
-
max-width: 100%;
|
|
8431
|
-
}
|
|
8432
|
-
.boff-explore-body table {
|
|
8433
|
-
display: block;
|
|
8434
|
-
overflow-x: auto;
|
|
8435
|
-
max-width: 100%;
|
|
8436
|
-
}
|
|
8437
|
-
.boff-explore-body img {
|
|
8438
|
-
max-width: 100%;
|
|
8439
|
-
height: auto;
|
|
8440
|
-
}
|
|
8441
|
-
|
|
8442
10631
|
/* ---- Ambient backdrop -----------------------------------------------------------------
|
|
8443
10632
|
Two very low-opacity radial washes behind the welcome state, drifting slowly. Painted on
|
|
8444
10633
|
a pseudo-element with pointer-events:none so it can never intercept a click \u2014 a
|
|
@@ -8495,11 +10684,40 @@ var EXPLORE_CSS = `
|
|
|
8495
10684
|
animation: boff-explore-sheen 1.5s ease-in-out infinite;
|
|
8496
10685
|
}
|
|
8497
10686
|
|
|
10687
|
+
/* ---- The composer, before anyone has typed -----------------------------------------
|
|
10688
|
+
On the welcome screen the box IS the page: everything above it is a way of explaining
|
|
10689
|
+
what to put in it. Unhighlighted it reads as a search bar at the bottom of a landing
|
|
10690
|
+
page, which people scroll past \u2014 so while the conversation is empty it gets a soft halo
|
|
10691
|
+
in the site's own --primary and one slow breath of it, and the moment there is a
|
|
10692
|
+
transcript, or the visitor focuses or types, it drops back to the ordinary card it was.
|
|
10693
|
+
An input that keeps pulsing while you are using it is nagging, not inviting.
|
|
10694
|
+
|
|
10695
|
+
Colour comes from the product's --primary token, so it is whatever that site's palette
|
|
10696
|
+
already is, never a colour chosen here. */
|
|
10697
|
+
.boff-explore-invite {
|
|
10698
|
+
border-color: hsl(var(--primary) / 0.45);
|
|
10699
|
+
box-shadow:
|
|
10700
|
+
0 0 0 4px hsl(var(--primary) / 0.08),
|
|
10701
|
+
0 8px 24px -12px hsl(var(--primary) / 0.45);
|
|
10702
|
+
animation: boff-explore-breathe 3.2s ease-in-out infinite;
|
|
10703
|
+
}
|
|
10704
|
+
/* Focus and typing both mean "I have found it", and the hint has done its job. */
|
|
10705
|
+
.boff-explore-invite:focus-within,
|
|
10706
|
+
.boff-explore-invite.boff-explore-invite-quiet {
|
|
10707
|
+
animation: none;
|
|
10708
|
+
box-shadow: 0 0 0 4px hsl(var(--primary) / 0.10);
|
|
10709
|
+
}
|
|
10710
|
+
@keyframes boff-explore-breathe {
|
|
10711
|
+
0%, 100% { box-shadow: 0 0 0 4px hsl(var(--primary) / 0.07), 0 8px 24px -12px hsl(var(--primary) / 0.40); }
|
|
10712
|
+
50% { box-shadow: 0 0 0 7px hsl(var(--primary) / 0.13), 0 8px 28px -12px hsl(var(--primary) / 0.55); }
|
|
10713
|
+
}
|
|
10714
|
+
|
|
8498
10715
|
/* Every one of the above is decoration. Reduced motion removes the movement and keeps the
|
|
8499
10716
|
final state, rather than leaving content mid-animation and invisible. */
|
|
8500
10717
|
@media (prefers-reduced-motion: reduce) {
|
|
8501
10718
|
.boff-explore-aura::before,
|
|
8502
|
-
.boff-explore-busy::after
|
|
10719
|
+
.boff-explore-busy::after,
|
|
10720
|
+
.boff-explore-invite { animation: none; }
|
|
8503
10721
|
.boff-explore-rise { animation: none; opacity: 1; transform: none; }
|
|
8504
10722
|
}
|
|
8505
10723
|
|
|
@@ -8610,7 +10828,7 @@ function isOwnElement(el, root) {
|
|
|
8610
10828
|
function visualViewportHeight() {
|
|
8611
10829
|
return window.visualViewport?.height ?? window.innerHeight;
|
|
8612
10830
|
}
|
|
8613
|
-
function
|
|
10831
|
+
function clamp2(value, min, max) {
|
|
8614
10832
|
return Math.min(Math.max(value, min), max);
|
|
8615
10833
|
}
|
|
8616
10834
|
function isRestoredNavigation() {
|
|
@@ -8629,51 +10847,23 @@ function isInternalPath(url) {
|
|
|
8629
10847
|
}
|
|
8630
10848
|
function hostnameOf(url) {
|
|
8631
10849
|
try {
|
|
8632
|
-
return new URL(url).hostname.replace(/^www\./, "");
|
|
8633
|
-
} catch {
|
|
8634
|
-
return "";
|
|
8635
|
-
}
|
|
8636
|
-
}
|
|
8637
|
-
function initialOf(value, fallback) {
|
|
8638
|
-
const source = (value || fallback).trim();
|
|
8639
|
-
return source ? source.slice(0, 1).toUpperCase() : "?";
|
|
8640
|
-
}
|
|
8641
|
-
function logoUrlOf(url) {
|
|
8642
|
-
try {
|
|
8643
|
-
const { origin, protocol } = new URL(url);
|
|
8644
|
-
if (protocol !== "https:" && protocol !== "http:") return null;
|
|
8645
|
-
return `${origin}/favicon.svg`;
|
|
8646
|
-
} catch {
|
|
8647
|
-
return null;
|
|
8648
|
-
}
|
|
8649
|
-
}
|
|
8650
|
-
function inlineImageOrigins(products) {
|
|
8651
|
-
const origins = /* @__PURE__ */ new Set();
|
|
8652
|
-
for (const product of products) {
|
|
8653
|
-
let url;
|
|
8654
|
-
try {
|
|
8655
|
-
url = new URL(product.website);
|
|
8656
|
-
} catch {
|
|
8657
|
-
continue;
|
|
8658
|
-
}
|
|
8659
|
-
if (url.protocol !== "https:") continue;
|
|
8660
|
-
const apex = url.hostname.replace(/^www\./, "");
|
|
8661
|
-
const port = url.port ? `:${url.port}` : "";
|
|
8662
|
-
origins.add(`https://${apex}${port}`);
|
|
8663
|
-
origins.add(`https://www.${apex}${port}`);
|
|
10850
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
10851
|
+
} catch {
|
|
10852
|
+
return "";
|
|
8664
10853
|
}
|
|
8665
|
-
return origins;
|
|
8666
10854
|
}
|
|
8667
|
-
function
|
|
8668
|
-
|
|
8669
|
-
|
|
10855
|
+
function initialOf(value, fallback) {
|
|
10856
|
+
const source = (value || fallback).trim();
|
|
10857
|
+
return source ? source.slice(0, 1).toUpperCase() : "?";
|
|
10858
|
+
}
|
|
10859
|
+
function logoUrlOf(url) {
|
|
8670
10860
|
try {
|
|
8671
|
-
|
|
10861
|
+
const { origin, protocol } = new URL(url);
|
|
10862
|
+
if (protocol !== "https:" && protocol !== "http:") return null;
|
|
10863
|
+
return `${origin}/favicon.svg`;
|
|
8672
10864
|
} catch {
|
|
8673
|
-
return
|
|
10865
|
+
return null;
|
|
8674
10866
|
}
|
|
8675
|
-
if (url.protocol !== "https:" || url.username || url.password) return false;
|
|
8676
|
-
return origins.has(url.origin);
|
|
8677
10867
|
}
|
|
8678
10868
|
var REFERENCE_KIND_ORDER = [
|
|
8679
10869
|
"CONCEPT",
|
|
@@ -8759,97 +10949,6 @@ function summariseReferences(references, origins, productNames) {
|
|
|
8759
10949
|
products
|
|
8760
10950
|
};
|
|
8761
10951
|
}
|
|
8762
|
-
var CODE_FENCE = /^\s*(?:```|~~~)/;
|
|
8763
|
-
function answerPlainText(markdown) {
|
|
8764
|
-
const lines = [];
|
|
8765
|
-
let inFence = false;
|
|
8766
|
-
for (const raw of markdown.split("\n")) {
|
|
8767
|
-
if (CODE_FENCE.test(raw)) {
|
|
8768
|
-
inFence = !inFence;
|
|
8769
|
-
continue;
|
|
8770
|
-
}
|
|
8771
|
-
if (inFence) {
|
|
8772
|
-
lines.push(raw);
|
|
8773
|
-
continue;
|
|
8774
|
-
}
|
|
8775
|
-
let line = raw;
|
|
8776
|
-
line = line.replace(/!\[[^\]]*\]\([^)\s]*(?:\s+"[^"]*")?\)/g, "");
|
|
8777
|
-
line = line.replace(/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, "$1 ($2)");
|
|
8778
|
-
line = line.replace(/<(https?:\/\/[^>\s]+)>/g, "$1");
|
|
8779
|
-
line = line.replace(/^\s{0,3}#{1,6}\s+/, "");
|
|
8780
|
-
line = line.replace(/^\s{0,3}>\s?/, "");
|
|
8781
|
-
if (/^\s{0,3}([-*_])[ \t]*(?:\1[ \t]*){2,}$/.test(line)) {
|
|
8782
|
-
lines.push("");
|
|
8783
|
-
continue;
|
|
8784
|
-
}
|
|
8785
|
-
line = line.replace(/`([^`]+)`/g, "$1");
|
|
8786
|
-
line = line.replace(/\*\*([^*]+)\*\*/g, "$1");
|
|
8787
|
-
line = line.replace(/__([^_]+)__/g, "$1");
|
|
8788
|
-
line = line.replace(/(^|[^*\w])\*([^*\n]+)\*(?![*\w])/g, "$1$2");
|
|
8789
|
-
line = line.replace(/(^|[^_\w])_([^_\n]+)_(?![_\w])/g, "$1$2");
|
|
8790
|
-
lines.push(line.replace(/[ \t]+$/, ""));
|
|
8791
|
-
}
|
|
8792
|
-
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
8793
|
-
}
|
|
8794
|
-
var InlineImageScopeContext = React.createContext(null);
|
|
8795
|
-
var InsideLinkContext = React.createContext(false);
|
|
8796
|
-
function AnswerLink(props) {
|
|
8797
|
-
return /* @__PURE__ */ jsxRuntime.jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownLink, { ...props }) });
|
|
8798
|
-
}
|
|
8799
|
-
var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
|
|
8800
|
-
function InlineConceptImage({ src, alt }) {
|
|
8801
|
-
const scope = React.useContext(InlineImageScopeContext);
|
|
8802
|
-
const insideLink = React.useContext(InsideLinkContext);
|
|
8803
|
-
if (!scope || !scope.enabled || !isInlineImageAllowed(src, scope.origins) || scope.failed.has(src)) {
|
|
8804
|
-
return null;
|
|
8805
|
-
}
|
|
8806
|
-
const { strings: T, onFailed } = scope;
|
|
8807
|
-
const picture = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8808
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8809
|
-
"img",
|
|
8810
|
-
{
|
|
8811
|
-
src,
|
|
8812
|
-
alt: alt ?? "",
|
|
8813
|
-
loading: "lazy",
|
|
8814
|
-
decoding: "async",
|
|
8815
|
-
onError: () => onFailed(src),
|
|
8816
|
-
className: "block h-auto max-h-80 w-auto max-w-full object-contain"
|
|
8817
|
-
}
|
|
8818
|
-
),
|
|
8819
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8820
|
-
"span",
|
|
8821
|
-
{
|
|
8822
|
-
"aria-hidden": "true",
|
|
8823
|
-
className: "pointer-events-none absolute left-2 top-2 rounded-full border border-border bg-background/90 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-foreground shadow-sm",
|
|
8824
|
-
children: T.conceptIllustration
|
|
8825
|
-
}
|
|
8826
|
-
)
|
|
8827
|
-
] });
|
|
8828
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-boff-explore": "inline-image", className: "my-3 block", children: insideLink ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: INLINE_IMAGE_FRAME, children: picture }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8829
|
-
"a",
|
|
8830
|
-
{
|
|
8831
|
-
href: src,
|
|
8832
|
-
target: "_blank",
|
|
8833
|
-
rel: "noopener noreferrer",
|
|
8834
|
-
className: cn(
|
|
8835
|
-
INLINE_IMAGE_FRAME,
|
|
8836
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
8837
|
-
),
|
|
8838
|
-
children: [
|
|
8839
|
-
picture,
|
|
8840
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
|
|
8841
|
-
"(",
|
|
8842
|
-
T.opensInNewTab,
|
|
8843
|
-
")"
|
|
8844
|
-
] })
|
|
8845
|
-
]
|
|
8846
|
-
}
|
|
8847
|
-
) });
|
|
8848
|
-
}
|
|
8849
|
-
var ANSWER_MARKDOWN_COMPONENTS = {
|
|
8850
|
-
a: AnswerLink,
|
|
8851
|
-
img: InlineConceptImage
|
|
8852
|
-
};
|
|
8853
10952
|
function ReferenceCard({
|
|
8854
10953
|
reference,
|
|
8855
10954
|
onFollow
|
|
@@ -9188,6 +11287,195 @@ function AnswerFeedback({
|
|
|
9188
11287
|
}
|
|
9189
11288
|
);
|
|
9190
11289
|
}
|
|
11290
|
+
function EscalateForm({
|
|
11291
|
+
strings: T,
|
|
11292
|
+
formId,
|
|
11293
|
+
onEscalate,
|
|
11294
|
+
onClose,
|
|
11295
|
+
onBusyChange
|
|
11296
|
+
}) {
|
|
11297
|
+
const [email, setEmail] = React.useState("");
|
|
11298
|
+
const [note, setNote] = React.useState("");
|
|
11299
|
+
const [error, setError] = React.useState(null);
|
|
11300
|
+
const [sending, setSending] = React.useState(false);
|
|
11301
|
+
const [sentTo, setSentTo] = React.useState(null);
|
|
11302
|
+
const emailRef = React.useRef(null);
|
|
11303
|
+
const inFlightRef = React.useRef(false);
|
|
11304
|
+
const titleId = `${formId}-title`;
|
|
11305
|
+
const emailId = `${formId}-email`;
|
|
11306
|
+
const noteId = `${formId}-note`;
|
|
11307
|
+
const errorId = `${formId}-error`;
|
|
11308
|
+
React.useEffect(() => {
|
|
11309
|
+
emailRef.current?.focus();
|
|
11310
|
+
}, []);
|
|
11311
|
+
React.useEffect(() => {
|
|
11312
|
+
onBusyChange?.(sending);
|
|
11313
|
+
return () => onBusyChange?.(false);
|
|
11314
|
+
}, [sending, onBusyChange]);
|
|
11315
|
+
const handleSubmit = React.useCallback(
|
|
11316
|
+
async (event) => {
|
|
11317
|
+
event.preventDefault();
|
|
11318
|
+
if (inFlightRef.current) return;
|
|
11319
|
+
const address = email.trim();
|
|
11320
|
+
if (!looksLikeDeliverableEmail(address)) {
|
|
11321
|
+
setError(T.escalateInvalidEmail);
|
|
11322
|
+
emailRef.current?.focus();
|
|
11323
|
+
return;
|
|
11324
|
+
}
|
|
11325
|
+
inFlightRef.current = true;
|
|
11326
|
+
setSending(true);
|
|
11327
|
+
setError(null);
|
|
11328
|
+
const result = await onEscalate(address, note);
|
|
11329
|
+
inFlightRef.current = false;
|
|
11330
|
+
setSending(false);
|
|
11331
|
+
switch (result.outcome) {
|
|
11332
|
+
case "sent":
|
|
11333
|
+
case "already-handed-over":
|
|
11334
|
+
setSentTo(result.email ?? address);
|
|
11335
|
+
return;
|
|
11336
|
+
case "invalid-email":
|
|
11337
|
+
setError(T.escalateInvalidEmail);
|
|
11338
|
+
emailRef.current?.focus();
|
|
11339
|
+
return;
|
|
11340
|
+
case "rate-limited":
|
|
11341
|
+
setError(T.escalateRateLimited);
|
|
11342
|
+
return;
|
|
11343
|
+
case "captcha":
|
|
11344
|
+
setError(T.escalateCaptcha);
|
|
11345
|
+
return;
|
|
11346
|
+
// `no-conversation` included: the form should not have been offered at all, and the
|
|
11347
|
+
// honest thing to show is that nothing was passed on.
|
|
11348
|
+
default:
|
|
11349
|
+
setError(T.escalateFailed);
|
|
11350
|
+
return;
|
|
11351
|
+
}
|
|
11352
|
+
},
|
|
11353
|
+
[T, email, note, onEscalate]
|
|
11354
|
+
);
|
|
11355
|
+
if (sentTo !== null) {
|
|
11356
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11357
|
+
"p",
|
|
11358
|
+
{
|
|
11359
|
+
id: formId,
|
|
11360
|
+
"data-boff-explore": "escalate-sent",
|
|
11361
|
+
role: "status",
|
|
11362
|
+
className: "boff-explore-fade mt-2 rounded-xl border border-border bg-card px-3 py-2 text-xs leading-relaxed text-card-foreground",
|
|
11363
|
+
children: fill(T.escalateSent, { email: sentTo })
|
|
11364
|
+
}
|
|
11365
|
+
);
|
|
11366
|
+
}
|
|
11367
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11368
|
+
"form",
|
|
11369
|
+
{
|
|
11370
|
+
id: formId,
|
|
11371
|
+
"data-boff-explore": "escalate-form",
|
|
11372
|
+
"aria-labelledby": titleId,
|
|
11373
|
+
noValidate: true,
|
|
11374
|
+
onSubmit: handleSubmit,
|
|
11375
|
+
onKeyDown: (event) => {
|
|
11376
|
+
if (event.key !== "Escape") return;
|
|
11377
|
+
event.stopPropagation();
|
|
11378
|
+
if (sending) return;
|
|
11379
|
+
onClose();
|
|
11380
|
+
},
|
|
11381
|
+
className: "boff-explore-fade mt-2 space-y-2 rounded-xl border border-border bg-card p-3",
|
|
11382
|
+
children: [
|
|
11383
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { id: titleId, className: "text-xs font-medium text-card-foreground", children: T.escalateTitle }),
|
|
11384
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: T.escalateBody }),
|
|
11385
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
11386
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11387
|
+
"label",
|
|
11388
|
+
{
|
|
11389
|
+
htmlFor: emailId,
|
|
11390
|
+
className: "block text-xs font-medium text-card-foreground",
|
|
11391
|
+
children: T.escalateEmailLabel
|
|
11392
|
+
}
|
|
11393
|
+
),
|
|
11394
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11395
|
+
"input",
|
|
11396
|
+
{
|
|
11397
|
+
ref: emailRef,
|
|
11398
|
+
id: emailId,
|
|
11399
|
+
name: "email",
|
|
11400
|
+
"data-boff-explore": "escalate-email",
|
|
11401
|
+
type: "email",
|
|
11402
|
+
inputMode: "email",
|
|
11403
|
+
autoComplete: "email",
|
|
11404
|
+
required: true,
|
|
11405
|
+
value: email,
|
|
11406
|
+
onChange: (event) => {
|
|
11407
|
+
setEmail(event.target.value);
|
|
11408
|
+
if (error) setError(null);
|
|
11409
|
+
},
|
|
11410
|
+
"aria-invalid": error ? "true" : void 0,
|
|
11411
|
+
"aria-describedby": error ? errorId : void 0,
|
|
11412
|
+
placeholder: T.escalateEmailPlaceholder,
|
|
11413
|
+
className: "w-full rounded-md border border-border bg-background px-2 py-1 text-base text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring sm:text-sm"
|
|
11414
|
+
}
|
|
11415
|
+
)
|
|
11416
|
+
] }),
|
|
11417
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
11418
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11419
|
+
"label",
|
|
11420
|
+
{
|
|
11421
|
+
htmlFor: noteId,
|
|
11422
|
+
className: "block text-xs font-medium text-card-foreground",
|
|
11423
|
+
children: T.escalateNoteLabel
|
|
11424
|
+
}
|
|
11425
|
+
),
|
|
11426
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11427
|
+
Textarea,
|
|
11428
|
+
{
|
|
11429
|
+
id: noteId,
|
|
11430
|
+
name: "note",
|
|
11431
|
+
"data-boff-explore": "escalate-note",
|
|
11432
|
+
rows: 2,
|
|
11433
|
+
value: note,
|
|
11434
|
+
onChange: (event) => setNote(event.target.value),
|
|
11435
|
+
maxLength: EXPLORE_ESCALATION_NOTE_SOFT_MAX,
|
|
11436
|
+
className: "min-h-0 border-border bg-background"
|
|
11437
|
+
}
|
|
11438
|
+
)
|
|
11439
|
+
] }),
|
|
11440
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
11441
|
+
"p",
|
|
11442
|
+
{
|
|
11443
|
+
id: errorId,
|
|
11444
|
+
"data-boff-explore": "escalate-error",
|
|
11445
|
+
role: "alert",
|
|
11446
|
+
className: "text-xs leading-relaxed text-destructive",
|
|
11447
|
+
children: error
|
|
11448
|
+
}
|
|
11449
|
+
) : null,
|
|
11450
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
11451
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11452
|
+
Button,
|
|
11453
|
+
{
|
|
11454
|
+
"data-boff-explore": "escalate-send",
|
|
11455
|
+
type: "submit",
|
|
11456
|
+
size: "sm",
|
|
11457
|
+
disabled: sending,
|
|
11458
|
+
children: sending ? T.escalateSending : T.escalateSubmit
|
|
11459
|
+
}
|
|
11460
|
+
),
|
|
11461
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11462
|
+
Button,
|
|
11463
|
+
{
|
|
11464
|
+
"data-boff-explore": "escalate-cancel",
|
|
11465
|
+
type: "button",
|
|
11466
|
+
size: "sm",
|
|
11467
|
+
variant: "ghost",
|
|
11468
|
+
className: "text-muted-foreground",
|
|
11469
|
+
disabled: sending,
|
|
11470
|
+
onClick: onClose,
|
|
11471
|
+
children: T.escalateCancel
|
|
11472
|
+
}
|
|
11473
|
+
)
|
|
11474
|
+
] })
|
|
11475
|
+
]
|
|
11476
|
+
}
|
|
11477
|
+
);
|
|
11478
|
+
}
|
|
9191
11479
|
var PROVENANCE_CHIP = "inline-flex max-w-full items-center gap-1 rounded-full border border-border bg-muted/60 px-2 py-0.5 text-[11px] leading-5 text-muted-foreground";
|
|
9192
11480
|
function ProvenanceChips({
|
|
9193
11481
|
strings: T,
|
|
@@ -9237,9 +11525,42 @@ function ProvenanceChips({
|
|
|
9237
11525
|
);
|
|
9238
11526
|
}
|
|
9239
11527
|
var COPY_FEEDBACK_MS = 2500;
|
|
11528
|
+
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";
|
|
11529
|
+
var ANSWER_ACTION_IDLE = "border-border bg-card text-muted-foreground hover:border-primary/40 hover:bg-accent hover:text-foreground";
|
|
11530
|
+
var ANSWER_ACTION_ACTIVE = "border-primary/40 bg-accent text-primary";
|
|
11531
|
+
function ReadAloudButton({
|
|
11532
|
+
strings: T,
|
|
11533
|
+
text,
|
|
11534
|
+
lang
|
|
11535
|
+
}) {
|
|
11536
|
+
const speech = useSpeechOutput({ lang });
|
|
11537
|
+
if (!speech.supported) return null;
|
|
11538
|
+
const label = speech.speaking ? T.stopReading : T.readAloud;
|
|
11539
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11540
|
+
"button",
|
|
11541
|
+
{
|
|
11542
|
+
"data-boff-explore": "read-aloud",
|
|
11543
|
+
"data-speaking": speech.speaking ? "true" : "false",
|
|
11544
|
+
type: "button",
|
|
11545
|
+
title: label,
|
|
11546
|
+
"aria-pressed": speech.speaking,
|
|
11547
|
+
onClick: () => speech.toggle(text),
|
|
11548
|
+
className: cn(
|
|
11549
|
+
ANSWER_ACTION_PILL,
|
|
11550
|
+
speech.speaking ? ANSWER_ACTION_ACTIVE : ANSWER_ACTION_IDLE
|
|
11551
|
+
),
|
|
11552
|
+
children: [
|
|
11553
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Volume2, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }),
|
|
11554
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label })
|
|
11555
|
+
]
|
|
11556
|
+
}
|
|
11557
|
+
);
|
|
11558
|
+
}
|
|
9240
11559
|
function AnswerActions({
|
|
9241
11560
|
strings: T,
|
|
9242
|
-
text
|
|
11561
|
+
text,
|
|
11562
|
+
speechText,
|
|
11563
|
+
speechLang
|
|
9243
11564
|
}) {
|
|
9244
11565
|
const [outcome, setOutcome] = React.useState("idle");
|
|
9245
11566
|
const resetRef = React.useRef(null);
|
|
@@ -9282,9 +11603,8 @@ function AnswerActions({
|
|
|
9282
11603
|
void copy();
|
|
9283
11604
|
},
|
|
9284
11605
|
className: cn(
|
|
9285
|
-
|
|
9286
|
-
"
|
|
9287
|
-
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"
|
|
11606
|
+
ANSWER_ACTION_PILL,
|
|
11607
|
+
outcome === "failed" ? "border-destructive/40 bg-card text-destructive" : ANSWER_ACTION_IDLE
|
|
9288
11608
|
),
|
|
9289
11609
|
children: [
|
|
9290
11610
|
outcome === "copied" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }),
|
|
@@ -9292,6 +11612,7 @@ function AnswerActions({
|
|
|
9292
11612
|
]
|
|
9293
11613
|
}
|
|
9294
11614
|
),
|
|
11615
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadAloudButton, { strings: T, text: speechText, lang: speechLang }),
|
|
9295
11616
|
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-boff-explore": "copy-status", role: "status", className: "sr-only", children: outcome === "idle" ? "" : label })
|
|
9296
11617
|
]
|
|
9297
11618
|
}
|
|
@@ -9343,34 +11664,20 @@ function AssistantBubble({
|
|
|
9343
11664
|
activity,
|
|
9344
11665
|
imageOrigins,
|
|
9345
11666
|
productNames,
|
|
11667
|
+
speechLang,
|
|
9346
11668
|
onNavigate,
|
|
9347
11669
|
anchorRef,
|
|
9348
11670
|
onFollow,
|
|
9349
11671
|
onFollowUp,
|
|
9350
|
-
onFeedback
|
|
11672
|
+
onFeedback,
|
|
11673
|
+
onEscalate,
|
|
11674
|
+
isLatestAnswer = false
|
|
9351
11675
|
}) {
|
|
9352
11676
|
const streaming = message.status === "PENDING" || message.status === "RUNNING";
|
|
9353
11677
|
const body = message.content || message.partialContent || "";
|
|
9354
11678
|
const failed = message.status === "FAILED";
|
|
9355
11679
|
const completed = message.status === "COMPLETED";
|
|
9356
|
-
const
|
|
9357
|
-
() => /* @__PURE__ */ new Set()
|
|
9358
|
-
);
|
|
9359
|
-
const markImageFailed = React.useCallback((src) => {
|
|
9360
|
-
setFailedImages(
|
|
9361
|
-
(current) => current.has(src) ? current : new Set(current).add(src)
|
|
9362
|
-
);
|
|
9363
|
-
}, []);
|
|
9364
|
-
const imageScope = React.useMemo(
|
|
9365
|
-
() => ({
|
|
9366
|
-
strings: T,
|
|
9367
|
-
enabled: completed,
|
|
9368
|
-
origins: imageOrigins,
|
|
9369
|
-
failed: failedImages,
|
|
9370
|
-
onFailed: markImageFailed
|
|
9371
|
-
}),
|
|
9372
|
-
[T, completed, imageOrigins, failedImages, markImageFailed]
|
|
9373
|
-
);
|
|
11680
|
+
const visible = useProgressiveReveal(body, !streaming);
|
|
9374
11681
|
const provenance = React.useMemo(
|
|
9375
11682
|
() => summariseReferences(message.references, imageOrigins, productNames),
|
|
9376
11683
|
[message.references, imageOrigins, productNames]
|
|
@@ -9379,7 +11686,25 @@ function AssistantBubble({
|
|
|
9379
11686
|
() => answerPlainText(message.content),
|
|
9380
11687
|
[message.content]
|
|
9381
11688
|
);
|
|
11689
|
+
const speechText = React.useMemo(
|
|
11690
|
+
() => answerSpeechText(message.content),
|
|
11691
|
+
[message.content]
|
|
11692
|
+
);
|
|
9382
11693
|
const grounded = completed && message.answered !== false;
|
|
11694
|
+
const [escalateOpen, setEscalateOpen] = React.useState(false);
|
|
11695
|
+
const [escalateBusy, setEscalateBusy] = React.useState(false);
|
|
11696
|
+
const escalateTriggerRef = React.useRef(null);
|
|
11697
|
+
const escalateFormId = `boff-explore-escalate-${message.id}`;
|
|
11698
|
+
const unanswered = completed && message.answered === false;
|
|
11699
|
+
const offerEscalate = Boolean(onEscalate) && completed;
|
|
11700
|
+
const showQuietEscalate = offerEscalate && !unanswered && isLatestAnswer;
|
|
11701
|
+
const closeEscalate = React.useCallback(() => {
|
|
11702
|
+
setEscalateOpen(false);
|
|
11703
|
+
escalateTriggerRef.current?.focus();
|
|
11704
|
+
}, []);
|
|
11705
|
+
const handleEscalateBusy = React.useCallback((busy) => {
|
|
11706
|
+
setEscalateBusy(busy);
|
|
11707
|
+
}, []);
|
|
9383
11708
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9384
11709
|
"div",
|
|
9385
11710
|
{
|
|
@@ -9397,7 +11722,7 @@ function AssistantBubble({
|
|
|
9397
11722
|
}
|
|
9398
11723
|
),
|
|
9399
11724
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-3", children: [
|
|
9400
|
-
|
|
11725
|
+
unanswered ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9401
11726
|
"div",
|
|
9402
11727
|
{
|
|
9403
11728
|
"data-boff-explore": "no-answer",
|
|
@@ -9407,26 +11732,56 @@ function AssistantBubble({
|
|
|
9407
11732
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9408
11733
|
T.noAnswer,
|
|
9409
11734
|
" ",
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
11735
|
+
offerEscalate ? (
|
|
11736
|
+
/* The point of the wave: the same words, but they now open a form that
|
|
11737
|
+
sends the conversation we are both looking at, instead of a link to a
|
|
11738
|
+
blank contact page that asks the visitor to type it all again. */
|
|
11739
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11740
|
+
"button",
|
|
11741
|
+
{
|
|
11742
|
+
ref: escalateTriggerRef,
|
|
11743
|
+
"data-boff-explore": "escalate-open",
|
|
11744
|
+
type: "button",
|
|
11745
|
+
"aria-expanded": escalateOpen,
|
|
11746
|
+
"aria-controls": escalateOpen ? escalateFormId : void 0,
|
|
11747
|
+
onClick: () => setEscalateOpen(true),
|
|
11748
|
+
className: "rounded-sm underline underline-offset-2 hover:text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
11749
|
+
children: T.askHuman
|
|
11750
|
+
}
|
|
11751
|
+
)
|
|
11752
|
+
) : (
|
|
11753
|
+
/* No conversation to hand over (a shared, read-only view). The old dead end
|
|
11754
|
+
is still better than a control whose submit could only fail. */
|
|
11755
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11756
|
+
"a",
|
|
11757
|
+
{
|
|
11758
|
+
href: "/contact",
|
|
11759
|
+
className: "underline underline-offset-2 hover:text-primary",
|
|
11760
|
+
onClick: (event) => {
|
|
11761
|
+
if (!onNavigate) return;
|
|
11762
|
+
event.preventDefault();
|
|
11763
|
+
onNavigate("/contact");
|
|
11764
|
+
},
|
|
11765
|
+
children: T.askHuman
|
|
11766
|
+
}
|
|
11767
|
+
)
|
|
9422
11768
|
),
|
|
9423
11769
|
"."
|
|
9424
11770
|
] })
|
|
9425
11771
|
]
|
|
9426
11772
|
}
|
|
9427
11773
|
) : null,
|
|
9428
|
-
|
|
9429
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11774
|
+
visible ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl rounded-tl-md border border-border bg-card px-4 py-3 shadow-sm", children: [
|
|
11775
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11776
|
+
ExploreAnswerBody,
|
|
11777
|
+
{
|
|
11778
|
+
strings: T,
|
|
11779
|
+
imageOrigins,
|
|
11780
|
+
enabled: completed,
|
|
11781
|
+
className: "boff-prose-sm text-card-foreground",
|
|
11782
|
+
children: visible
|
|
11783
|
+
}
|
|
11784
|
+
),
|
|
9430
11785
|
streaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "boff-explore-caret", "aria-hidden": "true" }) : null
|
|
9431
11786
|
] }) : null,
|
|
9432
11787
|
grounded && provenance.total > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ProvenanceChips, { strings: T, provenance }) : null,
|
|
@@ -9469,7 +11824,15 @@ function AssistantBubble({
|
|
|
9469
11824
|
question
|
|
9470
11825
|
)) })
|
|
9471
11826
|
] }) : null,
|
|
9472
|
-
completed && copyText !== "" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
11827
|
+
completed && copyText !== "" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
11828
|
+
AnswerActions,
|
|
11829
|
+
{
|
|
11830
|
+
strings: T,
|
|
11831
|
+
text: copyText,
|
|
11832
|
+
speechText,
|
|
11833
|
+
speechLang
|
|
11834
|
+
}
|
|
11835
|
+
) : null,
|
|
9473
11836
|
completed && onFeedback ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9474
11837
|
AnswerFeedback,
|
|
9475
11838
|
{
|
|
@@ -9478,6 +11841,30 @@ function AssistantBubble({
|
|
|
9478
11841
|
feedback: message.feedback,
|
|
9479
11842
|
onSubmit: onFeedback
|
|
9480
11843
|
}
|
|
11844
|
+
) : null,
|
|
11845
|
+
showQuietEscalate ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11846
|
+
"button",
|
|
11847
|
+
{
|
|
11848
|
+
ref: escalateTriggerRef,
|
|
11849
|
+
"data-boff-explore": "escalate-open",
|
|
11850
|
+
type: "button",
|
|
11851
|
+
"aria-expanded": escalateOpen,
|
|
11852
|
+
"aria-controls": escalateOpen ? escalateFormId : void 0,
|
|
11853
|
+
disabled: escalateBusy,
|
|
11854
|
+
onClick: () => setEscalateOpen((open) => !open),
|
|
11855
|
+
className: "rounded-sm text-xs text-muted-foreground underline underline-offset-2 hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
11856
|
+
children: T.escalateOpen
|
|
11857
|
+
}
|
|
11858
|
+
) }) : null,
|
|
11859
|
+
escalateOpen && onEscalate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
11860
|
+
EscalateForm,
|
|
11861
|
+
{
|
|
11862
|
+
strings: T,
|
|
11863
|
+
formId: escalateFormId,
|
|
11864
|
+
onEscalate,
|
|
11865
|
+
onClose: closeEscalate,
|
|
11866
|
+
onBusyChange: handleEscalateBusy
|
|
11867
|
+
}
|
|
9481
11868
|
) : null
|
|
9482
11869
|
] })
|
|
9483
11870
|
]
|
|
@@ -9917,15 +12304,6 @@ function WelcomeState({
|
|
|
9917
12304
|
}
|
|
9918
12305
|
)
|
|
9919
12306
|
] }) : null,
|
|
9920
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9921
|
-
ConceptStrip,
|
|
9922
|
-
{
|
|
9923
|
-
strings: T,
|
|
9924
|
-
highlights: conceptHighlights,
|
|
9925
|
-
onAsk: onPrompt,
|
|
9926
|
-
disabled
|
|
9927
|
-
}
|
|
9928
|
-
),
|
|
9929
12307
|
products.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-rise boff-explore-rise-3 mt-6", children: [
|
|
9930
12308
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: T.focusProduct }),
|
|
9931
12309
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -9937,7 +12315,16 @@ function WelcomeState({
|
|
|
9937
12315
|
onFocus
|
|
9938
12316
|
}
|
|
9939
12317
|
)
|
|
9940
|
-
] }) : null
|
|
12318
|
+
] }) : null,
|
|
12319
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12320
|
+
ConceptStrip,
|
|
12321
|
+
{
|
|
12322
|
+
strings: T,
|
|
12323
|
+
highlights: conceptHighlights,
|
|
12324
|
+
onAsk: onPrompt,
|
|
12325
|
+
disabled
|
|
12326
|
+
}
|
|
12327
|
+
)
|
|
9941
12328
|
] });
|
|
9942
12329
|
}
|
|
9943
12330
|
function ExplorePage({
|
|
@@ -9963,6 +12350,7 @@ function ExplorePage({
|
|
|
9963
12350
|
);
|
|
9964
12351
|
const T = React.useMemo(() => exploreStrings(activeLocale), [activeLocale]);
|
|
9965
12352
|
const rtl = isRtlLocale(activeLocale);
|
|
12353
|
+
const speechLang = speechLocaleOf(activeLocale);
|
|
9966
12354
|
const {
|
|
9967
12355
|
phase,
|
|
9968
12356
|
catalog,
|
|
@@ -9983,6 +12371,8 @@ function ExplorePage({
|
|
|
9983
12371
|
clearHistory,
|
|
9984
12372
|
recordClick,
|
|
9985
12373
|
submitFeedback,
|
|
12374
|
+
escalate,
|
|
12375
|
+
canEscalate,
|
|
9986
12376
|
createShareLink,
|
|
9987
12377
|
isSharedView
|
|
9988
12378
|
} = useExploreChat({
|
|
@@ -10067,11 +12457,11 @@ function ExplorePage({
|
|
|
10067
12457
|
const layoutHeight = window.innerHeight;
|
|
10068
12458
|
if (layoutHeight === 0) return;
|
|
10069
12459
|
const top = Math.round(
|
|
10070
|
-
|
|
12460
|
+
clamp2(el.getBoundingClientRect().top, 0, layoutHeight)
|
|
10071
12461
|
);
|
|
10072
12462
|
const viewport = window.visualViewport;
|
|
10073
12463
|
const inset = viewport ? Math.round(
|
|
10074
|
-
|
|
12464
|
+
clamp2(
|
|
10075
12465
|
layoutHeight - viewport.height - viewport.offsetTop,
|
|
10076
12466
|
0,
|
|
10077
12467
|
layoutHeight
|
|
@@ -10352,6 +12742,7 @@ function ExplorePage({
|
|
|
10352
12742
|
const text = draft.trim();
|
|
10353
12743
|
if (!text || overLimit || busy || !canSend) return;
|
|
10354
12744
|
stopDictation();
|
|
12745
|
+
stopSpeaking();
|
|
10355
12746
|
setDraft("");
|
|
10356
12747
|
stickToBottomRef.current = true;
|
|
10357
12748
|
void send(text, toPayload(stagedRef.current));
|
|
@@ -10362,6 +12753,7 @@ function ExplorePage({
|
|
|
10362
12753
|
const sendPrompt = React.useCallback(
|
|
10363
12754
|
(prompt) => {
|
|
10364
12755
|
if (!canSend || busy) return;
|
|
12756
|
+
stopSpeaking();
|
|
10365
12757
|
setDraft("");
|
|
10366
12758
|
stickToBottomRef.current = true;
|
|
10367
12759
|
void send(prompt, toPayload(stagedRef.current));
|
|
@@ -10424,6 +12816,7 @@ function ExplorePage({
|
|
|
10424
12816
|
),
|
|
10425
12817
|
/* @__PURE__ */ jsxRuntime.jsx(ProseStyles, {}),
|
|
10426
12818
|
/* @__PURE__ */ jsxRuntime.jsx(ExploreStyles, {}),
|
|
12819
|
+
/* @__PURE__ */ jsxRuntime.jsx(ExploreAnswerStyles, {}),
|
|
10427
12820
|
!showWelcome ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 border-b border-border px-4 py-2.5", children: [
|
|
10428
12821
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10429
12822
|
"span",
|
|
@@ -10597,11 +12990,14 @@ function ExplorePage({
|
|
|
10597
12990
|
activity,
|
|
10598
12991
|
imageOrigins,
|
|
10599
12992
|
productNames,
|
|
12993
|
+
speechLang,
|
|
10600
12994
|
onNavigate,
|
|
10601
12995
|
anchorRef: message.id === latestAssistantId ? latestAssistantRef : void 0,
|
|
10602
12996
|
onFollow: (kind, url) => recordClick(message.id, kind, url),
|
|
10603
12997
|
onFollowUp: sendPrompt,
|
|
10604
|
-
onFeedback: isSharedView ? void 0 : (rating, detail) => submitFeedback(message.id, rating, detail)
|
|
12998
|
+
onFeedback: isSharedView ? void 0 : (rating, detail) => submitFeedback(message.id, rating, detail),
|
|
12999
|
+
onEscalate: canEscalate ? escalate : void 0,
|
|
13000
|
+
isLatestAnswer: message.id === latestAssistantId
|
|
10605
13001
|
},
|
|
10606
13002
|
message.id
|
|
10607
13003
|
)
|
|
@@ -10708,10 +13104,19 @@ function ExplorePage({
|
|
|
10708
13104
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10709
13105
|
"div",
|
|
10710
13106
|
{
|
|
13107
|
+
"data-boff-explore": "composer-field",
|
|
10711
13108
|
className: cn(
|
|
10712
13109
|
"flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
|
|
10713
13110
|
busy && "boff-explore-busy",
|
|
10714
|
-
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
|
|
13111
|
+
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring",
|
|
13112
|
+
// The halo is an invitation, and an invitation is only useful before it has
|
|
13113
|
+
// been accepted: while the conversation is empty, the composer is usable, and
|
|
13114
|
+
// nothing has been typed. Once any of those stops being true the class goes
|
|
13115
|
+
// and the box is an ordinary card again. `-quiet` keeps the ring but stops the
|
|
13116
|
+
// movement the moment there are characters in the field, so it does not pulse
|
|
13117
|
+
// at someone who is mid-sentence.
|
|
13118
|
+
showWelcome && !composerDisabled && !overLimit && "boff-explore-invite",
|
|
13119
|
+
showWelcome && draft.length > 0 && "boff-explore-invite-quiet"
|
|
10715
13120
|
),
|
|
10716
13121
|
children: [
|
|
10717
13122
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -15558,6 +17963,11 @@ function StoreProductDetailPage({
|
|
|
15558
17963
|
] });
|
|
15559
17964
|
}
|
|
15560
17965
|
|
|
17966
|
+
exports.ANSWERS_PATH = ANSWERS_PATH;
|
|
17967
|
+
exports.ANSWER_HEADING_SHIFT = ANSWER_HEADING_SHIFT;
|
|
17968
|
+
exports.ANSWER_PATH_PREFIX = ANSWER_PATH_PREFIX;
|
|
17969
|
+
exports.AnswerDetailPage = AnswerDetailPage;
|
|
17970
|
+
exports.AnswersPage = AnswersPage;
|
|
15561
17971
|
exports.BlogListPage = BlogListPage;
|
|
15562
17972
|
exports.BlogPostPage = BlogPostPage;
|
|
15563
17973
|
exports.Button = Button;
|
|
@@ -15577,12 +17987,16 @@ exports.ContractsPage = ContractsPage;
|
|
|
15577
17987
|
exports.DEFAULT_CONTACT_CATEGORIES = DEFAULT_CONTACT_CATEGORIES;
|
|
15578
17988
|
exports.DEFAULT_EXPLORE_EXAMPLE_PROMPTS = DEFAULT_EXPLORE_EXAMPLE_PROMPTS;
|
|
15579
17989
|
exports.ECOSYSTEM_PRODUCTS = ECOSYSTEM_PRODUCTS;
|
|
17990
|
+
exports.ESCALATE_EXPLORE_CONVERSATION_MUTATION = ESCALATE_EXPLORE_CONVERSATION_MUTATION;
|
|
15580
17991
|
exports.EXPLORE_CATALOG_QUERY = EXPLORE_CATALOG_QUERY;
|
|
15581
17992
|
exports.EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS = EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS;
|
|
17993
|
+
exports.EXPLORE_ESCALATION_NOTE_SOFT_MAX = EXPLORE_ESCALATION_NOTE_SOFT_MAX;
|
|
15582
17994
|
exports.EXPLORE_LOCALES = EXPLORE_LOCALES;
|
|
15583
17995
|
exports.EXPLORE_MESSAGE_QUERY = EXPLORE_MESSAGE_QUERY;
|
|
15584
17996
|
exports.EXPLORE_RECAPTCHA_ACTION = EXPLORE_RECAPTCHA_ACTION;
|
|
15585
17997
|
exports.ElectronDownloadLink = ElectronDownloadLink;
|
|
17998
|
+
exports.ExploreAnswerBody = ExploreAnswerBody;
|
|
17999
|
+
exports.ExploreAnswerStyles = ExploreAnswerStyles;
|
|
15586
18000
|
exports.ExploreCta = ExploreCta;
|
|
15587
18001
|
exports.ExplorePage = ExplorePage;
|
|
15588
18002
|
exports.FALLBACK_EXPLORE_LIMITS = FALLBACK_EXPLORE_LIMITS;
|
|
@@ -15592,6 +18006,7 @@ exports.LaunchCountdown = LaunchCountdown;
|
|
|
15592
18006
|
exports.Markdown = Markdown;
|
|
15593
18007
|
exports.NewsletterForm = NewsletterForm;
|
|
15594
18008
|
exports.NewsletterPage = NewsletterPage;
|
|
18009
|
+
exports.PUBLISHED_ANSWER_FIELDS = PUBLISHED_ANSWER_FIELDS;
|
|
15595
18010
|
exports.PageHead = PageHead;
|
|
15596
18011
|
exports.PartnersPage = PartnersPage;
|
|
15597
18012
|
exports.PressKitPage = PressKitPage;
|
|
@@ -15617,6 +18032,11 @@ exports.WaitlistPage = WaitlistPage;
|
|
|
15617
18032
|
exports.WebSDKClient = WebSDKClient;
|
|
15618
18033
|
exports.WebSDKProvider = WebSDKProvider;
|
|
15619
18034
|
exports.WebsiteSwitcher = WebsiteSwitcher;
|
|
18035
|
+
exports.answerPath = answerPath;
|
|
18036
|
+
exports.answerPlainText = answerPlainText;
|
|
18037
|
+
exports.answerSourceHost = answerSourceHost;
|
|
18038
|
+
exports.answerSpeechText = answerSpeechText;
|
|
18039
|
+
exports.answerStrings = answerStrings;
|
|
15620
18040
|
exports.buttonVariants = buttonVariants;
|
|
15621
18041
|
exports.classifyExploreError = classifyExploreError;
|
|
15622
18042
|
exports.cn = cn;
|
|
@@ -15625,20 +18045,30 @@ exports.detectElectronPlatform = detectElectronPlatform;
|
|
|
15625
18045
|
exports.fetchPublicJobPosting = fetchPublicJobPosting;
|
|
15626
18046
|
exports.fetchPublicJobPostings = fetchPublicJobPostings;
|
|
15627
18047
|
exports.fetchPublicJobPostingsForSubmission = fetchPublicJobPostingsForSubmission;
|
|
18048
|
+
exports.formatAnswerDate = formatAnswerDate;
|
|
15628
18049
|
exports.formatDownloads = formatDownloads;
|
|
15629
18050
|
exports.formatPrice = formatPrice2;
|
|
18051
|
+
exports.getAnswerBySlug = getAnswerBySlug;
|
|
15630
18052
|
exports.getConceptBySlug = getConceptBySlug;
|
|
15631
18053
|
exports.getRecaptchaV3Token = getRecaptchaV3Token;
|
|
18054
|
+
exports.inlineImageOrigins = inlineImageOrigins;
|
|
18055
|
+
exports.isInlineImageAllowed = isInlineImageAllowed;
|
|
18056
|
+
exports.isPublishedSourceUrl = isPublishedSourceUrl;
|
|
15632
18057
|
exports.isValidUrl = isValidUrl;
|
|
15633
18058
|
exports.loadRecaptchaV3 = loadRecaptchaV3;
|
|
18059
|
+
exports.looksLikeDeliverableEmail = looksLikeDeliverableEmail;
|
|
18060
|
+
exports.speechLocaleOf = speechLocaleOf;
|
|
18061
|
+
exports.stopSpeaking = stopSpeaking;
|
|
15634
18062
|
exports.useContentPage = useContentPage;
|
|
15635
18063
|
exports.useContentPages = useContentPages;
|
|
15636
18064
|
exports.useExploreChat = useExploreChat;
|
|
15637
18065
|
exports.useProduct = useProduct;
|
|
15638
18066
|
exports.useProductConfig = useProductConfig;
|
|
18067
|
+
exports.useProgressiveReveal = useProgressiveReveal;
|
|
15639
18068
|
exports.usePublicJobPosting = usePublicJobPosting;
|
|
15640
18069
|
exports.usePublicJobPostings = usePublicJobPostings;
|
|
15641
18070
|
exports.usePublicJobPostingsForSubmission = usePublicJobPostingsForSubmission;
|
|
18071
|
+
exports.useSpeechOutput = useSpeechOutput;
|
|
15642
18072
|
exports.useWebSDK = useWebSDK;
|
|
15643
18073
|
exports.useWebSDKConfig = useWebSDKConfig;
|
|
15644
18074
|
//# sourceMappingURL=index.js.map
|