@burdenoff/website-sdk 2026.1021.4 → 2026.1026.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/contact.js +2 -1
- package/dist/components/contact.js.map +1 -1
- package/dist/components/contact.mjs +2 -1
- package/dist/components/contact.mjs.map +1 -1
- package/dist/components/explore-cta.d.mts +10 -1
- package/dist/components/explore-cta.d.ts +10 -1
- package/dist/components/explore-cta.js +82 -74
- package/dist/components/explore-cta.js.map +1 -1
- package/dist/components/explore-cta.mjs +83 -75
- package/dist/components/explore-cta.mjs.map +1 -1
- package/dist/components/explore.d.mts +2 -2
- package/dist/components/explore.d.ts +2 -2
- package/dist/components/explore.js +592 -464
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +593 -465
- package/dist/components/explore.mjs.map +1 -1
- package/dist/components/newsletter.js +2 -1
- package/dist/components/newsletter.js.map +1 -1
- package/dist/components/newsletter.mjs +2 -1
- package/dist/components/newsletter.mjs.map +1 -1
- package/dist/components/partners.js +2 -1
- package/dist/components/partners.js.map +1 -1
- package/dist/components/partners.mjs +2 -1
- package/dist/components/partners.mjs.map +1 -1
- package/dist/components/pricing.js +2 -1
- package/dist/components/pricing.js.map +1 -1
- package/dist/components/pricing.mjs +2 -1
- package/dist/components/pricing.mjs.map +1 -1
- package/dist/components/unsubscribe.js +2 -1
- package/dist/components/unsubscribe.js.map +1 -1
- package/dist/components/unsubscribe.mjs +2 -1
- package/dist/components/unsubscribe.mjs.map +1 -1
- package/dist/components/waitlist.js +2 -1
- package/dist/components/waitlist.js.map +1 -1
- package/dist/components/waitlist.mjs +2 -1
- package/dist/components/waitlist.mjs.map +1 -1
- package/dist/content/index.js +2 -1
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +2 -1
- package/dist/content/index.mjs.map +1 -1
- package/dist/{explore-POqE7J8r.d.mts → explore-BRfKFfvI.d.mts} +21 -2
- package/dist/{explore-D6kon7uz.d.ts → explore-DkfcKgp6.d.ts} +21 -2
- package/dist/{explore-types-BB8HNFzX.d.mts → explore-types-_9UJu6EA.d.mts} +1 -1
- package/dist/{explore-types-BB8HNFzX.d.ts → explore-types-_9UJu6EA.d.ts} +1 -1
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +15 -9
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +15 -9
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +123 -7
- package/dist/index.d.ts +123 -7
- package/dist/index.js +924 -118
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +924 -121
- package/dist/index.mjs.map +1 -1
- package/dist/seo/index.d.mts +11 -1
- package/dist/seo/index.d.ts +11 -1
- package/dist/seo/index.js +2 -1
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +2 -1
- package/dist/seo/index.mjs.map +1 -1
- package/dist/store/index.js +2 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/index.mjs +2 -1
- package/dist/store/index.mjs.map +1 -1
- package/dist/{use-progressive-reveal-Kr6DwGXG.d.mts → use-progressive-reveal-BFPWbEXy.d.mts} +25 -2
- package/dist/{use-progressive-reveal-BVJn9NIr.d.ts → use-progressive-reveal-C0hkdu_i.d.ts} +25 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -587,6 +587,7 @@ function PageHead({
|
|
|
587
587
|
locale = "en_US",
|
|
588
588
|
twitterHandle,
|
|
589
589
|
themeColor = "#000000",
|
|
590
|
+
author,
|
|
590
591
|
structuredData,
|
|
591
592
|
additionalMeta
|
|
592
593
|
}) {
|
|
@@ -599,7 +600,7 @@ function PageHead({
|
|
|
599
600
|
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "title", content: fullTitle }),
|
|
600
601
|
description && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "description", content: description }),
|
|
601
602
|
keywords && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "keywords", content: keywords }),
|
|
602
|
-
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "author", content:
|
|
603
|
+
author && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "author", content: author }),
|
|
603
604
|
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "robots", content: robots }),
|
|
604
605
|
resolvedUrl && /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "canonical", href: resolvedUrl }),
|
|
605
606
|
favicon && /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "icon", href: favicon }),
|
|
@@ -6560,6 +6561,14 @@ var EN = {
|
|
|
6560
6561
|
closeVideo: "Close video",
|
|
6561
6562
|
enterFullScreen: "Full screen",
|
|
6562
6563
|
exitFullScreen: "Exit full screen",
|
|
6564
|
+
panelTitle: "AI assistant",
|
|
6565
|
+
panelViews: "Assistant views",
|
|
6566
|
+
tabChat: "Chat",
|
|
6567
|
+
tabAvatar: "Avatar",
|
|
6568
|
+
closePanel: "Close",
|
|
6569
|
+
liveAvatar: "Live avatar",
|
|
6570
|
+
avatarComingSoon: "Live avatar coming soon",
|
|
6571
|
+
continueInChat: "Continue in Chat",
|
|
6563
6572
|
videoUnavailable: "This video can't be played right now.",
|
|
6564
6573
|
groundedIn: "What this answer is based on",
|
|
6565
6574
|
sourceCountOne: "1 source",
|
|
@@ -6668,6 +6677,14 @@ var ZH = {
|
|
|
6668
6677
|
closeVideo: "\u5173\u95ED\u89C6\u9891",
|
|
6669
6678
|
enterFullScreen: "\u5168\u5C4F",
|
|
6670
6679
|
exitFullScreen: "\u9000\u51FA\u5168\u5C4F",
|
|
6680
|
+
panelTitle: "AI \u52A9\u624B",
|
|
6681
|
+
panelViews: "\u52A9\u624B\u89C6\u56FE",
|
|
6682
|
+
tabChat: "\u804A\u5929",
|
|
6683
|
+
tabAvatar: "\u865A\u62DF\u5F62\u8C61",
|
|
6684
|
+
closePanel: "\u5173\u95ED",
|
|
6685
|
+
liveAvatar: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61",
|
|
6686
|
+
avatarComingSoon: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u5373\u5C06\u63A8\u51FA",
|
|
6687
|
+
continueInChat: "\u5728\u804A\u5929\u4E2D\u7EE7\u7EED",
|
|
6671
6688
|
videoUnavailable: "\u6682\u65F6\u65E0\u6CD5\u64AD\u653E\u6B64\u89C6\u9891\u3002",
|
|
6672
6689
|
groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
|
|
6673
6690
|
sourceCountOne: "1 \u4E2A\u6765\u6E90",
|
|
@@ -6772,6 +6789,14 @@ var HI = {
|
|
|
6772
6789
|
closeVideo: "\u0935\u0940\u0921\u093F\u092F\u094B \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6773
6790
|
enterFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928",
|
|
6774
6791
|
exitFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928 \u0938\u0947 \u092C\u093E\u0939\u0930 \u0928\u093F\u0915\u0932\u0947\u0902",
|
|
6792
|
+
panelTitle: "AI \u0938\u0939\u093E\u092F\u0915",
|
|
6793
|
+
panelViews: "\u0938\u0939\u093E\u092F\u0915 \u0926\u0943\u0936\u094D\u092F",
|
|
6794
|
+
tabChat: "\u091A\u0948\u091F",
|
|
6795
|
+
tabAvatar: "\u0905\u0935\u0924\u093E\u0930",
|
|
6796
|
+
closePanel: "\u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6797
|
+
liveAvatar: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930",
|
|
6798
|
+
avatarComingSoon: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u091C\u0932\u094D\u0926 \u0906 \u0930\u0939\u093E \u0939\u0948",
|
|
6799
|
+
continueInChat: "\u091A\u0948\u091F \u092E\u0947\u0902 \u091C\u093E\u0930\u0940 \u0930\u0916\u0947\u0902",
|
|
6775
6800
|
videoUnavailable: "\u092F\u0939 \u0935\u0940\u0921\u093F\u092F\u094B \u0905\u092D\u0940 \u0928\u0939\u0940\u0902 \u091A\u0932 \u0938\u0915\u0924\u093E\u0964",
|
|
6776
6801
|
groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
|
|
6777
6802
|
sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
|
|
@@ -6880,6 +6905,14 @@ var ES = {
|
|
|
6880
6905
|
closeVideo: "Cerrar v\xEDdeo",
|
|
6881
6906
|
enterFullScreen: "Pantalla completa",
|
|
6882
6907
|
exitFullScreen: "Salir de pantalla completa",
|
|
6908
|
+
panelTitle: "Asistente de IA",
|
|
6909
|
+
panelViews: "Vistas del asistente",
|
|
6910
|
+
tabChat: "Chat",
|
|
6911
|
+
tabAvatar: "Avatar",
|
|
6912
|
+
closePanel: "Cerrar",
|
|
6913
|
+
liveAvatar: "Avatar en vivo",
|
|
6914
|
+
avatarComingSoon: "Avatar en vivo: pr\xF3ximamente",
|
|
6915
|
+
continueInChat: "Continuar en el chat",
|
|
6883
6916
|
videoUnavailable: "Ahora mismo no se puede reproducir este v\xEDdeo.",
|
|
6884
6917
|
groundedIn: "En qu\xE9 se basa esta respuesta",
|
|
6885
6918
|
sourceCountOne: "1 fuente",
|
|
@@ -6988,6 +7021,14 @@ var AR = {
|
|
|
6988
7021
|
closeVideo: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0641\u064A\u062F\u064A\u0648",
|
|
6989
7022
|
enterFullScreen: "\u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
|
|
6990
7023
|
exitFullScreen: "\u0627\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
|
|
7024
|
+
panelTitle: "\u0645\u0633\u0627\u0639\u062F \u0627\u0644\u0630\u0643\u0627\u0621 \u0627\u0644\u0627\u0635\u0637\u0646\u0627\u0639\u064A",
|
|
7025
|
+
panelViews: "\u0637\u0631\u0642 \u0639\u0631\u0636 \u0627\u0644\u0645\u0633\u0627\u0639\u062F",
|
|
7026
|
+
tabChat: "\u062F\u0631\u062F\u0634\u0629",
|
|
7027
|
+
tabAvatar: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
|
|
7028
|
+
closePanel: "\u0625\u063A\u0644\u0627\u0642",
|
|
7029
|
+
liveAvatar: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631",
|
|
7030
|
+
avatarComingSoon: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631 \u0642\u0631\u064A\u0628\u064B\u0627",
|
|
7031
|
+
continueInChat: "\u0627\u0644\u0645\u062A\u0627\u0628\u0639\u0629 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629",
|
|
6991
7032
|
videoUnavailable: "\u062A\u0639\u0630\u0651\u0631 \u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u0627\u0644\u0622\u0646.",
|
|
6992
7033
|
groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6993
7034
|
sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
|
|
@@ -7096,6 +7137,14 @@ var TA = {
|
|
|
7096
7137
|
closeVideo: "\u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1",
|
|
7097
7138
|
enterFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8",
|
|
7098
7139
|
exitFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8\u0BAF\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BC7\u0BB1\u0BC1",
|
|
7140
|
+
panelTitle: "AI \u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD",
|
|
7141
|
+
panelViews: "\u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9A\u0BBF\u0B95\u0BB3\u0BCD",
|
|
7142
|
+
tabChat: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8",
|
|
7143
|
+
tabAvatar: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD",
|
|
7144
|
+
closePanel: "\u0BAE\u0BC2\u0B9F\u0BC1",
|
|
7145
|
+
liveAvatar: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD",
|
|
7146
|
+
avatarComingSoon: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BB5\u0BBF\u0BB0\u0BC8\u0BB5\u0BBF\u0BB2\u0BCD",
|
|
7147
|
+
continueInChat: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0BA4\u0BCA\u0B9F\u0BB0\u0BB5\u0BC1\u0BAE\u0BCD",
|
|
7099
7148
|
videoUnavailable: "\u0B87\u0BA8\u0BCD\u0BA4 \u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B87\u0BAF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
|
|
7100
7149
|
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",
|
|
7101
7150
|
sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
|
|
@@ -10252,7 +10301,9 @@ function useExploreChat(options = {}) {
|
|
|
10252
10301
|
pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,
|
|
10253
10302
|
storageKey = DEFAULT_STORAGE_KEY,
|
|
10254
10303
|
persist = true,
|
|
10255
|
-
onSend
|
|
10304
|
+
onSend,
|
|
10305
|
+
enabled = true,
|
|
10306
|
+
shareToken: shareTokenOption
|
|
10256
10307
|
} = options;
|
|
10257
10308
|
const client = useWebSDK();
|
|
10258
10309
|
const { productId } = useWebSDKConfig();
|
|
@@ -10290,7 +10341,7 @@ function useExploreChat(options = {}) {
|
|
|
10290
10341
|
const [hasConversation, setHasConversation] = React.useState(false);
|
|
10291
10342
|
const shareTokenRef = React.useRef(void 0);
|
|
10292
10343
|
if (shareTokenRef.current === void 0) {
|
|
10293
|
-
shareTokenRef.current = readShareToken();
|
|
10344
|
+
shareTokenRef.current = shareTokenOption === void 0 ? readShareToken() : shareTokenOption;
|
|
10294
10345
|
}
|
|
10295
10346
|
const isSharedView = shareTokenRef.current !== null;
|
|
10296
10347
|
const catalogRef = React.useRef(catalog);
|
|
@@ -10328,6 +10379,7 @@ function useExploreChat(options = {}) {
|
|
|
10328
10379
|
};
|
|
10329
10380
|
}, []);
|
|
10330
10381
|
React.useEffect(() => {
|
|
10382
|
+
if (!enabled) return;
|
|
10331
10383
|
const shareToken = shareTokenRef.current;
|
|
10332
10384
|
if (!shareToken) return;
|
|
10333
10385
|
let cancelled = false;
|
|
@@ -10362,8 +10414,9 @@ function useExploreChat(options = {}) {
|
|
|
10362
10414
|
return () => {
|
|
10363
10415
|
cancelled = true;
|
|
10364
10416
|
};
|
|
10365
|
-
}, [client]);
|
|
10417
|
+
}, [client, enabled]);
|
|
10366
10418
|
React.useEffect(() => {
|
|
10419
|
+
if (!enabled) return;
|
|
10367
10420
|
if (shareTokenRef.current !== null) return;
|
|
10368
10421
|
if (!persist) {
|
|
10369
10422
|
setHydrated(true);
|
|
@@ -10388,9 +10441,10 @@ function useExploreChat(options = {}) {
|
|
|
10388
10441
|
setTurnCount(turns);
|
|
10389
10442
|
}
|
|
10390
10443
|
setHydrated(true);
|
|
10391
|
-
}, [persist, rememberConversationToken, storageKey]);
|
|
10444
|
+
}, [persist, rememberConversationToken, storageKey, enabled]);
|
|
10392
10445
|
React.useEffect(() => {
|
|
10393
|
-
if (!persist || !hydrated || typeof window === "undefined")
|
|
10446
|
+
if (!persist || !hydrated || isSharedView || typeof window === "undefined")
|
|
10447
|
+
return;
|
|
10394
10448
|
try {
|
|
10395
10449
|
const payload = {
|
|
10396
10450
|
conversationToken: conversationTokenRef.current,
|
|
@@ -10404,10 +10458,10 @@ function useExploreChat(options = {}) {
|
|
|
10404
10458
|
window.localStorage.setItem(storageKey, JSON.stringify(payload));
|
|
10405
10459
|
} catch {
|
|
10406
10460
|
}
|
|
10407
|
-
}, [persist, hydrated, storageKey, messages, focusProduct]);
|
|
10461
|
+
}, [persist, hydrated, isSharedView, storageKey, messages, focusProduct]);
|
|
10408
10462
|
React.useEffect(() => {
|
|
10409
10463
|
messagesRef.current = messages;
|
|
10410
|
-
if (!persist || !hydrated) return;
|
|
10464
|
+
if (!persist || !hydrated || isSharedView) return;
|
|
10411
10465
|
const settled = messages.some(
|
|
10412
10466
|
(m) => m.role === "ASSISTANT" && (m.status === "COMPLETED" || m.status === "FAILED")
|
|
10413
10467
|
);
|
|
@@ -10419,8 +10473,9 @@ function useExploreChat(options = {}) {
|
|
|
10419
10473
|
focusProduct: focusProductRef.current
|
|
10420
10474
|
})
|
|
10421
10475
|
);
|
|
10422
|
-
}, [messages, persist, hydrated, storageKey]);
|
|
10476
|
+
}, [messages, persist, hydrated, isSharedView, storageKey]);
|
|
10423
10477
|
React.useEffect(() => {
|
|
10478
|
+
if (!enabled) return;
|
|
10424
10479
|
let cancelled = false;
|
|
10425
10480
|
const load = async () => {
|
|
10426
10481
|
const variables = { productSlug: productSlug ?? null };
|
|
@@ -10461,7 +10516,7 @@ function useExploreChat(options = {}) {
|
|
|
10461
10516
|
return () => {
|
|
10462
10517
|
cancelled = true;
|
|
10463
10518
|
};
|
|
10464
|
-
}, [client, productSlug, fallbackCatalog, bakedRaw]);
|
|
10519
|
+
}, [client, productSlug, fallbackCatalog, bakedRaw, enabled]);
|
|
10465
10520
|
const startPolling = React.useCallback(
|
|
10466
10521
|
(conversationToken, messageId) => {
|
|
10467
10522
|
pollGenerationRef.current += 1;
|
|
@@ -10958,6 +11013,56 @@ function makeOptimisticId() {
|
|
|
10958
11013
|
optimisticCounter += 1;
|
|
10959
11014
|
return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
|
|
10960
11015
|
}
|
|
11016
|
+
var ExploreConversationContext = React.createContext(null);
|
|
11017
|
+
function useExploreConversation(options = {}) {
|
|
11018
|
+
const {
|
|
11019
|
+
productSlug,
|
|
11020
|
+
locale,
|
|
11021
|
+
examplePrompts,
|
|
11022
|
+
onSend,
|
|
11023
|
+
pageUrl,
|
|
11024
|
+
enabled,
|
|
11025
|
+
shareToken
|
|
11026
|
+
} = options;
|
|
11027
|
+
const urlAtMount = React.useMemo(
|
|
11028
|
+
() => typeof window === "undefined" ? void 0 : window.location.href,
|
|
11029
|
+
[]
|
|
11030
|
+
);
|
|
11031
|
+
const T = React.useMemo(
|
|
11032
|
+
() => exploreStrings(resolveExploreLocale(locale)),
|
|
11033
|
+
[locale]
|
|
11034
|
+
);
|
|
11035
|
+
const chat = useExploreChat({
|
|
11036
|
+
productSlug,
|
|
11037
|
+
pageUrl: pageUrl ?? urlAtMount,
|
|
11038
|
+
onSend,
|
|
11039
|
+
// Locale-aware, so a catalog outage degrades to a translated welcome rather than an English one.
|
|
11040
|
+
examplePrompts: examplePrompts ?? T.prompts,
|
|
11041
|
+
fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody },
|
|
11042
|
+
...enabled === void 0 ? {} : { enabled },
|
|
11043
|
+
...shareToken === void 0 ? {} : { shareToken }
|
|
11044
|
+
});
|
|
11045
|
+
const [draft, setDraft] = React.useState("");
|
|
11046
|
+
const [staged, setStaged] = React.useState([]);
|
|
11047
|
+
return React.useMemo(
|
|
11048
|
+
() => ({ ...chat, draft, setDraft, staged, setStaged }),
|
|
11049
|
+
[chat, draft, staged]
|
|
11050
|
+
);
|
|
11051
|
+
}
|
|
11052
|
+
function ExploreChatProvider({
|
|
11053
|
+
enabled,
|
|
11054
|
+
children,
|
|
11055
|
+
...options
|
|
11056
|
+
}) {
|
|
11057
|
+
const [started, setStarted] = React.useState(enabled);
|
|
11058
|
+
if (enabled && !started) setStarted(true);
|
|
11059
|
+
const conversation = useExploreConversation({
|
|
11060
|
+
...options,
|
|
11061
|
+
// `enabled` as well as `started`: on the render that first sees `enabled`, the latch above has only been queued.
|
|
11062
|
+
enabled: enabled || started
|
|
11063
|
+
});
|
|
11064
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ExploreConversationContext.Provider, { value: conversation, children });
|
|
11065
|
+
}
|
|
10961
11066
|
var DRAIN_TARGET_MS = 1200;
|
|
10962
11067
|
var MIN_CHARS_PER_SECOND = 90;
|
|
10963
11068
|
var MAX_CHARS_PER_SECOND = 2200;
|
|
@@ -13602,15 +13707,17 @@ function WelcomeState({
|
|
|
13602
13707
|
focusProduct,
|
|
13603
13708
|
onPrompt,
|
|
13604
13709
|
onFocus,
|
|
13605
|
-
disabled
|
|
13710
|
+
disabled,
|
|
13711
|
+
heading = "h1"
|
|
13606
13712
|
}) {
|
|
13713
|
+
const Heading = heading;
|
|
13607
13714
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-aura mx-auto my-auto w-full max-w-3xl px-4 py-4 sm:py-5", children: [
|
|
13608
13715
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-rise text-center", children: [
|
|
13609
13716
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "boff-explore-hero-badge inline-flex items-center gap-1.5 rounded-full border border-border bg-muted px-3 py-1 text-xs font-medium text-muted-foreground", children: [
|
|
13610
13717
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" }),
|
|
13611
13718
|
T.badge
|
|
13612
13719
|
] }),
|
|
13613
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13720
|
+
/* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "mt-2 text-balance break-words text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
|
|
13614
13721
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mx-auto mt-2 max-w-2xl text-pretty text-sm leading-relaxed text-muted-foreground", children: body })
|
|
13615
13722
|
] }),
|
|
13616
13723
|
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "boff-explore-capabilities boff-explore-rise boff-explore-rise-1 mt-4 grid grid-cols-3 gap-2 sm:gap-2.5", children: CAPABILITIES.map(({ icon: Icon, body: capBody }, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -13665,19 +13772,36 @@ function exploreQuestionHref(question, base = "/explore") {
|
|
|
13665
13772
|
const joiner = base.includes("?") ? "&" : "?";
|
|
13666
13773
|
return `${base}${joiner}q=${encodeURIComponent(trimmed)}`;
|
|
13667
13774
|
}
|
|
13668
|
-
function ExplorePage({
|
|
13775
|
+
function ExplorePage(props) {
|
|
13776
|
+
const shared = React.useContext(ExploreConversationContext);
|
|
13777
|
+
return shared ? /* @__PURE__ */ jsxRuntime.jsx(ExploreView, { ...props, conversation: shared }) : /* @__PURE__ */ jsxRuntime.jsx(StandaloneExplorePage, { ...props });
|
|
13778
|
+
}
|
|
13779
|
+
function StandaloneExplorePage(props) {
|
|
13780
|
+
const conversation = useExploreConversation({
|
|
13781
|
+
productSlug: props.productSlug,
|
|
13782
|
+
locale: props.locale,
|
|
13783
|
+
examplePrompts: props.examplePrompts,
|
|
13784
|
+
onSend: props.onSend
|
|
13785
|
+
});
|
|
13786
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ExploreView, { ...props, conversation });
|
|
13787
|
+
}
|
|
13788
|
+
function ExploreView({
|
|
13669
13789
|
seo,
|
|
13670
13790
|
productSlug,
|
|
13671
|
-
examplePrompts,
|
|
13672
13791
|
className,
|
|
13673
13792
|
heightMode = "viewport",
|
|
13674
13793
|
viewportOffset,
|
|
13675
13794
|
onNavigate,
|
|
13676
|
-
onSend,
|
|
13677
13795
|
welcomeTitle,
|
|
13678
13796
|
welcomeBody,
|
|
13679
|
-
locale
|
|
13797
|
+
locale,
|
|
13798
|
+
presentation = "page",
|
|
13799
|
+
active = true,
|
|
13800
|
+
explorePath = "/explore",
|
|
13801
|
+
conversation
|
|
13680
13802
|
}) {
|
|
13803
|
+
const panel = presentation === "panel";
|
|
13804
|
+
const viewportPage = !panel && heightMode === "viewport";
|
|
13681
13805
|
const pageUrl = React.useMemo(
|
|
13682
13806
|
() => typeof window === "undefined" ? void 0 : window.location.href,
|
|
13683
13807
|
[]
|
|
@@ -13713,26 +13837,21 @@ function ExplorePage({
|
|
|
13713
13837
|
escalate,
|
|
13714
13838
|
canEscalate,
|
|
13715
13839
|
createShareLink,
|
|
13716
|
-
isSharedView
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
// English one. `T.prompts` seeds the chips the same way.
|
|
13723
|
-
examplePrompts: examplePrompts ?? T.prompts,
|
|
13724
|
-
fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody }
|
|
13725
|
-
});
|
|
13726
|
-
const [draft, setDraft] = React.useState("");
|
|
13840
|
+
isSharedView,
|
|
13841
|
+
draft,
|
|
13842
|
+
setDraft,
|
|
13843
|
+
staged,
|
|
13844
|
+
setStaged
|
|
13845
|
+
} = conversation;
|
|
13727
13846
|
const textareaRef = React.useRef(null);
|
|
13728
13847
|
React.useEffect(() => {
|
|
13729
|
-
if (typeof window === "undefined") return;
|
|
13848
|
+
if (typeof window === "undefined" || panel) return;
|
|
13730
13849
|
const params = new URLSearchParams(window.location.search);
|
|
13731
13850
|
if (params.has("c")) return;
|
|
13732
13851
|
const question = params.get("q")?.trim();
|
|
13733
13852
|
if (!question) return;
|
|
13734
13853
|
setDraft(question.slice(0, EXPLORE_PREFILL_MAX_LENGTH));
|
|
13735
|
-
}, []);
|
|
13854
|
+
}, [panel, setDraft]);
|
|
13736
13855
|
const [historyOpen, setHistoryOpen] = React.useState(false);
|
|
13737
13856
|
const speechStopRef = React.useRef(() => void 0);
|
|
13738
13857
|
const stopDictation = React.useCallback(() => {
|
|
@@ -13748,8 +13867,12 @@ function ExplorePage({
|
|
|
13748
13867
|
}
|
|
13749
13868
|
});
|
|
13750
13869
|
speechStopRef.current = speech.stop;
|
|
13870
|
+
React.useEffect(() => {
|
|
13871
|
+
if (active) return;
|
|
13872
|
+
stopDictation();
|
|
13873
|
+
stopSpeaking();
|
|
13874
|
+
}, [active, stopDictation]);
|
|
13751
13875
|
const [disclaimerOpen, setDisclaimerOpen] = React.useState(false);
|
|
13752
|
-
const [staged, setStaged] = React.useState([]);
|
|
13753
13876
|
const [attachmentNotice, setAttachmentNotice] = React.useState(null);
|
|
13754
13877
|
const fileInputRef = React.useRef(null);
|
|
13755
13878
|
const stagedRef = React.useRef([]);
|
|
@@ -13802,7 +13925,7 @@ function ExplorePage({
|
|
|
13802
13925
|
const [bottomInset, setBottomInset] = React.useState(0);
|
|
13803
13926
|
const paneOffsetRef = React.useRef(0);
|
|
13804
13927
|
const measurePane = React.useCallback(() => {
|
|
13805
|
-
if (
|
|
13928
|
+
if (!viewportPage) return;
|
|
13806
13929
|
const el = rootRef.current;
|
|
13807
13930
|
if (!el) return;
|
|
13808
13931
|
const layoutHeight = window.innerHeight;
|
|
@@ -13821,7 +13944,7 @@ function ExplorePage({
|
|
|
13821
13944
|
paneOffsetRef.current = top;
|
|
13822
13945
|
setPaneOffset((current) => current === top ? current : top);
|
|
13823
13946
|
setBottomInset((current) => current === inset ? current : inset);
|
|
13824
|
-
}, [
|
|
13947
|
+
}, [viewportPage]);
|
|
13825
13948
|
const [chromeOverlap, setChromeOverlap] = React.useState(0);
|
|
13826
13949
|
const measureChrome = React.useCallback(() => {
|
|
13827
13950
|
const root = rootRef.current;
|
|
@@ -13846,7 +13969,7 @@ function ExplorePage({
|
|
|
13846
13969
|
measureChrome();
|
|
13847
13970
|
}, [measurePane, measureChrome]);
|
|
13848
13971
|
React.useEffect(() => {
|
|
13849
|
-
if (typeof window === "undefined") return;
|
|
13972
|
+
if (typeof window === "undefined" || panel) return;
|
|
13850
13973
|
let frame = 0;
|
|
13851
13974
|
const run = () => {
|
|
13852
13975
|
frame = 0;
|
|
@@ -13884,12 +14007,12 @@ function ExplorePage({
|
|
|
13884
14007
|
setBottomInset(0);
|
|
13885
14008
|
setChromeOverlap(0);
|
|
13886
14009
|
};
|
|
13887
|
-
}, [remeasure]);
|
|
14010
|
+
}, [remeasure, panel]);
|
|
13888
14011
|
React.useEffect(() => {
|
|
13889
14012
|
measureChrome();
|
|
13890
14013
|
}, [measureChrome, paneOffset, bottomInset]);
|
|
13891
14014
|
React.useEffect(() => {
|
|
13892
|
-
if (
|
|
14015
|
+
if (!viewportPage || typeof window === "undefined") return;
|
|
13893
14016
|
const { history: browserHistory } = window;
|
|
13894
14017
|
const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
|
|
13895
14018
|
if (previousRestoration !== null)
|
|
@@ -13957,14 +14080,14 @@ function ExplorePage({
|
|
|
13957
14080
|
if (previousRestoration !== null)
|
|
13958
14081
|
browserHistory.scrollRestoration = previousRestoration;
|
|
13959
14082
|
};
|
|
13960
|
-
}, [
|
|
14083
|
+
}, [viewportPage, remeasure]);
|
|
13961
14084
|
const handleScroll = React.useCallback(() => {
|
|
13962
14085
|
const el = scrollRef.current;
|
|
13963
14086
|
if (!el) return;
|
|
13964
14087
|
stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
|
|
13965
14088
|
}, []);
|
|
13966
14089
|
React.useEffect(() => {
|
|
13967
|
-
if (typeof window === "undefined") return;
|
|
14090
|
+
if (typeof window === "undefined" || panel) return;
|
|
13968
14091
|
let frame = 0;
|
|
13969
14092
|
const run = () => {
|
|
13970
14093
|
frame = 0;
|
|
@@ -13987,7 +14110,7 @@ function ExplorePage({
|
|
|
13987
14110
|
if (frame) window.cancelAnimationFrame(frame);
|
|
13988
14111
|
window.removeEventListener("scroll", schedule);
|
|
13989
14112
|
};
|
|
13990
|
-
}, []);
|
|
14113
|
+
}, [panel]);
|
|
13991
14114
|
const latestAssistantId = React.useMemo(() => {
|
|
13992
14115
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
13993
14116
|
const message = messages[i];
|
|
@@ -14003,7 +14126,7 @@ function ExplorePage({
|
|
|
14003
14126
|
if (!stickToBottomRef.current) return;
|
|
14004
14127
|
if (anchor.offsetHeight === 0) return;
|
|
14005
14128
|
alignedForRef.current = latestAssistantId;
|
|
14006
|
-
if (!pageOwnsScrolling(el)) {
|
|
14129
|
+
if (panel || !pageOwnsScrolling(el)) {
|
|
14007
14130
|
const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
|
|
14008
14131
|
el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
|
|
14009
14132
|
return;
|
|
@@ -14012,7 +14135,7 @@ function ExplorePage({
|
|
|
14012
14135
|
anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
|
|
14013
14136
|
);
|
|
14014
14137
|
if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
14015
|
-
}, [latestAssistantId, messages]);
|
|
14138
|
+
}, [latestAssistantId, messages, panel]);
|
|
14016
14139
|
React.useEffect(() => {
|
|
14017
14140
|
if (messages.length === 0) return;
|
|
14018
14141
|
if (!stickToBottomRef.current) return;
|
|
@@ -14020,7 +14143,7 @@ function ExplorePage({
|
|
|
14020
14143
|
return;
|
|
14021
14144
|
const el = scrollRef.current;
|
|
14022
14145
|
if (!el) return;
|
|
14023
|
-
if (!pageOwnsScrolling(el)) {
|
|
14146
|
+
if (panel || !pageOwnsScrolling(el)) {
|
|
14024
14147
|
el.scrollTop = el.scrollHeight;
|
|
14025
14148
|
return;
|
|
14026
14149
|
}
|
|
@@ -14029,7 +14152,7 @@ function ExplorePage({
|
|
|
14029
14152
|
dock.getBoundingClientRect().bottom - visualViewportHeight()
|
|
14030
14153
|
);
|
|
14031
14154
|
if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
14032
|
-
}, [activity, latestAssistantId, messages]);
|
|
14155
|
+
}, [activity, latestAssistantId, messages, panel]);
|
|
14033
14156
|
const handleShare = React.useCallback(async () => {
|
|
14034
14157
|
setShareLabel(T.copying);
|
|
14035
14158
|
setShareUrl(null);
|
|
@@ -14039,7 +14162,7 @@ function ExplorePage({
|
|
|
14039
14162
|
setTimeout(() => setShareLabel(T.share), 2500);
|
|
14040
14163
|
return;
|
|
14041
14164
|
}
|
|
14042
|
-
const url = new URL(pageUrl ?? window.location.href);
|
|
14165
|
+
const url = panel ? new URL(explorePath, window.location.href) : new URL(pageUrl ?? window.location.href);
|
|
14043
14166
|
url.search = "";
|
|
14044
14167
|
url.hash = "";
|
|
14045
14168
|
url.searchParams.set("c", token);
|
|
@@ -14055,6 +14178,8 @@ function ExplorePage({
|
|
|
14055
14178
|
}, [
|
|
14056
14179
|
createShareLink,
|
|
14057
14180
|
pageUrl,
|
|
14181
|
+
panel,
|
|
14182
|
+
explorePath,
|
|
14058
14183
|
T.copied,
|
|
14059
14184
|
T.copying,
|
|
14060
14185
|
T.share,
|
|
@@ -14083,12 +14208,15 @@ function ExplorePage({
|
|
|
14083
14208
|
});
|
|
14084
14209
|
return pickQueueRef.current;
|
|
14085
14210
|
},
|
|
14086
|
-
[T]
|
|
14211
|
+
[T, setStaged]
|
|
14212
|
+
);
|
|
14213
|
+
const removeAttachment = React.useCallback(
|
|
14214
|
+
(id) => {
|
|
14215
|
+
setStaged((prev) => prev.filter((entry) => entry.id !== id));
|
|
14216
|
+
setAttachmentNotice(null);
|
|
14217
|
+
},
|
|
14218
|
+
[setStaged]
|
|
14087
14219
|
);
|
|
14088
|
-
const removeAttachment = React.useCallback((id) => {
|
|
14089
|
-
setStaged((prev) => prev.filter((entry) => entry.id !== id));
|
|
14090
|
-
setAttachmentNotice(null);
|
|
14091
|
-
}, []);
|
|
14092
14220
|
const submitDraft = React.useCallback(() => {
|
|
14093
14221
|
const text = draft.trim();
|
|
14094
14222
|
if (!text || overLimit || busy || !canSend) return;
|
|
@@ -14100,7 +14228,16 @@ function ExplorePage({
|
|
|
14100
14228
|
setStaged([]);
|
|
14101
14229
|
setAttachmentNotice(null);
|
|
14102
14230
|
textareaRef.current?.focus();
|
|
14103
|
-
}, [
|
|
14231
|
+
}, [
|
|
14232
|
+
busy,
|
|
14233
|
+
canSend,
|
|
14234
|
+
draft,
|
|
14235
|
+
overLimit,
|
|
14236
|
+
send,
|
|
14237
|
+
setDraft,
|
|
14238
|
+
setStaged,
|
|
14239
|
+
stopDictation
|
|
14240
|
+
]);
|
|
14104
14241
|
const sendPrompt = React.useCallback(
|
|
14105
14242
|
(prompt) => {
|
|
14106
14243
|
if (!canSend || busy) return;
|
|
@@ -14111,7 +14248,7 @@ function ExplorePage({
|
|
|
14111
14248
|
setStaged([]);
|
|
14112
14249
|
setAttachmentNotice(null);
|
|
14113
14250
|
},
|
|
14114
|
-
[busy, canSend, send]
|
|
14251
|
+
[busy, canSend, send, setDraft, setStaged]
|
|
14115
14252
|
);
|
|
14116
14253
|
const handleKeyDown = React.useCallback(
|
|
14117
14254
|
(event) => {
|
|
@@ -14133,7 +14270,7 @@ function ExplorePage({
|
|
|
14133
14270
|
[serverCatalogRaw]
|
|
14134
14271
|
);
|
|
14135
14272
|
const rootStyle = {};
|
|
14136
|
-
if (
|
|
14273
|
+
if (viewportPage) {
|
|
14137
14274
|
rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
|
|
14138
14275
|
if (bottomInset > 0) {
|
|
14139
14276
|
rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
|
|
@@ -14146,19 +14283,19 @@ function ExplorePage({
|
|
|
14146
14283
|
"div",
|
|
14147
14284
|
{
|
|
14148
14285
|
ref: rootRef,
|
|
14149
|
-
"data-boff-explore": "page",
|
|
14286
|
+
"data-boff-explore": panel ? "panel" : "page",
|
|
14150
14287
|
"data-phase": phase,
|
|
14151
14288
|
"data-locale": activeLocale,
|
|
14152
14289
|
dir: rtl ? "rtl" : void 0,
|
|
14153
14290
|
className: cn(
|
|
14154
|
-
"flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
|
|
14155
|
-
|
|
14156
|
-
heightMode === "auto" && "min-h-[70vh]",
|
|
14291
|
+
panel ? "boff-explore-panel flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden bg-background text-foreground" : "flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
|
|
14292
|
+
viewportPage && "boff-explore-viewport",
|
|
14293
|
+
!panel && heightMode === "auto" && "min-h-[70vh]",
|
|
14157
14294
|
className
|
|
14158
14295
|
),
|
|
14159
|
-
style: rootStyle,
|
|
14296
|
+
style: panel ? void 0 : rootStyle,
|
|
14160
14297
|
children: [
|
|
14161
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14298
|
+
panel ? null : /* @__PURE__ */ jsxRuntime.jsx(
|
|
14162
14299
|
PageHead,
|
|
14163
14300
|
{
|
|
14164
14301
|
title: seo?.title ?? T.seoTitle,
|
|
@@ -14171,7 +14308,11 @@ function ExplorePage({
|
|
|
14171
14308
|
),
|
|
14172
14309
|
/* @__PURE__ */ jsxRuntime.jsx(ProseStyles, {}),
|
|
14173
14310
|
/* @__PURE__ */ jsxRuntime.jsx(ExploreStyles, {}),
|
|
14174
|
-
|
|
14311
|
+
panel ? /* @__PURE__ */ jsxRuntime.jsx("style", { children: `.boff-explore-panel .boff-explore-scroll { container: boff-explore-pane / size; }
|
|
14312
|
+
@container boff-explore-pane (width < ${toRem(WELCOME_FIT_MIN_WIDTH_PX)}) {
|
|
14313
|
+
.boff-explore-panel .boff-explore-scroll .boff-explore-capabilities { display: none; }
|
|
14314
|
+
}` }) : null,
|
|
14315
|
+
!panel && bakedCatalogJson ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14175
14316
|
"script",
|
|
14176
14317
|
{
|
|
14177
14318
|
id: BAKED_CATALOG_ELEMENT_ID,
|
|
@@ -14191,7 +14332,7 @@ function ExplorePage({
|
|
|
14191
14332
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-4 w-4" })
|
|
14192
14333
|
}
|
|
14193
14334
|
),
|
|
14194
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-sm font-semibold", children: resolvedTitle }),
|
|
14335
|
+
panel ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-sm font-semibold", children: resolvedTitle }) : /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-sm font-semibold", children: resolvedTitle }),
|
|
14195
14336
|
focusedProductName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden shrink-0 rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-secondary-foreground sm:inline", children: focusedProductName }) : null,
|
|
14196
14337
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
14197
14338
|
Button,
|
|
@@ -14335,6 +14476,7 @@ function ExplorePage({
|
|
|
14335
14476
|
children: showWelcome ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14336
14477
|
WelcomeState,
|
|
14337
14478
|
{
|
|
14479
|
+
heading: panel ? "h2" : "h1",
|
|
14338
14480
|
strings: T,
|
|
14339
14481
|
title: resolvedTitle,
|
|
14340
14482
|
body: resolvedBody,
|
|
@@ -14697,77 +14839,738 @@ function samePath(a, b) {
|
|
|
14697
14839
|
const norm = (v) => v.length > 1 ? v.replace(/\/+$/, "") : v;
|
|
14698
14840
|
return norm(a) === norm(b);
|
|
14699
14841
|
}
|
|
14700
|
-
|
|
14701
|
-
|
|
14702
|
-
|
|
14703
|
-
|
|
14704
|
-
|
|
14842
|
+
var ExploreCta = React.forwardRef(
|
|
14843
|
+
function ExploreCta2({
|
|
14844
|
+
variant,
|
|
14845
|
+
href = "/explore",
|
|
14846
|
+
label = "Ask AI",
|
|
14847
|
+
className,
|
|
14848
|
+
onNavigate,
|
|
14849
|
+
onClick,
|
|
14850
|
+
currentPath,
|
|
14851
|
+
expanded,
|
|
14852
|
+
controls
|
|
14853
|
+
}, ref) {
|
|
14854
|
+
const path = useCurrentPath(currentPath);
|
|
14855
|
+
const isActive = samePath(path, href);
|
|
14856
|
+
if (variant === "floating" && isActive) return null;
|
|
14857
|
+
const handleClick = (event) => {
|
|
14858
|
+
onClick?.();
|
|
14859
|
+
if (!onNavigate) return;
|
|
14860
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {
|
|
14861
|
+
return;
|
|
14862
|
+
}
|
|
14863
|
+
event.preventDefault();
|
|
14864
|
+
onNavigate(href);
|
|
14865
|
+
};
|
|
14866
|
+
const classes = {
|
|
14867
|
+
// A quiet icon control, deliberately NOT a second gradient pill: a header should carry one
|
|
14868
|
+
// primary CTA ("Get started"), and a competing coloured button next to it reads as clutter.
|
|
14869
|
+
// This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].
|
|
14870
|
+
// The prominent, labelled entry point to /explore is the floating bubble, which is visible
|
|
14871
|
+
// on every page without scrolling. `shrink-0` keeps it from squeezing the nav.
|
|
14872
|
+
header: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
|
|
14873
|
+
mobile: "inline-flex w-full items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
|
|
14874
|
+
floating: "fixed bottom-5 right-5 z-40 inline-flex items-center gap-2 rounded-full bg-gradient-to-r from-primary to-primary/70 px-4 py-3 text-sm font-medium text-primary-foreground shadow-lg transition-opacity hover:opacity-90"
|
|
14875
|
+
};
|
|
14876
|
+
const hooks = {
|
|
14877
|
+
header: "cta-header",
|
|
14878
|
+
mobile: "cta-mobile",
|
|
14879
|
+
floating: "cta-floating"
|
|
14880
|
+
};
|
|
14881
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14882
|
+
"a",
|
|
14883
|
+
{
|
|
14884
|
+
ref,
|
|
14885
|
+
"data-boff-explore": hooks[variant],
|
|
14886
|
+
href,
|
|
14887
|
+
onClick: handleClick,
|
|
14888
|
+
"aria-label": label,
|
|
14889
|
+
"aria-current": isActive ? "page" : void 0,
|
|
14890
|
+
"aria-expanded": expanded,
|
|
14891
|
+
"aria-haspopup": expanded === void 0 ? void 0 : "dialog",
|
|
14892
|
+
"aria-controls": expanded === void 0 ? void 0 : controls,
|
|
14893
|
+
className: cn(
|
|
14894
|
+
classes[variant],
|
|
14895
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
14896
|
+
className
|
|
14897
|
+
),
|
|
14898
|
+
children: [
|
|
14899
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14900
|
+
lucideReact.Sparkles,
|
|
14901
|
+
{
|
|
14902
|
+
className: cn(
|
|
14903
|
+
"shrink-0",
|
|
14904
|
+
variant === "floating" ? "h-4 w-4" : variant === "header" ? "h-5 w-5" : "h-3.5 w-3.5"
|
|
14905
|
+
),
|
|
14906
|
+
"aria-hidden": "true"
|
|
14907
|
+
}
|
|
14908
|
+
),
|
|
14909
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14910
|
+
"span",
|
|
14911
|
+
{
|
|
14912
|
+
className: cn(
|
|
14913
|
+
variant === "floating" && "hidden sm:inline",
|
|
14914
|
+
// Never labelled in the header — see the class comment above.
|
|
14915
|
+
variant === "header" && "hidden"
|
|
14916
|
+
),
|
|
14917
|
+
children: label
|
|
14918
|
+
}
|
|
14919
|
+
)
|
|
14920
|
+
]
|
|
14921
|
+
}
|
|
14922
|
+
);
|
|
14923
|
+
}
|
|
14924
|
+
);
|
|
14925
|
+
var MARK_KEY = "boffExplorePanel";
|
|
14926
|
+
var POS_KEY = "boffExplorePanelPos";
|
|
14927
|
+
var DOC_KEY = "boffExplorePanelDoc";
|
|
14928
|
+
var DOC_ID = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
14929
|
+
var lastPos = 0;
|
|
14930
|
+
var hostMode = null;
|
|
14931
|
+
var NARROW_QUERY = "(max-width: 639px)";
|
|
14932
|
+
var TOUCH_FIRST_QUERY = "(hover: none) and (pointer: coarse)";
|
|
14933
|
+
var COMPOSER_FOCUS_TRIES = 15;
|
|
14934
|
+
var PANEL_CSS = `
|
|
14935
|
+
.boff-explore-shell {
|
|
14936
|
+
--boff-explore-shell-lift-at: max(var(--boff-explore-shell-lift, 0px), var(--boff-explore-shell-bottom, 0px));
|
|
14937
|
+
--boff-explore-shell-room-at: var(--boff-explore-shell-room, calc(100vh - var(--boff-explore-shell-bottom, 0px)));
|
|
14938
|
+
position: fixed;
|
|
14939
|
+
z-index: var(--boff-explore-shell-z, 50);
|
|
14940
|
+
display: flex;
|
|
14941
|
+
flex-direction: column;
|
|
14942
|
+
overflow: hidden;
|
|
14943
|
+
overscroll-behavior: contain;
|
|
14944
|
+
inset-inline-end: 1rem;
|
|
14945
|
+
bottom: calc(1rem + var(--boff-explore-shell-lift-at));
|
|
14946
|
+
width: min(26rem, calc(100vw - 2rem));
|
|
14947
|
+
height: min(40rem, calc(var(--boff-explore-shell-room-at) - 6rem));
|
|
14948
|
+
border-width: 1px;
|
|
14949
|
+
border-style: solid;
|
|
14950
|
+
border-radius: 1rem;
|
|
14951
|
+
}
|
|
14952
|
+
@supports (height: 100dvh) {
|
|
14953
|
+
.boff-explore-shell {
|
|
14954
|
+
--boff-explore-shell-room-at: var(--boff-explore-shell-room, calc(100dvh - var(--boff-explore-shell-bottom, 0px)));
|
|
14955
|
+
}
|
|
14956
|
+
}
|
|
14957
|
+
@media (max-width: 639px) {
|
|
14958
|
+
.boff-explore-shell[data-size="compact"] {
|
|
14959
|
+
inset-inline: 0;
|
|
14960
|
+
bottom: var(--boff-explore-shell-lift-at);
|
|
14961
|
+
width: auto;
|
|
14962
|
+
height: min(75vh, calc(var(--boff-explore-shell-room-at) - 4rem));
|
|
14963
|
+
border-width: 1px 0 0;
|
|
14964
|
+
border-radius: 1rem 1rem 0 0;
|
|
14965
|
+
}
|
|
14966
|
+
@supports (height: 100dvh) {
|
|
14967
|
+
.boff-explore-shell[data-size="compact"] {
|
|
14968
|
+
height: min(75dvh, calc(var(--boff-explore-shell-room-at) - 4rem));
|
|
14969
|
+
}
|
|
14970
|
+
}
|
|
14971
|
+
}
|
|
14972
|
+
.boff-explore-shell[data-size="expanded"] {
|
|
14973
|
+
inset: var(--boff-explore-shell-top, 0px) 0 var(--boff-explore-shell-lift-at) 0;
|
|
14974
|
+
width: auto;
|
|
14975
|
+
height: auto;
|
|
14976
|
+
border-width: 0;
|
|
14977
|
+
border-radius: 0;
|
|
14978
|
+
box-shadow: none;
|
|
14979
|
+
}
|
|
14980
|
+
.boff-explore-shell[data-open="false"] {
|
|
14981
|
+
visibility: hidden;
|
|
14982
|
+
content-visibility: hidden;
|
|
14983
|
+
}
|
|
14984
|
+
.boff-explore-shell:focus { outline: none; }
|
|
14985
|
+
`;
|
|
14986
|
+
function stateRecord() {
|
|
14987
|
+
const state = window.history.state;
|
|
14988
|
+
return state !== null && typeof state === "object" ? state : {};
|
|
14989
|
+
}
|
|
14990
|
+
function stampedHere() {
|
|
14991
|
+
return stateRecord()[DOC_KEY] === DOC_ID;
|
|
14992
|
+
}
|
|
14993
|
+
function readMark() {
|
|
14994
|
+
if (typeof window === "undefined" || !stampedHere()) return null;
|
|
14995
|
+
const mark = stateRecord()[MARK_KEY];
|
|
14996
|
+
return mark === "open" || mark === "expanded" ? mark : null;
|
|
14997
|
+
}
|
|
14998
|
+
function readPos() {
|
|
14999
|
+
if (typeof window === "undefined" || !stampedHere()) return null;
|
|
15000
|
+
const pos = stateRecord()[POS_KEY];
|
|
15001
|
+
return typeof pos === "number" ? pos : null;
|
|
15002
|
+
}
|
|
15003
|
+
function stamp() {
|
|
15004
|
+
if (typeof window === "undefined" || readPos() !== null) return;
|
|
15005
|
+
const rest = { ...stateRecord() };
|
|
15006
|
+
delete rest[MARK_KEY];
|
|
15007
|
+
delete rest[POS_KEY];
|
|
15008
|
+
delete rest[DOC_KEY];
|
|
15009
|
+
lastPos += 1;
|
|
15010
|
+
try {
|
|
15011
|
+
window.history.replaceState(
|
|
15012
|
+
{ ...rest, [POS_KEY]: lastPos, [DOC_KEY]: DOC_ID },
|
|
15013
|
+
""
|
|
15014
|
+
);
|
|
15015
|
+
} catch {
|
|
15016
|
+
}
|
|
15017
|
+
}
|
|
15018
|
+
function pushMark(mark) {
|
|
15019
|
+
const { history } = window;
|
|
15020
|
+
const mode = "scrollRestoration" in history ? history.scrollRestoration : null;
|
|
15021
|
+
try {
|
|
15022
|
+
if (mode !== null) history.scrollRestoration = "manual";
|
|
15023
|
+
lastPos += 1;
|
|
15024
|
+
history.pushState(
|
|
15025
|
+
{
|
|
15026
|
+
...stateRecord(),
|
|
15027
|
+
[MARK_KEY]: mark,
|
|
15028
|
+
[POS_KEY]: lastPos,
|
|
15029
|
+
[DOC_KEY]: DOC_ID
|
|
15030
|
+
},
|
|
15031
|
+
""
|
|
15032
|
+
);
|
|
15033
|
+
return true;
|
|
15034
|
+
} catch {
|
|
15035
|
+
return false;
|
|
15036
|
+
} finally {
|
|
15037
|
+
if (mode !== null) history.scrollRestoration = mode;
|
|
15038
|
+
}
|
|
15039
|
+
}
|
|
15040
|
+
function restoreScrollMode(mode, then) {
|
|
15041
|
+
const { history } = window;
|
|
15042
|
+
const put = () => {
|
|
15043
|
+
if (history.scrollRestoration === "manual")
|
|
15044
|
+
history.scrollRestoration = mode;
|
|
15045
|
+
then?.();
|
|
15046
|
+
};
|
|
15047
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
15048
|
+
window.setTimeout(put, 50);
|
|
15049
|
+
return;
|
|
15050
|
+
}
|
|
15051
|
+
window.requestAnimationFrame(() => window.requestAnimationFrame(put));
|
|
15052
|
+
}
|
|
15053
|
+
function closeInnerDialogs(shell) {
|
|
15054
|
+
let closed = false;
|
|
15055
|
+
document.querySelectorAll(
|
|
15056
|
+
'dialog[data-boff-explore="video-dialog"]'
|
|
15057
|
+
).forEach((dialog) => {
|
|
15058
|
+
if (!dialog.open) return;
|
|
15059
|
+
dialog.close();
|
|
15060
|
+
closed = true;
|
|
15061
|
+
});
|
|
15062
|
+
const disclaimer = shell?.querySelector(
|
|
15063
|
+
'[data-boff-explore="disclaimer-dialog"]'
|
|
15064
|
+
);
|
|
15065
|
+
if (disclaimer) {
|
|
15066
|
+
disclaimer.click();
|
|
15067
|
+
closed = true;
|
|
15068
|
+
}
|
|
15069
|
+
return closed;
|
|
15070
|
+
}
|
|
15071
|
+
function marksOnTop(mark) {
|
|
15072
|
+
if (mark === "expanded") return 2;
|
|
15073
|
+
return mark === "open" ? 1 : 0;
|
|
15074
|
+
}
|
|
15075
|
+
function matches(query) {
|
|
15076
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(query).matches;
|
|
15077
|
+
}
|
|
15078
|
+
function ExplorePanel({
|
|
15079
|
+
open,
|
|
15080
|
+
onOpenChange,
|
|
15081
|
+
id = "boff-explore-panel",
|
|
15082
|
+
productSlug,
|
|
15083
|
+
locale,
|
|
14705
15084
|
onNavigate,
|
|
14706
|
-
|
|
14707
|
-
|
|
15085
|
+
welcomeTitle,
|
|
15086
|
+
welcomeBody,
|
|
15087
|
+
explorePath,
|
|
15088
|
+
avatar,
|
|
15089
|
+
bottomOffset,
|
|
15090
|
+
zIndex,
|
|
15091
|
+
returnFocusRef,
|
|
15092
|
+
className
|
|
14708
15093
|
}) {
|
|
14709
|
-
const
|
|
14710
|
-
const
|
|
14711
|
-
|
|
14712
|
-
const
|
|
14713
|
-
|
|
14714
|
-
|
|
14715
|
-
|
|
15094
|
+
const resolvedLocale = resolveExploreLocale(locale);
|
|
15095
|
+
const T = React.useMemo(() => exploreStrings(resolvedLocale), [resolvedLocale]);
|
|
15096
|
+
const rtl = isRtlLocale(resolvedLocale);
|
|
15097
|
+
const uid = React.useId();
|
|
15098
|
+
const titleId = `${uid}-title`;
|
|
15099
|
+
const chatTabId = `${uid}-chat-tab`;
|
|
15100
|
+
const avatarTabId = `${uid}-avatar-tab`;
|
|
15101
|
+
const chatPaneId = `${uid}-chat`;
|
|
15102
|
+
const avatarPaneId = `${uid}-avatar`;
|
|
15103
|
+
const [mounted, setMounted] = React.useState(open);
|
|
15104
|
+
const [size, setSize] = React.useState("compact");
|
|
15105
|
+
const [view, setView] = React.useState("chat");
|
|
15106
|
+
const [focusRequest, setFocusRequest] = React.useState(
|
|
15107
|
+
open ? "in" : null
|
|
15108
|
+
);
|
|
15109
|
+
const [wasOpen, setWasOpen] = React.useState(open);
|
|
15110
|
+
if (open !== wasOpen) {
|
|
15111
|
+
setWasOpen(open);
|
|
15112
|
+
if (open) {
|
|
15113
|
+
setMounted(true);
|
|
15114
|
+
setFocusRequest("in");
|
|
15115
|
+
} else {
|
|
15116
|
+
setSize("compact");
|
|
15117
|
+
setFocusRequest("back");
|
|
15118
|
+
}
|
|
15119
|
+
}
|
|
15120
|
+
const shellRef = React.useRef(null);
|
|
15121
|
+
const chatPaneRef = React.useRef(null);
|
|
15122
|
+
const chatTabRef = React.useRef(null);
|
|
15123
|
+
const avatarTabRef = React.useRef(null);
|
|
15124
|
+
const ownPopsRef = React.useRef(0);
|
|
15125
|
+
const settlingRef = React.useRef(false);
|
|
15126
|
+
const afterPopRef = React.useRef([]);
|
|
15127
|
+
const markRef = React.useRef(null);
|
|
15128
|
+
const posRef = React.useRef(null);
|
|
15129
|
+
const hrefRef = React.useRef(null);
|
|
15130
|
+
const openRef = React.useRef(open);
|
|
15131
|
+
const onOpenChangeRef = React.useRef(onOpenChange);
|
|
15132
|
+
const lookedRef = React.useRef(false);
|
|
15133
|
+
const traverse = React.useCallback((delta) => {
|
|
15134
|
+
ownPopsRef.current += 1;
|
|
15135
|
+
window.history.go(delta);
|
|
15136
|
+
}, []);
|
|
15137
|
+
const push = React.useCallback((mark) => {
|
|
15138
|
+
const { history } = window;
|
|
15139
|
+
if ("scrollRestoration" in history && history.scrollRestoration !== "manual") {
|
|
15140
|
+
hostMode = history.scrollRestoration;
|
|
15141
|
+
}
|
|
15142
|
+
stamp();
|
|
15143
|
+
if (!pushMark(mark)) return false;
|
|
15144
|
+
markRef.current = mark;
|
|
15145
|
+
posRef.current = readPos();
|
|
15146
|
+
hrefRef.current = window.location.href;
|
|
15147
|
+
return true;
|
|
15148
|
+
}, []);
|
|
15149
|
+
const whenSettled = React.useCallback((work) => {
|
|
15150
|
+
if (ownPopsRef.current > 0 || settlingRef.current) {
|
|
15151
|
+
afterPopRef.current.push(work);
|
|
15152
|
+
} else {
|
|
15153
|
+
work();
|
|
15154
|
+
}
|
|
15155
|
+
}, []);
|
|
15156
|
+
const flush = React.useCallback(() => {
|
|
15157
|
+
settlingRef.current = false;
|
|
15158
|
+
while (afterPopRef.current.length > 0 && ownPopsRef.current === 0 && !settlingRef.current) {
|
|
15159
|
+
afterPopRef.current.shift()?.();
|
|
15160
|
+
}
|
|
15161
|
+
}, []);
|
|
15162
|
+
React.useEffect(() => {
|
|
15163
|
+
openRef.current = open;
|
|
15164
|
+
onOpenChangeRef.current = onOpenChange;
|
|
15165
|
+
});
|
|
15166
|
+
React.useEffect(() => {
|
|
15167
|
+
if (typeof window === "undefined") return;
|
|
15168
|
+
if (ownPopsRef.current > 0 || settlingRef.current) return;
|
|
15169
|
+
const pos = readPos();
|
|
15170
|
+
if (lookedRef.current && pos !== null && pos !== posRef.current) return;
|
|
15171
|
+
lookedRef.current = true;
|
|
15172
|
+
stamp();
|
|
15173
|
+
markRef.current = readMark();
|
|
15174
|
+
posRef.current = readPos();
|
|
15175
|
+
hrefRef.current = window.location.href;
|
|
15176
|
+
});
|
|
15177
|
+
React.useEffect(() => {
|
|
15178
|
+
if (typeof window === "undefined") return;
|
|
15179
|
+
whenSettled(() => {
|
|
15180
|
+
if (openRef.current) {
|
|
15181
|
+
if (readMark() === null) push("open");
|
|
15182
|
+
return;
|
|
15183
|
+
}
|
|
15184
|
+
closeInnerDialogs(shellRef.current);
|
|
15185
|
+
const count = marksOnTop(readMark());
|
|
15186
|
+
if (count > 0) traverse(-count);
|
|
15187
|
+
});
|
|
15188
|
+
}, [open, push, traverse, whenSettled]);
|
|
15189
|
+
React.useEffect(() => {
|
|
15190
|
+
if (typeof window === "undefined") return;
|
|
15191
|
+
const onPopState = () => {
|
|
15192
|
+
const open2 = openRef.current;
|
|
15193
|
+
const onOpenChange2 = onOpenChangeRef.current;
|
|
15194
|
+
const leftMark = markRef.current;
|
|
15195
|
+
const leftPos = posRef.current;
|
|
15196
|
+
const leftHref = hrefRef.current;
|
|
15197
|
+
const mark = readMark();
|
|
15198
|
+
const pos = readPos();
|
|
15199
|
+
markRef.current = mark;
|
|
15200
|
+
posRef.current = pos;
|
|
15201
|
+
hrefRef.current = window.location.href;
|
|
15202
|
+
const forward = pos !== null && leftPos !== null && pos > leftPos;
|
|
15203
|
+
const mode = hostMode;
|
|
15204
|
+
const restoring = leftMark !== null && mode !== null;
|
|
15205
|
+
if (ownPopsRef.current > 0) {
|
|
15206
|
+
ownPopsRef.current -= 1;
|
|
15207
|
+
if (ownPopsRef.current > 0) return;
|
|
15208
|
+
if (restoring) {
|
|
15209
|
+
settlingRef.current = true;
|
|
15210
|
+
restoreScrollMode(mode, flush);
|
|
15211
|
+
} else {
|
|
15212
|
+
flush();
|
|
15213
|
+
}
|
|
15214
|
+
return;
|
|
15215
|
+
}
|
|
15216
|
+
if (restoring) restoreScrollMode(mode);
|
|
15217
|
+
if (leftMark !== null && !forward) {
|
|
15218
|
+
if (open2 && closeInnerDialogs(shellRef.current)) {
|
|
15219
|
+
if (readMark() === null) push("open");
|
|
15220
|
+
if (leftMark === "expanded" && readMark() === "open") {
|
|
15221
|
+
push("expanded");
|
|
15222
|
+
}
|
|
15223
|
+
return;
|
|
15224
|
+
}
|
|
15225
|
+
setSize("compact");
|
|
15226
|
+
if (mark === null && open2) onOpenChange2(false);
|
|
15227
|
+
return;
|
|
15228
|
+
}
|
|
15229
|
+
if (leftHref !== null && window.location.href !== leftHref) {
|
|
15230
|
+
closeInnerDialogs(shellRef.current);
|
|
15231
|
+
}
|
|
15232
|
+
if (mark === null) return;
|
|
15233
|
+
if (forward) {
|
|
15234
|
+
setSize(mark === "expanded" ? "expanded" : "compact");
|
|
15235
|
+
if (!open2) onOpenChange2(true);
|
|
15236
|
+
return;
|
|
15237
|
+
}
|
|
15238
|
+
if (!open2) {
|
|
15239
|
+
traverse(-marksOnTop(mark));
|
|
15240
|
+
return;
|
|
15241
|
+
}
|
|
15242
|
+
setSize(mark === "expanded" ? "expanded" : "compact");
|
|
15243
|
+
};
|
|
15244
|
+
window.addEventListener("popstate", onPopState);
|
|
15245
|
+
return () => window.removeEventListener("popstate", onPopState);
|
|
15246
|
+
}, [flush, push, traverse]);
|
|
15247
|
+
React.useEffect(() => {
|
|
15248
|
+
if (!open || typeof window === "undefined") return;
|
|
15249
|
+
const viewport = window.visualViewport;
|
|
15250
|
+
const shell = shellRef.current;
|
|
15251
|
+
if (!viewport || !shell) return;
|
|
15252
|
+
const clear = () => {
|
|
15253
|
+
shell.style.removeProperty("--boff-explore-shell-lift");
|
|
15254
|
+
shell.style.removeProperty("--boff-explore-shell-room");
|
|
15255
|
+
shell.style.removeProperty("--boff-explore-shell-top");
|
|
15256
|
+
};
|
|
15257
|
+
const apply = () => {
|
|
15258
|
+
const covered = Math.max(
|
|
15259
|
+
0,
|
|
15260
|
+
Math.round(window.innerHeight - viewport.height - viewport.offsetTop)
|
|
15261
|
+
);
|
|
15262
|
+
const panned = viewport.offsetTop > 1;
|
|
15263
|
+
if (covered <= 1 && !panned) {
|
|
15264
|
+
clear();
|
|
15265
|
+
return;
|
|
15266
|
+
}
|
|
15267
|
+
shell.style.setProperty("--boff-explore-shell-lift", `${covered}px`);
|
|
15268
|
+
shell.style.setProperty(
|
|
15269
|
+
"--boff-explore-shell-room",
|
|
15270
|
+
`calc(${Math.round(viewport.height)}px - max(0px, var(--boff-explore-shell-bottom, 0px) - ${covered}px))`
|
|
15271
|
+
);
|
|
15272
|
+
shell.style.setProperty(
|
|
15273
|
+
"--boff-explore-shell-top",
|
|
15274
|
+
`${Math.max(0, Math.round(viewport.offsetTop))}px`
|
|
15275
|
+
);
|
|
15276
|
+
};
|
|
15277
|
+
apply();
|
|
15278
|
+
viewport.addEventListener("resize", apply);
|
|
15279
|
+
viewport.addEventListener("scroll", apply);
|
|
15280
|
+
return () => {
|
|
15281
|
+
viewport.removeEventListener("resize", apply);
|
|
15282
|
+
viewport.removeEventListener("scroll", apply);
|
|
15283
|
+
clear();
|
|
15284
|
+
};
|
|
15285
|
+
}, [open]);
|
|
15286
|
+
const focusComposerSoon = React.useCallback((from) => {
|
|
15287
|
+
let tries = 0;
|
|
15288
|
+
const next = (attempt2) => {
|
|
15289
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
15290
|
+
window.requestAnimationFrame(attempt2);
|
|
15291
|
+
} else {
|
|
15292
|
+
window.setTimeout(attempt2, 16);
|
|
15293
|
+
}
|
|
15294
|
+
};
|
|
15295
|
+
const attempt = () => {
|
|
15296
|
+
if (document.activeElement !== from) return;
|
|
15297
|
+
const composer = chatPaneRef.current?.querySelector(
|
|
15298
|
+
"textarea:not(:disabled)"
|
|
15299
|
+
);
|
|
15300
|
+
if (!composer) return;
|
|
15301
|
+
composer.focus();
|
|
15302
|
+
tries += 1;
|
|
15303
|
+
if (document.activeElement !== composer && tries < COMPOSER_FOCUS_TRIES) {
|
|
15304
|
+
next(attempt);
|
|
15305
|
+
}
|
|
15306
|
+
};
|
|
15307
|
+
next(attempt);
|
|
15308
|
+
}, []);
|
|
15309
|
+
React.useEffect(() => {
|
|
15310
|
+
if (focusRequest === null) return;
|
|
15311
|
+
setFocusRequest(null);
|
|
15312
|
+
const shell = shellRef.current;
|
|
15313
|
+
if (focusRequest === "back") {
|
|
15314
|
+
const active = document.activeElement;
|
|
15315
|
+
if (active === null || active === document.body || shell?.contains(active)) {
|
|
15316
|
+
returnFocusRef?.current?.focus();
|
|
15317
|
+
}
|
|
14716
15318
|
return;
|
|
14717
15319
|
}
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
15320
|
+
if (!shell) return;
|
|
15321
|
+
shell.focus();
|
|
15322
|
+
if (view === "chat" && !matches(TOUCH_FIRST_QUERY)) {
|
|
15323
|
+
focusComposerSoon(shell);
|
|
15324
|
+
}
|
|
15325
|
+
}, [focusComposerSoon, focusRequest, returnFocusRef, view]);
|
|
15326
|
+
const close = React.useCallback(() => onOpenChange(false), [onOpenChange]);
|
|
15327
|
+
const expand = React.useCallback(() => {
|
|
15328
|
+
setSize("expanded");
|
|
15329
|
+
whenSettled(() => {
|
|
15330
|
+
if (!openRef.current) return;
|
|
15331
|
+
if (readMark() === null) push("open");
|
|
15332
|
+
if (readMark() === "open") push("expanded");
|
|
15333
|
+
});
|
|
15334
|
+
}, [push, whenSettled]);
|
|
15335
|
+
const restore = React.useCallback(() => {
|
|
15336
|
+
setSize("compact");
|
|
15337
|
+
whenSettled(() => {
|
|
15338
|
+
if (readMark() === "expanded") traverse(-1);
|
|
15339
|
+
});
|
|
15340
|
+
}, [traverse, whenSettled]);
|
|
15341
|
+
const onKeyDown = React.useCallback(
|
|
15342
|
+
(event) => {
|
|
15343
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
15344
|
+
if (event.nativeEvent.isComposing || event.keyCode === 229) return;
|
|
15345
|
+
const shell = shellRef.current;
|
|
15346
|
+
if (!shell || !(event.target instanceof Node) || !shell.contains(event.target)) {
|
|
15347
|
+
return;
|
|
15348
|
+
}
|
|
15349
|
+
if (shell.querySelector('dialog[open], [role="dialog"][aria-modal="true"]')) {
|
|
15350
|
+
return;
|
|
15351
|
+
}
|
|
15352
|
+
event.preventDefault();
|
|
15353
|
+
if (size === "expanded") restore();
|
|
15354
|
+
else close();
|
|
15355
|
+
},
|
|
15356
|
+
[close, restore, size]
|
|
15357
|
+
);
|
|
15358
|
+
const navigate = React.useCallback(
|
|
15359
|
+
(path) => {
|
|
15360
|
+
if (!onNavigate) return;
|
|
15361
|
+
setSize("compact");
|
|
15362
|
+
const stayOpen = !matches(NARROW_QUERY);
|
|
15363
|
+
if (!stayOpen) onOpenChange(false);
|
|
15364
|
+
whenSettled(() => {
|
|
15365
|
+
const go = () => {
|
|
15366
|
+
onNavigate(path);
|
|
15367
|
+
if (stayOpen && openRef.current && readMark() === null) {
|
|
15368
|
+
push("open");
|
|
15369
|
+
}
|
|
15370
|
+
};
|
|
15371
|
+
const count = marksOnTop(readMark());
|
|
15372
|
+
if (count === 0) {
|
|
15373
|
+
go();
|
|
15374
|
+
return;
|
|
15375
|
+
}
|
|
15376
|
+
afterPopRef.current.push(go);
|
|
15377
|
+
traverse(-count);
|
|
15378
|
+
});
|
|
15379
|
+
},
|
|
15380
|
+
[onNavigate, onOpenChange, push, traverse, whenSettled]
|
|
15381
|
+
);
|
|
15382
|
+
const selectView = React.useCallback((next) => {
|
|
15383
|
+
setView(next);
|
|
15384
|
+
(next === "chat" ? chatTabRef : avatarTabRef).current?.focus();
|
|
15385
|
+
}, []);
|
|
15386
|
+
const continueInChat = React.useCallback(() => {
|
|
15387
|
+
setView("chat");
|
|
15388
|
+
const tab = chatTabRef.current;
|
|
15389
|
+
tab?.focus();
|
|
15390
|
+
focusComposerSoon(tab);
|
|
15391
|
+
}, [focusComposerSoon]);
|
|
15392
|
+
const onTabKeyDown = React.useCallback(
|
|
15393
|
+
(event) => {
|
|
15394
|
+
const other = view === "chat" ? "avatar" : "chat";
|
|
15395
|
+
const next = {
|
|
15396
|
+
ArrowLeft: other,
|
|
15397
|
+
ArrowRight: other,
|
|
15398
|
+
Home: "chat",
|
|
15399
|
+
End: "avatar"
|
|
15400
|
+
};
|
|
15401
|
+
const target = next[event.key];
|
|
15402
|
+
if (!target) return;
|
|
15403
|
+
event.preventDefault();
|
|
15404
|
+
selectView(target);
|
|
15405
|
+
},
|
|
15406
|
+
[selectView, view]
|
|
15407
|
+
);
|
|
15408
|
+
if (!mounted) return null;
|
|
15409
|
+
const style = {
|
|
15410
|
+
"--boff-explore-shell-bottom": bottomOffset ?? "0px",
|
|
15411
|
+
...zIndex === void 0 ? {} : { "--boff-explore-shell-z": String(zIndex) }
|
|
14735
15412
|
};
|
|
15413
|
+
const iconButton = "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
15414
|
+
const tabButton = "rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
15415
|
+
const expanded = size === "expanded";
|
|
15416
|
+
const sizeLabel = expanded ? T.exitFullScreen : T.enterFullScreen;
|
|
15417
|
+
const tabs = [
|
|
15418
|
+
{ key: "chat", id: chatTabId, pane: chatPaneId, label: T.tabChat },
|
|
15419
|
+
{ key: "avatar", id: avatarTabId, pane: avatarPaneId, label: T.tabAvatar }
|
|
15420
|
+
];
|
|
14736
15421
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14737
|
-
"
|
|
15422
|
+
"div",
|
|
14738
15423
|
{
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
"aria-
|
|
14743
|
-
"aria-
|
|
15424
|
+
ref: shellRef,
|
|
15425
|
+
id,
|
|
15426
|
+
role: "dialog",
|
|
15427
|
+
"aria-modal": "false",
|
|
15428
|
+
"aria-labelledby": titleId,
|
|
15429
|
+
tabIndex: -1,
|
|
15430
|
+
"data-boff-explore": "panel-shell",
|
|
15431
|
+
"data-open": open ? "true" : "false",
|
|
15432
|
+
"data-size": size,
|
|
15433
|
+
dir: rtl ? "rtl" : void 0,
|
|
14744
15434
|
className: cn(
|
|
14745
|
-
|
|
14746
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
15435
|
+
"boff-explore-shell border-border bg-background text-foreground shadow-2xl",
|
|
14747
15436
|
className
|
|
14748
15437
|
),
|
|
15438
|
+
style,
|
|
15439
|
+
onKeyDown,
|
|
14749
15440
|
children: [
|
|
14750
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
14755
|
-
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
|
|
14766
|
-
|
|
15441
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: PANEL_CSS }),
|
|
15442
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-border px-3 py-2", children: [
|
|
15443
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15444
|
+
"span",
|
|
15445
|
+
{
|
|
15446
|
+
id: titleId,
|
|
15447
|
+
className: "min-w-0 flex-1 truncate text-sm font-semibold",
|
|
15448
|
+
children: T.panelTitle
|
|
15449
|
+
}
|
|
15450
|
+
),
|
|
15451
|
+
avatar ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
15452
|
+
"div",
|
|
15453
|
+
{
|
|
15454
|
+
role: "tablist",
|
|
15455
|
+
"aria-label": T.panelViews,
|
|
15456
|
+
className: "inline-flex shrink-0 rounded-lg bg-muted p-0.5",
|
|
15457
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15458
|
+
"button",
|
|
15459
|
+
{
|
|
15460
|
+
ref: tab.key === "chat" ? chatTabRef : avatarTabRef,
|
|
15461
|
+
type: "button",
|
|
15462
|
+
role: "tab",
|
|
15463
|
+
id: tab.id,
|
|
15464
|
+
"aria-selected": view === tab.key,
|
|
15465
|
+
"aria-controls": tab.pane,
|
|
15466
|
+
tabIndex: view === tab.key ? 0 : -1,
|
|
15467
|
+
"data-boff-explore": `panel-tab-${tab.key}`,
|
|
15468
|
+
className: cn(
|
|
15469
|
+
tabButton,
|
|
15470
|
+
view === tab.key ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
15471
|
+
),
|
|
15472
|
+
onClick: () => selectView(tab.key),
|
|
15473
|
+
onKeyDown: onTabKeyDown,
|
|
15474
|
+
children: tab.label
|
|
15475
|
+
},
|
|
15476
|
+
tab.key
|
|
15477
|
+
))
|
|
15478
|
+
}
|
|
15479
|
+
) : null,
|
|
15480
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
15481
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15482
|
+
"button",
|
|
15483
|
+
{
|
|
15484
|
+
type: "button",
|
|
15485
|
+
"data-boff-explore": expanded ? "panel-restore" : "panel-expand",
|
|
15486
|
+
"aria-label": sizeLabel,
|
|
15487
|
+
title: sizeLabel,
|
|
15488
|
+
className: iconButton,
|
|
15489
|
+
onClick: expanded ? restore : expand,
|
|
15490
|
+
children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2, { className: "h-4 w-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
15491
|
+
}
|
|
14767
15492
|
),
|
|
14768
|
-
|
|
14769
|
-
|
|
14770
|
-
|
|
15493
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15494
|
+
"button",
|
|
15495
|
+
{
|
|
15496
|
+
type: "button",
|
|
15497
|
+
"data-boff-explore": "panel-close",
|
|
15498
|
+
"aria-label": T.closePanel,
|
|
15499
|
+
title: T.closePanel,
|
|
15500
|
+
className: iconButton,
|
|
15501
|
+
onClick: close,
|
|
15502
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
15503
|
+
}
|
|
15504
|
+
)
|
|
15505
|
+
] })
|
|
15506
|
+
] }),
|
|
15507
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col", children: [
|
|
15508
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15509
|
+
"div",
|
|
15510
|
+
{
|
|
15511
|
+
ref: chatPaneRef,
|
|
15512
|
+
id: chatPaneId,
|
|
15513
|
+
role: avatar ? "tabpanel" : void 0,
|
|
15514
|
+
"aria-labelledby": avatar ? chatTabId : void 0,
|
|
15515
|
+
"data-boff-explore": "panel-chat",
|
|
15516
|
+
className: cn(
|
|
15517
|
+
"flex min-h-0 flex-1 flex-col",
|
|
15518
|
+
view === "avatar" && "invisible"
|
|
15519
|
+
),
|
|
15520
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15521
|
+
ExplorePage,
|
|
15522
|
+
{
|
|
15523
|
+
presentation: "panel",
|
|
15524
|
+
active: open && view === "chat",
|
|
15525
|
+
productSlug,
|
|
15526
|
+
locale,
|
|
15527
|
+
onNavigate: onNavigate ? navigate : void 0,
|
|
15528
|
+
welcomeTitle,
|
|
15529
|
+
welcomeBody,
|
|
15530
|
+
explorePath
|
|
15531
|
+
}
|
|
15532
|
+
)
|
|
15533
|
+
}
|
|
15534
|
+
),
|
|
15535
|
+
avatar ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15536
|
+
"div",
|
|
15537
|
+
{
|
|
15538
|
+
id: avatarPaneId,
|
|
15539
|
+
role: "tabpanel",
|
|
15540
|
+
"aria-labelledby": avatarTabId,
|
|
15541
|
+
"data-boff-explore": "panel-avatar",
|
|
15542
|
+
className: cn(
|
|
15543
|
+
"absolute inset-0 flex-col items-center justify-center gap-4 overflow-y-auto bg-background p-6 text-center",
|
|
15544
|
+
view === "avatar" ? "flex" : "hidden"
|
|
15545
|
+
),
|
|
15546
|
+
children: [
|
|
15547
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15548
|
+
"img",
|
|
15549
|
+
{
|
|
15550
|
+
src: avatar.src,
|
|
15551
|
+
alt: avatar.name ? `${avatar.name}, ${T.liveAvatar}` : T.liveAvatar,
|
|
15552
|
+
loading: "lazy",
|
|
15553
|
+
decoding: "async",
|
|
15554
|
+
width: 128,
|
|
15555
|
+
height: 128,
|
|
15556
|
+
className: "h-32 w-32 rounded-full border border-border object-cover shadow-sm"
|
|
15557
|
+
}
|
|
15558
|
+
),
|
|
15559
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold", children: T.avatarComingSoon }),
|
|
15560
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15561
|
+
"button",
|
|
15562
|
+
{
|
|
15563
|
+
type: "button",
|
|
15564
|
+
"data-boff-explore": "panel-continue-chat",
|
|
15565
|
+
className: "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
15566
|
+
onClick: continueInChat,
|
|
15567
|
+
children: T.continueInChat
|
|
15568
|
+
}
|
|
15569
|
+
)
|
|
15570
|
+
]
|
|
15571
|
+
}
|
|
15572
|
+
) : null
|
|
15573
|
+
] })
|
|
14771
15574
|
]
|
|
14772
15575
|
}
|
|
14773
15576
|
);
|
|
@@ -19592,8 +20395,10 @@ exports.EXPLORE_RECAPTCHA_ACTION = EXPLORE_RECAPTCHA_ACTION;
|
|
|
19592
20395
|
exports.ElectronDownloadLink = ElectronDownloadLink;
|
|
19593
20396
|
exports.ExploreAnswerBody = ExploreAnswerBody;
|
|
19594
20397
|
exports.ExploreAnswerStyles = ExploreAnswerStyles;
|
|
20398
|
+
exports.ExploreChatProvider = ExploreChatProvider;
|
|
19595
20399
|
exports.ExploreCta = ExploreCta;
|
|
19596
20400
|
exports.ExplorePage = ExplorePage;
|
|
20401
|
+
exports.ExplorePanel = ExplorePanel;
|
|
19597
20402
|
exports.FALLBACK_EXPLORE_LIMITS = FALLBACK_EXPLORE_LIMITS;
|
|
19598
20403
|
exports.FOOTERLESS_ROUTES = FOOTERLESS_ROUTES;
|
|
19599
20404
|
exports.Input = Input;
|
|
@@ -19687,6 +20492,7 @@ exports.stopSpeaking = stopSpeaking;
|
|
|
19687
20492
|
exports.useContentPage = useContentPage;
|
|
19688
20493
|
exports.useContentPages = useContentPages;
|
|
19689
20494
|
exports.useExploreChat = useExploreChat;
|
|
20495
|
+
exports.useExploreConversation = useExploreConversation;
|
|
19690
20496
|
exports.useProduct = useProduct;
|
|
19691
20497
|
exports.useProductConfig = useProductConfig;
|
|
19692
20498
|
exports.useProgressiveReveal = useProgressiveReveal;
|