@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.
Files changed (31) hide show
  1. package/dist/components/explore-cta.d.mts +10 -1
  2. package/dist/components/explore-cta.d.ts +10 -1
  3. package/dist/components/explore-cta.js +82 -74
  4. package/dist/components/explore-cta.js.map +1 -1
  5. package/dist/components/explore-cta.mjs +83 -75
  6. package/dist/components/explore-cta.mjs.map +1 -1
  7. package/dist/components/explore.d.mts +2 -2
  8. package/dist/components/explore.d.ts +2 -2
  9. package/dist/components/explore.js +590 -463
  10. package/dist/components/explore.js.map +1 -1
  11. package/dist/components/explore.mjs +591 -464
  12. package/dist/components/explore.mjs.map +1 -1
  13. package/dist/{explore-POqE7J8r.d.mts → explore-BRfKFfvI.d.mts} +21 -2
  14. package/dist/{explore-D6kon7uz.d.ts → explore-DkfcKgp6.d.ts} +21 -2
  15. package/dist/{explore-types-BB8HNFzX.d.mts → explore-types-_9UJu6EA.d.mts} +1 -1
  16. package/dist/{explore-types-BB8HNFzX.d.ts → explore-types-_9UJu6EA.d.ts} +1 -1
  17. package/dist/hooks/index.d.mts +2 -2
  18. package/dist/hooks/index.d.ts +2 -2
  19. package/dist/hooks/index.js +15 -9
  20. package/dist/hooks/index.js.map +1 -1
  21. package/dist/hooks/index.mjs +15 -9
  22. package/dist/hooks/index.mjs.map +1 -1
  23. package/dist/index.d.mts +123 -7
  24. package/dist/index.d.ts +123 -7
  25. package/dist/index.js +922 -117
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +922 -120
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/{use-progressive-reveal-Kr6DwGXG.d.mts → use-progressive-reveal-BFPWbEXy.d.mts} +25 -2
  30. package/dist/{use-progressive-reveal-BVJn9NIr.d.ts → use-progressive-reveal-C0hkdu_i.d.ts} +25 -2
  31. 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") return;
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("h1", { className: "mt-2 text-balance break-words text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
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
- } = useExploreChat({
13719
- productSlug,
13720
- pageUrl,
13721
- onSend,
13722
- // Locale-aware, so a catalog outage degrades to a translated welcome rather than an
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 (heightMode !== "viewport") return;
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
- }, [heightMode]);
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 (heightMode !== "viewport" || typeof window === "undefined") return;
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
- }, [heightMode, remeasure]);
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
- }, [busy, canSend, draft, overLimit, send, stopDictation]);
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 (heightMode === "viewport") {
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
- heightMode === "viewport" && "boff-explore-viewport",
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
- bakedCatalogJson ? /* @__PURE__ */ jsxRuntime.jsx(
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
- function ExploreCta({
14702
- variant,
14703
- href = "/explore",
14704
- label = "Ask AI",
14705
- className,
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
- onClick,
14708
- currentPath
15085
+ welcomeTitle,
15086
+ welcomeBody,
15087
+ explorePath,
15088
+ avatar,
15089
+ bottomOffset,
15090
+ zIndex,
15091
+ returnFocusRef,
15092
+ className
14709
15093
  }) {
14710
- const path = useCurrentPath(currentPath);
14711
- const isActive = samePath(path, href);
14712
- if (variant === "floating" && isActive) return null;
14713
- const handleClick = (event) => {
14714
- onClick?.();
14715
- if (!onNavigate) return;
14716
- if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {
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
- event.preventDefault();
14720
- onNavigate(href);
14721
- };
14722
- const classes = {
14723
- // A quiet icon control, deliberately NOT a second gradient pill: a header should carry one
14724
- // primary CTA ("Get started"), and a competing coloured button next to it reads as clutter.
14725
- // This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].
14726
- // The prominent, labelled entry point to /explore is the floating bubble, which is visible
14727
- // on every page without scrolling. `shrink-0` keeps it from squeezing the nav.
14728
- 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",
14729
- 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",
14730
- 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"
14731
- };
14732
- const hooks = {
14733
- header: "cta-header",
14734
- mobile: "cta-mobile",
14735
- floating: "cta-floating"
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
- "a",
15422
+ "div",
14739
15423
  {
14740
- "data-boff-explore": hooks[variant],
14741
- href,
14742
- onClick: handleClick,
14743
- "aria-label": label,
14744
- "aria-current": isActive ? "page" : void 0,
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
- classes[variant],
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
- lucideReact.Sparkles,
14753
- {
14754
- className: cn(
14755
- "shrink-0",
14756
- variant === "floating" ? "h-4 w-4" : variant === "header" ? "h-5 w-5" : "h-3.5 w-3.5"
14757
- ),
14758
- "aria-hidden": "true"
14759
- }
14760
- ),
14761
- /* @__PURE__ */ jsxRuntime.jsx(
14762
- "span",
14763
- {
14764
- className: cn(
14765
- variant === "floating" && "hidden sm:inline",
14766
- // Never labelled in the header — see the class comment above.
14767
- variant === "header" && "hidden"
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
- children: label
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;