@burdenoff/website-sdk 2026.829.8 → 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 +217 -43
  9. package/dist/components/explore.js.map +1 -1
  10. package/dist/components/explore.mjs +217 -45
  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-BzXCz2UM.d.mts → explore-types-CLw19R76.d.mts} +1 -131
  37. package/dist/{use-explore-chat-BzXCz2UM.d.ts → explore-types-CLw19R76.d.ts} +1 -131
  38. package/dist/hooks/index.d.mts +2 -1
  39. package/dist/hooks/index.d.ts +2 -1
  40. package/dist/hooks/index.js +23 -7
  41. package/dist/hooks/index.js.map +1 -1
  42. package/dist/hooks/index.mjs +23 -7
  43. package/dist/hooks/index.mjs.map +1 -1
  44. package/dist/index.d.mts +143 -3
  45. package/dist/index.d.ts +143 -3
  46. package/dist/index.js +1552 -207
  47. package/dist/index.js.map +1 -1
  48. package/dist/index.mjs +1548 -210
  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
@@ -80,9 +80,12 @@ var EN = {
80
80
  attachmentTooLarge: "{{name}} is larger than {{size}} MB and was not attached.",
81
81
  attachmentTooMany: "Only {{max}} files can be attached, so {{name}} was skipped.",
82
82
  noAnswer: "I couldn't find this in our documentation, so the answer below is not grounded in a source. Try rephrasing, or",
83
+ answerDidNotArrive: "That answer didn't come through. Try asking again.",
83
84
  askHuman: "ask a human",
84
85
  prevSuggestion: "Previous suggestion",
85
86
  nextSuggestion: "Next suggestion",
87
+ conceptIllustration: "Concept illustration",
88
+ opensInNewTab: "opens in a new tab",
86
89
  capabilities: [
87
90
  "Grounded in our own docs",
88
91
  "Compare across the ecosystem",
@@ -128,9 +131,12 @@ var ZH = {
128
131
  attachmentTooLarge: "{{name}} \u8D85\u8FC7 {{size}} MB\uFF0C\u672A\u80FD\u6DFB\u52A0\u3002",
129
132
  attachmentTooMany: "\u6700\u591A\u53EA\u80FD\u6DFB\u52A0 {{max}} \u4E2A\u6587\u4EF6\uFF0C\u5DF2\u8DF3\u8FC7 {{name}}\u3002",
130
133
  noAnswer: "\u6211\u5728\u6587\u6863\u4E2D\u6CA1\u6709\u627E\u5230\u76F8\u5173\u5185\u5BB9\uFF0C\u4E0B\u9762\u7684\u56DE\u7B54\u6CA1\u6709\u6765\u6E90\u652F\u6301\u3002\u8BF7\u6362\u4E2A\u8BF4\u6CD5\uFF0C\u6216",
134
+ answerDidNotArrive: "\u8FD9\u6761\u56DE\u7B54\u6CA1\u6709\u8FD4\u56DE\u3002\u8BF7\u518D\u95EE\u4E00\u6B21\u3002",
131
135
  askHuman: "\u8054\u7CFB\u6211\u4EEC",
132
136
  prevSuggestion: "\u4E0A\u4E00\u4E2A\u5EFA\u8BAE",
133
137
  nextSuggestion: "\u4E0B\u4E00\u4E2A\u5EFA\u8BAE",
138
+ conceptIllustration: "\u6982\u5FF5\u793A\u610F\u56FE",
139
+ opensInNewTab: "\u5728\u65B0\u6807\u7B7E\u9875\u4E2D\u6253\u5F00",
134
140
  capabilities: ["\u57FA\u4E8E\u6211\u4EEC\u81EA\u5DF1\u7684\u6587\u6863", "\u8DE8\u4EA7\u54C1\u5BF9\u6BD4", "\u76F4\u8FBE\u6B63\u786E\u7684\u9875\u9762"],
135
141
  prompts: [
136
142
  "\u8FD9\u4E2A\u4EA7\u54C1\u5230\u5E95\u80FD\u505A\u4EC0\u4E48\uFF1F",
@@ -172,9 +178,12 @@ var HI = {
172
178
  attachmentTooLarge: "{{name}} {{size}} MB \u0938\u0947 \u092C\u0921\u093C\u0940 \u0939\u0948, \u0907\u0938\u0932\u093F\u090F \u091C\u094B\u0921\u093C\u0940 \u0928\u0939\u0940\u0902 \u0917\u0908\u0964",
173
179
  attachmentTooMany: "\u0915\u0947\u0935\u0932 {{max}} \u092B\u093C\u093E\u0907\u0932\u0947\u0902 \u091C\u094B\u0921\u093C\u0940 \u091C\u093E \u0938\u0915\u0924\u0940 \u0939\u0948\u0902, \u0907\u0938\u0932\u093F\u090F {{name}} \u091B\u094B\u0921\u093C \u0926\u0940 \u0917\u0908\u0964",
174
180
  noAnswer: "\u092F\u0939 \u092E\u0941\u091D\u0947 \u0939\u092E\u093E\u0930\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u092E\u0947\u0902 \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E, \u0907\u0938\u0932\u093F\u090F \u0928\u0940\u091A\u0947 \u0926\u093F\u092F\u093E \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938\u0940 \u0938\u094D\u0930\u094B\u0924 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0926\u0942\u0938\u0930\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902, \u092F\u093E",
181
+ answerDidNotArrive: "\u0935\u0939 \u0909\u0924\u094D\u0924\u0930 \u0928\u0939\u0940\u0902 \u0906 \u0938\u0915\u093E\u0964 \u0915\u0943\u092A\u092F\u093E \u0926\u094B\u092C\u093E\u0930\u093E \u092A\u0942\u091B\u0947\u0902\u0964",
175
182
  askHuman: "\u0939\u092E\u0938\u0947 \u0938\u0902\u092A\u0930\u094D\u0915 \u0915\u0930\u0947\u0902",
176
183
  prevSuggestion: "\u092A\u093F\u091B\u0932\u093E \u0938\u0941\u091D\u093E\u0935",
177
184
  nextSuggestion: "\u0905\u0917\u0932\u093E \u0938\u0941\u091D\u093E\u0935",
185
+ conceptIllustration: "\u0905\u0935\u0927\u093E\u0930\u0923\u093E \u091A\u093F\u0924\u094D\u0930\u0923",
186
+ opensInNewTab: "\u0928\u090F \u091F\u0948\u092C \u092E\u0947\u0902 \u0916\u0941\u0932\u0924\u093E \u0939\u0948",
178
187
  capabilities: [
179
188
  "\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",
180
189
  "\u0938\u092D\u0940 \u0909\u0924\u094D\u092A\u093E\u0926\u094B\u0902 \u0915\u0940 \u0924\u0941\u0932\u0928\u093E \u0915\u0930\u0947\u0902",
@@ -220,9 +229,12 @@ var ES = {
220
229
  attachmentTooLarge: "{{name}} supera los {{size}} MB y no se adjunt\xF3.",
221
230
  attachmentTooMany: "Solo se pueden adjuntar {{max}} archivos, as\xED que se omiti\xF3 {{name}}.",
222
231
  noAnswer: "No he encontrado esto en nuestra documentaci\xF3n, as\xED que la respuesta de abajo no se apoya en ninguna fuente. Prueba a reformularla, o",
232
+ answerDidNotArrive: "Esa respuesta no lleg\xF3. Int\xE9ntalo de nuevo.",
223
233
  askHuman: "habla con una persona",
224
234
  prevSuggestion: "Sugerencia anterior",
225
235
  nextSuggestion: "Sugerencia siguiente",
236
+ conceptIllustration: "Ilustraci\xF3n del concepto",
237
+ opensInNewTab: "se abre en una pesta\xF1a nueva",
226
238
  capabilities: [
227
239
  "Basado en nuestra documentaci\xF3n",
228
240
  "Compara todo el ecosistema",
@@ -268,9 +280,12 @@ var AR = {
268
280
  attachmentTooLarge: "{{name}} \u0623\u0643\u0628\u0631 \u0645\u0646 {{size}} \u0645\u064A\u063A\u0627\u0628\u0627\u064A\u062A \u0648\u0644\u0645 \u064A\u062A\u0645 \u0625\u0631\u0641\u0627\u0642\u0647.",
269
281
  attachmentTooMany: "\u064A\u0645\u0643\u0646 \u0625\u0631\u0641\u0627\u0642 {{max}} \u0645\u0644\u0641\u0627\u062A \u0641\u0642\u0637\u060C \u0644\u0630\u0627 \u062A\u0645 \u062A\u062E\u0637\u064A {{name}}.",
270
282
  noAnswer: "\u0644\u0645 \u0623\u062C\u062F \u0647\u0630\u0627 \u0641\u064A \u0648\u062B\u0627\u0626\u0642\u0646\u0627\u060C \u0644\u0630\u0627 \u0641\u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0623\u062F\u0646\u0627\u0647 \u063A\u064A\u0631 \u0645\u0633\u062A\u0646\u062F\u0629 \u0625\u0644\u0649 \u0645\u0635\u062F\u0631. \u062D\u0627\u0648\u0644 \u0625\u0639\u0627\u062F\u0629 \u0627\u0644\u0635\u064A\u0627\u063A\u0629\u060C \u0623\u0648",
283
+ answerDidNotArrive: "\u0644\u0645 \u062A\u0635\u0644 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
271
284
  askHuman: "\u062A\u062D\u062F\u0651\u062B \u0625\u0644\u0649 \u0634\u062E\u0635",
272
285
  prevSuggestion: "\u0627\u0644\u0627\u0642\u062A\u0631\u0627\u062D \u0627\u0644\u0633\u0627\u0628\u0642",
273
286
  nextSuggestion: "\u0627\u0644\u0627\u0642\u062A\u0631\u0627\u062D \u0627\u0644\u062A\u0627\u0644\u064A",
287
+ conceptIllustration: "\u0631\u0633\u0645 \u062A\u0648\u0636\u064A\u062D\u064A \u0644\u0644\u0645\u0641\u0647\u0648\u0645",
288
+ opensInNewTab: "\u064A\u064F\u0641\u062A\u062D \u0641\u064A \u0639\u0644\u0627\u0645\u0629 \u062A\u0628\u0648\u064A\u0628 \u062C\u062F\u064A\u062F\u0629",
274
289
  capabilities: [
275
290
  "\u0645\u0628\u0646\u064A \u0639\u0644\u0649 \u0648\u062B\u0627\u0626\u0642\u0646\u0627",
276
291
  "\u0642\u0627\u0631\u0646 \u0639\u0628\u0631 \u0627\u0644\u0645\u0646\u0638\u0648\u0645\u0629",
@@ -316,9 +331,12 @@ var TA = {
316
331
  attachmentTooLarge: "{{name}} {{size}} MB-\u0B90 \u0BB5\u0BBF\u0B9F \u0BAA\u0BC6\u0BB0\u0BBF\u0BAF\u0BA4\u0BC1, \u0B8E\u0BA9\u0BB5\u0BC7 \u0B87\u0BA3\u0BC8\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
317
332
  attachmentTooMany: "{{max}} \u0B95\u0BCB\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7 \u0B87\u0BA3\u0BC8\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BC1\u0BAE\u0BCD, \u0B8E\u0BA9\u0BB5\u0BC7 {{name}} \u0BA4\u0BB5\u0BBF\u0BB0\u0BCD\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1.",
318
333
  noAnswer: "\u0B87\u0BA4\u0BC1 \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8, \u0B8E\u0BA9\u0BB5\u0BC7 \u0B95\u0BC0\u0BB4\u0BC7 \u0B89\u0BB3\u0BCD\u0BB3 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8. \u0BB5\u0BC7\u0BB1\u0BC1 \u0BB5\u0B95\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1",
334
+ answerDidNotArrive: "\u0B85\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BB5\u0BB0\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0BBE\u0BB0\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
319
335
  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",
320
336
  prevSuggestion: "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA4\u0BC8\u0BAF \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8",
321
337
  nextSuggestion: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4 \u0BAA\u0BB0\u0BBF\u0BA8\u0BCD\u0BA4\u0BC1\u0BB0\u0BC8",
338
+ conceptIllustration: "\u0B95\u0BB0\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1 \u0BB5\u0BBF\u0BB3\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BAE\u0BCD",
339
+ opensInNewTab: "\u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0BA4\u0BBE\u0BB5\u0BB2\u0BBF\u0BB2\u0BCD \u0BA4\u0BBF\u0BB1\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD",
322
340
  capabilities: [
323
341
  "\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",
324
342
  "\u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC8 \u0B92\u0BAA\u0BCD\u0BAA\u0BBF\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
@@ -359,19 +377,26 @@ function exploreStrings(locale) {
359
377
  function fill(template, values) {
360
378
  return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
361
379
  }
380
+ function MarkdownLink({
381
+ href,
382
+ children,
383
+ // react-markdown passes the hast node to every override; it is not a DOM attribute.
384
+ node: _node,
385
+ ...props
386
+ }) {
387
+ const isExternal = typeof href === "string" && (href.startsWith("http://") || href.startsWith("https://"));
388
+ return /* @__PURE__ */ jsxRuntime.jsx(
389
+ "a",
390
+ {
391
+ href,
392
+ ...props,
393
+ ...isExternal ? { target: "_blank", rel: "noopener noreferrer" } : { rel: "noopener noreferrer" },
394
+ children
395
+ }
396
+ );
397
+ }
362
398
  var defaultComponents = {
363
- a: ({ href, children, ...props }) => {
364
- const isExternal = typeof href === "string" && (href.startsWith("http://") || href.startsWith("https://"));
365
- return /* @__PURE__ */ jsxRuntime.jsx(
366
- "a",
367
- {
368
- href,
369
- ...props,
370
- ...isExternal ? { target: "_blank", rel: "noopener noreferrer" } : { rel: "noopener noreferrer" },
371
- children
372
- }
373
- );
374
- }
399
+ a: MarkdownLink
375
400
  };
376
401
  function Markdown({
377
402
  children,
@@ -932,10 +957,13 @@ var ECOSYSTEM_PRODUCTS = [
932
957
  name: "VibeControls",
933
958
  websiteUrl: "https://vibecontrols.com"
934
959
  },
960
+ // FluidGrids ships on www.fluidgrids.ai — fluidgrids.com only redirects there. The explore
961
+ // catalog and the site's own sitemap use this origin, and so must the fallback catalog
962
+ // built from this list, or /explore rejects FluidGrids concept images until it loads.
935
963
  {
936
964
  slug: "fluidgrids",
937
965
  name: "FluidGrids",
938
- websiteUrl: "https://fluidgrids.com"
966
+ websiteUrl: "https://www.fluidgrids.ai"
939
967
  },
940
968
  // Botlit ships on botlit.ai — botlit.com does not resolve.
941
969
  { slug: "botlit", name: "Botlit", websiteUrl: "https://www.botlit.ai" },
@@ -1186,7 +1214,7 @@ var DEFAULT_EXPLORE_EXAMPLE_PROMPTS = [
1186
1214
  ];
1187
1215
  var FALLBACK_WELCOME_TITLE = "Ask anything about our products";
1188
1216
  var FALLBACK_WELCOME_BODY = "Get straight answers drawn from our product documentation and public pages \u2014 with links back to the exact page each answer came from.";
1189
- function buildFallbackCatalog(examplePrompts) {
1217
+ function buildFallbackCatalog(examplePrompts, welcome) {
1190
1218
  return {
1191
1219
  enabled: true,
1192
1220
  products: ECOSYSTEM_PRODUCTS.map((p) => ({
@@ -1196,8 +1224,8 @@ function buildFallbackCatalog(examplePrompts) {
1196
1224
  website: p.websiteUrl
1197
1225
  })),
1198
1226
  examplePrompts: examplePrompts?.length ? examplePrompts : DEFAULT_EXPLORE_EXAMPLE_PROMPTS,
1199
- welcomeTitle: FALLBACK_WELCOME_TITLE,
1200
- welcomeBody: FALLBACK_WELCOME_BODY,
1227
+ welcomeTitle: welcome?.title ?? FALLBACK_WELCOME_TITLE,
1228
+ welcomeBody: welcome?.body ?? FALLBACK_WELCOME_BODY,
1201
1229
  limits: FALLBACK_EXPLORE_LIMITS,
1202
1230
  captchaRequired: false,
1203
1231
  recaptchaSiteKey: null
@@ -1257,7 +1285,15 @@ function classifyExploreError(code, serverMessage) {
1257
1285
  retryable: true
1258
1286
  };
1259
1287
  }
1260
- if (c === "TIMEOUT" || c === "TOOL_BUDGET") {
1288
+ if (c === "TOOL_BUDGET") {
1289
+ return {
1290
+ kind: "scope",
1291
+ code: c,
1292
+ message: "That question spans more of our products than I can look through in one go. Try asking about two or three specific products.",
1293
+ retryable: false
1294
+ };
1295
+ }
1296
+ if (c === "TIMEOUT") {
1261
1297
  return {
1262
1298
  kind: "timeout",
1263
1299
  code: c,
@@ -1389,6 +1425,7 @@ function useExploreChat(options = {}) {
1389
1425
  pageUrl,
1390
1426
  locale,
1391
1427
  examplePrompts,
1428
+ fallbackWelcome,
1392
1429
  pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,
1393
1430
  pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,
1394
1431
  storageKey = DEFAULT_STORAGE_KEY,
@@ -1397,9 +1434,13 @@ function useExploreChat(options = {}) {
1397
1434
  } = options;
1398
1435
  const client = useWebSDK();
1399
1436
  const promptKey = JSON.stringify(examplePrompts ?? []);
1437
+ const welcomeKey = JSON.stringify(fallbackWelcome ?? null);
1400
1438
  const fallbackCatalog = React.useMemo(
1401
- () => buildFallbackCatalog(JSON.parse(promptKey)),
1402
- [promptKey]
1439
+ () => buildFallbackCatalog(
1440
+ JSON.parse(promptKey),
1441
+ JSON.parse(welcomeKey) ?? void 0
1442
+ ),
1443
+ [promptKey, welcomeKey]
1403
1444
  );
1404
1445
  const [catalog, setCatalog] = React.useState(fallbackCatalog);
1405
1446
  const [messages, setMessages] = React.useState([]);
@@ -2226,6 +2267,9 @@ function resolveImageUrl(image, base) {
2226
2267
  return image;
2227
2268
  }
2228
2269
  }
2270
+ function serializeJsonLd(data) {
2271
+ return JSON.stringify(data).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
2272
+ }
2229
2273
  function PageHead({
2230
2274
  title,
2231
2275
  description,
@@ -2267,7 +2311,7 @@ function PageHead({
2267
2311
  fullImageUrl && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:image", content: fullImageUrl }),
2268
2312
  twitterHandle && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:creator", content: twitterHandle }),
2269
2313
  /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "theme-color", content: themeColor }),
2270
- structuredDataItems.map((data, index) => /* @__PURE__ */ jsxRuntime.jsx("script", { type: "application/ld+json", children: JSON.stringify(data) }, `ld-${index}`)),
2314
+ structuredDataItems.map((data, index) => /* @__PURE__ */ jsxRuntime.jsx("script", { type: "application/ld+json", children: serializeJsonLd(data) }, `ld-${index}`)),
2271
2315
  additionalMeta?.map((meta, index) => /* @__PURE__ */ jsxRuntime.jsx(
2272
2316
  "meta",
2273
2317
  {
@@ -2684,6 +2728,93 @@ function logoUrlOf(url) {
2684
2728
  return null;
2685
2729
  }
2686
2730
  }
2731
+ function inlineImageOrigins(products) {
2732
+ const origins = /* @__PURE__ */ new Set();
2733
+ for (const product of products) {
2734
+ let url;
2735
+ try {
2736
+ url = new URL(product.website);
2737
+ } catch {
2738
+ continue;
2739
+ }
2740
+ if (url.protocol !== "https:") continue;
2741
+ const apex = url.hostname.replace(/^www\./, "");
2742
+ const port = url.port ? `:${url.port}` : "";
2743
+ origins.add(`https://${apex}${port}`);
2744
+ origins.add(`https://www.${apex}${port}`);
2745
+ }
2746
+ return origins;
2747
+ }
2748
+ function isInlineImageAllowed(src, origins) {
2749
+ if (typeof src !== "string" || src === "") return false;
2750
+ let url;
2751
+ try {
2752
+ url = new URL(src);
2753
+ } catch {
2754
+ return false;
2755
+ }
2756
+ if (url.protocol !== "https:" || url.username || url.password) return false;
2757
+ return origins.has(url.origin);
2758
+ }
2759
+ var InlineImageScopeContext = React.createContext(null);
2760
+ var InsideLinkContext = React.createContext(false);
2761
+ function AnswerLink(props) {
2762
+ return /* @__PURE__ */ jsxRuntime.jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownLink, { ...props }) });
2763
+ }
2764
+ var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
2765
+ function InlineConceptImage({ src, alt }) {
2766
+ const scope = React.useContext(InlineImageScopeContext);
2767
+ const insideLink = React.useContext(InsideLinkContext);
2768
+ if (!scope || !scope.enabled || !isInlineImageAllowed(src, scope.origins) || scope.failed.has(src)) {
2769
+ return null;
2770
+ }
2771
+ const { strings: T, onFailed } = scope;
2772
+ const picture = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2773
+ /* @__PURE__ */ jsxRuntime.jsx(
2774
+ "img",
2775
+ {
2776
+ src,
2777
+ alt: alt ?? "",
2778
+ loading: "lazy",
2779
+ decoding: "async",
2780
+ onError: () => onFailed(src),
2781
+ className: "block h-auto max-h-80 w-auto max-w-full object-contain"
2782
+ }
2783
+ ),
2784
+ /* @__PURE__ */ jsxRuntime.jsx(
2785
+ "span",
2786
+ {
2787
+ "aria-hidden": "true",
2788
+ 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",
2789
+ children: T.conceptIllustration
2790
+ }
2791
+ )
2792
+ ] });
2793
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-boff-explore": "inline-image", className: "my-3 block", children: insideLink ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: INLINE_IMAGE_FRAME, children: picture }) : /* @__PURE__ */ jsxRuntime.jsxs(
2794
+ "a",
2795
+ {
2796
+ href: src,
2797
+ target: "_blank",
2798
+ rel: "noopener noreferrer",
2799
+ className: cn(
2800
+ INLINE_IMAGE_FRAME,
2801
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
2802
+ ),
2803
+ children: [
2804
+ picture,
2805
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
2806
+ "(",
2807
+ T.opensInNewTab,
2808
+ ")"
2809
+ ] })
2810
+ ]
2811
+ }
2812
+ ) });
2813
+ }
2814
+ var ANSWER_MARKDOWN_COMPONENTS = {
2815
+ a: AnswerLink,
2816
+ img: InlineConceptImage
2817
+ };
2687
2818
  function ReferenceCard({
2688
2819
  reference,
2689
2820
  onFollow
@@ -2866,6 +2997,7 @@ function AssistantBubble({
2866
2997
  strings: T,
2867
2998
  message,
2868
2999
  activity,
3000
+ imageOrigins,
2869
3001
  onNavigate,
2870
3002
  anchorRef,
2871
3003
  onFollow,
@@ -2874,6 +3006,25 @@ function AssistantBubble({
2874
3006
  const streaming = message.status === "PENDING" || message.status === "RUNNING";
2875
3007
  const body = message.content || message.partialContent || "";
2876
3008
  const failed = message.status === "FAILED";
3009
+ const completed = message.status === "COMPLETED";
3010
+ const [failedImages, setFailedImages] = React.useState(
3011
+ () => /* @__PURE__ */ new Set()
3012
+ );
3013
+ const markImageFailed = React.useCallback((src) => {
3014
+ setFailedImages(
3015
+ (current) => current.has(src) ? current : new Set(current).add(src)
3016
+ );
3017
+ }, []);
3018
+ const imageScope = React.useMemo(
3019
+ () => ({
3020
+ strings: T,
3021
+ enabled: completed,
3022
+ origins: imageOrigins,
3023
+ failed: failedImages,
3024
+ onFailed: markImageFailed
3025
+ }),
3026
+ [T, completed, imageOrigins, failedImages, markImageFailed]
3027
+ );
2877
3028
  return /* @__PURE__ */ jsxRuntime.jsxs(
2878
3029
  "div",
2879
3030
  {
@@ -2899,7 +3050,7 @@ function AssistantBubble({
2899
3050
  children: [
2900
3051
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TriangleAlert, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-amber-600 dark:text-amber-400" }),
2901
3052
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2902
- "I couldn't find this in our documentation, so the answer below is not grounded in a source. Try rephrasing, or",
3053
+ T.noAnswer,
2903
3054
  " ",
2904
3055
  /* @__PURE__ */ jsxRuntime.jsx(
2905
3056
  "a",
@@ -2920,11 +3071,11 @@ function AssistantBubble({
2920
3071
  }
2921
3072
  ) : null,
2922
3073
  body ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl rounded-tl-md border border-border bg-card px-4 py-3 shadow-sm", children: [
2923
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { children: body }) }),
3074
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(InlineImageScopeContext.Provider, { value: imageScope, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { components: ANSWER_MARKDOWN_COMPONENTS, children: body }) }) }),
2924
3075
  streaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "boff-explore-caret", "aria-hidden": "true" }) : null
2925
3076
  ] }) : null,
2926
3077
  streaming ? /* @__PURE__ */ jsxRuntime.jsx(ThinkingIndicator, { activity }) : null,
2927
- failed && !body ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-2xl rounded-tl-md border border-border bg-muted px-4 py-3 text-sm text-muted-foreground", children: "That answer didn't come through. Try asking again." }) : null,
3078
+ failed && !body ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-2xl rounded-tl-md border border-border bg-muted px-4 py-3 text-sm text-muted-foreground", children: T.answerDidNotArrive }) : null,
2928
3079
  message.references.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2929
3080
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: T.sources }),
2930
3081
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3", children: message.references.map((reference) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -3340,6 +3491,12 @@ function ExplorePage({
3340
3491
  () => typeof window === "undefined" ? void 0 : window.location.href,
3341
3492
  []
3342
3493
  );
3494
+ const activeLocale = React.useMemo(
3495
+ () => resolveExploreLocale(locale),
3496
+ [locale]
3497
+ );
3498
+ const T = React.useMemo(() => exploreStrings(activeLocale), [activeLocale]);
3499
+ const rtl = isRtlLocale(activeLocale);
3343
3500
  const {
3344
3501
  phase,
3345
3502
  catalog,
@@ -3361,7 +3518,15 @@ function ExplorePage({
3361
3518
  recordClick,
3362
3519
  createShareLink,
3363
3520
  isSharedView
3364
- } = useExploreChat({ productSlug, pageUrl, onSend, examplePrompts });
3521
+ } = useExploreChat({
3522
+ productSlug,
3523
+ pageUrl,
3524
+ onSend,
3525
+ // Locale-aware, so a catalog outage degrades to a translated welcome rather than an
3526
+ // English one. `T.prompts` seeds the chips the same way.
3527
+ examplePrompts: examplePrompts ?? T.prompts,
3528
+ fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody }
3529
+ });
3365
3530
  const [draft, setDraft] = React.useState("");
3366
3531
  const textareaRef = React.useRef(null);
3367
3532
  const [historyOpen, setHistoryOpen] = React.useState(false);
@@ -3379,12 +3544,6 @@ function ExplorePage({
3379
3544
  }
3380
3545
  });
3381
3546
  speechStopRef.current = speech.stop;
3382
- const activeLocale = React.useMemo(
3383
- () => resolveExploreLocale(locale),
3384
- [locale]
3385
- );
3386
- const T = React.useMemo(() => exploreStrings(activeLocale), [activeLocale]);
3387
- const rtl = isRtlLocale(activeLocale);
3388
3547
  const [disclaimerOpen, setDisclaimerOpen] = React.useState(false);
3389
3548
  const [staged, setStaged] = React.useState([]);
3390
3549
  const [attachmentNotice, setAttachmentNotice] = React.useState(null);
@@ -3392,7 +3551,7 @@ function ExplorePage({
3392
3551
  const stagedRef = React.useRef([]);
3393
3552
  stagedRef.current = staged;
3394
3553
  const pickQueueRef = React.useRef(Promise.resolve());
3395
- const [shareLabel, setShareLabel] = React.useState("Share");
3554
+ const [shareLabel, setShareLabel] = React.useState(T.share);
3396
3555
  const [shareUrl, setShareUrl] = React.useState(null);
3397
3556
  const scrollRef = React.useRef(null);
3398
3557
  const latestAssistantRef = React.useRef(null);
@@ -3411,6 +3570,10 @@ function ExplorePage({
3411
3570
  () => catalog.products.find((p) => p.slug === focusProduct)?.name ?? null,
3412
3571
  [catalog.products, focusProduct]
3413
3572
  );
3573
+ const imageOrigins = React.useMemo(
3574
+ () => inlineImageOrigins(catalog.products),
3575
+ [catalog.products]
3576
+ );
3414
3577
  React.useEffect(() => {
3415
3578
  const el = textareaRef.current;
3416
3579
  if (!el) return;
@@ -3449,12 +3612,12 @@ function ExplorePage({
3449
3612
  el.scrollTop = el.scrollHeight;
3450
3613
  }, [activity, latestAssistantId, messages]);
3451
3614
  const handleShare = React.useCallback(async () => {
3452
- setShareLabel("Copying\u2026");
3615
+ setShareLabel(T.copying);
3453
3616
  setShareUrl(null);
3454
3617
  const token = await createShareLink();
3455
3618
  if (!token) {
3456
- setShareLabel("Unavailable");
3457
- setTimeout(() => setShareLabel("Share"), 2500);
3619
+ setShareLabel(T.shareUnavailable);
3620
+ setTimeout(() => setShareLabel(T.share), 2500);
3458
3621
  return;
3459
3622
  }
3460
3623
  const url = new URL(pageUrl ?? window.location.href);
@@ -3464,13 +3627,20 @@ function ExplorePage({
3464
3627
  const shareable = url.toString();
3465
3628
  try {
3466
3629
  await navigator.clipboard.writeText(shareable);
3467
- setShareLabel("Copied");
3468
- setTimeout(() => setShareLabel("Share"), 2500);
3630
+ setShareLabel(T.copied);
3631
+ setTimeout(() => setShareLabel(T.share), 2500);
3469
3632
  } catch {
3470
3633
  setShareUrl(shareable);
3471
- setShareLabel("Share");
3634
+ setShareLabel(T.share);
3472
3635
  }
3473
- }, [createShareLink, pageUrl]);
3636
+ }, [
3637
+ createShareLink,
3638
+ pageUrl,
3639
+ T.copied,
3640
+ T.copying,
3641
+ T.share,
3642
+ T.shareUnavailable
3643
+ ]);
3474
3644
  const handleFilesPicked = React.useCallback(
3475
3645
  (picked) => {
3476
3646
  if (!picked || picked.length === 0) return pickQueueRef.current;
@@ -3586,7 +3756,7 @@ function ExplorePage({
3586
3756
  onClick: reset,
3587
3757
  children: [
3588
3758
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "h-3.5 w-3.5" }),
3589
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "New chat" })
3759
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: T.newChat })
3590
3760
  ]
3591
3761
  }
3592
3762
  ),
@@ -3623,7 +3793,8 @@ function ExplorePage({
3623
3793
  children: [
3624
3794
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-3.5 w-3.5" }),
3625
3795
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden sm:inline", children: [
3626
- "History (",
3796
+ T.history,
3797
+ " (",
3627
3798
  history.length,
3628
3799
  ")"
3629
3800
  ] })
@@ -3653,7 +3824,7 @@ function ExplorePage({
3653
3824
  },
3654
3825
  children: [
3655
3826
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }),
3656
- "Clear history"
3827
+ T.clearHistory
3657
3828
  ]
3658
3829
  }
3659
3830
  )
@@ -3733,6 +3904,7 @@ function ExplorePage({
3733
3904
  strings: T,
3734
3905
  message,
3735
3906
  activity,
3907
+ imageOrigins,
3736
3908
  onNavigate,
3737
3909
  anchorRef: message.id === latestAssistantId ? latestAssistantRef : void 0,
3738
3910
  onFollow: (kind, url) => recordClick(message.id, kind, url),
@@ -3919,7 +4091,7 @@ function ExplorePage({
3919
4091
  type: "button",
3920
4092
  size: "icon",
3921
4093
  variant: "secondary",
3922
- "aria-label": "Stop generating",
4094
+ "aria-label": T.stop,
3923
4095
  onClick: stop,
3924
4096
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { className: "h-4 w-4" })
3925
4097
  }
@@ -3930,7 +4102,7 @@ function ExplorePage({
3930
4102
  type: "submit",
3931
4103
  size: "icon",
3932
4104
  disabled: !canSubmit,
3933
- "aria-label": "Send message",
4105
+ "aria-label": T.send,
3934
4106
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-4 w-4" })
3935
4107
  }
3936
4108
  )
@@ -4027,6 +4199,8 @@ function ExplorePage({
4027
4199
  }
4028
4200
 
4029
4201
  exports.ExplorePage = ExplorePage;
4202
+ exports.inlineImageOrigins = inlineImageOrigins;
4203
+ exports.isInlineImageAllowed = isInlineImageAllowed;
4030
4204
  exports.logoUrlOf = logoUrlOf;
4031
4205
  //# sourceMappingURL=explore.js.map
4032
4206
  //# sourceMappingURL=explore.js.map