@burdenoff/website-sdk 2026.830.1 → 2026.922.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.
- package/README.md +114 -3
- package/dist/components/contact.js +4 -1
- package/dist/components/contact.js.map +1 -1
- package/dist/components/contact.mjs +4 -1
- package/dist/components/contact.mjs.map +1 -1
- package/dist/components/explore.d.mts +24 -3
- package/dist/components/explore.d.ts +24 -3
- package/dist/components/explore.js +690 -236
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +690 -238
- package/dist/components/explore.mjs.map +1 -1
- package/dist/components/newsletter.js +4 -1
- package/dist/components/newsletter.js.map +1 -1
- package/dist/components/newsletter.mjs +4 -1
- package/dist/components/newsletter.mjs.map +1 -1
- package/dist/components/partners.js +23 -13
- package/dist/components/partners.js.map +1 -1
- package/dist/components/partners.mjs +23 -13
- package/dist/components/partners.mjs.map +1 -1
- package/dist/components/pricing.js +4 -1
- package/dist/components/pricing.js.map +1 -1
- package/dist/components/pricing.mjs +4 -1
- package/dist/components/pricing.mjs.map +1 -1
- package/dist/components/unsubscribe.js +4 -1
- package/dist/components/unsubscribe.js.map +1 -1
- package/dist/components/unsubscribe.mjs +4 -1
- package/dist/components/unsubscribe.mjs.map +1 -1
- package/dist/components/waitlist.js +4 -1
- package/dist/components/waitlist.js.map +1 -1
- package/dist/components/waitlist.mjs +4 -1
- package/dist/components/waitlist.mjs.map +1 -1
- package/dist/content/index.js +23 -13
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +23 -13
- package/dist/content/index.mjs.map +1 -1
- package/dist/{use-explore-chat-B8xKGid5.d.mts → explore-types-CLw19R76.d.mts} +1 -143
- package/dist/{use-explore-chat-B8xKGid5.d.ts → explore-types-CLw19R76.d.ts} +1 -143
- package/dist/hooks/index.d.mts +2 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.js +4 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +4 -1
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +141 -2
- package/dist/index.d.ts +141 -2
- package/dist/index.js +2025 -400
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2021 -403
- package/dist/index.mjs.map +1 -1
- package/dist/seo/index.js +4 -1
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +4 -1
- package/dist/seo/index.mjs.map +1 -1
- package/dist/store/index.js +23 -13
- package/dist/store/index.js.map +1 -1
- package/dist/store/index.mjs +23 -13
- package/dist/store/index.mjs.map +1 -1
- package/dist/use-explore-chat-CvW-kyIm.d.mts +145 -0
- package/dist/use-explore-chat-DdGBimiz.d.ts +145 -0
- 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:
|
|
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.
|
|
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:
|
|
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
|
{
|
|
@@ -2467,6 +2492,7 @@ function toPayload(staged) {
|
|
|
2467
2492
|
textContent
|
|
2468
2493
|
}));
|
|
2469
2494
|
}
|
|
2495
|
+
var SHORT_VIEWPORT_PX = 420;
|
|
2470
2496
|
var EXPLORE_CSS = `
|
|
2471
2497
|
@keyframes boff-explore-pulse {
|
|
2472
2498
|
0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
|
|
@@ -2501,6 +2527,12 @@ var EXPLORE_CSS = `
|
|
|
2501
2527
|
.boff-explore-scroll {
|
|
2502
2528
|
scrollbar-width: thin;
|
|
2503
2529
|
scrollbar-color: hsl(var(--border)) transparent;
|
|
2530
|
+
/* Stop the transcript handing its scroll to the page. Without this, the first
|
|
2531
|
+
swipe that exhausts the transcript chains to the document \u2014 and on a host site
|
|
2532
|
+
that is 65-70% footer, which is how a phone ends up showing nothing but the
|
|
2533
|
+
footer. Engines that do not support this property ignore the line and keep
|
|
2534
|
+
today's behaviour; the scroll correction above covers them. */
|
|
2535
|
+
overscroll-behavior: contain;
|
|
2504
2536
|
}
|
|
2505
2537
|
.boff-explore-scroll::-webkit-scrollbar { width: 10px; }
|
|
2506
2538
|
.boff-explore-scroll::-webkit-scrollbar-track { background: transparent; }
|
|
@@ -2618,6 +2650,68 @@ var EXPLORE_CSS = `
|
|
|
2618
2650
|
.boff-explore-busy::after { animation: none; }
|
|
2619
2651
|
.boff-explore-rise { animation: none; opacity: 1; transform: none; }
|
|
2620
2652
|
}
|
|
2653
|
+
|
|
2654
|
+
/* ---- Pane height ----------------------------------------------------------------------
|
|
2655
|
+
This used to be one inline declaration, \`height: calc(100dvh - 64px)\`, and it carried two
|
|
2656
|
+
defects. An inline style cannot carry a fallback, so every engine without \`dvh\` (iOS
|
|
2657
|
+
Safari < 15.4, Chrome/WebView < 108, Samsung Internet < 21, Firefox < 101) dropped it
|
|
2658
|
+
whole; and the 64px came from a prop hard-coded to 64 on all 41 host pages that matches
|
|
2659
|
+
none of them \u2014 the burdenoff/algoshred chrome is 80px, the sticky-header sites are 65.
|
|
2660
|
+
|
|
2661
|
+
A class plus custom properties lets the cascade do the work: \`vh\` is the floor and \`dvh\`
|
|
2662
|
+
an upgrade where it exists, while the two measured values stay *lengths*, never a height.
|
|
2663
|
+
That distinction is the whole prerender contract. The host sites snapshot \`/explore\` by
|
|
2664
|
+
loading the built SPA in headless Chromium and writing the POST-HYDRATION DOM to
|
|
2665
|
+
dist/explore/index.html, so every attribute and inline value this component sets after
|
|
2666
|
+
mount IS the static HTML CloudFront serves. A measured pixel *height* would therefore
|
|
2667
|
+
hand every phone the prerender viewport's height until the bundle executes; a measured
|
|
2668
|
+
*offset* is a site-header height, which is the same on every device to within a few
|
|
2669
|
+
pixels, and the height built from it stays viewport-relative on the visitor's own screen.
|
|
2670
|
+
|
|
2671
|
+
--boff-explore-offset chrome above the pane (measured root top; the prop pre-measure)
|
|
2672
|
+
--boff-explore-inset the slice of the layout viewport hidden below the visible area \u2014
|
|
2673
|
+
the on-screen keyboard, which \`dvh\` does not track. Zero unless
|
|
2674
|
+
something is actually covering the bottom, so a snapshot taken
|
|
2675
|
+
with no keyboard open never carries it. */
|
|
2676
|
+
.boff-explore-viewport {
|
|
2677
|
+
height: calc(100vh - var(--boff-explore-offset, 0px) - var(--boff-explore-inset, 0px));
|
|
2678
|
+
}
|
|
2679
|
+
@supports (height: 100dvh) {
|
|
2680
|
+
.boff-explore-viewport {
|
|
2681
|
+
height: calc(100dvh - var(--boff-explore-offset, 0px) - var(--boff-explore-inset, 0px));
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
/* Landscape phones and other short viewports: a one-screen pane leaves a ~124px transcript
|
|
2686
|
+
sliver under ~610px of chrome and content. At or below the threshold the pane stops
|
|
2687
|
+
pretending to be a window and lets the page's own scrolling carry the transcript. The
|
|
2688
|
+
min-height is the available height rather than a fixed rem value, so the fallback can
|
|
2689
|
+
never be taller than the screen it is rescuing. */
|
|
2690
|
+
@media (max-height: ${SHORT_VIEWPORT_PX}px) {
|
|
2691
|
+
.boff-explore-viewport {
|
|
2692
|
+
height: auto;
|
|
2693
|
+
min-height: calc(100vh - var(--boff-explore-offset, 0px));
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
@supports (height: 100dvh) {
|
|
2697
|
+
@media (max-height: ${SHORT_VIEWPORT_PX}px) {
|
|
2698
|
+
.boff-explore-viewport {
|
|
2699
|
+
min-height: calc(100dvh - var(--boff-explore-offset, 0px));
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
/* ---- Composer dock --------------------------------------------------------------------
|
|
2705
|
+
Three declarations, each the fallback for the one after it: a plain 1rem where \`max()\`
|
|
2706
|
+
is unknown, then the measured overlap of any FOREIGN fixed chrome sitting over the
|
|
2707
|
+
composer (the host sites' cookie banner is 229px tall and lands exactly there), then the
|
|
2708
|
+
same plus the home-indicator inset. \`--boff-explore-chrome\` is set on the root only once
|
|
2709
|
+
an overlap has actually been measured, so everywhere else this collapses to 1rem. */
|
|
2710
|
+
.boff-explore-composer {
|
|
2711
|
+
padding-bottom: 1rem;
|
|
2712
|
+
padding-bottom: max(1rem, var(--boff-explore-chrome, 0px));
|
|
2713
|
+
padding-bottom: max(1rem, env(safe-area-inset-bottom), var(--boff-explore-chrome, 0px));
|
|
2714
|
+
}
|
|
2621
2715
|
`;
|
|
2622
2716
|
function ExploreStyles() {
|
|
2623
2717
|
return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: EXPLORE_CSS } });
|
|
@@ -2639,6 +2733,8 @@ var CAPABILITIES = [
|
|
|
2639
2733
|
body: "Get the sources and next steps \u2014 pricing, docs, a demo \u2014 without hunting."
|
|
2640
2734
|
}
|
|
2641
2735
|
];
|
|
2736
|
+
var MIN_VISIBLE_FRACTION = 0.25;
|
|
2737
|
+
var SDK_OVERLAY_SELECTOR = "[data-boff-explore]";
|
|
2642
2738
|
var CTA_VARIANTS = {
|
|
2643
2739
|
CONTACT: "default",
|
|
2644
2740
|
WAITLIST: "default",
|
|
@@ -2654,6 +2750,28 @@ function normalizeOffset(offset) {
|
|
|
2654
2750
|
if (offset === void 0) return "0px";
|
|
2655
2751
|
return typeof offset === "number" ? `${offset}px` : offset;
|
|
2656
2752
|
}
|
|
2753
|
+
function isOwnElement(el, root) {
|
|
2754
|
+
if (el === document.body || el === document.documentElement) return true;
|
|
2755
|
+
if (root.contains(el)) return true;
|
|
2756
|
+
return el.closest(SDK_OVERLAY_SELECTOR) !== null;
|
|
2757
|
+
}
|
|
2758
|
+
function visualViewportHeight() {
|
|
2759
|
+
return window.visualViewport?.height ?? window.innerHeight;
|
|
2760
|
+
}
|
|
2761
|
+
function clamp(value, min, max) {
|
|
2762
|
+
return Math.min(Math.max(value, min), max);
|
|
2763
|
+
}
|
|
2764
|
+
function isRestoredNavigation() {
|
|
2765
|
+
const entries = window.performance?.getEntriesByType?.("navigation");
|
|
2766
|
+
const entry = entries?.[0];
|
|
2767
|
+
if (!entry) return true;
|
|
2768
|
+
const navigation = entry;
|
|
2769
|
+
return navigation.type === "reload" || navigation.type === "back_forward";
|
|
2770
|
+
}
|
|
2771
|
+
function pageOwnsScrolling(el) {
|
|
2772
|
+
if (window.innerHeight > SHORT_VIEWPORT_PX) return false;
|
|
2773
|
+
return el.scrollHeight - el.clientHeight <= 1;
|
|
2774
|
+
}
|
|
2657
2775
|
function isInternalPath(url) {
|
|
2658
2776
|
return url.startsWith("/") && !url.startsWith("//");
|
|
2659
2777
|
}
|
|
@@ -2677,6 +2795,93 @@ function logoUrlOf(url) {
|
|
|
2677
2795
|
return null;
|
|
2678
2796
|
}
|
|
2679
2797
|
}
|
|
2798
|
+
function inlineImageOrigins(products) {
|
|
2799
|
+
const origins = /* @__PURE__ */ new Set();
|
|
2800
|
+
for (const product of products) {
|
|
2801
|
+
let url;
|
|
2802
|
+
try {
|
|
2803
|
+
url = new URL(product.website);
|
|
2804
|
+
} catch {
|
|
2805
|
+
continue;
|
|
2806
|
+
}
|
|
2807
|
+
if (url.protocol !== "https:") continue;
|
|
2808
|
+
const apex = url.hostname.replace(/^www\./, "");
|
|
2809
|
+
const port = url.port ? `:${url.port}` : "";
|
|
2810
|
+
origins.add(`https://${apex}${port}`);
|
|
2811
|
+
origins.add(`https://www.${apex}${port}`);
|
|
2812
|
+
}
|
|
2813
|
+
return origins;
|
|
2814
|
+
}
|
|
2815
|
+
function isInlineImageAllowed(src, origins) {
|
|
2816
|
+
if (typeof src !== "string" || src === "") return false;
|
|
2817
|
+
let url;
|
|
2818
|
+
try {
|
|
2819
|
+
url = new URL(src);
|
|
2820
|
+
} catch {
|
|
2821
|
+
return false;
|
|
2822
|
+
}
|
|
2823
|
+
if (url.protocol !== "https:" || url.username || url.password) return false;
|
|
2824
|
+
return origins.has(url.origin);
|
|
2825
|
+
}
|
|
2826
|
+
var InlineImageScopeContext = createContext(null);
|
|
2827
|
+
var InsideLinkContext = createContext(false);
|
|
2828
|
+
function AnswerLink(props) {
|
|
2829
|
+
return /* @__PURE__ */ jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsx(MarkdownLink, { ...props }) });
|
|
2830
|
+
}
|
|
2831
|
+
var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
|
|
2832
|
+
function InlineConceptImage({ src, alt }) {
|
|
2833
|
+
const scope = useContext(InlineImageScopeContext);
|
|
2834
|
+
const insideLink = useContext(InsideLinkContext);
|
|
2835
|
+
if (!scope || !scope.enabled || !isInlineImageAllowed(src, scope.origins) || scope.failed.has(src)) {
|
|
2836
|
+
return null;
|
|
2837
|
+
}
|
|
2838
|
+
const { strings: T, onFailed } = scope;
|
|
2839
|
+
const picture = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2840
|
+
/* @__PURE__ */ jsx(
|
|
2841
|
+
"img",
|
|
2842
|
+
{
|
|
2843
|
+
src,
|
|
2844
|
+
alt: alt ?? "",
|
|
2845
|
+
loading: "lazy",
|
|
2846
|
+
decoding: "async",
|
|
2847
|
+
onError: () => onFailed(src),
|
|
2848
|
+
className: "block h-auto max-h-80 w-auto max-w-full object-contain"
|
|
2849
|
+
}
|
|
2850
|
+
),
|
|
2851
|
+
/* @__PURE__ */ jsx(
|
|
2852
|
+
"span",
|
|
2853
|
+
{
|
|
2854
|
+
"aria-hidden": "true",
|
|
2855
|
+
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",
|
|
2856
|
+
children: T.conceptIllustration
|
|
2857
|
+
}
|
|
2858
|
+
)
|
|
2859
|
+
] });
|
|
2860
|
+
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(
|
|
2861
|
+
"a",
|
|
2862
|
+
{
|
|
2863
|
+
href: src,
|
|
2864
|
+
target: "_blank",
|
|
2865
|
+
rel: "noopener noreferrer",
|
|
2866
|
+
className: cn(
|
|
2867
|
+
INLINE_IMAGE_FRAME,
|
|
2868
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
2869
|
+
),
|
|
2870
|
+
children: [
|
|
2871
|
+
picture,
|
|
2872
|
+
/* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
2873
|
+
"(",
|
|
2874
|
+
T.opensInNewTab,
|
|
2875
|
+
")"
|
|
2876
|
+
] })
|
|
2877
|
+
]
|
|
2878
|
+
}
|
|
2879
|
+
) });
|
|
2880
|
+
}
|
|
2881
|
+
var ANSWER_MARKDOWN_COMPONENTS = {
|
|
2882
|
+
a: AnswerLink,
|
|
2883
|
+
img: InlineConceptImage
|
|
2884
|
+
};
|
|
2680
2885
|
function ReferenceCard({
|
|
2681
2886
|
reference,
|
|
2682
2887
|
onFollow
|
|
@@ -2859,6 +3064,7 @@ function AssistantBubble({
|
|
|
2859
3064
|
strings: T,
|
|
2860
3065
|
message,
|
|
2861
3066
|
activity,
|
|
3067
|
+
imageOrigins,
|
|
2862
3068
|
onNavigate,
|
|
2863
3069
|
anchorRef,
|
|
2864
3070
|
onFollow,
|
|
@@ -2867,6 +3073,25 @@ function AssistantBubble({
|
|
|
2867
3073
|
const streaming = message.status === "PENDING" || message.status === "RUNNING";
|
|
2868
3074
|
const body = message.content || message.partialContent || "";
|
|
2869
3075
|
const failed = message.status === "FAILED";
|
|
3076
|
+
const completed = message.status === "COMPLETED";
|
|
3077
|
+
const [failedImages, setFailedImages] = useState(
|
|
3078
|
+
() => /* @__PURE__ */ new Set()
|
|
3079
|
+
);
|
|
3080
|
+
const markImageFailed = useCallback((src) => {
|
|
3081
|
+
setFailedImages(
|
|
3082
|
+
(current) => current.has(src) ? current : new Set(current).add(src)
|
|
3083
|
+
);
|
|
3084
|
+
}, []);
|
|
3085
|
+
const imageScope = useMemo(
|
|
3086
|
+
() => ({
|
|
3087
|
+
strings: T,
|
|
3088
|
+
enabled: completed,
|
|
3089
|
+
origins: imageOrigins,
|
|
3090
|
+
failed: failedImages,
|
|
3091
|
+
onFailed: markImageFailed
|
|
3092
|
+
}),
|
|
3093
|
+
[T, completed, imageOrigins, failedImages, markImageFailed]
|
|
3094
|
+
);
|
|
2870
3095
|
return /* @__PURE__ */ jsxs(
|
|
2871
3096
|
"div",
|
|
2872
3097
|
{
|
|
@@ -2913,7 +3138,7 @@ function AssistantBubble({
|
|
|
2913
3138
|
}
|
|
2914
3139
|
) : null,
|
|
2915
3140
|
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 }) }),
|
|
3141
|
+
/* @__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
3142
|
streaming ? /* @__PURE__ */ jsx("span", { className: "boff-explore-caret", "aria-hidden": "true" }) : null
|
|
2918
3143
|
] }) : null,
|
|
2919
3144
|
streaming ? /* @__PURE__ */ jsx(ThinkingIndicator, { activity }) : null,
|
|
@@ -3395,6 +3620,8 @@ function ExplorePage({
|
|
|
3395
3620
|
const pickQueueRef = useRef(Promise.resolve());
|
|
3396
3621
|
const [shareLabel, setShareLabel] = useState(T.share);
|
|
3397
3622
|
const [shareUrl, setShareUrl] = useState(null);
|
|
3623
|
+
const rootRef = useRef(null);
|
|
3624
|
+
const composerRef = useRef(null);
|
|
3398
3625
|
const scrollRef = useRef(null);
|
|
3399
3626
|
const latestAssistantRef = useRef(null);
|
|
3400
3627
|
const alignedForRef = useRef(null);
|
|
@@ -3412,17 +3639,206 @@ function ExplorePage({
|
|
|
3412
3639
|
() => catalog.products.find((p) => p.slug === focusProduct)?.name ?? null,
|
|
3413
3640
|
[catalog.products, focusProduct]
|
|
3414
3641
|
);
|
|
3642
|
+
const imageOrigins = useMemo(
|
|
3643
|
+
() => inlineImageOrigins(catalog.products),
|
|
3644
|
+
[catalog.products]
|
|
3645
|
+
);
|
|
3415
3646
|
useEffect(() => {
|
|
3416
3647
|
const el = textareaRef.current;
|
|
3417
3648
|
if (!el) return;
|
|
3418
3649
|
el.style.height = "auto";
|
|
3419
3650
|
el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
|
|
3420
3651
|
}, [draft]);
|
|
3652
|
+
const [paneOffset, setPaneOffset] = useState(null);
|
|
3653
|
+
const [bottomInset, setBottomInset] = useState(0);
|
|
3654
|
+
const paneOffsetRef = useRef(0);
|
|
3655
|
+
const measurePane = useCallback(() => {
|
|
3656
|
+
if (heightMode !== "viewport") return;
|
|
3657
|
+
const el = rootRef.current;
|
|
3658
|
+
if (!el) return;
|
|
3659
|
+
const layoutHeight = window.innerHeight;
|
|
3660
|
+
if (layoutHeight === 0) return;
|
|
3661
|
+
const top = Math.round(
|
|
3662
|
+
clamp(el.getBoundingClientRect().top, 0, layoutHeight)
|
|
3663
|
+
);
|
|
3664
|
+
const viewport = window.visualViewport;
|
|
3665
|
+
const inset = viewport ? Math.round(
|
|
3666
|
+
clamp(
|
|
3667
|
+
layoutHeight - viewport.height - viewport.offsetTop,
|
|
3668
|
+
0,
|
|
3669
|
+
layoutHeight
|
|
3670
|
+
)
|
|
3671
|
+
) : 0;
|
|
3672
|
+
paneOffsetRef.current = top;
|
|
3673
|
+
setPaneOffset((current) => current === top ? current : top);
|
|
3674
|
+
setBottomInset((current) => current === inset ? current : inset);
|
|
3675
|
+
}, [heightMode]);
|
|
3676
|
+
const [chromeOverlap, setChromeOverlap] = useState(0);
|
|
3677
|
+
const measureChrome = useCallback(() => {
|
|
3678
|
+
const root = rootRef.current;
|
|
3679
|
+
const dock = composerRef.current;
|
|
3680
|
+
if (!root || !dock) return;
|
|
3681
|
+
if (typeof document.elementFromPoint !== "function") return;
|
|
3682
|
+
const viewportHeight = visualViewportHeight();
|
|
3683
|
+
const rect = dock.getBoundingClientRect();
|
|
3684
|
+
if (rect.width === 0 || viewportHeight === 0) return;
|
|
3685
|
+
if (rect.bottom <= 0 || rect.top >= viewportHeight) return;
|
|
3686
|
+
const edge = Math.min(rect.bottom, viewportHeight);
|
|
3687
|
+
const hit = document.elementFromPoint(rect.left + rect.width / 2, edge - 1);
|
|
3688
|
+
if (!hit || isOwnElement(hit, root)) {
|
|
3689
|
+
setChromeOverlap(0);
|
|
3690
|
+
return;
|
|
3691
|
+
}
|
|
3692
|
+
const overlap = Math.round(edge - hit.getBoundingClientRect().top);
|
|
3693
|
+
setChromeOverlap(overlap > 0 && overlap < viewportHeight ? overlap : 0);
|
|
3694
|
+
}, []);
|
|
3695
|
+
const remeasure = useCallback(() => {
|
|
3696
|
+
measurePane();
|
|
3697
|
+
measureChrome();
|
|
3698
|
+
}, [measurePane, measureChrome]);
|
|
3699
|
+
useEffect(() => {
|
|
3700
|
+
if (typeof window === "undefined") return;
|
|
3701
|
+
let frame = 0;
|
|
3702
|
+
const run = () => {
|
|
3703
|
+
frame = 0;
|
|
3704
|
+
remeasure();
|
|
3705
|
+
};
|
|
3706
|
+
const schedule = () => {
|
|
3707
|
+
if (frame) return;
|
|
3708
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
3709
|
+
remeasure();
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3712
|
+
frame = window.requestAnimationFrame(run);
|
|
3713
|
+
};
|
|
3714
|
+
remeasure();
|
|
3715
|
+
const viewport = window.visualViewport;
|
|
3716
|
+
window.addEventListener("resize", schedule);
|
|
3717
|
+
window.addEventListener("orientationchange", schedule);
|
|
3718
|
+
viewport?.addEventListener("resize", schedule);
|
|
3719
|
+
viewport?.addEventListener("scroll", schedule);
|
|
3720
|
+
const observer = typeof MutationObserver === "function" ? new MutationObserver((records) => {
|
|
3721
|
+
const el = rootRef.current;
|
|
3722
|
+
if (el && records.every((record) => el.contains(record.target)))
|
|
3723
|
+
return;
|
|
3724
|
+
schedule();
|
|
3725
|
+
}) : null;
|
|
3726
|
+
observer?.observe(document.body, { childList: true, subtree: true });
|
|
3727
|
+
return () => {
|
|
3728
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
3729
|
+
window.removeEventListener("resize", schedule);
|
|
3730
|
+
window.removeEventListener("orientationchange", schedule);
|
|
3731
|
+
viewport?.removeEventListener("resize", schedule);
|
|
3732
|
+
viewport?.removeEventListener("scroll", schedule);
|
|
3733
|
+
observer?.disconnect();
|
|
3734
|
+
setPaneOffset(null);
|
|
3735
|
+
setBottomInset(0);
|
|
3736
|
+
setChromeOverlap(0);
|
|
3737
|
+
};
|
|
3738
|
+
}, [remeasure]);
|
|
3739
|
+
useEffect(() => {
|
|
3740
|
+
measureChrome();
|
|
3741
|
+
}, [measureChrome, paneOffset, bottomInset]);
|
|
3742
|
+
useEffect(() => {
|
|
3743
|
+
if (heightMode !== "viewport" || typeof window === "undefined") return;
|
|
3744
|
+
const { history: browserHistory } = window;
|
|
3745
|
+
const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
|
|
3746
|
+
if (previousRestoration !== null)
|
|
3747
|
+
browserHistory.scrollRestoration = "manual";
|
|
3748
|
+
let frame = 0;
|
|
3749
|
+
let visitorMoved = false;
|
|
3750
|
+
const onVisitorMove = () => {
|
|
3751
|
+
visitorMoved = true;
|
|
3752
|
+
};
|
|
3753
|
+
const align = () => {
|
|
3754
|
+
if (visitorMoved) return;
|
|
3755
|
+
const el = rootRef.current;
|
|
3756
|
+
if (!el) return;
|
|
3757
|
+
const viewportHeight = visualViewportHeight();
|
|
3758
|
+
const rect = el.getBoundingClientRect();
|
|
3759
|
+
if (rect.height === 0 || viewportHeight === 0) return;
|
|
3760
|
+
const visible = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
|
|
3761
|
+
const reachable = Math.min(rect.height, viewportHeight);
|
|
3762
|
+
if (visible >= reachable * MIN_VISIBLE_FRACTION) return;
|
|
3763
|
+
window.scrollTo({
|
|
3764
|
+
top: Math.max(0, window.scrollY + rect.top),
|
|
3765
|
+
left: window.scrollX,
|
|
3766
|
+
behavior: "auto"
|
|
3767
|
+
});
|
|
3768
|
+
if (typeof document.elementFromPoint === "function") {
|
|
3769
|
+
const probe = document.elementFromPoint(
|
|
3770
|
+
Math.max(0, rect.left + rect.width / 2),
|
|
3771
|
+
1
|
|
3772
|
+
);
|
|
3773
|
+
if (probe && !isOwnElement(probe, el)) {
|
|
3774
|
+
const chrome = probe.getBoundingClientRect().bottom;
|
|
3775
|
+
if (chrome > 0 && chrome < viewportHeight / 2) {
|
|
3776
|
+
window.scrollBy({ top: -chrome, left: 0, behavior: "auto" });
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
remeasure();
|
|
3781
|
+
};
|
|
3782
|
+
const alignIfRestored = () => {
|
|
3783
|
+
if (!isRestoredNavigation()) return;
|
|
3784
|
+
align();
|
|
3785
|
+
};
|
|
3786
|
+
alignIfRestored();
|
|
3787
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
3788
|
+
frame = window.requestAnimationFrame(alignIfRestored);
|
|
3789
|
+
}
|
|
3790
|
+
const onPageShow = (event) => {
|
|
3791
|
+
if (!event.persisted) {
|
|
3792
|
+
alignIfRestored();
|
|
3793
|
+
return;
|
|
3794
|
+
}
|
|
3795
|
+
visitorMoved = false;
|
|
3796
|
+
align();
|
|
3797
|
+
};
|
|
3798
|
+
window.addEventListener("pageshow", onPageShow);
|
|
3799
|
+
window.addEventListener("wheel", onVisitorMove, { passive: true });
|
|
3800
|
+
window.addEventListener("touchmove", onVisitorMove, { passive: true });
|
|
3801
|
+
window.addEventListener("keydown", onVisitorMove, { passive: true });
|
|
3802
|
+
return () => {
|
|
3803
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
3804
|
+
window.removeEventListener("pageshow", onPageShow);
|
|
3805
|
+
window.removeEventListener("wheel", onVisitorMove);
|
|
3806
|
+
window.removeEventListener("touchmove", onVisitorMove);
|
|
3807
|
+
window.removeEventListener("keydown", onVisitorMove);
|
|
3808
|
+
if (previousRestoration !== null)
|
|
3809
|
+
browserHistory.scrollRestoration = previousRestoration;
|
|
3810
|
+
};
|
|
3811
|
+
}, [heightMode, remeasure]);
|
|
3421
3812
|
const handleScroll = useCallback(() => {
|
|
3422
3813
|
const el = scrollRef.current;
|
|
3423
3814
|
if (!el) return;
|
|
3424
3815
|
stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
|
|
3425
3816
|
}, []);
|
|
3817
|
+
useEffect(() => {
|
|
3818
|
+
if (typeof window === "undefined") return;
|
|
3819
|
+
let frame = 0;
|
|
3820
|
+
const run = () => {
|
|
3821
|
+
frame = 0;
|
|
3822
|
+
const el = scrollRef.current;
|
|
3823
|
+
const dock = composerRef.current;
|
|
3824
|
+
if (!el || !dock) return;
|
|
3825
|
+
if (!pageOwnsScrolling(el)) return;
|
|
3826
|
+
stickToBottomRef.current = dock.getBoundingClientRect().bottom - visualViewportHeight() < 80;
|
|
3827
|
+
};
|
|
3828
|
+
const schedule = () => {
|
|
3829
|
+
if (frame) return;
|
|
3830
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
3831
|
+
run();
|
|
3832
|
+
return;
|
|
3833
|
+
}
|
|
3834
|
+
frame = window.requestAnimationFrame(run);
|
|
3835
|
+
};
|
|
3836
|
+
window.addEventListener("scroll", schedule, { passive: true });
|
|
3837
|
+
return () => {
|
|
3838
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
3839
|
+
window.removeEventListener("scroll", schedule);
|
|
3840
|
+
};
|
|
3841
|
+
}, []);
|
|
3426
3842
|
const latestAssistantId = useMemo(() => {
|
|
3427
3843
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
3428
3844
|
const message = messages[i];
|
|
@@ -3438,16 +3854,32 @@ function ExplorePage({
|
|
|
3438
3854
|
if (!stickToBottomRef.current) return;
|
|
3439
3855
|
if (anchor.offsetHeight === 0) return;
|
|
3440
3856
|
alignedForRef.current = latestAssistantId;
|
|
3441
|
-
|
|
3442
|
-
|
|
3857
|
+
if (!pageOwnsScrolling(el)) {
|
|
3858
|
+
const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
|
|
3859
|
+
el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
|
|
3860
|
+
return;
|
|
3861
|
+
}
|
|
3862
|
+
const delta = Math.round(
|
|
3863
|
+
anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
|
|
3864
|
+
);
|
|
3865
|
+
if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
3443
3866
|
}, [latestAssistantId, messages]);
|
|
3444
3867
|
useEffect(() => {
|
|
3868
|
+
if (messages.length === 0) return;
|
|
3445
3869
|
if (!stickToBottomRef.current) return;
|
|
3446
3870
|
if (latestAssistantId && alignedForRef.current === latestAssistantId)
|
|
3447
3871
|
return;
|
|
3448
3872
|
const el = scrollRef.current;
|
|
3449
3873
|
if (!el) return;
|
|
3450
|
-
el
|
|
3874
|
+
if (!pageOwnsScrolling(el)) {
|
|
3875
|
+
el.scrollTop = el.scrollHeight;
|
|
3876
|
+
return;
|
|
3877
|
+
}
|
|
3878
|
+
const dock = composerRef.current ?? el;
|
|
3879
|
+
const delta = Math.round(
|
|
3880
|
+
dock.getBoundingClientRect().bottom - visualViewportHeight()
|
|
3881
|
+
);
|
|
3882
|
+
if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
3451
3883
|
}, [activity, latestAssistantId, messages]);
|
|
3452
3884
|
const handleShare = useCallback(async () => {
|
|
3453
3885
|
setShareLabel(T.copying);
|
|
@@ -3545,16 +3977,27 @@ function ExplorePage({
|
|
|
3545
3977
|
const captchaOn = Boolean(
|
|
3546
3978
|
catalog.captchaRequired && catalog.recaptchaSiteKey
|
|
3547
3979
|
);
|
|
3548
|
-
const rootStyle =
|
|
3980
|
+
const rootStyle = {};
|
|
3981
|
+
if (heightMode === "viewport") {
|
|
3982
|
+
rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
|
|
3983
|
+
if (bottomInset > 0) {
|
|
3984
|
+
rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
if (chromeOverlap > 0) {
|
|
3988
|
+
rootStyle["--boff-explore-chrome"] = `${chromeOverlap}px`;
|
|
3989
|
+
}
|
|
3549
3990
|
return /* @__PURE__ */ jsxs(
|
|
3550
3991
|
"div",
|
|
3551
3992
|
{
|
|
3993
|
+
ref: rootRef,
|
|
3552
3994
|
"data-boff-explore": "page",
|
|
3553
3995
|
"data-phase": phase,
|
|
3554
3996
|
"data-locale": activeLocale,
|
|
3555
3997
|
dir: rtl ? "rtl" : void 0,
|
|
3556
3998
|
className: cn(
|
|
3557
3999
|
"flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
|
|
4000
|
+
heightMode === "viewport" && "boff-explore-viewport",
|
|
3558
4001
|
heightMode === "auto" && "min-h-[70vh]",
|
|
3559
4002
|
className
|
|
3560
4003
|
),
|
|
@@ -3742,6 +4185,7 @@ function ExplorePage({
|
|
|
3742
4185
|
strings: T,
|
|
3743
4186
|
message,
|
|
3744
4187
|
activity,
|
|
4188
|
+
imageOrigins,
|
|
3745
4189
|
onNavigate,
|
|
3746
4190
|
anchorRef: message.id === latestAssistantId ? latestAssistantRef : void 0,
|
|
3747
4191
|
onFollow: (kind, url) => recordClick(message.id, kind, url),
|
|
@@ -3787,254 +4231,262 @@ function ExplorePage({
|
|
|
3787
4231
|
]
|
|
3788
4232
|
}
|
|
3789
4233
|
) : null,
|
|
3790
|
-
/* @__PURE__ */ jsx(
|
|
3791
|
-
"
|
|
4234
|
+
/* @__PURE__ */ jsx(
|
|
4235
|
+
"div",
|
|
3792
4236
|
{
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
"
|
|
4237
|
+
ref: composerRef,
|
|
4238
|
+
"data-boff-explore": "composer-dock",
|
|
4239
|
+
className: "boff-explore-composer border-t border-border bg-background/85 px-4 pt-3 backdrop-blur-md",
|
|
4240
|
+
children: /* @__PURE__ */ jsxs(
|
|
4241
|
+
"form",
|
|
4242
|
+
{
|
|
4243
|
+
"data-boff-explore": "composer",
|
|
4244
|
+
className: "mx-auto w-full max-w-3xl",
|
|
4245
|
+
onSubmit: (event) => {
|
|
4246
|
+
event.preventDefault();
|
|
4247
|
+
submitDraft();
|
|
4248
|
+
},
|
|
4249
|
+
children: [
|
|
4250
|
+
error ? /* @__PURE__ */ jsx(ErrorBanner, { error, onRetry: retry, onReset: reset }) : null,
|
|
4251
|
+
staged.length > 0 ? /* @__PURE__ */ jsx(
|
|
4252
|
+
"ul",
|
|
3809
4253
|
{
|
|
3810
|
-
"data-boff-explore": "
|
|
3811
|
-
"
|
|
3812
|
-
|
|
4254
|
+
"data-boff-explore": "attachments",
|
|
4255
|
+
className: "mb-2 flex flex-wrap gap-1.5",
|
|
4256
|
+
"aria-label": T.attach,
|
|
4257
|
+
children: staged.map((entry) => /* @__PURE__ */ jsxs(
|
|
4258
|
+
"li",
|
|
4259
|
+
{
|
|
4260
|
+
"data-boff-explore": "attachment",
|
|
4261
|
+
"data-text-extracted": entry.textExtracted ? "true" : "false",
|
|
4262
|
+
className: "flex max-w-full items-center gap-1.5 rounded-full border border-border bg-muted/60 py-1 pl-2.5 pr-1 text-xs",
|
|
4263
|
+
children: [
|
|
4264
|
+
/* @__PURE__ */ jsx(Paperclip, { className: "h-3 w-3 shrink-0 text-muted-foreground" }),
|
|
4265
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", title: entry.name, children: entry.name }),
|
|
4266
|
+
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
4267
|
+
formatBytes(entry.size),
|
|
4268
|
+
entry.textExtracted ? "" : ` \xB7 ${T.attachmentNameOnly}`
|
|
4269
|
+
] }),
|
|
4270
|
+
/* @__PURE__ */ jsx(
|
|
4271
|
+
"button",
|
|
4272
|
+
{
|
|
4273
|
+
type: "button",
|
|
4274
|
+
"data-boff-explore": "attachment-remove",
|
|
4275
|
+
onClick: () => removeAttachment(entry.id),
|
|
4276
|
+
"aria-label": fill(T.removeAttachment, { name: entry.name }),
|
|
4277
|
+
className: "ml-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-background hover:text-foreground",
|
|
4278
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
|
|
4279
|
+
}
|
|
4280
|
+
)
|
|
4281
|
+
]
|
|
4282
|
+
},
|
|
4283
|
+
entry.id
|
|
4284
|
+
))
|
|
4285
|
+
}
|
|
4286
|
+
) : null,
|
|
4287
|
+
attachmentNotice !== null ? /* @__PURE__ */ jsx(
|
|
4288
|
+
"p",
|
|
4289
|
+
{
|
|
4290
|
+
"data-boff-explore": "attachment-notice",
|
|
4291
|
+
role: "status",
|
|
4292
|
+
className: "mb-2 text-xs text-destructive",
|
|
4293
|
+
children: attachmentNotice
|
|
4294
|
+
}
|
|
4295
|
+
) : null,
|
|
4296
|
+
/* @__PURE__ */ jsxs(
|
|
4297
|
+
"div",
|
|
4298
|
+
{
|
|
4299
|
+
className: cn(
|
|
4300
|
+
"flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
|
|
4301
|
+
busy && "boff-explore-busy",
|
|
4302
|
+
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
|
|
4303
|
+
),
|
|
3813
4304
|
children: [
|
|
3814
|
-
/* @__PURE__ */ jsx(Paperclip, { className: "h-3 w-3 shrink-0 text-muted-foreground" }),
|
|
3815
|
-
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", title: entry.name, children: entry.name }),
|
|
3816
|
-
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
3817
|
-
formatBytes(entry.size),
|
|
3818
|
-
entry.textExtracted ? "" : ` \xB7 ${T.attachmentNameOnly}`
|
|
3819
|
-
] }),
|
|
3820
4305
|
/* @__PURE__ */ jsx(
|
|
3821
|
-
|
|
4306
|
+
Textarea,
|
|
4307
|
+
{
|
|
4308
|
+
ref: textareaRef,
|
|
4309
|
+
value: draft,
|
|
4310
|
+
rows: 1,
|
|
4311
|
+
disabled: composerDisabled,
|
|
4312
|
+
onChange: (event) => setDraft(event.target.value),
|
|
4313
|
+
onKeyDown: handleKeyDown,
|
|
4314
|
+
onCompositionStart: () => {
|
|
4315
|
+
composingRef.current = true;
|
|
4316
|
+
},
|
|
4317
|
+
onCompositionEnd: () => {
|
|
4318
|
+
composingRef.current = false;
|
|
4319
|
+
},
|
|
4320
|
+
"aria-label": "Ask a question",
|
|
4321
|
+
placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
|
|
4322
|
+
product: focusedProductName
|
|
4323
|
+
}) : T.placeholder,
|
|
4324
|
+
className: "max-h-[200px] min-h-[44px] w-full min-w-0 flex-1 resize-none border-0 bg-transparent px-2 py-2.5 text-base shadow-none focus-visible:ring-0 sm:text-sm"
|
|
4325
|
+
}
|
|
4326
|
+
),
|
|
4327
|
+
/* @__PURE__ */ jsx(
|
|
4328
|
+
"input",
|
|
4329
|
+
{
|
|
4330
|
+
ref: fileInputRef,
|
|
4331
|
+
type: "file",
|
|
4332
|
+
multiple: true,
|
|
4333
|
+
className: "hidden",
|
|
4334
|
+
onChange: (event) => {
|
|
4335
|
+
void handleFilesPicked(event.target.files);
|
|
4336
|
+
event.target.value = "";
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
),
|
|
4340
|
+
/* @__PURE__ */ jsx(
|
|
4341
|
+
Button,
|
|
4342
|
+
{
|
|
4343
|
+
"data-boff-explore": "attach",
|
|
4344
|
+
type: "button",
|
|
4345
|
+
size: "icon",
|
|
4346
|
+
variant: "ghost",
|
|
4347
|
+
disabled: composerDisabled || staged.length >= MAX_ATTACHMENTS,
|
|
4348
|
+
"aria-label": T.attach,
|
|
4349
|
+
title: `${T.attach} \u2014 ${fill(T.attachHint, {
|
|
4350
|
+
max: String(MAX_ATTACHMENTS),
|
|
4351
|
+
size: String(MAX_ATTACHMENT_BYTES / (1024 * 1024))
|
|
4352
|
+
})}`,
|
|
4353
|
+
onClick: () => fileInputRef.current?.click(),
|
|
4354
|
+
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
|
|
4355
|
+
}
|
|
4356
|
+
),
|
|
4357
|
+
speech.supported ? /* @__PURE__ */ jsx(
|
|
4358
|
+
Button,
|
|
3822
4359
|
{
|
|
4360
|
+
"data-boff-explore": "mic",
|
|
4361
|
+
"data-listening": speech.listening ? "true" : "false",
|
|
3823
4362
|
type: "button",
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
4363
|
+
size: "icon",
|
|
4364
|
+
variant: speech.listening ? "default" : "ghost",
|
|
4365
|
+
disabled: composerDisabled,
|
|
4366
|
+
"aria-label": speech.listening ? T.stopDictating : T.dictate,
|
|
4367
|
+
"aria-pressed": speech.listening,
|
|
4368
|
+
title: speech.listening ? T.stopDictating : T.dictate,
|
|
4369
|
+
onClick: speech.toggle,
|
|
4370
|
+
className: cn(speech.listening && "animate-pulse"),
|
|
4371
|
+
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
4372
|
+
}
|
|
4373
|
+
) : null,
|
|
4374
|
+
busy ? /* @__PURE__ */ jsx(
|
|
4375
|
+
Button,
|
|
4376
|
+
{
|
|
4377
|
+
"data-boff-explore": "stop",
|
|
4378
|
+
type: "button",
|
|
4379
|
+
size: "icon",
|
|
4380
|
+
variant: "secondary",
|
|
4381
|
+
"aria-label": T.stop,
|
|
4382
|
+
onClick: stop,
|
|
4383
|
+
children: /* @__PURE__ */ jsx(Square, { className: "h-4 w-4" })
|
|
4384
|
+
}
|
|
4385
|
+
) : /* @__PURE__ */ jsx(
|
|
4386
|
+
Button,
|
|
4387
|
+
{
|
|
4388
|
+
"data-boff-explore": "send",
|
|
4389
|
+
type: "submit",
|
|
4390
|
+
size: "icon",
|
|
4391
|
+
disabled: !canSubmit,
|
|
4392
|
+
"aria-label": T.send,
|
|
4393
|
+
children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" })
|
|
3829
4394
|
}
|
|
3830
4395
|
)
|
|
3831
4396
|
]
|
|
3832
|
-
}
|
|
3833
|
-
entry.id
|
|
3834
|
-
))
|
|
3835
|
-
}
|
|
3836
|
-
) : null,
|
|
3837
|
-
attachmentNotice !== null ? /* @__PURE__ */ jsx(
|
|
3838
|
-
"p",
|
|
3839
|
-
{
|
|
3840
|
-
"data-boff-explore": "attachment-notice",
|
|
3841
|
-
role: "status",
|
|
3842
|
-
className: "mb-2 text-xs text-destructive",
|
|
3843
|
-
children: attachmentNotice
|
|
3844
|
-
}
|
|
3845
|
-
) : null,
|
|
3846
|
-
/* @__PURE__ */ jsxs(
|
|
3847
|
-
"div",
|
|
3848
|
-
{
|
|
3849
|
-
className: cn(
|
|
3850
|
-
"flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
|
|
3851
|
-
busy && "boff-explore-busy",
|
|
3852
|
-
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
|
|
4397
|
+
}
|
|
3853
4398
|
),
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
4399
|
+
speech.listening || speech.interim !== "" ? /* @__PURE__ */ jsxs(
|
|
4400
|
+
"p",
|
|
4401
|
+
{
|
|
4402
|
+
"data-boff-explore": "dictation",
|
|
4403
|
+
className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground",
|
|
4404
|
+
"aria-live": "polite",
|
|
4405
|
+
children: [
|
|
4406
|
+
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2 shrink-0", children: [
|
|
4407
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
|
|
4408
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-primary" })
|
|
4409
|
+
] }),
|
|
4410
|
+
/* @__PURE__ */ jsx("span", { className: "italic", children: speech.interim !== "" ? speech.interim : "Listening\u2026" })
|
|
4411
|
+
]
|
|
4412
|
+
}
|
|
4413
|
+
) : null,
|
|
4414
|
+
speech.error !== null ? /* @__PURE__ */ jsx(
|
|
4415
|
+
"p",
|
|
4416
|
+
{
|
|
4417
|
+
"data-boff-explore": "dictation-error",
|
|
4418
|
+
className: "mt-2 text-xs text-destructive",
|
|
4419
|
+
children: speech.error
|
|
4420
|
+
}
|
|
4421
|
+
) : null,
|
|
4422
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
4423
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Enter to send \xB7 Shift + Enter for a new line" }),
|
|
4424
|
+
remainingToday !== null ? /* @__PURE__ */ jsxs("span", { "data-boff-explore": "remaining", children: [
|
|
4425
|
+
remainingToday,
|
|
4426
|
+
" message",
|
|
4427
|
+
remainingToday === 1 ? "" : "s",
|
|
4428
|
+
" left today"
|
|
4429
|
+
] }) : null,
|
|
4430
|
+
/* @__PURE__ */ jsxs(
|
|
4431
|
+
"span",
|
|
3857
4432
|
{
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
onCompositionEnd: () => {
|
|
3868
|
-
composingRef.current = false;
|
|
3869
|
-
},
|
|
3870
|
-
"aria-label": "Ask a question",
|
|
3871
|
-
placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
|
|
3872
|
-
product: focusedProductName
|
|
3873
|
-
}) : T.placeholder,
|
|
3874
|
-
className: "max-h-[200px] min-h-[44px] w-full min-w-0 flex-1 resize-none border-0 bg-transparent px-2 py-2.5 text-base shadow-none focus-visible:ring-0 sm:text-sm"
|
|
4433
|
+
className: cn(
|
|
4434
|
+
"ml-auto tabular-nums",
|
|
4435
|
+
overLimit && "font-medium text-destructive"
|
|
4436
|
+
),
|
|
4437
|
+
children: [
|
|
4438
|
+
draft.length.toLocaleString(),
|
|
4439
|
+
" / ",
|
|
4440
|
+
maxLength.toLocaleString()
|
|
4441
|
+
]
|
|
3875
4442
|
}
|
|
3876
|
-
)
|
|
4443
|
+
)
|
|
4444
|
+
] }),
|
|
4445
|
+
shareUrl ? /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
|
|
3877
4446
|
/* @__PURE__ */ jsx(
|
|
3878
4447
|
"input",
|
|
3879
4448
|
{
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
event.target.value = "";
|
|
3887
|
-
}
|
|
4449
|
+
"data-boff-explore": "share-url",
|
|
4450
|
+
readOnly: true,
|
|
4451
|
+
value: shareUrl,
|
|
4452
|
+
"aria-label": "Read-only link to this conversation",
|
|
4453
|
+
onFocus: (event) => event.currentTarget.select(),
|
|
4454
|
+
className: "min-w-0 flex-1 rounded-md border border-border bg-muted px-2 py-1 text-xs text-muted-foreground"
|
|
3888
4455
|
}
|
|
3889
4456
|
),
|
|
3890
4457
|
/* @__PURE__ */ jsx(
|
|
3891
|
-
|
|
3892
|
-
{
|
|
3893
|
-
"data-boff-explore": "attach",
|
|
3894
|
-
type: "button",
|
|
3895
|
-
size: "icon",
|
|
3896
|
-
variant: "ghost",
|
|
3897
|
-
disabled: composerDisabled || staged.length >= MAX_ATTACHMENTS,
|
|
3898
|
-
"aria-label": T.attach,
|
|
3899
|
-
title: `${T.attach} \u2014 ${fill(T.attachHint, {
|
|
3900
|
-
max: String(MAX_ATTACHMENTS),
|
|
3901
|
-
size: String(MAX_ATTACHMENT_BYTES / (1024 * 1024))
|
|
3902
|
-
})}`,
|
|
3903
|
-
onClick: () => fileInputRef.current?.click(),
|
|
3904
|
-
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
|
|
3905
|
-
}
|
|
3906
|
-
),
|
|
3907
|
-
speech.supported ? /* @__PURE__ */ jsx(
|
|
3908
|
-
Button,
|
|
4458
|
+
"button",
|
|
3909
4459
|
{
|
|
3910
|
-
"data-boff-explore": "mic",
|
|
3911
|
-
"data-listening": speech.listening ? "true" : "false",
|
|
3912
4460
|
type: "button",
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
"aria-label": speech.listening ? T.stopDictating : T.dictate,
|
|
3917
|
-
"aria-pressed": speech.listening,
|
|
3918
|
-
title: speech.listening ? T.stopDictating : T.dictate,
|
|
3919
|
-
onClick: speech.toggle,
|
|
3920
|
-
className: cn(speech.listening && "animate-pulse"),
|
|
3921
|
-
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
4461
|
+
className: "shrink-0 text-xs underline underline-offset-2",
|
|
4462
|
+
onClick: () => setShareUrl(null),
|
|
4463
|
+
children: "Done"
|
|
3922
4464
|
}
|
|
3923
|
-
)
|
|
3924
|
-
|
|
3925
|
-
|
|
4465
|
+
)
|
|
4466
|
+
] }) : null,
|
|
4467
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
4468
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
|
|
4469
|
+
/* @__PURE__ */ jsx(
|
|
4470
|
+
"button",
|
|
3926
4471
|
{
|
|
3927
|
-
"data-boff-explore": "stop",
|
|
3928
4472
|
type: "button",
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
"
|
|
3932
|
-
|
|
3933
|
-
children: /* @__PURE__ */ jsx(Square, { className: "h-4 w-4" })
|
|
3934
|
-
}
|
|
3935
|
-
) : /* @__PURE__ */ jsx(
|
|
3936
|
-
Button,
|
|
3937
|
-
{
|
|
3938
|
-
"data-boff-explore": "send",
|
|
3939
|
-
type: "submit",
|
|
3940
|
-
size: "icon",
|
|
3941
|
-
disabled: !canSubmit,
|
|
3942
|
-
"aria-label": T.send,
|
|
3943
|
-
children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" })
|
|
4473
|
+
"data-boff-explore": "disclaimer",
|
|
4474
|
+
onClick: () => setDisclaimerOpen(true),
|
|
4475
|
+
className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
4476
|
+
children: T.disclaimer
|
|
3944
4477
|
}
|
|
3945
4478
|
)
|
|
3946
|
-
]
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
"p",
|
|
3951
|
-
{
|
|
3952
|
-
"data-boff-explore": "dictation",
|
|
3953
|
-
className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground",
|
|
3954
|
-
"aria-live": "polite",
|
|
3955
|
-
children: [
|
|
3956
|
-
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2 shrink-0", children: [
|
|
3957
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
|
|
3958
|
-
/* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-primary" })
|
|
3959
|
-
] }),
|
|
3960
|
-
/* @__PURE__ */ jsx("span", { className: "italic", children: speech.interim !== "" ? speech.interim : "Listening\u2026" })
|
|
3961
|
-
]
|
|
3962
|
-
}
|
|
3963
|
-
) : null,
|
|
3964
|
-
speech.error !== null ? /* @__PURE__ */ jsx(
|
|
3965
|
-
"p",
|
|
3966
|
-
{
|
|
3967
|
-
"data-boff-explore": "dictation-error",
|
|
3968
|
-
className: "mt-2 text-xs text-destructive",
|
|
3969
|
-
children: speech.error
|
|
3970
|
-
}
|
|
3971
|
-
) : null,
|
|
3972
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
3973
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Enter to send \xB7 Shift + Enter for a new line" }),
|
|
3974
|
-
remainingToday !== null ? /* @__PURE__ */ jsxs("span", { "data-boff-explore": "remaining", children: [
|
|
3975
|
-
remainingToday,
|
|
3976
|
-
" message",
|
|
3977
|
-
remainingToday === 1 ? "" : "s",
|
|
3978
|
-
" left today"
|
|
3979
|
-
] }) : null,
|
|
3980
|
-
/* @__PURE__ */ jsxs(
|
|
3981
|
-
"span",
|
|
3982
|
-
{
|
|
3983
|
-
className: cn(
|
|
3984
|
-
"ml-auto tabular-nums",
|
|
3985
|
-
overLimit && "font-medium text-destructive"
|
|
3986
|
-
),
|
|
3987
|
-
children: [
|
|
3988
|
-
draft.length.toLocaleString(),
|
|
3989
|
-
" / ",
|
|
3990
|
-
maxLength.toLocaleString()
|
|
3991
|
-
]
|
|
3992
|
-
}
|
|
3993
|
-
)
|
|
3994
|
-
] }),
|
|
3995
|
-
shareUrl ? /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
|
|
3996
|
-
/* @__PURE__ */ jsx(
|
|
3997
|
-
"input",
|
|
3998
|
-
{
|
|
3999
|
-
"data-boff-explore": "share-url",
|
|
4000
|
-
readOnly: true,
|
|
4001
|
-
value: shareUrl,
|
|
4002
|
-
"aria-label": "Read-only link to this conversation",
|
|
4003
|
-
onFocus: (event) => event.currentTarget.select(),
|
|
4004
|
-
className: "min-w-0 flex-1 rounded-md border border-border bg-muted px-2 py-1 text-xs text-muted-foreground"
|
|
4005
|
-
}
|
|
4006
|
-
),
|
|
4007
|
-
/* @__PURE__ */ jsx(
|
|
4008
|
-
"button",
|
|
4009
|
-
{
|
|
4010
|
-
type: "button",
|
|
4011
|
-
className: "shrink-0 text-xs underline underline-offset-2",
|
|
4012
|
-
onClick: () => setShareUrl(null),
|
|
4013
|
-
children: "Done"
|
|
4014
|
-
}
|
|
4015
|
-
)
|
|
4016
|
-
] }) : null,
|
|
4017
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
4018
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
|
|
4019
|
-
/* @__PURE__ */ jsx(
|
|
4020
|
-
"button",
|
|
4021
|
-
{
|
|
4022
|
-
type: "button",
|
|
4023
|
-
"data-boff-explore": "disclaimer",
|
|
4024
|
-
onClick: () => setDisclaimerOpen(true),
|
|
4025
|
-
className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
4026
|
-
children: T.disclaimer
|
|
4027
|
-
}
|
|
4028
|
-
)
|
|
4029
|
-
] })
|
|
4030
|
-
]
|
|
4479
|
+
] })
|
|
4480
|
+
]
|
|
4481
|
+
}
|
|
4482
|
+
)
|
|
4031
4483
|
}
|
|
4032
|
-
)
|
|
4484
|
+
)
|
|
4033
4485
|
]
|
|
4034
4486
|
}
|
|
4035
4487
|
);
|
|
4036
4488
|
}
|
|
4037
4489
|
|
|
4038
|
-
export { ExplorePage, logoUrlOf };
|
|
4490
|
+
export { ExplorePage, inlineImageOrigins, isInlineImageAllowed, logoUrlOf };
|
|
4039
4491
|
//# sourceMappingURL=explore.mjs.map
|
|
4040
4492
|
//# sourceMappingURL=explore.mjs.map
|