@burdenoff/website-sdk 2026.828.6 → 2026.829.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/dist/components/explore.js +402 -190
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +404 -192
- package/dist/components/explore.mjs.map +1 -1
- package/dist/hooks/index.js +111 -69
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +111 -69
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +402 -190
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +402 -190
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1523,23 +1523,37 @@ function getRecognitionCtor() {
|
|
|
1523
1523
|
const w = window;
|
|
1524
1524
|
return w.SpeechRecognition ?? w.webkitSpeechRecognition ?? null;
|
|
1525
1525
|
}
|
|
1526
|
+
function isTouchDevice() {
|
|
1527
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1528
|
+
try {
|
|
1529
|
+
return window.matchMedia("(pointer: coarse)").matches;
|
|
1530
|
+
} catch {
|
|
1531
|
+
return false;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1526
1534
|
var MIC_DENIED_MESSAGE = "Microphone access was blocked. Allow it in your browser's site settings to dictate.";
|
|
1535
|
+
var MIC_UNAVAILABLE_MESSAGE = "Dictation isn't available in this browser. You can type instead.";
|
|
1536
|
+
var RELEASE_SETTLE_MS = 250;
|
|
1537
|
+
var RETRY_DELAY_MS = 350;
|
|
1538
|
+
var sleep = (ms) => new Promise((resolve) => {
|
|
1539
|
+
setTimeout(resolve, ms);
|
|
1540
|
+
});
|
|
1527
1541
|
async function ensureMicrophoneAccess() {
|
|
1528
1542
|
const media = typeof navigator === "undefined" ? void 0 : navigator.mediaDevices;
|
|
1529
|
-
if (!media?.getUserMedia)
|
|
1543
|
+
if (!media?.getUserMedia)
|
|
1544
|
+
return { ok: true, confirmed: false, primed: false };
|
|
1530
1545
|
try {
|
|
1531
1546
|
const status = await navigator.permissions?.query({
|
|
1532
1547
|
name: "microphone"
|
|
1533
1548
|
});
|
|
1534
|
-
if (status?.state === "granted")
|
|
1535
|
-
|
|
1536
|
-
return { ok: false, message: MIC_DENIED_MESSAGE };
|
|
1549
|
+
if (status?.state === "granted")
|
|
1550
|
+
return { ok: true, confirmed: true, primed: false };
|
|
1537
1551
|
} catch {
|
|
1538
1552
|
}
|
|
1539
1553
|
try {
|
|
1540
1554
|
const stream = await media.getUserMedia({ audio: true });
|
|
1541
1555
|
for (const track of stream.getTracks()) track.stop();
|
|
1542
|
-
return { ok: true };
|
|
1556
|
+
return { ok: true, confirmed: true, primed: true };
|
|
1543
1557
|
} catch (error) {
|
|
1544
1558
|
const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
|
|
1545
1559
|
if (name === "NotAllowedError" || name === "SecurityError") {
|
|
@@ -1582,19 +1596,18 @@ function useSpeechInput({
|
|
|
1582
1596
|
const [error, setError] = React.useState(null);
|
|
1583
1597
|
const recognitionRef = React.useRef(null);
|
|
1584
1598
|
const startTokenRef = React.useRef(0);
|
|
1585
|
-
const
|
|
1586
|
-
const
|
|
1587
|
-
|
|
1588
|
-
beginRecognitionRef.current?.(Ctor, token);
|
|
1589
|
-
},
|
|
1590
|
-
[]
|
|
1591
|
-
);
|
|
1599
|
+
const micConfirmedRef = React.useRef(false);
|
|
1600
|
+
const wantsListeningRef = React.useRef(false);
|
|
1601
|
+
const retriedRef = React.useRef(false);
|
|
1592
1602
|
const finalRef = React.useRef(onFinalTranscript);
|
|
1593
1603
|
const errorRef = React.useRef(onError);
|
|
1594
1604
|
finalRef.current = onFinalTranscript;
|
|
1595
1605
|
errorRef.current = onError;
|
|
1606
|
+
const langRef = React.useRef(lang);
|
|
1607
|
+
langRef.current = lang;
|
|
1596
1608
|
const stop = React.useCallback(() => {
|
|
1597
1609
|
startTokenRef.current += 1;
|
|
1610
|
+
wantsListeningRef.current = false;
|
|
1598
1611
|
setListening(false);
|
|
1599
1612
|
setInterim("");
|
|
1600
1613
|
const recognition = recognitionRef.current;
|
|
@@ -1603,82 +1616,111 @@ function useSpeechInput({
|
|
|
1603
1616
|
recognition.stop();
|
|
1604
1617
|
} catch {
|
|
1605
1618
|
}
|
|
1606
|
-
setListening(false);
|
|
1607
|
-
setInterim("");
|
|
1608
1619
|
}, []);
|
|
1609
|
-
const
|
|
1620
|
+
const openSession = React.useCallback((token) => {
|
|
1610
1621
|
const Ctor = getRecognitionCtor();
|
|
1611
|
-
if (!Ctor) return;
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1622
|
+
if (!Ctor || token !== startTokenRef.current) return;
|
|
1623
|
+
const recognition = new Ctor();
|
|
1624
|
+
recognition.lang = langRef.current ?? (typeof navigator === "undefined" ? "en-US" : navigator.language || "en-US");
|
|
1625
|
+
recognition.continuous = !isTouchDevice();
|
|
1626
|
+
recognition.interimResults = true;
|
|
1627
|
+
recognition.maxAlternatives = 1;
|
|
1628
|
+
recognition.onstart = () => {
|
|
1629
|
+
if (token !== startTokenRef.current) return;
|
|
1630
|
+
setError(null);
|
|
1631
|
+
setListening(true);
|
|
1632
|
+
};
|
|
1633
|
+
recognition.onresult = (event) => {
|
|
1634
|
+
if (token !== startTokenRef.current) return;
|
|
1635
|
+
let settled = "";
|
|
1636
|
+
let pending = "";
|
|
1637
|
+
for (let i = event.resultIndex; i < event.results.length; i += 1) {
|
|
1638
|
+
const result = event.results[i];
|
|
1639
|
+
if (!result) continue;
|
|
1640
|
+
const text = result[0]?.transcript ?? "";
|
|
1641
|
+
if (result.isFinal) settled += text;
|
|
1642
|
+
else pending += text;
|
|
1643
|
+
}
|
|
1644
|
+
setInterim(pending);
|
|
1645
|
+
if (settled.trim() !== "") finalRef.current(settled);
|
|
1646
|
+
};
|
|
1647
|
+
recognition.onerror = (event) => {
|
|
1648
|
+
if (token !== startTokenRef.current) return;
|
|
1649
|
+
if ((event.error === "not-allowed" || event.error === "service-not-allowed") && micConfirmedRef.current && !retriedRef.current) {
|
|
1650
|
+
retriedRef.current = true;
|
|
1651
|
+
void sleep(RETRY_DELAY_MS).then(() => {
|
|
1652
|
+
if (token !== startTokenRef.current || !wantsListeningRef.current)
|
|
1653
|
+
return;
|
|
1654
|
+
openSessionRef.current?.(token);
|
|
1655
|
+
});
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
const message = micConfirmedRef.current && (event.error === "not-allowed" || event.error === "service-not-allowed") ? MIC_UNAVAILABLE_MESSAGE : describeError(event.error);
|
|
1659
|
+
wantsListeningRef.current = false;
|
|
1660
|
+
setListening(false);
|
|
1661
|
+
setInterim("");
|
|
1662
|
+
if (message !== "") {
|
|
1663
|
+
setError(message);
|
|
1664
|
+
errorRef.current?.(message);
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
recognition.onend = () => {
|
|
1668
|
+
if (token !== startTokenRef.current) return;
|
|
1669
|
+
setInterim("");
|
|
1670
|
+
if (wantsListeningRef.current && isTouchDevice()) {
|
|
1671
|
+
void sleep(120).then(() => {
|
|
1672
|
+
if (token !== startTokenRef.current || !wantsListeningRef.current)
|
|
1673
|
+
return;
|
|
1674
|
+
openSessionRef.current?.(token);
|
|
1675
|
+
});
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
setListening(false);
|
|
1679
|
+
};
|
|
1680
|
+
recognitionRef.current = recognition;
|
|
1681
|
+
try {
|
|
1682
|
+
recognition.start();
|
|
1683
|
+
} catch {
|
|
1684
|
+
wantsListeningRef.current = false;
|
|
1685
|
+
setListening(false);
|
|
1686
|
+
}
|
|
1687
|
+
}, []);
|
|
1688
|
+
const openSessionRef = React.useRef(null);
|
|
1689
|
+
openSessionRef.current = openSession;
|
|
1690
|
+
const start = React.useCallback(() => {
|
|
1691
|
+
if (!getRecognitionCtor()) return;
|
|
1615
1692
|
startTokenRef.current += 1;
|
|
1616
1693
|
const token = startTokenRef.current;
|
|
1617
|
-
|
|
1694
|
+
wantsListeningRef.current = true;
|
|
1695
|
+
retriedRef.current = false;
|
|
1696
|
+
micConfirmedRef.current = false;
|
|
1697
|
+
setError(null);
|
|
1698
|
+
setListening(true);
|
|
1699
|
+
void ensureMicrophoneAccess().then(async (access) => {
|
|
1618
1700
|
if (token !== startTokenRef.current) return;
|
|
1619
1701
|
if (!access.ok) {
|
|
1702
|
+
wantsListeningRef.current = false;
|
|
1620
1703
|
setListening(false);
|
|
1621
1704
|
setError(access.message);
|
|
1622
1705
|
errorRef.current?.(access.message);
|
|
1623
1706
|
return;
|
|
1624
1707
|
}
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
const beginRecognitionImpl = React.useCallback(
|
|
1629
|
-
(Ctor, token) => {
|
|
1630
|
-
const recognition = new Ctor();
|
|
1631
|
-
recognition.lang = lang ?? (typeof navigator === "undefined" ? "en-US" : navigator.language || "en-US");
|
|
1632
|
-
recognition.continuous = true;
|
|
1633
|
-
recognition.interimResults = true;
|
|
1634
|
-
recognition.maxAlternatives = 1;
|
|
1635
|
-
recognition.onstart = () => {
|
|
1708
|
+
micConfirmedRef.current = access.confirmed;
|
|
1709
|
+
if (access.primed) {
|
|
1710
|
+
await sleep(RELEASE_SETTLE_MS);
|
|
1636
1711
|
if (token !== startTokenRef.current) return;
|
|
1637
|
-
setError(null);
|
|
1638
|
-
setListening(true);
|
|
1639
|
-
};
|
|
1640
|
-
recognition.onresult = (event) => {
|
|
1641
|
-
let settled = "";
|
|
1642
|
-
let pending = "";
|
|
1643
|
-
for (let i = event.resultIndex; i < event.results.length; i += 1) {
|
|
1644
|
-
const result = event.results[i];
|
|
1645
|
-
if (!result) continue;
|
|
1646
|
-
const text = result[0]?.transcript ?? "";
|
|
1647
|
-
if (result.isFinal) settled += text;
|
|
1648
|
-
else pending += text;
|
|
1649
|
-
}
|
|
1650
|
-
setInterim(pending);
|
|
1651
|
-
if (settled.trim() !== "") finalRef.current(settled);
|
|
1652
|
-
};
|
|
1653
|
-
recognition.onerror = (event) => {
|
|
1654
|
-
const message = describeError(event.error);
|
|
1655
|
-
setListening(false);
|
|
1656
|
-
setInterim("");
|
|
1657
|
-
if (message !== "") {
|
|
1658
|
-
setError(message);
|
|
1659
|
-
errorRef.current?.(message);
|
|
1660
|
-
}
|
|
1661
|
-
};
|
|
1662
|
-
recognition.onend = () => {
|
|
1663
|
-
setListening(false);
|
|
1664
|
-
setInterim("");
|
|
1665
|
-
};
|
|
1666
|
-
recognitionRef.current = recognition;
|
|
1667
|
-
try {
|
|
1668
|
-
recognition.start();
|
|
1669
|
-
} catch {
|
|
1670
|
-
setListening(false);
|
|
1671
1712
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
);
|
|
1675
|
-
beginRecognitionRef.current = beginRecognitionImpl;
|
|
1713
|
+
openSessionRef.current?.(token);
|
|
1714
|
+
});
|
|
1715
|
+
}, []);
|
|
1676
1716
|
const toggle = React.useCallback(() => {
|
|
1677
1717
|
if (listening) stop();
|
|
1678
1718
|
else start();
|
|
1679
1719
|
}, [listening, start, stop]);
|
|
1680
1720
|
React.useEffect(
|
|
1681
1721
|
() => () => {
|
|
1722
|
+
startTokenRef.current += 1;
|
|
1723
|
+
wantsListeningRef.current = false;
|
|
1682
1724
|
const recognition = recognitionRef.current;
|
|
1683
1725
|
if (!recognition) return;
|
|
1684
1726
|
recognition.onresult = null;
|
|
@@ -1862,6 +1904,50 @@ var EXPLORE_CSS = `
|
|
|
1862
1904
|
border-radius: 9999px;
|
|
1863
1905
|
background-clip: content-box;
|
|
1864
1906
|
}
|
|
1907
|
+
|
|
1908
|
+
/* The product strip scrolls inside itself; a visible scrollbar would read as a broken
|
|
1909
|
+
layout rather than an affordance, and reserving its gutter shifts the chips. */
|
|
1910
|
+
.boff-explore-strip {
|
|
1911
|
+
scrollbar-width: none;
|
|
1912
|
+
-ms-overflow-style: none;
|
|
1913
|
+
}
|
|
1914
|
+
.boff-explore-strip::-webkit-scrollbar { display: none; }
|
|
1915
|
+
|
|
1916
|
+
@keyframes boff-explore-fade-in {
|
|
1917
|
+
from { opacity: 0; transform: translateY(2px); }
|
|
1918
|
+
to { opacity: 1; transform: none; }
|
|
1919
|
+
}
|
|
1920
|
+
.boff-explore-fade { animation: boff-explore-fade-in 220ms ease-out; }
|
|
1921
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1922
|
+
.boff-explore-fade { animation: none; }
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
/* Nothing inside an answer may widen the page. Model output carries long URLs, code and
|
|
1926
|
+
tables \u2014 each of those overflows a phone by default, and one overflowing child makes the
|
|
1927
|
+
WHOLE document horizontally scrollable, not just the bubble. */
|
|
1928
|
+
.boff-explore-body,
|
|
1929
|
+
.boff-explore-body p,
|
|
1930
|
+
.boff-explore-body li,
|
|
1931
|
+
.boff-explore-body a,
|
|
1932
|
+
.boff-explore-body h1,
|
|
1933
|
+
.boff-explore-body h2,
|
|
1934
|
+
.boff-explore-body h3 {
|
|
1935
|
+
overflow-wrap: anywhere;
|
|
1936
|
+
word-break: break-word;
|
|
1937
|
+
}
|
|
1938
|
+
.boff-explore-body pre {
|
|
1939
|
+
overflow-x: auto;
|
|
1940
|
+
max-width: 100%;
|
|
1941
|
+
}
|
|
1942
|
+
.boff-explore-body table {
|
|
1943
|
+
display: block;
|
|
1944
|
+
overflow-x: auto;
|
|
1945
|
+
max-width: 100%;
|
|
1946
|
+
}
|
|
1947
|
+
.boff-explore-body img {
|
|
1948
|
+
max-width: 100%;
|
|
1949
|
+
height: auto;
|
|
1950
|
+
}
|
|
1865
1951
|
`;
|
|
1866
1952
|
function ExploreStyles() {
|
|
1867
1953
|
return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: EXPLORE_CSS } });
|
|
@@ -1883,7 +1969,6 @@ var CAPABILITIES = [
|
|
|
1883
1969
|
body: "Get the sources and next steps \u2014 pricing, docs, a demo \u2014 without hunting."
|
|
1884
1970
|
}
|
|
1885
1971
|
];
|
|
1886
|
-
var PRODUCT_CHIP_PREVIEW = 12;
|
|
1887
1972
|
var CTA_VARIANTS = {
|
|
1888
1973
|
CONTACT: "default",
|
|
1889
1974
|
WAITLIST: "default",
|
|
@@ -2084,7 +2169,7 @@ function AssistantBubble({
|
|
|
2084
2169
|
),
|
|
2085
2170
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-3", children: [
|
|
2086
2171
|
body ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl rounded-tl-md border border-border bg-card px-4 py-3 shadow-sm", children: [
|
|
2087
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "boff-prose boff-prose-sm text-card-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { children: body }) }),
|
|
2172
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "boff-prose boff-prose-sm boff-explore-body min-w-0 text-card-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { children: body }) }),
|
|
2088
2173
|
streaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "boff-explore-caret", "aria-hidden": "true" }) : null
|
|
2089
2174
|
] }) : null,
|
|
2090
2175
|
streaming ? /* @__PURE__ */ jsxRuntime.jsx(ThinkingIndicator, { activity }) : null,
|
|
@@ -2146,6 +2231,200 @@ function ErrorBanner({
|
|
|
2146
2231
|
}
|
|
2147
2232
|
);
|
|
2148
2233
|
}
|
|
2234
|
+
function PromptCarousel({
|
|
2235
|
+
prompts,
|
|
2236
|
+
onPrompt,
|
|
2237
|
+
disabled
|
|
2238
|
+
}) {
|
|
2239
|
+
const [index, setIndex] = React.useState(0);
|
|
2240
|
+
const [paused, setPaused] = React.useState(false);
|
|
2241
|
+
const count = prompts.length;
|
|
2242
|
+
const current = prompts[index % count] ?? prompts[0] ?? "";
|
|
2243
|
+
const go = React.useCallback(
|
|
2244
|
+
(delta) => {
|
|
2245
|
+
setIndex((i) => (i + delta + count) % count);
|
|
2246
|
+
},
|
|
2247
|
+
[count]
|
|
2248
|
+
);
|
|
2249
|
+
React.useEffect(() => {
|
|
2250
|
+
if (paused || disabled || count < 2) return;
|
|
2251
|
+
if (typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
|
|
2252
|
+
return;
|
|
2253
|
+
}
|
|
2254
|
+
const timer = setInterval(() => setIndex((i) => (i + 1) % count), 4500);
|
|
2255
|
+
return () => clearInterval(timer);
|
|
2256
|
+
}, [paused, disabled, count]);
|
|
2257
|
+
if (count === 0) return null;
|
|
2258
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2259
|
+
"div",
|
|
2260
|
+
{
|
|
2261
|
+
className: "flex min-w-0 items-center gap-1.5",
|
|
2262
|
+
onMouseEnter: () => setPaused(true),
|
|
2263
|
+
onMouseLeave: () => setPaused(false),
|
|
2264
|
+
onFocusCapture: () => setPaused(true),
|
|
2265
|
+
onBlurCapture: () => setPaused(false),
|
|
2266
|
+
children: [
|
|
2267
|
+
count > 1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2268
|
+
"button",
|
|
2269
|
+
{
|
|
2270
|
+
type: "button",
|
|
2271
|
+
"aria-label": "Previous suggestion",
|
|
2272
|
+
onClick: () => go(-1),
|
|
2273
|
+
className: "hidden h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring sm:inline-flex",
|
|
2274
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" })
|
|
2275
|
+
}
|
|
2276
|
+
) : null,
|
|
2277
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2278
|
+
"button",
|
|
2279
|
+
{
|
|
2280
|
+
"data-boff-explore": "chip",
|
|
2281
|
+
"data-chip-kind": "prompt",
|
|
2282
|
+
type: "button",
|
|
2283
|
+
disabled,
|
|
2284
|
+
onClick: () => onPrompt(current),
|
|
2285
|
+
className: "boff-explore-fade group flex min-w-0 flex-1 items-center gap-2 rounded-full border border-border bg-card px-4 py-2 text-left text-sm text-card-foreground shadow-sm transition-colors hover:border-primary/50 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2286
|
+
children: [
|
|
2287
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5 shrink-0 text-primary" }),
|
|
2288
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: current }),
|
|
2289
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "ml-auto h-3.5 w-3.5 shrink-0 rotate-45 text-muted-foreground transition-colors group-hover:text-primary" })
|
|
2290
|
+
]
|
|
2291
|
+
},
|
|
2292
|
+
current
|
|
2293
|
+
),
|
|
2294
|
+
count > 1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2295
|
+
"button",
|
|
2296
|
+
{
|
|
2297
|
+
type: "button",
|
|
2298
|
+
"aria-label": "Next suggestion",
|
|
2299
|
+
onClick: () => go(1),
|
|
2300
|
+
className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2301
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" })
|
|
2302
|
+
}
|
|
2303
|
+
) : null
|
|
2304
|
+
]
|
|
2305
|
+
}
|
|
2306
|
+
);
|
|
2307
|
+
}
|
|
2308
|
+
function ProductStrip({
|
|
2309
|
+
products,
|
|
2310
|
+
focusProduct,
|
|
2311
|
+
onFocus
|
|
2312
|
+
}) {
|
|
2313
|
+
const [expanded, setExpanded] = React.useState(false);
|
|
2314
|
+
const chipClass = (active) => cn(
|
|
2315
|
+
"shrink-0 rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2316
|
+
active ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
|
2317
|
+
);
|
|
2318
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2319
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2320
|
+
"div",
|
|
2321
|
+
{
|
|
2322
|
+
className: cn(
|
|
2323
|
+
"boff-explore-strip flex min-w-0 flex-1 gap-2",
|
|
2324
|
+
expanded ? "flex-wrap" : "flex-nowrap overflow-x-auto"
|
|
2325
|
+
),
|
|
2326
|
+
children: [
|
|
2327
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2328
|
+
"button",
|
|
2329
|
+
{
|
|
2330
|
+
"data-boff-explore": "chip",
|
|
2331
|
+
"data-chip-kind": "product",
|
|
2332
|
+
"data-product": "all",
|
|
2333
|
+
type: "button",
|
|
2334
|
+
"aria-pressed": focusProduct === null,
|
|
2335
|
+
onClick: () => onFocus(null),
|
|
2336
|
+
className: chipClass(focusProduct === null),
|
|
2337
|
+
children: "All products"
|
|
2338
|
+
}
|
|
2339
|
+
),
|
|
2340
|
+
products.map((product) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2341
|
+
"button",
|
|
2342
|
+
{
|
|
2343
|
+
"data-boff-explore": "chip",
|
|
2344
|
+
"data-chip-kind": "product",
|
|
2345
|
+
"data-product": product.slug,
|
|
2346
|
+
type: "button",
|
|
2347
|
+
"aria-pressed": focusProduct === product.slug,
|
|
2348
|
+
title: product.tagline ?? product.name,
|
|
2349
|
+
onClick: () => onFocus(focusProduct === product.slug ? null : product.slug),
|
|
2350
|
+
className: chipClass(focusProduct === product.slug),
|
|
2351
|
+
children: product.name
|
|
2352
|
+
},
|
|
2353
|
+
product.slug
|
|
2354
|
+
))
|
|
2355
|
+
]
|
|
2356
|
+
}
|
|
2357
|
+
),
|
|
2358
|
+
products.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2359
|
+
"button",
|
|
2360
|
+
{
|
|
2361
|
+
type: "button",
|
|
2362
|
+
"data-boff-explore": "products-toggle",
|
|
2363
|
+
onClick: () => setExpanded((v) => !v),
|
|
2364
|
+
className: "shrink-0 whitespace-nowrap rounded-full px-2 py-1 text-xs font-medium text-primary underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2365
|
+
children: expanded ? "Show less" : `All ${products.length}`
|
|
2366
|
+
}
|
|
2367
|
+
) : null
|
|
2368
|
+
] });
|
|
2369
|
+
}
|
|
2370
|
+
function DisclaimerDialog({
|
|
2371
|
+
open,
|
|
2372
|
+
onClose,
|
|
2373
|
+
captchaOn
|
|
2374
|
+
}) {
|
|
2375
|
+
const closeRef = React.useRef(null);
|
|
2376
|
+
React.useEffect(() => {
|
|
2377
|
+
if (!open) return;
|
|
2378
|
+
const onKey = (event) => {
|
|
2379
|
+
if (event.key === "Escape") onClose();
|
|
2380
|
+
};
|
|
2381
|
+
document.addEventListener("keydown", onKey);
|
|
2382
|
+
closeRef.current?.focus();
|
|
2383
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
2384
|
+
}, [open, onClose]);
|
|
2385
|
+
if (!open) return null;
|
|
2386
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2387
|
+
"div",
|
|
2388
|
+
{
|
|
2389
|
+
"data-boff-explore": "disclaimer-dialog",
|
|
2390
|
+
role: "dialog",
|
|
2391
|
+
"aria-modal": "true",
|
|
2392
|
+
"aria-label": "How this assistant works",
|
|
2393
|
+
className: "fixed inset-0 z-50 flex items-end justify-center bg-foreground/40 p-4 backdrop-blur-sm sm:items-center",
|
|
2394
|
+
onClick: onClose,
|
|
2395
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2396
|
+
"div",
|
|
2397
|
+
{
|
|
2398
|
+
className: "w-full max-w-md rounded-2xl border border-border bg-card p-5 shadow-xl",
|
|
2399
|
+
onClick: (event) => event.stopPropagation(),
|
|
2400
|
+
children: [
|
|
2401
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
2402
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TriangleAlert, { className: "h-4 w-4" }) }),
|
|
2403
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
2404
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-card-foreground", children: "How this assistant works" }),
|
|
2405
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-2 text-xs leading-relaxed text-muted-foreground", children: [
|
|
2406
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Answers are generated from our public documentation and can be imperfect \u2014 check anything important against the linked sources." }),
|
|
2407
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Conversations are saved in this browser so you can come back to them, and are also stored on our servers to help us improve these answers. Please don't share personal or confidential information." }),
|
|
2408
|
+
captchaOn ? /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Protected by reCAPTCHA \u2014 the Google Privacy Policy and Terms of Service apply." }) : null
|
|
2409
|
+
] })
|
|
2410
|
+
] })
|
|
2411
|
+
] }),
|
|
2412
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2413
|
+
Button,
|
|
2414
|
+
{
|
|
2415
|
+
ref: closeRef,
|
|
2416
|
+
size: "sm",
|
|
2417
|
+
variant: "secondary",
|
|
2418
|
+
onClick: onClose,
|
|
2419
|
+
children: "Got it"
|
|
2420
|
+
}
|
|
2421
|
+
) })
|
|
2422
|
+
]
|
|
2423
|
+
}
|
|
2424
|
+
)
|
|
2425
|
+
}
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2149
2428
|
function WelcomeState({
|
|
2150
2429
|
title,
|
|
2151
2430
|
body,
|
|
@@ -2156,21 +2435,19 @@ function WelcomeState({
|
|
|
2156
2435
|
onFocus,
|
|
2157
2436
|
disabled
|
|
2158
2437
|
}) {
|
|
2159
|
-
|
|
2160
|
-
const visibleProducts = showAllProducts ? products : products.slice(0, PRODUCT_CHIP_PREVIEW);
|
|
2161
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-3xl px-4 py-10 sm:py-14", children: [
|
|
2438
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-3xl px-4 py-8 sm:py-12", children: [
|
|
2162
2439
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
2163
2440
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-muted px-3 py-1 text-xs font-medium text-muted-foreground", children: [
|
|
2164
2441
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" }),
|
|
2165
2442
|
"AI answers, grounded in our documentation"
|
|
2166
2443
|
] }),
|
|
2167
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-
|
|
2168
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mx-auto mt-
|
|
2444
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-4 text-balance break-words text-2xl font-bold tracking-tight sm:text-4xl", children: title }),
|
|
2445
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mx-auto mt-2.5 max-w-2xl text-pretty text-sm leading-relaxed text-muted-foreground sm:text-lg", children: body })
|
|
2169
2446
|
] }),
|
|
2170
|
-
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-
|
|
2447
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-7 grid gap-2.5 sm:grid-cols-3", children: CAPABILITIES.map(({ icon: Icon, title: capTitle, body: capBody }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2171
2448
|
"li",
|
|
2172
2449
|
{
|
|
2173
|
-
className: "rounded-xl border border-border bg-card p-
|
|
2450
|
+
className: "rounded-xl border border-border/70 bg-card/60 p-3.5 text-left transition-colors hover:border-border",
|
|
2174
2451
|
children: [
|
|
2175
2452
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-2.5 flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }) }),
|
|
2176
2453
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-card-foreground", children: capTitle }),
|
|
@@ -2179,72 +2456,27 @@ function WelcomeState({
|
|
|
2179
2456
|
},
|
|
2180
2457
|
capTitle
|
|
2181
2458
|
)) }),
|
|
2182
|
-
prompts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-
|
|
2183
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2
|
|
2184
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2185
|
-
|
|
2459
|
+
prompts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8", children: [
|
|
2460
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Try asking" }),
|
|
2461
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2462
|
+
PromptCarousel,
|
|
2186
2463
|
{
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
className: "group inline-flex max-w-full items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-left text-sm text-card-foreground transition-colors hover:border-primary/40 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2193
|
-
children: [
|
|
2194
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: prompt }),
|
|
2195
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-3 w-3 shrink-0 rotate-45 text-muted-foreground transition-colors group-hover:text-primary" })
|
|
2196
|
-
]
|
|
2197
|
-
},
|
|
2198
|
-
prompt
|
|
2199
|
-
)) })
|
|
2464
|
+
prompts,
|
|
2465
|
+
onPrompt,
|
|
2466
|
+
disabled
|
|
2467
|
+
}
|
|
2468
|
+
)
|
|
2200
2469
|
] }) : null,
|
|
2201
|
-
products.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-
|
|
2202
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2
|
|
2203
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
"aria-pressed": focusProduct === null,
|
|
2212
|
-
onClick: () => onFocus(null),
|
|
2213
|
-
className: cn(
|
|
2214
|
-
"rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2215
|
-
focusProduct === null ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
|
2216
|
-
),
|
|
2217
|
-
children: "All products"
|
|
2218
|
-
}
|
|
2219
|
-
),
|
|
2220
|
-
visibleProducts.map((product) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2221
|
-
"button",
|
|
2222
|
-
{
|
|
2223
|
-
"data-boff-explore": "chip",
|
|
2224
|
-
"data-chip-kind": "product",
|
|
2225
|
-
"data-product": product.slug,
|
|
2226
|
-
type: "button",
|
|
2227
|
-
"aria-pressed": focusProduct === product.slug,
|
|
2228
|
-
title: product.tagline ?? product.name,
|
|
2229
|
-
onClick: () => onFocus(focusProduct === product.slug ? null : product.slug),
|
|
2230
|
-
className: cn(
|
|
2231
|
-
"rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2232
|
-
focusProduct === product.slug ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
|
2233
|
-
),
|
|
2234
|
-
children: product.name
|
|
2235
|
-
},
|
|
2236
|
-
product.slug
|
|
2237
|
-
)),
|
|
2238
|
-
products.length > PRODUCT_CHIP_PREVIEW ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2239
|
-
"button",
|
|
2240
|
-
{
|
|
2241
|
-
type: "button",
|
|
2242
|
-
onClick: () => setShowAllProducts((v) => !v),
|
|
2243
|
-
className: "rounded-full px-3 py-1 text-xs font-medium text-primary underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2244
|
-
children: showAllProducts ? "Show fewer" : `Show all ${products.length}`
|
|
2245
|
-
}
|
|
2246
|
-
) : null
|
|
2247
|
-
] })
|
|
2470
|
+
products.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6", children: [
|
|
2471
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Focus on a product" }),
|
|
2472
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2473
|
+
ProductStrip,
|
|
2474
|
+
{
|
|
2475
|
+
products,
|
|
2476
|
+
focusProduct,
|
|
2477
|
+
onFocus
|
|
2478
|
+
}
|
|
2479
|
+
)
|
|
2248
2480
|
] }) : null
|
|
2249
2481
|
] });
|
|
2250
2482
|
}
|
|
@@ -2300,6 +2532,7 @@ function ExplorePage({
|
|
|
2300
2532
|
}
|
|
2301
2533
|
});
|
|
2302
2534
|
speechStopRef.current = speech.stop;
|
|
2535
|
+
const [disclaimerOpen, setDisclaimerOpen] = React.useState(false);
|
|
2303
2536
|
const scrollRef = React.useRef(null);
|
|
2304
2537
|
const latestAssistantRef = React.useRef(null);
|
|
2305
2538
|
const alignedForRef = React.useRef(null);
|
|
@@ -2392,7 +2625,7 @@ function ExplorePage({
|
|
|
2392
2625
|
"data-boff-explore": "page",
|
|
2393
2626
|
"data-phase": phase,
|
|
2394
2627
|
className: cn(
|
|
2395
|
-
"flex w-full flex-col bg-background text-foreground",
|
|
2628
|
+
"flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
|
|
2396
2629
|
heightMode === "auto" && "min-h-[70vh]",
|
|
2397
2630
|
className
|
|
2398
2631
|
),
|
|
@@ -2534,7 +2767,7 @@ function ExplorePage({
|
|
|
2534
2767
|
role: "log",
|
|
2535
2768
|
"aria-live": "polite",
|
|
2536
2769
|
"aria-label": "Explore conversation",
|
|
2537
|
-
className: "boff-explore-scroll min-h-0 flex-1 overflow-y-auto",
|
|
2770
|
+
className: "boff-explore-scroll min-h-0 min-w-0 flex-1 overflow-y-auto overflow-x-hidden",
|
|
2538
2771
|
children: showWelcome ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2539
2772
|
WelcomeState,
|
|
2540
2773
|
{
|
|
@@ -2547,7 +2780,7 @@ function ExplorePage({
|
|
|
2547
2780
|
onFocus: setFocusProduct,
|
|
2548
2781
|
disabled: !canSend || busy
|
|
2549
2782
|
}
|
|
2550
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-3xl space-y-6 px-4 py-6", children: messages.map(
|
|
2783
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full min-w-0 max-w-3xl space-y-6 px-4 py-6", children: messages.map(
|
|
2551
2784
|
(message) => message.role === "USER" ? /* @__PURE__ */ jsxRuntime.jsx(UserBubble, { message }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2552
2785
|
AssistantBubble,
|
|
2553
2786
|
{
|
|
@@ -2561,7 +2794,15 @@ function ExplorePage({
|
|
|
2561
2794
|
) })
|
|
2562
2795
|
}
|
|
2563
2796
|
),
|
|
2564
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2797
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2798
|
+
DisclaimerDialog,
|
|
2799
|
+
{
|
|
2800
|
+
open: disclaimerOpen,
|
|
2801
|
+
onClose: () => setDisclaimerOpen(false),
|
|
2802
|
+
captchaOn
|
|
2803
|
+
}
|
|
2804
|
+
),
|
|
2805
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border bg-background/85 px-4 pb-[max(1rem,env(safe-area-inset-bottom))] pt-3 backdrop-blur-md", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2565
2806
|
"form",
|
|
2566
2807
|
{
|
|
2567
2808
|
"data-boff-explore": "composer",
|
|
@@ -2576,7 +2817,7 @@ function ExplorePage({
|
|
|
2576
2817
|
"div",
|
|
2577
2818
|
{
|
|
2578
2819
|
className: cn(
|
|
2579
|
-
"flex items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-
|
|
2820
|
+
"flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
|
|
2580
2821
|
overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
|
|
2581
2822
|
),
|
|
2582
2823
|
children: [
|
|
@@ -2597,7 +2838,7 @@ function ExplorePage({
|
|
|
2597
2838
|
},
|
|
2598
2839
|
"aria-label": "Ask a question",
|
|
2599
2840
|
placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? `Ask about ${focusedProductName}\u2026` : "Ask anything about our products\u2026",
|
|
2600
|
-
className: "max-h-[200px] min-h-[44px] flex-1 resize-none border-0 bg-transparent px-2 py-2.5 text-sm shadow-none focus-visible:ring-0 md:text-sm"
|
|
2841
|
+
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-sm shadow-none focus-visible:ring-0 md:text-sm"
|
|
2601
2842
|
}
|
|
2602
2843
|
),
|
|
2603
2844
|
speech.supported ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2688,48 +2929,19 @@ function ExplorePage({
|
|
|
2688
2929
|
}
|
|
2689
2930
|
)
|
|
2690
2931
|
] }),
|
|
2691
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2692
|
-
"
|
|
2693
|
-
|
|
2694
|
-
"
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
"
|
|
2698
|
-
|
|
2699
|
-
"
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2705
|
-
"a",
|
|
2706
|
-
{
|
|
2707
|
-
href: "https://policies.google.com/privacy",
|
|
2708
|
-
target: "_blank",
|
|
2709
|
-
rel: "noopener noreferrer",
|
|
2710
|
-
className: "underline underline-offset-2 hover:text-foreground",
|
|
2711
|
-
children: "Privacy Policy"
|
|
2712
|
-
}
|
|
2713
|
-
),
|
|
2714
|
-
" ",
|
|
2715
|
-
"and",
|
|
2716
|
-
" ",
|
|
2717
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2718
|
-
"a",
|
|
2719
|
-
{
|
|
2720
|
-
href: "https://policies.google.com/terms",
|
|
2721
|
-
target: "_blank",
|
|
2722
|
-
rel: "noopener noreferrer",
|
|
2723
|
-
className: "underline underline-offset-2 hover:text-foreground",
|
|
2724
|
-
children: "Terms of Service"
|
|
2725
|
-
}
|
|
2726
|
-
),
|
|
2727
|
-
" ",
|
|
2728
|
-
"apply."
|
|
2729
|
-
] }) : null
|
|
2730
|
-
]
|
|
2731
|
-
}
|
|
2732
|
-
)
|
|
2932
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
2933
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: "Grounded in our docs \u2014 check anything important." }),
|
|
2934
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2935
|
+
"button",
|
|
2936
|
+
{
|
|
2937
|
+
type: "button",
|
|
2938
|
+
"data-boff-explore": "disclaimer",
|
|
2939
|
+
onClick: () => setDisclaimerOpen(true),
|
|
2940
|
+
className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2941
|
+
children: "Disclaimer"
|
|
2942
|
+
}
|
|
2943
|
+
)
|
|
2944
|
+
] })
|
|
2733
2945
|
]
|
|
2734
2946
|
}
|
|
2735
2947
|
) })
|