@burdenoff/website-sdk 2026.1021.4 → 2026.1026.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/components/contact.js +2 -1
  2. package/dist/components/contact.js.map +1 -1
  3. package/dist/components/contact.mjs +2 -1
  4. package/dist/components/contact.mjs.map +1 -1
  5. package/dist/components/explore-cta.d.mts +10 -1
  6. package/dist/components/explore-cta.d.ts +10 -1
  7. package/dist/components/explore-cta.js +82 -74
  8. package/dist/components/explore-cta.js.map +1 -1
  9. package/dist/components/explore-cta.mjs +83 -75
  10. package/dist/components/explore-cta.mjs.map +1 -1
  11. package/dist/components/explore.d.mts +2 -2
  12. package/dist/components/explore.d.ts +2 -2
  13. package/dist/components/explore.js +592 -464
  14. package/dist/components/explore.js.map +1 -1
  15. package/dist/components/explore.mjs +593 -465
  16. package/dist/components/explore.mjs.map +1 -1
  17. package/dist/components/newsletter.js +2 -1
  18. package/dist/components/newsletter.js.map +1 -1
  19. package/dist/components/newsletter.mjs +2 -1
  20. package/dist/components/newsletter.mjs.map +1 -1
  21. package/dist/components/partners.js +2 -1
  22. package/dist/components/partners.js.map +1 -1
  23. package/dist/components/partners.mjs +2 -1
  24. package/dist/components/partners.mjs.map +1 -1
  25. package/dist/components/pricing.js +2 -1
  26. package/dist/components/pricing.js.map +1 -1
  27. package/dist/components/pricing.mjs +2 -1
  28. package/dist/components/pricing.mjs.map +1 -1
  29. package/dist/components/unsubscribe.js +2 -1
  30. package/dist/components/unsubscribe.js.map +1 -1
  31. package/dist/components/unsubscribe.mjs +2 -1
  32. package/dist/components/unsubscribe.mjs.map +1 -1
  33. package/dist/components/waitlist.js +2 -1
  34. package/dist/components/waitlist.js.map +1 -1
  35. package/dist/components/waitlist.mjs +2 -1
  36. package/dist/components/waitlist.mjs.map +1 -1
  37. package/dist/content/index.js +2 -1
  38. package/dist/content/index.js.map +1 -1
  39. package/dist/content/index.mjs +2 -1
  40. package/dist/content/index.mjs.map +1 -1
  41. package/dist/{explore-POqE7J8r.d.mts → explore-BRfKFfvI.d.mts} +21 -2
  42. package/dist/{explore-D6kon7uz.d.ts → explore-DkfcKgp6.d.ts} +21 -2
  43. package/dist/{explore-types-BB8HNFzX.d.mts → explore-types-_9UJu6EA.d.mts} +1 -1
  44. package/dist/{explore-types-BB8HNFzX.d.ts → explore-types-_9UJu6EA.d.ts} +1 -1
  45. package/dist/hooks/index.d.mts +2 -2
  46. package/dist/hooks/index.d.ts +2 -2
  47. package/dist/hooks/index.js +15 -9
  48. package/dist/hooks/index.js.map +1 -1
  49. package/dist/hooks/index.mjs +15 -9
  50. package/dist/hooks/index.mjs.map +1 -1
  51. package/dist/index.d.mts +123 -7
  52. package/dist/index.d.ts +123 -7
  53. package/dist/index.js +924 -118
  54. package/dist/index.js.map +1 -1
  55. package/dist/index.mjs +924 -121
  56. package/dist/index.mjs.map +1 -1
  57. package/dist/seo/index.d.mts +11 -1
  58. package/dist/seo/index.d.ts +11 -1
  59. package/dist/seo/index.js +2 -1
  60. package/dist/seo/index.js.map +1 -1
  61. package/dist/seo/index.mjs +2 -1
  62. package/dist/seo/index.mjs.map +1 -1
  63. package/dist/store/index.js +2 -1
  64. package/dist/store/index.js.map +1 -1
  65. package/dist/store/index.mjs +2 -1
  66. package/dist/store/index.mjs.map +1 -1
  67. package/dist/{use-progressive-reveal-Kr6DwGXG.d.mts → use-progressive-reveal-BFPWbEXy.d.mts} +25 -2
  68. package/dist/{use-progressive-reveal-BVJn9NIr.d.ts → use-progressive-reveal-C0hkdu_i.d.ts} +25 -2
  69. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -587,6 +587,7 @@ function PageHead({
587
587
  locale = "en_US",
588
588
  twitterHandle,
589
589
  themeColor = "#000000",
590
+ author,
590
591
  structuredData,
591
592
  additionalMeta
592
593
  }) {
@@ -599,7 +600,7 @@ function PageHead({
599
600
  /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "title", content: fullTitle }),
600
601
  description && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "description", content: description }),
601
602
  keywords && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "keywords", content: keywords }),
602
- /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "author", content: "Burdenoff Consultancy Services Pvt Ltd" }),
603
+ author && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "author", content: author }),
603
604
  /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "robots", content: robots }),
604
605
  resolvedUrl && /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "canonical", href: resolvedUrl }),
605
606
  favicon && /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "icon", href: favicon }),
@@ -6560,6 +6561,14 @@ var EN = {
6560
6561
  closeVideo: "Close video",
6561
6562
  enterFullScreen: "Full screen",
6562
6563
  exitFullScreen: "Exit full screen",
6564
+ panelTitle: "AI assistant",
6565
+ panelViews: "Assistant views",
6566
+ tabChat: "Chat",
6567
+ tabAvatar: "Avatar",
6568
+ closePanel: "Close",
6569
+ liveAvatar: "Live avatar",
6570
+ avatarComingSoon: "Live avatar coming soon",
6571
+ continueInChat: "Continue in Chat",
6563
6572
  videoUnavailable: "This video can't be played right now.",
6564
6573
  groundedIn: "What this answer is based on",
6565
6574
  sourceCountOne: "1 source",
@@ -6668,6 +6677,14 @@ var ZH = {
6668
6677
  closeVideo: "\u5173\u95ED\u89C6\u9891",
6669
6678
  enterFullScreen: "\u5168\u5C4F",
6670
6679
  exitFullScreen: "\u9000\u51FA\u5168\u5C4F",
6680
+ panelTitle: "AI \u52A9\u624B",
6681
+ panelViews: "\u52A9\u624B\u89C6\u56FE",
6682
+ tabChat: "\u804A\u5929",
6683
+ tabAvatar: "\u865A\u62DF\u5F62\u8C61",
6684
+ closePanel: "\u5173\u95ED",
6685
+ liveAvatar: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61",
6686
+ avatarComingSoon: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u5373\u5C06\u63A8\u51FA",
6687
+ continueInChat: "\u5728\u804A\u5929\u4E2D\u7EE7\u7EED",
6671
6688
  videoUnavailable: "\u6682\u65F6\u65E0\u6CD5\u64AD\u653E\u6B64\u89C6\u9891\u3002",
6672
6689
  groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
6673
6690
  sourceCountOne: "1 \u4E2A\u6765\u6E90",
@@ -6772,6 +6789,14 @@ var HI = {
6772
6789
  closeVideo: "\u0935\u0940\u0921\u093F\u092F\u094B \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
6773
6790
  enterFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928",
6774
6791
  exitFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928 \u0938\u0947 \u092C\u093E\u0939\u0930 \u0928\u093F\u0915\u0932\u0947\u0902",
6792
+ panelTitle: "AI \u0938\u0939\u093E\u092F\u0915",
6793
+ panelViews: "\u0938\u0939\u093E\u092F\u0915 \u0926\u0943\u0936\u094D\u092F",
6794
+ tabChat: "\u091A\u0948\u091F",
6795
+ tabAvatar: "\u0905\u0935\u0924\u093E\u0930",
6796
+ closePanel: "\u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
6797
+ liveAvatar: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930",
6798
+ avatarComingSoon: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u091C\u0932\u094D\u0926 \u0906 \u0930\u0939\u093E \u0939\u0948",
6799
+ continueInChat: "\u091A\u0948\u091F \u092E\u0947\u0902 \u091C\u093E\u0930\u0940 \u0930\u0916\u0947\u0902",
6775
6800
  videoUnavailable: "\u092F\u0939 \u0935\u0940\u0921\u093F\u092F\u094B \u0905\u092D\u0940 \u0928\u0939\u0940\u0902 \u091A\u0932 \u0938\u0915\u0924\u093E\u0964",
6776
6801
  groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
6777
6802
  sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
@@ -6880,6 +6905,14 @@ var ES = {
6880
6905
  closeVideo: "Cerrar v\xEDdeo",
6881
6906
  enterFullScreen: "Pantalla completa",
6882
6907
  exitFullScreen: "Salir de pantalla completa",
6908
+ panelTitle: "Asistente de IA",
6909
+ panelViews: "Vistas del asistente",
6910
+ tabChat: "Chat",
6911
+ tabAvatar: "Avatar",
6912
+ closePanel: "Cerrar",
6913
+ liveAvatar: "Avatar en vivo",
6914
+ avatarComingSoon: "Avatar en vivo: pr\xF3ximamente",
6915
+ continueInChat: "Continuar en el chat",
6883
6916
  videoUnavailable: "Ahora mismo no se puede reproducir este v\xEDdeo.",
6884
6917
  groundedIn: "En qu\xE9 se basa esta respuesta",
6885
6918
  sourceCountOne: "1 fuente",
@@ -6988,6 +7021,14 @@ var AR = {
6988
7021
  closeVideo: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0641\u064A\u062F\u064A\u0648",
6989
7022
  enterFullScreen: "\u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
6990
7023
  exitFullScreen: "\u0627\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
7024
+ panelTitle: "\u0645\u0633\u0627\u0639\u062F \u0627\u0644\u0630\u0643\u0627\u0621 \u0627\u0644\u0627\u0635\u0637\u0646\u0627\u0639\u064A",
7025
+ panelViews: "\u0637\u0631\u0642 \u0639\u0631\u0636 \u0627\u0644\u0645\u0633\u0627\u0639\u062F",
7026
+ tabChat: "\u062F\u0631\u062F\u0634\u0629",
7027
+ tabAvatar: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
7028
+ closePanel: "\u0625\u063A\u0644\u0627\u0642",
7029
+ liveAvatar: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631",
7030
+ avatarComingSoon: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631 \u0642\u0631\u064A\u0628\u064B\u0627",
7031
+ continueInChat: "\u0627\u0644\u0645\u062A\u0627\u0628\u0639\u0629 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629",
6991
7032
  videoUnavailable: "\u062A\u0639\u0630\u0651\u0631 \u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u0627\u0644\u0622\u0646.",
6992
7033
  groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
6993
7034
  sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
@@ -7096,6 +7137,14 @@ var TA = {
7096
7137
  closeVideo: "\u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1",
7097
7138
  enterFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8",
7098
7139
  exitFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8\u0BAF\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BC7\u0BB1\u0BC1",
7140
+ panelTitle: "AI \u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD",
7141
+ panelViews: "\u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9A\u0BBF\u0B95\u0BB3\u0BCD",
7142
+ tabChat: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8",
7143
+ tabAvatar: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD",
7144
+ closePanel: "\u0BAE\u0BC2\u0B9F\u0BC1",
7145
+ liveAvatar: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD",
7146
+ avatarComingSoon: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BB5\u0BBF\u0BB0\u0BC8\u0BB5\u0BBF\u0BB2\u0BCD",
7147
+ continueInChat: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0BA4\u0BCA\u0B9F\u0BB0\u0BB5\u0BC1\u0BAE\u0BCD",
7099
7148
  videoUnavailable: "\u0B87\u0BA8\u0BCD\u0BA4 \u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B87\u0BAF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
7100
7149
  groundedIn: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B8E\u0BA4\u0BC8 \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BA4\u0BC1",
7101
7150
  sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
@@ -10252,7 +10301,9 @@ function useExploreChat(options = {}) {
10252
10301
  pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,
10253
10302
  storageKey = DEFAULT_STORAGE_KEY,
10254
10303
  persist = true,
10255
- onSend
10304
+ onSend,
10305
+ enabled = true,
10306
+ shareToken: shareTokenOption
10256
10307
  } = options;
10257
10308
  const client = useWebSDK();
10258
10309
  const { productId } = useWebSDKConfig();
@@ -10290,7 +10341,7 @@ function useExploreChat(options = {}) {
10290
10341
  const [hasConversation, setHasConversation] = React.useState(false);
10291
10342
  const shareTokenRef = React.useRef(void 0);
10292
10343
  if (shareTokenRef.current === void 0) {
10293
- shareTokenRef.current = readShareToken();
10344
+ shareTokenRef.current = shareTokenOption === void 0 ? readShareToken() : shareTokenOption;
10294
10345
  }
10295
10346
  const isSharedView = shareTokenRef.current !== null;
10296
10347
  const catalogRef = React.useRef(catalog);
@@ -10328,6 +10379,7 @@ function useExploreChat(options = {}) {
10328
10379
  };
10329
10380
  }, []);
10330
10381
  React.useEffect(() => {
10382
+ if (!enabled) return;
10331
10383
  const shareToken = shareTokenRef.current;
10332
10384
  if (!shareToken) return;
10333
10385
  let cancelled = false;
@@ -10362,8 +10414,9 @@ function useExploreChat(options = {}) {
10362
10414
  return () => {
10363
10415
  cancelled = true;
10364
10416
  };
10365
- }, [client]);
10417
+ }, [client, enabled]);
10366
10418
  React.useEffect(() => {
10419
+ if (!enabled) return;
10367
10420
  if (shareTokenRef.current !== null) return;
10368
10421
  if (!persist) {
10369
10422
  setHydrated(true);
@@ -10388,9 +10441,10 @@ function useExploreChat(options = {}) {
10388
10441
  setTurnCount(turns);
10389
10442
  }
10390
10443
  setHydrated(true);
10391
- }, [persist, rememberConversationToken, storageKey]);
10444
+ }, [persist, rememberConversationToken, storageKey, enabled]);
10392
10445
  React.useEffect(() => {
10393
- if (!persist || !hydrated || typeof window === "undefined") return;
10446
+ if (!persist || !hydrated || isSharedView || typeof window === "undefined")
10447
+ return;
10394
10448
  try {
10395
10449
  const payload = {
10396
10450
  conversationToken: conversationTokenRef.current,
@@ -10404,10 +10458,10 @@ function useExploreChat(options = {}) {
10404
10458
  window.localStorage.setItem(storageKey, JSON.stringify(payload));
10405
10459
  } catch {
10406
10460
  }
10407
- }, [persist, hydrated, storageKey, messages, focusProduct]);
10461
+ }, [persist, hydrated, isSharedView, storageKey, messages, focusProduct]);
10408
10462
  React.useEffect(() => {
10409
10463
  messagesRef.current = messages;
10410
- if (!persist || !hydrated) return;
10464
+ if (!persist || !hydrated || isSharedView) return;
10411
10465
  const settled = messages.some(
10412
10466
  (m) => m.role === "ASSISTANT" && (m.status === "COMPLETED" || m.status === "FAILED")
10413
10467
  );
@@ -10419,8 +10473,9 @@ function useExploreChat(options = {}) {
10419
10473
  focusProduct: focusProductRef.current
10420
10474
  })
10421
10475
  );
10422
- }, [messages, persist, hydrated, storageKey]);
10476
+ }, [messages, persist, hydrated, isSharedView, storageKey]);
10423
10477
  React.useEffect(() => {
10478
+ if (!enabled) return;
10424
10479
  let cancelled = false;
10425
10480
  const load = async () => {
10426
10481
  const variables = { productSlug: productSlug ?? null };
@@ -10461,7 +10516,7 @@ function useExploreChat(options = {}) {
10461
10516
  return () => {
10462
10517
  cancelled = true;
10463
10518
  };
10464
- }, [client, productSlug, fallbackCatalog, bakedRaw]);
10519
+ }, [client, productSlug, fallbackCatalog, bakedRaw, enabled]);
10465
10520
  const startPolling = React.useCallback(
10466
10521
  (conversationToken, messageId) => {
10467
10522
  pollGenerationRef.current += 1;
@@ -10958,6 +11013,56 @@ function makeOptimisticId() {
10958
11013
  optimisticCounter += 1;
10959
11014
  return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
10960
11015
  }
11016
+ var ExploreConversationContext = React.createContext(null);
11017
+ function useExploreConversation(options = {}) {
11018
+ const {
11019
+ productSlug,
11020
+ locale,
11021
+ examplePrompts,
11022
+ onSend,
11023
+ pageUrl,
11024
+ enabled,
11025
+ shareToken
11026
+ } = options;
11027
+ const urlAtMount = React.useMemo(
11028
+ () => typeof window === "undefined" ? void 0 : window.location.href,
11029
+ []
11030
+ );
11031
+ const T = React.useMemo(
11032
+ () => exploreStrings(resolveExploreLocale(locale)),
11033
+ [locale]
11034
+ );
11035
+ const chat = useExploreChat({
11036
+ productSlug,
11037
+ pageUrl: pageUrl ?? urlAtMount,
11038
+ onSend,
11039
+ // Locale-aware, so a catalog outage degrades to a translated welcome rather than an English one.
11040
+ examplePrompts: examplePrompts ?? T.prompts,
11041
+ fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody },
11042
+ ...enabled === void 0 ? {} : { enabled },
11043
+ ...shareToken === void 0 ? {} : { shareToken }
11044
+ });
11045
+ const [draft, setDraft] = React.useState("");
11046
+ const [staged, setStaged] = React.useState([]);
11047
+ return React.useMemo(
11048
+ () => ({ ...chat, draft, setDraft, staged, setStaged }),
11049
+ [chat, draft, staged]
11050
+ );
11051
+ }
11052
+ function ExploreChatProvider({
11053
+ enabled,
11054
+ children,
11055
+ ...options
11056
+ }) {
11057
+ const [started, setStarted] = React.useState(enabled);
11058
+ if (enabled && !started) setStarted(true);
11059
+ const conversation = useExploreConversation({
11060
+ ...options,
11061
+ // `enabled` as well as `started`: on the render that first sees `enabled`, the latch above has only been queued.
11062
+ enabled: enabled || started
11063
+ });
11064
+ return /* @__PURE__ */ jsxRuntime.jsx(ExploreConversationContext.Provider, { value: conversation, children });
11065
+ }
10961
11066
  var DRAIN_TARGET_MS = 1200;
10962
11067
  var MIN_CHARS_PER_SECOND = 90;
10963
11068
  var MAX_CHARS_PER_SECOND = 2200;
@@ -13602,15 +13707,17 @@ function WelcomeState({
13602
13707
  focusProduct,
13603
13708
  onPrompt,
13604
13709
  onFocus,
13605
- disabled
13710
+ disabled,
13711
+ heading = "h1"
13606
13712
  }) {
13713
+ const Heading = heading;
13607
13714
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-aura mx-auto my-auto w-full max-w-3xl px-4 py-4 sm:py-5", children: [
13608
13715
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-rise text-center", children: [
13609
13716
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "boff-explore-hero-badge inline-flex items-center gap-1.5 rounded-full border border-border bg-muted px-3 py-1 text-xs font-medium text-muted-foreground", children: [
13610
13717
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" }),
13611
13718
  T.badge
13612
13719
  ] }),
13613
- /* @__PURE__ */ jsxRuntime.jsx("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 }),
13614
13721
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mx-auto mt-2 max-w-2xl text-pretty text-sm leading-relaxed text-muted-foreground", children: body })
13615
13722
  ] }),
13616
13723
  /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "boff-explore-capabilities boff-explore-rise boff-explore-rise-1 mt-4 grid grid-cols-3 gap-2 sm:gap-2.5", children: CAPABILITIES.map(({ icon: Icon, body: capBody }, i) => /* @__PURE__ */ jsxRuntime.jsxs(
@@ -13665,19 +13772,36 @@ function exploreQuestionHref(question, base = "/explore") {
13665
13772
  const joiner = base.includes("?") ? "&" : "?";
13666
13773
  return `${base}${joiner}q=${encodeURIComponent(trimmed)}`;
13667
13774
  }
13668
- function ExplorePage({
13775
+ function ExplorePage(props) {
13776
+ const shared = React.useContext(ExploreConversationContext);
13777
+ return shared ? /* @__PURE__ */ jsxRuntime.jsx(ExploreView, { ...props, conversation: shared }) : /* @__PURE__ */ jsxRuntime.jsx(StandaloneExplorePage, { ...props });
13778
+ }
13779
+ function StandaloneExplorePage(props) {
13780
+ const conversation = useExploreConversation({
13781
+ productSlug: props.productSlug,
13782
+ locale: props.locale,
13783
+ examplePrompts: props.examplePrompts,
13784
+ onSend: props.onSend
13785
+ });
13786
+ return /* @__PURE__ */ jsxRuntime.jsx(ExploreView, { ...props, conversation });
13787
+ }
13788
+ function ExploreView({
13669
13789
  seo,
13670
13790
  productSlug,
13671
- examplePrompts,
13672
13791
  className,
13673
13792
  heightMode = "viewport",
13674
13793
  viewportOffset,
13675
13794
  onNavigate,
13676
- onSend,
13677
13795
  welcomeTitle,
13678
13796
  welcomeBody,
13679
- locale
13797
+ locale,
13798
+ presentation = "page",
13799
+ active = true,
13800
+ explorePath = "/explore",
13801
+ conversation
13680
13802
  }) {
13803
+ const panel = presentation === "panel";
13804
+ const viewportPage = !panel && heightMode === "viewport";
13681
13805
  const pageUrl = React.useMemo(
13682
13806
  () => typeof window === "undefined" ? void 0 : window.location.href,
13683
13807
  []
@@ -13713,26 +13837,21 @@ function ExplorePage({
13713
13837
  escalate,
13714
13838
  canEscalate,
13715
13839
  createShareLink,
13716
- isSharedView
13717
- } = useExploreChat({
13718
- productSlug,
13719
- pageUrl,
13720
- onSend,
13721
- // Locale-aware, so a catalog outage degrades to a translated welcome rather than an
13722
- // English one. `T.prompts` seeds the chips the same way.
13723
- examplePrompts: examplePrompts ?? T.prompts,
13724
- fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody }
13725
- });
13726
- const [draft, setDraft] = React.useState("");
13840
+ isSharedView,
13841
+ draft,
13842
+ setDraft,
13843
+ staged,
13844
+ setStaged
13845
+ } = conversation;
13727
13846
  const textareaRef = React.useRef(null);
13728
13847
  React.useEffect(() => {
13729
- if (typeof window === "undefined") return;
13848
+ if (typeof window === "undefined" || panel) return;
13730
13849
  const params = new URLSearchParams(window.location.search);
13731
13850
  if (params.has("c")) return;
13732
13851
  const question = params.get("q")?.trim();
13733
13852
  if (!question) return;
13734
13853
  setDraft(question.slice(0, EXPLORE_PREFILL_MAX_LENGTH));
13735
- }, []);
13854
+ }, [panel, setDraft]);
13736
13855
  const [historyOpen, setHistoryOpen] = React.useState(false);
13737
13856
  const speechStopRef = React.useRef(() => void 0);
13738
13857
  const stopDictation = React.useCallback(() => {
@@ -13748,8 +13867,12 @@ function ExplorePage({
13748
13867
  }
13749
13868
  });
13750
13869
  speechStopRef.current = speech.stop;
13870
+ React.useEffect(() => {
13871
+ if (active) return;
13872
+ stopDictation();
13873
+ stopSpeaking();
13874
+ }, [active, stopDictation]);
13751
13875
  const [disclaimerOpen, setDisclaimerOpen] = React.useState(false);
13752
- const [staged, setStaged] = React.useState([]);
13753
13876
  const [attachmentNotice, setAttachmentNotice] = React.useState(null);
13754
13877
  const fileInputRef = React.useRef(null);
13755
13878
  const stagedRef = React.useRef([]);
@@ -13802,7 +13925,7 @@ function ExplorePage({
13802
13925
  const [bottomInset, setBottomInset] = React.useState(0);
13803
13926
  const paneOffsetRef = React.useRef(0);
13804
13927
  const measurePane = React.useCallback(() => {
13805
- if (heightMode !== "viewport") return;
13928
+ if (!viewportPage) return;
13806
13929
  const el = rootRef.current;
13807
13930
  if (!el) return;
13808
13931
  const layoutHeight = window.innerHeight;
@@ -13821,7 +13944,7 @@ function ExplorePage({
13821
13944
  paneOffsetRef.current = top;
13822
13945
  setPaneOffset((current) => current === top ? current : top);
13823
13946
  setBottomInset((current) => current === inset ? current : inset);
13824
- }, [heightMode]);
13947
+ }, [viewportPage]);
13825
13948
  const [chromeOverlap, setChromeOverlap] = React.useState(0);
13826
13949
  const measureChrome = React.useCallback(() => {
13827
13950
  const root = rootRef.current;
@@ -13846,7 +13969,7 @@ function ExplorePage({
13846
13969
  measureChrome();
13847
13970
  }, [measurePane, measureChrome]);
13848
13971
  React.useEffect(() => {
13849
- if (typeof window === "undefined") return;
13972
+ if (typeof window === "undefined" || panel) return;
13850
13973
  let frame = 0;
13851
13974
  const run = () => {
13852
13975
  frame = 0;
@@ -13884,12 +14007,12 @@ function ExplorePage({
13884
14007
  setBottomInset(0);
13885
14008
  setChromeOverlap(0);
13886
14009
  };
13887
- }, [remeasure]);
14010
+ }, [remeasure, panel]);
13888
14011
  React.useEffect(() => {
13889
14012
  measureChrome();
13890
14013
  }, [measureChrome, paneOffset, bottomInset]);
13891
14014
  React.useEffect(() => {
13892
- if (heightMode !== "viewport" || typeof window === "undefined") return;
14015
+ if (!viewportPage || typeof window === "undefined") return;
13893
14016
  const { history: browserHistory } = window;
13894
14017
  const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
13895
14018
  if (previousRestoration !== null)
@@ -13957,14 +14080,14 @@ function ExplorePage({
13957
14080
  if (previousRestoration !== null)
13958
14081
  browserHistory.scrollRestoration = previousRestoration;
13959
14082
  };
13960
- }, [heightMode, remeasure]);
14083
+ }, [viewportPage, remeasure]);
13961
14084
  const handleScroll = React.useCallback(() => {
13962
14085
  const el = scrollRef.current;
13963
14086
  if (!el) return;
13964
14087
  stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
13965
14088
  }, []);
13966
14089
  React.useEffect(() => {
13967
- if (typeof window === "undefined") return;
14090
+ if (typeof window === "undefined" || panel) return;
13968
14091
  let frame = 0;
13969
14092
  const run = () => {
13970
14093
  frame = 0;
@@ -13987,7 +14110,7 @@ function ExplorePage({
13987
14110
  if (frame) window.cancelAnimationFrame(frame);
13988
14111
  window.removeEventListener("scroll", schedule);
13989
14112
  };
13990
- }, []);
14113
+ }, [panel]);
13991
14114
  const latestAssistantId = React.useMemo(() => {
13992
14115
  for (let i = messages.length - 1; i >= 0; i -= 1) {
13993
14116
  const message = messages[i];
@@ -14003,7 +14126,7 @@ function ExplorePage({
14003
14126
  if (!stickToBottomRef.current) return;
14004
14127
  if (anchor.offsetHeight === 0) return;
14005
14128
  alignedForRef.current = latestAssistantId;
14006
- if (!pageOwnsScrolling(el)) {
14129
+ if (panel || !pageOwnsScrolling(el)) {
14007
14130
  const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
14008
14131
  el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
14009
14132
  return;
@@ -14012,7 +14135,7 @@ function ExplorePage({
14012
14135
  anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
14013
14136
  );
14014
14137
  if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
14015
- }, [latestAssistantId, messages]);
14138
+ }, [latestAssistantId, messages, panel]);
14016
14139
  React.useEffect(() => {
14017
14140
  if (messages.length === 0) return;
14018
14141
  if (!stickToBottomRef.current) return;
@@ -14020,7 +14143,7 @@ function ExplorePage({
14020
14143
  return;
14021
14144
  const el = scrollRef.current;
14022
14145
  if (!el) return;
14023
- if (!pageOwnsScrolling(el)) {
14146
+ if (panel || !pageOwnsScrolling(el)) {
14024
14147
  el.scrollTop = el.scrollHeight;
14025
14148
  return;
14026
14149
  }
@@ -14029,7 +14152,7 @@ function ExplorePage({
14029
14152
  dock.getBoundingClientRect().bottom - visualViewportHeight()
14030
14153
  );
14031
14154
  if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
14032
- }, [activity, latestAssistantId, messages]);
14155
+ }, [activity, latestAssistantId, messages, panel]);
14033
14156
  const handleShare = React.useCallback(async () => {
14034
14157
  setShareLabel(T.copying);
14035
14158
  setShareUrl(null);
@@ -14039,7 +14162,7 @@ function ExplorePage({
14039
14162
  setTimeout(() => setShareLabel(T.share), 2500);
14040
14163
  return;
14041
14164
  }
14042
- const url = new URL(pageUrl ?? window.location.href);
14165
+ const url = panel ? new URL(explorePath, window.location.href) : new URL(pageUrl ?? window.location.href);
14043
14166
  url.search = "";
14044
14167
  url.hash = "";
14045
14168
  url.searchParams.set("c", token);
@@ -14055,6 +14178,8 @@ function ExplorePage({
14055
14178
  }, [
14056
14179
  createShareLink,
14057
14180
  pageUrl,
14181
+ panel,
14182
+ explorePath,
14058
14183
  T.copied,
14059
14184
  T.copying,
14060
14185
  T.share,
@@ -14083,12 +14208,15 @@ function ExplorePage({
14083
14208
  });
14084
14209
  return pickQueueRef.current;
14085
14210
  },
14086
- [T]
14211
+ [T, setStaged]
14212
+ );
14213
+ const removeAttachment = React.useCallback(
14214
+ (id) => {
14215
+ setStaged((prev) => prev.filter((entry) => entry.id !== id));
14216
+ setAttachmentNotice(null);
14217
+ },
14218
+ [setStaged]
14087
14219
  );
14088
- const removeAttachment = React.useCallback((id) => {
14089
- setStaged((prev) => prev.filter((entry) => entry.id !== id));
14090
- setAttachmentNotice(null);
14091
- }, []);
14092
14220
  const submitDraft = React.useCallback(() => {
14093
14221
  const text = draft.trim();
14094
14222
  if (!text || overLimit || busy || !canSend) return;
@@ -14100,7 +14228,16 @@ function ExplorePage({
14100
14228
  setStaged([]);
14101
14229
  setAttachmentNotice(null);
14102
14230
  textareaRef.current?.focus();
14103
- }, [busy, canSend, draft, overLimit, send, stopDictation]);
14231
+ }, [
14232
+ busy,
14233
+ canSend,
14234
+ draft,
14235
+ overLimit,
14236
+ send,
14237
+ setDraft,
14238
+ setStaged,
14239
+ stopDictation
14240
+ ]);
14104
14241
  const sendPrompt = React.useCallback(
14105
14242
  (prompt) => {
14106
14243
  if (!canSend || busy) return;
@@ -14111,7 +14248,7 @@ function ExplorePage({
14111
14248
  setStaged([]);
14112
14249
  setAttachmentNotice(null);
14113
14250
  },
14114
- [busy, canSend, send]
14251
+ [busy, canSend, send, setDraft, setStaged]
14115
14252
  );
14116
14253
  const handleKeyDown = React.useCallback(
14117
14254
  (event) => {
@@ -14133,7 +14270,7 @@ function ExplorePage({
14133
14270
  [serverCatalogRaw]
14134
14271
  );
14135
14272
  const rootStyle = {};
14136
- if (heightMode === "viewport") {
14273
+ if (viewportPage) {
14137
14274
  rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
14138
14275
  if (bottomInset > 0) {
14139
14276
  rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
@@ -14146,19 +14283,19 @@ function ExplorePage({
14146
14283
  "div",
14147
14284
  {
14148
14285
  ref: rootRef,
14149
- "data-boff-explore": "page",
14286
+ "data-boff-explore": panel ? "panel" : "page",
14150
14287
  "data-phase": phase,
14151
14288
  "data-locale": activeLocale,
14152
14289
  dir: rtl ? "rtl" : void 0,
14153
14290
  className: cn(
14154
- "flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
14155
- heightMode === "viewport" && "boff-explore-viewport",
14156
- heightMode === "auto" && "min-h-[70vh]",
14291
+ panel ? "boff-explore-panel flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden bg-background text-foreground" : "flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
14292
+ viewportPage && "boff-explore-viewport",
14293
+ !panel && heightMode === "auto" && "min-h-[70vh]",
14157
14294
  className
14158
14295
  ),
14159
- style: rootStyle,
14296
+ style: panel ? void 0 : rootStyle,
14160
14297
  children: [
14161
- /* @__PURE__ */ jsxRuntime.jsx(
14298
+ panel ? null : /* @__PURE__ */ jsxRuntime.jsx(
14162
14299
  PageHead,
14163
14300
  {
14164
14301
  title: seo?.title ?? T.seoTitle,
@@ -14171,7 +14308,11 @@ function ExplorePage({
14171
14308
  ),
14172
14309
  /* @__PURE__ */ jsxRuntime.jsx(ProseStyles, {}),
14173
14310
  /* @__PURE__ */ jsxRuntime.jsx(ExploreStyles, {}),
14174
- 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(
14175
14316
  "script",
14176
14317
  {
14177
14318
  id: BAKED_CATALOG_ELEMENT_ID,
@@ -14191,7 +14332,7 @@ function ExplorePage({
14191
14332
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-4 w-4" })
14192
14333
  }
14193
14334
  ),
14194
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-sm font-semibold", children: resolvedTitle }),
14335
+ panel ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-sm font-semibold", children: resolvedTitle }) : /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-sm font-semibold", children: resolvedTitle }),
14195
14336
  focusedProductName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden shrink-0 rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-secondary-foreground sm:inline", children: focusedProductName }) : null,
14196
14337
  /* @__PURE__ */ jsxRuntime.jsxs(
14197
14338
  Button,
@@ -14335,6 +14476,7 @@ function ExplorePage({
14335
14476
  children: showWelcome ? /* @__PURE__ */ jsxRuntime.jsx(
14336
14477
  WelcomeState,
14337
14478
  {
14479
+ heading: panel ? "h2" : "h1",
14338
14480
  strings: T,
14339
14481
  title: resolvedTitle,
14340
14482
  body: resolvedBody,
@@ -14697,77 +14839,738 @@ function samePath(a, b) {
14697
14839
  const norm = (v) => v.length > 1 ? v.replace(/\/+$/, "") : v;
14698
14840
  return norm(a) === norm(b);
14699
14841
  }
14700
- function ExploreCta({
14701
- variant,
14702
- href = "/explore",
14703
- label = "Ask AI",
14704
- 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,
14705
15084
  onNavigate,
14706
- onClick,
14707
- currentPath
15085
+ welcomeTitle,
15086
+ welcomeBody,
15087
+ explorePath,
15088
+ avatar,
15089
+ bottomOffset,
15090
+ zIndex,
15091
+ returnFocusRef,
15092
+ className
14708
15093
  }) {
14709
- const path = useCurrentPath(currentPath);
14710
- const isActive = samePath(path, href);
14711
- if (variant === "floating" && isActive) return null;
14712
- const handleClick = (event) => {
14713
- onClick?.();
14714
- if (!onNavigate) return;
14715
- 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
+ }
14716
15318
  return;
14717
15319
  }
14718
- event.preventDefault();
14719
- onNavigate(href);
14720
- };
14721
- const classes = {
14722
- // A quiet icon control, deliberately NOT a second gradient pill: a header should carry one
14723
- // primary CTA ("Get started"), and a competing coloured button next to it reads as clutter.
14724
- // This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].
14725
- // The prominent, labelled entry point to /explore is the floating bubble, which is visible
14726
- // on every page without scrolling. `shrink-0` keeps it from squeezing the nav.
14727
- 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",
14728
- 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",
14729
- 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"
14730
- };
14731
- const hooks = {
14732
- header: "cta-header",
14733
- mobile: "cta-mobile",
14734
- 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) }
14735
15412
  };
15413
+ const iconButton = "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
15414
+ const tabButton = "rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
15415
+ const expanded = size === "expanded";
15416
+ const sizeLabel = expanded ? T.exitFullScreen : T.enterFullScreen;
15417
+ const tabs = [
15418
+ { key: "chat", id: chatTabId, pane: chatPaneId, label: T.tabChat },
15419
+ { key: "avatar", id: avatarTabId, pane: avatarPaneId, label: T.tabAvatar }
15420
+ ];
14736
15421
  return /* @__PURE__ */ jsxRuntime.jsxs(
14737
- "a",
15422
+ "div",
14738
15423
  {
14739
- "data-boff-explore": hooks[variant],
14740
- href,
14741
- onClick: handleClick,
14742
- "aria-label": label,
14743
- "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,
14744
15434
  className: cn(
14745
- classes[variant],
14746
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
15435
+ "boff-explore-shell border-border bg-background text-foreground shadow-2xl",
14747
15436
  className
14748
15437
  ),
15438
+ style,
15439
+ onKeyDown,
14749
15440
  children: [
14750
- /* @__PURE__ */ jsxRuntime.jsx(
14751
- lucideReact.Sparkles,
14752
- {
14753
- className: cn(
14754
- "shrink-0",
14755
- variant === "floating" ? "h-4 w-4" : variant === "header" ? "h-5 w-5" : "h-3.5 w-3.5"
14756
- ),
14757
- "aria-hidden": "true"
14758
- }
14759
- ),
14760
- /* @__PURE__ */ jsxRuntime.jsx(
14761
- "span",
14762
- {
14763
- className: cn(
14764
- variant === "floating" && "hidden sm:inline",
14765
- // Never labelled in the header — see the class comment above.
14766
- 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
+ }
14767
15492
  ),
14768
- children: label
14769
- }
14770
- )
15493
+ /* @__PURE__ */ jsxRuntime.jsx(
15494
+ "button",
15495
+ {
15496
+ type: "button",
15497
+ "data-boff-explore": "panel-close",
15498
+ "aria-label": T.closePanel,
15499
+ title: T.closePanel,
15500
+ className: iconButton,
15501
+ onClick: close,
15502
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4", "aria-hidden": "true" })
15503
+ }
15504
+ )
15505
+ ] })
15506
+ ] }),
15507
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col", children: [
15508
+ /* @__PURE__ */ jsxRuntime.jsx(
15509
+ "div",
15510
+ {
15511
+ ref: chatPaneRef,
15512
+ id: chatPaneId,
15513
+ role: avatar ? "tabpanel" : void 0,
15514
+ "aria-labelledby": avatar ? chatTabId : void 0,
15515
+ "data-boff-explore": "panel-chat",
15516
+ className: cn(
15517
+ "flex min-h-0 flex-1 flex-col",
15518
+ view === "avatar" && "invisible"
15519
+ ),
15520
+ children: /* @__PURE__ */ jsxRuntime.jsx(
15521
+ ExplorePage,
15522
+ {
15523
+ presentation: "panel",
15524
+ active: open && view === "chat",
15525
+ productSlug,
15526
+ locale,
15527
+ onNavigate: onNavigate ? navigate : void 0,
15528
+ welcomeTitle,
15529
+ welcomeBody,
15530
+ explorePath
15531
+ }
15532
+ )
15533
+ }
15534
+ ),
15535
+ avatar ? /* @__PURE__ */ jsxRuntime.jsxs(
15536
+ "div",
15537
+ {
15538
+ id: avatarPaneId,
15539
+ role: "tabpanel",
15540
+ "aria-labelledby": avatarTabId,
15541
+ "data-boff-explore": "panel-avatar",
15542
+ className: cn(
15543
+ "absolute inset-0 flex-col items-center justify-center gap-4 overflow-y-auto bg-background p-6 text-center",
15544
+ view === "avatar" ? "flex" : "hidden"
15545
+ ),
15546
+ children: [
15547
+ /* @__PURE__ */ jsxRuntime.jsx(
15548
+ "img",
15549
+ {
15550
+ src: avatar.src,
15551
+ alt: avatar.name ? `${avatar.name}, ${T.liveAvatar}` : T.liveAvatar,
15552
+ loading: "lazy",
15553
+ decoding: "async",
15554
+ width: 128,
15555
+ height: 128,
15556
+ className: "h-32 w-32 rounded-full border border-border object-cover shadow-sm"
15557
+ }
15558
+ ),
15559
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold", children: T.avatarComingSoon }),
15560
+ /* @__PURE__ */ jsxRuntime.jsx(
15561
+ "button",
15562
+ {
15563
+ type: "button",
15564
+ "data-boff-explore": "panel-continue-chat",
15565
+ className: "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
15566
+ onClick: continueInChat,
15567
+ children: T.continueInChat
15568
+ }
15569
+ )
15570
+ ]
15571
+ }
15572
+ ) : null
15573
+ ] })
14771
15574
  ]
14772
15575
  }
14773
15576
  );
@@ -19592,8 +20395,10 @@ exports.EXPLORE_RECAPTCHA_ACTION = EXPLORE_RECAPTCHA_ACTION;
19592
20395
  exports.ElectronDownloadLink = ElectronDownloadLink;
19593
20396
  exports.ExploreAnswerBody = ExploreAnswerBody;
19594
20397
  exports.ExploreAnswerStyles = ExploreAnswerStyles;
20398
+ exports.ExploreChatProvider = ExploreChatProvider;
19595
20399
  exports.ExploreCta = ExploreCta;
19596
20400
  exports.ExplorePage = ExplorePage;
20401
+ exports.ExplorePanel = ExplorePanel;
19597
20402
  exports.FALLBACK_EXPLORE_LIMITS = FALLBACK_EXPLORE_LIMITS;
19598
20403
  exports.FOOTERLESS_ROUTES = FOOTERLESS_ROUTES;
19599
20404
  exports.Input = Input;
@@ -19687,6 +20492,7 @@ exports.stopSpeaking = stopSpeaking;
19687
20492
  exports.useContentPage = useContentPage;
19688
20493
  exports.useContentPages = useContentPages;
19689
20494
  exports.useExploreChat = useExploreChat;
20495
+ exports.useExploreConversation = useExploreConversation;
19690
20496
  exports.useProduct = useProduct;
19691
20497
  exports.useProductConfig = useProductConfig;
19692
20498
  exports.useProgressiveReveal = useProgressiveReveal;