@xenide-io/the-old-ui-theme 0.6.6 → 0.6.8
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/{ai-message-blocknote-4Q4U2T2W.mjs → ai-message-blocknote-DIUICX3G.mjs} +1 -1
- package/dist/{chunk-IAH7Z46I.mjs → chunk-VIWW7AW2.mjs} +3 -0
- package/dist/{chunk-3G43JEI3.mjs → chunk-VOCHIR3W.mjs} +2 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/dist/suite.d.mts +64 -15
- package/dist/suite.d.ts +64 -15
- package/dist/suite.js +753 -758
- package/dist/suite.mjs +573 -587
- package/dist/ui.js +2 -2
- package/dist/ui.mjs +1 -1
- package/package.json +1 -1
- package/src/app/globals.css +8 -1
- package/src/styles/suite-skin.css +6 -0
- package/src/styles/themes.css +36 -34
- package/src/suite/components/ai-panel.test.ts +14 -40
- package/src/suite/components/ai-panel.tsx +305 -633
- package/src/suite/components/suite-app-layout.tsx +3 -2
- package/src/suite/components/suite-layout.test.tsx +36 -2
- package/src/suite/components/suite-sidebar.tsx +235 -102
- package/src/suite/components/theme-provider.test.tsx +48 -0
- package/src/suite/components/theme-provider.tsx +4 -0
- package/src/suite/components/today-ui.tsx +1 -1
- package/src/suite/components/workspace-switcher.tsx +162 -0
- package/src/suite/index.ts +9 -0
- package/src/suite/lib/apps.test.ts +40 -0
- package/src/suite/lib/apps.ts +37 -0
- package/src/suite/lib/use-sidebar-width.ts +11 -1
package/dist/suite.js
CHANGED
|
@@ -106,6 +106,9 @@ function SuiteThemeProvider({
|
|
|
106
106
|
return { theme: theme2, resolvedTheme: resolvedTheme2 };
|
|
107
107
|
});
|
|
108
108
|
const { theme, resolvedTheme } = state;
|
|
109
|
+
(0, import_react7.useEffect)(() => {
|
|
110
|
+
applyTheme(theme, config);
|
|
111
|
+
}, [theme, config]);
|
|
109
112
|
(0, import_react7.useEffect)(() => {
|
|
110
113
|
if (theme !== "system") return;
|
|
111
114
|
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
@@ -163,8 +166,8 @@ function SuiteAiBlockNoteMessage({
|
|
|
163
166
|
markdown
|
|
164
167
|
}) {
|
|
165
168
|
const { resolvedTheme } = useSuiteTheme();
|
|
166
|
-
const editor = (0,
|
|
167
|
-
(0,
|
|
169
|
+
const editor = (0, import_react10.useCreateBlockNote)({ schema: assistantSchema });
|
|
170
|
+
(0, import_react9.useEffect)(() => {
|
|
168
171
|
try {
|
|
169
172
|
const blocks = editor.tryParseMarkdownToBlocks(markdown);
|
|
170
173
|
editor.replaceBlocks(
|
|
@@ -177,8 +180,8 @@ function SuiteAiBlockNoteMessage({
|
|
|
177
180
|
]);
|
|
178
181
|
}
|
|
179
182
|
}, [editor, markdown]);
|
|
180
|
-
return /* @__PURE__ */ (0,
|
|
181
|
-
|
|
183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
184
|
+
import_react10.BlockNoteViewRaw,
|
|
182
185
|
{
|
|
183
186
|
editor,
|
|
184
187
|
editable: false,
|
|
@@ -194,17 +197,17 @@ function SuiteAiBlockNoteMessage({
|
|
|
194
197
|
}
|
|
195
198
|
);
|
|
196
199
|
}
|
|
197
|
-
var
|
|
200
|
+
var import_react9, import_core, import_react10, import_style, import_jsx_runtime20, assistantSchema;
|
|
198
201
|
var init_ai_message_blocknote = __esm({
|
|
199
202
|
"src/suite/components/ai-message-blocknote.tsx"() {
|
|
200
203
|
"use strict";
|
|
201
204
|
"use client";
|
|
202
|
-
|
|
205
|
+
import_react9 = require("react");
|
|
203
206
|
import_core = require("@blocknote/core");
|
|
204
|
-
|
|
207
|
+
import_react10 = require("@blocknote/react");
|
|
205
208
|
import_style = require("@blocknote/react/style.css");
|
|
206
209
|
init_theme_provider();
|
|
207
|
-
|
|
210
|
+
import_jsx_runtime20 = require("react/jsx-runtime");
|
|
208
211
|
assistantSchema = import_core.BlockNoteSchema.create({
|
|
209
212
|
blockSpecs: {
|
|
210
213
|
paragraph: import_core.defaultBlockSpecs.paragraph,
|
|
@@ -270,6 +273,7 @@ __export(suite_exports, {
|
|
|
270
273
|
SuiteThemeProvider: () => SuiteThemeProvider,
|
|
271
274
|
SuiteToolbar: () => SuiteToolbar,
|
|
272
275
|
SuiteUserMenu: () => SuiteUserMenu,
|
|
276
|
+
SuiteWorkspaceSwitcher: () => SuiteWorkspaceSwitcher,
|
|
273
277
|
TodayAskAiCard: () => TodayAskAiCard,
|
|
274
278
|
TodayCalibrating: () => TodayCalibrating,
|
|
275
279
|
TodayEmptyAction: () => TodayEmptyAction,
|
|
@@ -285,11 +289,14 @@ __export(suite_exports, {
|
|
|
285
289
|
appSwitcherMarkClass: () => appSwitcherMarkClass,
|
|
286
290
|
appSwitcherMenuItemClass: () => appSwitcherMenuItemClass,
|
|
287
291
|
appSwitcherTriggerClass: () => appSwitcherTriggerClass,
|
|
292
|
+
classifySuiteHref: () => classifySuiteHref,
|
|
288
293
|
cn: () => cn,
|
|
294
|
+
consumePendingAskAiPrompt: () => consumePendingAskAiPrompt,
|
|
289
295
|
getTodayGreeting: () => getTodayGreeting,
|
|
290
|
-
m: () =>
|
|
296
|
+
m: () => import_react14.m,
|
|
291
297
|
openSuiteAskAi: () => openSuiteAskAi,
|
|
292
298
|
resolveSuiteNotificationHref: () => resolveSuiteNotificationHref,
|
|
299
|
+
sidebarColumnWidth: () => sidebarColumnWidth,
|
|
293
300
|
sourceToSuiteApp: () => sourceToSuiteApp,
|
|
294
301
|
suiteAppBaseUrl: () => suiteAppBaseUrl,
|
|
295
302
|
suiteAppLabel: () => suiteAppLabel,
|
|
@@ -1085,7 +1092,7 @@ function TodayLayout({
|
|
|
1085
1092
|
);
|
|
1086
1093
|
}
|
|
1087
1094
|
function TodayAskAiCard({
|
|
1088
|
-
title = "
|
|
1095
|
+
title = "Shelly AI",
|
|
1089
1096
|
description = "Ask about your workspace, draft something, or look a fact up online.",
|
|
1090
1097
|
cta = "Ask",
|
|
1091
1098
|
className,
|
|
@@ -1418,6 +1425,31 @@ function resolveSuiteNotificationHref(href, sourceApp) {
|
|
|
1418
1425
|
if (!slug) return path;
|
|
1419
1426
|
return `${suiteAppBaseUrl(slug)}${path}`;
|
|
1420
1427
|
}
|
|
1428
|
+
function classifySuiteHref(href, bases, currentOrigin = "") {
|
|
1429
|
+
let url;
|
|
1430
|
+
try {
|
|
1431
|
+
url = new URL(href, currentOrigin || "http://local.invalid");
|
|
1432
|
+
} catch (e) {
|
|
1433
|
+
return null;
|
|
1434
|
+
}
|
|
1435
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
1436
|
+
for (const slug of Object.keys(bases)) {
|
|
1437
|
+
const base = bases[slug];
|
|
1438
|
+
if (!base) continue;
|
|
1439
|
+
try {
|
|
1440
|
+
if (new URL(base).origin !== url.origin) continue;
|
|
1441
|
+
} catch (e) {
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
const path = `${url.pathname}${url.search}${url.hash}` || "/";
|
|
1445
|
+
return {
|
|
1446
|
+
slug,
|
|
1447
|
+
path,
|
|
1448
|
+
sameApp: Boolean(currentOrigin && url.origin === currentOrigin)
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1421
1453
|
|
|
1422
1454
|
// src/suite/components/suite-notification-bell.tsx
|
|
1423
1455
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
@@ -2562,12 +2594,152 @@ function TodayCalibrating({
|
|
|
2562
2594
|
init_theme_provider();
|
|
2563
2595
|
|
|
2564
2596
|
// src/suite/components/ai-panel.tsx
|
|
2565
|
-
var
|
|
2597
|
+
var import_react11 = require("react");
|
|
2566
2598
|
var import_iconoir_react8 = require("iconoir-react");
|
|
2567
|
-
|
|
2568
|
-
|
|
2599
|
+
|
|
2600
|
+
// src/components/ui/Tooltip.tsx
|
|
2601
|
+
var import_react8 = require("react");
|
|
2602
|
+
var import_react_dom = require("react-dom");
|
|
2603
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2604
|
+
var TooltipDelayContext = (0, import_react8.createContext)(0);
|
|
2605
|
+
function tooltipPosition(trigger, side, align, offset) {
|
|
2606
|
+
const horizontal = align === "start" ? trigger.left : align === "end" ? trigger.right : trigger.left + trigger.width / 2;
|
|
2607
|
+
const vertical = align === "start" ? trigger.top : align === "end" ? trigger.bottom : trigger.top + trigger.height / 2;
|
|
2608
|
+
if (side === "top")
|
|
2609
|
+
return {
|
|
2610
|
+
left: horizontal,
|
|
2611
|
+
top: trigger.top - offset,
|
|
2612
|
+
transform: "translate(-50%, -100%)"
|
|
2613
|
+
};
|
|
2614
|
+
if (side === "bottom")
|
|
2615
|
+
return {
|
|
2616
|
+
left: horizontal,
|
|
2617
|
+
top: trigger.bottom + offset,
|
|
2618
|
+
transform: "translate(-50%, 0)"
|
|
2619
|
+
};
|
|
2620
|
+
if (side === "left")
|
|
2621
|
+
return {
|
|
2622
|
+
left: trigger.left - offset,
|
|
2623
|
+
top: vertical,
|
|
2624
|
+
transform: "translate(-100%, -50%)"
|
|
2625
|
+
};
|
|
2626
|
+
return {
|
|
2627
|
+
left: trigger.right + offset,
|
|
2628
|
+
top: vertical,
|
|
2629
|
+
transform: "translate(0, -50%)"
|
|
2630
|
+
};
|
|
2631
|
+
}
|
|
2632
|
+
function Tooltip({
|
|
2633
|
+
content,
|
|
2634
|
+
children,
|
|
2635
|
+
side = "top",
|
|
2636
|
+
align = "center",
|
|
2637
|
+
sideOffset = 7,
|
|
2638
|
+
className,
|
|
2639
|
+
open,
|
|
2640
|
+
defaultOpen = false,
|
|
2641
|
+
onOpenChange,
|
|
2642
|
+
delayDuration
|
|
2643
|
+
}) {
|
|
2644
|
+
const providerDelay = (0, import_react8.useContext)(TooltipDelayContext);
|
|
2645
|
+
const generatedId = (0, import_react8.useId)().replace(/:/g, "");
|
|
2646
|
+
const triggerRef = (0, import_react8.useRef)(null);
|
|
2647
|
+
const timerRef = (0, import_react8.useRef)(null);
|
|
2648
|
+
const [internalOpen, setInternalOpen] = (0, import_react8.useState)(defaultOpen);
|
|
2649
|
+
const [position, setPosition] = (0, import_react8.useState)(null);
|
|
2650
|
+
const isOpen = open != null ? open : internalOpen;
|
|
2651
|
+
const triggerId = children.props.id;
|
|
2652
|
+
const tooltipId = triggerId ? `${triggerId}-tooltip` : `ph-tooltip-${generatedId}`;
|
|
2653
|
+
function setOpen(next) {
|
|
2654
|
+
if (open === void 0) setInternalOpen(next);
|
|
2655
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
2656
|
+
}
|
|
2657
|
+
function clearTimer() {
|
|
2658
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
2659
|
+
timerRef.current = null;
|
|
2660
|
+
}
|
|
2661
|
+
function updatePosition() {
|
|
2662
|
+
if (!triggerRef.current) return;
|
|
2663
|
+
setPosition(
|
|
2664
|
+
tooltipPosition(
|
|
2665
|
+
triggerRef.current.getBoundingClientRect(),
|
|
2666
|
+
side,
|
|
2667
|
+
align,
|
|
2668
|
+
sideOffset
|
|
2669
|
+
)
|
|
2670
|
+
);
|
|
2671
|
+
}
|
|
2672
|
+
function show(immediate) {
|
|
2673
|
+
clearTimer();
|
|
2674
|
+
updatePosition();
|
|
2675
|
+
const delay = immediate ? 0 : delayDuration != null ? delayDuration : providerDelay;
|
|
2676
|
+
if (!delay) setOpen(true);
|
|
2677
|
+
else timerRef.current = setTimeout(() => setOpen(true), delay);
|
|
2678
|
+
}
|
|
2679
|
+
function hide() {
|
|
2680
|
+
clearTimer();
|
|
2681
|
+
setOpen(false);
|
|
2682
|
+
}
|
|
2683
|
+
(0, import_react8.useEffect)(() => {
|
|
2684
|
+
if (!isOpen) return;
|
|
2685
|
+
const reposition = () => updatePosition();
|
|
2686
|
+
window.addEventListener("resize", reposition);
|
|
2687
|
+
window.addEventListener("scroll", reposition, true);
|
|
2688
|
+
return () => {
|
|
2689
|
+
window.removeEventListener("resize", reposition);
|
|
2690
|
+
window.removeEventListener("scroll", reposition, true);
|
|
2691
|
+
};
|
|
2692
|
+
});
|
|
2693
|
+
(0, import_react8.useEffect)(() => () => clearTimer(), []);
|
|
2694
|
+
const describedBy = [children.props["aria-describedby"], tooltipId].filter(Boolean).join(" ");
|
|
2695
|
+
const trigger = (0, import_react8.cloneElement)(children, { "aria-describedby": describedBy });
|
|
2696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2697
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2698
|
+
"span",
|
|
2699
|
+
{
|
|
2700
|
+
ref: triggerRef,
|
|
2701
|
+
className: "inline-flex",
|
|
2702
|
+
onMouseEnter: () => show(false),
|
|
2703
|
+
onMouseLeave: hide,
|
|
2704
|
+
onFocusCapture: () => show(true),
|
|
2705
|
+
onBlurCapture: hide,
|
|
2706
|
+
onKeyDown: (event) => {
|
|
2707
|
+
if (event.key === "Escape") hide();
|
|
2708
|
+
},
|
|
2709
|
+
children: trigger
|
|
2710
|
+
}
|
|
2711
|
+
),
|
|
2712
|
+
isOpen && position && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2714
|
+
"span",
|
|
2715
|
+
{
|
|
2716
|
+
style: __spreadValues({ position: "fixed" }, position),
|
|
2717
|
+
className: "pointer-events-none z-[200]",
|
|
2718
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2719
|
+
"span",
|
|
2720
|
+
{
|
|
2721
|
+
id: tooltipId,
|
|
2722
|
+
role: "tooltip",
|
|
2723
|
+
"data-side": side,
|
|
2724
|
+
className: cn2("ph-tooltip-content", className),
|
|
2725
|
+
children: content
|
|
2726
|
+
}
|
|
2727
|
+
)
|
|
2728
|
+
}
|
|
2729
|
+
),
|
|
2730
|
+
document.body
|
|
2731
|
+
) : null
|
|
2732
|
+
] });
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
// src/suite/components/ai-panel.tsx
|
|
2736
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2737
|
+
var SuiteAiBlockNoteMessage2 = (0, import_react11.lazy)(() => Promise.resolve().then(() => (init_ai_message_blocknote(), ai_message_blocknote_exports)));
|
|
2569
2738
|
var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
|
|
2739
|
+
var pendingAskAiPrompt = null;
|
|
2570
2740
|
function openSuiteAskAi(detail) {
|
|
2741
|
+
var _a;
|
|
2742
|
+
pendingAskAiPrompt = ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) || null;
|
|
2571
2743
|
if (typeof window === "undefined") return;
|
|
2572
2744
|
window.dispatchEvent(
|
|
2573
2745
|
new CustomEvent(SUITE_OPEN_ASK_AI_EVENT, {
|
|
@@ -2575,138 +2747,72 @@ function openSuiteAskAi(detail) {
|
|
|
2575
2747
|
})
|
|
2576
2748
|
);
|
|
2577
2749
|
}
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
LAUNCHER_EDGE_GAP,
|
|
2583
|
-
viewportWidth - launcherWidth - LAUNCHER_EDGE_GAP
|
|
2584
|
-
);
|
|
2585
|
-
const maxY = Math.max(
|
|
2586
|
-
LAUNCHER_EDGE_GAP,
|
|
2587
|
-
viewportHeight - launcherHeight - LAUNCHER_EDGE_GAP
|
|
2588
|
-
);
|
|
2589
|
-
const clampX = (x) => Math.min(Math.max(x, LAUNCHER_EDGE_GAP), maxX);
|
|
2590
|
-
const clampY = (y) => Math.min(Math.max(y, LAUNCHER_EDGE_GAP), maxY);
|
|
2591
|
-
switch (edge) {
|
|
2592
|
-
case "left":
|
|
2593
|
-
return { x: LAUNCHER_EDGE_GAP, y: clampY(desiredY) };
|
|
2594
|
-
case "right":
|
|
2595
|
-
return { x: maxX, y: clampY(desiredY) };
|
|
2596
|
-
case "top":
|
|
2597
|
-
return { x: clampX(desiredX), y: LAUNCHER_EDGE_GAP };
|
|
2598
|
-
case "bottom":
|
|
2599
|
-
return { x: clampX(desiredX), y: maxY };
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
function resolveSuiteAiNearestEdge(x, y, width, height, viewportWidth, viewportHeight) {
|
|
2603
|
-
const centerX = x + width / 2;
|
|
2604
|
-
const centerY = y + height / 2;
|
|
2605
|
-
const candidates = [
|
|
2606
|
-
{ edge: "left", distance: centerX },
|
|
2607
|
-
{ edge: "right", distance: viewportWidth - centerX },
|
|
2608
|
-
{ edge: "top", distance: centerY },
|
|
2609
|
-
{ edge: "bottom", distance: viewportHeight - centerY }
|
|
2610
|
-
];
|
|
2611
|
-
return candidates.reduce(
|
|
2612
|
-
(nearest, candidate) => candidate.distance < nearest.distance ? candidate : nearest
|
|
2613
|
-
).edge;
|
|
2614
|
-
}
|
|
2615
|
-
function resolveSuiteAiPanelSide(edge, x, viewportWidth) {
|
|
2616
|
-
if (edge === "left") return "left";
|
|
2617
|
-
if (edge === "right") return "right";
|
|
2618
|
-
return x < viewportWidth / 2 ? "left" : "right";
|
|
2750
|
+
function consumePendingAskAiPrompt() {
|
|
2751
|
+
const next = pendingAskAiPrompt;
|
|
2752
|
+
pendingAskAiPrompt = null;
|
|
2753
|
+
return next;
|
|
2619
2754
|
}
|
|
2620
2755
|
function SuiteAiPanel({
|
|
2621
2756
|
presets = [],
|
|
2622
2757
|
emptyState = "Ask anything about your workspace, or look something up online.",
|
|
2623
|
-
title = "
|
|
2758
|
+
title = "Shelly AI",
|
|
2624
2759
|
fetchChat,
|
|
2625
2760
|
sendMessage,
|
|
2626
2761
|
clearChat,
|
|
2627
2762
|
brandIcon: BrandIcon,
|
|
2628
2763
|
spinner: Spinner,
|
|
2629
|
-
|
|
2764
|
+
open: openProp,
|
|
2765
|
+
onOpenChange,
|
|
2766
|
+
suiteAppBases,
|
|
2767
|
+
onSwitchApp
|
|
2630
2768
|
}) {
|
|
2631
|
-
const
|
|
2632
|
-
const [
|
|
2633
|
-
const
|
|
2634
|
-
const
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
const [
|
|
2642
|
-
const [
|
|
2643
|
-
const
|
|
2644
|
-
const
|
|
2645
|
-
const
|
|
2646
|
-
const
|
|
2647
|
-
const
|
|
2648
|
-
const
|
|
2649
|
-
const
|
|
2650
|
-
const
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
);
|
|
2662
|
-
if ((stored == null ? void 0 : stored.side) === "top" || (stored == null ? void 0 : stored.side) === "right" || (stored == null ? void 0 : stored.side) === "bottom" || (stored == null ? void 0 : stored.side) === "left")
|
|
2663
|
-
side = stored.side;
|
|
2664
|
-
if (typeof (stored == null ? void 0 : stored.x) === "number") desiredX = stored.x;
|
|
2665
|
-
if (typeof (stored == null ? void 0 : stored.y) === "number") desiredY = stored.y;
|
|
2666
|
-
} catch (e) {
|
|
2769
|
+
const inputId = (0, import_react11.useId)();
|
|
2770
|
+
const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react11.useState)(false);
|
|
2771
|
+
const open = openProp != null ? openProp : uncontrolledOpen;
|
|
2772
|
+
const setOpen = (0, import_react11.useCallback)(
|
|
2773
|
+
(next) => {
|
|
2774
|
+
if (openProp === void 0) setUncontrolledOpen(next);
|
|
2775
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
2776
|
+
},
|
|
2777
|
+
[onOpenChange, openProp]
|
|
2778
|
+
);
|
|
2779
|
+
const [prompt, setPrompt] = (0, import_react11.useState)("");
|
|
2780
|
+
const [messages, setMessages] = (0, import_react11.useState)([]);
|
|
2781
|
+
const [loading, setLoading] = (0, import_react11.useState)(false);
|
|
2782
|
+
const [hydrating, setHydrating] = (0, import_react11.useState)(false);
|
|
2783
|
+
const [error, setError] = (0, import_react11.useState)("");
|
|
2784
|
+
const [atBottom, setAtBottom] = (0, import_react11.useState)(true);
|
|
2785
|
+
const scrollerRef = (0, import_react11.useRef)(null);
|
|
2786
|
+
const textareaRef = (0, import_react11.useRef)(null);
|
|
2787
|
+
const abortRef = (0, import_react11.useRef)(null);
|
|
2788
|
+
const pendingPromptRef = (0, import_react11.useRef)(null);
|
|
2789
|
+
(0, import_react11.useEffect)(() => {
|
|
2790
|
+
function onOpen(event) {
|
|
2791
|
+
var _a;
|
|
2792
|
+
const detail = event.detail;
|
|
2793
|
+
const queued = ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) || consumePendingAskAiPrompt();
|
|
2794
|
+
setOpen(true);
|
|
2795
|
+
if (queued) {
|
|
2796
|
+
pendingPromptRef.current = queued;
|
|
2797
|
+
setPrompt(queued);
|
|
2798
|
+
}
|
|
2667
2799
|
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
const element = launcherRef.current;
|
|
2673
|
-
if (!element) return;
|
|
2674
|
-
const next = resolveSuiteAiLauncherPosition(
|
|
2675
|
-
launcherSideRef.current,
|
|
2676
|
-
(_b = (_a = launcherPositionRef.current) == null ? void 0 : _a.x) != null ? _b : desiredX,
|
|
2677
|
-
(_d = (_c = launcherPositionRef.current) == null ? void 0 : _c.y) != null ? _d : desiredY,
|
|
2678
|
-
window.innerWidth,
|
|
2679
|
-
window.innerHeight,
|
|
2680
|
-
element.offsetWidth,
|
|
2681
|
-
element.offsetHeight
|
|
2682
|
-
);
|
|
2683
|
-
launcherPositionRef.current = next;
|
|
2684
|
-
setLauncherPosition(next);
|
|
2685
|
-
setPanelSide(
|
|
2686
|
-
resolveSuiteAiPanelSide(
|
|
2687
|
-
launcherSideRef.current,
|
|
2688
|
-
next.x,
|
|
2689
|
-
window.innerWidth
|
|
2690
|
-
)
|
|
2691
|
-
);
|
|
2692
|
-
};
|
|
2693
|
-
placeLauncher();
|
|
2694
|
-
window.addEventListener("resize", placeLauncher);
|
|
2695
|
-
return () => window.removeEventListener("resize", placeLauncher);
|
|
2696
|
-
}, []);
|
|
2697
|
-
const scrollToBottom = (0, import_react10.useCallback)((behavior = "auto") => {
|
|
2800
|
+
window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2801
|
+
return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2802
|
+
}, [setOpen]);
|
|
2803
|
+
const scrollToBottom = (0, import_react11.useCallback)((behavior = "auto") => {
|
|
2698
2804
|
const el = scrollerRef.current;
|
|
2699
2805
|
if (!el) return;
|
|
2700
2806
|
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
2701
2807
|
setAtBottom(true);
|
|
2702
2808
|
}, []);
|
|
2703
|
-
const handleScroll = (0,
|
|
2809
|
+
const handleScroll = (0, import_react11.useCallback)(() => {
|
|
2704
2810
|
const el = scrollerRef.current;
|
|
2705
2811
|
if (!el) return;
|
|
2706
2812
|
const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
2707
2813
|
setAtBottom(distance < 64);
|
|
2708
2814
|
}, []);
|
|
2709
|
-
const hydrate = (0,
|
|
2815
|
+
const hydrate = (0, import_react11.useCallback)(async () => {
|
|
2710
2816
|
var _a;
|
|
2711
2817
|
setHydrating(true);
|
|
2712
2818
|
setError("");
|
|
@@ -2718,51 +2824,31 @@ function SuiteAiPanel({
|
|
|
2718
2824
|
}
|
|
2719
2825
|
} catch (err) {
|
|
2720
2826
|
setError(
|
|
2721
|
-
err instanceof Error ? err.message : "Could not load
|
|
2827
|
+
err instanceof Error ? err.message : "Could not load Shelly AI."
|
|
2722
2828
|
);
|
|
2723
2829
|
} finally {
|
|
2724
2830
|
setHydrating(false);
|
|
2725
2831
|
}
|
|
2726
2832
|
}, [fetchChat]);
|
|
2727
|
-
(0,
|
|
2728
|
-
|
|
2729
|
-
var _a;
|
|
2730
|
-
const detail = event.detail;
|
|
2731
|
-
setOpen(true);
|
|
2732
|
-
if ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) {
|
|
2733
|
-
pendingPromptRef.current = detail.prompt.trim();
|
|
2734
|
-
setPrompt(detail.prompt.trim());
|
|
2735
|
-
}
|
|
2736
|
-
}
|
|
2737
|
-
window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2738
|
-
return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2739
|
-
}, []);
|
|
2740
|
-
(0, import_react10.useEffect)(() => {
|
|
2833
|
+
(0, import_react11.useEffect)(() => {
|
|
2834
|
+
var _a;
|
|
2741
2835
|
if (!open) return;
|
|
2836
|
+
const queued = (_a = pendingPromptRef.current) != null ? _a : consumePendingAskAiPrompt();
|
|
2837
|
+
pendingPromptRef.current = queued;
|
|
2742
2838
|
void hydrate().then(() => {
|
|
2743
2839
|
const pending = pendingPromptRef.current;
|
|
2744
2840
|
pendingPromptRef.current = null;
|
|
2745
|
-
if (pending)
|
|
2746
|
-
setPrompt(pending);
|
|
2747
|
-
}
|
|
2841
|
+
if (pending) setPrompt(pending);
|
|
2748
2842
|
});
|
|
2749
2843
|
}, [open, hydrate]);
|
|
2750
|
-
(0,
|
|
2844
|
+
(0, import_react11.useEffect)(() => {
|
|
2751
2845
|
if (open && atBottom) scrollToBottom();
|
|
2752
2846
|
}, [messages, loading, open, atBottom, scrollToBottom]);
|
|
2753
|
-
(0,
|
|
2847
|
+
(0, import_react11.useEffect)(() => {
|
|
2754
2848
|
var _a;
|
|
2755
2849
|
if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
|
|
2756
2850
|
}, [open, hydrating]);
|
|
2757
|
-
(0,
|
|
2758
|
-
if (!open) return;
|
|
2759
|
-
function onKey(event) {
|
|
2760
|
-
if (event.key === "Escape") setOpen(false);
|
|
2761
|
-
}
|
|
2762
|
-
window.addEventListener("keydown", onKey);
|
|
2763
|
-
return () => window.removeEventListener("keydown", onKey);
|
|
2764
|
-
}, [open]);
|
|
2765
|
-
(0, import_react10.useLayoutEffect)(() => {
|
|
2851
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2766
2852
|
const el = textareaRef.current;
|
|
2767
2853
|
if (!el) return;
|
|
2768
2854
|
el.style.height = "auto";
|
|
@@ -2811,7 +2897,7 @@ function SuiteAiPanel({
|
|
|
2811
2897
|
}
|
|
2812
2898
|
function retry() {
|
|
2813
2899
|
var _a;
|
|
2814
|
-
const lastUser = (_a = [...messages].reverse().find((
|
|
2900
|
+
const lastUser = (_a = [...messages].reverse().find((message) => message.role === "user")) == null ? void 0 : _a.content;
|
|
2815
2901
|
setError("");
|
|
2816
2902
|
if (lastUser) void ask(lastUser);
|
|
2817
2903
|
else void hydrate();
|
|
@@ -2828,417 +2914,346 @@ function SuiteAiPanel({
|
|
|
2828
2914
|
);
|
|
2829
2915
|
}
|
|
2830
2916
|
}
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
} catch (e) {
|
|
2837
|
-
}
|
|
2838
|
-
}
|
|
2839
|
-
function saveLauncherPosition(edge, position) {
|
|
2840
|
-
try {
|
|
2841
|
-
localStorage.setItem(
|
|
2842
|
-
LAUNCHER_STORAGE_KEY,
|
|
2843
|
-
JSON.stringify({ side: edge, x: position.x, y: position.y })
|
|
2844
|
-
);
|
|
2845
|
-
} catch (e) {
|
|
2846
|
-
}
|
|
2847
|
-
}
|
|
2848
|
-
function dockLauncher(edge, desiredX, desiredY) {
|
|
2849
|
-
const launcher = launcherRef.current;
|
|
2850
|
-
if (!launcher) return;
|
|
2851
|
-
const next = resolveSuiteAiLauncherPosition(
|
|
2852
|
-
edge,
|
|
2853
|
-
desiredX,
|
|
2854
|
-
desiredY,
|
|
2855
|
-
window.innerWidth,
|
|
2856
|
-
window.innerHeight,
|
|
2857
|
-
launcher.offsetWidth,
|
|
2858
|
-
launcher.offsetHeight
|
|
2859
|
-
);
|
|
2860
|
-
launcherSideRef.current = edge;
|
|
2861
|
-
launcherPositionRef.current = next;
|
|
2862
|
-
setLauncherSide(edge);
|
|
2863
|
-
setLauncherPosition(next);
|
|
2864
|
-
setPanelSide(resolveSuiteAiPanelSide(edge, next.x, window.innerWidth));
|
|
2865
|
-
saveLauncherPosition(edge, next);
|
|
2866
|
-
}
|
|
2867
|
-
function startLauncherDrag(event) {
|
|
2868
|
-
if (event.pointerType === "mouse" && event.button !== 0) return;
|
|
2869
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
2870
|
-
launcherDragRef.current = {
|
|
2871
|
-
pointerId: event.pointerId,
|
|
2872
|
-
offsetX: event.clientX - rect.left,
|
|
2873
|
-
offsetY: event.clientY - rect.top,
|
|
2874
|
-
startX: event.clientX,
|
|
2875
|
-
startY: event.clientY
|
|
2876
|
-
};
|
|
2877
|
-
suppressLauncherClickRef.current = false;
|
|
2878
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2879
|
-
setDraggingLauncher(true);
|
|
2880
|
-
}
|
|
2881
|
-
function moveLauncher(event) {
|
|
2882
|
-
const drag = launcherDragRef.current;
|
|
2883
|
-
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
2884
|
-
const launcher = event.currentTarget;
|
|
2885
|
-
const maxX = Math.max(
|
|
2886
|
-
LAUNCHER_EDGE_GAP,
|
|
2887
|
-
window.innerWidth - launcher.offsetWidth - LAUNCHER_EDGE_GAP
|
|
2888
|
-
);
|
|
2889
|
-
const maxY = Math.max(
|
|
2890
|
-
LAUNCHER_EDGE_GAP,
|
|
2891
|
-
window.innerHeight - launcher.offsetHeight - LAUNCHER_EDGE_GAP
|
|
2892
|
-
);
|
|
2893
|
-
const next = {
|
|
2894
|
-
x: Math.min(
|
|
2895
|
-
Math.max(event.clientX - drag.offsetX, LAUNCHER_EDGE_GAP),
|
|
2896
|
-
maxX
|
|
2897
|
-
),
|
|
2898
|
-
y: Math.min(
|
|
2899
|
-
Math.max(event.clientY - drag.offsetY, LAUNCHER_EDGE_GAP),
|
|
2900
|
-
maxY
|
|
2901
|
-
)
|
|
2902
|
-
};
|
|
2903
|
-
if (Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) > 4) {
|
|
2904
|
-
suppressLauncherClickRef.current = true;
|
|
2917
|
+
function onConversationClick(event) {
|
|
2918
|
+
var _a;
|
|
2919
|
+
if (event.defaultPrevented) return;
|
|
2920
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
2921
|
+
return;
|
|
2905
2922
|
}
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
2915
|
-
}
|
|
2916
|
-
launcherDragRef.current = null;
|
|
2917
|
-
setDraggingLauncher(false);
|
|
2918
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
2919
|
-
const currentX = (_b = (_a = launcherPositionRef.current) == null ? void 0 : _a.x) != null ? _b : rect.left;
|
|
2920
|
-
const currentY = (_d = (_c = launcherPositionRef.current) == null ? void 0 : _c.y) != null ? _d : rect.top;
|
|
2921
|
-
const edge = resolveSuiteAiNearestEdge(
|
|
2922
|
-
currentX,
|
|
2923
|
-
currentY,
|
|
2924
|
-
rect.width,
|
|
2925
|
-
rect.height,
|
|
2926
|
-
window.innerWidth,
|
|
2927
|
-
window.innerHeight
|
|
2923
|
+
const anchor = (_a = event.target) == null ? void 0 : _a.closest("a");
|
|
2924
|
+
if (!anchor || !suiteAppBases) return;
|
|
2925
|
+
const href = anchor.href;
|
|
2926
|
+
if (!href) return;
|
|
2927
|
+
const match = classifySuiteHref(
|
|
2928
|
+
href,
|
|
2929
|
+
suiteAppBases,
|
|
2930
|
+
window.location.origin
|
|
2928
2931
|
);
|
|
2929
|
-
|
|
2930
|
-
}
|
|
2931
|
-
function moveLauncherWithKeyboard(event) {
|
|
2932
|
-
var _a, _b, _c, _d;
|
|
2933
|
-
const edgeByKey = {
|
|
2934
|
-
ArrowLeft: "left",
|
|
2935
|
-
ArrowRight: "right",
|
|
2936
|
-
ArrowUp: "top",
|
|
2937
|
-
ArrowDown: "bottom"
|
|
2938
|
-
};
|
|
2939
|
-
const edge = edgeByKey[event.key];
|
|
2940
|
-
if (!edge) return;
|
|
2932
|
+
if (!match) return;
|
|
2941
2933
|
event.preventDefault();
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2934
|
+
if (match.sameApp) {
|
|
2935
|
+
window.location.assign(match.path);
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (onSwitchApp) onSwitchApp(match.slug, match.path);
|
|
2939
|
+
else window.location.assign(anchor.href);
|
|
2946
2940
|
}
|
|
2941
|
+
if (!open) return null;
|
|
2947
2942
|
const Icon = BrandIcon != null ? BrandIcon : import_iconoir_react8.Sparks;
|
|
2948
|
-
return /* @__PURE__ */ (0,
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
suppressLauncherClickRef.current = false;
|
|
2959
|
-
return;
|
|
2960
|
-
}
|
|
2961
|
-
setOpen(true);
|
|
2962
|
-
},
|
|
2963
|
-
onPointerDown: startLauncherDrag,
|
|
2964
|
-
onPointerMove: moveLauncher,
|
|
2965
|
-
onPointerUp: finishLauncherDrag,
|
|
2966
|
-
onPointerCancel: finishLauncherDrag,
|
|
2967
|
-
onKeyDown: moveLauncherWithKeyboard,
|
|
2968
|
-
className: `fixed z-30 flex touch-none select-none items-center gap-2 rounded-full border border-ph-border bg-ph-surface px-4 py-2.5 text-sm font-medium text-ph-ink shadow-ph hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand ${draggingLauncher ? "cursor-grabbing" : "cursor-grab"}`,
|
|
2969
|
-
style: launcherPosition ? { left: launcherPosition.x, top: launcherPosition.y } : { bottom: 20, right: 20 },
|
|
2970
|
-
"aria-label": "Open Ask AI",
|
|
2971
|
-
"aria-describedby": "suite-ask-ai-launcher-help",
|
|
2972
|
-
children: [
|
|
2973
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, { className: "h-4 w-4 text-ph-brand" }),
|
|
2974
|
-
"Ask AI"
|
|
2975
|
-
]
|
|
2976
|
-
}
|
|
2977
|
-
),
|
|
2978
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("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." })
|
|
2979
|
-
] }) : null,
|
|
2980
|
-
open ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2981
|
-
"div",
|
|
2982
|
-
{
|
|
2983
|
-
className: "fixed inset-0 z-40",
|
|
2984
|
-
role: "dialog",
|
|
2985
|
-
"aria-modal": "true",
|
|
2986
|
-
"aria-label": title,
|
|
2987
|
-
children: [
|
|
2988
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2944
|
+
"aside",
|
|
2945
|
+
{
|
|
2946
|
+
className: "flex h-full min-h-0 flex-col bg-ph-canvas",
|
|
2947
|
+
"data-test": "suite-ask-ai-panel",
|
|
2948
|
+
"aria-label": title,
|
|
2949
|
+
children: [
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("header", { className: "flex items-center gap-2 px-2 pb-2", children: [
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h2", { className: "sr-only", children: title }),
|
|
2952
|
+
messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2989
2953
|
"button",
|
|
2990
2954
|
{
|
|
2991
2955
|
type: "button",
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
"
|
|
2995
|
-
|
|
2956
|
+
onClick: () => void handleClear(),
|
|
2957
|
+
disabled: loading,
|
|
2958
|
+
className: "ml-auto inline-flex h-9 items-center gap-1.5 rounded-lg px-2 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",
|
|
2959
|
+
"data-test": "ask-ai-clear",
|
|
2960
|
+
children: [
|
|
2961
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.Erase, { className: "h-3.5 w-3.5" }),
|
|
2962
|
+
"Clear"
|
|
2963
|
+
]
|
|
2996
2964
|
}
|
|
2997
|
-
)
|
|
2998
|
-
|
|
2999
|
-
|
|
2965
|
+
) : null
|
|
2966
|
+
] }),
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative min-h-0 flex-1", children: [
|
|
2968
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2969
|
+
"div",
|
|
3000
2970
|
{
|
|
3001
|
-
|
|
3002
|
-
|
|
2971
|
+
ref: scrollerRef,
|
|
2972
|
+
onScroll: handleScroll,
|
|
2973
|
+
onClick: onConversationClick,
|
|
2974
|
+
role: "log",
|
|
2975
|
+
"aria-live": "polite",
|
|
2976
|
+
"aria-label": "Conversation",
|
|
2977
|
+
className: "suite-scroll-lock h-full space-y-5 overflow-y-auto px-2 py-3",
|
|
3003
2978
|
children: [
|
|
3004
|
-
/* @__PURE__ */ (0,
|
|
3005
|
-
/* @__PURE__ */ (0,
|
|
3006
|
-
|
|
2979
|
+
hydrating && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2 text-sm text-ph-subtle", children: [
|
|
2980
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2981
|
+
"Loading your chat\u2026"
|
|
2982
|
+
] }) : null,
|
|
2983
|
+
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mx-auto mt-4 flex max-w-sm flex-col items-center px-1 text-center", children: [
|
|
2984
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex h-10 w-10 items-center justify-center rounded-2xl bg-ph-brand/10 text-ph-brand", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { className: "h-5 w-5" }) }),
|
|
2985
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-3 font-display text-base font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2986
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-1 text-sm leading-relaxed text-ph-subtle", children: emptyState }),
|
|
2987
|
+
presets.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-4 flex w-full flex-col gap-2", children: presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3007
2988
|
"button",
|
|
3008
2989
|
{
|
|
3009
2990
|
type: "button",
|
|
3010
|
-
onClick: () => void
|
|
3011
|
-
disabled: loading,
|
|
3012
|
-
className: "
|
|
3013
|
-
"data-test": "ask-ai-clear",
|
|
2991
|
+
onClick: () => void ask(preset.prompt),
|
|
2992
|
+
disabled: loading || hydrating,
|
|
2993
|
+
className: "group flex w-full items-center gap-2 rounded-xl border border-ph-border bg-ph-surface px-3 py-2 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",
|
|
3014
2994
|
children: [
|
|
3015
|
-
/* @__PURE__ */ (0,
|
|
3016
|
-
"
|
|
2995
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.Sparks, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "min-w-0 flex-1 truncate", children: preset.label }),
|
|
2997
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.ArrowUp, { className: "h-3.5 w-3.5 shrink-0 rotate-45 text-ph-mutedtext transition-transform group-hover:translate-x-0.5" })
|
|
3017
2998
|
]
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
"
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
2999
|
+
},
|
|
3000
|
+
preset.label
|
|
3001
|
+
)) }) : null
|
|
3002
|
+
] }) : null,
|
|
3003
|
+
messages.map((message, index) => {
|
|
3004
|
+
const isUser = message.role === "user";
|
|
3005
|
+
if (isUser) {
|
|
3006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3007
|
+
"div",
|
|
3008
|
+
{
|
|
3009
|
+
className: "flex justify-end",
|
|
3010
|
+
"data-test": "ask-ai-user",
|
|
3011
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-fit max-w-[85%] whitespace-pre-wrap break-words rounded-2xl rounded-br-md bg-ph-brand px-3 py-2 text-sm leading-relaxed text-[var(--ph-on-accent)] [overflow-wrap:anywhere]", children: message.content })
|
|
3012
|
+
},
|
|
3013
|
+
`user-${index}`
|
|
3014
|
+
);
|
|
3015
|
+
}
|
|
3016
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3033
3017
|
"div",
|
|
3034
3018
|
{
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
role: "log",
|
|
3038
|
-
"aria-live": "polite",
|
|
3039
|
-
"aria-label": "Conversation",
|
|
3040
|
-
className: "suite-scroll-lock h-full space-y-5 overflow-y-auto px-4 py-5",
|
|
3019
|
+
className: "flex items-end gap-2",
|
|
3020
|
+
"data-test": "ask-ai-assistant",
|
|
3041
3021
|
children: [
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-4 font-display text-lg font-semibold text-ph-ink", children: "How can I help?" }),
|
|
3049
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1.5 text-sm leading-relaxed text-ph-subtle", children: emptyState }),
|
|
3050
|
-
presets.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "mt-5 flex w-full flex-col gap-2", children: presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
3051
|
-
"button",
|
|
3052
|
-
{
|
|
3053
|
-
type: "button",
|
|
3054
|
-
onClick: () => void ask(preset.prompt),
|
|
3055
|
-
disabled: loading || hydrating,
|
|
3056
|
-
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",
|
|
3057
|
-
children: [
|
|
3058
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.Sparks, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
3059
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "min-w-0 flex-1 truncate", children: preset.label }),
|
|
3060
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.ArrowUp, { className: "h-3.5 w-3.5 shrink-0 rotate-45 text-ph-mutedtext transition-transform group-hover:translate-x-0.5" })
|
|
3061
|
-
]
|
|
3062
|
-
},
|
|
3063
|
-
preset.label
|
|
3064
|
-
)) }) : null
|
|
3065
|
-
] }) : null,
|
|
3066
|
-
messages.map((message, index) => {
|
|
3067
|
-
const isUser = message.role === "user";
|
|
3068
|
-
if (isUser) {
|
|
3069
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3070
|
-
"div",
|
|
3071
|
-
{
|
|
3072
|
-
className: "flex justify-end",
|
|
3073
|
-
"data-test": "ask-ai-user",
|
|
3074
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("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 })
|
|
3075
|
-
},
|
|
3076
|
-
`user-${index}`
|
|
3077
|
-
);
|
|
3022
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3023
|
+
"span",
|
|
3024
|
+
{
|
|
3025
|
+
className: "mb-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand",
|
|
3026
|
+
"aria-hidden": true,
|
|
3027
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { className: "h-3.5 w-3.5" })
|
|
3078
3028
|
}
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
className: "flex gap-3",
|
|
3083
|
-
"data-test": "ask-ai-assistant",
|
|
3084
|
-
children: [
|
|
3085
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3086
|
-
"span",
|
|
3087
|
-
{
|
|
3088
|
-
className: "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand",
|
|
3089
|
-
"aria-hidden": true,
|
|
3090
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, { className: "h-4 w-4" })
|
|
3091
|
-
}
|
|
3092
|
-
),
|
|
3093
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
3094
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-sm leading-relaxed text-ph-ink", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3095
|
-
import_react10.Suspense,
|
|
3096
|
-
{
|
|
3097
|
-
fallback: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "whitespace-pre-wrap break-words", children: message.content }),
|
|
3098
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3099
|
-
SuiteAiBlockNoteMessage2,
|
|
3100
|
-
{
|
|
3101
|
-
markdown: message.content
|
|
3102
|
-
}
|
|
3103
|
-
)
|
|
3104
|
-
}
|
|
3105
|
-
) }),
|
|
3106
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
3107
|
-
"button",
|
|
3108
|
-
{
|
|
3109
|
-
type: "button",
|
|
3110
|
-
onClick: () => void copyMessage(index, message.content),
|
|
3111
|
-
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",
|
|
3112
|
-
children: [
|
|
3113
|
-
copiedId === index ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.Check, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.Copy, { className: "h-3 w-3" }),
|
|
3114
|
-
copiedId === index ? "Copied" : "Copy"
|
|
3115
|
-
]
|
|
3116
|
-
}
|
|
3117
|
-
)
|
|
3118
|
-
] })
|
|
3119
|
-
]
|
|
3120
|
-
},
|
|
3121
|
-
`assistant-${index}`
|
|
3122
|
-
);
|
|
3123
|
-
}),
|
|
3124
|
-
loading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-3", "aria-hidden": true, children: [
|
|
3125
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("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__ */ (0, import_jsx_runtime20.jsx)(Icon, { className: "h-4 w-4" }) }),
|
|
3126
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 py-1.5", children: [
|
|
3127
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce" }),
|
|
3128
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.15s]" }),
|
|
3129
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.3s]" })
|
|
3130
|
-
] })
|
|
3131
|
-
] }) : null,
|
|
3132
|
-
loading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "sr-only", "aria-live": "polite", children: "Assistant is responding\u2026" }) : null,
|
|
3133
|
-
error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
3134
|
-
"div",
|
|
3029
|
+
),
|
|
3030
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "min-w-0 max-w-[85%] rounded-2xl rounded-bl-md bg-ph-muted px-3 py-2 text-sm leading-relaxed text-ph-ink", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3031
|
+
import_react11.Suspense,
|
|
3135
3032
|
{
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
children: [
|
|
3139
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.WarningTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-ph-danger" }),
|
|
3140
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
3141
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "font-medium text-ph-danger", children: "Something went wrong" }),
|
|
3142
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-0.5 text-ph-subtle", children: error }),
|
|
3143
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3144
|
-
"button",
|
|
3145
|
-
{
|
|
3146
|
-
type: "button",
|
|
3147
|
-
onClick: retry,
|
|
3148
|
-
disabled: loading,
|
|
3149
|
-
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",
|
|
3150
|
-
children: "Try again"
|
|
3151
|
-
}
|
|
3152
|
-
)
|
|
3153
|
-
] })
|
|
3154
|
-
]
|
|
3033
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "whitespace-pre-wrap break-words", children: message.content }),
|
|
3034
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SuiteAiBlockNoteMessage2, { markdown: message.content })
|
|
3155
3035
|
}
|
|
3156
|
-
)
|
|
3036
|
+
) })
|
|
3157
3037
|
]
|
|
3158
|
-
}
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
}
|
|
3169
|
-
) : null
|
|
3170
|
-
] }),
|
|
3171
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "px-3 pb-[max(0.75rem,env(safe-area-inset-bottom))] pt-1", children: [
|
|
3172
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("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: [
|
|
3173
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("label", { htmlFor: "suite-ask-ai-input", className: "sr-only", children: "Ask a question" }),
|
|
3174
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3175
|
-
"textarea",
|
|
3176
|
-
{
|
|
3177
|
-
id: "suite-ask-ai-input",
|
|
3178
|
-
ref: textareaRef,
|
|
3179
|
-
value: prompt,
|
|
3180
|
-
onChange: (e) => setPrompt(e.target.value),
|
|
3181
|
-
onKeyDown: (e) => {
|
|
3182
|
-
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
3183
|
-
e.preventDefault();
|
|
3184
|
-
void ask(prompt);
|
|
3185
|
-
}
|
|
3186
|
-
},
|
|
3187
|
-
placeholder: "Ask anything\u2026",
|
|
3188
|
-
rows: 1,
|
|
3189
|
-
"data-test": "ask-ai-input",
|
|
3190
|
-
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"
|
|
3191
|
-
}
|
|
3192
|
-
),
|
|
3193
|
-
loading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3194
|
-
"button",
|
|
3195
|
-
{
|
|
3196
|
-
type: "button",
|
|
3197
|
-
onClick: stop,
|
|
3198
|
-
"data-test": "ask-ai-stop",
|
|
3199
|
-
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",
|
|
3200
|
-
"aria-label": "Stop generating",
|
|
3201
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.Square, { className: "h-3.5 w-3.5 fill-current" })
|
|
3202
|
-
}
|
|
3203
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3204
|
-
"button",
|
|
3205
|
-
{
|
|
3206
|
-
type: "button",
|
|
3207
|
-
onClick: () => void ask(prompt),
|
|
3208
|
-
disabled: !prompt.trim(),
|
|
3209
|
-
"data-test": "ask-ai-send",
|
|
3210
|
-
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",
|
|
3211
|
-
"aria-label": "Send message",
|
|
3212
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_iconoir_react8.ArrowUp, { className: "h-[18px] w-[18px]" })
|
|
3213
|
-
}
|
|
3214
|
-
)
|
|
3215
|
-
] }),
|
|
3216
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "mt-1.5 px-1 text-center text-xs text-ph-mutedtext", children: [
|
|
3217
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("kbd", { className: "font-mono", children: "Enter" }),
|
|
3218
|
-
" to send \xB7",
|
|
3219
|
-
" ",
|
|
3220
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("kbd", { className: "font-mono", children: "Shift" }),
|
|
3221
|
-
"+",
|
|
3222
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("kbd", { className: "font-mono", children: "Enter" }),
|
|
3223
|
-
" for a new line"
|
|
3038
|
+
},
|
|
3039
|
+
`assistant-${index}`
|
|
3040
|
+
);
|
|
3041
|
+
}),
|
|
3042
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-end gap-2", "aria-hidden": true, children: [
|
|
3043
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "mb-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { className: "h-3.5 w-3.5" }) }),
|
|
3044
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 rounded-2xl rounded-bl-md bg-ph-muted px-3 py-2.5", children: [
|
|
3045
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce" }),
|
|
3046
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.15s]" }),
|
|
3047
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.3s]" })
|
|
3224
3048
|
] })
|
|
3225
|
-
] })
|
|
3049
|
+
] }) : null,
|
|
3050
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "sr-only", "aria-live": "polite", children: "Assistant is responding\u2026" }) : null,
|
|
3051
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3052
|
+
"div",
|
|
3053
|
+
{
|
|
3054
|
+
role: "alert",
|
|
3055
|
+
className: "flex items-start gap-2 rounded-xl border border-ph-danger/30 bg-ph-danger/10 px-3 py-2.5 text-sm text-ph-ink",
|
|
3056
|
+
children: [
|
|
3057
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.WarningTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-ph-danger" }),
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
3059
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "font-medium text-ph-danger", children: "Something went wrong" }),
|
|
3060
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-0.5 text-ph-subtle", children: error }),
|
|
3061
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3062
|
+
"button",
|
|
3063
|
+
{
|
|
3064
|
+
type: "button",
|
|
3065
|
+
onClick: retry,
|
|
3066
|
+
disabled: loading,
|
|
3067
|
+
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",
|
|
3068
|
+
children: "Try again"
|
|
3069
|
+
}
|
|
3070
|
+
)
|
|
3071
|
+
] })
|
|
3072
|
+
]
|
|
3073
|
+
}
|
|
3074
|
+
) : null
|
|
3226
3075
|
]
|
|
3227
3076
|
}
|
|
3228
|
-
)
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3077
|
+
),
|
|
3078
|
+
!atBottom ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute bottom-3 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tooltip, { content: "Scroll to latest", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3079
|
+
"button",
|
|
3080
|
+
{
|
|
3081
|
+
type: "button",
|
|
3082
|
+
onClick: () => scrollToBottom("smooth"),
|
|
3083
|
+
className: "flex h-9 w-9 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",
|
|
3084
|
+
"aria-label": "Scroll to latest",
|
|
3085
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.ArrowDown, { className: "h-4 w-4" })
|
|
3086
|
+
}
|
|
3087
|
+
) }) }) : null
|
|
3088
|
+
] }),
|
|
3089
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-2 pt-2 pb-[max(2rem,calc(env(safe-area-inset-bottom)+1rem))]", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-end gap-1.5 rounded-2xl border border-ph-border bg-ph-surface px-1.5 py-1 transition-colors focus-within:border-ph-brand/45 focus-within:ring-2 focus-within:ring-ph-focus/35", children: [
|
|
3090
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Ask a question" }),
|
|
3091
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3092
|
+
"textarea",
|
|
3093
|
+
{
|
|
3094
|
+
id: inputId,
|
|
3095
|
+
ref: textareaRef,
|
|
3096
|
+
value: prompt,
|
|
3097
|
+
onChange: (event) => setPrompt(event.target.value),
|
|
3098
|
+
onKeyDown: (event) => {
|
|
3099
|
+
if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
|
|
3100
|
+
event.preventDefault();
|
|
3101
|
+
void ask(prompt);
|
|
3102
|
+
}
|
|
3103
|
+
},
|
|
3104
|
+
placeholder: "Ask anything\u2026",
|
|
3105
|
+
rows: 1,
|
|
3106
|
+
"data-test": "ask-ai-input",
|
|
3107
|
+
className: "max-h-36 min-h-10 flex-1 resize-none bg-transparent px-1.5 py-2 text-sm leading-relaxed text-ph-ink outline-none placeholder:text-ph-mutedtext"
|
|
3108
|
+
}
|
|
3109
|
+
),
|
|
3110
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3111
|
+
"button",
|
|
3112
|
+
{
|
|
3113
|
+
type: "button",
|
|
3114
|
+
onClick: stop,
|
|
3115
|
+
"data-test": "ask-ai-stop",
|
|
3116
|
+
className: "flex h-9 w-9 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",
|
|
3117
|
+
"aria-label": "Stop generating",
|
|
3118
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.Square, { className: "h-3.5 w-3.5 fill-current" })
|
|
3119
|
+
}
|
|
3120
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tooltip, { content: "Send message", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3121
|
+
"button",
|
|
3122
|
+
{
|
|
3123
|
+
type: "button",
|
|
3124
|
+
onClick: () => void ask(prompt),
|
|
3125
|
+
disabled: !prompt.trim(),
|
|
3126
|
+
"data-test": "ask-ai-send",
|
|
3127
|
+
className: "flex h-9 w-9 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",
|
|
3128
|
+
"aria-label": "Send message",
|
|
3129
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_iconoir_react8.ArrowUp, { className: "h-4 w-4" })
|
|
3130
|
+
}
|
|
3131
|
+
) })
|
|
3132
|
+
] }) })
|
|
3133
|
+
]
|
|
3134
|
+
}
|
|
3135
|
+
);
|
|
3136
|
+
}
|
|
3137
|
+
|
|
3138
|
+
// src/suite/components/workspace-switcher.tsx
|
|
3139
|
+
var import_react12 = require("react");
|
|
3140
|
+
var import_iconoir_react9 = require("iconoir-react");
|
|
3141
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3142
|
+
function SuiteWorkspaceSwitcher({
|
|
3143
|
+
workspaces = [],
|
|
3144
|
+
groups,
|
|
3145
|
+
currentId,
|
|
3146
|
+
onSelect,
|
|
3147
|
+
name,
|
|
3148
|
+
collapsed = false,
|
|
3149
|
+
emptyLabel = "No workspaces yet.",
|
|
3150
|
+
dropdownMenu: DropdownMenu2,
|
|
3151
|
+
dropdownItem: DropdownItem2,
|
|
3152
|
+
triggerId,
|
|
3153
|
+
triggerDataTest,
|
|
3154
|
+
footer
|
|
3155
|
+
}) {
|
|
3156
|
+
var _a;
|
|
3157
|
+
const [open, setOpen] = (0, import_react12.useState)(false);
|
|
3158
|
+
const sections = (_a = groups == null ? void 0 : groups.filter((group) => group.workspaces.length > 0)) != null ? _a : workspaces.length > 0 ? [{ id: "workspaces", label: "Switch workspace", workspaces }] : [];
|
|
3159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3160
|
+
DropdownMenu2,
|
|
3161
|
+
{
|
|
3162
|
+
"aria-label": "Switch workspace",
|
|
3163
|
+
triggerId: triggerId != null ? triggerId : "workspace-switcher-trigger",
|
|
3164
|
+
triggerDataTest: triggerDataTest != null ? triggerDataTest : "workspace-switcher-trigger",
|
|
3165
|
+
className: collapsed ? "w-11 shrink-0" : "w-full min-w-0 max-w-full [&_.ph-dropdown-trigger]:w-full",
|
|
3166
|
+
panelClassName: "w-64 max-w-full",
|
|
3167
|
+
align: "start",
|
|
3168
|
+
open,
|
|
3169
|
+
onOpenChange: setOpen,
|
|
3170
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3171
|
+
"span",
|
|
3172
|
+
{
|
|
3173
|
+
className: cn(
|
|
3174
|
+
"flex min-w-0 max-w-full items-center gap-2 rounded-lg border border-ph-border bg-ph-muted text-left transition-colors hover:bg-ph-muted",
|
|
3175
|
+
collapsed ? "h-10 w-10 justify-center p-0" : "w-full px-3 py-2",
|
|
3176
|
+
open && "border-ph-brand/40"
|
|
3177
|
+
),
|
|
3178
|
+
"data-test": "workspace-switcher-trigger",
|
|
3179
|
+
"aria-expanded": open,
|
|
3180
|
+
children: [
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_iconoir_react9.Building, { className: "h-4 w-4 shrink-0 text-ph-ink", "aria-hidden": true }),
|
|
3182
|
+
!collapsed ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3183
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-ph-ink", children: name }),
|
|
3184
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3185
|
+
import_iconoir_react9.NavArrowDown,
|
|
3186
|
+
{
|
|
3187
|
+
className: cn(
|
|
3188
|
+
"h-3.5 w-3.5 shrink-0 text-ph-mutedtext transition-transform",
|
|
3189
|
+
open && "rotate-180"
|
|
3190
|
+
),
|
|
3191
|
+
"aria-hidden": true
|
|
3192
|
+
}
|
|
3193
|
+
)
|
|
3194
|
+
] }) : null
|
|
3195
|
+
]
|
|
3196
|
+
}
|
|
3197
|
+
),
|
|
3198
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3199
|
+
"div",
|
|
3200
|
+
{
|
|
3201
|
+
id: "workspace-switcher-menu",
|
|
3202
|
+
className: "p-1",
|
|
3203
|
+
"data-test": "workspace-switcher-menu",
|
|
3204
|
+
children: [
|
|
3205
|
+
sections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "px-3 py-2 text-sm text-ph-mutedtext", children: emptyLabel }) : sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3206
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-ph-mutedtext", children: section.label }),
|
|
3207
|
+
section.workspaces.map((workspace) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3208
|
+
DropdownItem2,
|
|
3209
|
+
{
|
|
3210
|
+
id: `workspace-option-${workspace.id}`,
|
|
3211
|
+
role: "option",
|
|
3212
|
+
"aria-selected": workspace.id === currentId,
|
|
3213
|
+
"data-test": "workspace-option",
|
|
3214
|
+
"data-workspace-id": workspace.id,
|
|
3215
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
3216
|
+
onClick: () => {
|
|
3217
|
+
setOpen(false);
|
|
3218
|
+
onSelect(workspace);
|
|
3219
|
+
},
|
|
3220
|
+
className: appSwitcherMenuItemClass(),
|
|
3221
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "flex min-w-0 w-full items-center gap-3", children: [
|
|
3222
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
3223
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block truncate text-sm font-medium text-ph-ink", children: workspace.name }),
|
|
3224
|
+
workspace.description ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block truncate text-xs text-ph-mutedtext", children: workspace.description }) : null
|
|
3225
|
+
] }),
|
|
3226
|
+
workspace.id === currentId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3227
|
+
import_iconoir_react9.Check,
|
|
3228
|
+
{
|
|
3229
|
+
className: "h-4 w-4 shrink-0 text-ph-brand",
|
|
3230
|
+
"aria-hidden": "true"
|
|
3231
|
+
}
|
|
3232
|
+
) : null
|
|
3233
|
+
] })
|
|
3234
|
+
},
|
|
3235
|
+
workspace.id
|
|
3236
|
+
))
|
|
3237
|
+
] }, section.id)),
|
|
3238
|
+
footer ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mt-1 border-t border-ph-border pt-1", children: footer }) : null
|
|
3239
|
+
]
|
|
3240
|
+
}
|
|
3241
|
+
)
|
|
3242
|
+
}
|
|
3243
|
+
);
|
|
3233
3244
|
}
|
|
3234
3245
|
|
|
3235
3246
|
// src/suite/lib/use-sidebar-width.ts
|
|
3236
|
-
var
|
|
3247
|
+
var import_react13 = require("react");
|
|
3237
3248
|
var SIDEBAR_RAIL_WIDTH = 56;
|
|
3238
3249
|
var SIDEBAR_COLLAPSE_THRESHOLD = 80;
|
|
3239
3250
|
var SIDEBAR_MIN_EXPANDED_WIDTH = 180;
|
|
3240
|
-
var SIDEBAR_MAX_WIDTH =
|
|
3251
|
+
var SIDEBAR_MAX_WIDTH = 640;
|
|
3241
3252
|
var SIDEBAR_DEFAULT_WIDTH = 320;
|
|
3253
|
+
function sidebarColumnWidth(width, collapsed, _chatOpen = false) {
|
|
3254
|
+
if (collapsed) return SIDEBAR_RAIL_WIDTH;
|
|
3255
|
+
return width;
|
|
3256
|
+
}
|
|
3242
3257
|
function clampWidth(width) {
|
|
3243
3258
|
return Math.min(SIDEBAR_MAX_WIDTH, Math.max(SIDEBAR_RAIL_WIDTH, width));
|
|
3244
3259
|
}
|
|
@@ -3249,10 +3264,10 @@ function snapWidth(width) {
|
|
|
3249
3264
|
}
|
|
3250
3265
|
function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
|
|
3251
3266
|
const fallbackWidth = snapWidth(clampWidth(defaultWidth));
|
|
3252
|
-
const [width, setWidth] = (0,
|
|
3253
|
-
const [narrowViewport, setNarrowViewport] = (0,
|
|
3267
|
+
const [width, setWidth] = (0, import_react13.useState)(fallbackWidth);
|
|
3268
|
+
const [narrowViewport, setNarrowViewport] = (0, import_react13.useState)(false);
|
|
3254
3269
|
const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
|
|
3255
|
-
(0,
|
|
3270
|
+
(0, import_react13.useEffect)(() => {
|
|
3256
3271
|
let stored = null;
|
|
3257
3272
|
try {
|
|
3258
3273
|
stored = localStorage.getItem(storageKey);
|
|
@@ -3264,14 +3279,14 @@ function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
|
|
|
3264
3279
|
queueMicrotask(() => setWidth(snapWidth(clampWidth(parsed))));
|
|
3265
3280
|
}
|
|
3266
3281
|
}, [storageKey]);
|
|
3267
|
-
(0,
|
|
3282
|
+
(0, import_react13.useEffect)(() => {
|
|
3268
3283
|
const media = window.matchMedia("(max-width: 639px)");
|
|
3269
3284
|
const sync = () => setNarrowViewport(media.matches);
|
|
3270
3285
|
sync();
|
|
3271
3286
|
media.addEventListener("change", sync);
|
|
3272
3287
|
return () => media.removeEventListener("change", sync);
|
|
3273
3288
|
}, []);
|
|
3274
|
-
const persist = (0,
|
|
3289
|
+
const persist = (0, import_react13.useCallback)(
|
|
3275
3290
|
(value) => {
|
|
3276
3291
|
try {
|
|
3277
3292
|
localStorage.setItem(storageKey, String(value));
|
|
@@ -3280,7 +3295,7 @@ function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
|
|
|
3280
3295
|
},
|
|
3281
3296
|
[storageKey]
|
|
3282
3297
|
);
|
|
3283
|
-
const setCollapsed = (0,
|
|
3298
|
+
const setCollapsed = (0, import_react13.useCallback)(
|
|
3284
3299
|
(value) => {
|
|
3285
3300
|
setWidth((current) => {
|
|
3286
3301
|
const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? fallbackWidth : snapWidth(current);
|
|
@@ -3290,11 +3305,11 @@ function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
|
|
|
3290
3305
|
},
|
|
3291
3306
|
[fallbackWidth, persist]
|
|
3292
3307
|
);
|
|
3293
|
-
const resetWidth = (0,
|
|
3308
|
+
const resetWidth = (0, import_react13.useCallback)(() => {
|
|
3294
3309
|
setWidth(fallbackWidth);
|
|
3295
3310
|
persist(fallbackWidth);
|
|
3296
3311
|
}, [fallbackWidth, persist]);
|
|
3297
|
-
const startResize = (0,
|
|
3312
|
+
const startResize = (0, import_react13.useCallback)(
|
|
3298
3313
|
(event) => {
|
|
3299
3314
|
event.preventDefault();
|
|
3300
3315
|
const startX = event.clientX;
|
|
@@ -3316,7 +3331,7 @@ function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
|
|
|
3316
3331
|
},
|
|
3317
3332
|
[persist, width]
|
|
3318
3333
|
);
|
|
3319
|
-
const resizeBy = (0,
|
|
3334
|
+
const resizeBy = (0, import_react13.useCallback)(
|
|
3320
3335
|
(delta) => {
|
|
3321
3336
|
setWidth((current) => {
|
|
3322
3337
|
const next = clampWidth(current + delta);
|
|
@@ -3330,10 +3345,10 @@ function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
|
|
|
3330
3345
|
}
|
|
3331
3346
|
|
|
3332
3347
|
// src/suite/lib/motion.tsx
|
|
3333
|
-
var
|
|
3334
|
-
var
|
|
3348
|
+
var import_react14 = require("motion/react");
|
|
3349
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3335
3350
|
function SuiteMotionProvider({ children }) {
|
|
3336
|
-
return /* @__PURE__ */ (0,
|
|
3351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react14.LazyMotion, { features: import_react14.domAnimation, strict: true, children });
|
|
3337
3352
|
}
|
|
3338
3353
|
var SUITE_SPRINGS = {
|
|
3339
3354
|
/** Snappy panel/sheet entrances — small overshoot. */
|
|
@@ -3345,24 +3360,24 @@ var SUITE_SPRINGS = {
|
|
|
3345
3360
|
};
|
|
3346
3361
|
|
|
3347
3362
|
// src/suite/components/suite-skeleton.tsx
|
|
3348
|
-
var
|
|
3363
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3349
3364
|
function SuiteSkeleton({
|
|
3350
3365
|
className,
|
|
3351
3366
|
lines = 1,
|
|
3352
3367
|
circle,
|
|
3353
3368
|
width
|
|
3354
3369
|
}) {
|
|
3355
|
-
return /* @__PURE__ */ (0,
|
|
3370
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3356
3371
|
"div",
|
|
3357
3372
|
{
|
|
3358
3373
|
className: cn("space-y-2", circle ? "flex flex-col items-center" : ""),
|
|
3359
3374
|
"aria-hidden": true,
|
|
3360
|
-
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ (0,
|
|
3375
|
+
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3361
3376
|
"div",
|
|
3362
3377
|
{
|
|
3363
3378
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
3364
3379
|
style: { animationDelay: `${index * 80}ms` },
|
|
3365
|
-
children: /* @__PURE__ */ (0,
|
|
3380
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3366
3381
|
"div",
|
|
3367
3382
|
{
|
|
3368
3383
|
className: cn(
|
|
@@ -3386,7 +3401,7 @@ function SuiteSkeletonCard({
|
|
|
3386
3401
|
rows = 3,
|
|
3387
3402
|
header = true
|
|
3388
3403
|
}) {
|
|
3389
|
-
return /* @__PURE__ */ (0,
|
|
3404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3390
3405
|
"div",
|
|
3391
3406
|
{
|
|
3392
3407
|
className: cn(
|
|
@@ -3395,26 +3410,26 @@ function SuiteSkeletonCard({
|
|
|
3395
3410
|
),
|
|
3396
3411
|
"aria-hidden": true,
|
|
3397
3412
|
children: [
|
|
3398
|
-
header ? /* @__PURE__ */ (0,
|
|
3413
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3399
3414
|
"div",
|
|
3400
3415
|
{
|
|
3401
3416
|
className: "mb-5 flex items-center gap-3 animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
3402
3417
|
style: { animationDelay: "100ms" },
|
|
3403
3418
|
children: [
|
|
3404
|
-
/* @__PURE__ */ (0,
|
|
3405
|
-
/* @__PURE__ */ (0,
|
|
3406
|
-
/* @__PURE__ */ (0,
|
|
3407
|
-
/* @__PURE__ */ (0,
|
|
3419
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ph-skeleton h-10 w-10 rounded-xl" }),
|
|
3420
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 space-y-2", children: [
|
|
3421
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ph-skeleton h-4 w-1/3" }),
|
|
3422
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
3408
3423
|
] })
|
|
3409
3424
|
]
|
|
3410
3425
|
}
|
|
3411
3426
|
) : null,
|
|
3412
|
-
/* @__PURE__ */ (0,
|
|
3427
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-3", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3413
3428
|
"div",
|
|
3414
3429
|
{
|
|
3415
3430
|
className: "animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
3416
3431
|
style: { animationDelay: `${200 + index * 80}ms` },
|
|
3417
|
-
children: /* @__PURE__ */ (0,
|
|
3432
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3418
3433
|
"div",
|
|
3419
3434
|
{
|
|
3420
3435
|
className: "ph-skeleton h-3",
|
|
@@ -3432,16 +3447,16 @@ function SuiteSkeletonList({
|
|
|
3432
3447
|
className,
|
|
3433
3448
|
items = 4
|
|
3434
3449
|
}) {
|
|
3435
|
-
return /* @__PURE__ */ (0,
|
|
3450
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("space-y-3", className), "aria-hidden": true, children: Array.from({ length: items }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3436
3451
|
"div",
|
|
3437
3452
|
{
|
|
3438
3453
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
3439
3454
|
style: { animationDelay: `${index * 100}ms` },
|
|
3440
|
-
children: /* @__PURE__ */ (0,
|
|
3441
|
-
/* @__PURE__ */ (0,
|
|
3442
|
-
/* @__PURE__ */ (0,
|
|
3443
|
-
/* @__PURE__ */ (0,
|
|
3444
|
-
/* @__PURE__ */ (0,
|
|
3455
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-3 rounded-xl border border-ph-border bg-ph-surface p-4", children: [
|
|
3456
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ph-skeleton h-10 w-10 rounded-lg" }),
|
|
3457
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
3458
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ph-skeleton h-3.5 w-3/4" }),
|
|
3459
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
3445
3460
|
] })
|
|
3446
3461
|
] })
|
|
3447
3462
|
},
|
|
@@ -3456,7 +3471,7 @@ function SuiteEmptyState({
|
|
|
3456
3471
|
className,
|
|
3457
3472
|
size = "md"
|
|
3458
3473
|
}) {
|
|
3459
|
-
return /* @__PURE__ */ (0,
|
|
3474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3460
3475
|
"div",
|
|
3461
3476
|
{
|
|
3462
3477
|
className: cn(
|
|
@@ -3465,13 +3480,13 @@ function SuiteEmptyState({
|
|
|
3465
3480
|
className
|
|
3466
3481
|
),
|
|
3467
3482
|
children: [
|
|
3468
|
-
/* @__PURE__ */ (0,
|
|
3469
|
-
/* @__PURE__ */ (0,
|
|
3470
|
-
/* @__PURE__ */ (0,
|
|
3483
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "pointer-events-none absolute inset-0 overflow-hidden opacity-60", "aria-hidden": true, children: [
|
|
3484
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute -left-10 -top-10 h-40 w-40 rounded-full bg-ph-brand/10 blur-3xl" }),
|
|
3485
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute -bottom-10 -right-10 h-40 w-40 rounded-full bg-ph-accent/10 blur-3xl" })
|
|
3471
3486
|
] }),
|
|
3472
|
-
/* @__PURE__ */ (0,
|
|
3473
|
-
icon ? /* @__PURE__ */ (0,
|
|
3474
|
-
/* @__PURE__ */ (0,
|
|
3487
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative", children: [
|
|
3488
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mx-auto mb-4 inline-flex items-center justify-center rounded-2xl bg-ph-muted p-3 shadow-sm ring-1 ring-black/[0.06]", children: icon }) : null,
|
|
3489
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3475
3490
|
"h3",
|
|
3476
3491
|
{
|
|
3477
3492
|
className: cn(
|
|
@@ -3481,8 +3496,8 @@ function SuiteEmptyState({
|
|
|
3481
3496
|
children: title
|
|
3482
3497
|
}
|
|
3483
3498
|
),
|
|
3484
|
-
description ? /* @__PURE__ */ (0,
|
|
3485
|
-
action ? /* @__PURE__ */ (0,
|
|
3499
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mx-auto mt-2 max-w-sm text-sm leading-relaxed text-ph-subtle", children: description }) : null,
|
|
3500
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-5 flex flex-wrap items-center justify-center gap-2", children: action }) : null
|
|
3486
3501
|
] })
|
|
3487
3502
|
]
|
|
3488
3503
|
}
|
|
@@ -3490,8 +3505,8 @@ function SuiteEmptyState({
|
|
|
3490
3505
|
}
|
|
3491
3506
|
|
|
3492
3507
|
// src/suite/components/suite-settings-mobile-nav.tsx
|
|
3493
|
-
var
|
|
3494
|
-
var
|
|
3508
|
+
var import_react15 = require("react");
|
|
3509
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3495
3510
|
function SuiteSettingsMobileNav({
|
|
3496
3511
|
items,
|
|
3497
3512
|
activeHref,
|
|
@@ -3500,16 +3515,16 @@ function SuiteSettingsMobileNav({
|
|
|
3500
3515
|
ariaLabel = "Settings sections",
|
|
3501
3516
|
className
|
|
3502
3517
|
}) {
|
|
3503
|
-
return /* @__PURE__ */ (0,
|
|
3518
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3504
3519
|
"nav",
|
|
3505
3520
|
{
|
|
3506
3521
|
"data-test": dataTest,
|
|
3507
3522
|
"aria-label": ariaLabel,
|
|
3508
3523
|
className: cn("suite-settings-mobile-nav lg:hidden", className),
|
|
3509
|
-
children: /* @__PURE__ */ (0,
|
|
3524
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex snap-x gap-2 overflow-x-auto pb-3 pt-1 scrollbar-hide [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: items.map((item) => {
|
|
3510
3525
|
const Icon = item.icon;
|
|
3511
3526
|
const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
|
|
3512
|
-
const iconNode = (0,
|
|
3527
|
+
const iconNode = (0, import_react15.isValidElement)(item.icon) ? item.icon : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3513
3528
|
Icon,
|
|
3514
3529
|
{
|
|
3515
3530
|
className: cn(
|
|
@@ -3519,7 +3534,7 @@ function SuiteSettingsMobileNav({
|
|
|
3519
3534
|
"aria-hidden": true
|
|
3520
3535
|
}
|
|
3521
3536
|
);
|
|
3522
|
-
return /* @__PURE__ */ (0,
|
|
3537
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3523
3538
|
"button",
|
|
3524
3539
|
{
|
|
3525
3540
|
type: "button",
|
|
@@ -3534,8 +3549,8 @@ function SuiteSettingsMobileNav({
|
|
|
3534
3549
|
),
|
|
3535
3550
|
children: [
|
|
3536
3551
|
iconNode,
|
|
3537
|
-
/* @__PURE__ */ (0,
|
|
3538
|
-
active ? /* @__PURE__ */ (0,
|
|
3552
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "whitespace-nowrap", children: item.label }),
|
|
3553
|
+
active ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "absolute inset-x-0 -bottom-3 h-0.5 rounded-full bg-ph-ink lg:hidden" }) : null
|
|
3539
3554
|
]
|
|
3540
3555
|
},
|
|
3541
3556
|
item.href
|
|
@@ -3547,144 +3562,9 @@ function SuiteSettingsMobileNav({
|
|
|
3547
3562
|
|
|
3548
3563
|
// src/suite/components/suite-sidebar.tsx
|
|
3549
3564
|
var import_link2 = __toESM(require("next/link"));
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
var
|
|
3553
|
-
var import_react_dom = require("react-dom");
|
|
3554
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3555
|
-
var TooltipDelayContext = (0, import_react14.createContext)(0);
|
|
3556
|
-
function tooltipPosition(trigger, side, align, offset) {
|
|
3557
|
-
const horizontal = align === "start" ? trigger.left : align === "end" ? trigger.right : trigger.left + trigger.width / 2;
|
|
3558
|
-
const vertical = align === "start" ? trigger.top : align === "end" ? trigger.bottom : trigger.top + trigger.height / 2;
|
|
3559
|
-
if (side === "top")
|
|
3560
|
-
return {
|
|
3561
|
-
left: horizontal,
|
|
3562
|
-
top: trigger.top - offset,
|
|
3563
|
-
transform: "translate(-50%, -100%)"
|
|
3564
|
-
};
|
|
3565
|
-
if (side === "bottom")
|
|
3566
|
-
return {
|
|
3567
|
-
left: horizontal,
|
|
3568
|
-
top: trigger.bottom + offset,
|
|
3569
|
-
transform: "translate(-50%, 0)"
|
|
3570
|
-
};
|
|
3571
|
-
if (side === "left")
|
|
3572
|
-
return {
|
|
3573
|
-
left: trigger.left - offset,
|
|
3574
|
-
top: vertical,
|
|
3575
|
-
transform: "translate(-100%, -50%)"
|
|
3576
|
-
};
|
|
3577
|
-
return {
|
|
3578
|
-
left: trigger.right + offset,
|
|
3579
|
-
top: vertical,
|
|
3580
|
-
transform: "translate(0, -50%)"
|
|
3581
|
-
};
|
|
3582
|
-
}
|
|
3583
|
-
function Tooltip({
|
|
3584
|
-
content,
|
|
3585
|
-
children,
|
|
3586
|
-
side = "top",
|
|
3587
|
-
align = "center",
|
|
3588
|
-
sideOffset = 7,
|
|
3589
|
-
className,
|
|
3590
|
-
open,
|
|
3591
|
-
defaultOpen = false,
|
|
3592
|
-
onOpenChange,
|
|
3593
|
-
delayDuration
|
|
3594
|
-
}) {
|
|
3595
|
-
const providerDelay = (0, import_react14.useContext)(TooltipDelayContext);
|
|
3596
|
-
const generatedId = (0, import_react14.useId)().replace(/:/g, "");
|
|
3597
|
-
const triggerRef = (0, import_react14.useRef)(null);
|
|
3598
|
-
const timerRef = (0, import_react14.useRef)(null);
|
|
3599
|
-
const [internalOpen, setInternalOpen] = (0, import_react14.useState)(defaultOpen);
|
|
3600
|
-
const [position, setPosition] = (0, import_react14.useState)(null);
|
|
3601
|
-
const isOpen = open != null ? open : internalOpen;
|
|
3602
|
-
const triggerId = children.props.id;
|
|
3603
|
-
const tooltipId = triggerId ? `${triggerId}-tooltip` : `ph-tooltip-${generatedId}`;
|
|
3604
|
-
function setOpen(next) {
|
|
3605
|
-
if (open === void 0) setInternalOpen(next);
|
|
3606
|
-
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
3607
|
-
}
|
|
3608
|
-
function clearTimer() {
|
|
3609
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
3610
|
-
timerRef.current = null;
|
|
3611
|
-
}
|
|
3612
|
-
function updatePosition() {
|
|
3613
|
-
if (!triggerRef.current) return;
|
|
3614
|
-
setPosition(
|
|
3615
|
-
tooltipPosition(
|
|
3616
|
-
triggerRef.current.getBoundingClientRect(),
|
|
3617
|
-
side,
|
|
3618
|
-
align,
|
|
3619
|
-
sideOffset
|
|
3620
|
-
)
|
|
3621
|
-
);
|
|
3622
|
-
}
|
|
3623
|
-
function show(immediate) {
|
|
3624
|
-
clearTimer();
|
|
3625
|
-
updatePosition();
|
|
3626
|
-
const delay = immediate ? 0 : delayDuration != null ? delayDuration : providerDelay;
|
|
3627
|
-
if (!delay) setOpen(true);
|
|
3628
|
-
else timerRef.current = setTimeout(() => setOpen(true), delay);
|
|
3629
|
-
}
|
|
3630
|
-
function hide() {
|
|
3631
|
-
clearTimer();
|
|
3632
|
-
setOpen(false);
|
|
3633
|
-
}
|
|
3634
|
-
(0, import_react14.useEffect)(() => {
|
|
3635
|
-
if (!isOpen) return;
|
|
3636
|
-
const reposition = () => updatePosition();
|
|
3637
|
-
window.addEventListener("resize", reposition);
|
|
3638
|
-
window.addEventListener("scroll", reposition, true);
|
|
3639
|
-
return () => {
|
|
3640
|
-
window.removeEventListener("resize", reposition);
|
|
3641
|
-
window.removeEventListener("scroll", reposition, true);
|
|
3642
|
-
};
|
|
3643
|
-
});
|
|
3644
|
-
(0, import_react14.useEffect)(() => () => clearTimer(), []);
|
|
3645
|
-
const describedBy = [children.props["aria-describedby"], tooltipId].filter(Boolean).join(" ");
|
|
3646
|
-
const trigger = (0, import_react14.cloneElement)(children, { "aria-describedby": describedBy });
|
|
3647
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
3648
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3649
|
-
"span",
|
|
3650
|
-
{
|
|
3651
|
-
ref: triggerRef,
|
|
3652
|
-
className: "inline-flex",
|
|
3653
|
-
onMouseEnter: () => show(false),
|
|
3654
|
-
onMouseLeave: hide,
|
|
3655
|
-
onFocusCapture: () => show(true),
|
|
3656
|
-
onBlurCapture: hide,
|
|
3657
|
-
onKeyDown: (event) => {
|
|
3658
|
-
if (event.key === "Escape") hide();
|
|
3659
|
-
},
|
|
3660
|
-
children: trigger
|
|
3661
|
-
}
|
|
3662
|
-
),
|
|
3663
|
-
isOpen && position && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
|
|
3664
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3665
|
-
"span",
|
|
3666
|
-
{
|
|
3667
|
-
style: __spreadValues({ position: "fixed" }, position),
|
|
3668
|
-
className: "pointer-events-none z-[200]",
|
|
3669
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3670
|
-
"span",
|
|
3671
|
-
{
|
|
3672
|
-
id: tooltipId,
|
|
3673
|
-
role: "tooltip",
|
|
3674
|
-
"data-side": side,
|
|
3675
|
-
className: cn2("ph-tooltip-content", className),
|
|
3676
|
-
children: content
|
|
3677
|
-
}
|
|
3678
|
-
)
|
|
3679
|
-
}
|
|
3680
|
-
),
|
|
3681
|
-
document.body
|
|
3682
|
-
) : null
|
|
3683
|
-
] });
|
|
3684
|
-
}
|
|
3685
|
-
|
|
3686
|
-
// src/suite/components/suite-sidebar.tsx
|
|
3687
|
-
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3565
|
+
var import_react16 = require("react");
|
|
3566
|
+
var import_iconoir_react10 = require("iconoir-react");
|
|
3567
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
3688
3568
|
function renderNode(node, collapsed) {
|
|
3689
3569
|
if (typeof node === "function") return node(collapsed);
|
|
3690
3570
|
return node;
|
|
@@ -3699,9 +3579,94 @@ function SuiteSidebar({
|
|
|
3699
3579
|
footerExtras,
|
|
3700
3580
|
collapsed = false,
|
|
3701
3581
|
className,
|
|
3702
|
-
surface = false
|
|
3582
|
+
surface = false,
|
|
3583
|
+
askAiOpen = false,
|
|
3584
|
+
onAskAiOpenChange,
|
|
3585
|
+
askAi,
|
|
3586
|
+
onRequestExpand
|
|
3703
3587
|
}) {
|
|
3704
|
-
|
|
3588
|
+
const showAskAi = Boolean(onAskAiOpenChange && askAi);
|
|
3589
|
+
const chatOpen = showAskAi && askAiOpen && !collapsed;
|
|
3590
|
+
(0, import_react16.useEffect)(() => {
|
|
3591
|
+
if (!onAskAiOpenChange) return;
|
|
3592
|
+
function onOpen() {
|
|
3593
|
+
onRequestExpand == null ? void 0 : onRequestExpand();
|
|
3594
|
+
onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(true);
|
|
3595
|
+
}
|
|
3596
|
+
window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
3597
|
+
return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
3598
|
+
}, [onAskAiOpenChange, onRequestExpand]);
|
|
3599
|
+
(0, import_react16.useEffect)(() => {
|
|
3600
|
+
if (!chatOpen) return;
|
|
3601
|
+
function onKey(event) {
|
|
3602
|
+
if (event.key === "Escape") onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(false);
|
|
3603
|
+
}
|
|
3604
|
+
window.addEventListener("keydown", onKey);
|
|
3605
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
3606
|
+
}, [chatOpen, onAskAiOpenChange]);
|
|
3607
|
+
function toggleAskAi() {
|
|
3608
|
+
if (askAiOpen) {
|
|
3609
|
+
onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(false);
|
|
3610
|
+
return;
|
|
3611
|
+
}
|
|
3612
|
+
if (collapsed) onRequestExpand == null ? void 0 : onRequestExpand();
|
|
3613
|
+
onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(true);
|
|
3614
|
+
}
|
|
3615
|
+
const askAiButton = /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3616
|
+
"button",
|
|
3617
|
+
{
|
|
3618
|
+
type: "button",
|
|
3619
|
+
"data-test": "suite-ask-ai-toggle",
|
|
3620
|
+
"aria-pressed": askAiOpen,
|
|
3621
|
+
"aria-label": askAiOpen ? "Back to navigation" : "Shelly AI",
|
|
3622
|
+
onClick: toggleAskAi,
|
|
3623
|
+
className: cn(
|
|
3624
|
+
"inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-lg transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ph-focus-ring",
|
|
3625
|
+
askAiOpen ? "bg-ph-brand/10 text-ph-brand" : "text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink"
|
|
3626
|
+
),
|
|
3627
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_iconoir_react10.Sparks, { className: "h-4 w-4", "aria-hidden": true })
|
|
3628
|
+
}
|
|
3629
|
+
);
|
|
3630
|
+
if (chatOpen) {
|
|
3631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3632
|
+
"div",
|
|
3633
|
+
{
|
|
3634
|
+
"data-suite-chat-open": "",
|
|
3635
|
+
className: cn(
|
|
3636
|
+
"flex h-full w-full min-w-0 flex-col text-ph-ink",
|
|
3637
|
+
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3638
|
+
className
|
|
3639
|
+
),
|
|
3640
|
+
children: [
|
|
3641
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3642
|
+
"div",
|
|
3643
|
+
{
|
|
3644
|
+
className: cn(
|
|
3645
|
+
"flex h-14 shrink-0 items-center gap-1 border-b border-ph-border px-2",
|
|
3646
|
+
surface ? "bg-ph-surface" : "bg-ph-canvas"
|
|
3647
|
+
),
|
|
3648
|
+
children: [
|
|
3649
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Tooltip, { content: "Back to navigation", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3650
|
+
"button",
|
|
3651
|
+
{
|
|
3652
|
+
type: "button",
|
|
3653
|
+
"data-test": "suite-ask-ai-back",
|
|
3654
|
+
"aria-label": "Back to navigation",
|
|
3655
|
+
onClick: () => onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(false),
|
|
3656
|
+
className: "inline-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-brand",
|
|
3657
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_iconoir_react10.NavArrowLeft, { className: "h-4 w-4", "aria-hidden": true })
|
|
3658
|
+
}
|
|
3659
|
+
) }),
|
|
3660
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-ph-ink", children: "Shelly AI" })
|
|
3661
|
+
]
|
|
3662
|
+
}
|
|
3663
|
+
),
|
|
3664
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "min-h-0 flex-1", children: askAi })
|
|
3665
|
+
]
|
|
3666
|
+
}
|
|
3667
|
+
);
|
|
3668
|
+
}
|
|
3669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3705
3670
|
"div",
|
|
3706
3671
|
{
|
|
3707
3672
|
className: cn(
|
|
@@ -3710,7 +3675,7 @@ function SuiteSidebar({
|
|
|
3710
3675
|
className
|
|
3711
3676
|
),
|
|
3712
3677
|
children: [
|
|
3713
|
-
/* @__PURE__ */ (0,
|
|
3678
|
+
appSwitcher || notificationBell ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3714
3679
|
"div",
|
|
3715
3680
|
{
|
|
3716
3681
|
className: cn(
|
|
@@ -3719,27 +3684,46 @@ function SuiteSidebar({
|
|
|
3719
3684
|
collapsed ? "flex-col items-center gap-1 px-1 py-2" : "h-14 items-center justify-between gap-2 px-3"
|
|
3720
3685
|
),
|
|
3721
3686
|
children: [
|
|
3722
|
-
/* @__PURE__ */ (0,
|
|
3723
|
-
collapsed ? null : /* @__PURE__ */ (0,
|
|
3687
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn("min-w-0", collapsed ? "shrink-0" : "flex-1"), children: renderNode(appSwitcher, collapsed) }),
|
|
3688
|
+
collapsed ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "shrink-0", children: renderNode(notificationBell, collapsed) })
|
|
3724
3689
|
]
|
|
3725
3690
|
}
|
|
3726
|
-
),
|
|
3727
|
-
/* @__PURE__ */ (0,
|
|
3691
|
+
) : null,
|
|
3692
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3728
3693
|
"div",
|
|
3729
3694
|
{
|
|
3730
3695
|
className: cn(
|
|
3731
|
-
"flex min-h-0 flex-1 flex-col
|
|
3696
|
+
"flex min-h-0 flex-1 flex-col",
|
|
3732
3697
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3698
|
+
chatOpen ? "min-h-0" : "overflow-y-auto",
|
|
3733
3699
|
collapsed ? "px-1.5 py-2" : "p-2"
|
|
3734
3700
|
),
|
|
3735
3701
|
children: [
|
|
3736
|
-
/* @__PURE__ */ (0,
|
|
3737
|
-
|
|
3738
|
-
/* @__PURE__ */ (0,
|
|
3702
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn("mb-3 w-full shrink-0", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
|
|
3703
|
+
chatOpen ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
3704
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mb-2 flex shrink-0 items-center gap-1", children: [
|
|
3705
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3706
|
+
"button",
|
|
3707
|
+
{
|
|
3708
|
+
type: "button",
|
|
3709
|
+
"data-test": "suite-ask-ai-back",
|
|
3710
|
+
onClick: () => onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(false),
|
|
3711
|
+
className: "inline-flex h-9 items-center gap-1 rounded-lg px-2 text-sm 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-brand",
|
|
3712
|
+
children: [
|
|
3713
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_iconoir_react10.NavArrowLeft, { className: "h-4 w-4", "aria-hidden": true }),
|
|
3714
|
+
"Nav"
|
|
3715
|
+
]
|
|
3716
|
+
}
|
|
3717
|
+
),
|
|
3718
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "truncate text-sm font-semibold text-ph-ink", children: "Shelly AI" })
|
|
3719
|
+
] }),
|
|
3720
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "min-h-0 flex-1", children: askAi })
|
|
3721
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
3722
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("nav", { "aria-label": "Pages", className: "shrink-0 space-y-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "space-y-0.5", children: navItems.map((item) => {
|
|
3739
3723
|
var _a;
|
|
3740
3724
|
const Icon = item.icon;
|
|
3741
3725
|
const active = Boolean(item.active);
|
|
3742
|
-
const link = /* @__PURE__ */ (0,
|
|
3726
|
+
const link = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3743
3727
|
import_link2.default,
|
|
3744
3728
|
{
|
|
3745
3729
|
href: item.href,
|
|
@@ -3753,7 +3737,7 @@ function SuiteSidebar({
|
|
|
3753
3737
|
collapsed ? "mx-auto size-11 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
3754
3738
|
),
|
|
3755
3739
|
children: [
|
|
3756
|
-
/* @__PURE__ */ (0,
|
|
3740
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3757
3741
|
"span",
|
|
3758
3742
|
{
|
|
3759
3743
|
className: cn(
|
|
@@ -3761,7 +3745,7 @@ function SuiteSidebar({
|
|
|
3761
3745
|
item.iconClassName
|
|
3762
3746
|
),
|
|
3763
3747
|
"aria-hidden": true,
|
|
3764
|
-
children: /* @__PURE__ */ (0,
|
|
3748
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3765
3749
|
Icon,
|
|
3766
3750
|
{
|
|
3767
3751
|
className: "h-full w-full",
|
|
@@ -3770,7 +3754,7 @@ function SuiteSidebar({
|
|
|
3770
3754
|
)
|
|
3771
3755
|
}
|
|
3772
3756
|
),
|
|
3773
|
-
/* @__PURE__ */ (0,
|
|
3757
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3774
3758
|
"span",
|
|
3775
3759
|
{
|
|
3776
3760
|
className: cn(
|
|
@@ -3781,26 +3765,26 @@ function SuiteSidebar({
|
|
|
3781
3765
|
children: item.label
|
|
3782
3766
|
}
|
|
3783
3767
|
),
|
|
3784
|
-
!collapsed && item.badge ? /* @__PURE__ */ (0,
|
|
3768
|
+
!collapsed && item.badge ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "relative ml-auto shrink-0", children: item.badge }) : null
|
|
3785
3769
|
]
|
|
3786
3770
|
},
|
|
3787
3771
|
item.label
|
|
3788
3772
|
);
|
|
3789
|
-
return collapsed ? /* @__PURE__ */ (0,
|
|
3790
|
-
}) })
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
)
|
|
3773
|
+
return collapsed ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Tooltip, { content: item.label, side: "right", children: link }, item.label) : link;
|
|
3774
|
+
}) }) }),
|
|
3775
|
+
secondaryNav ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3776
|
+
"div",
|
|
3777
|
+
{
|
|
3778
|
+
className: "min-h-0 flex-1",
|
|
3779
|
+
"data-test": "suite-sidebar-secondary-nav",
|
|
3780
|
+
children: secondaryNav
|
|
3781
|
+
}
|
|
3782
|
+
) : null
|
|
3783
|
+
] })
|
|
3800
3784
|
]
|
|
3801
3785
|
}
|
|
3802
3786
|
),
|
|
3803
|
-
/* @__PURE__ */ (0,
|
|
3787
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3804
3788
|
"div",
|
|
3805
3789
|
{
|
|
3806
3790
|
className: cn(
|
|
@@ -3808,16 +3792,23 @@ function SuiteSidebar({
|
|
|
3808
3792
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3809
3793
|
collapsed ? "p-1.5" : "p-3"
|
|
3810
3794
|
),
|
|
3811
|
-
children: /* @__PURE__ */ (0,
|
|
3795
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3812
3796
|
"div",
|
|
3813
3797
|
{
|
|
3814
3798
|
className: cn(
|
|
3815
3799
|
"flex items-center gap-2",
|
|
3816
|
-
collapsed ? "flex-col items-center justify-center [
|
|
3800
|
+
collapsed ? "flex-col items-center justify-center [&>div]:w-auto" : "w-full min-w-0"
|
|
3817
3801
|
),
|
|
3818
3802
|
children: [
|
|
3819
3803
|
renderNode(userMenu, collapsed),
|
|
3820
|
-
|
|
3804
|
+
showAskAi ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3805
|
+
"div",
|
|
3806
|
+
{
|
|
3807
|
+
className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"),
|
|
3808
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Tooltip, { content: "Shelly AI", side: collapsed ? "right" : "top", children: askAiButton })
|
|
3809
|
+
}
|
|
3810
|
+
) : footerExtras ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"), children: renderNode(footerExtras, collapsed) }) : null,
|
|
3811
|
+
showAskAi && footerExtras ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn("shrink-0", collapsed && "mt-2"), children: renderNode(footerExtras, collapsed) }) : null
|
|
3821
3812
|
]
|
|
3822
3813
|
}
|
|
3823
3814
|
)
|
|
@@ -3829,7 +3820,7 @@ function SuiteSidebar({
|
|
|
3829
3820
|
}
|
|
3830
3821
|
|
|
3831
3822
|
// src/suite/components/suite-app-layout.tsx
|
|
3832
|
-
var
|
|
3823
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3833
3824
|
function SuiteAppLayout({
|
|
3834
3825
|
sidebar,
|
|
3835
3826
|
children,
|
|
@@ -3843,7 +3834,7 @@ function SuiteAppLayout({
|
|
|
3843
3834
|
onResetWidth,
|
|
3844
3835
|
className
|
|
3845
3836
|
}) {
|
|
3846
|
-
return /* @__PURE__ */ (0,
|
|
3837
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3847
3838
|
"div",
|
|
3848
3839
|
{
|
|
3849
3840
|
"data-test": "app-shell",
|
|
@@ -3852,15 +3843,15 @@ function SuiteAppLayout({
|
|
|
3852
3843
|
className
|
|
3853
3844
|
),
|
|
3854
3845
|
children: [
|
|
3855
|
-
/* @__PURE__ */ (0,
|
|
3846
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3856
3847
|
"aside",
|
|
3857
3848
|
{
|
|
3858
3849
|
className: "relative hidden shrink-0 flex-col overflow-visible border-r border-ph-border ease-out lg:flex",
|
|
3859
3850
|
style: { width: `${sidebarWidth}px` },
|
|
3860
3851
|
"data-collapsed": collapsed ? "true" : "false",
|
|
3861
3852
|
children: [
|
|
3862
|
-
sidebar,
|
|
3863
|
-
onStartResize ? /* @__PURE__ */ (0,
|
|
3853
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "relative z-0 h-full min-h-0 isolate", children: sidebar }),
|
|
3854
|
+
onStartResize ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3864
3855
|
"div",
|
|
3865
3856
|
{
|
|
3866
3857
|
role: "separator",
|
|
@@ -3882,15 +3873,15 @@ function SuiteAppLayout({
|
|
|
3882
3873
|
onResizeBy == null ? void 0 : onResizeBy(16);
|
|
3883
3874
|
}
|
|
3884
3875
|
},
|
|
3885
|
-
className: "absolute inset-y-0
|
|
3876
|
+
className: "absolute inset-y-0 right-0 z-20 w-2 cursor-col-resize touch-none transition-colors hover:bg-[color-mix(in_oklab,var(--ph-accent)_30%,transparent)]"
|
|
3886
3877
|
}
|
|
3887
3878
|
) : null
|
|
3888
3879
|
]
|
|
3889
3880
|
}
|
|
3890
3881
|
),
|
|
3891
|
-
/* @__PURE__ */ (0,
|
|
3892
|
-
mobileHeader ? /* @__PURE__ */ (0,
|
|
3893
|
-
/* @__PURE__ */ (0,
|
|
3882
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
|
|
3883
|
+
mobileHeader ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "shrink-0 lg:hidden", children: mobileHeader }) : null,
|
|
3884
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3894
3885
|
"main",
|
|
3895
3886
|
{
|
|
3896
3887
|
id: "main-content",
|
|
@@ -3904,7 +3895,7 @@ function SuiteAppLayout({
|
|
|
3904
3895
|
children
|
|
3905
3896
|
}
|
|
3906
3897
|
),
|
|
3907
|
-
bottomNav ? /* @__PURE__ */ (0,
|
|
3898
|
+
bottomNav ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "shrink-0 lg:hidden", children: bottomNav }) : null
|
|
3908
3899
|
] })
|
|
3909
3900
|
]
|
|
3910
3901
|
}
|
|
@@ -3958,6 +3949,7 @@ function SuiteAppLayout({
|
|
|
3958
3949
|
SuiteThemeProvider,
|
|
3959
3950
|
SuiteToolbar,
|
|
3960
3951
|
SuiteUserMenu,
|
|
3952
|
+
SuiteWorkspaceSwitcher,
|
|
3961
3953
|
TodayAskAiCard,
|
|
3962
3954
|
TodayCalibrating,
|
|
3963
3955
|
TodayEmptyAction,
|
|
@@ -3973,11 +3965,14 @@ function SuiteAppLayout({
|
|
|
3973
3965
|
appSwitcherMarkClass,
|
|
3974
3966
|
appSwitcherMenuItemClass,
|
|
3975
3967
|
appSwitcherTriggerClass,
|
|
3968
|
+
classifySuiteHref,
|
|
3976
3969
|
cn,
|
|
3970
|
+
consumePendingAskAiPrompt,
|
|
3977
3971
|
getTodayGreeting,
|
|
3978
3972
|
m,
|
|
3979
3973
|
openSuiteAskAi,
|
|
3980
3974
|
resolveSuiteNotificationHref,
|
|
3975
|
+
sidebarColumnWidth,
|
|
3981
3976
|
sourceToSuiteApp,
|
|
3982
3977
|
suiteAppBaseUrl,
|
|
3983
3978
|
suiteAppLabel,
|