@burdenoff/website-sdk 2026.921.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 +2 -2
- package/dist/components/explore.d.mts +10 -2
- package/dist/components/explore.d.ts +10 -2
- package/dist/components/explore.js +536 -221
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +536 -221
- package/dist/components/explore.mjs.map +1 -1
- package/dist/index.js +536 -221
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +536 -221
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7999,6 +7999,7 @@ function toPayload(staged) {
|
|
|
7999
7999
|
textContent
|
|
8000
8000
|
}));
|
|
8001
8001
|
}
|
|
8002
|
+
var SHORT_VIEWPORT_PX = 420;
|
|
8002
8003
|
var EXPLORE_CSS = `
|
|
8003
8004
|
@keyframes boff-explore-pulse {
|
|
8004
8005
|
0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
|
|
@@ -8033,6 +8034,12 @@ var EXPLORE_CSS = `
|
|
|
8033
8034
|
.boff-explore-scroll {
|
|
8034
8035
|
scrollbar-width: thin;
|
|
8035
8036
|
scrollbar-color: hsl(var(--border)) transparent;
|
|
8037
|
+
/* Stop the transcript handing its scroll to the page. Without this, the first
|
|
8038
|
+
swipe that exhausts the transcript chains to the document \u2014 and on a host site
|
|
8039
|
+
that is 65-70% footer, which is how a phone ends up showing nothing but the
|
|
8040
|
+
footer. Engines that do not support this property ignore the line and keep
|
|
8041
|
+
today's behaviour; the scroll correction above covers them. */
|
|
8042
|
+
overscroll-behavior: contain;
|
|
8036
8043
|
}
|
|
8037
8044
|
.boff-explore-scroll::-webkit-scrollbar { width: 10px; }
|
|
8038
8045
|
.boff-explore-scroll::-webkit-scrollbar-track { background: transparent; }
|
|
@@ -8150,6 +8157,68 @@ var EXPLORE_CSS = `
|
|
|
8150
8157
|
.boff-explore-busy::after { animation: none; }
|
|
8151
8158
|
.boff-explore-rise { animation: none; opacity: 1; transform: none; }
|
|
8152
8159
|
}
|
|
8160
|
+
|
|
8161
|
+
/* ---- Pane height ----------------------------------------------------------------------
|
|
8162
|
+
This used to be one inline declaration, \`height: calc(100dvh - 64px)\`, and it carried two
|
|
8163
|
+
defects. An inline style cannot carry a fallback, so every engine without \`dvh\` (iOS
|
|
8164
|
+
Safari < 15.4, Chrome/WebView < 108, Samsung Internet < 21, Firefox < 101) dropped it
|
|
8165
|
+
whole; and the 64px came from a prop hard-coded to 64 on all 41 host pages that matches
|
|
8166
|
+
none of them \u2014 the burdenoff/algoshred chrome is 80px, the sticky-header sites are 65.
|
|
8167
|
+
|
|
8168
|
+
A class plus custom properties lets the cascade do the work: \`vh\` is the floor and \`dvh\`
|
|
8169
|
+
an upgrade where it exists, while the two measured values stay *lengths*, never a height.
|
|
8170
|
+
That distinction is the whole prerender contract. The host sites snapshot \`/explore\` by
|
|
8171
|
+
loading the built SPA in headless Chromium and writing the POST-HYDRATION DOM to
|
|
8172
|
+
dist/explore/index.html, so every attribute and inline value this component sets after
|
|
8173
|
+
mount IS the static HTML CloudFront serves. A measured pixel *height* would therefore
|
|
8174
|
+
hand every phone the prerender viewport's height until the bundle executes; a measured
|
|
8175
|
+
*offset* is a site-header height, which is the same on every device to within a few
|
|
8176
|
+
pixels, and the height built from it stays viewport-relative on the visitor's own screen.
|
|
8177
|
+
|
|
8178
|
+
--boff-explore-offset chrome above the pane (measured root top; the prop pre-measure)
|
|
8179
|
+
--boff-explore-inset the slice of the layout viewport hidden below the visible area \u2014
|
|
8180
|
+
the on-screen keyboard, which \`dvh\` does not track. Zero unless
|
|
8181
|
+
something is actually covering the bottom, so a snapshot taken
|
|
8182
|
+
with no keyboard open never carries it. */
|
|
8183
|
+
.boff-explore-viewport {
|
|
8184
|
+
height: calc(100vh - var(--boff-explore-offset, 0px) - var(--boff-explore-inset, 0px));
|
|
8185
|
+
}
|
|
8186
|
+
@supports (height: 100dvh) {
|
|
8187
|
+
.boff-explore-viewport {
|
|
8188
|
+
height: calc(100dvh - var(--boff-explore-offset, 0px) - var(--boff-explore-inset, 0px));
|
|
8189
|
+
}
|
|
8190
|
+
}
|
|
8191
|
+
|
|
8192
|
+
/* Landscape phones and other short viewports: a one-screen pane leaves a ~124px transcript
|
|
8193
|
+
sliver under ~610px of chrome and content. At or below the threshold the pane stops
|
|
8194
|
+
pretending to be a window and lets the page's own scrolling carry the transcript. The
|
|
8195
|
+
min-height is the available height rather than a fixed rem value, so the fallback can
|
|
8196
|
+
never be taller than the screen it is rescuing. */
|
|
8197
|
+
@media (max-height: ${SHORT_VIEWPORT_PX}px) {
|
|
8198
|
+
.boff-explore-viewport {
|
|
8199
|
+
height: auto;
|
|
8200
|
+
min-height: calc(100vh - var(--boff-explore-offset, 0px));
|
|
8201
|
+
}
|
|
8202
|
+
}
|
|
8203
|
+
@supports (height: 100dvh) {
|
|
8204
|
+
@media (max-height: ${SHORT_VIEWPORT_PX}px) {
|
|
8205
|
+
.boff-explore-viewport {
|
|
8206
|
+
min-height: calc(100dvh - var(--boff-explore-offset, 0px));
|
|
8207
|
+
}
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
8210
|
+
|
|
8211
|
+
/* ---- Composer dock --------------------------------------------------------------------
|
|
8212
|
+
Three declarations, each the fallback for the one after it: a plain 1rem where \`max()\`
|
|
8213
|
+
is unknown, then the measured overlap of any FOREIGN fixed chrome sitting over the
|
|
8214
|
+
composer (the host sites' cookie banner is 229px tall and lands exactly there), then the
|
|
8215
|
+
same plus the home-indicator inset. \`--boff-explore-chrome\` is set on the root only once
|
|
8216
|
+
an overlap has actually been measured, so everywhere else this collapses to 1rem. */
|
|
8217
|
+
.boff-explore-composer {
|
|
8218
|
+
padding-bottom: 1rem;
|
|
8219
|
+
padding-bottom: max(1rem, var(--boff-explore-chrome, 0px));
|
|
8220
|
+
padding-bottom: max(1rem, env(safe-area-inset-bottom), var(--boff-explore-chrome, 0px));
|
|
8221
|
+
}
|
|
8153
8222
|
`;
|
|
8154
8223
|
function ExploreStyles() {
|
|
8155
8224
|
return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: EXPLORE_CSS } });
|
|
@@ -8171,6 +8240,8 @@ var CAPABILITIES = [
|
|
|
8171
8240
|
body: "Get the sources and next steps \u2014 pricing, docs, a demo \u2014 without hunting."
|
|
8172
8241
|
}
|
|
8173
8242
|
];
|
|
8243
|
+
var MIN_VISIBLE_FRACTION = 0.25;
|
|
8244
|
+
var SDK_OVERLAY_SELECTOR = "[data-boff-explore]";
|
|
8174
8245
|
var CTA_VARIANTS = {
|
|
8175
8246
|
CONTACT: "default",
|
|
8176
8247
|
WAITLIST: "default",
|
|
@@ -8186,6 +8257,28 @@ function normalizeOffset(offset) {
|
|
|
8186
8257
|
if (offset === void 0) return "0px";
|
|
8187
8258
|
return typeof offset === "number" ? `${offset}px` : offset;
|
|
8188
8259
|
}
|
|
8260
|
+
function isOwnElement(el, root) {
|
|
8261
|
+
if (el === document.body || el === document.documentElement) return true;
|
|
8262
|
+
if (root.contains(el)) return true;
|
|
8263
|
+
return el.closest(SDK_OVERLAY_SELECTOR) !== null;
|
|
8264
|
+
}
|
|
8265
|
+
function visualViewportHeight() {
|
|
8266
|
+
return window.visualViewport?.height ?? window.innerHeight;
|
|
8267
|
+
}
|
|
8268
|
+
function clamp(value, min, max) {
|
|
8269
|
+
return Math.min(Math.max(value, min), max);
|
|
8270
|
+
}
|
|
8271
|
+
function isRestoredNavigation() {
|
|
8272
|
+
const entries = window.performance?.getEntriesByType?.("navigation");
|
|
8273
|
+
const entry = entries?.[0];
|
|
8274
|
+
if (!entry) return true;
|
|
8275
|
+
const navigation = entry;
|
|
8276
|
+
return navigation.type === "reload" || navigation.type === "back_forward";
|
|
8277
|
+
}
|
|
8278
|
+
function pageOwnsScrolling(el) {
|
|
8279
|
+
if (window.innerHeight > SHORT_VIEWPORT_PX) return false;
|
|
8280
|
+
return el.scrollHeight - el.clientHeight <= 1;
|
|
8281
|
+
}
|
|
8189
8282
|
function isInternalPath(url) {
|
|
8190
8283
|
return url.startsWith("/") && !url.startsWith("//");
|
|
8191
8284
|
}
|
|
@@ -9034,6 +9127,8 @@ function ExplorePage({
|
|
|
9034
9127
|
const pickQueueRef = useRef(Promise.resolve());
|
|
9035
9128
|
const [shareLabel, setShareLabel] = useState(T.share);
|
|
9036
9129
|
const [shareUrl, setShareUrl] = useState(null);
|
|
9130
|
+
const rootRef = useRef(null);
|
|
9131
|
+
const composerRef = useRef(null);
|
|
9037
9132
|
const scrollRef = useRef(null);
|
|
9038
9133
|
const latestAssistantRef = useRef(null);
|
|
9039
9134
|
const alignedForRef = useRef(null);
|
|
@@ -9061,11 +9156,196 @@ function ExplorePage({
|
|
|
9061
9156
|
el.style.height = "auto";
|
|
9062
9157
|
el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
|
|
9063
9158
|
}, [draft]);
|
|
9159
|
+
const [paneOffset, setPaneOffset] = useState(null);
|
|
9160
|
+
const [bottomInset, setBottomInset] = useState(0);
|
|
9161
|
+
const paneOffsetRef = useRef(0);
|
|
9162
|
+
const measurePane = useCallback(() => {
|
|
9163
|
+
if (heightMode !== "viewport") return;
|
|
9164
|
+
const el = rootRef.current;
|
|
9165
|
+
if (!el) return;
|
|
9166
|
+
const layoutHeight = window.innerHeight;
|
|
9167
|
+
if (layoutHeight === 0) return;
|
|
9168
|
+
const top = Math.round(
|
|
9169
|
+
clamp(el.getBoundingClientRect().top, 0, layoutHeight)
|
|
9170
|
+
);
|
|
9171
|
+
const viewport = window.visualViewport;
|
|
9172
|
+
const inset = viewport ? Math.round(
|
|
9173
|
+
clamp(
|
|
9174
|
+
layoutHeight - viewport.height - viewport.offsetTop,
|
|
9175
|
+
0,
|
|
9176
|
+
layoutHeight
|
|
9177
|
+
)
|
|
9178
|
+
) : 0;
|
|
9179
|
+
paneOffsetRef.current = top;
|
|
9180
|
+
setPaneOffset((current) => current === top ? current : top);
|
|
9181
|
+
setBottomInset((current) => current === inset ? current : inset);
|
|
9182
|
+
}, [heightMode]);
|
|
9183
|
+
const [chromeOverlap, setChromeOverlap] = useState(0);
|
|
9184
|
+
const measureChrome = useCallback(() => {
|
|
9185
|
+
const root = rootRef.current;
|
|
9186
|
+
const dock = composerRef.current;
|
|
9187
|
+
if (!root || !dock) return;
|
|
9188
|
+
if (typeof document.elementFromPoint !== "function") return;
|
|
9189
|
+
const viewportHeight = visualViewportHeight();
|
|
9190
|
+
const rect = dock.getBoundingClientRect();
|
|
9191
|
+
if (rect.width === 0 || viewportHeight === 0) return;
|
|
9192
|
+
if (rect.bottom <= 0 || rect.top >= viewportHeight) return;
|
|
9193
|
+
const edge = Math.min(rect.bottom, viewportHeight);
|
|
9194
|
+
const hit = document.elementFromPoint(rect.left + rect.width / 2, edge - 1);
|
|
9195
|
+
if (!hit || isOwnElement(hit, root)) {
|
|
9196
|
+
setChromeOverlap(0);
|
|
9197
|
+
return;
|
|
9198
|
+
}
|
|
9199
|
+
const overlap = Math.round(edge - hit.getBoundingClientRect().top);
|
|
9200
|
+
setChromeOverlap(overlap > 0 && overlap < viewportHeight ? overlap : 0);
|
|
9201
|
+
}, []);
|
|
9202
|
+
const remeasure = useCallback(() => {
|
|
9203
|
+
measurePane();
|
|
9204
|
+
measureChrome();
|
|
9205
|
+
}, [measurePane, measureChrome]);
|
|
9206
|
+
useEffect(() => {
|
|
9207
|
+
if (typeof window === "undefined") return;
|
|
9208
|
+
let frame = 0;
|
|
9209
|
+
const run = () => {
|
|
9210
|
+
frame = 0;
|
|
9211
|
+
remeasure();
|
|
9212
|
+
};
|
|
9213
|
+
const schedule = () => {
|
|
9214
|
+
if (frame) return;
|
|
9215
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
9216
|
+
remeasure();
|
|
9217
|
+
return;
|
|
9218
|
+
}
|
|
9219
|
+
frame = window.requestAnimationFrame(run);
|
|
9220
|
+
};
|
|
9221
|
+
remeasure();
|
|
9222
|
+
const viewport = window.visualViewport;
|
|
9223
|
+
window.addEventListener("resize", schedule);
|
|
9224
|
+
window.addEventListener("orientationchange", schedule);
|
|
9225
|
+
viewport?.addEventListener("resize", schedule);
|
|
9226
|
+
viewport?.addEventListener("scroll", schedule);
|
|
9227
|
+
const observer = typeof MutationObserver === "function" ? new MutationObserver((records) => {
|
|
9228
|
+
const el = rootRef.current;
|
|
9229
|
+
if (el && records.every((record) => el.contains(record.target)))
|
|
9230
|
+
return;
|
|
9231
|
+
schedule();
|
|
9232
|
+
}) : null;
|
|
9233
|
+
observer?.observe(document.body, { childList: true, subtree: true });
|
|
9234
|
+
return () => {
|
|
9235
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
9236
|
+
window.removeEventListener("resize", schedule);
|
|
9237
|
+
window.removeEventListener("orientationchange", schedule);
|
|
9238
|
+
viewport?.removeEventListener("resize", schedule);
|
|
9239
|
+
viewport?.removeEventListener("scroll", schedule);
|
|
9240
|
+
observer?.disconnect();
|
|
9241
|
+
setPaneOffset(null);
|
|
9242
|
+
setBottomInset(0);
|
|
9243
|
+
setChromeOverlap(0);
|
|
9244
|
+
};
|
|
9245
|
+
}, [remeasure]);
|
|
9246
|
+
useEffect(() => {
|
|
9247
|
+
measureChrome();
|
|
9248
|
+
}, [measureChrome, paneOffset, bottomInset]);
|
|
9249
|
+
useEffect(() => {
|
|
9250
|
+
if (heightMode !== "viewport" || typeof window === "undefined") return;
|
|
9251
|
+
const { history: browserHistory } = window;
|
|
9252
|
+
const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
|
|
9253
|
+
if (previousRestoration !== null)
|
|
9254
|
+
browserHistory.scrollRestoration = "manual";
|
|
9255
|
+
let frame = 0;
|
|
9256
|
+
let visitorMoved = false;
|
|
9257
|
+
const onVisitorMove = () => {
|
|
9258
|
+
visitorMoved = true;
|
|
9259
|
+
};
|
|
9260
|
+
const align = () => {
|
|
9261
|
+
if (visitorMoved) return;
|
|
9262
|
+
const el = rootRef.current;
|
|
9263
|
+
if (!el) return;
|
|
9264
|
+
const viewportHeight = visualViewportHeight();
|
|
9265
|
+
const rect = el.getBoundingClientRect();
|
|
9266
|
+
if (rect.height === 0 || viewportHeight === 0) return;
|
|
9267
|
+
const visible = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
|
|
9268
|
+
const reachable = Math.min(rect.height, viewportHeight);
|
|
9269
|
+
if (visible >= reachable * MIN_VISIBLE_FRACTION) return;
|
|
9270
|
+
window.scrollTo({
|
|
9271
|
+
top: Math.max(0, window.scrollY + rect.top),
|
|
9272
|
+
left: window.scrollX,
|
|
9273
|
+
behavior: "auto"
|
|
9274
|
+
});
|
|
9275
|
+
if (typeof document.elementFromPoint === "function") {
|
|
9276
|
+
const probe = document.elementFromPoint(
|
|
9277
|
+
Math.max(0, rect.left + rect.width / 2),
|
|
9278
|
+
1
|
|
9279
|
+
);
|
|
9280
|
+
if (probe && !isOwnElement(probe, el)) {
|
|
9281
|
+
const chrome = probe.getBoundingClientRect().bottom;
|
|
9282
|
+
if (chrome > 0 && chrome < viewportHeight / 2) {
|
|
9283
|
+
window.scrollBy({ top: -chrome, left: 0, behavior: "auto" });
|
|
9284
|
+
}
|
|
9285
|
+
}
|
|
9286
|
+
}
|
|
9287
|
+
remeasure();
|
|
9288
|
+
};
|
|
9289
|
+
const alignIfRestored = () => {
|
|
9290
|
+
if (!isRestoredNavigation()) return;
|
|
9291
|
+
align();
|
|
9292
|
+
};
|
|
9293
|
+
alignIfRestored();
|
|
9294
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
9295
|
+
frame = window.requestAnimationFrame(alignIfRestored);
|
|
9296
|
+
}
|
|
9297
|
+
const onPageShow = (event) => {
|
|
9298
|
+
if (!event.persisted) {
|
|
9299
|
+
alignIfRestored();
|
|
9300
|
+
return;
|
|
9301
|
+
}
|
|
9302
|
+
visitorMoved = false;
|
|
9303
|
+
align();
|
|
9304
|
+
};
|
|
9305
|
+
window.addEventListener("pageshow", onPageShow);
|
|
9306
|
+
window.addEventListener("wheel", onVisitorMove, { passive: true });
|
|
9307
|
+
window.addEventListener("touchmove", onVisitorMove, { passive: true });
|
|
9308
|
+
window.addEventListener("keydown", onVisitorMove, { passive: true });
|
|
9309
|
+
return () => {
|
|
9310
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
9311
|
+
window.removeEventListener("pageshow", onPageShow);
|
|
9312
|
+
window.removeEventListener("wheel", onVisitorMove);
|
|
9313
|
+
window.removeEventListener("touchmove", onVisitorMove);
|
|
9314
|
+
window.removeEventListener("keydown", onVisitorMove);
|
|
9315
|
+
if (previousRestoration !== null)
|
|
9316
|
+
browserHistory.scrollRestoration = previousRestoration;
|
|
9317
|
+
};
|
|
9318
|
+
}, [heightMode, remeasure]);
|
|
9064
9319
|
const handleScroll = useCallback(() => {
|
|
9065
9320
|
const el = scrollRef.current;
|
|
9066
9321
|
if (!el) return;
|
|
9067
9322
|
stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
|
|
9068
9323
|
}, []);
|
|
9324
|
+
useEffect(() => {
|
|
9325
|
+
if (typeof window === "undefined") return;
|
|
9326
|
+
let frame = 0;
|
|
9327
|
+
const run = () => {
|
|
9328
|
+
frame = 0;
|
|
9329
|
+
const el = scrollRef.current;
|
|
9330
|
+
const dock = composerRef.current;
|
|
9331
|
+
if (!el || !dock) return;
|
|
9332
|
+
if (!pageOwnsScrolling(el)) return;
|
|
9333
|
+
stickToBottomRef.current = dock.getBoundingClientRect().bottom - visualViewportHeight() < 80;
|
|
9334
|
+
};
|
|
9335
|
+
const schedule = () => {
|
|
9336
|
+
if (frame) return;
|
|
9337
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
9338
|
+
run();
|
|
9339
|
+
return;
|
|
9340
|
+
}
|
|
9341
|
+
frame = window.requestAnimationFrame(run);
|
|
9342
|
+
};
|
|
9343
|
+
window.addEventListener("scroll", schedule, { passive: true });
|
|
9344
|
+
return () => {
|
|
9345
|
+
if (frame) window.cancelAnimationFrame(frame);
|
|
9346
|
+
window.removeEventListener("scroll", schedule);
|
|
9347
|
+
};
|
|
9348
|
+
}, []);
|
|
9069
9349
|
const latestAssistantId = useMemo(() => {
|
|
9070
9350
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
9071
9351
|
const message = messages[i];
|
|
@@ -9081,16 +9361,32 @@ function ExplorePage({
|
|
|
9081
9361
|
if (!stickToBottomRef.current) return;
|
|
9082
9362
|
if (anchor.offsetHeight === 0) return;
|
|
9083
9363
|
alignedForRef.current = latestAssistantId;
|
|
9084
|
-
|
|
9085
|
-
|
|
9364
|
+
if (!pageOwnsScrolling(el)) {
|
|
9365
|
+
const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
|
|
9366
|
+
el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
|
|
9367
|
+
return;
|
|
9368
|
+
}
|
|
9369
|
+
const delta = Math.round(
|
|
9370
|
+
anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
|
|
9371
|
+
);
|
|
9372
|
+
if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
9086
9373
|
}, [latestAssistantId, messages]);
|
|
9087
9374
|
useEffect(() => {
|
|
9375
|
+
if (messages.length === 0) return;
|
|
9088
9376
|
if (!stickToBottomRef.current) return;
|
|
9089
9377
|
if (latestAssistantId && alignedForRef.current === latestAssistantId)
|
|
9090
9378
|
return;
|
|
9091
9379
|
const el = scrollRef.current;
|
|
9092
9380
|
if (!el) return;
|
|
9093
|
-
el
|
|
9381
|
+
if (!pageOwnsScrolling(el)) {
|
|
9382
|
+
el.scrollTop = el.scrollHeight;
|
|
9383
|
+
return;
|
|
9384
|
+
}
|
|
9385
|
+
const dock = composerRef.current ?? el;
|
|
9386
|
+
const delta = Math.round(
|
|
9387
|
+
dock.getBoundingClientRect().bottom - visualViewportHeight()
|
|
9388
|
+
);
|
|
9389
|
+
if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
|
|
9094
9390
|
}, [activity, latestAssistantId, messages]);
|
|
9095
9391
|
const handleShare = useCallback(async () => {
|
|
9096
9392
|
setShareLabel(T.copying);
|
|
@@ -9188,16 +9484,27 @@ function ExplorePage({
|
|
|
9188
9484
|
const captchaOn = Boolean(
|
|
9189
9485
|
catalog.captchaRequired && catalog.recaptchaSiteKey
|
|
9190
9486
|
);
|
|
9191
|
-
const rootStyle =
|
|
9487
|
+
const rootStyle = {};
|
|
9488
|
+
if (heightMode === "viewport") {
|
|
9489
|
+
rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
|
|
9490
|
+
if (bottomInset > 0) {
|
|
9491
|
+
rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
|
|
9492
|
+
}
|
|
9493
|
+
}
|
|
9494
|
+
if (chromeOverlap > 0) {
|
|
9495
|
+
rootStyle["--boff-explore-chrome"] = `${chromeOverlap}px`;
|
|
9496
|
+
}
|
|
9192
9497
|
return /* @__PURE__ */ jsxs(
|
|
9193
9498
|
"div",
|
|
9194
9499
|
{
|
|
9500
|
+
ref: rootRef,
|
|
9195
9501
|
"data-boff-explore": "page",
|
|
9196
9502
|
"data-phase": phase,
|
|
9197
9503
|
"data-locale": activeLocale,
|
|
9198
9504
|
dir: rtl ? "rtl" : void 0,
|
|
9199
9505
|
className: cn(
|
|
9200
9506
|
"flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
|
|
9507
|
+
heightMode === "viewport" && "boff-explore-viewport",
|
|
9201
9508
|
heightMode === "auto" && "min-h-[70vh]",
|
|
9202
9509
|
className
|
|
9203
9510
|
),
|
|
@@ -9431,249 +9738,257 @@ function ExplorePage({
|
|
|
9431
9738
|
]
|
|
9432
9739
|
}
|
|
9433
9740
|
) : null,
|
|
9434
|
-
/* @__PURE__ */ jsx(
|
|
9435
|
-
"
|
|
9741
|
+
/* @__PURE__ */ jsx(
|
|
9742
|
+
"div",
|
|
9436
9743
|
{
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
"
|
|
9744
|
+
ref: composerRef,
|
|
9745
|
+
"data-boff-explore": "composer-dock",
|
|
9746
|
+
className: "boff-explore-composer border-t border-border bg-background/85 px-4 pt-3 backdrop-blur-md",
|
|
9747
|
+
children: /* @__PURE__ */ jsxs(
|
|
9748
|
+
"form",
|
|
9749
|
+
{
|
|
9750
|
+
"data-boff-explore": "composer",
|
|
9751
|
+
className: "mx-auto w-full max-w-3xl",
|
|
9752
|
+
onSubmit: (event) => {
|
|
9753
|
+
event.preventDefault();
|
|
9754
|
+
submitDraft();
|
|
9755
|
+
},
|
|
9756
|
+
children: [
|
|
9757
|
+
error ? /* @__PURE__ */ jsx(ErrorBanner, { error, onRetry: retry, onReset: reset }) : null,
|
|
9758
|
+
staged.length > 0 ? /* @__PURE__ */ jsx(
|
|
9759
|
+
"ul",
|
|
9760
|
+
{
|
|
9761
|
+
"data-boff-explore": "attachments",
|
|
9762
|
+
className: "mb-2 flex flex-wrap gap-1.5",
|
|
9763
|
+
"aria-label": T.attach,
|
|
9764
|
+
children: staged.map((entry) => /* @__PURE__ */ jsxs(
|
|
9765
|
+
"li",
|
|
9766
|
+
{
|
|
9767
|
+
"data-boff-explore": "attachment",
|
|
9768
|
+
"data-text-extracted": entry.textExtracted ? "true" : "false",
|
|
9769
|
+
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",
|
|
9770
|
+
children: [
|
|
9771
|
+
/* @__PURE__ */ jsx(Paperclip, { className: "h-3 w-3 shrink-0 text-muted-foreground" }),
|
|
9772
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", title: entry.name, children: entry.name }),
|
|
9773
|
+
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
9774
|
+
formatBytes(entry.size),
|
|
9775
|
+
entry.textExtracted ? "" : ` \xB7 ${T.attachmentNameOnly}`
|
|
9776
|
+
] }),
|
|
9777
|
+
/* @__PURE__ */ jsx(
|
|
9778
|
+
"button",
|
|
9779
|
+
{
|
|
9780
|
+
type: "button",
|
|
9781
|
+
"data-boff-explore": "attachment-remove",
|
|
9782
|
+
onClick: () => removeAttachment(entry.id),
|
|
9783
|
+
"aria-label": fill(T.removeAttachment, { name: entry.name }),
|
|
9784
|
+
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",
|
|
9785
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
|
|
9786
|
+
}
|
|
9787
|
+
)
|
|
9788
|
+
]
|
|
9789
|
+
},
|
|
9790
|
+
entry.id
|
|
9791
|
+
))
|
|
9792
|
+
}
|
|
9793
|
+
) : null,
|
|
9794
|
+
attachmentNotice !== null ? /* @__PURE__ */ jsx(
|
|
9795
|
+
"p",
|
|
9453
9796
|
{
|
|
9454
|
-
"data-boff-explore": "attachment",
|
|
9455
|
-
|
|
9456
|
-
className: "
|
|
9797
|
+
"data-boff-explore": "attachment-notice",
|
|
9798
|
+
role: "status",
|
|
9799
|
+
className: "mb-2 text-xs text-destructive",
|
|
9800
|
+
children: attachmentNotice
|
|
9801
|
+
}
|
|
9802
|
+
) : null,
|
|
9803
|
+
/* @__PURE__ */ jsxs(
|
|
9804
|
+
"div",
|
|
9805
|
+
{
|
|
9806
|
+
className: cn(
|
|
9807
|
+
"flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
|
|
9808
|
+
busy && "boff-explore-busy",
|
|
9809
|
+
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
|
|
9810
|
+
),
|
|
9457
9811
|
children: [
|
|
9458
|
-
/* @__PURE__ */ jsx(Paperclip, { className: "h-3 w-3 shrink-0 text-muted-foreground" }),
|
|
9459
|
-
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", title: entry.name, children: entry.name }),
|
|
9460
|
-
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
9461
|
-
formatBytes(entry.size),
|
|
9462
|
-
entry.textExtracted ? "" : ` \xB7 ${T.attachmentNameOnly}`
|
|
9463
|
-
] }),
|
|
9464
9812
|
/* @__PURE__ */ jsx(
|
|
9465
|
-
|
|
9813
|
+
Textarea,
|
|
9466
9814
|
{
|
|
9815
|
+
ref: textareaRef,
|
|
9816
|
+
value: draft,
|
|
9817
|
+
rows: 1,
|
|
9818
|
+
disabled: composerDisabled,
|
|
9819
|
+
onChange: (event) => setDraft(event.target.value),
|
|
9820
|
+
onKeyDown: handleKeyDown,
|
|
9821
|
+
onCompositionStart: () => {
|
|
9822
|
+
composingRef.current = true;
|
|
9823
|
+
},
|
|
9824
|
+
onCompositionEnd: () => {
|
|
9825
|
+
composingRef.current = false;
|
|
9826
|
+
},
|
|
9827
|
+
"aria-label": "Ask a question",
|
|
9828
|
+
placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
|
|
9829
|
+
product: focusedProductName
|
|
9830
|
+
}) : T.placeholder,
|
|
9831
|
+
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"
|
|
9832
|
+
}
|
|
9833
|
+
),
|
|
9834
|
+
/* @__PURE__ */ jsx(
|
|
9835
|
+
"input",
|
|
9836
|
+
{
|
|
9837
|
+
ref: fileInputRef,
|
|
9838
|
+
type: "file",
|
|
9839
|
+
multiple: true,
|
|
9840
|
+
className: "hidden",
|
|
9841
|
+
onChange: (event) => {
|
|
9842
|
+
void handleFilesPicked(event.target.files);
|
|
9843
|
+
event.target.value = "";
|
|
9844
|
+
}
|
|
9845
|
+
}
|
|
9846
|
+
),
|
|
9847
|
+
/* @__PURE__ */ jsx(
|
|
9848
|
+
Button,
|
|
9849
|
+
{
|
|
9850
|
+
"data-boff-explore": "attach",
|
|
9851
|
+
type: "button",
|
|
9852
|
+
size: "icon",
|
|
9853
|
+
variant: "ghost",
|
|
9854
|
+
disabled: composerDisabled || staged.length >= MAX_ATTACHMENTS,
|
|
9855
|
+
"aria-label": T.attach,
|
|
9856
|
+
title: `${T.attach} \u2014 ${fill(T.attachHint, {
|
|
9857
|
+
max: String(MAX_ATTACHMENTS),
|
|
9858
|
+
size: String(MAX_ATTACHMENT_BYTES / (1024 * 1024))
|
|
9859
|
+
})}`,
|
|
9860
|
+
onClick: () => fileInputRef.current?.click(),
|
|
9861
|
+
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
|
|
9862
|
+
}
|
|
9863
|
+
),
|
|
9864
|
+
speech.supported ? /* @__PURE__ */ jsx(
|
|
9865
|
+
Button,
|
|
9866
|
+
{
|
|
9867
|
+
"data-boff-explore": "mic",
|
|
9868
|
+
"data-listening": speech.listening ? "true" : "false",
|
|
9467
9869
|
type: "button",
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9870
|
+
size: "icon",
|
|
9871
|
+
variant: speech.listening ? "default" : "ghost",
|
|
9872
|
+
disabled: composerDisabled,
|
|
9873
|
+
"aria-label": speech.listening ? T.stopDictating : T.dictate,
|
|
9874
|
+
"aria-pressed": speech.listening,
|
|
9875
|
+
title: speech.listening ? T.stopDictating : T.dictate,
|
|
9876
|
+
onClick: speech.toggle,
|
|
9877
|
+
className: cn(speech.listening && "animate-pulse"),
|
|
9878
|
+
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
9879
|
+
}
|
|
9880
|
+
) : null,
|
|
9881
|
+
busy ? /* @__PURE__ */ jsx(
|
|
9882
|
+
Button,
|
|
9883
|
+
{
|
|
9884
|
+
"data-boff-explore": "stop",
|
|
9885
|
+
type: "button",
|
|
9886
|
+
size: "icon",
|
|
9887
|
+
variant: "secondary",
|
|
9888
|
+
"aria-label": T.stop,
|
|
9889
|
+
onClick: stop,
|
|
9890
|
+
children: /* @__PURE__ */ jsx(Square, { className: "h-4 w-4" })
|
|
9891
|
+
}
|
|
9892
|
+
) : /* @__PURE__ */ jsx(
|
|
9893
|
+
Button,
|
|
9894
|
+
{
|
|
9895
|
+
"data-boff-explore": "send",
|
|
9896
|
+
type: "submit",
|
|
9897
|
+
size: "icon",
|
|
9898
|
+
disabled: !canSubmit,
|
|
9899
|
+
"aria-label": T.send,
|
|
9900
|
+
children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" })
|
|
9473
9901
|
}
|
|
9474
9902
|
)
|
|
9475
9903
|
]
|
|
9476
|
-
}
|
|
9477
|
-
entry.id
|
|
9478
|
-
))
|
|
9479
|
-
}
|
|
9480
|
-
) : null,
|
|
9481
|
-
attachmentNotice !== null ? /* @__PURE__ */ jsx(
|
|
9482
|
-
"p",
|
|
9483
|
-
{
|
|
9484
|
-
"data-boff-explore": "attachment-notice",
|
|
9485
|
-
role: "status",
|
|
9486
|
-
className: "mb-2 text-xs text-destructive",
|
|
9487
|
-
children: attachmentNotice
|
|
9488
|
-
}
|
|
9489
|
-
) : null,
|
|
9490
|
-
/* @__PURE__ */ jsxs(
|
|
9491
|
-
"div",
|
|
9492
|
-
{
|
|
9493
|
-
className: cn(
|
|
9494
|
-
"flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
|
|
9495
|
-
busy && "boff-explore-busy",
|
|
9496
|
-
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
|
|
9904
|
+
}
|
|
9497
9905
|
),
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9906
|
+
speech.listening || speech.interim !== "" ? /* @__PURE__ */ jsxs(
|
|
9907
|
+
"p",
|
|
9908
|
+
{
|
|
9909
|
+
"data-boff-explore": "dictation",
|
|
9910
|
+
className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground",
|
|
9911
|
+
"aria-live": "polite",
|
|
9912
|
+
children: [
|
|
9913
|
+
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2 shrink-0", children: [
|
|
9914
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
|
|
9915
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-primary" })
|
|
9916
|
+
] }),
|
|
9917
|
+
/* @__PURE__ */ jsx("span", { className: "italic", children: speech.interim !== "" ? speech.interim : "Listening\u2026" })
|
|
9918
|
+
]
|
|
9919
|
+
}
|
|
9920
|
+
) : null,
|
|
9921
|
+
speech.error !== null ? /* @__PURE__ */ jsx(
|
|
9922
|
+
"p",
|
|
9923
|
+
{
|
|
9924
|
+
"data-boff-explore": "dictation-error",
|
|
9925
|
+
className: "mt-2 text-xs text-destructive",
|
|
9926
|
+
children: speech.error
|
|
9927
|
+
}
|
|
9928
|
+
) : null,
|
|
9929
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
9930
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Enter to send \xB7 Shift + Enter for a new line" }),
|
|
9931
|
+
remainingToday !== null ? /* @__PURE__ */ jsxs("span", { "data-boff-explore": "remaining", children: [
|
|
9932
|
+
remainingToday,
|
|
9933
|
+
" message",
|
|
9934
|
+
remainingToday === 1 ? "" : "s",
|
|
9935
|
+
" left today"
|
|
9936
|
+
] }) : null,
|
|
9937
|
+
/* @__PURE__ */ jsxs(
|
|
9938
|
+
"span",
|
|
9501
9939
|
{
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
onCompositionEnd: () => {
|
|
9512
|
-
composingRef.current = false;
|
|
9513
|
-
},
|
|
9514
|
-
"aria-label": "Ask a question",
|
|
9515
|
-
placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
|
|
9516
|
-
product: focusedProductName
|
|
9517
|
-
}) : T.placeholder,
|
|
9518
|
-
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"
|
|
9940
|
+
className: cn(
|
|
9941
|
+
"ml-auto tabular-nums",
|
|
9942
|
+
overLimit && "font-medium text-destructive"
|
|
9943
|
+
),
|
|
9944
|
+
children: [
|
|
9945
|
+
draft.length.toLocaleString(),
|
|
9946
|
+
" / ",
|
|
9947
|
+
maxLength.toLocaleString()
|
|
9948
|
+
]
|
|
9519
9949
|
}
|
|
9520
|
-
)
|
|
9950
|
+
)
|
|
9951
|
+
] }),
|
|
9952
|
+
shareUrl ? /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
|
|
9521
9953
|
/* @__PURE__ */ jsx(
|
|
9522
9954
|
"input",
|
|
9523
9955
|
{
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
event.target.value = "";
|
|
9531
|
-
}
|
|
9956
|
+
"data-boff-explore": "share-url",
|
|
9957
|
+
readOnly: true,
|
|
9958
|
+
value: shareUrl,
|
|
9959
|
+
"aria-label": "Read-only link to this conversation",
|
|
9960
|
+
onFocus: (event) => event.currentTarget.select(),
|
|
9961
|
+
className: "min-w-0 flex-1 rounded-md border border-border bg-muted px-2 py-1 text-xs text-muted-foreground"
|
|
9532
9962
|
}
|
|
9533
9963
|
),
|
|
9534
9964
|
/* @__PURE__ */ jsx(
|
|
9535
|
-
|
|
9965
|
+
"button",
|
|
9536
9966
|
{
|
|
9537
|
-
"data-boff-explore": "attach",
|
|
9538
9967
|
type: "button",
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
"aria-label": T.attach,
|
|
9543
|
-
title: `${T.attach} \u2014 ${fill(T.attachHint, {
|
|
9544
|
-
max: String(MAX_ATTACHMENTS),
|
|
9545
|
-
size: String(MAX_ATTACHMENT_BYTES / (1024 * 1024))
|
|
9546
|
-
})}`,
|
|
9547
|
-
onClick: () => fileInputRef.current?.click(),
|
|
9548
|
-
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
|
|
9968
|
+
className: "shrink-0 text-xs underline underline-offset-2",
|
|
9969
|
+
onClick: () => setShareUrl(null),
|
|
9970
|
+
children: "Done"
|
|
9549
9971
|
}
|
|
9550
|
-
)
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
type: "button",
|
|
9557
|
-
size: "icon",
|
|
9558
|
-
variant: speech.listening ? "default" : "ghost",
|
|
9559
|
-
disabled: composerDisabled,
|
|
9560
|
-
"aria-label": speech.listening ? T.stopDictating : T.dictate,
|
|
9561
|
-
"aria-pressed": speech.listening,
|
|
9562
|
-
title: speech.listening ? T.stopDictating : T.dictate,
|
|
9563
|
-
onClick: speech.toggle,
|
|
9564
|
-
className: cn(speech.listening && "animate-pulse"),
|
|
9565
|
-
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
9566
|
-
}
|
|
9567
|
-
) : null,
|
|
9568
|
-
busy ? /* @__PURE__ */ jsx(
|
|
9569
|
-
Button,
|
|
9972
|
+
)
|
|
9973
|
+
] }) : null,
|
|
9974
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
9975
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
|
|
9976
|
+
/* @__PURE__ */ jsx(
|
|
9977
|
+
"button",
|
|
9570
9978
|
{
|
|
9571
|
-
"data-boff-explore": "stop",
|
|
9572
9979
|
type: "button",
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
"
|
|
9576
|
-
|
|
9577
|
-
children: /* @__PURE__ */ jsx(Square, { className: "h-4 w-4" })
|
|
9578
|
-
}
|
|
9579
|
-
) : /* @__PURE__ */ jsx(
|
|
9580
|
-
Button,
|
|
9581
|
-
{
|
|
9582
|
-
"data-boff-explore": "send",
|
|
9583
|
-
type: "submit",
|
|
9584
|
-
size: "icon",
|
|
9585
|
-
disabled: !canSubmit,
|
|
9586
|
-
"aria-label": T.send,
|
|
9587
|
-
children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" })
|
|
9980
|
+
"data-boff-explore": "disclaimer",
|
|
9981
|
+
onClick: () => setDisclaimerOpen(true),
|
|
9982
|
+
className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
9983
|
+
children: T.disclaimer
|
|
9588
9984
|
}
|
|
9589
9985
|
)
|
|
9590
|
-
]
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
"p",
|
|
9595
|
-
{
|
|
9596
|
-
"data-boff-explore": "dictation",
|
|
9597
|
-
className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground",
|
|
9598
|
-
"aria-live": "polite",
|
|
9599
|
-
children: [
|
|
9600
|
-
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2 shrink-0", children: [
|
|
9601
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
|
|
9602
|
-
/* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-primary" })
|
|
9603
|
-
] }),
|
|
9604
|
-
/* @__PURE__ */ jsx("span", { className: "italic", children: speech.interim !== "" ? speech.interim : "Listening\u2026" })
|
|
9605
|
-
]
|
|
9606
|
-
}
|
|
9607
|
-
) : null,
|
|
9608
|
-
speech.error !== null ? /* @__PURE__ */ jsx(
|
|
9609
|
-
"p",
|
|
9610
|
-
{
|
|
9611
|
-
"data-boff-explore": "dictation-error",
|
|
9612
|
-
className: "mt-2 text-xs text-destructive",
|
|
9613
|
-
children: speech.error
|
|
9614
|
-
}
|
|
9615
|
-
) : null,
|
|
9616
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
9617
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Enter to send \xB7 Shift + Enter for a new line" }),
|
|
9618
|
-
remainingToday !== null ? /* @__PURE__ */ jsxs("span", { "data-boff-explore": "remaining", children: [
|
|
9619
|
-
remainingToday,
|
|
9620
|
-
" message",
|
|
9621
|
-
remainingToday === 1 ? "" : "s",
|
|
9622
|
-
" left today"
|
|
9623
|
-
] }) : null,
|
|
9624
|
-
/* @__PURE__ */ jsxs(
|
|
9625
|
-
"span",
|
|
9626
|
-
{
|
|
9627
|
-
className: cn(
|
|
9628
|
-
"ml-auto tabular-nums",
|
|
9629
|
-
overLimit && "font-medium text-destructive"
|
|
9630
|
-
),
|
|
9631
|
-
children: [
|
|
9632
|
-
draft.length.toLocaleString(),
|
|
9633
|
-
" / ",
|
|
9634
|
-
maxLength.toLocaleString()
|
|
9635
|
-
]
|
|
9636
|
-
}
|
|
9637
|
-
)
|
|
9638
|
-
] }),
|
|
9639
|
-
shareUrl ? /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
|
|
9640
|
-
/* @__PURE__ */ jsx(
|
|
9641
|
-
"input",
|
|
9642
|
-
{
|
|
9643
|
-
"data-boff-explore": "share-url",
|
|
9644
|
-
readOnly: true,
|
|
9645
|
-
value: shareUrl,
|
|
9646
|
-
"aria-label": "Read-only link to this conversation",
|
|
9647
|
-
onFocus: (event) => event.currentTarget.select(),
|
|
9648
|
-
className: "min-w-0 flex-1 rounded-md border border-border bg-muted px-2 py-1 text-xs text-muted-foreground"
|
|
9649
|
-
}
|
|
9650
|
-
),
|
|
9651
|
-
/* @__PURE__ */ jsx(
|
|
9652
|
-
"button",
|
|
9653
|
-
{
|
|
9654
|
-
type: "button",
|
|
9655
|
-
className: "shrink-0 text-xs underline underline-offset-2",
|
|
9656
|
-
onClick: () => setShareUrl(null),
|
|
9657
|
-
children: "Done"
|
|
9658
|
-
}
|
|
9659
|
-
)
|
|
9660
|
-
] }) : null,
|
|
9661
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
9662
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
|
|
9663
|
-
/* @__PURE__ */ jsx(
|
|
9664
|
-
"button",
|
|
9665
|
-
{
|
|
9666
|
-
type: "button",
|
|
9667
|
-
"data-boff-explore": "disclaimer",
|
|
9668
|
-
onClick: () => setDisclaimerOpen(true),
|
|
9669
|
-
className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
9670
|
-
children: T.disclaimer
|
|
9671
|
-
}
|
|
9672
|
-
)
|
|
9673
|
-
] })
|
|
9674
|
-
]
|
|
9986
|
+
] })
|
|
9987
|
+
]
|
|
9988
|
+
}
|
|
9989
|
+
)
|
|
9675
9990
|
}
|
|
9676
|
-
)
|
|
9991
|
+
)
|
|
9677
9992
|
]
|
|
9678
9993
|
}
|
|
9679
9994
|
);
|