@burdenoff/website-sdk 2026.924.10 → 2026.924.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/explore.js +119 -22
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +119 -22
- package/dist/components/explore.mjs.map +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +56 -7
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +56 -7
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +119 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +119 -22
- package/dist/index.mjs.map +1 -1
- package/dist/{use-progressive-reveal-Cmy8bA7L.d.mts → use-progressive-reveal-BBLRAnbU.d.mts} +6 -1
- package/dist/{use-progressive-reveal-DHPGGxZu.d.ts → use-progressive-reveal-myNKWb6S.d.ts} +6 -1
- package/package.json +1 -1
|
@@ -2033,6 +2033,45 @@ function buildFallbackCatalog(examplePrompts, welcome) {
|
|
|
2033
2033
|
conceptHighlights: []
|
|
2034
2034
|
};
|
|
2035
2035
|
}
|
|
2036
|
+
var BAKED_CATALOG_ELEMENT_ID = "boff-explore-catalog";
|
|
2037
|
+
function bakedCatalogLocale() {
|
|
2038
|
+
if (typeof navigator === "undefined") return "";
|
|
2039
|
+
return (navigator.language || "").toLowerCase().split("-")[0] ?? "";
|
|
2040
|
+
}
|
|
2041
|
+
function snapshotBakedElement() {
|
|
2042
|
+
if (typeof document === "undefined") return null;
|
|
2043
|
+
const el = document.getElementById(BAKED_CATALOG_ELEMENT_ID);
|
|
2044
|
+
if (!el || el.tagName !== "SCRIPT" || el.getAttribute("type") !== "application/json")
|
|
2045
|
+
return null;
|
|
2046
|
+
return {
|
|
2047
|
+
product: el.getAttribute("data-product") ?? "",
|
|
2048
|
+
locale: el.getAttribute("data-locale") ?? "",
|
|
2049
|
+
text: el.textContent ?? ""
|
|
2050
|
+
};
|
|
2051
|
+
}
|
|
2052
|
+
var BAKED_AT_LOAD = snapshotBakedElement();
|
|
2053
|
+
function isCatalogShape(value) {
|
|
2054
|
+
if (!value || typeof value !== "object") return false;
|
|
2055
|
+
const c = value;
|
|
2056
|
+
const listOrAbsent = (v) => v === void 0 || v === null || Array.isArray(v);
|
|
2057
|
+
const textOrAbsent = (v) => v === void 0 || v === null || typeof v === "string";
|
|
2058
|
+
return (c["enabled"] === void 0 || typeof c["enabled"] === "boolean") && listOrAbsent(c["products"]) && listOrAbsent(c["examplePrompts"]) && listOrAbsent(c["conceptHighlights"]) && textOrAbsent(c["welcomeTitle"]) && textOrAbsent(c["welcomeBody"]);
|
|
2059
|
+
}
|
|
2060
|
+
function readBakedCatalog(productSlug) {
|
|
2061
|
+
const baked = snapshotBakedElement() ?? BAKED_AT_LOAD;
|
|
2062
|
+
if (!baked) return null;
|
|
2063
|
+
if (baked.product !== (productSlug ?? "")) return null;
|
|
2064
|
+
if (baked.locale && baked.locale !== bakedCatalogLocale()) return null;
|
|
2065
|
+
try {
|
|
2066
|
+
const parsed = JSON.parse(baked.text);
|
|
2067
|
+
return isCatalogShape(parsed) ? parsed : null;
|
|
2068
|
+
} catch {
|
|
2069
|
+
return null;
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
function serializeBakedCatalog(raw) {
|
|
2073
|
+
return JSON.stringify(raw).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
2074
|
+
}
|
|
2036
2075
|
function normalizeCatalog(raw, fallback) {
|
|
2037
2076
|
return {
|
|
2038
2077
|
enabled: raw.enabled !== false,
|
|
@@ -2282,9 +2321,17 @@ function useExploreChat(options = {}) {
|
|
|
2282
2321
|
),
|
|
2283
2322
|
[promptKey, welcomeKey]
|
|
2284
2323
|
);
|
|
2285
|
-
const [
|
|
2324
|
+
const [bakedRaw] = useState(
|
|
2325
|
+
() => readBakedCatalog(productSlug)
|
|
2326
|
+
);
|
|
2327
|
+
const [catalog, setCatalog] = useState(
|
|
2328
|
+
() => bakedRaw ? normalizeCatalog(bakedRaw, fallbackCatalog) : fallbackCatalog
|
|
2329
|
+
);
|
|
2330
|
+
const [serverCatalogRaw, setServerCatalogRaw] = useState(bakedRaw);
|
|
2286
2331
|
const [messages, setMessages] = useState([]);
|
|
2287
|
-
const [phase, setPhase] = useState(
|
|
2332
|
+
const [phase, setPhase] = useState(
|
|
2333
|
+
() => bakedRaw ? bakedRaw.enabled === false ? "disabled" : "ready" : "loading"
|
|
2334
|
+
);
|
|
2288
2335
|
const [error, setError] = useState(null);
|
|
2289
2336
|
const [remainingToday, setRemainingToday] = useState(null);
|
|
2290
2337
|
const [focusProduct, setFocusProductState] = useState(null);
|
|
@@ -2302,7 +2349,7 @@ function useExploreChat(options = {}) {
|
|
|
2302
2349
|
shareTokenRef.current = readShareToken();
|
|
2303
2350
|
}
|
|
2304
2351
|
const isSharedView = shareTokenRef.current !== null;
|
|
2305
|
-
const catalogRef = useRef(
|
|
2352
|
+
const catalogRef = useRef(catalog);
|
|
2306
2353
|
const turnCountRef = useRef(0);
|
|
2307
2354
|
const focusProductRef = useRef(null);
|
|
2308
2355
|
const lastSentTextRef = useRef(null);
|
|
@@ -2448,25 +2495,29 @@ function useExploreChat(options = {}) {
|
|
|
2448
2495
|
const raw = res.data?.exploreCatalog;
|
|
2449
2496
|
if (res.errors?.length || !raw) {
|
|
2450
2497
|
console.warn(
|
|
2451
|
-
"[WebSDK] exploreCatalog unavailable \u2014
|
|
2498
|
+
"[WebSDK] exploreCatalog unavailable \u2014 keeping the catalog the page started with",
|
|
2452
2499
|
res.errors?.[0]?.message
|
|
2453
2500
|
);
|
|
2454
2501
|
setPhase((prev) => prev === "loading" ? "ready" : prev);
|
|
2455
2502
|
return;
|
|
2456
2503
|
}
|
|
2457
|
-
const next = normalizeCatalog(
|
|
2504
|
+
const next = normalizeCatalog(
|
|
2505
|
+
raw,
|
|
2506
|
+
bakedRaw ? normalizeCatalog(bakedRaw, fallbackCatalog) : fallbackCatalog
|
|
2507
|
+
);
|
|
2458
2508
|
setCatalog(next);
|
|
2509
|
+
setServerCatalogRaw(raw);
|
|
2459
2510
|
catalogRef.current = next;
|
|
2460
2511
|
setPhase((prev) => {
|
|
2461
2512
|
if (!next.enabled) return "disabled";
|
|
2462
|
-
return prev === "loading" ? "ready" : prev;
|
|
2513
|
+
return prev === "loading" || prev === "disabled" ? "ready" : prev;
|
|
2463
2514
|
});
|
|
2464
2515
|
};
|
|
2465
2516
|
void load();
|
|
2466
2517
|
return () => {
|
|
2467
2518
|
cancelled = true;
|
|
2468
2519
|
};
|
|
2469
|
-
}, [client, productSlug, fallbackCatalog]);
|
|
2520
|
+
}, [client, productSlug, fallbackCatalog, bakedRaw]);
|
|
2470
2521
|
const startPolling = useCallback(
|
|
2471
2522
|
(conversationToken, messageId) => {
|
|
2472
2523
|
pollGenerationRef.current += 1;
|
|
@@ -2934,6 +2985,7 @@ function useExploreChat(options = {}) {
|
|
|
2934
2985
|
return {
|
|
2935
2986
|
phase,
|
|
2936
2987
|
catalog,
|
|
2988
|
+
serverCatalogRaw,
|
|
2937
2989
|
messages,
|
|
2938
2990
|
activity,
|
|
2939
2991
|
remainingToday,
|
|
@@ -3892,6 +3944,30 @@ var EXPLORE_CSS = `
|
|
|
3892
3944
|
}
|
|
3893
3945
|
.boff-explore-strip::-webkit-scrollbar { display: none; }
|
|
3894
3946
|
|
|
3947
|
+
/* The product chips run past the edge of their row (there are 38). A hard edge sliced the
|
|
3948
|
+
last visible chip mid-word ("Bi", "BigC") right beside "All 38"; a short fade says "there
|
|
3949
|
+
is more this way" instead. A mask carries only alpha, so the gradient's colour is a token
|
|
3950
|
+
that never shows. Mirrored for right-to-left locales, whose row runs the other way. */
|
|
3951
|
+
.boff-explore-chips-fade {
|
|
3952
|
+
/* Focus scrolling honours scroll-padding, so a tabbed-to chip is brought clear of the fade
|
|
3953
|
+
rather than left half-hidden under it. */
|
|
3954
|
+
scroll-padding-inline-end: 2rem;
|
|
3955
|
+
-webkit-mask-image: linear-gradient(to right, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
|
|
3956
|
+
mask-image: linear-gradient(to right, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
|
|
3957
|
+
}
|
|
3958
|
+
/* A fade over a fixed edge would leave the LAST chip under it once the row is scrolled to
|
|
3959
|
+
the end \u2014 the visitor could never read it. A trailing spacer the width of the fade lets
|
|
3960
|
+
the final chip scroll clear of it. A pseudo-element rather than padding: trailing padding
|
|
3961
|
+
on a flex scroll container is not reliably part of its scrollable overflow. */
|
|
3962
|
+
.boff-explore-chips-fade::after {
|
|
3963
|
+
content: "";
|
|
3964
|
+
flex: 0 0 2rem;
|
|
3965
|
+
}
|
|
3966
|
+
[dir="rtl"] .boff-explore-chips-fade {
|
|
3967
|
+
-webkit-mask-image: linear-gradient(to left, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
|
|
3968
|
+
mask-image: linear-gradient(to left, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
|
|
3969
|
+
}
|
|
3970
|
+
|
|
3895
3971
|
@keyframes boff-explore-fade-in {
|
|
3896
3972
|
from { opacity: 0; transform: translateY(2px); }
|
|
3897
3973
|
to { opacity: 1; transform: none; }
|
|
@@ -3968,10 +4044,10 @@ var EXPLORE_CSS = `
|
|
|
3968
4044
|
Colour comes from the product's --primary token, so it is whatever that site's palette
|
|
3969
4045
|
already is, never a colour chosen here. */
|
|
3970
4046
|
.boff-explore-invite {
|
|
3971
|
-
border-color: hsl(var(--primary) / 0.
|
|
4047
|
+
border-color: hsl(var(--primary) / 0.6);
|
|
3972
4048
|
box-shadow:
|
|
3973
|
-
0 0 0 4px hsl(var(--primary) / 0.
|
|
3974
|
-
0 8px 24px -12px hsl(var(--primary) / 0.
|
|
4049
|
+
0 0 0 4px hsl(var(--primary) / 0.12),
|
|
4050
|
+
0 8px 24px -12px hsl(var(--primary) / 0.55);
|
|
3975
4051
|
animation: boff-explore-breathe 3.2s ease-in-out infinite;
|
|
3976
4052
|
}
|
|
3977
4053
|
/* Focus and typing both mean "I have found it", and the hint has done its job. */
|
|
@@ -3981,8 +4057,8 @@ var EXPLORE_CSS = `
|
|
|
3981
4057
|
box-shadow: 0 0 0 4px hsl(var(--primary) / 0.10);
|
|
3982
4058
|
}
|
|
3983
4059
|
@keyframes boff-explore-breathe {
|
|
3984
|
-
0%, 100% { box-shadow: 0 0 0 4px hsl(var(--primary) / 0.
|
|
3985
|
-
50% { box-shadow: 0 0 0 7px hsl(var(--primary) / 0.
|
|
4060
|
+
0%, 100% { box-shadow: 0 0 0 4px hsl(var(--primary) / 0.10), 0 8px 24px -12px hsl(var(--primary) / 0.50); }
|
|
4061
|
+
50% { box-shadow: 0 0 0 7px hsl(var(--primary) / 0.18), 0 8px 28px -12px hsl(var(--primary) / 0.65); }
|
|
3986
4062
|
}
|
|
3987
4063
|
|
|
3988
4064
|
/* Every one of the above is decoration. Reduced motion removes the movement and keeps the
|
|
@@ -5291,14 +5367,20 @@ function PromptCarousel({
|
|
|
5291
5367
|
"aria-label": `Ask: ${current}`,
|
|
5292
5368
|
"aria-live": paused ? "polite" : "off",
|
|
5293
5369
|
onClick: () => onPrompt(current),
|
|
5294
|
-
className: "
|
|
5370
|
+
className: "group flex min-w-0 flex-1 items-center gap-2 rounded-full border border-border bg-card px-4 py-2 max-sm:min-h-[3.625rem] max-sm:rounded-2xl text-left text-sm text-card-foreground shadow-sm transition-colors hover:border-primary/50 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
5295
5371
|
children: [
|
|
5296
5372
|
/* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 shrink-0 text-primary" }),
|
|
5297
|
-
/* @__PURE__ */ jsx(
|
|
5373
|
+
/* @__PURE__ */ jsx(
|
|
5374
|
+
"span",
|
|
5375
|
+
{
|
|
5376
|
+
className: "boff-explore-fade min-w-0 max-sm:line-clamp-2 sm:truncate",
|
|
5377
|
+
children: current
|
|
5378
|
+
},
|
|
5379
|
+
current
|
|
5380
|
+
),
|
|
5298
5381
|
/* @__PURE__ */ jsx(ArrowUp, { className: "ml-auto h-3.5 w-3.5 shrink-0 rotate-45 text-muted-foreground transition-colors group-hover:text-primary" })
|
|
5299
5382
|
]
|
|
5300
|
-
}
|
|
5301
|
-
current
|
|
5383
|
+
}
|
|
5302
5384
|
),
|
|
5303
5385
|
count > 1 ? /* @__PURE__ */ jsx(
|
|
5304
5386
|
"button",
|
|
@@ -5337,7 +5419,7 @@ function ProductStrip({
|
|
|
5337
5419
|
{
|
|
5338
5420
|
className: cn(
|
|
5339
5421
|
"boff-explore-strip flex min-w-0 flex-1 gap-2",
|
|
5340
|
-
expanded ? "flex-wrap" : "flex-nowrap overflow-x-auto"
|
|
5422
|
+
expanded ? "flex-wrap" : "boff-explore-chips-fade flex-nowrap overflow-x-auto"
|
|
5341
5423
|
),
|
|
5342
5424
|
children: [
|
|
5343
5425
|
/* @__PURE__ */ jsx(
|
|
@@ -5475,11 +5557,11 @@ function ConceptStrip({
|
|
|
5475
5557
|
onScroll: measureRail,
|
|
5476
5558
|
"data-boff-explore": "concept-strip",
|
|
5477
5559
|
"aria-label": T.conceptStripLabel,
|
|
5478
|
-
className: "boff-explore-strip flex min-w-0 snap-x gap-3 overflow-x-auto pb-1",
|
|
5560
|
+
className: "boff-explore-strip flex min-w-0 snap-x gap-3 overflow-x-auto pb-1 sm:mx-10",
|
|
5479
5561
|
children: visible.map((highlight) => /* @__PURE__ */ jsx(
|
|
5480
5562
|
"li",
|
|
5481
5563
|
{
|
|
5482
|
-
className: "shrink-0 snap-start",
|
|
5564
|
+
className: "flex shrink-0 snap-start",
|
|
5483
5565
|
children: /* @__PURE__ */ jsxs(
|
|
5484
5566
|
"button",
|
|
5485
5567
|
{
|
|
@@ -5520,9 +5602,9 @@ function ConceptStrip({
|
|
|
5520
5602
|
}
|
|
5521
5603
|
)
|
|
5522
5604
|
] }),
|
|
5523
|
-
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col gap-0.5 p-2.5", children: [
|
|
5605
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5 p-2.5", children: [
|
|
5524
5606
|
/* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-xs font-semibold leading-snug text-card-foreground", children: highlight.title }),
|
|
5525
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: highlight.productName })
|
|
5607
|
+
/* @__PURE__ */ jsx("span", { className: "mt-auto truncate text-[11px] text-muted-foreground", children: highlight.productName })
|
|
5526
5608
|
] })
|
|
5527
5609
|
]
|
|
5528
5610
|
}
|
|
@@ -5739,6 +5821,7 @@ function ExplorePage({
|
|
|
5739
5821
|
const {
|
|
5740
5822
|
phase,
|
|
5741
5823
|
catalog,
|
|
5824
|
+
serverCatalogRaw,
|
|
5742
5825
|
messages,
|
|
5743
5826
|
activity,
|
|
5744
5827
|
remainingToday,
|
|
@@ -6170,6 +6253,10 @@ function ExplorePage({
|
|
|
6170
6253
|
const captchaOn = Boolean(
|
|
6171
6254
|
catalog.captchaRequired && catalog.recaptchaSiteKey
|
|
6172
6255
|
);
|
|
6256
|
+
const bakedCatalogJson = useMemo(
|
|
6257
|
+
() => serverCatalogRaw && serverCatalogRaw.enabled !== false ? serializeBakedCatalog(serverCatalogRaw) : null,
|
|
6258
|
+
[serverCatalogRaw]
|
|
6259
|
+
);
|
|
6173
6260
|
const rootStyle = {};
|
|
6174
6261
|
if (heightMode === "viewport") {
|
|
6175
6262
|
rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
|
|
@@ -6209,6 +6296,16 @@ function ExplorePage({
|
|
|
6209
6296
|
),
|
|
6210
6297
|
/* @__PURE__ */ jsx(ProseStyles, {}),
|
|
6211
6298
|
/* @__PURE__ */ jsx(ExploreStyles, {}),
|
|
6299
|
+
bakedCatalogJson ? /* @__PURE__ */ jsx(
|
|
6300
|
+
"script",
|
|
6301
|
+
{
|
|
6302
|
+
id: BAKED_CATALOG_ELEMENT_ID,
|
|
6303
|
+
type: "application/json",
|
|
6304
|
+
"data-product": productSlug ?? "",
|
|
6305
|
+
"data-locale": bakedCatalogLocale(),
|
|
6306
|
+
dangerouslySetInnerHTML: { __html: bakedCatalogJson }
|
|
6307
|
+
}
|
|
6308
|
+
) : null,
|
|
6212
6309
|
/* @__PURE__ */ jsx(ExploreAnswerStyles, {}),
|
|
6213
6310
|
!showWelcome ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 border-b border-border px-4 py-2.5", children: [
|
|
6214
6311
|
/* @__PURE__ */ jsx(
|
|
@@ -6683,7 +6780,7 @@ function ExplorePage({
|
|
|
6683
6780
|
)
|
|
6684
6781
|
] }) : null,
|
|
6685
6782
|
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
6686
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
|
|
6783
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 sm:truncate", children: T.disclaimerShort }),
|
|
6687
6784
|
/* @__PURE__ */ jsx(
|
|
6688
6785
|
"button",
|
|
6689
6786
|
{
|