@melony/react 0.1.28 → 0.1.31

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,23 +4,22 @@ 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 button = require('@base-ui/react/button');
8
- var classVarianceAuthority = require('class-variance-authority');
9
7
  var clsx = require('clsx');
10
8
  var tailwindMerge = require('tailwind-merge');
9
+ var dialog = require('@base-ui/react/dialog');
10
+ var button = require('@base-ui/react/button');
11
+ var classVarianceAuthority = require('class-variance-authority');
11
12
  var ICONS = require('@tabler/icons-react');
13
+ var menu = require('@base-ui/react/menu');
14
+ var separator = require('@base-ui/react/separator');
12
15
  var client = require('melony/client');
13
16
  var nuqs = require('nuqs');
14
17
  var mergeProps = require('@base-ui/react/merge-props');
15
18
  var useRender = require('@base-ui/react/use-render');
16
- var menu = require('@base-ui/react/menu');
17
- var separator = require('@base-ui/react/separator');
18
- var dialog = require('@base-ui/react/dialog');
19
19
  var input = require('@base-ui/react/input');
20
20
  var select = require('@base-ui/react/select');
21
21
  var reactDom = require('react-dom');
22
22
  var reactHotkeysHook = require('react-hotkeys-hook');
23
- var alertDialog = require('@base-ui/react/alert-dialog');
24
23
 
25
24
  function _interopNamespace(e) {
26
25
  if (e && e.__esModule) return e;
@@ -145,10 +144,10 @@ var MelonyContextProviderInner = ({
145
144
  [client, reset]
146
145
  );
147
146
  const sendEvent = React11.useCallback(
148
- async (event, options) => {
147
+ async (event) => {
149
148
  const handled = await dispatchClientAction(event);
150
149
  if (handled) return;
151
- const generator = client.sendEvent(event, options);
150
+ const generator = client.sendEvent(event);
152
151
  for await (const incomingEvent of generator) {
153
152
  await dispatchClientAction(incomingEvent);
154
153
  }
@@ -188,9 +187,121 @@ var MelonyProvider = ({
188
187
  }
189
188
  ) }) });
190
189
  };
190
+ var useAuth = () => {
191
+ const context = React11.useContext(AuthContext);
192
+ if (context === void 0) {
193
+ throw new Error("useAuth must be used within an AuthProvider");
194
+ }
195
+ return context;
196
+ };
191
197
  function cn(...inputs) {
192
198
  return tailwindMerge.twMerge(clsx.clsx(inputs));
193
199
  }
200
+ function Dialog({ ...props }) {
201
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Root, { "data-slot": "dialog", ...props });
202
+ }
203
+ function DialogTrigger({ ...props }) {
204
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Trigger, { "data-slot": "dialog-trigger", ...props });
205
+ }
206
+ function DialogPortal({ ...props }) {
207
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Portal, { "data-slot": "dialog-portal", ...props });
208
+ }
209
+ function DialogOverlay({
210
+ className,
211
+ ...props
212
+ }) {
213
+ return /* @__PURE__ */ jsxRuntime.jsx(
214
+ dialog.Dialog.Backdrop,
215
+ {
216
+ "data-slot": "dialog-overlay",
217
+ className: cn(
218
+ "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-200 supports-backdrop-filter:backdrop-blur-sm fixed inset-0 isolate z-50",
219
+ className
220
+ ),
221
+ ...props
222
+ }
223
+ );
224
+ }
225
+ function DialogContent({
226
+ className,
227
+ ...props
228
+ }) {
229
+ return /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
230
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
231
+ /* @__PURE__ */ jsxRuntime.jsx(
232
+ dialog.Dialog.Popup,
233
+ {
234
+ "data-slot": "dialog-content",
235
+ className: cn(
236
+ "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg outline-none",
237
+ className
238
+ ),
239
+ ...props
240
+ }
241
+ )
242
+ ] });
243
+ }
244
+ function DialogClose({
245
+ className,
246
+ ...props
247
+ }) {
248
+ return /* @__PURE__ */ jsxRuntime.jsx(
249
+ dialog.Dialog.Close,
250
+ {
251
+ "data-slot": "dialog-close",
252
+ className: cn(
253
+ "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
254
+ className
255
+ ),
256
+ ...props
257
+ }
258
+ );
259
+ }
260
+ function DialogHeader({
261
+ className,
262
+ ...props
263
+ }) {
264
+ return /* @__PURE__ */ jsxRuntime.jsx(
265
+ "div",
266
+ {
267
+ "data-slot": "dialog-header",
268
+ className: cn(
269
+ "flex flex-col space-y-1.5 text-center sm:text-left",
270
+ className
271
+ ),
272
+ ...props
273
+ }
274
+ );
275
+ }
276
+ function DialogTitle({
277
+ className,
278
+ ...props
279
+ }) {
280
+ return /* @__PURE__ */ jsxRuntime.jsx(
281
+ dialog.Dialog.Title,
282
+ {
283
+ "data-slot": "dialog-title",
284
+ className: cn(
285
+ "text-lg font-semibold leading-none tracking-tight",
286
+ className
287
+ ),
288
+ ...props
289
+ }
290
+ );
291
+ }
292
+ function DialogDescription({
293
+ className,
294
+ ...props
295
+ }) {
296
+ return /* @__PURE__ */ jsxRuntime.jsx(
297
+ dialog.Dialog.Description,
298
+ {
299
+ "data-slot": "dialog-description",
300
+ className: cn("text-sm text-muted-foreground", className),
301
+ ...props
302
+ }
303
+ );
304
+ }
194
305
  var buttonVariants = classVarianceAuthority.cva(
195
306
  "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
307
  {
@@ -235,12 +346,287 @@ function Button({
235
346
  }
236
347
  );
237
348
  }
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");
349
+ function DropdownMenu({ ...props }) {
350
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
351
+ }
352
+ function DropdownMenuTrigger({ ...props }) {
353
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
354
+ }
355
+ function DropdownMenuContent({
356
+ align = "start",
357
+ alignOffset = 0,
358
+ side = "bottom",
359
+ sideOffset = 4,
360
+ className,
361
+ ...props
362
+ }) {
363
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
364
+ menu.Menu.Positioner,
365
+ {
366
+ className: "isolate z-50 outline-none",
367
+ align,
368
+ alignOffset,
369
+ side,
370
+ sideOffset,
371
+ children: /* @__PURE__ */ jsxRuntime.jsx(
372
+ menu.Menu.Popup,
373
+ {
374
+ "data-slot": "dropdown-menu-content",
375
+ className: cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 bg-popover text-popover-foreground min-w-48 rounded-2xl p-1 shadow-2xl ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden", className),
376
+ ...props
377
+ }
378
+ )
379
+ }
380
+ ) });
381
+ }
382
+ function DropdownMenuGroup({ ...props }) {
383
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Group, { "data-slot": "dropdown-menu-group", ...props });
384
+ }
385
+ function DropdownMenuLabel({
386
+ className,
387
+ inset,
388
+ ...props
389
+ }) {
390
+ return /* @__PURE__ */ jsxRuntime.jsx(
391
+ menu.Menu.GroupLabel,
392
+ {
393
+ "data-slot": "dropdown-menu-label",
394
+ "data-inset": inset,
395
+ className: cn("text-muted-foreground px-3 py-2.5 text-xs data-[inset]:pl-8", className),
396
+ ...props
397
+ }
398
+ );
399
+ }
400
+ function DropdownMenuItem({
401
+ className,
402
+ inset,
403
+ variant = "default",
404
+ ...props
405
+ }) {
406
+ return /* @__PURE__ */ jsxRuntime.jsx(
407
+ menu.Menu.Item,
408
+ {
409
+ "data-slot": "dropdown-menu-item",
410
+ "data-inset": inset,
411
+ "data-variant": variant,
412
+ className: cn(
413
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2.5 rounded-xl px-3 py-2 text-sm [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
414
+ className
415
+ ),
416
+ ...props
417
+ }
418
+ );
419
+ }
420
+ function DropdownMenuCheckboxItem({
421
+ className,
422
+ children,
423
+ checked,
424
+ ...props
425
+ }) {
426
+ return /* @__PURE__ */ jsxRuntime.jsxs(
427
+ menu.Menu.CheckboxItem,
428
+ {
429
+ "data-slot": "dropdown-menu-checkbox-item",
430
+ className: cn(
431
+ "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2.5 rounded-xl py-2 pr-8 pl-3 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
432
+ className
433
+ ),
434
+ checked,
435
+ ...props,
436
+ children: [
437
+ /* @__PURE__ */ jsxRuntime.jsx(
438
+ "span",
439
+ {
440
+ className: "pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none",
441
+ "data-slot": "dropdown-menu-checkbox-item-indicator",
442
+ children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(
443
+ ICONS.IconCheck,
444
+ {}
445
+ ) })
446
+ }
447
+ ),
448
+ children
449
+ ]
450
+ }
451
+ );
452
+ }
453
+ function DropdownMenuSeparator({
454
+ className,
455
+ ...props
456
+ }) {
457
+ return /* @__PURE__ */ jsxRuntime.jsx(
458
+ menu.Menu.Separator,
459
+ {
460
+ "data-slot": "dropdown-menu-separator",
461
+ className: cn("bg-border/50 -mx-1 my-1 h-px", className),
462
+ ...props
463
+ }
464
+ );
465
+ }
466
+ function Separator({
467
+ className,
468
+ orientation = "horizontal",
469
+ ...props
470
+ }) {
471
+ return /* @__PURE__ */ jsxRuntime.jsx(
472
+ separator.Separator,
473
+ {
474
+ "data-slot": "separator",
475
+ orientation,
476
+ className: cn(
477
+ "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch",
478
+ className
479
+ ),
480
+ ...props
481
+ }
482
+ );
483
+ }
484
+ var AccountButton = ({
485
+ className,
486
+ variant = "outline",
487
+ size
488
+ }) => {
489
+ const { isLoading, isAuthenticated, user, login, logout } = useAuth();
490
+ const [open, setOpen] = React11__namespace.useState(false);
491
+ const [accountInfoOpen, setAccountInfoOpen] = React11__namespace.useState(false);
492
+ const [error, setError] = React11__namespace.useState(null);
493
+ const initials = React11__namespace.useMemo(() => {
494
+ const name = user?.displayName || user?.name;
495
+ if (!name) return "";
496
+ return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
497
+ }, [user?.displayName, user?.name]);
498
+ const handleGoogleSignIn = async () => {
499
+ login();
500
+ };
501
+ if (isAuthenticated) {
502
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
503
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
504
+ /* @__PURE__ */ jsxRuntime.jsx(
505
+ DropdownMenuTrigger,
506
+ {
507
+ render: (props) => /* @__PURE__ */ jsxRuntime.jsx(
508
+ Button,
509
+ {
510
+ variant,
511
+ size: "icon",
512
+ ...props,
513
+ className: cn("rounded-full", className),
514
+ children: user?.picture ? /* @__PURE__ */ jsxRuntime.jsx(
515
+ "img",
516
+ {
517
+ src: user.picture,
518
+ alt: user.displayName || user.name,
519
+ className: "size-7 rounded-full object-cover"
520
+ }
521
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-7 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "size-4" }) })
522
+ }
523
+ )
524
+ }
525
+ ),
526
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
527
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 p-2", children: [
528
+ user?.picture ? /* @__PURE__ */ jsxRuntime.jsx(
529
+ "img",
530
+ {
531
+ src: user.picture,
532
+ alt: user.displayName || user.name,
533
+ className: "size-8 rounded-full object-cover"
534
+ }
535
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "size-4" }) }),
536
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-0.5 overflow-hidden", children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-medium", children: user?.displayName || user?.name }),
538
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-muted-foreground", children: user?.email })
539
+ ] })
540
+ ] }),
541
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-1" }),
542
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => setAccountInfoOpen(true), children: [
543
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "mr-2 size-4" }),
544
+ "Account Settings"
545
+ ] }),
546
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: logout, className: "text-destructive", children: [
547
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLogout, { className: "mr-2 size-4" }),
548
+ "Logout"
549
+ ] })
550
+ ] })
551
+ ] }),
552
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: accountInfoOpen, onOpenChange: setAccountInfoOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-md", children: [
553
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
554
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Account Information" }),
555
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Your account details and settings." })
556
+ ] }),
557
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogClose, { children: [
558
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconX, { className: "size-4" }),
559
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
560
+ ] }),
561
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 py-4", children: [
562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
563
+ user?.picture ? /* @__PURE__ */ jsxRuntime.jsx(
564
+ "img",
565
+ {
566
+ src: user.picture,
567
+ alt: user.displayName || user.name,
568
+ className: "size-16 rounded-full object-cover"
569
+ }
570
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-16 items-center justify-center rounded-full bg-muted text-xl font-bold", children: initials || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "size-8 text-muted-foreground" }) }),
571
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
572
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: user?.displayName || user?.name }),
573
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: user?.email })
574
+ ] })
575
+ ] }),
576
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
577
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
578
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
579
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "User ID" }),
580
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-xs truncate", children: user?.uid || user?.id })
581
+ ] }),
582
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
583
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "Created At" }),
584
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs", children: user?.createdAt || "N/A" })
585
+ ] })
586
+ ] })
587
+ ] })
588
+ ] }) })
589
+ ] });
242
590
  }
243
- return context;
591
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
592
+ /* @__PURE__ */ jsxRuntime.jsx(
593
+ Button,
594
+ {
595
+ variant,
596
+ size,
597
+ onClick: () => setOpen(true),
598
+ className,
599
+ children: "Sign in"
600
+ }
601
+ ),
602
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-md", children: [
603
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
604
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Sign in to continue" }),
605
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Choose your preferred sign-in method to access your account." })
606
+ ] }),
607
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogClose, { children: [
608
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconX, { className: "size-4" }),
609
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
610
+ ] }),
611
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
612
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-destructive/10 p-3 text-sm text-destructive", children: error }),
613
+ /* @__PURE__ */ jsxRuntime.jsxs(
614
+ Button,
615
+ {
616
+ onClick: handleGoogleSignIn,
617
+ disabled: isLoading,
618
+ variant: "outline",
619
+ className: "w-full",
620
+ size: "lg",
621
+ children: [
622
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconBrandGoogle, { className: "mr-2 size-5" }),
623
+ isLoading ? "Signing in..." : "Continue with Google"
624
+ ]
625
+ }
626
+ )
627
+ ] })
628
+ ] }) })
629
+ ] });
244
630
  };
245
631
  function WelcomeScreen({
246
632
  title = "Welcome to Melony",
@@ -271,13 +657,6 @@ function WelcomeScreen({
271
657
  imageAlt = "Product screenshot"
272
658
  }) {
273
659
  const { login, isLoading } = useAuth();
274
- const handleLogin = () => {
275
- if (onLoginClick) {
276
- onLoginClick();
277
- } else {
278
- login();
279
- }
280
- };
281
660
  return /* @__PURE__ */ jsxRuntime.jsxs(
282
661
  "div",
283
662
  {
@@ -314,26 +693,7 @@ function WelcomeScreen({
314
693
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-bold tracking-tight text-foreground", children: "Get Started" }),
315
694
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-lg", children: "Sign in to your account to continue" })
316
695
  ] }),
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
- ] }),
696
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsx(AccountButton, {}) }),
337
697
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground leading-relaxed text-center md:text-left", children: [
338
698
  "By continuing, you agree to our ",
339
699
  /* @__PURE__ */ jsxRuntime.jsx("br", { className: "hidden md:block" }),
@@ -696,175 +1056,58 @@ var useThreads = () => {
696
1056
  throw new Error("useThreads must be used within a ThreadProvider");
697
1057
  }
698
1058
  return context;
699
- };
700
- function Textarea({ className, ...props }) {
701
- return /* @__PURE__ */ jsxRuntime.jsx(
702
- "textarea",
703
- {
704
- "data-slot": "textarea",
705
- className: cn(
706
- "border-input bg-input/30 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 resize-none rounded-xl border px-3 py-3 text-base transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50",
707
- className
708
- ),
709
- ...props
710
- }
711
- );
712
- }
713
- var badgeVariants = classVarianceAuthority.cva(
714
- "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
715
- {
716
- variants: {
717
- variant: {
718
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
719
- secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
720
- destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
721
- outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
722
- ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
723
- link: "text-primary underline-offset-4 hover:underline"
724
- }
725
- },
726
- defaultVariants: {
727
- variant: "default"
728
- }
729
- }
730
- );
731
- function Badge({
732
- className,
733
- variant = "default",
734
- render,
735
- ...props
736
- }) {
737
- return useRender.useRender({
738
- defaultTagName: "span",
739
- props: mergeProps.mergeProps(
740
- {
741
- className: cn(badgeVariants({ className, variant }))
742
- },
743
- props
744
- ),
745
- render,
746
- state: {
747
- slot: "badge",
748
- variant
749
- }
750
- });
751
- }
752
- function DropdownMenu({ ...props }) {
753
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
754
- }
755
- function DropdownMenuTrigger({ ...props }) {
756
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
757
- }
758
- function DropdownMenuContent({
759
- align = "start",
760
- alignOffset = 0,
761
- side = "bottom",
762
- sideOffset = 4,
763
- className,
764
- ...props
765
- }) {
766
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
767
- menu.Menu.Positioner,
768
- {
769
- className: "isolate z-50 outline-none",
770
- align,
771
- alignOffset,
772
- side,
773
- sideOffset,
774
- children: /* @__PURE__ */ jsxRuntime.jsx(
775
- menu.Menu.Popup,
776
- {
777
- "data-slot": "dropdown-menu-content",
778
- className: cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 bg-popover text-popover-foreground min-w-48 rounded-2xl p-1 shadow-2xl ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden", className),
779
- ...props
780
- }
781
- )
782
- }
783
- ) });
784
- }
785
- function DropdownMenuGroup({ ...props }) {
786
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Group, { "data-slot": "dropdown-menu-group", ...props });
787
- }
788
- function DropdownMenuLabel({
789
- className,
790
- inset,
791
- ...props
792
- }) {
793
- return /* @__PURE__ */ jsxRuntime.jsx(
794
- menu.Menu.GroupLabel,
795
- {
796
- "data-slot": "dropdown-menu-label",
797
- "data-inset": inset,
798
- className: cn("text-muted-foreground px-3 py-2.5 text-xs data-[inset]:pl-8", className),
799
- ...props
800
- }
801
- );
802
- }
803
- function DropdownMenuItem({
804
- className,
805
- inset,
806
- variant = "default",
807
- ...props
808
- }) {
1059
+ };
1060
+ function Textarea({ className, ...props }) {
809
1061
  return /* @__PURE__ */ jsxRuntime.jsx(
810
- menu.Menu.Item,
1062
+ "textarea",
811
1063
  {
812
- "data-slot": "dropdown-menu-item",
813
- "data-inset": inset,
814
- "data-variant": variant,
1064
+ "data-slot": "textarea",
815
1065
  className: cn(
816
- "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2.5 rounded-xl px-3 py-2 text-sm [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
1066
+ "border-input bg-input/30 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 resize-none rounded-xl border px-3 py-3 text-base transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50",
817
1067
  className
818
1068
  ),
819
1069
  ...props
820
1070
  }
821
1071
  );
822
1072
  }
823
- function DropdownMenuCheckboxItem({
824
- className,
825
- children,
826
- checked,
827
- ...props
828
- }) {
829
- return /* @__PURE__ */ jsxRuntime.jsxs(
830
- menu.Menu.CheckboxItem,
831
- {
832
- "data-slot": "dropdown-menu-checkbox-item",
833
- className: cn(
834
- "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2.5 rounded-xl py-2 pr-8 pl-3 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
835
- className
836
- ),
837
- checked,
838
- ...props,
839
- children: [
840
- /* @__PURE__ */ jsxRuntime.jsx(
841
- "span",
842
- {
843
- className: "pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none",
844
- "data-slot": "dropdown-menu-checkbox-item-indicator",
845
- children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(
846
- ICONS.IconCheck,
847
- {}
848
- ) })
849
- }
850
- ),
851
- children
852
- ]
1073
+ var badgeVariants = classVarianceAuthority.cva(
1074
+ "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
1075
+ {
1076
+ variants: {
1077
+ variant: {
1078
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
1079
+ secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
1080
+ destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
1081
+ outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
1082
+ ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
1083
+ link: "text-primary underline-offset-4 hover:underline"
1084
+ }
1085
+ },
1086
+ defaultVariants: {
1087
+ variant: "default"
853
1088
  }
854
- );
855
- }
856
- function DropdownMenuSeparator({
1089
+ }
1090
+ );
1091
+ function Badge({
857
1092
  className,
1093
+ variant = "default",
1094
+ render,
858
1095
  ...props
859
1096
  }) {
860
- return /* @__PURE__ */ jsxRuntime.jsx(
861
- menu.Menu.Separator,
862
- {
863
- "data-slot": "dropdown-menu-separator",
864
- className: cn("bg-border/50 -mx-1 my-1 h-px", className),
865
- ...props
1097
+ return useRender.useRender({
1098
+ defaultTagName: "span",
1099
+ props: mergeProps.mergeProps(
1100
+ {
1101
+ className: cn(badgeVariants({ className, variant }))
1102
+ },
1103
+ props
1104
+ ),
1105
+ render,
1106
+ state: {
1107
+ slot: "badge",
1108
+ variant
866
1109
  }
867
- );
1110
+ });
868
1111
  }
869
1112
  function Composer({
870
1113
  value,
@@ -1109,11 +1352,12 @@ function Composer({
1109
1352
  /* @__PURE__ */ jsxRuntime.jsx(
1110
1353
  DropdownMenuTrigger,
1111
1354
  {
1112
- render: /* @__PURE__ */ jsxRuntime.jsxs(
1355
+ render: (props) => /* @__PURE__ */ jsxRuntime.jsxs(
1113
1356
  Button,
1114
1357
  {
1115
1358
  variant: "ghost",
1116
1359
  size: "sm",
1360
+ ...props,
1117
1361
  className: cn(
1118
1362
  "gap-2",
1119
1363
  selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
@@ -1152,7 +1396,7 @@ function Composer({
1152
1396
  Button,
1153
1397
  {
1154
1398
  type: "submit",
1155
- disabled: !value.trim() && attachedFiles.length === 0 && !isLoading || isLoading,
1399
+ disabled: !value.trim() && attachedFiles.length === 0 && selectedOptions.size === 0 && !isLoading || isLoading,
1156
1400
  size: "icon-lg",
1157
1401
  onClick: () => handleInternalSubmit().catch(console.error),
1158
1402
  children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconArrowUp, { className: "h-5 w-5" })
@@ -1426,24 +1670,6 @@ var Spacer = ({
1426
1670
  }
1427
1671
  );
1428
1672
  };
1429
- function Separator({
1430
- className,
1431
- orientation = "horizontal",
1432
- ...props
1433
- }) {
1434
- return /* @__PURE__ */ jsxRuntime.jsx(
1435
- separator.Separator,
1436
- {
1437
- "data-slot": "separator",
1438
- orientation,
1439
- className: cn(
1440
- "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch",
1441
- className
1442
- ),
1443
- ...props
1444
- }
1445
- );
1446
- }
1447
1673
  var Divider = ({
1448
1674
  orientation = "horizontal",
1449
1675
  className,
@@ -1487,7 +1713,7 @@ var ListItem = ({
1487
1713
  const paddingClasses = {
1488
1714
  xs: "px-1.5 py-1",
1489
1715
  sm: "px-2 py-1.5",
1490
- md: "px-3 py-2",
1716
+ md: "px-3 py-1.5",
1491
1717
  lg: "px-4 py-3",
1492
1718
  xl: "px-6 py-4"
1493
1719
  };
@@ -1523,7 +1749,7 @@ var ListItem = ({
1523
1749
  {
1524
1750
  onClick: isInteractive ? handleClick : void 0,
1525
1751
  className: cn(
1526
- "flex rounded-md transition-colors",
1752
+ "flex rounded-md transition-colors text-sm",
1527
1753
  orientation === "horizontal" ? "flex-row" : "flex-col",
1528
1754
  gapClasses[gap] || "gap-3",
1529
1755
  alignClasses[resolvedAlign],
@@ -1540,111 +1766,6 @@ var ListItem = ({
1540
1766
  }
1541
1767
  );
1542
1768
  };
1543
- function Dialog({ ...props }) {
1544
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Root, { "data-slot": "dialog", ...props });
1545
- }
1546
- function DialogTrigger({ ...props }) {
1547
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Trigger, { "data-slot": "dialog-trigger", ...props });
1548
- }
1549
- function DialogPortal({ ...props }) {
1550
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Portal, { "data-slot": "dialog-portal", ...props });
1551
- }
1552
- function DialogOverlay({
1553
- className,
1554
- ...props
1555
- }) {
1556
- return /* @__PURE__ */ jsxRuntime.jsx(
1557
- dialog.Dialog.Backdrop,
1558
- {
1559
- "data-slot": "dialog-overlay",
1560
- className: cn(
1561
- "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-200 supports-backdrop-filter:backdrop-blur-sm fixed inset-0 isolate z-50",
1562
- className
1563
- ),
1564
- ...props
1565
- }
1566
- );
1567
- }
1568
- function DialogContent({
1569
- className,
1570
- ...props
1571
- }) {
1572
- return /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
1573
- /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
1574
- /* @__PURE__ */ jsxRuntime.jsx(
1575
- dialog.Dialog.Popup,
1576
- {
1577
- "data-slot": "dialog-content",
1578
- className: cn(
1579
- "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg outline-none",
1580
- className
1581
- ),
1582
- ...props
1583
- }
1584
- )
1585
- ] });
1586
- }
1587
- function DialogClose({
1588
- className,
1589
- ...props
1590
- }) {
1591
- return /* @__PURE__ */ jsxRuntime.jsx(
1592
- dialog.Dialog.Close,
1593
- {
1594
- "data-slot": "dialog-close",
1595
- className: cn(
1596
- "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
1597
- className
1598
- ),
1599
- ...props
1600
- }
1601
- );
1602
- }
1603
- function DialogHeader({
1604
- className,
1605
- ...props
1606
- }) {
1607
- return /* @__PURE__ */ jsxRuntime.jsx(
1608
- "div",
1609
- {
1610
- "data-slot": "dialog-header",
1611
- className: cn(
1612
- "flex flex-col space-y-1.5 text-center sm:text-left",
1613
- className
1614
- ),
1615
- ...props
1616
- }
1617
- );
1618
- }
1619
- function DialogTitle({
1620
- className,
1621
- ...props
1622
- }) {
1623
- return /* @__PURE__ */ jsxRuntime.jsx(
1624
- dialog.Dialog.Title,
1625
- {
1626
- "data-slot": "dialog-title",
1627
- className: cn(
1628
- "text-lg font-semibold leading-none tracking-tight",
1629
- className
1630
- ),
1631
- ...props
1632
- }
1633
- );
1634
- }
1635
- function DialogDescription({
1636
- className,
1637
- ...props
1638
- }) {
1639
- return /* @__PURE__ */ jsxRuntime.jsx(
1640
- dialog.Dialog.Description,
1641
- {
1642
- "data-slot": "dialog-description",
1643
- className: cn("text-sm text-muted-foreground", className),
1644
- ...props
1645
- }
1646
- );
1647
- }
1648
1769
  var Image = ({
1649
1770
  src,
1650
1771
  alt,
@@ -2670,7 +2791,16 @@ function UIRenderer({ node }) {
2670
2791
  return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...componentProps, children: renderedChildren });
2671
2792
  }
2672
2793
  function MessageContent({ events }) {
2794
+ const latestSlotIndexes = /* @__PURE__ */ new Map();
2795
+ events.forEach((event, index) => {
2796
+ if (event.slot) {
2797
+ latestSlotIndexes.set(event.slot, index);
2798
+ }
2799
+ });
2673
2800
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: events.map((event, index) => {
2801
+ if (event.slot && latestSlotIndexes.get(event.slot) !== index) {
2802
+ return null;
2803
+ }
2674
2804
  if (event.type === "text-delta") {
2675
2805
  return /* @__PURE__ */ jsxRuntime.jsx("span", { children: event.data?.delta }, index);
2676
2806
  }
@@ -2783,15 +2913,19 @@ function Thread({
2783
2913
  const handleSubmit = async (state, overrideInput) => {
2784
2914
  const text = (overrideInput ?? input).trim();
2785
2915
  const hasFiles = state?.files && Array.isArray(state.files) && state.files.length > 0;
2786
- if (!text && !hasFiles || isLoading) return;
2916
+ const hasOptions = state && Object.keys(state).filter((k) => k !== "threadId").length > 0;
2917
+ if (!text && !hasFiles && !hasOptions || isLoading) return;
2787
2918
  if (!overrideInput) setInput("");
2788
2919
  await sendEvent(
2789
2920
  {
2790
2921
  type: "text",
2791
2922
  role: "user",
2792
- data: { content: text || "" }
2793
- },
2794
- { state: { ...state, threadId: activeThreadId ?? void 0 } }
2923
+ data: { content: text || "" },
2924
+ state: {
2925
+ ...state,
2926
+ threadId: activeThreadId ?? void 0
2927
+ }
2928
+ }
2795
2929
  );
2796
2930
  };
2797
2931
  const handleStarterPromptClick = (prompt) => {
@@ -2887,11 +3021,39 @@ function ChatHeader({
2887
3021
  }
2888
3022
  );
2889
3023
  }
2890
- var ThreadList = ({
3024
+ var Dropdown = ({
2891
3025
  className,
2892
- emptyState,
2893
- onThreadSelect
3026
+ trigger,
3027
+ triggerClassName,
3028
+ items
2894
3029
  }) => {
3030
+ return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
3031
+ /* @__PURE__ */ jsxRuntime.jsx(
3032
+ DropdownMenuTrigger,
3033
+ {
3034
+ className: triggerClassName,
3035
+ render: (props) => /* @__PURE__ */ jsxRuntime.jsx(
3036
+ Button,
3037
+ {
3038
+ variant: "ghost",
3039
+ size: "icon-xs",
3040
+ ...props,
3041
+ onClick: (e) => {
3042
+ e.stopPropagation();
3043
+ props.onClick?.(e);
3044
+ },
3045
+ children: trigger || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconDotsVertical, { className: "size-3.5" })
3046
+ }
3047
+ )
3048
+ }
3049
+ ),
3050
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "start", className: cn("w-32", className), children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: item.onClick, children: [
3051
+ item.icon,
3052
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label })
3053
+ ] }, item.label)) })
3054
+ ] });
3055
+ };
3056
+ var ThreadList = ({ className }) => {
2895
3057
  const { threads, activeThreadId, selectThread, deleteThread, isLoading } = useThreads();
2896
3058
  const sortedThreads = React11__namespace.useMemo(() => {
2897
3059
  return [...threads].sort((a, b) => {
@@ -2900,73 +3062,44 @@ var ThreadList = ({
2900
3062
  return dateB - dateA;
2901
3063
  });
2902
3064
  }, [threads]);
2903
- const handleThreadClick = (threadId) => {
2904
- if (threadId !== activeThreadId) {
2905
- selectThread(threadId);
2906
- }
2907
- onThreadSelect?.(threadId);
2908
- };
2909
3065
  const handleDelete = async (threadId) => {
2910
- try {
2911
- await deleteThread(threadId);
2912
- } catch (error) {
2913
- console.error("Failed to delete thread:", error);
2914
- }
2915
- };
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",
2923
- {
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
- ),
2929
- children: [
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
- ] }) })
3066
+ try {
3067
+ await deleteThread(threadId);
3068
+ } catch (error) {
3069
+ console.error("Failed to delete thread:", error);
3070
+ }
3071
+ };
3072
+ return /* @__PURE__ */ jsxRuntime.jsx(List, { className, children: sortedThreads.map((thread) => {
3073
+ const isActive = thread.id === activeThreadId;
3074
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3075
+ ListItem,
3076
+ {
3077
+ onClickAction: {
3078
+ type: "client:navigate",
3079
+ data: {
3080
+ url: `?threadId=${thread.id}`
3081
+ }
3082
+ },
3083
+ className: isActive ? "bg-muted text-foreground group" : "hover:bg-muted/50 text-muted-foreground hover:text-foreground group",
3084
+ children: [
3085
+ /* @__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)}` }) }),
3086
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 flex items-center opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsxRuntime.jsx(
3087
+ Dropdown,
3088
+ {
3089
+ items: [
3090
+ {
3091
+ label: "Delete",
3092
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconTrash, { className: "size-4" }),
3093
+ onClick: () => handleDelete(thread.id)
3094
+ }
3095
+ ]
3096
+ }
3097
+ ) })
2965
3098
  ]
2966
3099
  },
2967
3100
  thread.id
2968
3101
  );
2969
- }) }) }) });
3102
+ }) });
2970
3103
  };
2971
3104
  function PopupChat({
2972
3105
  title = "Chat",
@@ -3053,7 +3186,6 @@ function PopupChat({
3053
3186
  ) : /* @__PURE__ */ jsxRuntime.jsx(
3054
3187
  ThreadList,
3055
3188
  {
3056
- onThreadSelect: () => setView("chat"),
3057
3189
  className: "h-full"
3058
3190
  }
3059
3191
  ) })
@@ -3356,8 +3488,7 @@ var ThreadPopover = ({
3356
3488
  buttonClassName,
3357
3489
  buttonVariant = "ghost",
3358
3490
  buttonSize = "icon",
3359
- emptyState,
3360
- onThreadSelect
3491
+ emptyState
3361
3492
  }) => {
3362
3493
  const [isOpen, setIsOpen] = React11__namespace.useState(false);
3363
3494
  reactHotkeysHook.useHotkeys(
@@ -3373,10 +3504,6 @@ var ThreadPopover = ({
3373
3504
  // Don't trigger in contenteditable elements
3374
3505
  }
3375
3506
  );
3376
- const handleThreadSelect = (threadId) => {
3377
- setIsOpen(false);
3378
- onThreadSelect?.(threadId);
3379
- };
3380
3507
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
3381
3508
  /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3382
3509
  Button,
@@ -3394,14 +3521,7 @@ var ThreadPopover = ({
3394
3521
  side: "bottom",
3395
3522
  align: "start",
3396
3523
  sideOffset: 8,
3397
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col h-[400px]", children: /* @__PURE__ */ jsxRuntime.jsx(
3398
- ThreadList,
3399
- {
3400
- emptyState,
3401
- onThreadSelect: handleThreadSelect,
3402
- className: "h-full"
3403
- }
3404
- ) })
3524
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col h-[400px]", children: /* @__PURE__ */ jsxRuntime.jsx(ThreadList, { emptyState, className: "h-full" }) })
3405
3525
  }
3406
3526
  )
3407
3527
  ] });
@@ -3455,231 +3575,6 @@ var CreateThreadButton = ({
3455
3575
  }
3456
3576
  );
3457
3577
  };
3458
- function AlertDialog({ ...props }) {
3459
- return /* @__PURE__ */ jsxRuntime.jsx(alertDialog.AlertDialog.Root, { "data-slot": "alert-dialog", ...props });
3460
- }
3461
- function AlertDialogPortal({ ...props }) {
3462
- return /* @__PURE__ */ jsxRuntime.jsx(alertDialog.AlertDialog.Portal, { "data-slot": "alert-dialog-portal", ...props });
3463
- }
3464
- function AlertDialogOverlay({
3465
- className,
3466
- ...props
3467
- }) {
3468
- return /* @__PURE__ */ jsxRuntime.jsx(
3469
- alertDialog.AlertDialog.Backdrop,
3470
- {
3471
- "data-slot": "alert-dialog-overlay",
3472
- className: cn(
3473
- "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50",
3474
- className
3475
- ),
3476
- ...props
3477
- }
3478
- );
3479
- }
3480
- function AlertDialogContent({
3481
- className,
3482
- size = "default",
3483
- ...props
3484
- }) {
3485
- return /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogPortal, { children: [
3486
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogOverlay, {}),
3487
- /* @__PURE__ */ jsxRuntime.jsx(
3488
- alertDialog.AlertDialog.Popup,
3489
- {
3490
- "data-slot": "alert-dialog-content",
3491
- "data-size": size,
3492
- className: cn(
3493
- "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/5 gap-6 rounded-4xl p-6 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-md group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",
3494
- className
3495
- ),
3496
- ...props
3497
- }
3498
- )
3499
- ] });
3500
- }
3501
- function AlertDialogHeader({
3502
- className,
3503
- ...props
3504
- }) {
3505
- return /* @__PURE__ */ jsxRuntime.jsx(
3506
- "div",
3507
- {
3508
- "data-slot": "alert-dialog-header",
3509
- className: cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className),
3510
- ...props
3511
- }
3512
- );
3513
- }
3514
- function AlertDialogTitle({
3515
- className,
3516
- ...props
3517
- }) {
3518
- return /* @__PURE__ */ jsxRuntime.jsx(
3519
- alertDialog.AlertDialog.Title,
3520
- {
3521
- "data-slot": "alert-dialog-title",
3522
- className: cn("text-lg font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", className),
3523
- ...props
3524
- }
3525
- );
3526
- }
3527
- function AlertDialogDescription({
3528
- className,
3529
- ...props
3530
- }) {
3531
- return /* @__PURE__ */ jsxRuntime.jsx(
3532
- alertDialog.AlertDialog.Description,
3533
- {
3534
- "data-slot": "alert-dialog-description",
3535
- className: cn("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3", className),
3536
- ...props
3537
- }
3538
- );
3539
- }
3540
- var AccountDialog = ({
3541
- className,
3542
- variant = "outline",
3543
- size
3544
- }) => {
3545
- const { isLoading, isAuthenticated, user, login, logout } = useAuth();
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(() => {
3550
- const name = user?.displayName || user?.name;
3551
- if (!name) return "";
3552
- return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
3553
- }, [user?.displayName, user?.name]);
3554
- const handleGoogleSignIn = async () => {
3555
- login();
3556
- };
3557
- if (isAuthenticated) {
3558
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3559
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
3560
- /* @__PURE__ */ jsxRuntime.jsx(
3561
- DropdownMenuTrigger,
3562
- {
3563
- render: (props) => /* @__PURE__ */ jsxRuntime.jsx(
3564
- Button,
3565
- {
3566
- variant,
3567
- size: "icon",
3568
- ...props,
3569
- className: cn("rounded-full", className),
3570
- children: user?.picture ? /* @__PURE__ */ jsxRuntime.jsx(
3571
- "img",
3572
- {
3573
- src: user.picture,
3574
- alt: user.displayName || user.name,
3575
- className: "size-7 rounded-full object-cover"
3576
- }
3577
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-7 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "size-4" }) })
3578
- }
3579
- )
3580
- }
3581
- ),
3582
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
3583
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 p-2", children: [
3584
- user?.picture ? /* @__PURE__ */ jsxRuntime.jsx(
3585
- "img",
3586
- {
3587
- src: user.picture,
3588
- alt: user.displayName || user.name,
3589
- className: "size-8 rounded-full object-cover"
3590
- }
3591
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "size-4" }) }),
3592
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-0.5 overflow-hidden", children: [
3593
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-medium", children: user?.displayName || user?.name }),
3594
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-muted-foreground", children: user?.email })
3595
- ] })
3596
- ] }),
3597
- /* @__PURE__ */ jsxRuntime.jsx(Separator, { className: "my-1" }),
3598
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => setAccountInfoOpen(true), children: [
3599
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "mr-2 size-4" }),
3600
- "Account Settings"
3601
- ] }),
3602
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onClick: logout, className: "text-destructive", children: [
3603
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLogout, { className: "mr-2 size-4" }),
3604
- "Logout"
3605
- ] })
3606
- ] })
3607
- ] }),
3608
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: accountInfoOpen, onOpenChange: setAccountInfoOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-md", children: [
3609
- /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
3610
- /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Account Information" }),
3611
- /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Your account details and settings." })
3612
- ] }),
3613
- /* @__PURE__ */ jsxRuntime.jsxs(DialogClose, { children: [
3614
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconX, { className: "size-4" }),
3615
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
3616
- ] }),
3617
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 py-4", children: [
3618
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
3619
- user?.picture ? /* @__PURE__ */ jsxRuntime.jsx(
3620
- "img",
3621
- {
3622
- src: user.picture,
3623
- alt: user.displayName || user.name,
3624
- className: "size-16 rounded-full object-cover"
3625
- }
3626
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-16 items-center justify-center rounded-full bg-muted text-xl font-bold", children: initials || /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconUser, { className: "size-8 text-muted-foreground" }) }),
3627
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
3628
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: user?.displayName || user?.name }),
3629
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: user?.email })
3630
- ] })
3631
- ] }),
3632
- /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
3633
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
3634
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
3635
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "User ID" }),
3636
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-xs truncate", children: user?.uid || user?.id })
3637
- ] }),
3638
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
3639
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "Created At" }),
3640
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs", children: user?.createdAt || "N/A" })
3641
- ] })
3642
- ] })
3643
- ] })
3644
- ] }) })
3645
- ] });
3646
- }
3647
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3648
- /* @__PURE__ */ jsxRuntime.jsx(
3649
- Button,
3650
- {
3651
- variant,
3652
- size,
3653
- onClick: () => setOpen(true),
3654
- className,
3655
- children: "Sign in"
3656
- }
3657
- ),
3658
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "sm:max-w-md", children: [
3659
- /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { children: [
3660
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTitle, { children: "Sign in to continue" }),
3661
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogDescription, { children: "Choose your preferred sign-in method to access your account." })
3662
- ] }),
3663
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 py-4", children: [
3664
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3665
- /* @__PURE__ */ jsxRuntime.jsxs(
3666
- Button,
3667
- {
3668
- onClick: handleGoogleSignIn,
3669
- disabled: isLoading,
3670
- variant: "outline",
3671
- className: "w-full",
3672
- size: "lg",
3673
- children: [
3674
- /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconBrandGoogle, { className: "mr-2 size-5" }),
3675
- isLoading ? "Signing in..." : "Continue with Google"
3676
- ]
3677
- }
3678
- )
3679
- ] })
3680
- ] }) })
3681
- ] });
3682
- };
3683
3578
  function ThemeToggle() {
3684
3579
  const { theme, setTheme, resolvedTheme } = useTheme();
3685
3580
  const cycleTheme = () => {
@@ -3715,8 +3610,54 @@ function ThemeToggle() {
3715
3610
  }
3716
3611
  );
3717
3612
  }
3613
+ var CreateThreadNavItem = ({
3614
+ className
3615
+ }) => {
3616
+ const { createThread } = useThreads();
3617
+ const [isCreating, setIsCreating] = React11__namespace.useState(false);
3618
+ const handleCreateThread = async () => {
3619
+ if (isCreating) return;
3620
+ try {
3621
+ setIsCreating(true);
3622
+ const threadId = await createThread();
3623
+ } catch (error) {
3624
+ console.error("Failed to create thread:", error);
3625
+ } finally {
3626
+ setIsCreating(false);
3627
+ }
3628
+ };
3629
+ reactHotkeysHook.useHotkeys(
3630
+ "n",
3631
+ (e) => {
3632
+ e.preventDefault();
3633
+ handleCreateThread();
3634
+ },
3635
+ {
3636
+ enableOnFormTags: false,
3637
+ // Don't trigger when typing in form inputs
3638
+ enableOnContentEditable: false
3639
+ // Don't trigger in contenteditable elements
3640
+ }
3641
+ );
3642
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3643
+ ListItem,
3644
+ {
3645
+ onClickAction: {
3646
+ type: "client:navigate",
3647
+ data: {
3648
+ url: `?threadId=${client.generateId()}`
3649
+ }
3650
+ },
3651
+ className: cn(className),
3652
+ children: [
3653
+ /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "size-4" }),
3654
+ "New chat"
3655
+ ]
3656
+ }
3657
+ );
3658
+ };
3718
3659
 
3719
- exports.AccountDialog = AccountDialog;
3660
+ exports.AccountButton = AccountButton;
3720
3661
  exports.AuthContext = AuthContext;
3721
3662
  exports.AuthProvider = AuthProvider;
3722
3663
  exports.Badge = Badge2;
@@ -3729,7 +3670,9 @@ exports.Checkbox = Checkbox;
3729
3670
  exports.Col = Col;
3730
3671
  exports.Composer = Composer;
3731
3672
  exports.CreateThreadButton = CreateThreadButton;
3673
+ exports.CreateThreadNavItem = CreateThreadNavItem;
3732
3674
  exports.Divider = Divider;
3675
+ exports.Dropdown = Dropdown;
3733
3676
  exports.Form = Form;
3734
3677
  exports.FullChat = FullChat;
3735
3678
  exports.Heading = Heading;