@burdenoff/website-sdk 2026.1028.1 → 2026.1031.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 (52) hide show
  1. package/README.md +159 -1
  2. package/dist/avatar-live/index.d.mts +11 -0
  3. package/dist/avatar-live/index.d.ts +11 -0
  4. package/dist/avatar-live/index.js +120 -0
  5. package/dist/avatar-live/index.js.map +1 -0
  6. package/dist/avatar-live/index.mjs +118 -0
  7. package/dist/avatar-live/index.mjs.map +1 -0
  8. package/dist/avatar-live-view/index.d.mts +42 -0
  9. package/dist/avatar-live-view/index.d.ts +42 -0
  10. package/dist/avatar-live-view/index.js +1422 -0
  11. package/dist/avatar-live-view/index.js.map +1 -0
  12. package/dist/avatar-live-view/index.mjs +1420 -0
  13. package/dist/avatar-live-view/index.mjs.map +1 -0
  14. package/dist/components/contact.js +9 -3
  15. package/dist/components/contact.js.map +1 -1
  16. package/dist/components/contact.mjs +9 -3
  17. package/dist/components/contact.mjs.map +1 -1
  18. package/dist/components/explore.d.mts +2 -2
  19. package/dist/components/explore.d.ts +2 -2
  20. package/dist/components/explore.js +11 -4
  21. package/dist/components/explore.js.map +1 -1
  22. package/dist/components/explore.mjs +11 -4
  23. package/dist/components/explore.mjs.map +1 -1
  24. package/dist/components/partners.js +9 -3
  25. package/dist/components/partners.js.map +1 -1
  26. package/dist/components/partners.mjs +9 -3
  27. package/dist/components/partners.mjs.map +1 -1
  28. package/dist/{explore-BEgq1_0O.d.mts → explore-DUTNYUOm.d.mts} +1 -1
  29. package/dist/{explore-CHiP9u-4.d.ts → explore-DjQE7Xia.d.ts} +1 -1
  30. package/dist/explore-avatar-live-config-B171o1Yo.d.ts +283 -0
  31. package/dist/explore-avatar-live-config-BGsGwbcq.d.mts +283 -0
  32. package/dist/{explore-types-_9UJu6EA.d.mts → explore-types-Bb2Ih3d8.d.mts} +1 -1
  33. package/dist/{explore-types-_9UJu6EA.d.ts → explore-types-Bb2Ih3d8.d.ts} +1 -1
  34. package/dist/hooks/index.d.mts +3 -2
  35. package/dist/hooks/index.d.ts +3 -2
  36. package/dist/hooks/index.js +6 -1
  37. package/dist/hooks/index.js.map +1 -1
  38. package/dist/hooks/index.mjs +6 -1
  39. package/dist/hooks/index.mjs.map +1 -1
  40. package/dist/index.d.mts +16 -253
  41. package/dist/index.d.ts +16 -253
  42. package/dist/index.js +225 -41
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +225 -41
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/types-CndbmBK-.d.mts +68 -0
  47. package/dist/types-CndbmBK-.d.ts +68 -0
  48. package/dist/{use-progressive-reveal-C0hkdu_i.d.ts → use-explore-chat-DunjG-3p.d.ts} +10 -36
  49. package/dist/{use-progressive-reveal-BFPWbEXy.d.mts → use-explore-chat-zRuoAin6.d.mts} +10 -36
  50. package/dist/use-progressive-reveal-ppicEgzZ.d.mts +35 -0
  51. package/dist/use-progressive-reveal-ppicEgzZ.d.ts +35 -0
  52. package/package.json +15 -3
package/dist/index.js CHANGED
@@ -913,6 +913,12 @@ function ContactPage({
913
913
  setIsSubmitting(false);
914
914
  }
915
915
  };
916
+ const heroDescriptionText = replacePlaceholders(
917
+ heroDescription,
918
+ displayName,
919
+ contactEmail
920
+ ).trim();
921
+ const hasHero = heroTitle.trim() !== "" || heroDescriptionText !== "";
916
922
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
917
923
  seo && /* @__PURE__ */ jsxRuntime.jsx(
918
924
  PageHead,
@@ -925,13 +931,13 @@ function ContactPage({
925
931
  url: seo.url
926
932
  }
927
933
  ),
928
- /* @__PURE__ */ jsxRuntime.jsx(
934
+ hasHero && /* @__PURE__ */ jsxRuntime.jsx(
929
935
  "section",
930
936
  {
931
937
  className: headingLevel === 2 ? "py-12 md:py-16" : "bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24",
932
938
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
933
- headingLevel === 2 ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-3", children: heroTitle }) : /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6", children: heroTitle }),
934
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg sm:text-xl text-muted-foreground leading-relaxed", children: replacePlaceholders(heroDescription, displayName, contactEmail) })
939
+ !heroTitle.trim() ? null : headingLevel === 2 ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-3", children: heroTitle }) : /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6", children: heroTitle }),
940
+ heroDescriptionText && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg sm:text-xl text-muted-foreground leading-relaxed", children: heroDescriptionText })
935
941
  ] }) })
936
942
  }
937
943
  ),
@@ -5551,7 +5557,7 @@ function FilterChip({
5551
5557
  {
5552
5558
  className: cn(
5553
5559
  "rounded-full px-1.5 text-xs tabular-nums",
5554
- active ? "bg-primary-foreground/20 text-primary-foreground" : "bg-muted text-muted-foreground"
5560
+ active ? "bg-primary-foreground text-primary" : "bg-muted text-muted-foreground"
5555
5561
  ),
5556
5562
  children: count
5557
5563
  }
@@ -6468,6 +6474,11 @@ function ConceptDetail({
6468
6474
  );
6469
6475
  }
6470
6476
 
6477
+ // src/components/explore-fill.ts
6478
+ function fill(template, values) {
6479
+ return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
6480
+ }
6481
+
6471
6482
  // src/components/explore-i18n.ts
6472
6483
  var EXPLORE_LOCALES = ["en", "zh", "hi", "es", "ar", "ta"];
6473
6484
  var RTL_LOCALES = /* @__PURE__ */ new Set(["ar"]);
@@ -7255,9 +7266,6 @@ function resolveExploreLocale(explicit) {
7255
7266
  function exploreStrings(locale) {
7256
7267
  return STRINGS[locale] ?? EN;
7257
7268
  }
7258
- function fill(template, values) {
7259
- return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
7260
- }
7261
7269
 
7262
7270
  // src/components/answers-i18n.ts
7263
7271
  var EN2 = {
@@ -9006,7 +9014,7 @@ function FilterChip2({
9006
9014
  {
9007
9015
  className: cn(
9008
9016
  "rounded-full px-1.5 text-xs tabular-nums",
9009
- active ? "bg-primary-foreground/20 text-primary-foreground" : "bg-muted text-muted-foreground"
9017
+ active ? "bg-primary-foreground text-primary" : "bg-muted text-muted-foreground"
9010
9018
  ),
9011
9019
  children: count
9012
9020
  }
@@ -11031,6 +11039,10 @@ function useExploreChat(options = {}) {
11031
11039
  [client, productId]
11032
11040
  );
11033
11041
  const canEscalate = hasConversation && !isSharedView;
11042
+ const getConversationToken = React.useCallback(
11043
+ () => conversationTokenRef.current,
11044
+ []
11045
+ );
11034
11046
  return {
11035
11047
  phase,
11036
11048
  catalog,
@@ -11055,7 +11067,8 @@ function useExploreChat(options = {}) {
11055
11067
  escalate,
11056
11068
  canEscalate,
11057
11069
  createShareLink,
11058
- isSharedView
11070
+ isSharedView,
11071
+ getConversationToken
11059
11072
  };
11060
11073
  }
11061
11074
  var optimisticCounter = 0;
@@ -15162,6 +15175,164 @@ var ExploreCta = React.forwardRef(
15162
15175
  );
15163
15176
  }
15164
15177
  );
15178
+
15179
+ // src/components/explore-avatar-live-config.ts
15180
+ var AVATAR_WEB_API_PATH = "/api/web-avatar/v1";
15181
+ var SITE = /^[a-z][a-z0-9-]{1,31}$/;
15182
+ var VERSION = /^[A-Za-z0-9._-]{1,32}$/;
15183
+ var SITE_KEY = /^[A-Za-z0-9_-]{1,128}$/;
15184
+ var LOOPBACK_HOSTS2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
15185
+ function isAvatarSite(value) {
15186
+ return SITE.test(value);
15187
+ }
15188
+ function isAvatarVersion(value) {
15189
+ return VERSION.test(value);
15190
+ }
15191
+ function avatarApiBase(gatewayUrl) {
15192
+ if (!gatewayUrl) return null;
15193
+ let url;
15194
+ try {
15195
+ url = new URL(gatewayUrl);
15196
+ } catch {
15197
+ return null;
15198
+ }
15199
+ const local = url.protocol === "http:" && LOOPBACK_HOSTS2.has(url.hostname.toLowerCase());
15200
+ if (url.protocol !== "https:" && !local) return null;
15201
+ return `${url.origin}${AVATAR_WEB_API_PATH}`;
15202
+ }
15203
+ function liveConfigComplete(live) {
15204
+ return typeof live.load === "function" && typeof live.site === "string" && isAvatarSite(live.site) && typeof live.manifestVersion === "string" && isAvatarVersion(live.manifestVersion) && typeof live.turnstileSiteKey === "string" && SITE_KEY.test(live.turnstileSiteKey);
15205
+ }
15206
+ var REVIEWED = /* @__PURE__ */ new Set(["en"]);
15207
+ function isAvatarLiveLocaleReviewed(locale) {
15208
+ return REVIEWED.has(locale);
15209
+ }
15210
+ var VIEW_LOAD_TIMEOUT_MS = 8e3;
15211
+ function loadAvatarLiveView() {
15212
+ return import('./avatar-live-view/index.js').then(
15213
+ (loaded) => loaded.AvatarLiveView
15214
+ );
15215
+ }
15216
+ function ExploreAvatarLive({
15217
+ live,
15218
+ active,
15219
+ locale,
15220
+ productName,
15221
+ still,
15222
+ fallback,
15223
+ onContinueInChat,
15224
+ loadView = loadAvatarLiveView
15225
+ }) {
15226
+ const T = exploreStrings(locale);
15227
+ const config = useWebSDKConfig();
15228
+ const conversation = React.useContext(ExploreConversationContext);
15229
+ const base = avatarApiBase(config.gatewayUrl);
15230
+ const headers = React.useMemo(
15231
+ () => cfAccessHeaders(config.gatewayUrl, config.cfAccess),
15232
+ [config.gatewayUrl, config.cfAccess]
15233
+ );
15234
+ const complete = liveConfigComplete(live);
15235
+ const off = !complete || base === null || conversation === null || conversation.isSharedView || !isAvatarLiveLocaleReviewed(locale);
15236
+ React.useEffect(() => {
15237
+ if (!complete) {
15238
+ console.warn(
15239
+ "[WebSDK] ExplorePanel: avatar.live needs site, load, turnstileSiteKey and manifestVersion; the live avatar stays off."
15240
+ );
15241
+ }
15242
+ }, [complete]);
15243
+ const [View, setView] = React.useState(null);
15244
+ const [failed, setFailed] = React.useState(false);
15245
+ const wanted = active && !off;
15246
+ React.useEffect(() => {
15247
+ if (!wanted || View !== null) return;
15248
+ let cancelled = false;
15249
+ let loading;
15250
+ try {
15251
+ loading = loadView();
15252
+ } catch (error) {
15253
+ loading = Promise.reject(error);
15254
+ }
15255
+ const patience = setTimeout(() => {
15256
+ if (!cancelled) setFailed(true);
15257
+ }, VIEW_LOAD_TIMEOUT_MS);
15258
+ loading.then(
15259
+ (component) => {
15260
+ if (!cancelled) setView(() => component);
15261
+ },
15262
+ () => {
15263
+ clearTimeout(patience);
15264
+ if (!cancelled) setFailed(true);
15265
+ }
15266
+ );
15267
+ return () => {
15268
+ cancelled = true;
15269
+ clearTimeout(patience);
15270
+ };
15271
+ }, [wanted, View, loadView]);
15272
+ if (View !== null) {
15273
+ return /* @__PURE__ */ jsxRuntime.jsx(
15274
+ View,
15275
+ {
15276
+ live,
15277
+ active,
15278
+ locale,
15279
+ productName,
15280
+ still,
15281
+ fallback,
15282
+ onContinueInChat,
15283
+ continueInChat: T.continueInChat,
15284
+ off,
15285
+ base,
15286
+ headers,
15287
+ conversation
15288
+ }
15289
+ );
15290
+ }
15291
+ if (off || failed) {
15292
+ return (
15293
+ // `display: contents`: the earlier Avatar view's picture, line and button lay out in the pane exactly as before.
15294
+ /* @__PURE__ */ jsxRuntime.jsx(
15295
+ "div",
15296
+ {
15297
+ style: { display: "contents" },
15298
+ "data-boff-explore": "avatar-live",
15299
+ "data-phase": off ? "off" : "inert",
15300
+ children: fallback
15301
+ }
15302
+ )
15303
+ );
15304
+ }
15305
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15306
+ "div",
15307
+ {
15308
+ "data-boff-explore": "avatar-live",
15309
+ "data-phase": "idle",
15310
+ className: "flex max-h-full w-full flex-col items-center gap-4 overflow-y-auto",
15311
+ children: [
15312
+ /* @__PURE__ */ jsxRuntime.jsx(
15313
+ "img",
15314
+ {
15315
+ src: still.src,
15316
+ alt: still.alt,
15317
+ decoding: "async",
15318
+ width: 128,
15319
+ height: 128,
15320
+ className: "shrink-0 rounded-full border border-border object-cover shadow-sm h-32 w-32"
15321
+ }
15322
+ ),
15323
+ /* @__PURE__ */ jsxRuntime.jsx(
15324
+ "p",
15325
+ {
15326
+ role: "status",
15327
+ "data-boff-explore": "avatar-live-status",
15328
+ className: "text-sm text-muted-foreground"
15329
+ }
15330
+ ),
15331
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-boff-explore": "avatar-live-bot-check" })
15332
+ ]
15333
+ }
15334
+ );
15335
+ }
15165
15336
  var MARK_KEY = "boffExplorePanel";
15166
15337
  var POS_KEY = "boffExplorePanelPos";
15167
15338
  var DOC_KEY = "boffExplorePanelDoc";
@@ -15353,15 +15524,15 @@ function ExplorePanel({
15353
15524
  const rtl = isRtlLocale(resolvedLocale);
15354
15525
  const catalogProducts = React.useContext(ExploreCatalogProductsContext);
15355
15526
  const pinnedSlug = pinnedProductSlug(scope, productSlug);
15356
- const title = React.useMemo(() => {
15357
- if (pinnedSlug === null) return T.panelTitle;
15358
- const name = productNameFor(
15527
+ const pinnedName = React.useMemo(
15528
+ () => pinnedSlug === null ? null : productNameFor(
15359
15529
  catalogProducts ?? ECOSYSTEM_PRODUCTS,
15360
15530
  pinnedSlug,
15361
15531
  productName
15362
- );
15363
- return name === null ? T.panelTitle : fill(T.panelTitleProduct, { product: name });
15364
- }, [T, catalogProducts, pinnedSlug, productName]);
15532
+ ),
15533
+ [catalogProducts, pinnedSlug, productName]
15534
+ );
15535
+ const title = pinnedName === null ? T.panelTitle : fill(T.panelTitleProduct, { product: pinnedName });
15365
15536
  const uid = React.useId();
15366
15537
  const titleId = `${uid}-title`;
15367
15538
  const chatTabId = `${uid}-chat-tab`;
@@ -15682,6 +15853,32 @@ function ExplorePanel({
15682
15853
  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";
15683
15854
  const expanded = size === "expanded";
15684
15855
  const sizeLabel = expanded ? T.exitFullScreen : T.enterFullScreen;
15856
+ const avatarAlt = avatar?.name ? `${avatar.name}, ${T.liveAvatar}` : T.liveAvatar;
15857
+ const comingSoon = avatar ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15858
+ /* @__PURE__ */ jsxRuntime.jsx(
15859
+ "img",
15860
+ {
15861
+ src: avatar.src,
15862
+ alt: avatarAlt,
15863
+ loading: "lazy",
15864
+ decoding: "async",
15865
+ width: 128,
15866
+ height: 128,
15867
+ className: "h-32 w-32 rounded-full border border-border object-cover shadow-sm"
15868
+ }
15869
+ ),
15870
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold", children: T.avatarComingSoon }),
15871
+ /* @__PURE__ */ jsxRuntime.jsx(
15872
+ "button",
15873
+ {
15874
+ type: "button",
15875
+ "data-boff-explore": "panel-continue-chat",
15876
+ 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",
15877
+ onClick: continueInChat,
15878
+ children: T.continueInChat
15879
+ }
15880
+ )
15881
+ ] }) : null;
15685
15882
  const tabs = [
15686
15883
  { key: "chat", id: chatTabId, pane: chatPaneId, label: T.tabChat },
15687
15884
  { key: "avatar", id: avatarTabId, pane: avatarPaneId, label: T.tabAvatar }
@@ -15811,7 +16008,7 @@ function ExplorePanel({
15811
16008
  )
15812
16009
  }
15813
16010
  ),
15814
- avatar ? /* @__PURE__ */ jsxRuntime.jsxs(
16011
+ avatar ? /* @__PURE__ */ jsxRuntime.jsx(
15815
16012
  "div",
15816
16013
  {
15817
16014
  id: avatarPaneId,
@@ -15822,31 +16019,18 @@ function ExplorePanel({
15822
16019
  "absolute inset-0 flex-col items-center justify-center gap-4 overflow-y-auto bg-background p-6 text-center",
15823
16020
  view === "avatar" ? "flex" : "hidden"
15824
16021
  ),
15825
- children: [
15826
- /* @__PURE__ */ jsxRuntime.jsx(
15827
- "img",
15828
- {
15829
- src: avatar.src,
15830
- alt: avatar.name ? `${avatar.name}, ${T.liveAvatar}` : T.liveAvatar,
15831
- loading: "lazy",
15832
- decoding: "async",
15833
- width: 128,
15834
- height: 128,
15835
- className: "h-32 w-32 rounded-full border border-border object-cover shadow-sm"
15836
- }
15837
- ),
15838
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold", children: T.avatarComingSoon }),
15839
- /* @__PURE__ */ jsxRuntime.jsx(
15840
- "button",
15841
- {
15842
- type: "button",
15843
- "data-boff-explore": "panel-continue-chat",
15844
- 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",
15845
- onClick: continueInChat,
15846
- children: T.continueInChat
15847
- }
15848
- )
15849
- ]
16022
+ children: avatar.live ? /* @__PURE__ */ jsxRuntime.jsx(
16023
+ ExploreAvatarLive,
16024
+ {
16025
+ live: avatar.live,
16026
+ active: open && view === "avatar",
16027
+ locale: resolvedLocale,
16028
+ productName: pinnedName,
16029
+ still: { src: avatar.src, alt: avatarAlt },
16030
+ fallback: comingSoon,
16031
+ onContinueInChat: continueInChat
16032
+ }
16033
+ ) : comingSoon
15850
16034
  }
15851
16035
  ) : null
15852
16036
  ] })