@burdenoff/website-sdk 2026.1024.1 → 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/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 +590 -463
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +591 -464
- package/dist/components/explore.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 +922 -117
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +922 -120
- package/dist/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
|
@@ -6561,6 +6561,14 @@ var EN = {
|
|
|
6561
6561
|
closeVideo: "Close video",
|
|
6562
6562
|
enterFullScreen: "Full screen",
|
|
6563
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",
|
|
6564
6572
|
videoUnavailable: "This video can't be played right now.",
|
|
6565
6573
|
groundedIn: "What this answer is based on",
|
|
6566
6574
|
sourceCountOne: "1 source",
|
|
@@ -6669,6 +6677,14 @@ var ZH = {
|
|
|
6669
6677
|
closeVideo: "\u5173\u95ED\u89C6\u9891",
|
|
6670
6678
|
enterFullScreen: "\u5168\u5C4F",
|
|
6671
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",
|
|
6672
6688
|
videoUnavailable: "\u6682\u65F6\u65E0\u6CD5\u64AD\u653E\u6B64\u89C6\u9891\u3002",
|
|
6673
6689
|
groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
|
|
6674
6690
|
sourceCountOne: "1 \u4E2A\u6765\u6E90",
|
|
@@ -6773,6 +6789,14 @@ var HI = {
|
|
|
6773
6789
|
closeVideo: "\u0935\u0940\u0921\u093F\u092F\u094B \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6774
6790
|
enterFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928",
|
|
6775
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",
|
|
6776
6800
|
videoUnavailable: "\u092F\u0939 \u0935\u0940\u0921\u093F\u092F\u094B \u0905\u092D\u0940 \u0928\u0939\u0940\u0902 \u091A\u0932 \u0938\u0915\u0924\u093E\u0964",
|
|
6777
6801
|
groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
|
|
6778
6802
|
sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
|
|
@@ -6881,6 +6905,14 @@ var ES = {
|
|
|
6881
6905
|
closeVideo: "Cerrar v\xEDdeo",
|
|
6882
6906
|
enterFullScreen: "Pantalla completa",
|
|
6883
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",
|
|
6884
6916
|
videoUnavailable: "Ahora mismo no se puede reproducir este v\xEDdeo.",
|
|
6885
6917
|
groundedIn: "En qu\xE9 se basa esta respuesta",
|
|
6886
6918
|
sourceCountOne: "1 fuente",
|
|
@@ -6989,6 +7021,14 @@ var AR = {
|
|
|
6989
7021
|
closeVideo: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0641\u064A\u062F\u064A\u0648",
|
|
6990
7022
|
enterFullScreen: "\u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
|
|
6991
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",
|
|
6992
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.",
|
|
6993
7033
|
groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6994
7034
|
sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
|
|
@@ -7097,6 +7137,14 @@ var TA = {
|
|
|
7097
7137
|
closeVideo: "\u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1",
|
|
7098
7138
|
enterFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8",
|
|
7099
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",
|
|
7100
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.",
|
|
7101
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",
|
|
7102
7150
|
sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
|
|
@@ -10253,7 +10301,9 @@ function useExploreChat(options = {}) {
|
|
|
10253
10301
|
pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,
|
|
10254
10302
|
storageKey = DEFAULT_STORAGE_KEY,
|
|
10255
10303
|
persist = true,
|
|
10256
|
-
onSend
|
|
10304
|
+
onSend,
|
|
10305
|
+
enabled = true,
|
|
10306
|
+
shareToken: shareTokenOption
|
|
10257
10307
|
} = options;
|
|
10258
10308
|
const client = useWebSDK();
|
|
10259
10309
|
const { productId } = useWebSDKConfig();
|
|
@@ -10291,7 +10341,7 @@ function useExploreChat(options = {}) {
|
|
|
10291
10341
|
const [hasConversation, setHasConversation] = React.useState(false);
|
|
10292
10342
|
const shareTokenRef = React.useRef(void 0);
|
|
10293
10343
|
if (shareTokenRef.current === void 0) {
|
|
10294
|
-
shareTokenRef.current = readShareToken();
|
|
10344
|
+
shareTokenRef.current = shareTokenOption === void 0 ? readShareToken() : shareTokenOption;
|
|
10295
10345
|
}
|
|
10296
10346
|
const isSharedView = shareTokenRef.current !== null;
|
|
10297
10347
|
const catalogRef = React.useRef(catalog);
|
|
@@ -10329,6 +10379,7 @@ function useExploreChat(options = {}) {
|
|
|
10329
10379
|
};
|
|
10330
10380
|
}, []);
|
|
10331
10381
|
React.useEffect(() => {
|
|
10382
|
+
if (!enabled) return;
|
|
10332
10383
|
const shareToken = shareTokenRef.current;
|
|
10333
10384
|
if (!shareToken) return;
|
|
10334
10385
|
let cancelled = false;
|
|
@@ -10363,8 +10414,9 @@ function useExploreChat(options = {}) {
|
|
|
10363
10414
|
return () => {
|
|
10364
10415
|
cancelled = true;
|
|
10365
10416
|
};
|
|
10366
|
-
}, [client]);
|
|
10417
|
+
}, [client, enabled]);
|
|
10367
10418
|
React.useEffect(() => {
|
|
10419
|
+
if (!enabled) return;
|
|
10368
10420
|
if (shareTokenRef.current !== null) return;
|
|
10369
10421
|
if (!persist) {
|
|
10370
10422
|
setHydrated(true);
|
|
@@ -10389,9 +10441,10 @@ function useExploreChat(options = {}) {
|
|
|
10389
10441
|
setTurnCount(turns);
|
|
10390
10442
|
}
|
|
10391
10443
|
setHydrated(true);
|
|
10392
|
-
}, [persist, rememberConversationToken, storageKey]);
|
|
10444
|
+
}, [persist, rememberConversationToken, storageKey, enabled]);
|
|
10393
10445
|
React.useEffect(() => {
|
|
10394
|
-
if (!persist || !hydrated || typeof window === "undefined")
|
|
10446
|
+
if (!persist || !hydrated || isSharedView || typeof window === "undefined")
|
|
10447
|
+
return;
|
|
10395
10448
|
try {
|
|
10396
10449
|
const payload = {
|
|
10397
10450
|
conversationToken: conversationTokenRef.current,
|
|
@@ -10405,10 +10458,10 @@ function useExploreChat(options = {}) {
|
|
|
10405
10458
|
window.localStorage.setItem(storageKey, JSON.stringify(payload));
|
|
10406
10459
|
} catch {
|
|
10407
10460
|
}
|
|
10408
|
-
}, [persist, hydrated, storageKey, messages, focusProduct]);
|
|
10461
|
+
}, [persist, hydrated, isSharedView, storageKey, messages, focusProduct]);
|
|
10409
10462
|
React.useEffect(() => {
|
|
10410
10463
|
messagesRef.current = messages;
|
|
10411
|
-
if (!persist || !hydrated) return;
|
|
10464
|
+
if (!persist || !hydrated || isSharedView) return;
|
|
10412
10465
|
const settled = messages.some(
|
|
10413
10466
|
(m) => m.role === "ASSISTANT" && (m.status === "COMPLETED" || m.status === "FAILED")
|
|
10414
10467
|
);
|
|
@@ -10420,8 +10473,9 @@ function useExploreChat(options = {}) {
|
|
|
10420
10473
|
focusProduct: focusProductRef.current
|
|
10421
10474
|
})
|
|
10422
10475
|
);
|
|
10423
|
-
}, [messages, persist, hydrated, storageKey]);
|
|
10476
|
+
}, [messages, persist, hydrated, isSharedView, storageKey]);
|
|
10424
10477
|
React.useEffect(() => {
|
|
10478
|
+
if (!enabled) return;
|
|
10425
10479
|
let cancelled = false;
|
|
10426
10480
|
const load = async () => {
|
|
10427
10481
|
const variables = { productSlug: productSlug ?? null };
|
|
@@ -10462,7 +10516,7 @@ function useExploreChat(options = {}) {
|
|
|
10462
10516
|
return () => {
|
|
10463
10517
|
cancelled = true;
|
|
10464
10518
|
};
|
|
10465
|
-
}, [client, productSlug, fallbackCatalog, bakedRaw]);
|
|
10519
|
+
}, [client, productSlug, fallbackCatalog, bakedRaw, enabled]);
|
|
10466
10520
|
const startPolling = React.useCallback(
|
|
10467
10521
|
(conversationToken, messageId) => {
|
|
10468
10522
|
pollGenerationRef.current += 1;
|
|
@@ -10959,6 +11013,56 @@ function makeOptimisticId() {
|
|
|
10959
11013
|
optimisticCounter += 1;
|
|
10960
11014
|
return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
|
|
10961
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
|
+
}
|
|
10962
11066
|
var DRAIN_TARGET_MS = 1200;
|
|
10963
11067
|
var MIN_CHARS_PER_SECOND = 90;
|
|
10964
11068
|
var MAX_CHARS_PER_SECOND = 2200;
|
|
@@ -13603,15 +13707,17 @@ function WelcomeState({
|
|
|
13603
13707
|
focusProduct,
|
|
13604
13708
|
onPrompt,
|
|
13605
13709
|
onFocus,
|
|
13606
|
-
disabled
|
|
13710
|
+
disabled,
|
|
13711
|
+
heading = "h1"
|
|
13607
13712
|
}) {
|
|
13713
|
+
const Heading = heading;
|
|
13608
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: [
|
|
13609
13715
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-rise text-center", children: [
|
|
13610
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: [
|
|
13611
13717
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" }),
|
|
13612
13718
|
T.badge
|
|
13613
13719
|
] }),
|
|
13614
|
-
/* @__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 }),
|
|
13615
13721
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mx-auto mt-2 max-w-2xl text-pretty text-sm leading-relaxed text-muted-foreground", children: body })
|
|
13616
13722
|
] }),
|
|
13617
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(
|
|
@@ -13666,19 +13772,36 @@ function exploreQuestionHref(question, base = "/explore") {
|
|
|
13666
13772
|
const joiner = base.includes("?") ? "&" : "?";
|
|
13667
13773
|
return `${base}${joiner}q=${encodeURIComponent(trimmed)}`;
|
|
13668
13774
|
}
|
|
13669
|
-
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({
|
|
13670
13789
|
seo,
|
|
13671
13790
|
productSlug,
|
|
13672
|
-
examplePrompts,
|
|
13673
13791
|
className,
|
|
13674
13792
|
heightMode = "viewport",
|
|
13675
13793
|
viewportOffset,
|
|
13676
13794
|
onNavigate,
|
|
13677
|
-
onSend,
|
|
13678
13795
|
welcomeTitle,
|
|
13679
13796
|
welcomeBody,
|
|
13680
|
-
locale
|
|
13797
|
+
locale,
|
|
13798
|
+
presentation = "page",
|
|
13799
|
+
active = true,
|
|
13800
|
+
explorePath = "/explore",
|
|
13801
|
+
conversation
|
|
13681
13802
|
}) {
|
|
13803
|
+
const panel = presentation === "panel";
|
|
13804
|
+
const viewportPage = !panel && heightMode === "viewport";
|
|
13682
13805
|
const pageUrl = React.useMemo(
|
|
13683
13806
|
() => typeof window === "undefined" ? void 0 : window.location.href,
|
|
13684
13807
|
[]
|
|
@@ -13714,26 +13837,21 @@ function ExplorePage({
|
|
|
13714
13837
|
escalate,
|
|
13715
13838
|
canEscalate,
|
|
13716
13839
|
createShareLink,
|
|
13717
|
-
isSharedView
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
// English one. `T.prompts` seeds the chips the same way.
|
|
13724
|
-
examplePrompts: examplePrompts ?? T.prompts,
|
|
13725
|
-
fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody }
|
|
13726
|
-
});
|
|
13727
|
-
const [draft, setDraft] = React.useState("");
|
|
13840
|
+
isSharedView,
|
|
13841
|
+
draft,
|
|
13842
|
+
setDraft,
|
|
13843
|
+
staged,
|
|
13844
|
+
setStaged
|
|
13845
|
+
} = conversation;
|
|
13728
13846
|
const textareaRef = React.useRef(null);
|
|
13729
13847
|
React.useEffect(() => {
|
|
13730
|
-
if (typeof window === "undefined") return;
|
|
13848
|
+
if (typeof window === "undefined" || panel) return;
|
|
13731
13849
|
const params = new URLSearchParams(window.location.search);
|
|
13732
13850
|
if (params.has("c")) return;
|
|
13733
13851
|
const question = params.get("q")?.trim();
|
|
13734
13852
|
if (!question) return;
|
|
13735
13853
|
setDraft(question.slice(0, EXPLORE_PREFILL_MAX_LENGTH));
|
|
13736
|
-
}, []);
|
|
13854
|
+
}, [panel, setDraft]);
|
|
13737
13855
|
const [historyOpen, setHistoryOpen] = React.useState(false);
|
|
13738
13856
|
const speechStopRef = React.useRef(() => void 0);
|
|
13739
13857
|
const stopDictation = React.useCallback(() => {
|
|
@@ -13749,8 +13867,12 @@ function ExplorePage({
|
|
|
13749
13867
|
}
|
|
13750
13868
|
});
|
|
13751
13869
|
speechStopRef.current = speech.stop;
|
|
13870
|
+
React.useEffect(() => {
|
|
13871
|
+
if (active) return;
|
|
13872
|
+
stopDictation();
|
|
13873
|
+
stopSpeaking();
|
|
13874
|
+
}, [active, stopDictation]);
|
|
13752
13875
|
const [disclaimerOpen, setDisclaimerOpen] = React.useState(false);
|
|
13753
|
-
const [staged, setStaged] = React.useState([]);
|
|
13754
13876
|
const [attachmentNotice, setAttachmentNotice] = React.useState(null);
|
|
13755
13877
|
const fileInputRef = React.useRef(null);
|
|
13756
13878
|
const stagedRef = React.useRef([]);
|
|
@@ -13803,7 +13925,7 @@ function ExplorePage({
|
|
|
13803
13925
|
const [bottomInset, setBottomInset] = React.useState(0);
|
|
13804
13926
|
const paneOffsetRef = React.useRef(0);
|
|
13805
13927
|
const measurePane = React.useCallback(() => {
|
|
13806
|
-
if (
|
|
13928
|
+
if (!viewportPage) return;
|
|
13807
13929
|
const el = rootRef.current;
|
|
13808
13930
|
if (!el) return;
|
|
13809
13931
|
const layoutHeight = window.innerHeight;
|
|
@@ -13822,7 +13944,7 @@ function ExplorePage({
|
|
|
13822
13944
|
paneOffsetRef.current = top;
|
|
13823
13945
|
setPaneOffset((current) => current === top ? current : top);
|
|
13824
13946
|
setBottomInset((current) => current === inset ? current : inset);
|
|
13825
|
-
}, [
|
|
13947
|
+
}, [viewportPage]);
|
|
13826
13948
|
const [chromeOverlap, setChromeOverlap] = React.useState(0);
|
|
13827
13949
|
const measureChrome = React.useCallback(() => {
|
|
13828
13950
|
const root = rootRef.current;
|
|
@@ -13847,7 +13969,7 @@ function ExplorePage({
|
|
|
13847
13969
|
measureChrome();
|
|
13848
13970
|
}, [measurePane, measureChrome]);
|
|
13849
13971
|
React.useEffect(() => {
|
|
13850
|
-
if (typeof window === "undefined") return;
|
|
13972
|
+
if (typeof window === "undefined" || panel) return;
|
|
13851
13973
|
let frame = 0;
|
|
13852
13974
|
const run = () => {
|
|
13853
13975
|
frame = 0;
|
|
@@ -13885,12 +14007,12 @@ function ExplorePage({
|
|
|
13885
14007
|
setBottomInset(0);
|
|
13886
14008
|
setChromeOverlap(0);
|
|
13887
14009
|
};
|
|
13888
|
-
}, [remeasure]);
|
|
14010
|
+
}, [remeasure, panel]);
|
|
13889
14011
|
React.useEffect(() => {
|
|
13890
14012
|
measureChrome();
|
|
13891
14013
|
}, [measureChrome, paneOffset, bottomInset]);
|
|
13892
14014
|
React.useEffect(() => {
|
|
13893
|
-
if (
|
|
14015
|
+
if (!viewportPage || typeof window === "undefined") return;
|
|
13894
14016
|
const { history: browserHistory } = window;
|
|
13895
14017
|
const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
|
|
13896
14018
|
if (previousRestoration !== null)
|
|
@@ -13958,14 +14080,14 @@ function ExplorePage({
|
|
|
13958
14080
|
if (previousRestoration !== null)
|
|
13959
14081
|
browserHistory.scrollRestoration = previousRestoration;
|
|
13960
14082
|
};
|
|
13961
|
-
}, [
|
|
14083
|
+
}, [viewportPage, remeasure]);
|
|
13962
14084
|
const handleScroll = React.useCallback(() => {
|
|
13963
14085
|
const el = scrollRef.current;
|
|
13964
14086
|
if (!el) return;
|
|
13965
14087
|
stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
|
|
13966
14088
|
}, []);
|
|
13967
14089
|
React.useEffect(() => {
|
|
13968
|
-
if (typeof window === "undefined") return;
|
|
14090
|
+
if (typeof window === "undefined" || panel) return;
|
|
13969
14091
|
let frame = 0;
|
|
13970
14092
|
const run = () => {
|
|
13971
14093
|
frame = 0;
|
|
@@ -13988,7 +14110,7 @@ function ExplorePage({
|
|
|
13988
14110
|
if (frame) window.cancelAnimationFrame(frame);
|
|
13989
14111
|
window.removeEventListener("scroll", schedule);
|
|
13990
14112
|
};
|
|
13991
|
-
}, []);
|
|
14113
|
+
}, [panel]);
|
|
13992
14114
|
const latestAssistantId = React.useMemo(() => {
|
|
13993
14115
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
13994
14116
|
const message = messages[i];
|
|
@@ -14004,7 +14126,7 @@ function ExplorePage({
|
|
|
14004
14126
|
if (!stickToBottomRef.current) return;
|
|
14005
14127
|
if (anchor.offsetHeight === 0) return;
|
|
14006
14128
|
alignedForRef.current = latestAssistantId;
|
|
14007
|
-
if (!pageOwnsScrolling(el)) {
|
|
14129
|
+
if (panel || !pageOwnsScrolling(el)) {
|
|
14008
14130
|
const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
|
|
14009
14131
|
el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
|
|
14010
14132
|
return;
|
|
@@ -14013,7 +14135,7 @@ function ExplorePage({
|
|
|
14013
14135
|
anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
|
|
14014
14136
|
);
|
|
14015
14137
|
if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
14016
|
-
}, [latestAssistantId, messages]);
|
|
14138
|
+
}, [latestAssistantId, messages, panel]);
|
|
14017
14139
|
React.useEffect(() => {
|
|
14018
14140
|
if (messages.length === 0) return;
|
|
14019
14141
|
if (!stickToBottomRef.current) return;
|
|
@@ -14021,7 +14143,7 @@ function ExplorePage({
|
|
|
14021
14143
|
return;
|
|
14022
14144
|
const el = scrollRef.current;
|
|
14023
14145
|
if (!el) return;
|
|
14024
|
-
if (!pageOwnsScrolling(el)) {
|
|
14146
|
+
if (panel || !pageOwnsScrolling(el)) {
|
|
14025
14147
|
el.scrollTop = el.scrollHeight;
|
|
14026
14148
|
return;
|
|
14027
14149
|
}
|
|
@@ -14030,7 +14152,7 @@ function ExplorePage({
|
|
|
14030
14152
|
dock.getBoundingClientRect().bottom - visualViewportHeight()
|
|
14031
14153
|
);
|
|
14032
14154
|
if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
14033
|
-
}, [activity, latestAssistantId, messages]);
|
|
14155
|
+
}, [activity, latestAssistantId, messages, panel]);
|
|
14034
14156
|
const handleShare = React.useCallback(async () => {
|
|
14035
14157
|
setShareLabel(T.copying);
|
|
14036
14158
|
setShareUrl(null);
|
|
@@ -14040,7 +14162,7 @@ function ExplorePage({
|
|
|
14040
14162
|
setTimeout(() => setShareLabel(T.share), 2500);
|
|
14041
14163
|
return;
|
|
14042
14164
|
}
|
|
14043
|
-
const url = new URL(pageUrl ?? window.location.href);
|
|
14165
|
+
const url = panel ? new URL(explorePath, window.location.href) : new URL(pageUrl ?? window.location.href);
|
|
14044
14166
|
url.search = "";
|
|
14045
14167
|
url.hash = "";
|
|
14046
14168
|
url.searchParams.set("c", token);
|
|
@@ -14056,6 +14178,8 @@ function ExplorePage({
|
|
|
14056
14178
|
}, [
|
|
14057
14179
|
createShareLink,
|
|
14058
14180
|
pageUrl,
|
|
14181
|
+
panel,
|
|
14182
|
+
explorePath,
|
|
14059
14183
|
T.copied,
|
|
14060
14184
|
T.copying,
|
|
14061
14185
|
T.share,
|
|
@@ -14084,12 +14208,15 @@ function ExplorePage({
|
|
|
14084
14208
|
});
|
|
14085
14209
|
return pickQueueRef.current;
|
|
14086
14210
|
},
|
|
14087
|
-
[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]
|
|
14088
14219
|
);
|
|
14089
|
-
const removeAttachment = React.useCallback((id) => {
|
|
14090
|
-
setStaged((prev) => prev.filter((entry) => entry.id !== id));
|
|
14091
|
-
setAttachmentNotice(null);
|
|
14092
|
-
}, []);
|
|
14093
14220
|
const submitDraft = React.useCallback(() => {
|
|
14094
14221
|
const text = draft.trim();
|
|
14095
14222
|
if (!text || overLimit || busy || !canSend) return;
|
|
@@ -14101,7 +14228,16 @@ function ExplorePage({
|
|
|
14101
14228
|
setStaged([]);
|
|
14102
14229
|
setAttachmentNotice(null);
|
|
14103
14230
|
textareaRef.current?.focus();
|
|
14104
|
-
}, [
|
|
14231
|
+
}, [
|
|
14232
|
+
busy,
|
|
14233
|
+
canSend,
|
|
14234
|
+
draft,
|
|
14235
|
+
overLimit,
|
|
14236
|
+
send,
|
|
14237
|
+
setDraft,
|
|
14238
|
+
setStaged,
|
|
14239
|
+
stopDictation
|
|
14240
|
+
]);
|
|
14105
14241
|
const sendPrompt = React.useCallback(
|
|
14106
14242
|
(prompt) => {
|
|
14107
14243
|
if (!canSend || busy) return;
|
|
@@ -14112,7 +14248,7 @@ function ExplorePage({
|
|
|
14112
14248
|
setStaged([]);
|
|
14113
14249
|
setAttachmentNotice(null);
|
|
14114
14250
|
},
|
|
14115
|
-
[busy, canSend, send]
|
|
14251
|
+
[busy, canSend, send, setDraft, setStaged]
|
|
14116
14252
|
);
|
|
14117
14253
|
const handleKeyDown = React.useCallback(
|
|
14118
14254
|
(event) => {
|
|
@@ -14134,7 +14270,7 @@ function ExplorePage({
|
|
|
14134
14270
|
[serverCatalogRaw]
|
|
14135
14271
|
);
|
|
14136
14272
|
const rootStyle = {};
|
|
14137
|
-
if (
|
|
14273
|
+
if (viewportPage) {
|
|
14138
14274
|
rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
|
|
14139
14275
|
if (bottomInset > 0) {
|
|
14140
14276
|
rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
|
|
@@ -14147,19 +14283,19 @@ function ExplorePage({
|
|
|
14147
14283
|
"div",
|
|
14148
14284
|
{
|
|
14149
14285
|
ref: rootRef,
|
|
14150
|
-
"data-boff-explore": "page",
|
|
14286
|
+
"data-boff-explore": panel ? "panel" : "page",
|
|
14151
14287
|
"data-phase": phase,
|
|
14152
14288
|
"data-locale": activeLocale,
|
|
14153
14289
|
dir: rtl ? "rtl" : void 0,
|
|
14154
14290
|
className: cn(
|
|
14155
|
-
"flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
|
|
14156
|
-
|
|
14157
|
-
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]",
|
|
14158
14294
|
className
|
|
14159
14295
|
),
|
|
14160
|
-
style: rootStyle,
|
|
14296
|
+
style: panel ? void 0 : rootStyle,
|
|
14161
14297
|
children: [
|
|
14162
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14298
|
+
panel ? null : /* @__PURE__ */ jsxRuntime.jsx(
|
|
14163
14299
|
PageHead,
|
|
14164
14300
|
{
|
|
14165
14301
|
title: seo?.title ?? T.seoTitle,
|
|
@@ -14172,7 +14308,11 @@ function ExplorePage({
|
|
|
14172
14308
|
),
|
|
14173
14309
|
/* @__PURE__ */ jsxRuntime.jsx(ProseStyles, {}),
|
|
14174
14310
|
/* @__PURE__ */ jsxRuntime.jsx(ExploreStyles, {}),
|
|
14175
|
-
|
|
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(
|
|
14176
14316
|
"script",
|
|
14177
14317
|
{
|
|
14178
14318
|
id: BAKED_CATALOG_ELEMENT_ID,
|
|
@@ -14192,7 +14332,7 @@ function ExplorePage({
|
|
|
14192
14332
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-4 w-4" })
|
|
14193
14333
|
}
|
|
14194
14334
|
),
|
|
14195
|
-
/* @__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 }),
|
|
14196
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,
|
|
14197
14337
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
14198
14338
|
Button,
|
|
@@ -14336,6 +14476,7 @@ function ExplorePage({
|
|
|
14336
14476
|
children: showWelcome ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14337
14477
|
WelcomeState,
|
|
14338
14478
|
{
|
|
14479
|
+
heading: panel ? "h2" : "h1",
|
|
14339
14480
|
strings: T,
|
|
14340
14481
|
title: resolvedTitle,
|
|
14341
14482
|
body: resolvedBody,
|
|
@@ -14698,77 +14839,738 @@ function samePath(a, b) {
|
|
|
14698
14839
|
const norm = (v) => v.length > 1 ? v.replace(/\/+$/, "") : v;
|
|
14699
14840
|
return norm(a) === norm(b);
|
|
14700
14841
|
}
|
|
14701
|
-
|
|
14702
|
-
|
|
14703
|
-
|
|
14704
|
-
|
|
14705
|
-
|
|
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,
|
|
14706
15084
|
onNavigate,
|
|
14707
|
-
|
|
14708
|
-
|
|
15085
|
+
welcomeTitle,
|
|
15086
|
+
welcomeBody,
|
|
15087
|
+
explorePath,
|
|
15088
|
+
avatar,
|
|
15089
|
+
bottomOffset,
|
|
15090
|
+
zIndex,
|
|
15091
|
+
returnFocusRef,
|
|
15092
|
+
className
|
|
14709
15093
|
}) {
|
|
14710
|
-
const
|
|
14711
|
-
const
|
|
14712
|
-
|
|
14713
|
-
const
|
|
14714
|
-
|
|
14715
|
-
|
|
14716
|
-
|
|
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
|
+
}
|
|
14717
15318
|
return;
|
|
14718
15319
|
}
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
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) }
|
|
14736
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
|
+
];
|
|
14737
15421
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14738
|
-
"
|
|
15422
|
+
"div",
|
|
14739
15423
|
{
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
14743
|
-
"aria-
|
|
14744
|
-
"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,
|
|
14745
15434
|
className: cn(
|
|
14746
|
-
|
|
14747
|
-
"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",
|
|
14748
15436
|
className
|
|
14749
15437
|
),
|
|
15438
|
+
style,
|
|
15439
|
+
onKeyDown,
|
|
14750
15440
|
children: [
|
|
14751
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
14755
|
-
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
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
|
+
}
|
|
14768
15492
|
),
|
|
14769
|
-
|
|
14770
|
-
|
|
14771
|
-
|
|
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
|
+
] })
|
|
14772
15574
|
]
|
|
14773
15575
|
}
|
|
14774
15576
|
);
|
|
@@ -19593,8 +20395,10 @@ exports.EXPLORE_RECAPTCHA_ACTION = EXPLORE_RECAPTCHA_ACTION;
|
|
|
19593
20395
|
exports.ElectronDownloadLink = ElectronDownloadLink;
|
|
19594
20396
|
exports.ExploreAnswerBody = ExploreAnswerBody;
|
|
19595
20397
|
exports.ExploreAnswerStyles = ExploreAnswerStyles;
|
|
20398
|
+
exports.ExploreChatProvider = ExploreChatProvider;
|
|
19596
20399
|
exports.ExploreCta = ExploreCta;
|
|
19597
20400
|
exports.ExplorePage = ExplorePage;
|
|
20401
|
+
exports.ExplorePanel = ExplorePanel;
|
|
19598
20402
|
exports.FALLBACK_EXPLORE_LIMITS = FALLBACK_EXPLORE_LIMITS;
|
|
19599
20403
|
exports.FOOTERLESS_ROUTES = FOOTERLESS_ROUTES;
|
|
19600
20404
|
exports.Input = Input;
|
|
@@ -19688,6 +20492,7 @@ exports.stopSpeaking = stopSpeaking;
|
|
|
19688
20492
|
exports.useContentPage = useContentPage;
|
|
19689
20493
|
exports.useContentPages = useContentPages;
|
|
19690
20494
|
exports.useExploreChat = useExploreChat;
|
|
20495
|
+
exports.useExploreConversation = useExploreConversation;
|
|
19691
20496
|
exports.useProduct = useProduct;
|
|
19692
20497
|
exports.useProductConfig = useProductConfig;
|
|
19693
20498
|
exports.useProgressiveReveal = useProgressiveReveal;
|