@melony/react 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/index.cjs +460 -401
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -46
- package/dist/index.d.ts +47 -46
- package/dist/index.js +456 -399
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as React11 from 'react';
|
|
2
|
-
import React11__default, { createContext, useState,
|
|
2
|
+
import React11__default, { createContext, useState, useContext, useCallback, useMemo, useEffect, useRef } from 'react';
|
|
3
3
|
import { NuqsAdapter } from 'nuqs/adapters/react';
|
|
4
4
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import { generateId } from 'melony/client';
|
|
7
|
-
import { useQueryState, parseAsString } from 'nuqs';
|
|
8
|
-
import { clsx } from 'clsx';
|
|
9
|
-
import { twMerge } from 'tailwind-merge';
|
|
10
6
|
import { Button as Button$1 } from '@base-ui/react/button';
|
|
11
7
|
import { cva } from 'class-variance-authority';
|
|
8
|
+
import { clsx } from 'clsx';
|
|
9
|
+
import { twMerge } from 'tailwind-merge';
|
|
10
|
+
import * as ICONS from '@tabler/icons-react';
|
|
11
|
+
import { IconBrandGoogle, IconFileText, IconFile, IconX, IconPaperclip, IconChevronDown, IconLoader2, IconArrowUp, IconMessage, IconDotsVertical, IconTrash, IconHistory, IconPlus, IconArrowLeft, IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightExpand, IconLayoutSidebarRightCollapse, IconUser, IconLogout, IconDeviceDesktop, IconMoon, IconSun, IconCheck, IconSelector, IconChevronUp } from '@tabler/icons-react';
|
|
12
|
+
import { generateId } from 'melony/client';
|
|
13
|
+
import { useQueryState, parseAsString } from 'nuqs';
|
|
12
14
|
import { mergeProps } from '@base-ui/react/merge-props';
|
|
13
15
|
import { useRender } from '@base-ui/react/use-render';
|
|
14
|
-
import * as ICONS from '@tabler/icons-react';
|
|
15
|
-
import { IconPaperclip, IconX, IconPlus, IconChevronDown, IconLoader2, IconArrowUp, IconMessage, IconTrash, IconHistory, IconArrowLeft, IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightExpand, IconLayoutSidebarRightCollapse, IconUser, IconLogout, IconBrandGoogle, IconDeviceDesktop, IconMoon, IconSun, IconCheck, IconSelector, IconChevronUp } from '@tabler/icons-react';
|
|
16
16
|
import { Menu } from '@base-ui/react/menu';
|
|
17
17
|
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
18
18
|
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
@@ -167,49 +167,215 @@ var MelonyClientProvider = ({
|
|
|
167
167
|
}
|
|
168
168
|
) }) });
|
|
169
169
|
};
|
|
170
|
+
function cn(...inputs) {
|
|
171
|
+
return twMerge(clsx(inputs));
|
|
172
|
+
}
|
|
173
|
+
var buttonVariants = cva(
|
|
174
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-4xl border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
|
|
175
|
+
{
|
|
176
|
+
variants: {
|
|
177
|
+
variant: {
|
|
178
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
179
|
+
outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
180
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
181
|
+
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
182
|
+
destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
|
183
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
184
|
+
},
|
|
185
|
+
size: {
|
|
186
|
+
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
187
|
+
xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
|
|
188
|
+
sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
189
|
+
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
190
|
+
icon: "size-9",
|
|
191
|
+
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
192
|
+
"icon-sm": "size-8",
|
|
193
|
+
"icon-lg": "size-10"
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
defaultVariants: {
|
|
197
|
+
variant: "default",
|
|
198
|
+
size: "default"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
function Button({
|
|
203
|
+
className,
|
|
204
|
+
variant = "default",
|
|
205
|
+
size = "default",
|
|
206
|
+
...props
|
|
207
|
+
}) {
|
|
208
|
+
return /* @__PURE__ */ jsx(
|
|
209
|
+
Button$1,
|
|
210
|
+
{
|
|
211
|
+
"data-slot": "button",
|
|
212
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
213
|
+
...props
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
var useAuth = () => {
|
|
218
|
+
const context = useContext(AuthContext);
|
|
219
|
+
if (context === void 0) {
|
|
220
|
+
throw new Error("useAuth must be used within an AuthProvider");
|
|
221
|
+
}
|
|
222
|
+
return context;
|
|
223
|
+
};
|
|
224
|
+
function WelcomeScreen({
|
|
225
|
+
title = "Welcome to Melony",
|
|
226
|
+
description = "The most powerful AI agent framework for building modern applications. Connect your tools, build your brain, and ship faster.",
|
|
227
|
+
features = [
|
|
228
|
+
{
|
|
229
|
+
title: "Context Aware",
|
|
230
|
+
description: "Built-in state management for complex LLM flows."
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
title: "Extensible",
|
|
234
|
+
description: "Plugin architecture for easy integrations."
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
title: "Real-time",
|
|
238
|
+
description: "Streaming responses and live state updates."
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
title: "Tool-ready",
|
|
242
|
+
description: "Ready-to-use actions for common tasks."
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
className,
|
|
246
|
+
onLoginClick,
|
|
247
|
+
termsUrl = "#",
|
|
248
|
+
privacyUrl = "#",
|
|
249
|
+
imageUrl,
|
|
250
|
+
imageAlt = "Product screenshot"
|
|
251
|
+
}) {
|
|
252
|
+
const { login, isLoading } = useAuth();
|
|
253
|
+
const handleLogin = () => {
|
|
254
|
+
if (onLoginClick) {
|
|
255
|
+
onLoginClick();
|
|
256
|
+
} else {
|
|
257
|
+
login();
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
return /* @__PURE__ */ jsxs(
|
|
261
|
+
"div",
|
|
262
|
+
{
|
|
263
|
+
className: cn(
|
|
264
|
+
"flex min-h-[600px] h-full w-full flex-col md:flex-row bg-background overflow-hidden",
|
|
265
|
+
className
|
|
266
|
+
),
|
|
267
|
+
children: [
|
|
268
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-8/12 flex-col bg-sidebar text-foreground relative overflow-hidden", children: [
|
|
269
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -top-24 -left-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
|
|
270
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -bottom-24 -right-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
|
|
271
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto overflow-x-hidden relative z-10 flex flex-col p-8 md:p-12 lg:p-20", children: /* @__PURE__ */ jsxs("div", { className: "max-w-xl mx-auto w-full my-auto", children: [
|
|
272
|
+
/* @__PURE__ */ jsx("h1", { className: "mb-6 text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl text-foreground", children: title }),
|
|
273
|
+
/* @__PURE__ */ jsx("p", { className: "mb-12 text-lg text-muted-foreground md:text-xl leading-relaxed", children: description }),
|
|
274
|
+
imageUrl && /* @__PURE__ */ jsxs("div", { className: "mb-12 relative group", children: [
|
|
275
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -inset-1 bg-gradient-to-r from-primary/20 to-primary/10 rounded-xl blur opacity-25 group-hover:opacity-50 transition duration-1000 group-hover:duration-200" }),
|
|
276
|
+
/* @__PURE__ */ jsx(
|
|
277
|
+
"img",
|
|
278
|
+
{
|
|
279
|
+
src: imageUrl,
|
|
280
|
+
alt: imageAlt,
|
|
281
|
+
className: "relative rounded-xl border border-border/50 shadow-2xl transition-transform duration-500 hover:scale-[1.02] w-full"
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
] }),
|
|
285
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-x-8 gap-y-10 sm:grid-cols-2", children: features.map((feature, i) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
286
|
+
/* @__PURE__ */ jsx("h3", { className: "font-bold text-lg text-foreground", children: feature.title }),
|
|
287
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: feature.description })
|
|
288
|
+
] }, i)) })
|
|
289
|
+
] }) })
|
|
290
|
+
] }),
|
|
291
|
+
/* @__PURE__ */ jsx("div", { className: "flex w-4/12 flex-col overflow-y-auto p-8 md:p-12 lg:p-20 bg-background transition-colors duration-300", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm space-y-8 my-auto mx-auto", children: [
|
|
292
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3 text-center md:text-left", children: [
|
|
293
|
+
/* @__PURE__ */ jsx("h2", { className: "text-3xl font-bold tracking-tight text-foreground", children: "Get Started" }),
|
|
294
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-lg", children: "Sign in to your account to continue" })
|
|
295
|
+
] }),
|
|
296
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
297
|
+
/* @__PURE__ */ jsxs(
|
|
298
|
+
Button,
|
|
299
|
+
{
|
|
300
|
+
size: "lg",
|
|
301
|
+
variant: "outline",
|
|
302
|
+
className: "w-full h-16 text-lg shadow-sm hover:shadow-md transition-all flex items-center justify-center gap-3 border-2 font-medium bg-background text-foreground hover:bg-accent",
|
|
303
|
+
onClick: handleLogin,
|
|
304
|
+
disabled: isLoading,
|
|
305
|
+
children: [
|
|
306
|
+
/* @__PURE__ */ jsx(IconBrandGoogle, { className: "size-6" }),
|
|
307
|
+
isLoading ? "Signing in..." : "Continue with Google"
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
),
|
|
311
|
+
/* @__PURE__ */ jsxs("div", { className: "relative py-4", children: [
|
|
312
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx("span", { className: "w-full border-t border-border" }) }),
|
|
313
|
+
/* @__PURE__ */ jsx("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx("span", { className: "bg-background px-3 text-muted-foreground tracking-widest font-medium", children: "Secure access" }) })
|
|
314
|
+
] })
|
|
315
|
+
] }),
|
|
316
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground leading-relaxed text-center md:text-left", children: [
|
|
317
|
+
"By continuing, you agree to our ",
|
|
318
|
+
/* @__PURE__ */ jsx("br", { className: "hidden md:block" }),
|
|
319
|
+
/* @__PURE__ */ jsx(
|
|
320
|
+
"a",
|
|
321
|
+
{
|
|
322
|
+
href: termsUrl,
|
|
323
|
+
target: "_blank",
|
|
324
|
+
rel: "noopener noreferrer",
|
|
325
|
+
className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
|
|
326
|
+
children: "Terms of Service"
|
|
327
|
+
}
|
|
328
|
+
),
|
|
329
|
+
" ",
|
|
330
|
+
"and",
|
|
331
|
+
" ",
|
|
332
|
+
/* @__PURE__ */ jsx(
|
|
333
|
+
"a",
|
|
334
|
+
{
|
|
335
|
+
href: privacyUrl,
|
|
336
|
+
target: "_blank",
|
|
337
|
+
rel: "noopener noreferrer",
|
|
338
|
+
className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
|
|
339
|
+
children: "Privacy Policy"
|
|
340
|
+
}
|
|
341
|
+
),
|
|
342
|
+
"."
|
|
343
|
+
] })
|
|
344
|
+
] }) })
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
}
|
|
170
349
|
var AuthContext = createContext(
|
|
171
350
|
void 0
|
|
172
351
|
);
|
|
173
352
|
var AuthProvider = ({
|
|
174
353
|
children,
|
|
175
|
-
service
|
|
354
|
+
service,
|
|
355
|
+
welcomeScreenProps
|
|
176
356
|
}) => {
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
} finally {
|
|
188
|
-
setIsLoading(false);
|
|
357
|
+
const queryClient = useQueryClient();
|
|
358
|
+
const { data: user, isLoading } = useQuery({
|
|
359
|
+
queryKey: ["auth-user", service],
|
|
360
|
+
queryFn: () => service.getMe(),
|
|
361
|
+
retry: false
|
|
362
|
+
});
|
|
363
|
+
const logoutMutation = useMutation({
|
|
364
|
+
mutationFn: () => service.logout(),
|
|
365
|
+
onSuccess: () => {
|
|
366
|
+
queryClient.setQueryData(["auth-user", service], null);
|
|
189
367
|
}
|
|
190
|
-
}
|
|
191
|
-
useEffect(() => {
|
|
192
|
-
fetchMe();
|
|
193
|
-
}, [fetchMe]);
|
|
368
|
+
});
|
|
194
369
|
const login = useCallback(() => {
|
|
195
370
|
service.login();
|
|
196
371
|
}, [service]);
|
|
197
372
|
const logout = useCallback(async () => {
|
|
198
373
|
try {
|
|
199
|
-
await
|
|
200
|
-
setUser(null);
|
|
374
|
+
await logoutMutation.mutateAsync();
|
|
201
375
|
} catch (error) {
|
|
202
376
|
console.error("Failed to logout:", error);
|
|
203
377
|
}
|
|
204
|
-
}, [
|
|
205
|
-
const value = {
|
|
206
|
-
user,
|
|
207
|
-
isAuthenticated: !!user,
|
|
208
|
-
isLoading,
|
|
209
|
-
login,
|
|
210
|
-
logout,
|
|
211
|
-
getToken: service.getToken
|
|
212
|
-
};
|
|
378
|
+
}, [logoutMutation]);
|
|
213
379
|
if (isLoading) {
|
|
214
380
|
return /* @__PURE__ */ jsx(
|
|
215
381
|
"div",
|
|
@@ -228,7 +394,15 @@ var AuthProvider = ({
|
|
|
228
394
|
}
|
|
229
395
|
);
|
|
230
396
|
}
|
|
231
|
-
|
|
397
|
+
const value = {
|
|
398
|
+
user: user || null,
|
|
399
|
+
isAuthenticated: !!user,
|
|
400
|
+
isLoading,
|
|
401
|
+
login,
|
|
402
|
+
logout,
|
|
403
|
+
getToken: service.getToken
|
|
404
|
+
};
|
|
405
|
+
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children: !value.isAuthenticated && welcomeScreenProps ? /* @__PURE__ */ jsx(WelcomeScreen, { ...welcomeScreenProps }) : children });
|
|
232
406
|
};
|
|
233
407
|
var ThreadContext = createContext(
|
|
234
408
|
void 0
|
|
@@ -325,6 +499,103 @@ var ThreadProvider = ({
|
|
|
325
499
|
);
|
|
326
500
|
return /* @__PURE__ */ jsx(ThreadContext.Provider, { value, children });
|
|
327
501
|
};
|
|
502
|
+
function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
|
|
503
|
+
const [screenSize, setScreenSize] = useState(() => {
|
|
504
|
+
if (typeof window === "undefined") {
|
|
505
|
+
return {
|
|
506
|
+
width: 1024,
|
|
507
|
+
height: 768,
|
|
508
|
+
isMobile: false,
|
|
509
|
+
isTablet: false,
|
|
510
|
+
isDesktop: true
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
const width = window.innerWidth;
|
|
514
|
+
return {
|
|
515
|
+
width,
|
|
516
|
+
height: window.innerHeight,
|
|
517
|
+
isMobile: width < mobileBreakpoint,
|
|
518
|
+
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
519
|
+
isDesktop: width >= tabletBreakpoint
|
|
520
|
+
};
|
|
521
|
+
});
|
|
522
|
+
useEffect(() => {
|
|
523
|
+
if (typeof window === "undefined") return;
|
|
524
|
+
const updateScreenSize = () => {
|
|
525
|
+
const width = window.innerWidth;
|
|
526
|
+
const height = window.innerHeight;
|
|
527
|
+
setScreenSize({
|
|
528
|
+
width,
|
|
529
|
+
height,
|
|
530
|
+
isMobile: width < mobileBreakpoint,
|
|
531
|
+
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
532
|
+
isDesktop: width >= tabletBreakpoint
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
updateScreenSize();
|
|
536
|
+
window.addEventListener("resize", updateScreenSize);
|
|
537
|
+
return () => {
|
|
538
|
+
window.removeEventListener("resize", updateScreenSize);
|
|
539
|
+
};
|
|
540
|
+
}, [mobileBreakpoint, tabletBreakpoint]);
|
|
541
|
+
return screenSize;
|
|
542
|
+
}
|
|
543
|
+
var SidebarContext = createContext(
|
|
544
|
+
void 0
|
|
545
|
+
);
|
|
546
|
+
function useSidebar() {
|
|
547
|
+
const context = useContext(SidebarContext);
|
|
548
|
+
if (context === void 0) {
|
|
549
|
+
throw new Error("useSidebar must be used within a SidebarProvider");
|
|
550
|
+
}
|
|
551
|
+
return context;
|
|
552
|
+
}
|
|
553
|
+
function SidebarProvider({
|
|
554
|
+
children,
|
|
555
|
+
defaultLeftCollapsed,
|
|
556
|
+
defaultRightCollapsed
|
|
557
|
+
}) {
|
|
558
|
+
const { isMobile, isTablet } = useScreenSize();
|
|
559
|
+
const isSmallScreen = isMobile || isTablet;
|
|
560
|
+
const [leftCollapsed, setLeftCollapsed] = useState(() => {
|
|
561
|
+
if (defaultLeftCollapsed !== void 0) return defaultLeftCollapsed;
|
|
562
|
+
if (typeof window !== "undefined") {
|
|
563
|
+
return window.innerWidth < 1024;
|
|
564
|
+
}
|
|
565
|
+
return false;
|
|
566
|
+
});
|
|
567
|
+
const [rightCollapsed, setRightCollapsed] = useState(() => {
|
|
568
|
+
if (defaultRightCollapsed !== void 0) return defaultRightCollapsed;
|
|
569
|
+
if (typeof window !== "undefined") {
|
|
570
|
+
return window.innerWidth < 1024;
|
|
571
|
+
}
|
|
572
|
+
return false;
|
|
573
|
+
});
|
|
574
|
+
useEffect(() => {
|
|
575
|
+
if (isSmallScreen) {
|
|
576
|
+
setLeftCollapsed(true);
|
|
577
|
+
setRightCollapsed(true);
|
|
578
|
+
}
|
|
579
|
+
}, [isSmallScreen]);
|
|
580
|
+
const handleLeftToggle = useCallback((collapsed) => {
|
|
581
|
+
setLeftCollapsed(collapsed);
|
|
582
|
+
}, []);
|
|
583
|
+
const handleRightToggle = useCallback((collapsed) => {
|
|
584
|
+
setRightCollapsed(collapsed);
|
|
585
|
+
}, []);
|
|
586
|
+
const contextValue = useMemo(
|
|
587
|
+
() => ({
|
|
588
|
+
leftCollapsed,
|
|
589
|
+
rightCollapsed,
|
|
590
|
+
setLeftCollapsed: handleLeftToggle,
|
|
591
|
+
setRightCollapsed: handleRightToggle,
|
|
592
|
+
leftCollapsible: true,
|
|
593
|
+
rightCollapsible: true
|
|
594
|
+
}),
|
|
595
|
+
[leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
|
|
596
|
+
);
|
|
597
|
+
return /* @__PURE__ */ jsx(SidebarContext.Provider, { value: contextValue, children });
|
|
598
|
+
}
|
|
328
599
|
var ThemeContext = createContext(void 0);
|
|
329
600
|
function ThemeProvider({ children }) {
|
|
330
601
|
const [theme, setThemeState] = useState("system");
|
|
@@ -398,13 +669,6 @@ var useMelony = (options) => {
|
|
|
398
669
|
}, [client, initialEvents, reset]);
|
|
399
670
|
return context;
|
|
400
671
|
};
|
|
401
|
-
var useAuth = () => {
|
|
402
|
-
const context = useContext(AuthContext);
|
|
403
|
-
if (context === void 0) {
|
|
404
|
-
throw new Error("useAuth must be used within an AuthProvider");
|
|
405
|
-
}
|
|
406
|
-
return context;
|
|
407
|
-
};
|
|
408
672
|
var useThreads = () => {
|
|
409
673
|
const context = useContext(ThreadContext);
|
|
410
674
|
if (context === void 0) {
|
|
@@ -412,94 +676,6 @@ var useThreads = () => {
|
|
|
412
676
|
}
|
|
413
677
|
return context;
|
|
414
678
|
};
|
|
415
|
-
function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
|
|
416
|
-
const [screenSize, setScreenSize] = useState(() => {
|
|
417
|
-
if (typeof window === "undefined") {
|
|
418
|
-
return {
|
|
419
|
-
width: 1024,
|
|
420
|
-
height: 768,
|
|
421
|
-
isMobile: false,
|
|
422
|
-
isTablet: false,
|
|
423
|
-
isDesktop: true
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
const width = window.innerWidth;
|
|
427
|
-
return {
|
|
428
|
-
width,
|
|
429
|
-
height: window.innerHeight,
|
|
430
|
-
isMobile: width < mobileBreakpoint,
|
|
431
|
-
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
432
|
-
isDesktop: width >= tabletBreakpoint
|
|
433
|
-
};
|
|
434
|
-
});
|
|
435
|
-
useEffect(() => {
|
|
436
|
-
if (typeof window === "undefined") return;
|
|
437
|
-
const updateScreenSize = () => {
|
|
438
|
-
const width = window.innerWidth;
|
|
439
|
-
const height = window.innerHeight;
|
|
440
|
-
setScreenSize({
|
|
441
|
-
width,
|
|
442
|
-
height,
|
|
443
|
-
isMobile: width < mobileBreakpoint,
|
|
444
|
-
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
445
|
-
isDesktop: width >= tabletBreakpoint
|
|
446
|
-
});
|
|
447
|
-
};
|
|
448
|
-
updateScreenSize();
|
|
449
|
-
window.addEventListener("resize", updateScreenSize);
|
|
450
|
-
return () => {
|
|
451
|
-
window.removeEventListener("resize", updateScreenSize);
|
|
452
|
-
};
|
|
453
|
-
}, [mobileBreakpoint, tabletBreakpoint]);
|
|
454
|
-
return screenSize;
|
|
455
|
-
}
|
|
456
|
-
function cn(...inputs) {
|
|
457
|
-
return twMerge(clsx(inputs));
|
|
458
|
-
}
|
|
459
|
-
var buttonVariants = cva(
|
|
460
|
-
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-4xl border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
|
|
461
|
-
{
|
|
462
|
-
variants: {
|
|
463
|
-
variant: {
|
|
464
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
465
|
-
outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
466
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
467
|
-
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
468
|
-
destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
|
469
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
470
|
-
},
|
|
471
|
-
size: {
|
|
472
|
-
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
473
|
-
xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
|
|
474
|
-
sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
475
|
-
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
476
|
-
icon: "size-9",
|
|
477
|
-
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
478
|
-
"icon-sm": "size-8",
|
|
479
|
-
"icon-lg": "size-10"
|
|
480
|
-
}
|
|
481
|
-
},
|
|
482
|
-
defaultVariants: {
|
|
483
|
-
variant: "default",
|
|
484
|
-
size: "default"
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
);
|
|
488
|
-
function Button({
|
|
489
|
-
className,
|
|
490
|
-
variant = "default",
|
|
491
|
-
size = "default",
|
|
492
|
-
...props
|
|
493
|
-
}) {
|
|
494
|
-
return /* @__PURE__ */ jsx(
|
|
495
|
-
Button$1,
|
|
496
|
-
{
|
|
497
|
-
"data-slot": "button",
|
|
498
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
499
|
-
...props
|
|
500
|
-
}
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
679
|
function Textarea({ className, ...props }) {
|
|
504
680
|
return /* @__PURE__ */ jsx(
|
|
505
681
|
"textarea",
|
|
@@ -689,7 +865,22 @@ function Composer({
|
|
|
689
865
|
() => new Set(defaultSelectedIds)
|
|
690
866
|
);
|
|
691
867
|
const [attachedFiles, setAttachedFiles] = React11__default.useState([]);
|
|
868
|
+
const [previews, setPreviews] = React11__default.useState([]);
|
|
692
869
|
const fileInputRef = React11__default.useRef(null);
|
|
870
|
+
React11__default.useEffect(() => {
|
|
871
|
+
const newPreviews = attachedFiles.map((file) => ({
|
|
872
|
+
name: file.name,
|
|
873
|
+
type: file.type,
|
|
874
|
+
size: file.size,
|
|
875
|
+
url: file.type.startsWith("image/") ? URL.createObjectURL(file) : ""
|
|
876
|
+
}));
|
|
877
|
+
setPreviews(newPreviews);
|
|
878
|
+
return () => {
|
|
879
|
+
newPreviews.forEach((p) => {
|
|
880
|
+
if (p.url) URL.revokeObjectURL(p.url);
|
|
881
|
+
});
|
|
882
|
+
};
|
|
883
|
+
}, [attachedFiles]);
|
|
693
884
|
const toggleOption = (id, groupOptions, type = "multiple") => {
|
|
694
885
|
const next = new Set(selectedOptions);
|
|
695
886
|
if (type === "single") {
|
|
@@ -735,11 +926,6 @@ function Composer({
|
|
|
735
926
|
const handleRemoveFile = (index) => {
|
|
736
927
|
setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
737
928
|
};
|
|
738
|
-
const formatFileSize = (bytes) => {
|
|
739
|
-
if (bytes < 1024) return bytes + " B";
|
|
740
|
-
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
741
|
-
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
742
|
-
};
|
|
743
929
|
const handleInternalSubmit = async () => {
|
|
744
930
|
const state = {};
|
|
745
931
|
options.forEach((group) => {
|
|
@@ -805,13 +991,56 @@ function Composer({
|
|
|
805
991
|
handleInternalSubmit().catch(console.error);
|
|
806
992
|
}
|
|
807
993
|
};
|
|
994
|
+
const handlePaste = (e) => {
|
|
995
|
+
if (!enabled) return;
|
|
996
|
+
const items = Array.from(e.clipboardData.items);
|
|
997
|
+
const files = items.map((item) => item.getAsFile()).filter((file) => file !== null);
|
|
998
|
+
if (files.length > 0) {
|
|
999
|
+
const remainingSlots = maxFiles - attachedFiles.length;
|
|
1000
|
+
const validFiles = files.filter((f) => f.size <= maxFileSize);
|
|
1001
|
+
const filesToAdd = validFiles.slice(0, remainingSlots);
|
|
1002
|
+
if (filesToAdd.length > 0) {
|
|
1003
|
+
setAttachedFiles((prev) => [...prev, ...filesToAdd]);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
808
1007
|
return /* @__PURE__ */ jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col w-full border-input border-[1.5px] rounded-3xl bg-background shadow-sm focus-within:border-ring transition-all p-2", children: [
|
|
1008
|
+
previews.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3 p-2 px-3 pb-3", children: previews.map((preview, index) => /* @__PURE__ */ jsxs(
|
|
1009
|
+
"div",
|
|
1010
|
+
{
|
|
1011
|
+
className: "group relative flex flex-col items-center justify-center w-20 h-20 rounded-xl border bg-muted/30 overflow-hidden shadow-sm",
|
|
1012
|
+
children: [
|
|
1013
|
+
preview.type.startsWith("image/") ? /* @__PURE__ */ jsx(
|
|
1014
|
+
"img",
|
|
1015
|
+
{
|
|
1016
|
+
src: preview.url,
|
|
1017
|
+
alt: preview.name,
|
|
1018
|
+
className: "w-full h-full object-cover"
|
|
1019
|
+
}
|
|
1020
|
+
) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center p-2 text-center", children: [
|
|
1021
|
+
preview.type.includes("text") || preview.type.includes("pdf") ? /* @__PURE__ */ jsx(IconFileText, { className: "h-8 w-8 text-muted-foreground" }) : /* @__PURE__ */ jsx(IconFile, { className: "h-8 w-8 text-muted-foreground" }),
|
|
1022
|
+
/* @__PURE__ */ jsx("span", { className: "text-[9px] truncate w-full px-1 mt-1 text-muted-foreground", children: preview.name })
|
|
1023
|
+
] }),
|
|
1024
|
+
/* @__PURE__ */ jsx(
|
|
1025
|
+
"button",
|
|
1026
|
+
{
|
|
1027
|
+
type: "button",
|
|
1028
|
+
onClick: () => handleRemoveFile(index),
|
|
1029
|
+
className: "absolute top-1 right-1 p-1 rounded-full bg-foreground/10 hover:bg-foreground/20 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1030
|
+
children: /* @__PURE__ */ jsx(IconX, { className: "h-3 w-3" })
|
|
1031
|
+
}
|
|
1032
|
+
)
|
|
1033
|
+
]
|
|
1034
|
+
},
|
|
1035
|
+
index
|
|
1036
|
+
)) }),
|
|
809
1037
|
/* @__PURE__ */ jsx(
|
|
810
1038
|
Textarea,
|
|
811
1039
|
{
|
|
812
1040
|
value,
|
|
813
1041
|
onChange: (e) => onChange(e.target.value),
|
|
814
1042
|
onKeyDown: handleKeyDown,
|
|
1043
|
+
onPaste: handlePaste,
|
|
815
1044
|
placeholder,
|
|
816
1045
|
className: "min-h-[44px] max-h-[200px] border-none bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 py-2 text-[15px] resize-none",
|
|
817
1046
|
autoFocus
|
|
@@ -832,100 +1061,22 @@ function Composer({
|
|
|
832
1061
|
disabled: isLoading || attachedFiles.length >= maxFiles
|
|
833
1062
|
}
|
|
834
1063
|
),
|
|
835
|
-
|
|
1064
|
+
/* @__PURE__ */ jsxs(
|
|
836
1065
|
Button,
|
|
837
1066
|
{
|
|
838
1067
|
type: "button",
|
|
839
1068
|
variant: "ghost",
|
|
840
1069
|
size: "sm",
|
|
841
1070
|
onClick: () => fileInputRef.current?.click(),
|
|
842
|
-
disabled: isLoading,
|
|
1071
|
+
disabled: isLoading || attachedFiles.length >= maxFiles,
|
|
843
1072
|
className: "text-muted-foreground",
|
|
844
1073
|
title: "Attach file",
|
|
845
|
-
children:
|
|
1074
|
+
children: [
|
|
1075
|
+
/* @__PURE__ */ jsx(IconPaperclip, { className: "h-4 w-4" }),
|
|
1076
|
+
attachedFiles.length > 0 && /* @__PURE__ */ jsx(Badge, { className: "ml-1 h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
|
|
1077
|
+
]
|
|
846
1078
|
}
|
|
847
|
-
)
|
|
848
|
-
/* @__PURE__ */ jsx(
|
|
849
|
-
DropdownMenuTrigger,
|
|
850
|
-
{
|
|
851
|
-
render: /* @__PURE__ */ jsxs(
|
|
852
|
-
Button,
|
|
853
|
-
{
|
|
854
|
-
type: "button",
|
|
855
|
-
variant: "ghost",
|
|
856
|
-
size: "sm",
|
|
857
|
-
className: "text-muted-foreground gap-2",
|
|
858
|
-
title: `${attachedFiles.length} files attached`,
|
|
859
|
-
children: [
|
|
860
|
-
/* @__PURE__ */ jsx(IconPaperclip, { className: "h-4 w-4" }),
|
|
861
|
-
/* @__PURE__ */ jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
|
|
862
|
-
]
|
|
863
|
-
}
|
|
864
|
-
)
|
|
865
|
-
}
|
|
866
|
-
),
|
|
867
|
-
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", className: "w-64", children: [
|
|
868
|
-
/* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
869
|
-
/* @__PURE__ */ jsxs(DropdownMenuLabel, { children: [
|
|
870
|
-
"Attached Files (",
|
|
871
|
-
attachedFiles.length,
|
|
872
|
-
"/",
|
|
873
|
-
maxFiles,
|
|
874
|
-
")"
|
|
875
|
-
] }),
|
|
876
|
-
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
877
|
-
attachedFiles.map((file, index) => /* @__PURE__ */ jsxs(
|
|
878
|
-
DropdownMenuItem,
|
|
879
|
-
{
|
|
880
|
-
className: "flex items-center justify-between group",
|
|
881
|
-
onSelect: (e) => e.preventDefault(),
|
|
882
|
-
children: [
|
|
883
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
884
|
-
/* @__PURE__ */ jsx(
|
|
885
|
-
"span",
|
|
886
|
-
{
|
|
887
|
-
className: "truncate text-sm",
|
|
888
|
-
title: file.name,
|
|
889
|
-
children: file.name
|
|
890
|
-
}
|
|
891
|
-
),
|
|
892
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatFileSize(file.size) })
|
|
893
|
-
] }),
|
|
894
|
-
/* @__PURE__ */ jsx(
|
|
895
|
-
Button,
|
|
896
|
-
{
|
|
897
|
-
type: "button",
|
|
898
|
-
variant: "ghost",
|
|
899
|
-
size: "icon",
|
|
900
|
-
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
901
|
-
onClick: () => handleRemoveFile(index),
|
|
902
|
-
children: /* @__PURE__ */ jsx(IconX, { className: "h-3 w-3" })
|
|
903
|
-
}
|
|
904
|
-
)
|
|
905
|
-
]
|
|
906
|
-
},
|
|
907
|
-
index
|
|
908
|
-
))
|
|
909
|
-
] }),
|
|
910
|
-
attachedFiles.length < maxFiles && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
911
|
-
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
912
|
-
/* @__PURE__ */ jsxs(
|
|
913
|
-
DropdownMenuItem,
|
|
914
|
-
{
|
|
915
|
-
onSelect: (e) => {
|
|
916
|
-
e.preventDefault();
|
|
917
|
-
fileInputRef.current?.click();
|
|
918
|
-
},
|
|
919
|
-
className: "text-primary focus:text-primary",
|
|
920
|
-
children: [
|
|
921
|
-
/* @__PURE__ */ jsx(IconPlus, { className: "mr-2 h-4 w-4" }),
|
|
922
|
-
/* @__PURE__ */ jsx("span", { children: "Add more files" })
|
|
923
|
-
]
|
|
924
|
-
}
|
|
925
|
-
)
|
|
926
|
-
] })
|
|
927
|
-
] })
|
|
928
|
-
] })
|
|
1079
|
+
)
|
|
929
1080
|
] }),
|
|
930
1081
|
options.map((group) => {
|
|
931
1082
|
const selectedInGroup = group.options.filter(
|
|
@@ -2720,55 +2871,31 @@ var ThreadList = ({
|
|
|
2720
2871
|
emptyState,
|
|
2721
2872
|
onThreadSelect
|
|
2722
2873
|
}) => {
|
|
2723
|
-
const {
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
}
|
|
2874
|
+
const { threads, activeThreadId, selectThread, deleteThread, isLoading } = useThreads();
|
|
2875
|
+
const sortedThreads = React11.useMemo(() => {
|
|
2876
|
+
return [...threads].sort((a, b) => {
|
|
2877
|
+
const dateA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
|
|
2878
|
+
const dateB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
|
|
2879
|
+
return dateB - dateA;
|
|
2880
|
+
});
|
|
2881
|
+
}, [threads]);
|
|
2731
2882
|
const handleThreadClick = (threadId) => {
|
|
2732
2883
|
if (threadId !== activeThreadId) {
|
|
2733
2884
|
selectThread(threadId);
|
|
2734
2885
|
}
|
|
2735
2886
|
onThreadSelect?.(threadId);
|
|
2736
2887
|
};
|
|
2737
|
-
const handleDelete = async (
|
|
2738
|
-
e.stopPropagation();
|
|
2888
|
+
const handleDelete = async (threadId) => {
|
|
2739
2889
|
try {
|
|
2740
2890
|
await deleteThread(threadId);
|
|
2741
2891
|
} catch (error) {
|
|
2742
2892
|
console.error("Failed to delete thread:", error);
|
|
2743
2893
|
}
|
|
2744
2894
|
};
|
|
2745
|
-
const handleNewThread = async () => {
|
|
2746
|
-
try {
|
|
2747
|
-
await createThread();
|
|
2748
|
-
} catch (error) {
|
|
2749
|
-
console.error("Failed to create thread:", error);
|
|
2750
|
-
}
|
|
2751
|
-
};
|
|
2752
|
-
const formatDate = (date) => {
|
|
2753
|
-
if (!date) return "";
|
|
2754
|
-
const d = typeof date === "string" ? new Date(date) : date;
|
|
2755
|
-
if (isNaN(d.getTime())) return "";
|
|
2756
|
-
const now = /* @__PURE__ */ new Date();
|
|
2757
|
-
const diffMs = now.getTime() - d.getTime();
|
|
2758
|
-
const diffMins = Math.floor(diffMs / 6e4);
|
|
2759
|
-
const diffHours = Math.floor(diffMs / 36e5);
|
|
2760
|
-
const diffDays = Math.floor(diffMs / 864e5);
|
|
2761
|
-
if (diffMins < 1) return "Just now";
|
|
2762
|
-
if (diffMins < 60) return `${diffMins}m ago`;
|
|
2763
|
-
if (diffHours < 24) return `${diffHours}h ago`;
|
|
2764
|
-
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2765
|
-
return d.toLocaleDateString();
|
|
2766
|
-
};
|
|
2767
2895
|
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col h-full", className), children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading && threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground" }) }) : threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-muted-foreground", children: emptyState || /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2768
2896
|
/* @__PURE__ */ jsx(IconMessage, { className: "size-8 mx-auto opacity-50" }),
|
|
2769
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No threads yet" })
|
|
2770
|
-
|
|
2771
|
-
] }) }) : /* @__PURE__ */ jsx("div", { className: "p-2 space-y-1", children: threads.map((thread) => {
|
|
2897
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No threads yet" })
|
|
2898
|
+
] }) }) : /* @__PURE__ */ jsx("div", { className: "p-2 space-y-1", children: sortedThreads.map((thread) => {
|
|
2772
2899
|
const isActive = thread.id === activeThreadId;
|
|
2773
2900
|
return /* @__PURE__ */ jsxs(
|
|
2774
2901
|
"div",
|
|
@@ -2776,33 +2903,51 @@ var ThreadList = ({
|
|
|
2776
2903
|
onClick: () => handleThreadClick(thread.id),
|
|
2777
2904
|
className: cn(
|
|
2778
2905
|
"group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
|
|
2779
|
-
isActive ? "bg-muted" : "hover:bg-muted"
|
|
2906
|
+
isActive ? "bg-muted text-foreground" : "hover:bg-muted/50 text-muted-foreground hover:text-foreground"
|
|
2780
2907
|
),
|
|
2781
2908
|
children: [
|
|
2782
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2909
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: thread.title || `Thread ${thread.id.slice(0, 8)}` }) }),
|
|
2910
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 flex items-center opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2911
|
+
/* @__PURE__ */ jsx(
|
|
2912
|
+
DropdownMenuTrigger,
|
|
2913
|
+
{
|
|
2914
|
+
render: (props) => /* @__PURE__ */ jsx(
|
|
2915
|
+
Button,
|
|
2916
|
+
{
|
|
2917
|
+
variant: "ghost",
|
|
2918
|
+
size: "icon-xs",
|
|
2919
|
+
...props,
|
|
2920
|
+
onClick: (e) => {
|
|
2921
|
+
e.stopPropagation();
|
|
2922
|
+
props.onClick?.(e);
|
|
2923
|
+
},
|
|
2924
|
+
children: /* @__PURE__ */ jsx(IconDotsVertical, { className: "size-3.5" })
|
|
2925
|
+
}
|
|
2926
|
+
)
|
|
2927
|
+
}
|
|
2928
|
+
),
|
|
2929
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "w-32", children: /* @__PURE__ */ jsxs(
|
|
2930
|
+
DropdownMenuItem,
|
|
2931
|
+
{
|
|
2932
|
+
variant: "destructive",
|
|
2933
|
+
onClick: (e) => {
|
|
2934
|
+
e.stopPropagation();
|
|
2935
|
+
handleDelete(thread.id);
|
|
2936
|
+
},
|
|
2937
|
+
children: [
|
|
2938
|
+
/* @__PURE__ */ jsx(IconTrash, { className: "size-4 mr-2" }),
|
|
2939
|
+
/* @__PURE__ */ jsx("span", { children: "Delete" })
|
|
2940
|
+
]
|
|
2941
|
+
}
|
|
2942
|
+
) })
|
|
2943
|
+
] }) })
|
|
2799
2944
|
]
|
|
2800
2945
|
},
|
|
2801
2946
|
thread.id
|
|
2802
2947
|
);
|
|
2803
2948
|
}) }) }) });
|
|
2804
2949
|
};
|
|
2805
|
-
function
|
|
2950
|
+
function PopupChat({
|
|
2806
2951
|
title = "Chat",
|
|
2807
2952
|
placeholder = "Message the AI",
|
|
2808
2953
|
starterPrompts,
|
|
@@ -2906,136 +3051,46 @@ function ChatPopup({
|
|
|
2906
3051
|
)
|
|
2907
3052
|
] });
|
|
2908
3053
|
}
|
|
2909
|
-
function
|
|
3054
|
+
function Sidebar({ side, children, className }) {
|
|
3055
|
+
const { leftCollapsed, rightCollapsed } = useSidebar();
|
|
3056
|
+
const collapsed = side === "left" ? leftCollapsed : rightCollapsed;
|
|
3057
|
+
return /* @__PURE__ */ jsx(
|
|
3058
|
+
"div",
|
|
3059
|
+
{
|
|
3060
|
+
className: cn(
|
|
3061
|
+
"flex-shrink-0 border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3062
|
+
side === "left" ? "border-r" : "border-l",
|
|
3063
|
+
collapsed ? "w-0 border-r-0 border-l-0 min-w-0" : "",
|
|
3064
|
+
!collapsed && className
|
|
3065
|
+
),
|
|
3066
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children })
|
|
3067
|
+
}
|
|
3068
|
+
);
|
|
3069
|
+
}
|
|
3070
|
+
function FullChat({
|
|
2910
3071
|
title = "Chat",
|
|
2911
|
-
placeholder
|
|
3072
|
+
placeholder,
|
|
2912
3073
|
starterPrompts,
|
|
2913
3074
|
options,
|
|
2914
3075
|
className,
|
|
2915
3076
|
headerProps,
|
|
3077
|
+
autoFocus = false,
|
|
2916
3078
|
defaultSelectedIds
|
|
2917
3079
|
}) {
|
|
2918
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full
|
|
2919
|
-
/* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
2920
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
3080
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full w-full bg-background", className), children: [
|
|
3081
|
+
title && /* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
3082
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden flex relative", children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx(
|
|
2921
3083
|
Thread,
|
|
2922
3084
|
{
|
|
2923
3085
|
placeholder,
|
|
2924
3086
|
starterPrompts,
|
|
2925
3087
|
options,
|
|
2926
|
-
|
|
3088
|
+
autoFocus,
|
|
2927
3089
|
defaultSelectedIds
|
|
2928
3090
|
}
|
|
2929
|
-
) })
|
|
3091
|
+
) }) })
|
|
2930
3092
|
] });
|
|
2931
3093
|
}
|
|
2932
|
-
var ChatSidebarContext = createContext(
|
|
2933
|
-
void 0
|
|
2934
|
-
);
|
|
2935
|
-
function useChatSidebar() {
|
|
2936
|
-
const context = useContext(ChatSidebarContext);
|
|
2937
|
-
if (context === void 0) {
|
|
2938
|
-
throw new Error("useChatSidebar must be used within a ChatSidebarProvider");
|
|
2939
|
-
}
|
|
2940
|
-
return context;
|
|
2941
|
-
}
|
|
2942
|
-
function ChatFull({
|
|
2943
|
-
title = "Chat",
|
|
2944
|
-
placeholder = "Message the AI",
|
|
2945
|
-
starterPrompts,
|
|
2946
|
-
options,
|
|
2947
|
-
className,
|
|
2948
|
-
headerProps,
|
|
2949
|
-
leftSidebar,
|
|
2950
|
-
rightSidebar,
|
|
2951
|
-
leftSidebarClassName,
|
|
2952
|
-
rightSidebarClassName,
|
|
2953
|
-
autoFocus = false,
|
|
2954
|
-
defaultSelectedIds
|
|
2955
|
-
}) {
|
|
2956
|
-
const { isMobile, isTablet } = useScreenSize();
|
|
2957
|
-
const isSmallScreen = isMobile || isTablet;
|
|
2958
|
-
const [internalLeftCollapsed, setInternalLeftCollapsed] = useState(() => {
|
|
2959
|
-
if (typeof window !== "undefined") {
|
|
2960
|
-
return window.innerWidth < 1024;
|
|
2961
|
-
}
|
|
2962
|
-
return false;
|
|
2963
|
-
});
|
|
2964
|
-
const [internalRightCollapsed, setInternalRightCollapsed] = useState(() => {
|
|
2965
|
-
if (typeof window !== "undefined") {
|
|
2966
|
-
return window.innerWidth < 1024;
|
|
2967
|
-
}
|
|
2968
|
-
return false;
|
|
2969
|
-
});
|
|
2970
|
-
useEffect(() => {
|
|
2971
|
-
if (isSmallScreen) {
|
|
2972
|
-
setInternalLeftCollapsed(true);
|
|
2973
|
-
setInternalRightCollapsed(true);
|
|
2974
|
-
}
|
|
2975
|
-
}, [isSmallScreen]);
|
|
2976
|
-
const leftCollapsed = internalLeftCollapsed;
|
|
2977
|
-
const rightCollapsed = internalRightCollapsed;
|
|
2978
|
-
const handleLeftToggle = useCallback((collapsed) => {
|
|
2979
|
-
setInternalLeftCollapsed(collapsed);
|
|
2980
|
-
}, []);
|
|
2981
|
-
const handleRightToggle = useCallback((collapsed) => {
|
|
2982
|
-
setInternalRightCollapsed(collapsed);
|
|
2983
|
-
}, []);
|
|
2984
|
-
const contextValue = useMemo(
|
|
2985
|
-
() => ({
|
|
2986
|
-
leftCollapsed,
|
|
2987
|
-
rightCollapsed,
|
|
2988
|
-
setLeftCollapsed: handleLeftToggle,
|
|
2989
|
-
setRightCollapsed: handleRightToggle,
|
|
2990
|
-
leftCollapsible: true,
|
|
2991
|
-
rightCollapsible: true
|
|
2992
|
-
}),
|
|
2993
|
-
[leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
|
|
2994
|
-
);
|
|
2995
|
-
return /* @__PURE__ */ jsx(ChatSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
|
|
2996
|
-
"div",
|
|
2997
|
-
{
|
|
2998
|
-
className: cn("flex flex-col h-full w-full bg-background", className),
|
|
2999
|
-
children: [
|
|
3000
|
-
title && /* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
3001
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden flex relative", children: [
|
|
3002
|
-
leftSidebar && /* @__PURE__ */ jsx(
|
|
3003
|
-
"div",
|
|
3004
|
-
{
|
|
3005
|
-
className: cn(
|
|
3006
|
-
"flex-shrink-0 border-r border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3007
|
-
leftCollapsed ? "w-0 border-r-0 min-w-0" : "",
|
|
3008
|
-
!leftCollapsed && leftSidebarClassName
|
|
3009
|
-
),
|
|
3010
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: leftSidebar })
|
|
3011
|
-
}
|
|
3012
|
-
),
|
|
3013
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx(
|
|
3014
|
-
Thread,
|
|
3015
|
-
{
|
|
3016
|
-
placeholder,
|
|
3017
|
-
starterPrompts,
|
|
3018
|
-
options,
|
|
3019
|
-
autoFocus,
|
|
3020
|
-
defaultSelectedIds
|
|
3021
|
-
}
|
|
3022
|
-
) }),
|
|
3023
|
-
rightSidebar && /* @__PURE__ */ jsx(
|
|
3024
|
-
"div",
|
|
3025
|
-
{
|
|
3026
|
-
className: cn(
|
|
3027
|
-
"flex-shrink-0 border-l border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3028
|
-
rightCollapsed ? "w-0 border-l-0 min-w-0" : "",
|
|
3029
|
-
!rightCollapsed && rightSidebarClassName
|
|
3030
|
-
),
|
|
3031
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: rightSidebar })
|
|
3032
|
-
}
|
|
3033
|
-
)
|
|
3034
|
-
] })
|
|
3035
|
-
]
|
|
3036
|
-
}
|
|
3037
|
-
) });
|
|
3038
|
-
}
|
|
3039
3094
|
function SidebarToggle({ side, className }) {
|
|
3040
3095
|
const {
|
|
3041
3096
|
leftCollapsed,
|
|
@@ -3044,13 +3099,14 @@ function SidebarToggle({ side, className }) {
|
|
|
3044
3099
|
setRightCollapsed,
|
|
3045
3100
|
leftCollapsible,
|
|
3046
3101
|
rightCollapsible
|
|
3047
|
-
} =
|
|
3102
|
+
} = useSidebar();
|
|
3048
3103
|
if (side === "left") {
|
|
3049
3104
|
if (!leftCollapsible) return null;
|
|
3050
3105
|
return /* @__PURE__ */ jsx(
|
|
3051
3106
|
Button,
|
|
3052
3107
|
{
|
|
3053
3108
|
variant: "ghost",
|
|
3109
|
+
size: "icon",
|
|
3054
3110
|
onClick: () => setLeftCollapsed(!leftCollapsed),
|
|
3055
3111
|
"aria-label": leftCollapsed ? "Expand left sidebar" : "Collapse left sidebar",
|
|
3056
3112
|
className: cn("", className),
|
|
@@ -3064,6 +3120,7 @@ function SidebarToggle({ side, className }) {
|
|
|
3064
3120
|
Button,
|
|
3065
3121
|
{
|
|
3066
3122
|
variant: "ghost",
|
|
3123
|
+
size: "icon",
|
|
3067
3124
|
onClick: () => setRightCollapsed(!rightCollapsed),
|
|
3068
3125
|
"aria-label": rightCollapsed ? "Expand right sidebar" : "Collapse right sidebar",
|
|
3069
3126
|
className: cn("", className),
|
|
@@ -3331,7 +3388,7 @@ var ThreadPopover = ({
|
|
|
3331
3388
|
var CreateThreadButton = ({
|
|
3332
3389
|
className,
|
|
3333
3390
|
variant = "ghost",
|
|
3334
|
-
size = "
|
|
3391
|
+
size = "default",
|
|
3335
3392
|
children,
|
|
3336
3393
|
onThreadCreated
|
|
3337
3394
|
}) => {
|
|
@@ -3362,7 +3419,7 @@ var CreateThreadButton = ({
|
|
|
3362
3419
|
// Don't trigger in contenteditable elements
|
|
3363
3420
|
}
|
|
3364
3421
|
);
|
|
3365
|
-
return /* @__PURE__ */
|
|
3422
|
+
return /* @__PURE__ */ jsxs(
|
|
3366
3423
|
Button,
|
|
3367
3424
|
{
|
|
3368
3425
|
variant,
|
|
@@ -3370,7 +3427,10 @@ var CreateThreadButton = ({
|
|
|
3370
3427
|
onClick: handleCreateThread,
|
|
3371
3428
|
disabled: isCreating,
|
|
3372
3429
|
className: cn(className),
|
|
3373
|
-
children:
|
|
3430
|
+
children: [
|
|
3431
|
+
/* @__PURE__ */ jsx(IconPlus, { className: "size-4" }),
|
|
3432
|
+
"New chat"
|
|
3433
|
+
]
|
|
3374
3434
|
}
|
|
3375
3435
|
);
|
|
3376
3436
|
};
|
|
@@ -3564,17 +3624,14 @@ var AccountDialog = ({
|
|
|
3564
3624
|
] });
|
|
3565
3625
|
}
|
|
3566
3626
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3567
|
-
/* @__PURE__ */
|
|
3627
|
+
/* @__PURE__ */ jsx(
|
|
3568
3628
|
Button,
|
|
3569
3629
|
{
|
|
3570
3630
|
variant,
|
|
3571
3631
|
size,
|
|
3572
3632
|
onClick: () => setOpen(true),
|
|
3573
3633
|
className,
|
|
3574
|
-
children:
|
|
3575
|
-
/* @__PURE__ */ jsx(IconBrandGoogle, { className: "mr-2 size-4" }),
|
|
3576
|
-
"Sign in with Google"
|
|
3577
|
-
]
|
|
3634
|
+
children: "Sign in"
|
|
3578
3635
|
}
|
|
3579
3636
|
),
|
|
3580
3637
|
/* @__PURE__ */ jsx(AlertDialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(AlertDialogContent, { className: "sm:max-w-md", children: [
|
|
@@ -3638,6 +3695,6 @@ function ThemeToggle() {
|
|
|
3638
3695
|
);
|
|
3639
3696
|
}
|
|
3640
3697
|
|
|
3641
|
-
export { AccountDialog, AuthContext, AuthProvider, Badge2 as Badge, Box, Button2 as Button, Card2 as Card, Chart,
|
|
3698
|
+
export { AccountDialog, AuthContext, AuthProvider, Badge2 as Badge, Box, Button2 as Button, Card2 as Card, Chart, ChatHeader, Checkbox, Col, Composer, CreateThreadButton, Divider, Form, FullChat, Heading, Image, Input2 as Input, Label2 as Label, List, ListItem, MelonyClientProvider, MelonyContext, PopupChat, RadioGroup, Row, Select2 as Select, Sidebar, SidebarContext, SidebarProvider, SidebarToggle, Spacer, Text, Textarea2 as Textarea, ThemeProvider, ThemeToggle, Thread, ThreadContext, ThreadList, ThreadPopover, ThreadProvider, UIRenderer, WelcomeScreen, groupEventsToMessages, useAuth, useMelony, useScreenSize, useSidebar, useTheme, useThreads };
|
|
3642
3699
|
//# sourceMappingURL=index.js.map
|
|
3643
3700
|
//# sourceMappingURL=index.js.map
|