@burdenoff/website-sdk 2026.830.1 → 2026.921.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 (60) hide show
  1. package/README.md +112 -1
  2. package/dist/components/contact.js +4 -1
  3. package/dist/components/contact.js.map +1 -1
  4. package/dist/components/contact.mjs +4 -1
  5. package/dist/components/contact.mjs.map +1 -1
  6. package/dist/components/explore.d.mts +14 -1
  7. package/dist/components/explore.d.ts +14 -1
  8. package/dist/components/explore.js +154 -15
  9. package/dist/components/explore.js.map +1 -1
  10. package/dist/components/explore.mjs +154 -17
  11. package/dist/components/explore.mjs.map +1 -1
  12. package/dist/components/newsletter.js +4 -1
  13. package/dist/components/newsletter.js.map +1 -1
  14. package/dist/components/newsletter.mjs +4 -1
  15. package/dist/components/newsletter.mjs.map +1 -1
  16. package/dist/components/partners.js +23 -13
  17. package/dist/components/partners.js.map +1 -1
  18. package/dist/components/partners.mjs +23 -13
  19. package/dist/components/partners.mjs.map +1 -1
  20. package/dist/components/pricing.js +4 -1
  21. package/dist/components/pricing.js.map +1 -1
  22. package/dist/components/pricing.mjs +4 -1
  23. package/dist/components/pricing.mjs.map +1 -1
  24. package/dist/components/unsubscribe.js +4 -1
  25. package/dist/components/unsubscribe.js.map +1 -1
  26. package/dist/components/unsubscribe.mjs +4 -1
  27. package/dist/components/unsubscribe.mjs.map +1 -1
  28. package/dist/components/waitlist.js +4 -1
  29. package/dist/components/waitlist.js.map +1 -1
  30. package/dist/components/waitlist.mjs +4 -1
  31. package/dist/components/waitlist.mjs.map +1 -1
  32. package/dist/content/index.js +23 -13
  33. package/dist/content/index.js.map +1 -1
  34. package/dist/content/index.mjs +23 -13
  35. package/dist/content/index.mjs.map +1 -1
  36. package/dist/{use-explore-chat-B8xKGid5.d.mts → explore-types-CLw19R76.d.mts} +1 -143
  37. package/dist/{use-explore-chat-B8xKGid5.d.ts → explore-types-CLw19R76.d.ts} +1 -143
  38. package/dist/hooks/index.d.mts +2 -1
  39. package/dist/hooks/index.d.ts +2 -1
  40. package/dist/hooks/index.js +4 -1
  41. package/dist/hooks/index.js.map +1 -1
  42. package/dist/hooks/index.mjs +4 -1
  43. package/dist/hooks/index.mjs.map +1 -1
  44. package/dist/index.d.mts +141 -2
  45. package/dist/index.d.ts +141 -2
  46. package/dist/index.js +1489 -179
  47. package/dist/index.js.map +1 -1
  48. package/dist/index.mjs +1485 -182
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/seo/index.js +4 -1
  51. package/dist/seo/index.js.map +1 -1
  52. package/dist/seo/index.mjs +4 -1
  53. package/dist/seo/index.mjs.map +1 -1
  54. package/dist/store/index.js +23 -13
  55. package/dist/store/index.js.map +1 -1
  56. package/dist/store/index.mjs +23 -13
  57. package/dist/store/index.mjs.map +1 -1
  58. package/dist/use-explore-chat-CvW-kyIm.d.mts +145 -0
  59. package/dist/use-explore-chat-DdGBimiz.d.ts +145 -0
  60. package/package.json +1 -1
@@ -4,7 +4,7 @@ import { Sparkles, RotateCcw, Link2, History, Trash2, Paperclip, X, Mic, Square,
4
4
  import ReactMarkdown from 'react-markdown';
5
5
  import rehypeSanitize from 'rehype-sanitize';
6
6
  import remarkGfm from 'remark-gfm';
7
- import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import { Helmet } from 'react-helmet-async';
9
9
  import { Slot } from '@radix-ui/react-slot';
10
10
  import { cva } from 'class-variance-authority';
@@ -58,6 +58,8 @@ var EN = {
58
58
  askHuman: "ask a human",
59
59
  prevSuggestion: "Previous suggestion",
60
60
  nextSuggestion: "Next suggestion",
61
+ conceptIllustration: "Concept illustration",
62
+ opensInNewTab: "opens in a new tab",
61
63
  capabilities: [
62
64
  "Grounded in our own docs",
63
65
  "Compare across the ecosystem",
@@ -107,6 +109,8 @@ var ZH = {
107
109
  askHuman: "\u8054\u7CFB\u6211\u4EEC",
108
110
  prevSuggestion: "\u4E0A\u4E00\u4E2A\u5EFA\u8BAE",
109
111
  nextSuggestion: "\u4E0B\u4E00\u4E2A\u5EFA\u8BAE",
112
+ conceptIllustration: "\u6982\u5FF5\u793A\u610F\u56FE",
113
+ opensInNewTab: "\u5728\u65B0\u6807\u7B7E\u9875\u4E2D\u6253\u5F00",
110
114
  capabilities: ["\u57FA\u4E8E\u6211\u4EEC\u81EA\u5DF1\u7684\u6587\u6863", "\u8DE8\u4EA7\u54C1\u5BF9\u6BD4", "\u76F4\u8FBE\u6B63\u786E\u7684\u9875\u9762"],
111
115
  prompts: [
112
116
  "\u8FD9\u4E2A\u4EA7\u54C1\u5230\u5E95\u80FD\u505A\u4EC0\u4E48\uFF1F",
@@ -152,6 +156,8 @@ var HI = {
152
156
  askHuman: "\u0939\u092E\u0938\u0947 \u0938\u0902\u092A\u0930\u094D\u0915 \u0915\u0930\u0947\u0902",
153
157
  prevSuggestion: "\u092A\u093F\u091B\u0932\u093E \u0938\u0941\u091D\u093E\u0935",
154
158
  nextSuggestion: "\u0905\u0917\u0932\u093E \u0938\u0941\u091D\u093E\u0935",
159
+ conceptIllustration: "\u0905\u0935\u0927\u093E\u0930\u0923\u093E \u091A\u093F\u0924\u094D\u0930\u0923",
160
+ opensInNewTab: "\u0928\u090F \u091F\u0948\u092C \u092E\u0947\u0902 \u0916\u0941\u0932\u0924\u093E \u0939\u0948",
155
161
  capabilities: [
156
162
  "\u0939\u092E\u093E\u0930\u0947 \u0905\u092A\u0928\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924",
157
163
  "\u0938\u092D\u0940 \u0909\u0924\u094D\u092A\u093E\u0926\u094B\u0902 \u0915\u0940 \u0924\u0941\u0932\u0928\u093E \u0915\u0930\u0947\u0902",
@@ -201,6 +207,8 @@ var ES = {
201
207
  askHuman: "habla con una persona",
202
208
  prevSuggestion: "Sugerencia anterior",
203
209
  nextSuggestion: "Sugerencia siguiente",
210
+ conceptIllustration: "Ilustraci\xF3n del concepto",
211
+ opensInNewTab: "se abre en una pesta\xF1a nueva",
204
212
  capabilities: [
205
213
  "Basado en nuestra documentaci\xF3n",
206
214
  "Compara todo el ecosistema",
@@ -250,6 +258,8 @@ var AR = {
250
258
  askHuman: "\u062A\u062D\u062F\u0651\u062B \u0625\u0644\u0649 \u0634\u062E\u0635",
251
259
  prevSuggestion: "\u0627\u0644\u0627\u0642\u062A\u0631\u0627\u062D \u0627\u0644\u0633\u0627\u0628\u0642",
252
260
  nextSuggestion: "\u0627\u0644\u0627\u0642\u062A\u0631\u0627\u062D \u0627\u0644\u062A\u0627\u0644\u064A",
261
+ conceptIllustration: "\u0631\u0633\u0645 \u062A\u0648\u0636\u064A\u062D\u064A \u0644\u0644\u0645\u0641\u0647\u0648\u0645",
262
+ opensInNewTab: "\u064A\u064F\u0641\u062A\u062D \u0641\u064A \u0639\u0644\u0627\u0645\u0629 \u062A\u0628\u0648\u064A\u0628 \u062C\u062F\u064A\u062F\u0629",
253
263
  capabilities: [
254
264
  "\u0645\u0628\u0646\u064A \u0639\u0644\u0649 \u0648\u062B\u0627\u0626\u0642\u0646\u0627",
255
265
  "\u0642\u0627\u0631\u0646 \u0639\u0628\u0631 \u0627\u0644\u0645\u0646\u0638\u0648\u0645\u0629",
@@ -299,6 +309,8 @@ var TA = {
299
309
  askHuman: "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BC8\u0BA4\u0BCD \u0BA4\u0BCA\u0B9F\u0BB0\u0BCD\u0BAA\u0BC1 \u0B95\u0BCA\u0BB3\u0BCD\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
300
310
  prevSuggestion: "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA4\u0BC8\u0BAF \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8",
301
311
  nextSuggestion: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4 \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8",
312
+ conceptIllustration: "\u0B95\u0BB0\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1 \u0BB5\u0BBF\u0BB3\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BAE\u0BCD",
313
+ opensInNewTab: "\u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0BA4\u0BBE\u0BB5\u0BB2\u0BBF\u0BB2\u0BCD \u0BA4\u0BBF\u0BB1\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD",
302
314
  capabilities: [
303
315
  "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BA9\u0BCD \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD",
304
316
  "\u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC8 \u0B92\u0BAA\u0BCD\u0BAA\u0BBF\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
@@ -339,19 +351,26 @@ function exploreStrings(locale) {
339
351
  function fill(template, values) {
340
352
  return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
341
353
  }
354
+ function MarkdownLink({
355
+ href,
356
+ children,
357
+ // react-markdown passes the hast node to every override; it is not a DOM attribute.
358
+ node: _node,
359
+ ...props
360
+ }) {
361
+ const isExternal = typeof href === "string" && (href.startsWith("http://") || href.startsWith("https://"));
362
+ return /* @__PURE__ */ jsx(
363
+ "a",
364
+ {
365
+ href,
366
+ ...props,
367
+ ...isExternal ? { target: "_blank", rel: "noopener noreferrer" } : { rel: "noopener noreferrer" },
368
+ children
369
+ }
370
+ );
371
+ }
342
372
  var defaultComponents = {
343
- a: ({ href, children, ...props }) => {
344
- const isExternal = typeof href === "string" && (href.startsWith("http://") || href.startsWith("https://"));
345
- return /* @__PURE__ */ jsx(
346
- "a",
347
- {
348
- href,
349
- ...props,
350
- ...isExternal ? { target: "_blank", rel: "noopener noreferrer" } : { rel: "noopener noreferrer" },
351
- children
352
- }
353
- );
354
- }
373
+ a: MarkdownLink
355
374
  };
356
375
  function Markdown({
357
376
  children,
@@ -912,10 +931,13 @@ var ECOSYSTEM_PRODUCTS = [
912
931
  name: "VibeControls",
913
932
  websiteUrl: "https://vibecontrols.com"
914
933
  },
934
+ // FluidGrids ships on www.fluidgrids.ai — fluidgrids.com only redirects there. The explore
935
+ // catalog and the site's own sitemap use this origin, and so must the fallback catalog
936
+ // built from this list, or /explore rejects FluidGrids concept images until it loads.
915
937
  {
916
938
  slug: "fluidgrids",
917
939
  name: "FluidGrids",
918
- websiteUrl: "https://fluidgrids.com"
940
+ websiteUrl: "https://www.fluidgrids.ai"
919
941
  },
920
942
  // Botlit ships on botlit.ai — botlit.com does not resolve.
921
943
  { slug: "botlit", name: "Botlit", websiteUrl: "https://www.botlit.ai" },
@@ -2219,6 +2241,9 @@ function resolveImageUrl(image, base) {
2219
2241
  return image;
2220
2242
  }
2221
2243
  }
2244
+ function serializeJsonLd(data) {
2245
+ return JSON.stringify(data).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
2246
+ }
2222
2247
  function PageHead({
2223
2248
  title,
2224
2249
  description,
@@ -2260,7 +2285,7 @@ function PageHead({
2260
2285
  fullImageUrl && /* @__PURE__ */ jsx("meta", { name: "twitter:image", content: fullImageUrl }),
2261
2286
  twitterHandle && /* @__PURE__ */ jsx("meta", { name: "twitter:creator", content: twitterHandle }),
2262
2287
  /* @__PURE__ */ jsx("meta", { name: "theme-color", content: themeColor }),
2263
- structuredDataItems.map((data, index) => /* @__PURE__ */ jsx("script", { type: "application/ld+json", children: JSON.stringify(data) }, `ld-${index}`)),
2288
+ structuredDataItems.map((data, index) => /* @__PURE__ */ jsx("script", { type: "application/ld+json", children: serializeJsonLd(data) }, `ld-${index}`)),
2264
2289
  additionalMeta?.map((meta, index) => /* @__PURE__ */ jsx(
2265
2290
  "meta",
2266
2291
  {
@@ -2677,6 +2702,93 @@ function logoUrlOf(url) {
2677
2702
  return null;
2678
2703
  }
2679
2704
  }
2705
+ function inlineImageOrigins(products) {
2706
+ const origins = /* @__PURE__ */ new Set();
2707
+ for (const product of products) {
2708
+ let url;
2709
+ try {
2710
+ url = new URL(product.website);
2711
+ } catch {
2712
+ continue;
2713
+ }
2714
+ if (url.protocol !== "https:") continue;
2715
+ const apex = url.hostname.replace(/^www\./, "");
2716
+ const port = url.port ? `:${url.port}` : "";
2717
+ origins.add(`https://${apex}${port}`);
2718
+ origins.add(`https://www.${apex}${port}`);
2719
+ }
2720
+ return origins;
2721
+ }
2722
+ function isInlineImageAllowed(src, origins) {
2723
+ if (typeof src !== "string" || src === "") return false;
2724
+ let url;
2725
+ try {
2726
+ url = new URL(src);
2727
+ } catch {
2728
+ return false;
2729
+ }
2730
+ if (url.protocol !== "https:" || url.username || url.password) return false;
2731
+ return origins.has(url.origin);
2732
+ }
2733
+ var InlineImageScopeContext = createContext(null);
2734
+ var InsideLinkContext = createContext(false);
2735
+ function AnswerLink(props) {
2736
+ return /* @__PURE__ */ jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsx(MarkdownLink, { ...props }) });
2737
+ }
2738
+ var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
2739
+ function InlineConceptImage({ src, alt }) {
2740
+ const scope = useContext(InlineImageScopeContext);
2741
+ const insideLink = useContext(InsideLinkContext);
2742
+ if (!scope || !scope.enabled || !isInlineImageAllowed(src, scope.origins) || scope.failed.has(src)) {
2743
+ return null;
2744
+ }
2745
+ const { strings: T, onFailed } = scope;
2746
+ const picture = /* @__PURE__ */ jsxs(Fragment, { children: [
2747
+ /* @__PURE__ */ jsx(
2748
+ "img",
2749
+ {
2750
+ src,
2751
+ alt: alt ?? "",
2752
+ loading: "lazy",
2753
+ decoding: "async",
2754
+ onError: () => onFailed(src),
2755
+ className: "block h-auto max-h-80 w-auto max-w-full object-contain"
2756
+ }
2757
+ ),
2758
+ /* @__PURE__ */ jsx(
2759
+ "span",
2760
+ {
2761
+ "aria-hidden": "true",
2762
+ className: "pointer-events-none absolute left-2 top-2 rounded-full border border-border bg-background/90 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-foreground shadow-sm",
2763
+ children: T.conceptIllustration
2764
+ }
2765
+ )
2766
+ ] });
2767
+ return /* @__PURE__ */ jsx("span", { "data-boff-explore": "inline-image", className: "my-3 block", children: insideLink ? /* @__PURE__ */ jsx("span", { className: INLINE_IMAGE_FRAME, children: picture }) : /* @__PURE__ */ jsxs(
2768
+ "a",
2769
+ {
2770
+ href: src,
2771
+ target: "_blank",
2772
+ rel: "noopener noreferrer",
2773
+ className: cn(
2774
+ INLINE_IMAGE_FRAME,
2775
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
2776
+ ),
2777
+ children: [
2778
+ picture,
2779
+ /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
2780
+ "(",
2781
+ T.opensInNewTab,
2782
+ ")"
2783
+ ] })
2784
+ ]
2785
+ }
2786
+ ) });
2787
+ }
2788
+ var ANSWER_MARKDOWN_COMPONENTS = {
2789
+ a: AnswerLink,
2790
+ img: InlineConceptImage
2791
+ };
2680
2792
  function ReferenceCard({
2681
2793
  reference,
2682
2794
  onFollow
@@ -2859,6 +2971,7 @@ function AssistantBubble({
2859
2971
  strings: T,
2860
2972
  message,
2861
2973
  activity,
2974
+ imageOrigins,
2862
2975
  onNavigate,
2863
2976
  anchorRef,
2864
2977
  onFollow,
@@ -2867,6 +2980,25 @@ function AssistantBubble({
2867
2980
  const streaming = message.status === "PENDING" || message.status === "RUNNING";
2868
2981
  const body = message.content || message.partialContent || "";
2869
2982
  const failed = message.status === "FAILED";
2983
+ const completed = message.status === "COMPLETED";
2984
+ const [failedImages, setFailedImages] = useState(
2985
+ () => /* @__PURE__ */ new Set()
2986
+ );
2987
+ const markImageFailed = useCallback((src) => {
2988
+ setFailedImages(
2989
+ (current) => current.has(src) ? current : new Set(current).add(src)
2990
+ );
2991
+ }, []);
2992
+ const imageScope = useMemo(
2993
+ () => ({
2994
+ strings: T,
2995
+ enabled: completed,
2996
+ origins: imageOrigins,
2997
+ failed: failedImages,
2998
+ onFailed: markImageFailed
2999
+ }),
3000
+ [T, completed, imageOrigins, failedImages, markImageFailed]
3001
+ );
2870
3002
  return /* @__PURE__ */ jsxs(
2871
3003
  "div",
2872
3004
  {
@@ -2913,7 +3045,7 @@ function AssistantBubble({
2913
3045
  }
2914
3046
  ) : null,
2915
3047
  body ? /* @__PURE__ */ jsxs("div", { className: "rounded-2xl rounded-tl-md border border-border bg-card px-4 py-3 shadow-sm", children: [
2916
- /* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsx(Markdown, { children: body }) }),
3048
+ /* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsx(InlineImageScopeContext.Provider, { value: imageScope, children: /* @__PURE__ */ jsx(Markdown, { components: ANSWER_MARKDOWN_COMPONENTS, children: body }) }) }),
2917
3049
  streaming ? /* @__PURE__ */ jsx("span", { className: "boff-explore-caret", "aria-hidden": "true" }) : null
2918
3050
  ] }) : null,
2919
3051
  streaming ? /* @__PURE__ */ jsx(ThinkingIndicator, { activity }) : null,
@@ -3412,6 +3544,10 @@ function ExplorePage({
3412
3544
  () => catalog.products.find((p) => p.slug === focusProduct)?.name ?? null,
3413
3545
  [catalog.products, focusProduct]
3414
3546
  );
3547
+ const imageOrigins = useMemo(
3548
+ () => inlineImageOrigins(catalog.products),
3549
+ [catalog.products]
3550
+ );
3415
3551
  useEffect(() => {
3416
3552
  const el = textareaRef.current;
3417
3553
  if (!el) return;
@@ -3742,6 +3878,7 @@ function ExplorePage({
3742
3878
  strings: T,
3743
3879
  message,
3744
3880
  activity,
3881
+ imageOrigins,
3745
3882
  onNavigate,
3746
3883
  anchorRef: message.id === latestAssistantId ? latestAssistantRef : void 0,
3747
3884
  onFollow: (kind, url) => recordClick(message.id, kind, url),
@@ -4035,6 +4172,6 @@ function ExplorePage({
4035
4172
  );
4036
4173
  }
4037
4174
 
4038
- export { ExplorePage, logoUrlOf };
4175
+ export { ExplorePage, inlineImageOrigins, isInlineImageAllowed, logoUrlOf };
4039
4176
  //# sourceMappingURL=explore.mjs.map
4040
4177
  //# sourceMappingURL=explore.mjs.map