@melony/react 0.1.26 → 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
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
 
3
- var React12 = require('react');
3
+ 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');
@@ -40,7 +40,7 @@ function _interopNamespace(e) {
40
40
  return Object.freeze(n);
41
41
  }
42
42
 
43
- var React12__namespace = /*#__PURE__*/_interopNamespace(React12);
43
+ var React11__namespace = /*#__PURE__*/_interopNamespace(React11);
44
44
  var ICONS__namespace = /*#__PURE__*/_interopNamespace(ICONS);
45
45
 
46
46
  // src/providers/melony-provider.tsx
@@ -69,7 +69,7 @@ function groupEventsToMessages(events) {
69
69
  }
70
70
  return messages;
71
71
  }
72
- var MelonyContext = React12.createContext(
72
+ var MelonyContext = React11.createContext(
73
73
  void 0
74
74
  );
75
75
  var defaultQueryClient = new reactQuery.QueryClient({
@@ -86,29 +86,29 @@ var MelonyContextProviderInner = ({
86
86
  initialEvents,
87
87
  setContextValue
88
88
  }) => {
89
- const [state, setState] = React12.useState(client.getState());
89
+ const [state, setState] = React11.useState(client.getState());
90
90
  const { data: config } = reactQuery.useQuery({
91
91
  queryKey: ["melony-config", client.url],
92
92
  queryFn: () => client.getConfig(),
93
93
  staleTime: Infinity
94
94
  });
95
- React12.useEffect(() => {
95
+ React11.useEffect(() => {
96
96
  if (initialEvents && initialEvents.length > 0 && client.getState().events.length === 0) {
97
97
  client.reset(initialEvents);
98
98
  }
99
99
  }, [client, initialEvents]);
100
- React12.useEffect(() => {
100
+ React11.useEffect(() => {
101
101
  setState(client.getState());
102
102
  const unsubscribe = client.subscribe(setState);
103
103
  return () => {
104
104
  unsubscribe();
105
105
  };
106
106
  }, [client]);
107
- const reset = React12.useCallback(
107
+ const reset = React11.useCallback(
108
108
  (events) => client.reset(events),
109
109
  [client]
110
110
  );
111
- const dispatchClientAction = React12.useCallback(
111
+ const dispatchClientAction = React11.useCallback(
112
112
  async (event) => {
113
113
  if (!event.type.startsWith("client:")) return false;
114
114
  switch (event.type) {
@@ -144,7 +144,7 @@ var MelonyContextProviderInner = ({
144
144
  },
145
145
  [client, reset]
146
146
  );
147
- const sendEvent = React12.useCallback(
147
+ const sendEvent = React11.useCallback(
148
148
  async (event, options) => {
149
149
  const handled = await dispatchClientAction(event);
150
150
  if (handled) return;
@@ -155,7 +155,7 @@ var MelonyContextProviderInner = ({
155
155
  },
156
156
  [client, dispatchClientAction]
157
157
  );
158
- const value = React12.useMemo(
158
+ const value = React11.useMemo(
159
159
  () => ({
160
160
  ...state,
161
161
  messages: groupEventsToMessages(state.events),
@@ -166,7 +166,7 @@ var MelonyContextProviderInner = ({
166
166
  }),
167
167
  [state, sendEvent, reset, client, config]
168
168
  );
169
- React12.useEffect(() => {
169
+ React11.useEffect(() => {
170
170
  setContextValue(value);
171
171
  }, [value, setContextValue]);
172
172
  return /* @__PURE__ */ jsxRuntime.jsx(react.NuqsAdapter, { children });
@@ -177,7 +177,7 @@ var MelonyClientProvider = ({
177
177
  initialEvents,
178
178
  queryClient = defaultQueryClient
179
179
  }) => {
180
- const [contextValue, setContextValue] = React12.useState(void 0);
180
+ const [contextValue, setContextValue] = React11.useState(void 0);
181
181
  return /* @__PURE__ */ jsxRuntime.jsx(MelonyContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(
182
182
  MelonyContextProviderInner,
183
183
  {
@@ -188,49 +188,215 @@ var MelonyClientProvider = ({
188
188
  }
189
189
  ) }) });
190
190
  };
191
- var AuthContext = React12.createContext(
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
+ }
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] = React12.useState(null);
199
- const [isLoading, setIsLoading] = React12.useState(true);
200
- const fetchMe = React12.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
- React12.useEffect(() => {
213
- fetchMe();
214
- }, [fetchMe]);
215
- const login = React12.useCallback(() => {
389
+ });
390
+ const login = React11.useCallback(() => {
216
391
  service.login();
217
392
  }, [service]);
218
- const logout = React12.useCallback(async () => {
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,9 +415,17 @@ 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
- var ThreadContext = React12.createContext(
428
+ var ThreadContext = React11.createContext(
255
429
  void 0
256
430
  );
257
431
  var ThreadProvider = ({
@@ -260,7 +434,7 @@ var ThreadProvider = ({
260
434
  initialThreadId: providedInitialThreadId
261
435
  }) => {
262
436
  const queryClient = reactQuery.useQueryClient();
263
- const defaultInitialThreadId = React12.useMemo(() => client.generateId(), []);
437
+ const defaultInitialThreadId = React11.useMemo(() => client.generateId(), []);
264
438
  const initialThreadId = providedInitialThreadId || defaultInitialThreadId;
265
439
  const [activeThreadId, setActiveThreadId] = nuqs.useQueryState(
266
440
  "threadId",
@@ -301,22 +475,22 @@ var ThreadProvider = ({
301
475
  }
302
476
  }
303
477
  });
304
- const selectThread = React12.useCallback(
478
+ const selectThread = React11.useCallback(
305
479
  (threadId) => {
306
480
  setActiveThreadId(threadId);
307
481
  },
308
482
  [setActiveThreadId]
309
483
  );
310
- const createThread = React12.useCallback(async () => {
484
+ const createThread = React11.useCallback(async () => {
311
485
  return createMutation.mutateAsync();
312
486
  }, [createMutation]);
313
- const deleteThread = React12.useCallback(
487
+ const deleteThread = React11.useCallback(
314
488
  async (threadId) => {
315
489
  return deleteMutation.mutateAsync(threadId);
316
490
  },
317
491
  [deleteMutation]
318
492
  );
319
- const value = React12.useMemo(
493
+ const value = React11.useMemo(
320
494
  () => ({
321
495
  threads,
322
496
  activeThreadId,
@@ -346,11 +520,108 @@ var ThreadProvider = ({
346
520
  );
347
521
  return /* @__PURE__ */ jsxRuntime.jsx(ThreadContext.Provider, { value, children });
348
522
  };
349
- var ThemeContext = React12.createContext(void 0);
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
+ }
620
+ var ThemeContext = React11.createContext(void 0);
350
621
  function ThemeProvider({ children }) {
351
- const [theme, setThemeState] = React12.useState("system");
352
- const [resolvedTheme, setResolvedTheme] = React12.useState("light");
353
- React12.useEffect(() => {
622
+ const [theme, setThemeState] = React11.useState("system");
623
+ const [resolvedTheme, setResolvedTheme] = React11.useState("light");
624
+ React11.useEffect(() => {
354
625
  if (typeof window !== "undefined") {
355
626
  const stored = localStorage.getItem("theme");
356
627
  if (stored) {
@@ -358,7 +629,7 @@ function ThemeProvider({ children }) {
358
629
  }
359
630
  }
360
631
  }, []);
361
- React12.useEffect(() => {
632
+ React11.useEffect(() => {
362
633
  if (typeof window !== "undefined") {
363
634
  if (theme === "system") {
364
635
  const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
@@ -373,7 +644,7 @@ function ThemeProvider({ children }) {
373
644
  }
374
645
  }
375
646
  }, [theme]);
376
- React12.useEffect(() => {
647
+ React11.useEffect(() => {
377
648
  if (typeof window !== "undefined") {
378
649
  const root = document.documentElement;
379
650
  if (resolvedTheme === "dark") {
@@ -392,21 +663,21 @@ function ThemeProvider({ children }) {
392
663
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: { theme, setTheme, resolvedTheme }, children });
393
664
  }
394
665
  function useTheme() {
395
- const context = React12.useContext(ThemeContext);
666
+ const context = React11.useContext(ThemeContext);
396
667
  if (context === void 0) {
397
668
  throw new Error("useTheme must be used within a ThemeProvider");
398
669
  }
399
670
  return context;
400
671
  }
401
672
  var useMelony = (options) => {
402
- const context = React12.useContext(MelonyContext);
673
+ const context = React11.useContext(MelonyContext);
403
674
  if (context === void 0) {
404
675
  throw new Error("useMelony must be used within a MelonyClientProvider");
405
676
  }
406
677
  const { client, reset } = context;
407
678
  const { initialEvents } = options || {};
408
- const prevInitialEventsRef = React12.useRef(void 0);
409
- React12.useEffect(() => {
679
+ const prevInitialEventsRef = React11.useRef(void 0);
680
+ React11.useEffect(() => {
410
681
  const currentSerialized = initialEvents ? JSON.stringify(initialEvents) : void 0;
411
682
  if (currentSerialized !== prevInitialEventsRef.current) {
412
683
  if (initialEvents) {
@@ -419,108 +690,13 @@ var useMelony = (options) => {
419
690
  }, [client, initialEvents, reset]);
420
691
  return context;
421
692
  };
422
- var useAuth = () => {
423
- const context = React12.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
- const context = React12.useContext(ThreadContext);
694
+ const context = React11.useContext(ThreadContext);
431
695
  if (context === void 0) {
432
696
  throw new Error("useThreads must be used within a ThreadProvider");
433
697
  }
434
698
  return context;
435
699
  };
436
- function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
437
- const [screenSize, setScreenSize] = React12.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
- React12.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",
@@ -706,11 +882,26 @@ function Composer({
706
882
  const accept = fileAttachments?.accept;
707
883
  const maxFiles = fileAttachments?.maxFiles ?? 10;
708
884
  const maxFileSize = fileAttachments?.maxFileSize ?? 10 * 1024 * 1024;
709
- const [selectedOptions, setSelectedOptions] = React12__namespace.default.useState(
885
+ const [selectedOptions, setSelectedOptions] = React11__namespace.default.useState(
710
886
  () => new Set(defaultSelectedIds)
711
887
  );
712
- const [attachedFiles, setAttachedFiles] = React12__namespace.default.useState([]);
713
- const fileInputRef = React12__namespace.default.useRef(null);
888
+ const [attachedFiles, setAttachedFiles] = React11__namespace.default.useState([]);
889
+ const [previews, setPreviews] = React11__namespace.default.useState([]);
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(
@@ -1501,9 +1652,9 @@ var Image = ({
1501
1652
  className,
1502
1653
  style
1503
1654
  }) => {
1504
- const [hasError, setHasError] = React12.useState(false);
1505
- const [isLoading, setIsLoading] = React12.useState(true);
1506
- const [open, setOpen] = React12.useState(false);
1655
+ const [hasError, setHasError] = React11.useState(false);
1656
+ const [isLoading, setIsLoading] = React11.useState(true);
1657
+ const [open, setOpen] = React11.useState(false);
1507
1658
  const sizes = {
1508
1659
  sm: "h-11",
1509
1660
  md: "h-22",
@@ -1662,7 +1813,7 @@ var Chart = ({
1662
1813
  className,
1663
1814
  style
1664
1815
  }) => {
1665
- const [tooltip, setTooltip] = React12.useState(null);
1816
+ const [tooltip, setTooltip] = React11.useState(null);
1666
1817
  if (!Array.isArray(data)) {
1667
1818
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-destructive border border-destructive/20 rounded-md bg-destructive/5", children: "Error: Chart data must be an array" });
1668
1819
  }
@@ -2408,7 +2559,7 @@ var Button2 = ({
2408
2559
  };
2409
2560
  var Form = ({ children, onSubmitAction, className, style }) => {
2410
2561
  const { sendEvent } = useMelony();
2411
- const [isSubmitted, setIsSubmitted] = React12.useState(false);
2562
+ const [isSubmitted, setIsSubmitted] = React11.useState(false);
2412
2563
  const handleSubmit = (e) => {
2413
2564
  e.preventDefault();
2414
2565
  if (isSubmitted) return;
@@ -2555,7 +2706,7 @@ function MessageBubble({ message }) {
2555
2706
  );
2556
2707
  }
2557
2708
  function LoadingIndicator({ status }) {
2558
- const [isExpanded, setIsExpanded] = React12.useState(false);
2709
+ const [isExpanded, setIsExpanded] = React11.useState(false);
2559
2710
  const message = status?.message || "Processing...";
2560
2711
  const details = status?.details;
2561
2712
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
@@ -2587,7 +2738,7 @@ function MessageList({
2587
2738
  if (messages.length === 0) {
2588
2739
  return null;
2589
2740
  }
2590
- const isTextStreaming = React12.useMemo(() => {
2741
+ const isTextStreaming = React11.useMemo(() => {
2591
2742
  if (messages.length === 0 || !isLoading) return false;
2592
2743
  const lastMessage = messages[messages.length - 1];
2593
2744
  return lastMessage.content.some((event) => event.type === "text-delta");
@@ -2615,7 +2766,7 @@ function Thread({
2615
2766
  const starterPrompts = localStarterPrompts ?? config?.starterPrompts;
2616
2767
  const options = localOptions ?? config?.options;
2617
2768
  const fileAttachments = config?.fileAttachments;
2618
- const allDefaultSelectedIds = React12.useMemo(() => {
2769
+ const allDefaultSelectedIds = React11.useMemo(() => {
2619
2770
  const defaultSelectedIdsFromOptions = options?.flatMap((group) => group.defaultSelectedIds ?? []) ?? [];
2620
2771
  return [
2621
2772
  .../* @__PURE__ */ new Set([
@@ -2624,9 +2775,9 @@ function Thread({
2624
2775
  ])
2625
2776
  ];
2626
2777
  }, [options, defaultSelectedIds]);
2627
- const [input, setInput] = React12.useState("");
2628
- const messagesEndRef = React12.useRef(null);
2629
- React12.useEffect(() => {
2778
+ const [input, setInput] = React11.useState("");
2779
+ const messagesEndRef = React11.useRef(null);
2780
+ React11.useEffect(() => {
2630
2781
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
2631
2782
  }, [messages]);
2632
2783
  const handleSubmit = async (state, overrideInput) => {
@@ -2741,15 +2892,8 @@ 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();
2752
- const sortedThreads = React12__namespace.useMemo(() => {
2895
+ const { threads, activeThreadId, selectThread, deleteThread, isLoading } = useThreads();
2896
+ const sortedThreads = React11__namespace.useMemo(() => {
2753
2897
  return [...threads].sort((a, b) => {
2754
2898
  const dateA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
2755
2899
  const dateB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
@@ -2769,84 +2913,62 @@ var ThreadList = ({
2769
2913
  console.error("Failed to delete thread:", error);
2770
2914
  }
2771
2915
  };
2772
- const handleNewThread = async () => {
2773
- try {
2774
- await createThread();
2775
- } catch (error) {
2776
- console.error("Failed to create thread:", error);
2777
- }
2778
- };
2779
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col h-full", className), children: [
2780
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
2781
- Button,
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: [
2917
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconMessage, { className: "size-8 mx-auto opacity-50" }),
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) => {
2920
+ const isActive = thread.id === activeThreadId;
2921
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2922
+ "div",
2782
2923
  {
2783
- variant: "outline",
2784
- className: "w-full justify-start gap-2 h-9 px-3 border-dashed hover:border-solid transition-all",
2785
- onClick: handleNewThread,
2924
+ onClick: () => handleThreadClick(thread.id),
2925
+ className: cn(
2926
+ "group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
2927
+ isActive ? "bg-muted text-foreground" : "hover:bg-muted/50 text-muted-foreground hover:text-foreground"
2928
+ ),
2786
2929
  children: [
2787
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "size-4" }),
2788
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "New chat" })
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
+ ] }) })
2789
2965
  ]
2790
- }
2791
- ) }),
2792
- /* @__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: [
2793
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconMessage, { className: "size-8 mx-auto opacity-50" }),
2794
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No threads yet" }),
2795
- /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
2796
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 space-y-1", children: sortedThreads.map((thread) => {
2797
- const isActive = thread.id === activeThreadId;
2798
- return /* @__PURE__ */ jsxRuntime.jsxs(
2799
- "div",
2800
- {
2801
- onClick: () => handleThreadClick(thread.id),
2802
- className: cn(
2803
- "group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
2804
- isActive ? "bg-muted text-foreground" : "hover:bg-muted/50 text-muted-foreground hover:text-foreground"
2805
- ),
2806
- children: [
2807
- /* @__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)}` }) }),
2808
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 flex items-center opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
2809
- /* @__PURE__ */ jsxRuntime.jsx(
2810
- DropdownMenuTrigger,
2811
- {
2812
- render: (props) => /* @__PURE__ */ jsxRuntime.jsx(
2813
- Button,
2814
- {
2815
- variant: "ghost",
2816
- size: "icon-xs",
2817
- ...props,
2818
- onClick: (e) => {
2819
- e.stopPropagation();
2820
- props.onClick?.(e);
2821
- },
2822
- children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconDotsVertical, { className: "size-3.5" })
2823
- }
2824
- )
2825
- }
2826
- ),
2827
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "start", className: "w-32", children: /* @__PURE__ */ jsxRuntime.jsxs(
2828
- DropdownMenuItem,
2829
- {
2830
- variant: "destructive",
2831
- onClick: (e) => {
2832
- e.stopPropagation();
2833
- handleDelete(thread.id);
2834
- },
2835
- children: [
2836
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconTrash, { className: "size-4 mr-2" }),
2837
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delete" })
2838
- ]
2839
- }
2840
- ) })
2841
- ] }) })
2842
- ]
2843
- },
2844
- thread.id
2845
- );
2846
- }) }) })
2847
- ] });
2966
+ },
2967
+ thread.id
2968
+ );
2969
+ }) }) }) });
2848
2970
  };
2849
- function ChatPopup({
2971
+ function PopupChat({
2850
2972
  title = "Chat",
2851
2973
  placeholder = "Message the AI",
2852
2974
  starterPrompts,
@@ -2855,8 +2977,8 @@ function ChatPopup({
2855
2977
  headerProps,
2856
2978
  defaultSelectedIds
2857
2979
  }) {
2858
- const [isOpen, setIsOpen] = React12.useState(defaultOpen);
2859
- const [view, setView] = React12.useState("chat");
2980
+ const [isOpen, setIsOpen] = React11.useState(defaultOpen);
2981
+ const [view, setView] = React11.useState("chat");
2860
2982
  const { createThread } = useThreads();
2861
2983
  const handleNewChat = async () => {
2862
2984
  try {
@@ -2950,266 +3072,45 @@ function ChatPopup({
2950
3072
  )
2951
3073
  ] });
2952
3074
  }
2953
- function ChatSidebar({
2954
- title = "Chat",
2955
- placeholder = "Message the AI",
2956
- starterPrompts,
2957
- options,
2958
- className,
2959
- headerProps,
2960
- defaultSelectedIds
2961
- }) {
2962
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col h-full border-r bg-background w-80", className), children: [
2963
- /* @__PURE__ */ jsxRuntime.jsx(ChatHeader, { title, ...headerProps }),
2964
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
2965
- Thread,
2966
- {
2967
- placeholder,
2968
- starterPrompts,
2969
- options,
2970
- className: "h-full",
2971
- defaultSelectedIds
2972
- }
2973
- ) })
2974
- ] });
2975
- }
2976
- var ChatSidebarContext = React12.createContext(
2977
- void 0
2978
- );
2979
- function useChatSidebar() {
2980
- const context = React12.useContext(ChatSidebarContext);
2981
- if (context === void 0) {
2982
- throw new Error("useChatSidebar must be used within a ChatSidebarProvider");
2983
- }
2984
- return context;
2985
- }
2986
- function WelcomeScreen({
2987
- title = "Welcome to Melony",
2988
- description = "The most powerful AI agent framework for building modern applications. Connect your tools, build your brain, and ship faster.",
2989
- features = [
2990
- {
2991
- title: "Context Aware",
2992
- description: "Built-in state management for complex LLM flows."
2993
- },
2994
- {
2995
- title: "Extensible",
2996
- description: "Plugin architecture for easy integrations."
2997
- },
2998
- {
2999
- title: "Real-time",
3000
- description: "Streaming responses and live state updates."
3001
- },
3002
- {
3003
- title: "Tool-ready",
3004
- description: "Ready-to-use actions for common tasks."
3005
- }
3006
- ],
3007
- className,
3008
- onLoginClick,
3009
- termsUrl = "#",
3010
- privacyUrl = "#",
3011
- imageUrl,
3012
- imageAlt = "Product screenshot"
3013
- }) {
3014
- const { login, isLoading } = useAuth();
3015
- const handleLogin = () => {
3016
- if (onLoginClick) {
3017
- onLoginClick();
3018
- } else {
3019
- login();
3020
- }
3021
- };
3022
- return /* @__PURE__ */ jsxRuntime.jsxs(
3075
+ function Sidebar({ side, children, className }) {
3076
+ const { leftCollapsed, rightCollapsed } = useSidebar();
3077
+ const collapsed = side === "left" ? leftCollapsed : rightCollapsed;
3078
+ return /* @__PURE__ */ jsxRuntime.jsx(
3023
3079
  "div",
3024
3080
  {
3025
3081
  className: cn(
3026
- "flex min-h-[600px] h-full w-full flex-col md:flex-row bg-background overflow-hidden",
3027
- className
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
3028
3086
  ),
3029
- children: [
3030
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col bg-sidebar text-foreground relative overflow-hidden", children: [
3031
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-24 -left-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
3032
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -bottom-24 -right-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
3033
- /* @__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", children: [
3034
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mb-6 text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl text-foreground", children: title }),
3035
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-12 text-lg text-muted-foreground md:text-xl leading-relaxed", children: description }),
3036
- imageUrl && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-12 relative group", children: [
3037
- /* @__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" }),
3038
- /* @__PURE__ */ jsxRuntime.jsx(
3039
- "img",
3040
- {
3041
- src: imageUrl,
3042
- alt: imageAlt,
3043
- className: "relative rounded-xl border border-border/50 shadow-2xl transition-transform duration-500 hover:scale-[1.02] w-full"
3044
- }
3045
- )
3046
- ] }),
3047
- /* @__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: [
3048
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-bold text-lg text-foreground", children: feature.title }),
3049
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: feature.description })
3050
- ] }, i)) })
3051
- ] }) })
3052
- ] }),
3053
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col items-center justify-center 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", children: [
3054
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 text-center md:text-left", children: [
3055
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-bold tracking-tight text-foreground", children: "Get Started" }),
3056
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-lg", children: "Sign in to your account to continue" })
3057
- ] }),
3058
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3059
- /* @__PURE__ */ jsxRuntime.jsxs(
3060
- Button,
3061
- {
3062
- size: "lg",
3063
- variant: "outline",
3064
- 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",
3065
- onClick: handleLogin,
3066
- disabled: isLoading,
3067
- children: [
3068
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconBrandGoogle, { className: "size-6" }),
3069
- isLoading ? "Signing in..." : "Continue with Google"
3070
- ]
3071
- }
3072
- ),
3073
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative py-4", children: [
3074
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-full border-t border-border" }) }),
3075
- /* @__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" }) })
3076
- ] })
3077
- ] }),
3078
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground leading-relaxed text-center md:text-left", children: [
3079
- "By continuing, you agree to our ",
3080
- /* @__PURE__ */ jsxRuntime.jsx("br", { className: "hidden md:block" }),
3081
- /* @__PURE__ */ jsxRuntime.jsx(
3082
- "a",
3083
- {
3084
- href: termsUrl,
3085
- target: "_blank",
3086
- rel: "noopener noreferrer",
3087
- className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
3088
- children: "Terms of Service"
3089
- }
3090
- ),
3091
- " ",
3092
- "and",
3093
- " ",
3094
- /* @__PURE__ */ jsxRuntime.jsx(
3095
- "a",
3096
- {
3097
- href: privacyUrl,
3098
- target: "_blank",
3099
- rel: "noopener noreferrer",
3100
- className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
3101
- children: "Privacy Policy"
3102
- }
3103
- ),
3104
- "."
3105
- ] })
3106
- ] }) })
3107
- ]
3087
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children })
3108
3088
  }
3109
3089
  );
3110
3090
  }
3111
- function ChatFull({
3091
+ function FullChat({
3112
3092
  title = "Chat",
3113
3093
  placeholder,
3114
3094
  starterPrompts,
3115
3095
  options,
3116
3096
  className,
3117
3097
  headerProps,
3118
- leftSidebar,
3119
- rightSidebar,
3120
- leftSidebarClassName,
3121
- rightSidebarClassName,
3122
3098
  autoFocus = false,
3123
- defaultSelectedIds,
3124
- showWelcomeScreen = false,
3125
- welcomeScreenProps
3099
+ defaultSelectedIds
3126
3100
  }) {
3127
- const { isMobile, isTablet } = useScreenSize();
3128
- const { isAuthenticated, isLoading } = useAuth();
3129
- const isSmallScreen = isMobile || isTablet;
3130
- const [internalLeftCollapsed, setInternalLeftCollapsed] = React12.useState(() => {
3131
- if (typeof window !== "undefined") {
3132
- return window.innerWidth < 1024;
3133
- }
3134
- return false;
3135
- });
3136
- const [internalRightCollapsed, setInternalRightCollapsed] = React12.useState(() => {
3137
- if (typeof window !== "undefined") {
3138
- return window.innerWidth < 1024;
3139
- }
3140
- return false;
3141
- });
3142
- React12.useEffect(() => {
3143
- if (isSmallScreen) {
3144
- setInternalLeftCollapsed(true);
3145
- setInternalRightCollapsed(true);
3146
- }
3147
- }, [isSmallScreen]);
3148
- const leftCollapsed = internalLeftCollapsed;
3149
- const rightCollapsed = internalRightCollapsed;
3150
- const handleLeftToggle = React12.useCallback((collapsed) => {
3151
- setInternalLeftCollapsed(collapsed);
3152
- }, []);
3153
- const handleRightToggle = React12.useCallback((collapsed) => {
3154
- setInternalRightCollapsed(collapsed);
3155
- }, []);
3156
- const contextValue = React12.useMemo(
3157
- () => ({
3158
- leftCollapsed,
3159
- rightCollapsed,
3160
- setLeftCollapsed: handleLeftToggle,
3161
- setRightCollapsed: handleRightToggle,
3162
- leftCollapsible: true,
3163
- rightCollapsible: true
3164
- }),
3165
- [leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
3166
- );
3167
- if (showWelcomeScreen && !isAuthenticated && !isLoading) {
3168
- return /* @__PURE__ */ jsxRuntime.jsx(WelcomeScreen, { ...welcomeScreenProps });
3169
- }
3170
- return /* @__PURE__ */ jsxRuntime.jsx(ChatSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
3171
- "div",
3172
- {
3173
- className: cn("flex flex-col h-full w-full bg-background", className),
3174
- children: [
3175
- title && /* @__PURE__ */ jsxRuntime.jsx(ChatHeader, { title, ...headerProps }),
3176
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden flex relative", children: [
3177
- leftSidebar && /* @__PURE__ */ jsxRuntime.jsx(
3178
- "div",
3179
- {
3180
- className: cn(
3181
- "flex-shrink-0 border-r border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
3182
- leftCollapsed ? "w-0 border-r-0 min-w-0" : "",
3183
- !leftCollapsed && leftSidebarClassName
3184
- ),
3185
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: leftSidebar })
3186
- }
3187
- ),
3188
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
3189
- Thread,
3190
- {
3191
- placeholder,
3192
- starterPrompts,
3193
- options,
3194
- autoFocus,
3195
- defaultSelectedIds
3196
- }
3197
- ) }),
3198
- rightSidebar && /* @__PURE__ */ jsxRuntime.jsx(
3199
- "div",
3200
- {
3201
- className: cn(
3202
- "flex-shrink-0 border-l border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
3203
- rightCollapsed ? "w-0 border-l-0 min-w-0" : "",
3204
- !rightCollapsed && rightSidebarClassName
3205
- ),
3206
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: rightSidebar })
3207
- }
3208
- )
3209
- ] })
3210
- ]
3211
- }
3212
- ) });
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(
3104
+ Thread,
3105
+ {
3106
+ placeholder,
3107
+ starterPrompts,
3108
+ options,
3109
+ autoFocus,
3110
+ defaultSelectedIds
3111
+ }
3112
+ ) }) })
3113
+ ] });
3213
3114
  }
3214
3115
  function SidebarToggle({ side, className }) {
3215
3116
  const {
@@ -3219,13 +3120,14 @@ function SidebarToggle({ side, className }) {
3219
3120
  setRightCollapsed,
3220
3121
  leftCollapsible,
3221
3122
  rightCollapsible
3222
- } = useChatSidebar();
3123
+ } = useSidebar();
3223
3124
  if (side === "left") {
3224
3125
  if (!leftCollapsible) return null;
3225
3126
  return /* @__PURE__ */ jsxRuntime.jsx(
3226
3127
  Button,
3227
3128
  {
3228
3129
  variant: "ghost",
3130
+ size: "icon",
3229
3131
  onClick: () => setLeftCollapsed(!leftCollapsed),
3230
3132
  "aria-label": leftCollapsed ? "Expand left sidebar" : "Collapse left sidebar",
3231
3133
  className: cn("", className),
@@ -3239,6 +3141,7 @@ function SidebarToggle({ side, className }) {
3239
3141
  Button,
3240
3142
  {
3241
3143
  variant: "ghost",
3144
+ size: "icon",
3242
3145
  onClick: () => setRightCollapsed(!rightCollapsed),
3243
3146
  "aria-label": rightCollapsed ? "Expand right sidebar" : "Collapse right sidebar",
3244
3147
  className: cn("", className),
@@ -3248,11 +3151,11 @@ function SidebarToggle({ side, className }) {
3248
3151
  }
3249
3152
  return null;
3250
3153
  }
3251
- var PopoverContext = React12__namespace.createContext(
3154
+ var PopoverContext = React11__namespace.createContext(
3252
3155
  void 0
3253
3156
  );
3254
3157
  function usePopoverContext() {
3255
- const context = React12__namespace.useContext(PopoverContext);
3158
+ const context = React11__namespace.useContext(PopoverContext);
3256
3159
  if (!context) {
3257
3160
  throw new Error("Popover components must be used within a Popover");
3258
3161
  }
@@ -3264,10 +3167,10 @@ function Popover({
3264
3167
  open: controlledOpen,
3265
3168
  onOpenChange
3266
3169
  }) {
3267
- const [internalOpen, setInternalOpen] = React12__namespace.useState(defaultOpen);
3268
- const triggerRef = React12__namespace.useRef(null);
3170
+ const [internalOpen, setInternalOpen] = React11__namespace.useState(defaultOpen);
3171
+ const triggerRef = React11__namespace.useRef(null);
3269
3172
  const open = controlledOpen ?? internalOpen;
3270
- const setOpen = React12__namespace.useCallback(
3173
+ const setOpen = React11__namespace.useCallback(
3271
3174
  (newOpen) => {
3272
3175
  if (controlledOpen === void 0) {
3273
3176
  setInternalOpen(newOpen);
@@ -3276,7 +3179,7 @@ function Popover({
3276
3179
  },
3277
3180
  [controlledOpen, onOpenChange]
3278
3181
  );
3279
- const value = React12__namespace.useMemo(
3182
+ const value = React11__namespace.useMemo(
3280
3183
  () => ({
3281
3184
  open,
3282
3185
  setOpen,
@@ -3286,15 +3189,15 @@ function Popover({
3286
3189
  );
3287
3190
  return /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value, children });
3288
3191
  }
3289
- var PopoverTrigger = React12__namespace.forwardRef(
3192
+ var PopoverTrigger = React11__namespace.forwardRef(
3290
3193
  ({ asChild, className, children, ...props }, ref) => {
3291
3194
  const { setOpen, triggerRef } = usePopoverContext();
3292
3195
  const handleClick = (e) => {
3293
3196
  setOpen(true);
3294
3197
  props.onClick?.(e);
3295
3198
  };
3296
- if (asChild && React12__namespace.isValidElement(children)) {
3297
- return React12__namespace.cloneElement(children, {
3199
+ if (asChild && React11__namespace.isValidElement(children)) {
3200
+ return React11__namespace.cloneElement(children, {
3298
3201
  ref: (node) => {
3299
3202
  triggerRef.current = node;
3300
3203
  if (typeof children.ref === "function") {
@@ -3326,7 +3229,7 @@ var PopoverTrigger = React12__namespace.forwardRef(
3326
3229
  }
3327
3230
  );
3328
3231
  PopoverTrigger.displayName = "PopoverTrigger";
3329
- var PopoverContent = React12__namespace.forwardRef(
3232
+ var PopoverContent = React11__namespace.forwardRef(
3330
3233
  ({
3331
3234
  className,
3332
3235
  side = "bottom",
@@ -3337,9 +3240,9 @@ var PopoverContent = React12__namespace.forwardRef(
3337
3240
  ...props
3338
3241
  }, ref) => {
3339
3242
  const { open, setOpen, triggerRef } = usePopoverContext();
3340
- const [position, setPosition] = React12__namespace.useState({ top: 0, left: 0 });
3341
- const contentRef = React12__namespace.useRef(null);
3342
- React12__namespace.useEffect(() => {
3243
+ const [position, setPosition] = React11__namespace.useState({ top: 0, left: 0 });
3244
+ const contentRef = React11__namespace.useRef(null);
3245
+ React11__namespace.useEffect(() => {
3343
3246
  if (!open || !triggerRef.current) return;
3344
3247
  const updatePosition = () => {
3345
3248
  if (!triggerRef.current || !contentRef.current) return;
@@ -3400,7 +3303,7 @@ var PopoverContent = React12__namespace.forwardRef(
3400
3303
  window.removeEventListener("scroll", updatePosition, true);
3401
3304
  };
3402
3305
  }, [open, side, align, sideOffset, alignOffset, triggerRef]);
3403
- React12__namespace.useEffect(() => {
3306
+ React11__namespace.useEffect(() => {
3404
3307
  if (!open) return;
3405
3308
  const handleClickOutside = (event) => {
3406
3309
  if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
@@ -3456,7 +3359,7 @@ var ThreadPopover = ({
3456
3359
  emptyState,
3457
3360
  onThreadSelect
3458
3361
  }) => {
3459
- const [isOpen, setIsOpen] = React12__namespace.useState(false);
3362
+ const [isOpen, setIsOpen] = React11__namespace.useState(false);
3460
3363
  reactHotkeysHook.useHotkeys(
3461
3364
  "h",
3462
3365
  (e) => {
@@ -3506,12 +3409,12 @@ var ThreadPopover = ({
3506
3409
  var CreateThreadButton = ({
3507
3410
  className,
3508
3411
  variant = "ghost",
3509
- size = "icon",
3412
+ size = "default",
3510
3413
  children,
3511
3414
  onThreadCreated
3512
3415
  }) => {
3513
3416
  const { createThread } = useThreads();
3514
- const [isCreating, setIsCreating] = React12__namespace.useState(false);
3417
+ const [isCreating, setIsCreating] = React11__namespace.useState(false);
3515
3418
  const handleCreateThread = async () => {
3516
3419
  if (isCreating) return;
3517
3420
  try {
@@ -3537,7 +3440,7 @@ var CreateThreadButton = ({
3537
3440
  // Don't trigger in contenteditable elements
3538
3441
  }
3539
3442
  );
3540
- return /* @__PURE__ */ jsxRuntime.jsx(
3443
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3541
3444
  Button,
3542
3445
  {
3543
3446
  variant,
@@ -3545,7 +3448,10 @@ var CreateThreadButton = ({
3545
3448
  onClick: handleCreateThread,
3546
3449
  disabled: isCreating,
3547
3450
  className: cn(className),
3548
- children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "size-4" })
3451
+ children: [
3452
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "size-4" }),
3453
+ "New chat"
3454
+ ]
3549
3455
  }
3550
3456
  );
3551
3457
  };
@@ -3637,10 +3543,10 @@ var AccountDialog = ({
3637
3543
  size
3638
3544
  }) => {
3639
3545
  const { isLoading, isAuthenticated, user, login, logout } = useAuth();
3640
- const [open, setOpen] = React12__namespace.useState(false);
3641
- const [accountInfoOpen, setAccountInfoOpen] = React12__namespace.useState(false);
3642
- const [error, setError] = React12__namespace.useState(null);
3643
- const initials = React12__namespace.useMemo(() => {
3546
+ const [open, setOpen] = React11__namespace.useState(false);
3547
+ const [accountInfoOpen, setAccountInfoOpen] = React11__namespace.useState(false);
3548
+ const [error, setError] = React11__namespace.useState(null);
3549
+ const initials = React11__namespace.useMemo(() => {
3644
3550
  const name = user?.displayName || user?.name;
3645
3551
  if (!name) return "";
3646
3552
  return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
@@ -3739,17 +3645,14 @@ var AccountDialog = ({
3739
3645
  ] });
3740
3646
  }
3741
3647
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3742
- /* @__PURE__ */ jsxRuntime.jsxs(
3648
+ /* @__PURE__ */ jsxRuntime.jsx(
3743
3649
  Button,
3744
3650
  {
3745
3651
  variant,
3746
3652
  size,
3747
3653
  onClick: () => setOpen(true),
3748
3654
  className,
3749
- children: [
3750
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconBrandGoogle, { className: "mr-2 size-4" }),
3751
- "Sign in with Google"
3752
- ]
3655
+ children: "Sign in"
3753
3656
  }
3754
3657
  ),
3755
3658
  /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "sm:max-w-md", children: [
@@ -3821,17 +3724,14 @@ exports.Box = Box;
3821
3724
  exports.Button = Button2;
3822
3725
  exports.Card = Card2;
3823
3726
  exports.Chart = Chart;
3824
- exports.ChatFull = ChatFull;
3825
3727
  exports.ChatHeader = ChatHeader;
3826
- exports.ChatPopup = ChatPopup;
3827
- exports.ChatSidebar = ChatSidebar;
3828
- exports.ChatSidebarContext = ChatSidebarContext;
3829
3728
  exports.Checkbox = Checkbox;
3830
3729
  exports.Col = Col;
3831
3730
  exports.Composer = Composer;
3832
3731
  exports.CreateThreadButton = CreateThreadButton;
3833
3732
  exports.Divider = Divider;
3834
3733
  exports.Form = Form;
3734
+ exports.FullChat = FullChat;
3835
3735
  exports.Heading = Heading;
3836
3736
  exports.Image = Image;
3837
3737
  exports.Input = Input2;
@@ -3840,9 +3740,13 @@ exports.List = List;
3840
3740
  exports.ListItem = ListItem;
3841
3741
  exports.MelonyClientProvider = MelonyClientProvider;
3842
3742
  exports.MelonyContext = MelonyContext;
3743
+ exports.PopupChat = PopupChat;
3843
3744
  exports.RadioGroup = RadioGroup;
3844
3745
  exports.Row = Row;
3845
3746
  exports.Select = Select2;
3747
+ exports.Sidebar = Sidebar;
3748
+ exports.SidebarContext = SidebarContext;
3749
+ exports.SidebarProvider = SidebarProvider;
3846
3750
  exports.SidebarToggle = SidebarToggle;
3847
3751
  exports.Spacer = Spacer;
3848
3752
  exports.Text = Text;
@@ -3858,9 +3762,9 @@ exports.UIRenderer = UIRenderer;
3858
3762
  exports.WelcomeScreen = WelcomeScreen;
3859
3763
  exports.groupEventsToMessages = groupEventsToMessages;
3860
3764
  exports.useAuth = useAuth;
3861
- exports.useChatSidebar = useChatSidebar;
3862
3765
  exports.useMelony = useMelony;
3863
3766
  exports.useScreenSize = useScreenSize;
3767
+ exports.useSidebar = useSidebar;
3864
3768
  exports.useTheme = useTheme;
3865
3769
  exports.useThreads = useThreads;
3866
3770
  //# sourceMappingURL=index.cjs.map