@xenide-io/the-old-ui-theme 0.6.3 → 0.6.6
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/suite.d.mts +7 -4
- package/dist/suite.d.ts +7 -4
- package/dist/suite.js +378 -181
- package/dist/suite.mjs +390 -182
- package/package.json +1 -1
- package/src/styles/suite-skin.css +136 -45
- package/src/suite/components/ai-panel.tsx +306 -137
- package/src/suite/components/suite-layout.test.tsx +5 -0
- package/src/suite/components/suite-layout.tsx +22 -12
- package/src/suite/components/suite-sidebar.tsx +3 -1
- package/src/suite/components/suite-user-menu.tsx +43 -7
- package/src/suite/components/today-page-frame.tsx +4 -5
- package/src/suite/lib/apps.ts +1 -1
package/dist/suite.mjs
CHANGED
|
@@ -19,12 +19,12 @@ function TodayPageFrame({ children }) {
|
|
|
19
19
|
"div",
|
|
20
20
|
{
|
|
21
21
|
"data-test": "today-page",
|
|
22
|
-
className: "today-page-frame relative flex min-h-0 w-full flex-1 flex-col overflow-x-
|
|
22
|
+
className: "today-page-frame relative flex min-h-0 w-full flex-1 flex-col overflow-x-clip",
|
|
23
23
|
children: [
|
|
24
24
|
/* @__PURE__ */ jsxs(
|
|
25
25
|
"div",
|
|
26
26
|
{
|
|
27
|
-
className: "pointer-events-none
|
|
27
|
+
className: "today-page-frame__backdrop pointer-events-none overflow-hidden",
|
|
28
28
|
"aria-hidden": true,
|
|
29
29
|
children: [
|
|
30
30
|
/* @__PURE__ */ jsx("div", { className: "today-page-frame__glow absolute inset-0" }),
|
|
@@ -1094,7 +1094,7 @@ var SUITE_APPS2 = [
|
|
|
1094
1094
|
name: "Kraken",
|
|
1095
1095
|
description: "Documents and knowledge",
|
|
1096
1096
|
icon: "/kraken-icon.svg",
|
|
1097
|
-
landing: "/
|
|
1097
|
+
landing: "/ask",
|
|
1098
1098
|
baseUrlEnv: "NEXT_PUBLIC_KRAKEN_URL",
|
|
1099
1099
|
baseUrlFallback: "http://localhost:3003"
|
|
1100
1100
|
},
|
|
@@ -1625,7 +1625,7 @@ function SuitePage({
|
|
|
1625
1625
|
role,
|
|
1626
1626
|
"aria-live": ariaLive,
|
|
1627
1627
|
className: cn(
|
|
1628
|
-
"suite-page-stage flex w-full min-w-0 flex-col",
|
|
1628
|
+
"suite-page-stage relative flex w-full min-w-0 flex-col",
|
|
1629
1629
|
inset && "suite-page-inset",
|
|
1630
1630
|
className
|
|
1631
1631
|
),
|
|
@@ -1650,20 +1650,28 @@ function SuitePageHeader({
|
|
|
1650
1650
|
badge,
|
|
1651
1651
|
/** Breadcrumb line rendered above the title. */
|
|
1652
1652
|
breadcrumb,
|
|
1653
|
-
/**
|
|
1654
|
-
|
|
1653
|
+
/**
|
|
1654
|
+
* Keep the title parked at the top of the scrollport while the page scrolls.
|
|
1655
|
+
* On by default — opt out only for pages that are not the page's own title.
|
|
1656
|
+
*/
|
|
1657
|
+
sticky = true
|
|
1655
1658
|
}) {
|
|
1656
1659
|
const headerRef = useRef2(null);
|
|
1657
1660
|
const [stuck, setStuck] = useState6(false);
|
|
1658
1661
|
useEffect5(() => {
|
|
1659
|
-
var _a;
|
|
1660
1662
|
if (!sticky) return;
|
|
1663
|
+
if (typeof IntersectionObserver === "undefined") return;
|
|
1661
1664
|
const el = headerRef.current;
|
|
1662
1665
|
if (!el) return;
|
|
1666
|
+
const parent = el.parentElement;
|
|
1667
|
+
if (!parent) return;
|
|
1663
1668
|
const sentinel = document.createElement("div");
|
|
1664
1669
|
sentinel.setAttribute("aria-hidden", "true");
|
|
1665
|
-
sentinel.style.cssText = "position:
|
|
1666
|
-
(
|
|
1670
|
+
sentinel.style.cssText = "position:absolute;top:0;left:0;height:1px;width:1px;margin:0;padding:0;pointer-events:none";
|
|
1671
|
+
if (getComputedStyle(parent).position === "static") {
|
|
1672
|
+
parent.style.position = "relative";
|
|
1673
|
+
}
|
|
1674
|
+
parent.insertBefore(sentinel, el);
|
|
1667
1675
|
const observer = new IntersectionObserver(
|
|
1668
1676
|
([entry]) => {
|
|
1669
1677
|
setStuck(!entry.isIntersecting);
|
|
@@ -1680,7 +1688,7 @@ function SuitePageHeader({
|
|
|
1680
1688
|
TodayTimeIcon,
|
|
1681
1689
|
{
|
|
1682
1690
|
className: cn(
|
|
1683
|
-
"h-
|
|
1691
|
+
"h-6 w-6 text-amber-500",
|
|
1684
1692
|
todayIconClassName
|
|
1685
1693
|
)
|
|
1686
1694
|
}
|
|
@@ -1692,9 +1700,8 @@ function SuitePageHeader({
|
|
|
1692
1700
|
"data-test": dataTest,
|
|
1693
1701
|
"data-stuck": sticky ? stuck ? "true" : "false" : void 0,
|
|
1694
1702
|
className: cn(
|
|
1695
|
-
"flex min-w-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3",
|
|
1703
|
+
"flex min-w-0 shrink-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3",
|
|
1696
1704
|
// No extra pt here — page inset sets the shared title baseline.
|
|
1697
|
-
// Stuck state adds pad via .suite-page-header-sticky[data-stuck].
|
|
1698
1705
|
sticky && "suite-page-header-sticky",
|
|
1699
1706
|
className
|
|
1700
1707
|
),
|
|
@@ -1706,7 +1713,7 @@ function SuitePageHeader({
|
|
|
1706
1713
|
resolvedIcon ? /* @__PURE__ */ jsx12(
|
|
1707
1714
|
"div",
|
|
1708
1715
|
{
|
|
1709
|
-
className: "hidden shrink-0 sm:flex sm:items-center [&_svg]:h-
|
|
1716
|
+
className: "hidden shrink-0 sm:flex sm:items-center [&_svg]:h-6 [&_svg]:w-6",
|
|
1710
1717
|
"aria-hidden": "true",
|
|
1711
1718
|
children: resolvedIcon
|
|
1712
1719
|
}
|
|
@@ -1716,7 +1723,7 @@ function SuitePageHeader({
|
|
|
1716
1723
|
"h1",
|
|
1717
1724
|
{
|
|
1718
1725
|
className: cn(
|
|
1719
|
-
"min-w-0 break-words font-display text-[1.
|
|
1726
|
+
"min-w-0 break-words font-display text-[1.375rem] font-semibold leading-tight tracking-tight text-ph-ink text-balance sm:text-2xl",
|
|
1720
1727
|
titleClassName
|
|
1721
1728
|
),
|
|
1722
1729
|
children: title
|
|
@@ -1730,7 +1737,7 @@ function SuitePageHeader({
|
|
|
1730
1737
|
{
|
|
1731
1738
|
className: cn(
|
|
1732
1739
|
"mt-1.5 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle",
|
|
1733
|
-
resolvedIcon && "sm:pl-
|
|
1740
|
+
resolvedIcon && "sm:pl-9"
|
|
1734
1741
|
),
|
|
1735
1742
|
children: description
|
|
1736
1743
|
}
|
|
@@ -1868,6 +1875,20 @@ function computeInitials(name, email) {
|
|
|
1868
1875
|
const source = (name || email || "?").trim();
|
|
1869
1876
|
return source.split(/[\s@]+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
1870
1877
|
}
|
|
1878
|
+
var AVATAR_TOKENS = [
|
|
1879
|
+
"bg-ph-brand",
|
|
1880
|
+
"bg-ph-violet",
|
|
1881
|
+
"bg-ph-info",
|
|
1882
|
+
"bg-ph-success",
|
|
1883
|
+
"bg-ph-danger"
|
|
1884
|
+
];
|
|
1885
|
+
function avatarColorClass(seed) {
|
|
1886
|
+
let hash = 0;
|
|
1887
|
+
for (let i = 0; i < seed.length; i += 1) {
|
|
1888
|
+
hash = seed.charCodeAt(i) + ((hash << 5) - hash);
|
|
1889
|
+
}
|
|
1890
|
+
return AVATAR_TOKENS[Math.abs(hash) % AVATAR_TOKENS.length];
|
|
1891
|
+
}
|
|
1871
1892
|
function SuiteUserMenu({
|
|
1872
1893
|
name,
|
|
1873
1894
|
email,
|
|
@@ -1883,17 +1904,27 @@ function SuiteUserMenu({
|
|
|
1883
1904
|
}) {
|
|
1884
1905
|
const router = useRouter2();
|
|
1885
1906
|
const initials = fallbackInitials != null ? fallbackInitials : computeInitials(name, email);
|
|
1886
|
-
const
|
|
1907
|
+
const fallbackColor = avatarColorClass(email || name || "?");
|
|
1908
|
+
const avatar = /* @__PURE__ */ jsx14("span", { className: "inline-flex h-10 w-10 items-center justify-center overflow-hidden rounded-full border border-ph-border", children: image ? /* @__PURE__ */ jsx14(
|
|
1887
1909
|
Image2,
|
|
1888
1910
|
{
|
|
1889
1911
|
src: image,
|
|
1890
1912
|
alt: "",
|
|
1891
1913
|
width: 40,
|
|
1892
1914
|
height: 40,
|
|
1893
|
-
className: "h-
|
|
1915
|
+
className: "h-full w-full object-cover",
|
|
1894
1916
|
unoptimized: true
|
|
1895
1917
|
}
|
|
1896
|
-
) : /* @__PURE__ */ jsx14(
|
|
1918
|
+
) : /* @__PURE__ */ jsx14(
|
|
1919
|
+
"span",
|
|
1920
|
+
{
|
|
1921
|
+
className: cn(
|
|
1922
|
+
"flex h-full w-full items-center justify-center text-sm font-semibold text-white",
|
|
1923
|
+
fallbackColor
|
|
1924
|
+
),
|
|
1925
|
+
children: initials
|
|
1926
|
+
}
|
|
1927
|
+
) });
|
|
1897
1928
|
const accountMenu = /* @__PURE__ */ jsxs12(
|
|
1898
1929
|
DropdownMenu,
|
|
1899
1930
|
{
|
|
@@ -1906,7 +1937,10 @@ function SuiteUserMenu({
|
|
|
1906
1937
|
sideOffset: 6,
|
|
1907
1938
|
collisionPadding: 16,
|
|
1908
1939
|
modal: false,
|
|
1909
|
-
className:
|
|
1940
|
+
className: cn(
|
|
1941
|
+
"[&_.ph-dropdown-trigger]:rounded-full",
|
|
1942
|
+
showSignOutAction ? void 0 : className
|
|
1943
|
+
),
|
|
1910
1944
|
"data-test": dataTest,
|
|
1911
1945
|
children: [
|
|
1912
1946
|
/* @__PURE__ */ jsxs12("div", { className: "px-2 py-1.5", children: [
|
|
@@ -1935,21 +1969,30 @@ function SuiteUserMenu({
|
|
|
1935
1969
|
if (!showSignOutAction) {
|
|
1936
1970
|
return accountMenu;
|
|
1937
1971
|
}
|
|
1938
|
-
return /* @__PURE__ */ jsxs12(
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
"
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1972
|
+
return /* @__PURE__ */ jsxs12(
|
|
1973
|
+
"div",
|
|
1974
|
+
{
|
|
1975
|
+
className: cn(
|
|
1976
|
+
"flex w-full min-w-0 flex-1 items-center justify-between gap-2",
|
|
1977
|
+
className
|
|
1978
|
+
),
|
|
1979
|
+
children: [
|
|
1980
|
+
/* @__PURE__ */ jsx14("div", { className: "shrink-0", children: accountMenu }),
|
|
1981
|
+
/* @__PURE__ */ jsx14(
|
|
1982
|
+
"button",
|
|
1983
|
+
{
|
|
1984
|
+
type: "button",
|
|
1985
|
+
"data-test": `${dataTest}-visible-sign-out`,
|
|
1986
|
+
title: "Sign out",
|
|
1987
|
+
"aria-label": "Sign out",
|
|
1988
|
+
className: "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ph-focus-ring",
|
|
1989
|
+
onClick: onSignOut,
|
|
1990
|
+
children: /* @__PURE__ */ jsx14(LogOut, { className: "h-4 w-4", "aria-hidden": true })
|
|
1991
|
+
}
|
|
1992
|
+
)
|
|
1993
|
+
]
|
|
1994
|
+
}
|
|
1995
|
+
);
|
|
1953
1996
|
}
|
|
1954
1997
|
|
|
1955
1998
|
// src/suite/components/suite-bottom-nav.tsx
|
|
@@ -2093,10 +2136,21 @@ import {
|
|
|
2093
2136
|
Suspense,
|
|
2094
2137
|
useCallback as useCallback2,
|
|
2095
2138
|
useEffect as useEffect6,
|
|
2139
|
+
useLayoutEffect,
|
|
2096
2140
|
useRef as useRef3,
|
|
2097
2141
|
useState as useState7
|
|
2098
2142
|
} from "react";
|
|
2099
|
-
import {
|
|
2143
|
+
import {
|
|
2144
|
+
ArrowDown,
|
|
2145
|
+
ArrowUp,
|
|
2146
|
+
Check as Check2,
|
|
2147
|
+
Copy,
|
|
2148
|
+
Erase,
|
|
2149
|
+
Sparks,
|
|
2150
|
+
Square,
|
|
2151
|
+
WarningTriangle,
|
|
2152
|
+
Xmark as X2
|
|
2153
|
+
} from "iconoir-react";
|
|
2100
2154
|
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2101
2155
|
var SuiteAiBlockNoteMessage = lazy(() => import("./ai-message-blocknote-4Q4U2T2W.mjs"));
|
|
2102
2156
|
var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
|
|
@@ -2168,11 +2222,14 @@ function SuiteAiPanel({
|
|
|
2168
2222
|
const [hydrating, setHydrating] = useState7(false);
|
|
2169
2223
|
const [error, setError] = useState7("");
|
|
2170
2224
|
const [copiedId, setCopiedId] = useState7(null);
|
|
2225
|
+
const [atBottom, setAtBottom] = useState7(true);
|
|
2171
2226
|
const [launcherSide, setLauncherSide] = useState7("right");
|
|
2172
2227
|
const [panelSide, setPanelSide] = useState7("right");
|
|
2173
2228
|
const [launcherPosition, setLauncherPosition] = useState7(null);
|
|
2174
2229
|
const [draggingLauncher, setDraggingLauncher] = useState7(false);
|
|
2175
2230
|
const scrollerRef = useRef3(null);
|
|
2231
|
+
const textareaRef = useRef3(null);
|
|
2232
|
+
const abortRef = useRef3(null);
|
|
2176
2233
|
const launcherRef = useRef3(null);
|
|
2177
2234
|
const launcherSideRef = useRef3("right");
|
|
2178
2235
|
const launcherPositionRef = useRef3(null);
|
|
@@ -2224,10 +2281,17 @@ function SuiteAiPanel({
|
|
|
2224
2281
|
window.addEventListener("resize", placeLauncher);
|
|
2225
2282
|
return () => window.removeEventListener("resize", placeLauncher);
|
|
2226
2283
|
}, []);
|
|
2227
|
-
const scrollToBottom = useCallback2(() => {
|
|
2284
|
+
const scrollToBottom = useCallback2((behavior = "auto") => {
|
|
2228
2285
|
const el = scrollerRef.current;
|
|
2229
2286
|
if (!el) return;
|
|
2230
|
-
el.
|
|
2287
|
+
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
2288
|
+
setAtBottom(true);
|
|
2289
|
+
}, []);
|
|
2290
|
+
const handleScroll = useCallback2(() => {
|
|
2291
|
+
const el = scrollerRef.current;
|
|
2292
|
+
if (!el) return;
|
|
2293
|
+
const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
2294
|
+
setAtBottom(distance < 64);
|
|
2231
2295
|
}, []);
|
|
2232
2296
|
const hydrate = useCallback2(async () => {
|
|
2233
2297
|
var _a;
|
|
@@ -2271,20 +2335,46 @@ function SuiteAiPanel({
|
|
|
2271
2335
|
});
|
|
2272
2336
|
}, [open, hydrate]);
|
|
2273
2337
|
useEffect6(() => {
|
|
2274
|
-
if (open) scrollToBottom();
|
|
2275
|
-
}, [messages, loading, open, scrollToBottom]);
|
|
2338
|
+
if (open && atBottom) scrollToBottom();
|
|
2339
|
+
}, [messages, loading, open, atBottom, scrollToBottom]);
|
|
2340
|
+
useEffect6(() => {
|
|
2341
|
+
var _a;
|
|
2342
|
+
if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
|
|
2343
|
+
}, [open, hydrating]);
|
|
2344
|
+
useEffect6(() => {
|
|
2345
|
+
if (!open) return;
|
|
2346
|
+
function onKey(event) {
|
|
2347
|
+
if (event.key === "Escape") setOpen(false);
|
|
2348
|
+
}
|
|
2349
|
+
window.addEventListener("keydown", onKey);
|
|
2350
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
2351
|
+
}, [open]);
|
|
2352
|
+
useLayoutEffect(() => {
|
|
2353
|
+
const el = textareaRef.current;
|
|
2354
|
+
if (!el) return;
|
|
2355
|
+
el.style.height = "auto";
|
|
2356
|
+
el.style.height = `${Math.min(el.scrollHeight, 176)}px`;
|
|
2357
|
+
}, [prompt, open]);
|
|
2276
2358
|
async function ask(text) {
|
|
2277
2359
|
var _a;
|
|
2278
2360
|
const trimmed = text.trim();
|
|
2279
2361
|
if (!trimmed || loading) return;
|
|
2362
|
+
const controller = new AbortController();
|
|
2363
|
+
abortRef.current = controller;
|
|
2280
2364
|
setLoading(true);
|
|
2281
2365
|
setError("");
|
|
2282
2366
|
setPrompt("");
|
|
2367
|
+
setAtBottom(true);
|
|
2283
2368
|
setMessages((prev) => [...prev, { role: "user", content: trimmed }]);
|
|
2284
2369
|
try {
|
|
2285
|
-
const result = await sendMessage({
|
|
2370
|
+
const result = await sendMessage({
|
|
2371
|
+
prompt: trimmed,
|
|
2372
|
+
signal: controller.signal
|
|
2373
|
+
});
|
|
2374
|
+
if (controller.signal.aborted) return;
|
|
2286
2375
|
setMessages((_a = result.messages) != null ? _a : []);
|
|
2287
2376
|
} catch (err) {
|
|
2377
|
+
if (controller.signal.aborted) return;
|
|
2288
2378
|
setMessages(
|
|
2289
2379
|
(prev) => {
|
|
2290
2380
|
var _a2, _b;
|
|
@@ -2296,9 +2386,23 @@ function SuiteAiPanel({
|
|
|
2296
2386
|
err instanceof Error ? err.message : "The AI request failed. Try again."
|
|
2297
2387
|
);
|
|
2298
2388
|
} finally {
|
|
2389
|
+
if (abortRef.current === controller) abortRef.current = null;
|
|
2299
2390
|
setLoading(false);
|
|
2300
2391
|
}
|
|
2301
2392
|
}
|
|
2393
|
+
function stop() {
|
|
2394
|
+
var _a;
|
|
2395
|
+
(_a = abortRef.current) == null ? void 0 : _a.abort();
|
|
2396
|
+
abortRef.current = null;
|
|
2397
|
+
setLoading(false);
|
|
2398
|
+
}
|
|
2399
|
+
function retry() {
|
|
2400
|
+
var _a;
|
|
2401
|
+
const lastUser = (_a = [...messages].reverse().find((m2) => m2.role === "user")) == null ? void 0 : _a.content;
|
|
2402
|
+
setError("");
|
|
2403
|
+
if (lastUser) void ask(lastUser);
|
|
2404
|
+
else void hydrate();
|
|
2405
|
+
}
|
|
2302
2406
|
async function handleClear() {
|
|
2303
2407
|
if (loading) return;
|
|
2304
2408
|
try {
|
|
@@ -2460,154 +2564,258 @@ function SuiteAiPanel({
|
|
|
2460
2564
|
),
|
|
2461
2565
|
/* @__PURE__ */ jsx17("span", { id: "suite-ask-ai-launcher-help", className: "sr-only", children: "Drag to reposition, or use arrow keys. The launcher docks to the nearest screen edge." })
|
|
2462
2566
|
] }) : null,
|
|
2463
|
-
open ? /* @__PURE__ */ jsxs15(
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2567
|
+
open ? /* @__PURE__ */ jsxs15(
|
|
2568
|
+
"div",
|
|
2569
|
+
{
|
|
2570
|
+
className: "fixed inset-0 z-40",
|
|
2571
|
+
role: "dialog",
|
|
2572
|
+
"aria-modal": "true",
|
|
2573
|
+
"aria-label": title,
|
|
2574
|
+
children: [
|
|
2575
|
+
/* @__PURE__ */ jsx17(
|
|
2576
|
+
"button",
|
|
2577
|
+
{
|
|
2578
|
+
type: "button",
|
|
2579
|
+
className: "absolute inset-0 bg-ph-ink/25",
|
|
2580
|
+
onClick: () => setOpen(false),
|
|
2581
|
+
"aria-label": "Close Ask AI",
|
|
2582
|
+
tabIndex: -1
|
|
2583
|
+
}
|
|
2584
|
+
),
|
|
2585
|
+
/* @__PURE__ */ jsxs15(
|
|
2586
|
+
"aside",
|
|
2587
|
+
{
|
|
2588
|
+
className: `absolute inset-y-0 flex w-full flex-col bg-ph-canvas shadow-2xl sm:max-w-xl ${panelSide === "left" ? "left-0 border-r border-ph-border" : "right-0 border-l border-ph-border"}`,
|
|
2589
|
+
"data-test": "suite-ask-ai-panel",
|
|
2590
|
+
children: [
|
|
2591
|
+
/* @__PURE__ */ jsxs15("header", { className: "flex items-center gap-2 px-4 py-3", children: [
|
|
2592
|
+
/* @__PURE__ */ jsx17("h2", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-ph-ink", children: title }),
|
|
2593
|
+
messages.length > 0 ? /* @__PURE__ */ jsxs15(
|
|
2594
|
+
"button",
|
|
2595
|
+
{
|
|
2596
|
+
type: "button",
|
|
2597
|
+
onClick: () => void handleClear(),
|
|
2598
|
+
disabled: loading,
|
|
2599
|
+
className: "inline-flex h-10 items-center gap-1.5 rounded-lg px-2.5 text-xs font-medium text-ph-subtle transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2600
|
+
"data-test": "ask-ai-clear",
|
|
2601
|
+
children: [
|
|
2602
|
+
/* @__PURE__ */ jsx17(Erase, { className: "h-3.5 w-3.5" }),
|
|
2603
|
+
"Clear"
|
|
2604
|
+
]
|
|
2605
|
+
}
|
|
2606
|
+
) : null,
|
|
2607
|
+
/* @__PURE__ */ jsx17(
|
|
2608
|
+
"button",
|
|
2609
|
+
{
|
|
2610
|
+
type: "button",
|
|
2611
|
+
onClick: () => setOpen(false),
|
|
2612
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-ph-subtle transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus",
|
|
2613
|
+
"aria-label": "Close Ask AI",
|
|
2614
|
+
children: /* @__PURE__ */ jsx17(X2, { className: "h-4 w-4" })
|
|
2615
|
+
}
|
|
2616
|
+
)
|
|
2484
2617
|
] }),
|
|
2485
|
-
/* @__PURE__ */
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
"aria-label": "Close",
|
|
2506
|
-
children: /* @__PURE__ */ jsx17(X2, { className: "h-4 w-4" })
|
|
2507
|
-
}
|
|
2508
|
-
)
|
|
2509
|
-
] })
|
|
2510
|
-
] }),
|
|
2511
|
-
presets.length > 0 && messages.length === 0 ? /* @__PURE__ */ jsx17("div", { className: "flex flex-wrap gap-1.5 border-b border-ph-border px-4 py-2", children: presets.map((preset) => /* @__PURE__ */ jsx17(
|
|
2512
|
-
"button",
|
|
2513
|
-
{
|
|
2514
|
-
type: "button",
|
|
2515
|
-
onClick: () => void ask(preset.prompt),
|
|
2516
|
-
disabled: loading || hydrating,
|
|
2517
|
-
className: "rounded-full border border-ph-border px-2.5 py-1 text-xs text-ph-ink hover:bg-ph-muted disabled:opacity-50",
|
|
2518
|
-
children: preset.label
|
|
2519
|
-
},
|
|
2520
|
-
preset.label
|
|
2521
|
-
)) }) : null,
|
|
2522
|
-
/* @__PURE__ */ jsxs15(
|
|
2523
|
-
"div",
|
|
2524
|
-
{
|
|
2525
|
-
ref: scrollerRef,
|
|
2526
|
-
className: "flex-1 space-y-3 overflow-y-auto p-4",
|
|
2527
|
-
children: [
|
|
2528
|
-
error ? /* @__PURE__ */ jsx17("p", { className: "bg-ph-danger/10 rounded-lg px-3 py-2 text-sm text-ph-danger", children: error }) : null,
|
|
2529
|
-
hydrating && messages.length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2530
|
-
/* @__PURE__ */ jsx17(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2531
|
-
"Loading chat\u2026"
|
|
2532
|
-
] }) : null,
|
|
2533
|
-
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ jsxs15("div", { className: "mt-10 px-2 text-center", children: [
|
|
2534
|
-
/* @__PURE__ */ jsx17("p", { className: "font-display text-base font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2535
|
-
/* @__PURE__ */ jsx17("p", { className: "mt-2 text-sm leading-relaxed text-ph-subtle", children: emptyState })
|
|
2536
|
-
] }) : null,
|
|
2537
|
-
messages.map((message, index) => {
|
|
2538
|
-
const isUser = message.role === "user";
|
|
2539
|
-
return /* @__PURE__ */ jsxs15(
|
|
2540
|
-
"div",
|
|
2541
|
-
{
|
|
2542
|
-
className: isUser ? "ml-8 rounded-2xl bg-ph-brand/10 px-3.5 py-2.5 text-sm text-ph-ink" : "mr-4 rounded-2xl bg-ph-muted px-3.5 py-2.5 text-sm text-ph-ink",
|
|
2543
|
-
"data-test": isUser ? "ask-ai-user" : "ask-ai-assistant",
|
|
2544
|
-
children: [
|
|
2545
|
-
isUser ? /* @__PURE__ */ jsx17("p", { className: "whitespace-pre-wrap", children: message.content }) : /* @__PURE__ */ jsx17(
|
|
2546
|
-
Suspense,
|
|
2547
|
-
{
|
|
2548
|
-
fallback: /* @__PURE__ */ jsx17("p", { className: "whitespace-pre-wrap", children: message.content }),
|
|
2549
|
-
children: /* @__PURE__ */ jsx17(SuiteAiBlockNoteMessage, { markdown: message.content })
|
|
2550
|
-
}
|
|
2551
|
-
),
|
|
2552
|
-
!isUser ? /* @__PURE__ */ jsxs15(
|
|
2618
|
+
/* @__PURE__ */ jsxs15("div", { className: "relative min-h-0 flex-1", children: [
|
|
2619
|
+
/* @__PURE__ */ jsxs15(
|
|
2620
|
+
"div",
|
|
2621
|
+
{
|
|
2622
|
+
ref: scrollerRef,
|
|
2623
|
+
onScroll: handleScroll,
|
|
2624
|
+
role: "log",
|
|
2625
|
+
"aria-live": "polite",
|
|
2626
|
+
"aria-label": "Conversation",
|
|
2627
|
+
className: "suite-scroll-lock h-full space-y-5 overflow-y-auto px-4 py-5",
|
|
2628
|
+
children: [
|
|
2629
|
+
hydrating && messages.length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 text-sm text-ph-subtle", children: [
|
|
2630
|
+
/* @__PURE__ */ jsx17(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2631
|
+
"Loading your chat\u2026"
|
|
2632
|
+
] }) : null,
|
|
2633
|
+
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ jsxs15("div", { className: "mx-auto mt-6 flex max-w-sm flex-col items-center px-2 text-center", children: [
|
|
2634
|
+
/* @__PURE__ */ jsx17("span", { className: "flex h-12 w-12 items-center justify-center rounded-2xl bg-ph-brand/10 text-ph-brand", children: /* @__PURE__ */ jsx17(Icon, { className: "h-6 w-6" }) }),
|
|
2635
|
+
/* @__PURE__ */ jsx17("p", { className: "mt-4 font-display text-lg font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2636
|
+
/* @__PURE__ */ jsx17("p", { className: "mt-1.5 text-sm leading-relaxed text-ph-subtle", children: emptyState }),
|
|
2637
|
+
presets.length > 0 ? /* @__PURE__ */ jsx17("div", { className: "mt-5 flex w-full flex-col gap-2", children: presets.map((preset) => /* @__PURE__ */ jsxs15(
|
|
2553
2638
|
"button",
|
|
2554
2639
|
{
|
|
2555
2640
|
type: "button",
|
|
2556
|
-
onClick: () => void
|
|
2557
|
-
|
|
2641
|
+
onClick: () => void ask(preset.prompt),
|
|
2642
|
+
disabled: loading || hydrating,
|
|
2643
|
+
className: "group flex w-full items-center gap-2 rounded-xl border border-ph-border bg-ph-surface px-3.5 py-2.5 text-left text-sm text-ph-ink transition-colors hover:border-ph-brand/40 hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2558
2644
|
children: [
|
|
2559
|
-
|
|
2560
|
-
|
|
2645
|
+
/* @__PURE__ */ jsx17(Sparks, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
2646
|
+
/* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate", children: preset.label }),
|
|
2647
|
+
/* @__PURE__ */ jsx17(ArrowUp, { className: "h-3.5 w-3.5 shrink-0 rotate-45 text-ph-mutedtext transition-transform group-hover:translate-x-0.5" })
|
|
2561
2648
|
]
|
|
2562
|
-
}
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2649
|
+
},
|
|
2650
|
+
preset.label
|
|
2651
|
+
)) }) : null
|
|
2652
|
+
] }) : null,
|
|
2653
|
+
messages.map((message, index) => {
|
|
2654
|
+
const isUser = message.role === "user";
|
|
2655
|
+
if (isUser) {
|
|
2656
|
+
return /* @__PURE__ */ jsx17(
|
|
2657
|
+
"div",
|
|
2658
|
+
{
|
|
2659
|
+
className: "flex justify-end",
|
|
2660
|
+
"data-test": "ask-ai-user",
|
|
2661
|
+
children: /* @__PURE__ */ jsx17("div", { className: "max-w-[min(85%,42rem)] whitespace-pre-wrap break-words rounded-2xl rounded-br-md bg-ph-brand/12 px-3.5 py-2.5 text-sm leading-relaxed text-ph-ink", children: message.content })
|
|
2662
|
+
},
|
|
2663
|
+
`user-${index}`
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2666
|
+
return /* @__PURE__ */ jsxs15(
|
|
2667
|
+
"div",
|
|
2668
|
+
{
|
|
2669
|
+
className: "flex gap-3",
|
|
2670
|
+
"data-test": "ask-ai-assistant",
|
|
2671
|
+
children: [
|
|
2672
|
+
/* @__PURE__ */ jsx17(
|
|
2673
|
+
"span",
|
|
2674
|
+
{
|
|
2675
|
+
className: "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand",
|
|
2676
|
+
"aria-hidden": true,
|
|
2677
|
+
children: /* @__PURE__ */ jsx17(Icon, { className: "h-4 w-4" })
|
|
2678
|
+
}
|
|
2679
|
+
),
|
|
2680
|
+
/* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
|
|
2681
|
+
/* @__PURE__ */ jsx17("div", { className: "text-sm leading-relaxed text-ph-ink", children: /* @__PURE__ */ jsx17(
|
|
2682
|
+
Suspense,
|
|
2683
|
+
{
|
|
2684
|
+
fallback: /* @__PURE__ */ jsx17("p", { className: "whitespace-pre-wrap break-words", children: message.content }),
|
|
2685
|
+
children: /* @__PURE__ */ jsx17(
|
|
2686
|
+
SuiteAiBlockNoteMessage,
|
|
2687
|
+
{
|
|
2688
|
+
markdown: message.content
|
|
2689
|
+
}
|
|
2690
|
+
)
|
|
2691
|
+
}
|
|
2692
|
+
) }),
|
|
2693
|
+
/* @__PURE__ */ jsxs15(
|
|
2694
|
+
"button",
|
|
2695
|
+
{
|
|
2696
|
+
type: "button",
|
|
2697
|
+
onClick: () => void copyMessage(index, message.content),
|
|
2698
|
+
className: "mt-1.5 inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-xs text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus",
|
|
2699
|
+
children: [
|
|
2700
|
+
copiedId === index ? /* @__PURE__ */ jsx17(Check2, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx17(Copy, { className: "h-3 w-3" }),
|
|
2701
|
+
copiedId === index ? "Copied" : "Copy"
|
|
2702
|
+
]
|
|
2703
|
+
}
|
|
2704
|
+
)
|
|
2705
|
+
] })
|
|
2706
|
+
]
|
|
2707
|
+
},
|
|
2708
|
+
`assistant-${index}`
|
|
2709
|
+
);
|
|
2710
|
+
}),
|
|
2711
|
+
loading ? /* @__PURE__ */ jsxs15("div", { className: "flex gap-3", "aria-hidden": true, children: [
|
|
2712
|
+
/* @__PURE__ */ jsx17("span", { className: "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand", children: /* @__PURE__ */ jsx17(Icon, { className: "h-4 w-4" }) }),
|
|
2713
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1.5 py-1.5", children: [
|
|
2714
|
+
/* @__PURE__ */ jsx17("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce" }),
|
|
2715
|
+
/* @__PURE__ */ jsx17("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.15s]" }),
|
|
2716
|
+
/* @__PURE__ */ jsx17("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.3s]" })
|
|
2717
|
+
] })
|
|
2718
|
+
] }) : null,
|
|
2719
|
+
loading ? /* @__PURE__ */ jsx17("span", { className: "sr-only", "aria-live": "polite", children: "Assistant is responding\u2026" }) : null,
|
|
2720
|
+
error ? /* @__PURE__ */ jsxs15(
|
|
2721
|
+
"div",
|
|
2722
|
+
{
|
|
2723
|
+
role: "alert",
|
|
2724
|
+
className: "flex items-start gap-2.5 rounded-xl border border-ph-danger/30 bg-ph-danger/10 px-3.5 py-3 text-sm text-ph-ink",
|
|
2725
|
+
children: [
|
|
2726
|
+
/* @__PURE__ */ jsx17(WarningTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-ph-danger" }),
|
|
2727
|
+
/* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
|
|
2728
|
+
/* @__PURE__ */ jsx17("p", { className: "font-medium text-ph-danger", children: "Something went wrong" }),
|
|
2729
|
+
/* @__PURE__ */ jsx17("p", { className: "mt-0.5 text-ph-subtle", children: error }),
|
|
2730
|
+
/* @__PURE__ */ jsx17(
|
|
2731
|
+
"button",
|
|
2732
|
+
{
|
|
2733
|
+
type: "button",
|
|
2734
|
+
onClick: retry,
|
|
2735
|
+
disabled: loading,
|
|
2736
|
+
className: "mt-2 inline-flex min-h-8 items-center gap-1.5 rounded-lg border border-ph-border bg-ph-surface px-2.5 text-xs font-medium text-ph-ink transition-colors hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2737
|
+
children: "Try again"
|
|
2738
|
+
}
|
|
2739
|
+
)
|
|
2740
|
+
] })
|
|
2741
|
+
]
|
|
2742
|
+
}
|
|
2743
|
+
) : null
|
|
2744
|
+
]
|
|
2586
2745
|
}
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2746
|
+
),
|
|
2747
|
+
!atBottom ? /* @__PURE__ */ jsx17(
|
|
2748
|
+
"button",
|
|
2749
|
+
{
|
|
2750
|
+
type: "button",
|
|
2751
|
+
onClick: () => scrollToBottom("smooth"),
|
|
2752
|
+
className: "absolute bottom-3 left-1/2 flex h-9 w-9 -translate-x-1/2 items-center justify-center rounded-full border border-ph-border bg-ph-surface text-ph-subtle shadow-ph-md transition-colors hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus motion-safe:animate-[suite-ai-fade_150ms_ease-out]",
|
|
2753
|
+
"aria-label": "Scroll to latest",
|
|
2754
|
+
children: /* @__PURE__ */ jsx17(ArrowDown, { className: "h-4 w-4" })
|
|
2755
|
+
}
|
|
2756
|
+
) : null
|
|
2757
|
+
] }),
|
|
2758
|
+
/* @__PURE__ */ jsxs15("div", { className: "px-3 pb-[max(0.75rem,env(safe-area-inset-bottom))] pt-1", children: [
|
|
2759
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-end gap-2 rounded-3xl border border-ph-border bg-ph-surface px-2 py-1 shadow-sm transition-colors focus-within:border-ph-brand/45 focus-within:ring-2 focus-within:ring-ph-focus/35", children: [
|
|
2760
|
+
/* @__PURE__ */ jsx17("label", { htmlFor: "suite-ask-ai-input", className: "sr-only", children: "Ask a question" }),
|
|
2761
|
+
/* @__PURE__ */ jsx17(
|
|
2762
|
+
"textarea",
|
|
2763
|
+
{
|
|
2764
|
+
id: "suite-ask-ai-input",
|
|
2765
|
+
ref: textareaRef,
|
|
2766
|
+
value: prompt,
|
|
2767
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
2768
|
+
onKeyDown: (e) => {
|
|
2769
|
+
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
2770
|
+
e.preventDefault();
|
|
2771
|
+
void ask(prompt);
|
|
2772
|
+
}
|
|
2773
|
+
},
|
|
2774
|
+
placeholder: "Ask anything\u2026",
|
|
2775
|
+
rows: 1,
|
|
2776
|
+
"data-test": "ask-ai-input",
|
|
2777
|
+
className: "max-h-44 min-h-[44px] flex-1 resize-none bg-transparent px-2 py-2.5 text-sm leading-relaxed text-ph-ink outline-none placeholder:text-ph-mutedtext"
|
|
2778
|
+
}
|
|
2779
|
+
),
|
|
2780
|
+
loading ? /* @__PURE__ */ jsx17(
|
|
2781
|
+
"button",
|
|
2782
|
+
{
|
|
2783
|
+
type: "button",
|
|
2784
|
+
onClick: stop,
|
|
2785
|
+
"data-test": "ask-ai-stop",
|
|
2786
|
+
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-ph-muted text-ph-ink transition-colors hover:bg-ph-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus",
|
|
2787
|
+
"aria-label": "Stop generating",
|
|
2788
|
+
children: /* @__PURE__ */ jsx17(Square, { className: "h-3.5 w-3.5 fill-current" })
|
|
2789
|
+
}
|
|
2790
|
+
) : /* @__PURE__ */ jsx17(
|
|
2791
|
+
"button",
|
|
2792
|
+
{
|
|
2793
|
+
type: "button",
|
|
2794
|
+
onClick: () => void ask(prompt),
|
|
2795
|
+
disabled: !prompt.trim(),
|
|
2796
|
+
"data-test": "ask-ai-send",
|
|
2797
|
+
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-ph-brand text-[color:var(--ph-on-accent)] transition-opacity hover:bg-ph-brand-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2798
|
+
"aria-label": "Send message",
|
|
2799
|
+
children: /* @__PURE__ */ jsx17(ArrowUp, { className: "h-[18px] w-[18px]" })
|
|
2800
|
+
}
|
|
2801
|
+
)
|
|
2802
|
+
] }),
|
|
2803
|
+
/* @__PURE__ */ jsxs15("p", { className: "mt-1.5 px-1 text-center text-xs text-ph-mutedtext", children: [
|
|
2804
|
+
/* @__PURE__ */ jsx17("kbd", { className: "font-mono", children: "Enter" }),
|
|
2805
|
+
" to send \xB7",
|
|
2806
|
+
" ",
|
|
2807
|
+
/* @__PURE__ */ jsx17("kbd", { className: "font-mono", children: "Shift" }),
|
|
2808
|
+
"+",
|
|
2809
|
+
/* @__PURE__ */ jsx17("kbd", { className: "font-mono", children: "Enter" }),
|
|
2810
|
+
" for a new line"
|
|
2811
|
+
] })
|
|
2812
|
+
] })
|
|
2813
|
+
]
|
|
2814
|
+
}
|
|
2815
|
+
)
|
|
2816
|
+
]
|
|
2817
|
+
}
|
|
2818
|
+
) : null
|
|
2611
2819
|
] });
|
|
2612
2820
|
}
|
|
2613
2821
|
|
|
@@ -3059,7 +3267,7 @@ function SuiteSidebar({
|
|
|
3059
3267
|
{
|
|
3060
3268
|
className: cn(
|
|
3061
3269
|
"flex items-center gap-2",
|
|
3062
|
-
collapsed ? "flex-col justify-center" : "min-w-0"
|
|
3270
|
+
collapsed ? "flex-col items-center justify-center [&_[data-test$='-visible-sign-out']]:hidden [&>div]:w-auto" : "w-full min-w-0"
|
|
3063
3271
|
),
|
|
3064
3272
|
children: [
|
|
3065
3273
|
renderNode(userMenu, collapsed),
|