@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/dist/index.cjs CHANGED
@@ -4,15 +4,15 @@ var React11 = require('react');
4
4
  var react = require('nuqs/adapters/react');
5
5
  var reactQuery = require('@tanstack/react-query');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
- var client = require('melony/client');
8
- var nuqs = require('nuqs');
9
- var clsx = require('clsx');
10
- var tailwindMerge = require('tailwind-merge');
11
7
  var button = require('@base-ui/react/button');
12
8
  var classVarianceAuthority = require('class-variance-authority');
9
+ var clsx = require('clsx');
10
+ var tailwindMerge = require('tailwind-merge');
11
+ var ICONS = require('@tabler/icons-react');
12
+ var client = require('melony/client');
13
+ var nuqs = require('nuqs');
13
14
  var mergeProps = require('@base-ui/react/merge-props');
14
15
  var useRender = require('@base-ui/react/use-render');
15
- var ICONS = require('@tabler/icons-react');
16
16
  var menu = require('@base-ui/react/menu');
17
17
  var separator = require('@base-ui/react/separator');
18
18
  var dialog = require('@base-ui/react/dialog');
@@ -188,49 +188,215 @@ var MelonyClientProvider = ({
188
188
  }
189
189
  ) }) });
190
190
  };
191
+ function cn(...inputs) {
192
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
193
+ }
194
+ var buttonVariants = classVarianceAuthority.cva(
195
+ "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",
196
+ {
197
+ variants: {
198
+ variant: {
199
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
200
+ outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
201
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
202
+ ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
203
+ 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",
204
+ link: "text-primary underline-offset-4 hover:underline"
205
+ },
206
+ size: {
207
+ default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
208
+ 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",
209
+ sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
210
+ lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
211
+ icon: "size-9",
212
+ "icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
213
+ "icon-sm": "size-8",
214
+ "icon-lg": "size-10"
215
+ }
216
+ },
217
+ defaultVariants: {
218
+ variant: "default",
219
+ size: "default"
220
+ }
221
+ }
222
+ );
223
+ function Button({
224
+ className,
225
+ variant = "default",
226
+ size = "default",
227
+ ...props
228
+ }) {
229
+ return /* @__PURE__ */ jsxRuntime.jsx(
230
+ button.Button,
231
+ {
232
+ "data-slot": "button",
233
+ className: cn(buttonVariants({ variant, size, className })),
234
+ ...props
235
+ }
236
+ );
237
+ }
238
+ var useAuth = () => {
239
+ const context = React11.useContext(AuthContext);
240
+ if (context === void 0) {
241
+ throw new Error("useAuth must be used within an AuthProvider");
242
+ }
243
+ return context;
244
+ };
245
+ function WelcomeScreen({
246
+ title = "Welcome to Melony",
247
+ description = "The most powerful AI agent framework for building modern applications. Connect your tools, build your brain, and ship faster.",
248
+ features = [
249
+ {
250
+ title: "Context Aware",
251
+ description: "Built-in state management for complex LLM flows."
252
+ },
253
+ {
254
+ title: "Extensible",
255
+ description: "Plugin architecture for easy integrations."
256
+ },
257
+ {
258
+ title: "Real-time",
259
+ description: "Streaming responses and live state updates."
260
+ },
261
+ {
262
+ title: "Tool-ready",
263
+ description: "Ready-to-use actions for common tasks."
264
+ }
265
+ ],
266
+ className,
267
+ onLoginClick,
268
+ termsUrl = "#",
269
+ privacyUrl = "#",
270
+ imageUrl,
271
+ imageAlt = "Product screenshot"
272
+ }) {
273
+ const { login, isLoading } = useAuth();
274
+ const handleLogin = () => {
275
+ if (onLoginClick) {
276
+ onLoginClick();
277
+ } else {
278
+ login();
279
+ }
280
+ };
281
+ return /* @__PURE__ */ jsxRuntime.jsxs(
282
+ "div",
283
+ {
284
+ className: cn(
285
+ "flex min-h-[600px] h-full w-full flex-col md:flex-row bg-background overflow-hidden",
286
+ className
287
+ ),
288
+ children: [
289
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-8/12 flex-col bg-sidebar text-foreground relative overflow-hidden", children: [
290
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-24 -left-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
291
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -bottom-24 -right-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
292
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "max-w-xl mx-auto w-full my-auto", children: [
293
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mb-6 text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl text-foreground", children: title }),
294
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-12 text-lg text-muted-foreground md:text-xl leading-relaxed", children: description }),
295
+ imageUrl && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-12 relative group", children: [
296
+ /* @__PURE__ */ jsxRuntime.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" }),
297
+ /* @__PURE__ */ jsxRuntime.jsx(
298
+ "img",
299
+ {
300
+ src: imageUrl,
301
+ alt: imageAlt,
302
+ className: "relative rounded-xl border border-border/50 shadow-2xl transition-transform duration-500 hover:scale-[1.02] w-full"
303
+ }
304
+ )
305
+ ] }),
306
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-x-8 gap-y-10 sm:grid-cols-2", children: features.map((feature, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
307
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-bold text-lg text-foreground", children: feature.title }),
308
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: feature.description })
309
+ ] }, i)) })
310
+ ] }) })
311
+ ] }),
312
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-sm space-y-8 my-auto mx-auto", children: [
313
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 text-center md:text-left", children: [
314
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-bold tracking-tight text-foreground", children: "Get Started" }),
315
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-lg", children: "Sign in to your account to continue" })
316
+ ] }),
317
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
318
+ /* @__PURE__ */ jsxRuntime.jsxs(
319
+ Button,
320
+ {
321
+ size: "lg",
322
+ variant: "outline",
323
+ 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",
324
+ onClick: handleLogin,
325
+ disabled: isLoading,
326
+ children: [
327
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconBrandGoogle, { className: "size-6" }),
328
+ isLoading ? "Signing in..." : "Continue with Google"
329
+ ]
330
+ }
331
+ ),
332
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative py-4", children: [
333
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-full border-t border-border" }) }),
334
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-background px-3 text-muted-foreground tracking-widest font-medium", children: "Secure access" }) })
335
+ ] })
336
+ ] }),
337
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground leading-relaxed text-center md:text-left", children: [
338
+ "By continuing, you agree to our ",
339
+ /* @__PURE__ */ jsxRuntime.jsx("br", { className: "hidden md:block" }),
340
+ /* @__PURE__ */ jsxRuntime.jsx(
341
+ "a",
342
+ {
343
+ href: termsUrl,
344
+ target: "_blank",
345
+ rel: "noopener noreferrer",
346
+ className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
347
+ children: "Terms of Service"
348
+ }
349
+ ),
350
+ " ",
351
+ "and",
352
+ " ",
353
+ /* @__PURE__ */ jsxRuntime.jsx(
354
+ "a",
355
+ {
356
+ href: privacyUrl,
357
+ target: "_blank",
358
+ rel: "noopener noreferrer",
359
+ className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
360
+ children: "Privacy Policy"
361
+ }
362
+ ),
363
+ "."
364
+ ] })
365
+ ] }) })
366
+ ]
367
+ }
368
+ );
369
+ }
191
370
  var AuthContext = React11.createContext(
192
371
  void 0
193
372
  );
194
373
  var AuthProvider = ({
195
374
  children,
196
- service
375
+ service,
376
+ welcomeScreenProps
197
377
  }) => {
198
- const [user, setUser] = React11.useState(null);
199
- const [isLoading, setIsLoading] = React11.useState(true);
200
- const fetchMe = React11.useCallback(async () => {
201
- setIsLoading(true);
202
- try {
203
- const userData = await service.getMe();
204
- setUser(userData);
205
- } catch (error) {
206
- console.error("Failed to fetch user:", error);
207
- setUser(null);
208
- } finally {
209
- setIsLoading(false);
378
+ const queryClient = reactQuery.useQueryClient();
379
+ const { data: user, isLoading } = reactQuery.useQuery({
380
+ queryKey: ["auth-user", service],
381
+ queryFn: () => service.getMe(),
382
+ retry: false
383
+ });
384
+ const logoutMutation = reactQuery.useMutation({
385
+ mutationFn: () => service.logout(),
386
+ onSuccess: () => {
387
+ queryClient.setQueryData(["auth-user", service], null);
210
388
  }
211
- }, [service]);
212
- React11.useEffect(() => {
213
- fetchMe();
214
- }, [fetchMe]);
389
+ });
215
390
  const login = React11.useCallback(() => {
216
391
  service.login();
217
392
  }, [service]);
218
393
  const logout = React11.useCallback(async () => {
219
394
  try {
220
- await service.logout();
221
- setUser(null);
395
+ await logoutMutation.mutateAsync();
222
396
  } catch (error) {
223
397
  console.error("Failed to logout:", error);
224
398
  }
225
- }, [service]);
226
- const value = {
227
- user,
228
- isAuthenticated: !!user,
229
- isLoading,
230
- login,
231
- logout,
232
- getToken: service.getToken
233
- };
399
+ }, [logoutMutation]);
234
400
  if (isLoading) {
235
401
  return /* @__PURE__ */ jsxRuntime.jsx(
236
402
  "div",
@@ -249,7 +415,15 @@ var AuthProvider = ({
249
415
  }
250
416
  );
251
417
  }
252
- return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children });
418
+ const value = {
419
+ user: user || null,
420
+ isAuthenticated: !!user,
421
+ isLoading,
422
+ login,
423
+ logout,
424
+ getToken: service.getToken
425
+ };
426
+ return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children: !value.isAuthenticated && welcomeScreenProps ? /* @__PURE__ */ jsxRuntime.jsx(WelcomeScreen, { ...welcomeScreenProps }) : children });
253
427
  };
254
428
  var ThreadContext = React11.createContext(
255
429
  void 0
@@ -346,6 +520,103 @@ var ThreadProvider = ({
346
520
  );
347
521
  return /* @__PURE__ */ jsxRuntime.jsx(ThreadContext.Provider, { value, children });
348
522
  };
523
+ function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
524
+ const [screenSize, setScreenSize] = React11.useState(() => {
525
+ if (typeof window === "undefined") {
526
+ return {
527
+ width: 1024,
528
+ height: 768,
529
+ isMobile: false,
530
+ isTablet: false,
531
+ isDesktop: true
532
+ };
533
+ }
534
+ const width = window.innerWidth;
535
+ return {
536
+ width,
537
+ height: window.innerHeight,
538
+ isMobile: width < mobileBreakpoint,
539
+ isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
540
+ isDesktop: width >= tabletBreakpoint
541
+ };
542
+ });
543
+ React11.useEffect(() => {
544
+ if (typeof window === "undefined") return;
545
+ const updateScreenSize = () => {
546
+ const width = window.innerWidth;
547
+ const height = window.innerHeight;
548
+ setScreenSize({
549
+ width,
550
+ height,
551
+ isMobile: width < mobileBreakpoint,
552
+ isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
553
+ isDesktop: width >= tabletBreakpoint
554
+ });
555
+ };
556
+ updateScreenSize();
557
+ window.addEventListener("resize", updateScreenSize);
558
+ return () => {
559
+ window.removeEventListener("resize", updateScreenSize);
560
+ };
561
+ }, [mobileBreakpoint, tabletBreakpoint]);
562
+ return screenSize;
563
+ }
564
+ var SidebarContext = React11.createContext(
565
+ void 0
566
+ );
567
+ function useSidebar() {
568
+ const context = React11.useContext(SidebarContext);
569
+ if (context === void 0) {
570
+ throw new Error("useSidebar must be used within a SidebarProvider");
571
+ }
572
+ return context;
573
+ }
574
+ function SidebarProvider({
575
+ children,
576
+ defaultLeftCollapsed,
577
+ defaultRightCollapsed
578
+ }) {
579
+ const { isMobile, isTablet } = useScreenSize();
580
+ const isSmallScreen = isMobile || isTablet;
581
+ const [leftCollapsed, setLeftCollapsed] = React11.useState(() => {
582
+ if (defaultLeftCollapsed !== void 0) return defaultLeftCollapsed;
583
+ if (typeof window !== "undefined") {
584
+ return window.innerWidth < 1024;
585
+ }
586
+ return false;
587
+ });
588
+ const [rightCollapsed, setRightCollapsed] = React11.useState(() => {
589
+ if (defaultRightCollapsed !== void 0) return defaultRightCollapsed;
590
+ if (typeof window !== "undefined") {
591
+ return window.innerWidth < 1024;
592
+ }
593
+ return false;
594
+ });
595
+ React11.useEffect(() => {
596
+ if (isSmallScreen) {
597
+ setLeftCollapsed(true);
598
+ setRightCollapsed(true);
599
+ }
600
+ }, [isSmallScreen]);
601
+ const handleLeftToggle = React11.useCallback((collapsed) => {
602
+ setLeftCollapsed(collapsed);
603
+ }, []);
604
+ const handleRightToggle = React11.useCallback((collapsed) => {
605
+ setRightCollapsed(collapsed);
606
+ }, []);
607
+ const contextValue = React11.useMemo(
608
+ () => ({
609
+ leftCollapsed,
610
+ rightCollapsed,
611
+ setLeftCollapsed: handleLeftToggle,
612
+ setRightCollapsed: handleRightToggle,
613
+ leftCollapsible: true,
614
+ rightCollapsible: true
615
+ }),
616
+ [leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
617
+ );
618
+ return /* @__PURE__ */ jsxRuntime.jsx(SidebarContext.Provider, { value: contextValue, children });
619
+ }
349
620
  var ThemeContext = React11.createContext(void 0);
350
621
  function ThemeProvider({ children }) {
351
622
  const [theme, setThemeState] = React11.useState("system");
@@ -419,13 +690,6 @@ var useMelony = (options) => {
419
690
  }, [client, initialEvents, reset]);
420
691
  return context;
421
692
  };
422
- var useAuth = () => {
423
- const context = React11.useContext(AuthContext);
424
- if (context === void 0) {
425
- throw new Error("useAuth must be used within an AuthProvider");
426
- }
427
- return context;
428
- };
429
693
  var useThreads = () => {
430
694
  const context = React11.useContext(ThreadContext);
431
695
  if (context === void 0) {
@@ -433,94 +697,6 @@ var useThreads = () => {
433
697
  }
434
698
  return context;
435
699
  };
436
- function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
437
- const [screenSize, setScreenSize] = React11.useState(() => {
438
- if (typeof window === "undefined") {
439
- return {
440
- width: 1024,
441
- height: 768,
442
- isMobile: false,
443
- isTablet: false,
444
- isDesktop: true
445
- };
446
- }
447
- const width = window.innerWidth;
448
- return {
449
- width,
450
- height: window.innerHeight,
451
- isMobile: width < mobileBreakpoint,
452
- isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
453
- isDesktop: width >= tabletBreakpoint
454
- };
455
- });
456
- React11.useEffect(() => {
457
- if (typeof window === "undefined") return;
458
- const updateScreenSize = () => {
459
- const width = window.innerWidth;
460
- const height = window.innerHeight;
461
- setScreenSize({
462
- width,
463
- height,
464
- isMobile: width < mobileBreakpoint,
465
- isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
466
- isDesktop: width >= tabletBreakpoint
467
- });
468
- };
469
- updateScreenSize();
470
- window.addEventListener("resize", updateScreenSize);
471
- return () => {
472
- window.removeEventListener("resize", updateScreenSize);
473
- };
474
- }, [mobileBreakpoint, tabletBreakpoint]);
475
- return screenSize;
476
- }
477
- function cn(...inputs) {
478
- return tailwindMerge.twMerge(clsx.clsx(inputs));
479
- }
480
- var buttonVariants = classVarianceAuthority.cva(
481
- "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",
482
- {
483
- variants: {
484
- variant: {
485
- default: "bg-primary text-primary-foreground hover:bg-primary/80",
486
- outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
487
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
488
- ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
489
- 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",
490
- link: "text-primary underline-offset-4 hover:underline"
491
- },
492
- size: {
493
- default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
494
- 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",
495
- sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
496
- lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
497
- icon: "size-9",
498
- "icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
499
- "icon-sm": "size-8",
500
- "icon-lg": "size-10"
501
- }
502
- },
503
- defaultVariants: {
504
- variant: "default",
505
- size: "default"
506
- }
507
- }
508
- );
509
- function Button({
510
- className,
511
- variant = "default",
512
- size = "default",
513
- ...props
514
- }) {
515
- return /* @__PURE__ */ jsxRuntime.jsx(
516
- button.Button,
517
- {
518
- "data-slot": "button",
519
- className: cn(buttonVariants({ variant, size, className })),
520
- ...props
521
- }
522
- );
523
- }
524
700
  function Textarea({ className, ...props }) {
525
701
  return /* @__PURE__ */ jsxRuntime.jsx(
526
702
  "textarea",
@@ -710,7 +886,22 @@ function Composer({
710
886
  () => new Set(defaultSelectedIds)
711
887
  );
712
888
  const [attachedFiles, setAttachedFiles] = React11__namespace.default.useState([]);
889
+ const [previews, setPreviews] = React11__namespace.default.useState([]);
713
890
  const fileInputRef = React11__namespace.default.useRef(null);
891
+ React11__namespace.default.useEffect(() => {
892
+ const newPreviews = attachedFiles.map((file) => ({
893
+ name: file.name,
894
+ type: file.type,
895
+ size: file.size,
896
+ url: file.type.startsWith("image/") ? URL.createObjectURL(file) : ""
897
+ }));
898
+ setPreviews(newPreviews);
899
+ return () => {
900
+ newPreviews.forEach((p) => {
901
+ if (p.url) URL.revokeObjectURL(p.url);
902
+ });
903
+ };
904
+ }, [attachedFiles]);
714
905
  const toggleOption = (id, groupOptions, type = "multiple") => {
715
906
  const next = new Set(selectedOptions);
716
907
  if (type === "single") {
@@ -756,11 +947,6 @@ function Composer({
756
947
  const handleRemoveFile = (index) => {
757
948
  setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
758
949
  };
759
- const formatFileSize = (bytes) => {
760
- if (bytes < 1024) return bytes + " B";
761
- if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
762
- return (bytes / (1024 * 1024)).toFixed(1) + " MB";
763
- };
764
950
  const handleInternalSubmit = async () => {
765
951
  const state = {};
766
952
  options.forEach((group) => {
@@ -826,13 +1012,56 @@ function Composer({
826
1012
  handleInternalSubmit().catch(console.error);
827
1013
  }
828
1014
  };
1015
+ const handlePaste = (e) => {
1016
+ if (!enabled) return;
1017
+ const items = Array.from(e.clipboardData.items);
1018
+ const files = items.map((item) => item.getAsFile()).filter((file) => file !== null);
1019
+ if (files.length > 0) {
1020
+ const remainingSlots = maxFiles - attachedFiles.length;
1021
+ const validFiles = files.filter((f) => f.size <= maxFileSize);
1022
+ const filesToAdd = validFiles.slice(0, remainingSlots);
1023
+ if (filesToAdd.length > 0) {
1024
+ setAttachedFiles((prev) => [...prev, ...filesToAdd]);
1025
+ }
1026
+ }
1027
+ };
829
1028
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxRuntime.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: [
1029
+ previews.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3 p-2 px-3 pb-3", children: previews.map((preview, index) => /* @__PURE__ */ jsxRuntime.jsxs(
1030
+ "div",
1031
+ {
1032
+ className: "group relative flex flex-col items-center justify-center w-20 h-20 rounded-xl border bg-muted/30 overflow-hidden shadow-sm",
1033
+ children: [
1034
+ preview.type.startsWith("image/") ? /* @__PURE__ */ jsxRuntime.jsx(
1035
+ "img",
1036
+ {
1037
+ src: preview.url,
1038
+ alt: preview.name,
1039
+ className: "w-full h-full object-cover"
1040
+ }
1041
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center p-2 text-center", children: [
1042
+ preview.type.includes("text") || preview.type.includes("pdf") ? /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconFileText, { className: "h-8 w-8 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconFile, { className: "h-8 w-8 text-muted-foreground" }),
1043
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] truncate w-full px-1 mt-1 text-muted-foreground", children: preview.name })
1044
+ ] }),
1045
+ /* @__PURE__ */ jsxRuntime.jsx(
1046
+ "button",
1047
+ {
1048
+ type: "button",
1049
+ onClick: () => handleRemoveFile(index),
1050
+ 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",
1051
+ children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconX, { className: "h-3 w-3" })
1052
+ }
1053
+ )
1054
+ ]
1055
+ },
1056
+ index
1057
+ )) }),
830
1058
  /* @__PURE__ */ jsxRuntime.jsx(
831
1059
  Textarea,
832
1060
  {
833
1061
  value,
834
1062
  onChange: (e) => onChange(e.target.value),
835
1063
  onKeyDown: handleKeyDown,
1064
+ onPaste: handlePaste,
836
1065
  placeholder,
837
1066
  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",
838
1067
  autoFocus
@@ -853,100 +1082,22 @@ function Composer({
853
1082
  disabled: isLoading || attachedFiles.length >= maxFiles
854
1083
  }
855
1084
  ),
856
- attachedFiles.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1085
+ /* @__PURE__ */ jsxRuntime.jsxs(
857
1086
  Button,
858
1087
  {
859
1088
  type: "button",
860
1089
  variant: "ghost",
861
1090
  size: "sm",
862
1091
  onClick: () => fileInputRef.current?.click(),
863
- disabled: isLoading,
1092
+ disabled: isLoading || attachedFiles.length >= maxFiles,
864
1093
  className: "text-muted-foreground",
865
1094
  title: "Attach file",
866
- children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPaperclip, { className: "h-4 w-4" })
1095
+ children: [
1096
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPaperclip, { className: "h-4 w-4" }),
1097
+ attachedFiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "ml-1 h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
1098
+ ]
867
1099
  }
868
- ) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
869
- /* @__PURE__ */ jsxRuntime.jsx(
870
- DropdownMenuTrigger,
871
- {
872
- render: /* @__PURE__ */ jsxRuntime.jsxs(
873
- Button,
874
- {
875
- type: "button",
876
- variant: "ghost",
877
- size: "sm",
878
- className: "text-muted-foreground gap-2",
879
- title: `${attachedFiles.length} files attached`,
880
- children: [
881
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPaperclip, { className: "h-4 w-4" }),
882
- /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
883
- ]
884
- }
885
- )
886
- }
887
- ),
888
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "start", className: "w-64", children: [
889
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuGroup, { children: [
890
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuLabel, { children: [
891
- "Attached Files (",
892
- attachedFiles.length,
893
- "/",
894
- maxFiles,
895
- ")"
896
- ] }),
897
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
898
- attachedFiles.map((file, index) => /* @__PURE__ */ jsxRuntime.jsxs(
899
- DropdownMenuItem,
900
- {
901
- className: "flex items-center justify-between group",
902
- onSelect: (e) => e.preventDefault(),
903
- children: [
904
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
905
- /* @__PURE__ */ jsxRuntime.jsx(
906
- "span",
907
- {
908
- className: "truncate text-sm",
909
- title: file.name,
910
- children: file.name
911
- }
912
- ),
913
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatFileSize(file.size) })
914
- ] }),
915
- /* @__PURE__ */ jsxRuntime.jsx(
916
- Button,
917
- {
918
- type: "button",
919
- variant: "ghost",
920
- size: "icon",
921
- className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
922
- onClick: () => handleRemoveFile(index),
923
- children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconX, { className: "h-3 w-3" })
924
- }
925
- )
926
- ]
927
- },
928
- index
929
- ))
930
- ] }),
931
- attachedFiles.length < maxFiles && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
932
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
933
- /* @__PURE__ */ jsxRuntime.jsxs(
934
- DropdownMenuItem,
935
- {
936
- onSelect: (e) => {
937
- e.preventDefault();
938
- fileInputRef.current?.click();
939
- },
940
- className: "text-primary focus:text-primary",
941
- children: [
942
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "mr-2 h-4 w-4" }),
943
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add more files" })
944
- ]
945
- }
946
- )
947
- ] })
948
- ] })
949
- ] })
1100
+ )
950
1101
  ] }),
951
1102
  options.map((group) => {
952
1103
  const selectedInGroup = group.options.filter(
@@ -2741,55 +2892,31 @@ var ThreadList = ({
2741
2892
  emptyState,
2742
2893
  onThreadSelect
2743
2894
  }) => {
2744
- const {
2745
- threads,
2746
- activeThreadId,
2747
- selectThread,
2748
- createThread,
2749
- deleteThread,
2750
- isLoading
2751
- } = useThreads();
2895
+ const { threads, activeThreadId, selectThread, deleteThread, isLoading } = useThreads();
2896
+ const sortedThreads = React11__namespace.useMemo(() => {
2897
+ return [...threads].sort((a, b) => {
2898
+ const dateA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
2899
+ const dateB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
2900
+ return dateB - dateA;
2901
+ });
2902
+ }, [threads]);
2752
2903
  const handleThreadClick = (threadId) => {
2753
2904
  if (threadId !== activeThreadId) {
2754
2905
  selectThread(threadId);
2755
2906
  }
2756
2907
  onThreadSelect?.(threadId);
2757
2908
  };
2758
- const handleDelete = async (e, threadId) => {
2759
- e.stopPropagation();
2909
+ const handleDelete = async (threadId) => {
2760
2910
  try {
2761
2911
  await deleteThread(threadId);
2762
2912
  } catch (error) {
2763
2913
  console.error("Failed to delete thread:", error);
2764
2914
  }
2765
2915
  };
2766
- const handleNewThread = async () => {
2767
- try {
2768
- await createThread();
2769
- } catch (error) {
2770
- console.error("Failed to create thread:", error);
2771
- }
2772
- };
2773
- const formatDate = (date) => {
2774
- if (!date) return "";
2775
- const d = typeof date === "string" ? new Date(date) : date;
2776
- if (isNaN(d.getTime())) return "";
2777
- const now = /* @__PURE__ */ new Date();
2778
- const diffMs = now.getTime() - d.getTime();
2779
- const diffMins = Math.floor(diffMs / 6e4);
2780
- const diffHours = Math.floor(diffMs / 36e5);
2781
- const diffDays = Math.floor(diffMs / 864e5);
2782
- if (diffMins < 1) return "Just now";
2783
- if (diffMins < 60) return `${diffMins}m ago`;
2784
- if (diffHours < 24) return `${diffHours}h ago`;
2785
- if (diffDays < 7) return `${diffDays}d ago`;
2786
- return d.toLocaleDateString();
2787
- };
2788
2916
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading && threads.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLoader2, { className: "size-5 animate-spin text-muted-foreground" }) }) : threads.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-muted-foreground", children: emptyState || /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2789
2917
  /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconMessage, { className: "size-8 mx-auto opacity-50" }),
2790
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No threads yet" }),
2791
- /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
2792
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 space-y-1", children: threads.map((thread) => {
2918
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No threads yet" })
2919
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 space-y-1", children: sortedThreads.map((thread) => {
2793
2920
  const isActive = thread.id === activeThreadId;
2794
2921
  return /* @__PURE__ */ jsxRuntime.jsxs(
2795
2922
  "div",
@@ -2797,33 +2924,51 @@ var ThreadList = ({
2797
2924
  onClick: () => handleThreadClick(thread.id),
2798
2925
  className: cn(
2799
2926
  "group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
2800
- isActive ? "bg-muted" : "hover:bg-muted"
2927
+ isActive ? "bg-muted text-foreground" : "hover:bg-muted/50 text-muted-foreground hover:text-foreground"
2801
2928
  ),
2802
2929
  children: [
2803
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
2804
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm font-medium truncate"), children: thread.title || `Thread ${thread.id.slice(0, 8)}` }),
2805
- thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs shrink-0"), children: formatDate(thread.updatedAt) })
2806
- ] }) }),
2807
- /* @__PURE__ */ jsxRuntime.jsx(
2808
- Button,
2809
- {
2810
- variant: "ghost",
2811
- size: "icon-xs",
2812
- onClick: (e) => handleDelete(e, thread.id),
2813
- className: cn(
2814
- "opacity-0 group-hover:opacity-100 transition-opacity shrink-0",
2815
- isActive && "hover:bg-primary-foreground/20"
2816
- ),
2817
- children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconTrash, { className: "size-3" })
2818
- }
2819
- )
2930
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium truncate", children: thread.title || `Thread ${thread.id.slice(0, 8)}` }) }),
2931
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 flex items-center opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
2932
+ /* @__PURE__ */ jsxRuntime.jsx(
2933
+ DropdownMenuTrigger,
2934
+ {
2935
+ render: (props) => /* @__PURE__ */ jsxRuntime.jsx(
2936
+ Button,
2937
+ {
2938
+ variant: "ghost",
2939
+ size: "icon-xs",
2940
+ ...props,
2941
+ onClick: (e) => {
2942
+ e.stopPropagation();
2943
+ props.onClick?.(e);
2944
+ },
2945
+ children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconDotsVertical, { className: "size-3.5" })
2946
+ }
2947
+ )
2948
+ }
2949
+ ),
2950
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "start", className: "w-32", children: /* @__PURE__ */ jsxRuntime.jsxs(
2951
+ DropdownMenuItem,
2952
+ {
2953
+ variant: "destructive",
2954
+ onClick: (e) => {
2955
+ e.stopPropagation();
2956
+ handleDelete(thread.id);
2957
+ },
2958
+ children: [
2959
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconTrash, { className: "size-4 mr-2" }),
2960
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delete" })
2961
+ ]
2962
+ }
2963
+ ) })
2964
+ ] }) })
2820
2965
  ]
2821
2966
  },
2822
2967
  thread.id
2823
2968
  );
2824
2969
  }) }) }) });
2825
2970
  };
2826
- function ChatPopup({
2971
+ function PopupChat({
2827
2972
  title = "Chat",
2828
2973
  placeholder = "Message the AI",
2829
2974
  starterPrompts,
@@ -2927,136 +3072,46 @@ function ChatPopup({
2927
3072
  )
2928
3073
  ] });
2929
3074
  }
2930
- function ChatSidebar({
3075
+ function Sidebar({ side, children, className }) {
3076
+ const { leftCollapsed, rightCollapsed } = useSidebar();
3077
+ const collapsed = side === "left" ? leftCollapsed : rightCollapsed;
3078
+ return /* @__PURE__ */ jsxRuntime.jsx(
3079
+ "div",
3080
+ {
3081
+ className: cn(
3082
+ "flex-shrink-0 border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
3083
+ side === "left" ? "border-r" : "border-l",
3084
+ collapsed ? "w-0 border-r-0 border-l-0 min-w-0" : "",
3085
+ !collapsed && className
3086
+ ),
3087
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children })
3088
+ }
3089
+ );
3090
+ }
3091
+ function FullChat({
2931
3092
  title = "Chat",
2932
- placeholder = "Message the AI",
3093
+ placeholder,
2933
3094
  starterPrompts,
2934
3095
  options,
2935
3096
  className,
2936
3097
  headerProps,
3098
+ autoFocus = false,
2937
3099
  defaultSelectedIds
2938
3100
  }) {
2939
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col h-full border-r bg-background w-80", className), children: [
2940
- /* @__PURE__ */ jsxRuntime.jsx(ChatHeader, { title, ...headerProps }),
2941
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
3101
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col h-full w-full bg-background", className), children: [
3102
+ title && /* @__PURE__ */ jsxRuntime.jsx(ChatHeader, { title, ...headerProps }),
3103
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden flex relative", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
2942
3104
  Thread,
2943
3105
  {
2944
3106
  placeholder,
2945
3107
  starterPrompts,
2946
3108
  options,
2947
- className: "h-full",
3109
+ autoFocus,
2948
3110
  defaultSelectedIds
2949
3111
  }
2950
- ) })
3112
+ ) }) })
2951
3113
  ] });
2952
3114
  }
2953
- var ChatSidebarContext = React11.createContext(
2954
- void 0
2955
- );
2956
- function useChatSidebar() {
2957
- const context = React11.useContext(ChatSidebarContext);
2958
- if (context === void 0) {
2959
- throw new Error("useChatSidebar must be used within a ChatSidebarProvider");
2960
- }
2961
- return context;
2962
- }
2963
- function ChatFull({
2964
- title = "Chat",
2965
- placeholder = "Message the AI",
2966
- starterPrompts,
2967
- options,
2968
- className,
2969
- headerProps,
2970
- leftSidebar,
2971
- rightSidebar,
2972
- leftSidebarClassName,
2973
- rightSidebarClassName,
2974
- autoFocus = false,
2975
- defaultSelectedIds
2976
- }) {
2977
- const { isMobile, isTablet } = useScreenSize();
2978
- const isSmallScreen = isMobile || isTablet;
2979
- const [internalLeftCollapsed, setInternalLeftCollapsed] = React11.useState(() => {
2980
- if (typeof window !== "undefined") {
2981
- return window.innerWidth < 1024;
2982
- }
2983
- return false;
2984
- });
2985
- const [internalRightCollapsed, setInternalRightCollapsed] = React11.useState(() => {
2986
- if (typeof window !== "undefined") {
2987
- return window.innerWidth < 1024;
2988
- }
2989
- return false;
2990
- });
2991
- React11.useEffect(() => {
2992
- if (isSmallScreen) {
2993
- setInternalLeftCollapsed(true);
2994
- setInternalRightCollapsed(true);
2995
- }
2996
- }, [isSmallScreen]);
2997
- const leftCollapsed = internalLeftCollapsed;
2998
- const rightCollapsed = internalRightCollapsed;
2999
- const handleLeftToggle = React11.useCallback((collapsed) => {
3000
- setInternalLeftCollapsed(collapsed);
3001
- }, []);
3002
- const handleRightToggle = React11.useCallback((collapsed) => {
3003
- setInternalRightCollapsed(collapsed);
3004
- }, []);
3005
- const contextValue = React11.useMemo(
3006
- () => ({
3007
- leftCollapsed,
3008
- rightCollapsed,
3009
- setLeftCollapsed: handleLeftToggle,
3010
- setRightCollapsed: handleRightToggle,
3011
- leftCollapsible: true,
3012
- rightCollapsible: true
3013
- }),
3014
- [leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
3015
- );
3016
- return /* @__PURE__ */ jsxRuntime.jsx(ChatSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
3017
- "div",
3018
- {
3019
- className: cn("flex flex-col h-full w-full bg-background", className),
3020
- children: [
3021
- title && /* @__PURE__ */ jsxRuntime.jsx(ChatHeader, { title, ...headerProps }),
3022
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden flex relative", children: [
3023
- leftSidebar && /* @__PURE__ */ jsxRuntime.jsx(
3024
- "div",
3025
- {
3026
- className: cn(
3027
- "flex-shrink-0 border-r border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
3028
- leftCollapsed ? "w-0 border-r-0 min-w-0" : "",
3029
- !leftCollapsed && leftSidebarClassName
3030
- ),
3031
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: leftSidebar })
3032
- }
3033
- ),
3034
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
3035
- Thread,
3036
- {
3037
- placeholder,
3038
- starterPrompts,
3039
- options,
3040
- autoFocus,
3041
- defaultSelectedIds
3042
- }
3043
- ) }),
3044
- rightSidebar && /* @__PURE__ */ jsxRuntime.jsx(
3045
- "div",
3046
- {
3047
- className: cn(
3048
- "flex-shrink-0 border-l border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
3049
- rightCollapsed ? "w-0 border-l-0 min-w-0" : "",
3050
- !rightCollapsed && rightSidebarClassName
3051
- ),
3052
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: rightSidebar })
3053
- }
3054
- )
3055
- ] })
3056
- ]
3057
- }
3058
- ) });
3059
- }
3060
3115
  function SidebarToggle({ side, className }) {
3061
3116
  const {
3062
3117
  leftCollapsed,
@@ -3065,13 +3120,14 @@ function SidebarToggle({ side, className }) {
3065
3120
  setRightCollapsed,
3066
3121
  leftCollapsible,
3067
3122
  rightCollapsible
3068
- } = useChatSidebar();
3123
+ } = useSidebar();
3069
3124
  if (side === "left") {
3070
3125
  if (!leftCollapsible) return null;
3071
3126
  return /* @__PURE__ */ jsxRuntime.jsx(
3072
3127
  Button,
3073
3128
  {
3074
3129
  variant: "ghost",
3130
+ size: "icon",
3075
3131
  onClick: () => setLeftCollapsed(!leftCollapsed),
3076
3132
  "aria-label": leftCollapsed ? "Expand left sidebar" : "Collapse left sidebar",
3077
3133
  className: cn("", className),
@@ -3085,6 +3141,7 @@ function SidebarToggle({ side, className }) {
3085
3141
  Button,
3086
3142
  {
3087
3143
  variant: "ghost",
3144
+ size: "icon",
3088
3145
  onClick: () => setRightCollapsed(!rightCollapsed),
3089
3146
  "aria-label": rightCollapsed ? "Expand right sidebar" : "Collapse right sidebar",
3090
3147
  className: cn("", className),
@@ -3352,7 +3409,7 @@ var ThreadPopover = ({
3352
3409
  var CreateThreadButton = ({
3353
3410
  className,
3354
3411
  variant = "ghost",
3355
- size = "icon",
3412
+ size = "default",
3356
3413
  children,
3357
3414
  onThreadCreated
3358
3415
  }) => {
@@ -3383,7 +3440,7 @@ var CreateThreadButton = ({
3383
3440
  // Don't trigger in contenteditable elements
3384
3441
  }
3385
3442
  );
3386
- return /* @__PURE__ */ jsxRuntime.jsx(
3443
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3387
3444
  Button,
3388
3445
  {
3389
3446
  variant,
@@ -3391,7 +3448,10 @@ var CreateThreadButton = ({
3391
3448
  onClick: handleCreateThread,
3392
3449
  disabled: isCreating,
3393
3450
  className: cn(className),
3394
- children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "size-4" })
3451
+ children: [
3452
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "size-4" }),
3453
+ "New chat"
3454
+ ]
3395
3455
  }
3396
3456
  );
3397
3457
  };
@@ -3585,17 +3645,14 @@ var AccountDialog = ({
3585
3645
  ] });
3586
3646
  }
3587
3647
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3588
- /* @__PURE__ */ jsxRuntime.jsxs(
3648
+ /* @__PURE__ */ jsxRuntime.jsx(
3589
3649
  Button,
3590
3650
  {
3591
3651
  variant,
3592
3652
  size,
3593
3653
  onClick: () => setOpen(true),
3594
3654
  className,
3595
- children: [
3596
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconBrandGoogle, { className: "mr-2 size-4" }),
3597
- "Sign in with Google"
3598
- ]
3655
+ children: "Sign in"
3599
3656
  }
3600
3657
  ),
3601
3658
  /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "sm:max-w-md", children: [
@@ -3667,17 +3724,14 @@ exports.Box = Box;
3667
3724
  exports.Button = Button2;
3668
3725
  exports.Card = Card2;
3669
3726
  exports.Chart = Chart;
3670
- exports.ChatFull = ChatFull;
3671
3727
  exports.ChatHeader = ChatHeader;
3672
- exports.ChatPopup = ChatPopup;
3673
- exports.ChatSidebar = ChatSidebar;
3674
- exports.ChatSidebarContext = ChatSidebarContext;
3675
3728
  exports.Checkbox = Checkbox;
3676
3729
  exports.Col = Col;
3677
3730
  exports.Composer = Composer;
3678
3731
  exports.CreateThreadButton = CreateThreadButton;
3679
3732
  exports.Divider = Divider;
3680
3733
  exports.Form = Form;
3734
+ exports.FullChat = FullChat;
3681
3735
  exports.Heading = Heading;
3682
3736
  exports.Image = Image;
3683
3737
  exports.Input = Input2;
@@ -3686,9 +3740,13 @@ exports.List = List;
3686
3740
  exports.ListItem = ListItem;
3687
3741
  exports.MelonyClientProvider = MelonyClientProvider;
3688
3742
  exports.MelonyContext = MelonyContext;
3743
+ exports.PopupChat = PopupChat;
3689
3744
  exports.RadioGroup = RadioGroup;
3690
3745
  exports.Row = Row;
3691
3746
  exports.Select = Select2;
3747
+ exports.Sidebar = Sidebar;
3748
+ exports.SidebarContext = SidebarContext;
3749
+ exports.SidebarProvider = SidebarProvider;
3692
3750
  exports.SidebarToggle = SidebarToggle;
3693
3751
  exports.Spacer = Spacer;
3694
3752
  exports.Text = Text;
@@ -3701,11 +3759,12 @@ exports.ThreadList = ThreadList;
3701
3759
  exports.ThreadPopover = ThreadPopover;
3702
3760
  exports.ThreadProvider = ThreadProvider;
3703
3761
  exports.UIRenderer = UIRenderer;
3762
+ exports.WelcomeScreen = WelcomeScreen;
3704
3763
  exports.groupEventsToMessages = groupEventsToMessages;
3705
3764
  exports.useAuth = useAuth;
3706
- exports.useChatSidebar = useChatSidebar;
3707
3765
  exports.useMelony = useMelony;
3708
3766
  exports.useScreenSize = useScreenSize;
3767
+ exports.useSidebar = useSidebar;
3709
3768
  exports.useTheme = useTheme;
3710
3769
  exports.useThreads = useThreads;
3711
3770
  //# sourceMappingURL=index.cjs.map