@melony/react 0.1.12 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -194
- package/dist/index.cjs +1409 -415
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -12
- package/dist/index.d.ts +181 -12
- package/dist/index.js +1358 -371
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { createContext, useState, useEffect, useCallback, useMemo, useContext, useRef } from 'react';
|
|
1
|
+
import * as React11 from 'react';
|
|
2
|
+
import React11__default, { createContext, useState, useEffect, useCallback, useMemo, useContext, useRef } from 'react';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { generateId } from 'melony/client';
|
|
3
5
|
import { clsx } from 'clsx';
|
|
4
6
|
import { twMerge } from 'tailwind-merge';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
7
|
+
import { Button as Button$1 } from '@base-ui/react/button';
|
|
8
|
+
import { cva } from 'class-variance-authority';
|
|
8
9
|
import * as ICONS from '@tabler/icons-react';
|
|
9
|
-
import { IconArrowUp, IconPlus, IconMessage, IconTrash, IconArrowLeft,
|
|
10
|
+
import { IconChevronDown, IconLoader2, IconArrowUp, IconPlus, IconMessage, IconTrash, IconHistory, IconX, IconArrowLeft, IconChevronLeft, IconChevronRight, IconUser, IconLogout, IconBrandGoogle, IconDeviceDesktop, IconMoon, IconSun, IconCheck, IconSelector, IconChevronUp } from '@tabler/icons-react';
|
|
11
|
+
import { Menu } from '@base-ui/react/menu';
|
|
12
|
+
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
13
|
+
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
10
14
|
import { mergeProps } from '@base-ui/react/merge-props';
|
|
11
15
|
import { useRender } from '@base-ui/react/use-render';
|
|
12
|
-
import { cva } from 'class-variance-authority';
|
|
13
16
|
import { Input as Input$1 } from '@base-ui/react/input';
|
|
14
17
|
import { Select as Select$1 } from '@base-ui/react/select';
|
|
15
|
-
import {
|
|
18
|
+
import { createPortal } from 'react-dom';
|
|
19
|
+
import { useHotkeys } from 'react-hotkeys-hook';
|
|
16
20
|
import { AlertDialog as AlertDialog$1 } from '@base-ui/react/alert-dialog';
|
|
17
|
-
import { Menu } from '@base-ui/react/menu';
|
|
18
21
|
|
|
19
22
|
// src/providers/melony-provider.tsx
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
+
|
|
24
|
+
// src/lib/group-events-to-messages.ts
|
|
23
25
|
function groupEventsToMessages(events) {
|
|
24
26
|
if (events.length === 0) return [];
|
|
25
27
|
const messages = [];
|
|
@@ -282,6 +284,58 @@ var ThreadProvider = ({
|
|
|
282
284
|
);
|
|
283
285
|
return /* @__PURE__ */ jsx(ThreadContext.Provider, { value, children });
|
|
284
286
|
};
|
|
287
|
+
var ThemeContext = createContext(void 0);
|
|
288
|
+
function ThemeProvider({ children }) {
|
|
289
|
+
const [theme, setThemeState] = useState("system");
|
|
290
|
+
const [resolvedTheme, setResolvedTheme] = useState("light");
|
|
291
|
+
useEffect(() => {
|
|
292
|
+
if (typeof window !== "undefined") {
|
|
293
|
+
const stored = localStorage.getItem("theme");
|
|
294
|
+
if (stored) {
|
|
295
|
+
setThemeState(stored);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}, []);
|
|
299
|
+
useEffect(() => {
|
|
300
|
+
if (typeof window !== "undefined") {
|
|
301
|
+
if (theme === "system") {
|
|
302
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
303
|
+
const updateResolvedTheme = () => {
|
|
304
|
+
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
305
|
+
};
|
|
306
|
+
updateResolvedTheme();
|
|
307
|
+
mediaQuery.addEventListener("change", updateResolvedTheme);
|
|
308
|
+
return () => mediaQuery.removeEventListener("change", updateResolvedTheme);
|
|
309
|
+
} else {
|
|
310
|
+
setResolvedTheme(theme);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}, [theme]);
|
|
314
|
+
useEffect(() => {
|
|
315
|
+
if (typeof window !== "undefined") {
|
|
316
|
+
const root = document.documentElement;
|
|
317
|
+
if (resolvedTheme === "dark") {
|
|
318
|
+
root.classList.add("dark");
|
|
319
|
+
} else {
|
|
320
|
+
root.classList.remove("dark");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}, [resolvedTheme]);
|
|
324
|
+
const setTheme = (newTheme) => {
|
|
325
|
+
setThemeState(newTheme);
|
|
326
|
+
if (typeof window !== "undefined") {
|
|
327
|
+
localStorage.setItem("theme", newTheme);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme, resolvedTheme }, children });
|
|
331
|
+
}
|
|
332
|
+
function useTheme() {
|
|
333
|
+
const context = useContext(ThemeContext);
|
|
334
|
+
if (context === void 0) {
|
|
335
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
336
|
+
}
|
|
337
|
+
return context;
|
|
338
|
+
}
|
|
285
339
|
var useMelony = (options) => {
|
|
286
340
|
const context = useContext(MelonyContext);
|
|
287
341
|
if (context === void 0) {
|
|
@@ -310,6 +364,313 @@ var useThreads = () => {
|
|
|
310
364
|
}
|
|
311
365
|
return context;
|
|
312
366
|
};
|
|
367
|
+
function cn(...inputs) {
|
|
368
|
+
return twMerge(clsx(inputs));
|
|
369
|
+
}
|
|
370
|
+
var buttonVariants = cva(
|
|
371
|
+
"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",
|
|
372
|
+
{
|
|
373
|
+
variants: {
|
|
374
|
+
variant: {
|
|
375
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
376
|
+
outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
377
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
378
|
+
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
379
|
+
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",
|
|
380
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
381
|
+
},
|
|
382
|
+
size: {
|
|
383
|
+
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
384
|
+
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",
|
|
385
|
+
sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
386
|
+
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
387
|
+
icon: "size-9",
|
|
388
|
+
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
389
|
+
"icon-sm": "size-8",
|
|
390
|
+
"icon-lg": "size-10"
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
defaultVariants: {
|
|
394
|
+
variant: "default",
|
|
395
|
+
size: "default"
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
);
|
|
399
|
+
function Button({
|
|
400
|
+
className,
|
|
401
|
+
variant = "default",
|
|
402
|
+
size = "default",
|
|
403
|
+
...props
|
|
404
|
+
}) {
|
|
405
|
+
return /* @__PURE__ */ jsx(
|
|
406
|
+
Button$1,
|
|
407
|
+
{
|
|
408
|
+
"data-slot": "button",
|
|
409
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
410
|
+
...props
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
function Textarea({ className, ...props }) {
|
|
415
|
+
return /* @__PURE__ */ jsx(
|
|
416
|
+
"textarea",
|
|
417
|
+
{
|
|
418
|
+
"data-slot": "textarea",
|
|
419
|
+
className: cn(
|
|
420
|
+
"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",
|
|
421
|
+
className
|
|
422
|
+
),
|
|
423
|
+
...props
|
|
424
|
+
}
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
function DropdownMenu({ ...props }) {
|
|
428
|
+
return /* @__PURE__ */ jsx(Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
429
|
+
}
|
|
430
|
+
function DropdownMenuTrigger({ ...props }) {
|
|
431
|
+
return /* @__PURE__ */ jsx(Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
432
|
+
}
|
|
433
|
+
function DropdownMenuContent({
|
|
434
|
+
align = "start",
|
|
435
|
+
alignOffset = 0,
|
|
436
|
+
side = "bottom",
|
|
437
|
+
sideOffset = 4,
|
|
438
|
+
className,
|
|
439
|
+
...props
|
|
440
|
+
}) {
|
|
441
|
+
return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
|
|
442
|
+
Menu.Positioner,
|
|
443
|
+
{
|
|
444
|
+
className: "isolate z-50 outline-none",
|
|
445
|
+
align,
|
|
446
|
+
alignOffset,
|
|
447
|
+
side,
|
|
448
|
+
sideOffset,
|
|
449
|
+
children: /* @__PURE__ */ jsx(
|
|
450
|
+
Menu.Popup,
|
|
451
|
+
{
|
|
452
|
+
"data-slot": "dropdown-menu-content",
|
|
453
|
+
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),
|
|
454
|
+
...props
|
|
455
|
+
}
|
|
456
|
+
)
|
|
457
|
+
}
|
|
458
|
+
) });
|
|
459
|
+
}
|
|
460
|
+
function DropdownMenuGroup({ ...props }) {
|
|
461
|
+
return /* @__PURE__ */ jsx(Menu.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
462
|
+
}
|
|
463
|
+
function DropdownMenuLabel({
|
|
464
|
+
className,
|
|
465
|
+
inset,
|
|
466
|
+
...props
|
|
467
|
+
}) {
|
|
468
|
+
return /* @__PURE__ */ jsx(
|
|
469
|
+
Menu.GroupLabel,
|
|
470
|
+
{
|
|
471
|
+
"data-slot": "dropdown-menu-label",
|
|
472
|
+
"data-inset": inset,
|
|
473
|
+
className: cn("text-muted-foreground px-3 py-2.5 text-xs data-[inset]:pl-8", className),
|
|
474
|
+
...props
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
function DropdownMenuItem({
|
|
479
|
+
className,
|
|
480
|
+
inset,
|
|
481
|
+
variant = "default",
|
|
482
|
+
...props
|
|
483
|
+
}) {
|
|
484
|
+
return /* @__PURE__ */ jsx(
|
|
485
|
+
Menu.Item,
|
|
486
|
+
{
|
|
487
|
+
"data-slot": "dropdown-menu-item",
|
|
488
|
+
"data-inset": inset,
|
|
489
|
+
"data-variant": variant,
|
|
490
|
+
className: cn(
|
|
491
|
+
"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",
|
|
492
|
+
className
|
|
493
|
+
),
|
|
494
|
+
...props
|
|
495
|
+
}
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
function DropdownMenuCheckboxItem({
|
|
499
|
+
className,
|
|
500
|
+
children,
|
|
501
|
+
checked,
|
|
502
|
+
...props
|
|
503
|
+
}) {
|
|
504
|
+
return /* @__PURE__ */ jsxs(
|
|
505
|
+
Menu.CheckboxItem,
|
|
506
|
+
{
|
|
507
|
+
"data-slot": "dropdown-menu-checkbox-item",
|
|
508
|
+
className: cn(
|
|
509
|
+
"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",
|
|
510
|
+
className
|
|
511
|
+
),
|
|
512
|
+
checked,
|
|
513
|
+
...props,
|
|
514
|
+
children: [
|
|
515
|
+
/* @__PURE__ */ jsx(
|
|
516
|
+
"span",
|
|
517
|
+
{
|
|
518
|
+
className: "pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none",
|
|
519
|
+
"data-slot": "dropdown-menu-checkbox-item-indicator",
|
|
520
|
+
children: /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx(
|
|
521
|
+
IconCheck,
|
|
522
|
+
{}
|
|
523
|
+
) })
|
|
524
|
+
}
|
|
525
|
+
),
|
|
526
|
+
children
|
|
527
|
+
]
|
|
528
|
+
}
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
function DropdownMenuSeparator({
|
|
532
|
+
className,
|
|
533
|
+
...props
|
|
534
|
+
}) {
|
|
535
|
+
return /* @__PURE__ */ jsx(
|
|
536
|
+
Menu.Separator,
|
|
537
|
+
{
|
|
538
|
+
"data-slot": "dropdown-menu-separator",
|
|
539
|
+
className: cn("bg-border/50 -mx-1 my-1 h-px", className),
|
|
540
|
+
...props
|
|
541
|
+
}
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
function Composer({
|
|
545
|
+
value,
|
|
546
|
+
onChange,
|
|
547
|
+
onSubmit,
|
|
548
|
+
placeholder = "Type a message...",
|
|
549
|
+
isLoading,
|
|
550
|
+
className,
|
|
551
|
+
options = [],
|
|
552
|
+
autoFocus = false,
|
|
553
|
+
defaultSelectedIds = []
|
|
554
|
+
}) {
|
|
555
|
+
const [selectedOptions, setSelectedOptions] = React11__default.useState(
|
|
556
|
+
() => new Set(defaultSelectedIds)
|
|
557
|
+
);
|
|
558
|
+
const toggleOption = (id, groupOptions, type = "multiple") => {
|
|
559
|
+
const next = new Set(selectedOptions);
|
|
560
|
+
if (type === "single") {
|
|
561
|
+
const isAlreadySelected = next.has(id);
|
|
562
|
+
if (groupOptions) {
|
|
563
|
+
groupOptions.forEach((o) => next.delete(o.id));
|
|
564
|
+
}
|
|
565
|
+
if (!isAlreadySelected) {
|
|
566
|
+
next.add(id);
|
|
567
|
+
}
|
|
568
|
+
} else {
|
|
569
|
+
if (next.has(id)) {
|
|
570
|
+
next.delete(id);
|
|
571
|
+
} else {
|
|
572
|
+
next.add(id);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
setSelectedOptions(next);
|
|
576
|
+
};
|
|
577
|
+
const handleInternalSubmit = () => {
|
|
578
|
+
const state = {};
|
|
579
|
+
options.forEach((group) => {
|
|
580
|
+
const selectedInGroup = group.options.filter(
|
|
581
|
+
(o) => selectedOptions.has(o.id)
|
|
582
|
+
);
|
|
583
|
+
if (selectedInGroup.length > 0) {
|
|
584
|
+
if (group.type === "single") {
|
|
585
|
+
state[group.id] = selectedInGroup[0].value;
|
|
586
|
+
} else {
|
|
587
|
+
state[group.id] = selectedInGroup.map((o) => ({
|
|
588
|
+
id: o.id,
|
|
589
|
+
value: o.value
|
|
590
|
+
}));
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
onSubmit(state);
|
|
595
|
+
};
|
|
596
|
+
const handleKeyDown = (e) => {
|
|
597
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
598
|
+
e.preventDefault();
|
|
599
|
+
handleInternalSubmit();
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col w-full border-input border-[1.5px] rounded-3xl bg-background shadow-sm focus-within:border-ring transition-all p-2", children: [
|
|
603
|
+
/* @__PURE__ */ jsx(
|
|
604
|
+
Textarea,
|
|
605
|
+
{
|
|
606
|
+
value,
|
|
607
|
+
onChange: (e) => onChange(e.target.value),
|
|
608
|
+
onKeyDown: handleKeyDown,
|
|
609
|
+
placeholder,
|
|
610
|
+
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",
|
|
611
|
+
autoFocus
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
|
|
615
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: options.map((group) => {
|
|
616
|
+
const selectedInGroup = group.options.filter(
|
|
617
|
+
(o) => selectedOptions.has(o.id)
|
|
618
|
+
);
|
|
619
|
+
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : `${group.label} (${selectedInGroup.length})`;
|
|
620
|
+
const isSingle = group.type === "single";
|
|
621
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
622
|
+
/* @__PURE__ */ jsx(
|
|
623
|
+
DropdownMenuTrigger,
|
|
624
|
+
{
|
|
625
|
+
render: /* @__PURE__ */ jsxs(
|
|
626
|
+
Button,
|
|
627
|
+
{
|
|
628
|
+
variant: "ghost",
|
|
629
|
+
size: "sm",
|
|
630
|
+
className: cn(
|
|
631
|
+
selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
|
|
632
|
+
),
|
|
633
|
+
children: [
|
|
634
|
+
label,
|
|
635
|
+
/* @__PURE__ */ jsx(IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
636
|
+
]
|
|
637
|
+
}
|
|
638
|
+
)
|
|
639
|
+
}
|
|
640
|
+
),
|
|
641
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "w-56", children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
642
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: group.label }),
|
|
643
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
644
|
+
group.options.map((option) => /* @__PURE__ */ jsx(
|
|
645
|
+
DropdownMenuCheckboxItem,
|
|
646
|
+
{
|
|
647
|
+
checked: selectedOptions.has(option.id),
|
|
648
|
+
onCheckedChange: () => toggleOption(
|
|
649
|
+
option.id,
|
|
650
|
+
group.options,
|
|
651
|
+
isSingle ? "single" : "multiple"
|
|
652
|
+
),
|
|
653
|
+
onSelect: (e) => e.preventDefault(),
|
|
654
|
+
children: option.label
|
|
655
|
+
},
|
|
656
|
+
option.id
|
|
657
|
+
))
|
|
658
|
+
] }) })
|
|
659
|
+
] }, group.id);
|
|
660
|
+
}) }),
|
|
661
|
+
/* @__PURE__ */ jsx(
|
|
662
|
+
Button,
|
|
663
|
+
{
|
|
664
|
+
type: "submit",
|
|
665
|
+
disabled: !value.trim() && !isLoading || isLoading,
|
|
666
|
+
size: "icon-lg",
|
|
667
|
+
onClick: handleInternalSubmit,
|
|
668
|
+
children: isLoading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsx(IconArrowUp, { className: "h-5 w-5" })
|
|
669
|
+
}
|
|
670
|
+
)
|
|
671
|
+
] })
|
|
672
|
+
] }) });
|
|
673
|
+
}
|
|
313
674
|
function Card({
|
|
314
675
|
className,
|
|
315
676
|
size = "default",
|
|
@@ -378,7 +739,7 @@ var Card2 = ({
|
|
|
378
739
|
return /* @__PURE__ */ jsxs(
|
|
379
740
|
Card,
|
|
380
741
|
{
|
|
381
|
-
className: cn("
|
|
742
|
+
className: cn("min-w-96", className),
|
|
382
743
|
style,
|
|
383
744
|
children: [
|
|
384
745
|
(title || subtitle) && /* @__PURE__ */ jsxs(CardHeader, { className: "pb-3", children: [
|
|
@@ -693,26 +1054,132 @@ var ListItem = ({
|
|
|
693
1054
|
}
|
|
694
1055
|
);
|
|
695
1056
|
};
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
1057
|
+
function Dialog({ ...props }) {
|
|
1058
|
+
return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "dialog", ...props });
|
|
1059
|
+
}
|
|
1060
|
+
function DialogTrigger({ ...props }) {
|
|
1061
|
+
return /* @__PURE__ */ jsx(Dialog$1.Trigger, { "data-slot": "dialog-trigger", ...props });
|
|
1062
|
+
}
|
|
1063
|
+
function DialogPortal({ ...props }) {
|
|
1064
|
+
return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "dialog-portal", ...props });
|
|
1065
|
+
}
|
|
1066
|
+
function DialogOverlay({
|
|
700
1067
|
className,
|
|
701
|
-
|
|
702
|
-
})
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
1068
|
+
...props
|
|
1069
|
+
}) {
|
|
1070
|
+
return /* @__PURE__ */ jsx(
|
|
1071
|
+
Dialog$1.Backdrop,
|
|
1072
|
+
{
|
|
1073
|
+
"data-slot": "dialog-overlay",
|
|
1074
|
+
className: cn(
|
|
1075
|
+
"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",
|
|
1076
|
+
className
|
|
1077
|
+
),
|
|
1078
|
+
...props
|
|
1079
|
+
}
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
function DialogContent({
|
|
1083
|
+
className,
|
|
1084
|
+
...props
|
|
1085
|
+
}) {
|
|
1086
|
+
return /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
1087
|
+
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
1088
|
+
/* @__PURE__ */ jsx(
|
|
1089
|
+
Dialog$1.Popup,
|
|
1090
|
+
{
|
|
1091
|
+
"data-slot": "dialog-content",
|
|
1092
|
+
className: cn(
|
|
1093
|
+
"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",
|
|
1094
|
+
className
|
|
1095
|
+
),
|
|
1096
|
+
...props
|
|
1097
|
+
}
|
|
1098
|
+
)
|
|
1099
|
+
] });
|
|
1100
|
+
}
|
|
1101
|
+
function DialogClose({
|
|
1102
|
+
className,
|
|
1103
|
+
...props
|
|
1104
|
+
}) {
|
|
1105
|
+
return /* @__PURE__ */ jsx(
|
|
1106
|
+
Dialog$1.Close,
|
|
1107
|
+
{
|
|
1108
|
+
"data-slot": "dialog-close",
|
|
1109
|
+
className: cn(
|
|
1110
|
+
"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",
|
|
1111
|
+
className
|
|
1112
|
+
),
|
|
1113
|
+
...props
|
|
1114
|
+
}
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
function DialogHeader({
|
|
1118
|
+
className,
|
|
1119
|
+
...props
|
|
1120
|
+
}) {
|
|
1121
|
+
return /* @__PURE__ */ jsx(
|
|
1122
|
+
"div",
|
|
1123
|
+
{
|
|
1124
|
+
"data-slot": "dialog-header",
|
|
1125
|
+
className: cn(
|
|
1126
|
+
"flex flex-col space-y-1.5 text-center sm:text-left",
|
|
1127
|
+
className
|
|
1128
|
+
),
|
|
1129
|
+
...props
|
|
1130
|
+
}
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
function DialogTitle({
|
|
1134
|
+
className,
|
|
1135
|
+
...props
|
|
1136
|
+
}) {
|
|
1137
|
+
return /* @__PURE__ */ jsx(
|
|
1138
|
+
Dialog$1.Title,
|
|
1139
|
+
{
|
|
1140
|
+
"data-slot": "dialog-title",
|
|
1141
|
+
className: cn(
|
|
1142
|
+
"text-lg font-semibold leading-none tracking-tight",
|
|
1143
|
+
className
|
|
1144
|
+
),
|
|
1145
|
+
...props
|
|
1146
|
+
}
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
function DialogDescription({
|
|
1150
|
+
className,
|
|
1151
|
+
...props
|
|
1152
|
+
}) {
|
|
1153
|
+
return /* @__PURE__ */ jsx(
|
|
1154
|
+
Dialog$1.Description,
|
|
1155
|
+
{
|
|
1156
|
+
"data-slot": "dialog-description",
|
|
1157
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
1158
|
+
...props
|
|
1159
|
+
}
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
var Image = ({
|
|
1163
|
+
src,
|
|
1164
|
+
alt,
|
|
1165
|
+
size = "sm",
|
|
1166
|
+
className,
|
|
1167
|
+
style
|
|
1168
|
+
}) => {
|
|
1169
|
+
const [hasError, setHasError] = useState(false);
|
|
1170
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
1171
|
+
const [open, setOpen] = useState(false);
|
|
1172
|
+
const sizes = {
|
|
1173
|
+
sm: "h-11",
|
|
1174
|
+
md: "h-22",
|
|
1175
|
+
lg: "h-44"
|
|
1176
|
+
};
|
|
1177
|
+
const handleError = () => {
|
|
1178
|
+
setHasError(true);
|
|
1179
|
+
setIsLoading(false);
|
|
1180
|
+
};
|
|
1181
|
+
const handleLoad = () => {
|
|
1182
|
+
setIsLoading(false);
|
|
716
1183
|
};
|
|
717
1184
|
if (hasError) {
|
|
718
1185
|
return /* @__PURE__ */ jsx(
|
|
@@ -728,22 +1195,67 @@ var Image = ({
|
|
|
728
1195
|
}
|
|
729
1196
|
);
|
|
730
1197
|
}
|
|
731
|
-
return /* @__PURE__ */ jsxs(
|
|
1198
|
+
return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
1199
|
+
/* @__PURE__ */ jsx(DialogTrigger, { children: /* @__PURE__ */ jsxs(
|
|
1200
|
+
"div",
|
|
1201
|
+
{
|
|
1202
|
+
className: cn("relative overflow-hidden rounded-md border cursor-pointer", className),
|
|
1203
|
+
style,
|
|
1204
|
+
children: [
|
|
1205
|
+
/* @__PURE__ */ jsx(
|
|
1206
|
+
"img",
|
|
1207
|
+
{
|
|
1208
|
+
src,
|
|
1209
|
+
alt,
|
|
1210
|
+
onError: handleError,
|
|
1211
|
+
onLoad: handleLoad,
|
|
1212
|
+
className: cn(
|
|
1213
|
+
"block h-auto w-full transition-opacity duration-200 hover:opacity-90",
|
|
1214
|
+
isLoading ? "opacity-0" : "opacity-100",
|
|
1215
|
+
sizes[size]
|
|
1216
|
+
)
|
|
1217
|
+
}
|
|
1218
|
+
),
|
|
1219
|
+
isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-muted animate-pulse" })
|
|
1220
|
+
]
|
|
1221
|
+
}
|
|
1222
|
+
) }),
|
|
732
1223
|
/* @__PURE__ */ jsx(
|
|
733
|
-
|
|
1224
|
+
DialogContent,
|
|
734
1225
|
{
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1226
|
+
className: "max-w-[90vw] max-h-[90vh] p-0 bg-transparent border-none shadow-none",
|
|
1227
|
+
onClick: (e) => e.stopPropagation(),
|
|
1228
|
+
children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
1229
|
+
/* @__PURE__ */ jsx(DialogClose, { className: "absolute -top-10 right-0 text-white hover:text-gray-300 transition-colors z-10 bg-black/50 rounded-full p-2", children: /* @__PURE__ */ jsx(
|
|
1230
|
+
"svg",
|
|
1231
|
+
{
|
|
1232
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1233
|
+
className: "h-5 w-5",
|
|
1234
|
+
fill: "none",
|
|
1235
|
+
viewBox: "0 0 24 24",
|
|
1236
|
+
stroke: "currentColor",
|
|
1237
|
+
children: /* @__PURE__ */ jsx(
|
|
1238
|
+
"path",
|
|
1239
|
+
{
|
|
1240
|
+
strokeLinecap: "round",
|
|
1241
|
+
strokeLinejoin: "round",
|
|
1242
|
+
strokeWidth: 2,
|
|
1243
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
1244
|
+
}
|
|
1245
|
+
)
|
|
1246
|
+
}
|
|
1247
|
+
) }),
|
|
1248
|
+
/* @__PURE__ */ jsx(
|
|
1249
|
+
"img",
|
|
1250
|
+
{
|
|
1251
|
+
src,
|
|
1252
|
+
alt: alt || "Enlarged image",
|
|
1253
|
+
className: "max-w-full max-h-[90vh] object-contain rounded-lg"
|
|
1254
|
+
}
|
|
1255
|
+
)
|
|
1256
|
+
] })
|
|
744
1257
|
}
|
|
745
|
-
)
|
|
746
|
-
isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-muted animate-pulse" })
|
|
1258
|
+
)
|
|
747
1259
|
] });
|
|
748
1260
|
};
|
|
749
1261
|
var Icon = ({
|
|
@@ -1199,19 +1711,6 @@ var Input2 = ({
|
|
|
1199
1711
|
)
|
|
1200
1712
|
] });
|
|
1201
1713
|
};
|
|
1202
|
-
function Textarea({ className, ...props }) {
|
|
1203
|
-
return /* @__PURE__ */ jsx(
|
|
1204
|
-
"textarea",
|
|
1205
|
-
{
|
|
1206
|
-
"data-slot": "textarea",
|
|
1207
|
-
className: cn(
|
|
1208
|
-
"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",
|
|
1209
|
-
className
|
|
1210
|
-
),
|
|
1211
|
-
...props
|
|
1212
|
-
}
|
|
1213
|
-
);
|
|
1214
|
-
}
|
|
1215
1714
|
var Textarea2 = ({
|
|
1216
1715
|
placeholder,
|
|
1217
1716
|
defaultValue,
|
|
@@ -1583,50 +2082,6 @@ var RadioGroup = ({
|
|
|
1583
2082
|
)
|
|
1584
2083
|
] });
|
|
1585
2084
|
};
|
|
1586
|
-
var buttonVariants = cva(
|
|
1587
|
-
"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",
|
|
1588
|
-
{
|
|
1589
|
-
variants: {
|
|
1590
|
-
variant: {
|
|
1591
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
1592
|
-
outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
1593
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
1594
|
-
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
1595
|
-
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",
|
|
1596
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
1597
|
-
},
|
|
1598
|
-
size: {
|
|
1599
|
-
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
1600
|
-
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",
|
|
1601
|
-
sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
1602
|
-
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
1603
|
-
icon: "size-9",
|
|
1604
|
-
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
1605
|
-
"icon-sm": "size-8",
|
|
1606
|
-
"icon-lg": "size-10"
|
|
1607
|
-
}
|
|
1608
|
-
},
|
|
1609
|
-
defaultVariants: {
|
|
1610
|
-
variant: "default",
|
|
1611
|
-
size: "default"
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
);
|
|
1615
|
-
function Button({
|
|
1616
|
-
className,
|
|
1617
|
-
variant = "default",
|
|
1618
|
-
size = "default",
|
|
1619
|
-
...props
|
|
1620
|
-
}) {
|
|
1621
|
-
return /* @__PURE__ */ jsx(
|
|
1622
|
-
Button$1,
|
|
1623
|
-
{
|
|
1624
|
-
"data-slot": "button",
|
|
1625
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
1626
|
-
...props
|
|
1627
|
-
}
|
|
1628
|
-
);
|
|
1629
|
-
}
|
|
1630
2085
|
var Button2 = ({
|
|
1631
2086
|
label,
|
|
1632
2087
|
variant = "primary",
|
|
@@ -1643,6 +2098,8 @@ var Button2 = ({
|
|
|
1643
2098
|
secondary: "secondary",
|
|
1644
2099
|
danger: "destructive",
|
|
1645
2100
|
outline: "outline",
|
|
2101
|
+
ghost: "ghost",
|
|
2102
|
+
link: "link",
|
|
1646
2103
|
success: "default"
|
|
1647
2104
|
// Success doesn't have a direct shadcn mapping in base variant, default is usually primary
|
|
1648
2105
|
};
|
|
@@ -1711,6 +2168,32 @@ var Form = ({ children, onSubmitAction, className, style }) => {
|
|
|
1711
2168
|
}
|
|
1712
2169
|
);
|
|
1713
2170
|
};
|
|
2171
|
+
function StarterPrompts({
|
|
2172
|
+
prompts,
|
|
2173
|
+
onPromptClick
|
|
2174
|
+
}) {
|
|
2175
|
+
if (!prompts || prompts.length === 0) {
|
|
2176
|
+
return null;
|
|
2177
|
+
}
|
|
2178
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-4 animate-in fade-in slide-in-from-bottom-4 duration-500 mt-auto max-w-2xl", children: [
|
|
2179
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: "What can I help with today?" }) }),
|
|
2180
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 w-full", children: prompts.map((item, index) => /* @__PURE__ */ jsx(
|
|
2181
|
+
Button2,
|
|
2182
|
+
{
|
|
2183
|
+
label: item.label,
|
|
2184
|
+
variant: "ghost",
|
|
2185
|
+
size: "lg",
|
|
2186
|
+
onClickAction: {
|
|
2187
|
+
type: "text",
|
|
2188
|
+
role: "user",
|
|
2189
|
+
data: { content: item.prompt }
|
|
2190
|
+
},
|
|
2191
|
+
className: "w-full justify-start"
|
|
2192
|
+
},
|
|
2193
|
+
index
|
|
2194
|
+
)) })
|
|
2195
|
+
] });
|
|
2196
|
+
}
|
|
1714
2197
|
function UIRenderer({ node }) {
|
|
1715
2198
|
const { type, props, children } = node;
|
|
1716
2199
|
const typeMap = {
|
|
@@ -1749,69 +2232,108 @@ function UIRenderer({ node }) {
|
|
|
1749
2232
|
const componentProps = { ...props };
|
|
1750
2233
|
return /* @__PURE__ */ jsx(Component, { ...componentProps, children: renderedChildren });
|
|
1751
2234
|
}
|
|
1752
|
-
function
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
placeholder = "Type a message...",
|
|
1757
|
-
isLoading,
|
|
1758
|
-
className
|
|
1759
|
-
}) {
|
|
1760
|
-
const handleKeyDown = (e) => {
|
|
1761
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
1762
|
-
e.preventDefault();
|
|
1763
|
-
onSubmit();
|
|
2235
|
+
function MessageContent({ events }) {
|
|
2236
|
+
return /* @__PURE__ */ jsx(Fragment, { children: events.map((event, index) => {
|
|
2237
|
+
if (event.type === "text-delta") {
|
|
2238
|
+
return /* @__PURE__ */ jsx("span", { children: event.data?.delta }, index);
|
|
1764
2239
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
{
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
2240
|
+
if (event.type === "text") {
|
|
2241
|
+
return /* @__PURE__ */ jsx("p", { children: event.data?.content || event.data?.text }, index);
|
|
2242
|
+
}
|
|
2243
|
+
if (event.ui) {
|
|
2244
|
+
return /* @__PURE__ */ jsx(UIRenderer, { node: event.ui }, index);
|
|
2245
|
+
}
|
|
2246
|
+
return null;
|
|
2247
|
+
}) });
|
|
2248
|
+
}
|
|
2249
|
+
function MessageBubble({ message }) {
|
|
2250
|
+
const isUser = message.role === "user";
|
|
2251
|
+
return /* @__PURE__ */ jsx(
|
|
2252
|
+
"div",
|
|
2253
|
+
{
|
|
2254
|
+
className: cn(
|
|
2255
|
+
"flex flex-col",
|
|
2256
|
+
isUser ? "items-end" : "items-start"
|
|
2257
|
+
),
|
|
2258
|
+
children: /* @__PURE__ */ jsx(
|
|
2259
|
+
"div",
|
|
2260
|
+
{
|
|
2261
|
+
className: cn(
|
|
2262
|
+
"flex flex-col items-start max-w-[85%] rounded-2xl px-4 py-2 space-y-4 whitespace-pre-wrap",
|
|
2263
|
+
isUser ? "bg-primary text-primary-foreground" : "px-0 py-0 text-foreground"
|
|
2264
|
+
),
|
|
2265
|
+
children: /* @__PURE__ */ jsx(MessageContent, { events: message.content })
|
|
2266
|
+
}
|
|
2267
|
+
)
|
|
2268
|
+
}
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
2271
|
+
function LoadingIndicator({ status }) {
|
|
2272
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
2273
|
+
const message = status?.message || "Processing...";
|
|
2274
|
+
const details = status?.details;
|
|
2275
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2276
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground group", children: [
|
|
2277
|
+
/* @__PURE__ */ jsx(IconLoader2, { className: "size-3.5 animate-spin" }),
|
|
2278
|
+
/* @__PURE__ */ jsx("div", { className: "animate-pulse", children: message }),
|
|
2279
|
+
details && /* @__PURE__ */ jsx(
|
|
2280
|
+
"button",
|
|
2281
|
+
{
|
|
2282
|
+
onClick: () => setIsExpanded(!isExpanded),
|
|
2283
|
+
className: "p-0.5 hover:bg-muted rounded-sm transition-colors flex items-center justify-center",
|
|
2284
|
+
title: isExpanded ? "Hide details" : "Show details",
|
|
2285
|
+
children: isExpanded ? /* @__PURE__ */ jsx(IconChevronUp, { className: "size-3.5 opacity-50 group-hover:opacity-100" }) : /* @__PURE__ */ jsx(IconChevronDown, { className: "size-3.5 opacity-50 group-hover:opacity-100" })
|
|
2286
|
+
}
|
|
2287
|
+
)
|
|
2288
|
+
] }),
|
|
2289
|
+
isExpanded && details && /* @__PURE__ */ jsx("div", { className: "text-[10px] leading-relaxed font-mono bg-muted/30 p-2.5 rounded border border-border/50 max-h-64 overflow-y-auto whitespace-pre-wrap text-muted-foreground shadow-sm", children: details })
|
|
2290
|
+
] });
|
|
2291
|
+
}
|
|
2292
|
+
function ErrorDisplay({ error }) {
|
|
2293
|
+
return /* @__PURE__ */ jsx("div", { className: "text-destructive p-2 border border-destructive rounded-md bg-destructive/10", children: error.message });
|
|
2294
|
+
}
|
|
2295
|
+
function MessageList({ messages, isLoading, error, loadingStatus }) {
|
|
2296
|
+
if (messages.length === 0) {
|
|
2297
|
+
return null;
|
|
2298
|
+
}
|
|
2299
|
+
const isTextStreaming = useMemo(() => {
|
|
2300
|
+
if (messages.length === 0 || !isLoading) return false;
|
|
2301
|
+
const lastMessage = messages[messages.length - 1];
|
|
2302
|
+
return lastMessage.content.some((event) => event.type === "text-delta");
|
|
2303
|
+
}, [messages, isLoading]);
|
|
2304
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
2305
|
+
messages.map((message, index) => /* @__PURE__ */ jsx(MessageBubble, { message }, index)),
|
|
2306
|
+
isLoading && !isTextStreaming && /* @__PURE__ */ jsx(LoadingIndicator, { status: loadingStatus }),
|
|
2307
|
+
error && /* @__PURE__ */ jsx(ErrorDisplay, { error })
|
|
2308
|
+
] });
|
|
1792
2309
|
}
|
|
1793
2310
|
function Thread({
|
|
1794
2311
|
className,
|
|
1795
2312
|
placeholder = "Type a message...",
|
|
1796
2313
|
starterPrompts,
|
|
1797
|
-
onStarterPromptClick
|
|
2314
|
+
onStarterPromptClick,
|
|
2315
|
+
options,
|
|
2316
|
+
autoFocus = false,
|
|
2317
|
+
defaultSelectedIds
|
|
1798
2318
|
}) {
|
|
1799
|
-
const { messages, isLoading, error, sendEvent } = useMelony();
|
|
2319
|
+
const { messages, isLoading, error, sendEvent, loadingStatus } = useMelony();
|
|
1800
2320
|
const [input, setInput] = useState("");
|
|
1801
2321
|
const messagesEndRef = useRef(null);
|
|
1802
2322
|
useEffect(() => {
|
|
1803
2323
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1804
2324
|
}, [messages]);
|
|
1805
|
-
const handleSubmit = async (
|
|
1806
|
-
e?.preventDefault();
|
|
2325
|
+
const handleSubmit = async (state, overrideInput) => {
|
|
1807
2326
|
const text = (overrideInput ?? input).trim();
|
|
1808
2327
|
if (!text || isLoading) return;
|
|
1809
2328
|
if (!overrideInput) setInput("");
|
|
1810
|
-
await sendEvent(
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
2329
|
+
await sendEvent(
|
|
2330
|
+
{
|
|
2331
|
+
type: "text",
|
|
2332
|
+
role: "user",
|
|
2333
|
+
data: { content: text }
|
|
2334
|
+
},
|
|
2335
|
+
{ state }
|
|
2336
|
+
);
|
|
1815
2337
|
};
|
|
1816
2338
|
const handleStarterPromptClick = (prompt) => {
|
|
1817
2339
|
if (onStarterPromptClick) {
|
|
@@ -1820,66 +2342,73 @@ function Thread({
|
|
|
1820
2342
|
handleSubmit(void 0, prompt);
|
|
1821
2343
|
}
|
|
1822
2344
|
};
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
2345
|
+
const showStarterPrompts = messages.length === 0 && starterPrompts && starterPrompts.length > 0;
|
|
2346
|
+
return /* @__PURE__ */ jsxs(
|
|
2347
|
+
"div",
|
|
2348
|
+
{
|
|
2349
|
+
className: cn("relative flex flex-col h-full bg-background", className),
|
|
2350
|
+
children: [
|
|
2351
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-4 pb-36", children: [
|
|
2352
|
+
/* @__PURE__ */ jsxs(
|
|
2353
|
+
"div",
|
|
1830
2354
|
{
|
|
1831
|
-
|
|
1832
|
-
|
|
2355
|
+
className: cn(
|
|
2356
|
+
"max-w-4xl mx-auto w-full p-4",
|
|
2357
|
+
showStarterPrompts && "min-h-full flex flex-col"
|
|
2358
|
+
),
|
|
1833
2359
|
children: [
|
|
1834
|
-
|
|
1835
|
-
|
|
2360
|
+
showStarterPrompts && /* @__PURE__ */ jsx(
|
|
2361
|
+
StarterPrompts,
|
|
2362
|
+
{
|
|
2363
|
+
prompts: starterPrompts,
|
|
2364
|
+
onPromptClick: handleStarterPromptClick
|
|
2365
|
+
}
|
|
2366
|
+
),
|
|
2367
|
+
/* @__PURE__ */ jsx(
|
|
2368
|
+
MessageList,
|
|
2369
|
+
{
|
|
2370
|
+
messages,
|
|
2371
|
+
isLoading,
|
|
2372
|
+
error,
|
|
2373
|
+
loadingStatus
|
|
2374
|
+
}
|
|
2375
|
+
)
|
|
1836
2376
|
]
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
|
|
2377
|
+
}
|
|
2378
|
+
),
|
|
2379
|
+
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
1840
2380
|
] }),
|
|
1841
|
-
|
|
1842
|
-
|
|
2381
|
+
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 p-4 w-full", children: /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto", children: /* @__PURE__ */ jsx(
|
|
2382
|
+
Composer,
|
|
1843
2383
|
{
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
] }),
|
|
1873
|
-
/* @__PURE__ */ jsx("div", { className: "p-4 border-t w-full", children: /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto", children: /* @__PURE__ */ jsx(
|
|
1874
|
-
Composer,
|
|
1875
|
-
{
|
|
1876
|
-
value: input,
|
|
1877
|
-
onChange: setInput,
|
|
1878
|
-
onSubmit: handleSubmit,
|
|
1879
|
-
placeholder,
|
|
1880
|
-
isLoading
|
|
1881
|
-
}
|
|
1882
|
-
) }) })
|
|
2384
|
+
value: input,
|
|
2385
|
+
onChange: setInput,
|
|
2386
|
+
onSubmit: handleSubmit,
|
|
2387
|
+
placeholder,
|
|
2388
|
+
isLoading,
|
|
2389
|
+
options,
|
|
2390
|
+
autoFocus,
|
|
2391
|
+
defaultSelectedIds
|
|
2392
|
+
}
|
|
2393
|
+
) }) })
|
|
2394
|
+
]
|
|
2395
|
+
}
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
function ChatHeader({
|
|
2399
|
+
title,
|
|
2400
|
+
leftContent,
|
|
2401
|
+
rightContent,
|
|
2402
|
+
className,
|
|
2403
|
+
titleClassName,
|
|
2404
|
+
children
|
|
2405
|
+
}) {
|
|
2406
|
+
if (children) {
|
|
2407
|
+
return /* @__PURE__ */ jsx("div", { className: cn("p-4 border-b border-border h-14 flex items-center shrink-0", className), children });
|
|
2408
|
+
}
|
|
2409
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("p-4 border-b border-border h-14 flex items-center justify-between shrink-0", className), children: [
|
|
2410
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: leftContent }),
|
|
2411
|
+
rightContent && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 shrink-0 ml-2", children: rightContent })
|
|
1883
2412
|
] });
|
|
1884
2413
|
}
|
|
1885
2414
|
var ThreadList = ({
|
|
@@ -1887,13 +2416,7 @@ var ThreadList = ({
|
|
|
1887
2416
|
emptyState,
|
|
1888
2417
|
onThreadSelect
|
|
1889
2418
|
}) => {
|
|
1890
|
-
const {
|
|
1891
|
-
threads,
|
|
1892
|
-
activeThreadId,
|
|
1893
|
-
selectThread,
|
|
1894
|
-
createThread,
|
|
1895
|
-
deleteThread
|
|
1896
|
-
} = useThreads();
|
|
2419
|
+
const { threads, activeThreadId, selectThread, createThread, deleteThread } = useThreads();
|
|
1897
2420
|
const handleThreadClick = (threadId) => {
|
|
1898
2421
|
if (threadId !== activeThreadId) {
|
|
1899
2422
|
selectThread(threadId);
|
|
@@ -1931,10 +2454,10 @@ var ThreadList = ({
|
|
|
1931
2454
|
return d.toLocaleDateString();
|
|
1932
2455
|
};
|
|
1933
2456
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full", className), children: [
|
|
1934
|
-
/* @__PURE__ */ jsx("div", { className: "p-2
|
|
2457
|
+
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxs(
|
|
1935
2458
|
Button,
|
|
1936
2459
|
{
|
|
1937
|
-
variant: "
|
|
2460
|
+
variant: "ghost",
|
|
1938
2461
|
size: "sm",
|
|
1939
2462
|
onClick: handleNewThread,
|
|
1940
2463
|
className: "w-full justify-start",
|
|
@@ -1955,31 +2478,13 @@ var ThreadList = ({
|
|
|
1955
2478
|
{
|
|
1956
2479
|
onClick: () => handleThreadClick(thread.id),
|
|
1957
2480
|
className: cn(
|
|
1958
|
-
"group relative flex items-center gap-3
|
|
1959
|
-
isActive ? "bg-
|
|
2481
|
+
"group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
|
|
2482
|
+
isActive ? "bg-muted" : "hover:bg-muted"
|
|
1960
2483
|
),
|
|
1961
2484
|
children: [
|
|
1962
2485
|
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1963
|
-
/* @__PURE__ */ jsx(
|
|
1964
|
-
|
|
1965
|
-
{
|
|
1966
|
-
className: cn(
|
|
1967
|
-
"text-sm font-medium truncate",
|
|
1968
|
-
isActive && "text-primary-foreground"
|
|
1969
|
-
),
|
|
1970
|
-
children: thread.title || `Thread ${thread.id.slice(0, 8)}`
|
|
1971
|
-
}
|
|
1972
|
-
),
|
|
1973
|
-
thread.updatedAt && /* @__PURE__ */ jsx(
|
|
1974
|
-
"span",
|
|
1975
|
-
{
|
|
1976
|
-
className: cn(
|
|
1977
|
-
"text-xs shrink-0",
|
|
1978
|
-
isActive ? "text-primary-foreground/70" : "text-muted-foreground"
|
|
1979
|
-
),
|
|
1980
|
-
children: formatDate(thread.updatedAt)
|
|
1981
|
-
}
|
|
1982
|
-
)
|
|
2486
|
+
/* @__PURE__ */ jsx("p", { className: cn("text-sm font-medium truncate"), children: thread.title || `Thread ${thread.id.slice(0, 8)}` }),
|
|
2487
|
+
thread.updatedAt && /* @__PURE__ */ jsx("span", { className: cn("text-xs shrink-0"), children: formatDate(thread.updatedAt) })
|
|
1983
2488
|
] }) }),
|
|
1984
2489
|
/* @__PURE__ */ jsx(
|
|
1985
2490
|
Button,
|
|
@@ -2005,7 +2510,10 @@ function ChatPopup({
|
|
|
2005
2510
|
title = "Chat",
|
|
2006
2511
|
placeholder = "Message the AI",
|
|
2007
2512
|
starterPrompts,
|
|
2008
|
-
|
|
2513
|
+
options,
|
|
2514
|
+
defaultOpen = false,
|
|
2515
|
+
headerProps,
|
|
2516
|
+
defaultSelectedIds
|
|
2009
2517
|
}) {
|
|
2010
2518
|
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
2011
2519
|
const [view, setView] = useState("chat");
|
|
@@ -2019,10 +2527,12 @@ function ChatPopup({
|
|
|
2019
2527
|
}
|
|
2020
2528
|
};
|
|
2021
2529
|
return /* @__PURE__ */ jsxs("div", { className: "fixed bottom-6 right-6 z-50 flex flex-col items-end gap-4 font-sans", children: [
|
|
2022
|
-
isOpen && /* @__PURE__ */ jsxs(Card, { className: "py-0 w-[440px] h-[640px] flex flex-col overflow-hidden border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60 shadow-2xl animate-in fade-in zoom-in-95 duration-200 origin-bottom-right", children: [
|
|
2023
|
-
/* @__PURE__ */
|
|
2024
|
-
|
|
2025
|
-
|
|
2530
|
+
isOpen && /* @__PURE__ */ jsxs(Card, { className: "py-0 w-[440px] h-[640px] gap-0 flex flex-col overflow-hidden border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60 shadow-2xl animate-in fade-in zoom-in-95 duration-200 origin-bottom-right", children: [
|
|
2531
|
+
/* @__PURE__ */ jsx(
|
|
2532
|
+
ChatHeader,
|
|
2533
|
+
{
|
|
2534
|
+
title: view === "history" ? "History" : title,
|
|
2535
|
+
leftContent: view === "history" ? /* @__PURE__ */ jsx(
|
|
2026
2536
|
Button,
|
|
2027
2537
|
{
|
|
2028
2538
|
variant: "ghost",
|
|
@@ -2031,50 +2541,52 @@ function ChatPopup({
|
|
|
2031
2541
|
className: "text-muted-foreground hover:text-foreground",
|
|
2032
2542
|
children: /* @__PURE__ */ jsx(IconArrowLeft, { className: "size-4" })
|
|
2033
2543
|
}
|
|
2034
|
-
),
|
|
2035
|
-
/* @__PURE__ */
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2544
|
+
) : void 0,
|
|
2545
|
+
rightContent: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2546
|
+
view === "chat" && /* @__PURE__ */ jsx(
|
|
2547
|
+
Button,
|
|
2548
|
+
{
|
|
2549
|
+
variant: "ghost",
|
|
2550
|
+
size: "icon-xs",
|
|
2551
|
+
onClick: () => setView("history"),
|
|
2552
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
2553
|
+
title: "History",
|
|
2554
|
+
children: /* @__PURE__ */ jsx(IconHistory, { className: "size-4" })
|
|
2555
|
+
}
|
|
2556
|
+
),
|
|
2557
|
+
/* @__PURE__ */ jsx(
|
|
2558
|
+
Button,
|
|
2559
|
+
{
|
|
2560
|
+
variant: "ghost",
|
|
2561
|
+
size: "icon-xs",
|
|
2562
|
+
onClick: handleNewChat,
|
|
2563
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
2564
|
+
title: "New Chat",
|
|
2565
|
+
children: /* @__PURE__ */ jsx(IconPlus, { className: "size-4" })
|
|
2566
|
+
}
|
|
2567
|
+
),
|
|
2568
|
+
/* @__PURE__ */ jsx(
|
|
2569
|
+
Button,
|
|
2570
|
+
{
|
|
2571
|
+
variant: "ghost",
|
|
2572
|
+
size: "icon-xs",
|
|
2573
|
+
onClick: () => setIsOpen(false),
|
|
2574
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
2575
|
+
children: /* @__PURE__ */ jsx(IconX, { className: "size-4" })
|
|
2576
|
+
}
|
|
2577
|
+
)
|
|
2578
|
+
] }),
|
|
2579
|
+
...headerProps
|
|
2580
|
+
}
|
|
2581
|
+
),
|
|
2072
2582
|
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: view === "chat" ? /* @__PURE__ */ jsx(
|
|
2073
2583
|
Thread,
|
|
2074
2584
|
{
|
|
2075
2585
|
placeholder,
|
|
2076
2586
|
starterPrompts,
|
|
2077
|
-
|
|
2587
|
+
options,
|
|
2588
|
+
className: "h-full",
|
|
2589
|
+
defaultSelectedIds
|
|
2078
2590
|
}
|
|
2079
2591
|
) : /* @__PURE__ */ jsx(
|
|
2080
2592
|
ThreadList,
|
|
@@ -2102,16 +2614,21 @@ function ChatSidebar({
|
|
|
2102
2614
|
title = "Chat",
|
|
2103
2615
|
placeholder = "Message the AI",
|
|
2104
2616
|
starterPrompts,
|
|
2105
|
-
|
|
2617
|
+
options,
|
|
2618
|
+
className,
|
|
2619
|
+
headerProps,
|
|
2620
|
+
defaultSelectedIds
|
|
2106
2621
|
}) {
|
|
2107
2622
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full border-r bg-background w-80", className), children: [
|
|
2108
|
-
/* @__PURE__ */ jsx(
|
|
2623
|
+
/* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
2109
2624
|
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
2110
2625
|
Thread,
|
|
2111
2626
|
{
|
|
2112
2627
|
placeholder,
|
|
2113
2628
|
starterPrompts,
|
|
2114
|
-
|
|
2629
|
+
options,
|
|
2630
|
+
className: "h-full",
|
|
2631
|
+
defaultSelectedIds
|
|
2115
2632
|
}
|
|
2116
2633
|
) })
|
|
2117
2634
|
] });
|
|
@@ -2120,13 +2637,437 @@ function ChatFull({
|
|
|
2120
2637
|
title = "Chat",
|
|
2121
2638
|
placeholder = "Message the AI",
|
|
2122
2639
|
starterPrompts,
|
|
2123
|
-
|
|
2640
|
+
options,
|
|
2641
|
+
className,
|
|
2642
|
+
headerProps,
|
|
2643
|
+
leftSidebar,
|
|
2644
|
+
rightSidebar,
|
|
2645
|
+
leftSidebarClassName,
|
|
2646
|
+
rightSidebarClassName,
|
|
2647
|
+
leftSidebarCollapsible = false,
|
|
2648
|
+
rightSidebarCollapsible = false,
|
|
2649
|
+
defaultLeftSidebarCollapsed = false,
|
|
2650
|
+
defaultRightSidebarCollapsed = false,
|
|
2651
|
+
leftSidebarCollapsed: controlledLeftCollapsed,
|
|
2652
|
+
rightSidebarCollapsed: controlledRightCollapsed,
|
|
2653
|
+
onLeftSidebarCollapseChange,
|
|
2654
|
+
onRightSidebarCollapseChange,
|
|
2655
|
+
autoFocus = false,
|
|
2656
|
+
defaultSelectedIds
|
|
2124
2657
|
}) {
|
|
2658
|
+
const [internalLeftCollapsed, setInternalLeftCollapsed] = useState(
|
|
2659
|
+
defaultLeftSidebarCollapsed
|
|
2660
|
+
);
|
|
2661
|
+
const [internalRightCollapsed, setInternalRightCollapsed] = useState(
|
|
2662
|
+
defaultRightSidebarCollapsed
|
|
2663
|
+
);
|
|
2664
|
+
const leftCollapsed = controlledLeftCollapsed !== void 0 ? controlledLeftCollapsed : internalLeftCollapsed;
|
|
2665
|
+
const rightCollapsed = controlledRightCollapsed !== void 0 ? controlledRightCollapsed : internalRightCollapsed;
|
|
2666
|
+
const handleLeftToggle = () => {
|
|
2667
|
+
const newCollapsed = !leftCollapsed;
|
|
2668
|
+
if (controlledLeftCollapsed === void 0) {
|
|
2669
|
+
setInternalLeftCollapsed(newCollapsed);
|
|
2670
|
+
}
|
|
2671
|
+
onLeftSidebarCollapseChange?.(newCollapsed);
|
|
2672
|
+
};
|
|
2673
|
+
const handleRightToggle = () => {
|
|
2674
|
+
const newCollapsed = !rightCollapsed;
|
|
2675
|
+
if (controlledRightCollapsed === void 0) {
|
|
2676
|
+
setInternalRightCollapsed(newCollapsed);
|
|
2677
|
+
}
|
|
2678
|
+
onRightSidebarCollapseChange?.(newCollapsed);
|
|
2679
|
+
};
|
|
2125
2680
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full w-full bg-background", className), children: [
|
|
2126
|
-
title && /* @__PURE__ */ jsx(
|
|
2127
|
-
/* @__PURE__ */
|
|
2681
|
+
title && /* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
2682
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden flex relative", children: [
|
|
2683
|
+
leftSidebar && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2684
|
+
/* @__PURE__ */ jsx(
|
|
2685
|
+
"div",
|
|
2686
|
+
{
|
|
2687
|
+
className: cn(
|
|
2688
|
+
"flex-shrink-0 border-r border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
2689
|
+
leftCollapsed && leftSidebarCollapsible ? "w-0 border-r-0 min-w-0" : "",
|
|
2690
|
+
!leftCollapsed && leftSidebarClassName
|
|
2691
|
+
),
|
|
2692
|
+
children: !leftCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2693
|
+
leftSidebarCollapsible && /* @__PURE__ */ jsx("div", { className: "flex justify-end p-2 border-b border-border shrink-0", children: /* @__PURE__ */ jsx(
|
|
2694
|
+
Button,
|
|
2695
|
+
{
|
|
2696
|
+
variant: "ghost",
|
|
2697
|
+
size: "icon-sm",
|
|
2698
|
+
onClick: handleLeftToggle,
|
|
2699
|
+
"aria-label": "Collapse left sidebar",
|
|
2700
|
+
className: "h-8 w-8",
|
|
2701
|
+
children: /* @__PURE__ */ jsx(IconChevronLeft, { className: "h-4 w-4" })
|
|
2702
|
+
}
|
|
2703
|
+
) }),
|
|
2704
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: leftSidebar })
|
|
2705
|
+
] })
|
|
2706
|
+
}
|
|
2707
|
+
),
|
|
2708
|
+
leftSidebarCollapsible && leftCollapsed && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 border-r border-border bg-background flex items-center justify-center w-10", children: /* @__PURE__ */ jsx(
|
|
2709
|
+
Button,
|
|
2710
|
+
{
|
|
2711
|
+
variant: "ghost",
|
|
2712
|
+
size: "icon-sm",
|
|
2713
|
+
onClick: handleLeftToggle,
|
|
2714
|
+
"aria-label": "Expand left sidebar",
|
|
2715
|
+
className: "h-8 w-8",
|
|
2716
|
+
children: /* @__PURE__ */ jsx(IconChevronRight, { className: "h-4 w-4" })
|
|
2717
|
+
}
|
|
2718
|
+
) })
|
|
2719
|
+
] }),
|
|
2720
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx(
|
|
2721
|
+
Thread,
|
|
2722
|
+
{
|
|
2723
|
+
placeholder,
|
|
2724
|
+
starterPrompts,
|
|
2725
|
+
options,
|
|
2726
|
+
autoFocus,
|
|
2727
|
+
defaultSelectedIds
|
|
2728
|
+
}
|
|
2729
|
+
) }),
|
|
2730
|
+
rightSidebar && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2731
|
+
rightSidebarCollapsible && rightCollapsed && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 border-l border-border bg-background flex items-center justify-center w-10", children: /* @__PURE__ */ jsx(
|
|
2732
|
+
Button,
|
|
2733
|
+
{
|
|
2734
|
+
variant: "ghost",
|
|
2735
|
+
size: "icon-sm",
|
|
2736
|
+
onClick: handleRightToggle,
|
|
2737
|
+
"aria-label": "Expand right sidebar",
|
|
2738
|
+
className: "h-8 w-8",
|
|
2739
|
+
children: /* @__PURE__ */ jsx(IconChevronLeft, { className: "h-4 w-4" })
|
|
2740
|
+
}
|
|
2741
|
+
) }),
|
|
2742
|
+
/* @__PURE__ */ jsx(
|
|
2743
|
+
"div",
|
|
2744
|
+
{
|
|
2745
|
+
className: cn(
|
|
2746
|
+
"flex-shrink-0 border-l border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
2747
|
+
rightCollapsed && rightSidebarCollapsible ? "w-0 border-l-0 min-w-0" : "",
|
|
2748
|
+
!rightCollapsed && rightSidebarClassName
|
|
2749
|
+
),
|
|
2750
|
+
children: !rightCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2751
|
+
rightSidebarCollapsible && /* @__PURE__ */ jsx("div", { className: "flex justify-start p-2 border-b border-border shrink-0", children: /* @__PURE__ */ jsx(
|
|
2752
|
+
Button,
|
|
2753
|
+
{
|
|
2754
|
+
variant: "ghost",
|
|
2755
|
+
size: "icon-sm",
|
|
2756
|
+
onClick: handleRightToggle,
|
|
2757
|
+
"aria-label": "Collapse right sidebar",
|
|
2758
|
+
className: "h-8 w-8",
|
|
2759
|
+
children: /* @__PURE__ */ jsx(IconChevronRight, { className: "h-4 w-4" })
|
|
2760
|
+
}
|
|
2761
|
+
) }),
|
|
2762
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: rightSidebar })
|
|
2763
|
+
] })
|
|
2764
|
+
}
|
|
2765
|
+
)
|
|
2766
|
+
] })
|
|
2767
|
+
] })
|
|
2128
2768
|
] });
|
|
2129
2769
|
}
|
|
2770
|
+
var PopoverContext = React11.createContext(
|
|
2771
|
+
void 0
|
|
2772
|
+
);
|
|
2773
|
+
function usePopoverContext() {
|
|
2774
|
+
const context = React11.useContext(PopoverContext);
|
|
2775
|
+
if (!context) {
|
|
2776
|
+
throw new Error("Popover components must be used within a Popover");
|
|
2777
|
+
}
|
|
2778
|
+
return context;
|
|
2779
|
+
}
|
|
2780
|
+
function Popover({
|
|
2781
|
+
children,
|
|
2782
|
+
defaultOpen = false,
|
|
2783
|
+
open: controlledOpen,
|
|
2784
|
+
onOpenChange
|
|
2785
|
+
}) {
|
|
2786
|
+
const [internalOpen, setInternalOpen] = React11.useState(defaultOpen);
|
|
2787
|
+
const triggerRef = React11.useRef(null);
|
|
2788
|
+
const open = controlledOpen ?? internalOpen;
|
|
2789
|
+
const setOpen = React11.useCallback(
|
|
2790
|
+
(newOpen) => {
|
|
2791
|
+
if (controlledOpen === void 0) {
|
|
2792
|
+
setInternalOpen(newOpen);
|
|
2793
|
+
}
|
|
2794
|
+
onOpenChange?.(newOpen);
|
|
2795
|
+
},
|
|
2796
|
+
[controlledOpen, onOpenChange]
|
|
2797
|
+
);
|
|
2798
|
+
const value = React11.useMemo(
|
|
2799
|
+
() => ({
|
|
2800
|
+
open,
|
|
2801
|
+
setOpen,
|
|
2802
|
+
triggerRef
|
|
2803
|
+
}),
|
|
2804
|
+
[open, setOpen]
|
|
2805
|
+
);
|
|
2806
|
+
return /* @__PURE__ */ jsx(PopoverContext.Provider, { value, children });
|
|
2807
|
+
}
|
|
2808
|
+
var PopoverTrigger = React11.forwardRef(
|
|
2809
|
+
({ asChild, className, children, ...props }, ref) => {
|
|
2810
|
+
const { setOpen, triggerRef } = usePopoverContext();
|
|
2811
|
+
const handleClick = (e) => {
|
|
2812
|
+
setOpen(true);
|
|
2813
|
+
props.onClick?.(e);
|
|
2814
|
+
};
|
|
2815
|
+
if (asChild && React11.isValidElement(children)) {
|
|
2816
|
+
return React11.cloneElement(children, {
|
|
2817
|
+
ref: (node) => {
|
|
2818
|
+
triggerRef.current = node;
|
|
2819
|
+
if (typeof children.ref === "function") {
|
|
2820
|
+
children.ref(node);
|
|
2821
|
+
} else if (children.ref) {
|
|
2822
|
+
children.ref.current = node;
|
|
2823
|
+
}
|
|
2824
|
+
},
|
|
2825
|
+
onClick: handleClick
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
return /* @__PURE__ */ jsx(
|
|
2829
|
+
"button",
|
|
2830
|
+
{
|
|
2831
|
+
ref: (node) => {
|
|
2832
|
+
triggerRef.current = node;
|
|
2833
|
+
if (typeof ref === "function") {
|
|
2834
|
+
ref(node);
|
|
2835
|
+
} else if (ref) {
|
|
2836
|
+
ref.current = node;
|
|
2837
|
+
}
|
|
2838
|
+
},
|
|
2839
|
+
className,
|
|
2840
|
+
onClick: handleClick,
|
|
2841
|
+
...props,
|
|
2842
|
+
children
|
|
2843
|
+
}
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2846
|
+
);
|
|
2847
|
+
PopoverTrigger.displayName = "PopoverTrigger";
|
|
2848
|
+
var PopoverContent = React11.forwardRef(
|
|
2849
|
+
({
|
|
2850
|
+
className,
|
|
2851
|
+
side = "bottom",
|
|
2852
|
+
align = "start",
|
|
2853
|
+
sideOffset = 4,
|
|
2854
|
+
alignOffset = 0,
|
|
2855
|
+
children,
|
|
2856
|
+
...props
|
|
2857
|
+
}, ref) => {
|
|
2858
|
+
const { open, setOpen, triggerRef } = usePopoverContext();
|
|
2859
|
+
const [position, setPosition] = React11.useState({ top: 0, left: 0 });
|
|
2860
|
+
const contentRef = React11.useRef(null);
|
|
2861
|
+
React11.useEffect(() => {
|
|
2862
|
+
if (!open || !triggerRef.current) return;
|
|
2863
|
+
const updatePosition = () => {
|
|
2864
|
+
if (!triggerRef.current || !contentRef.current) return;
|
|
2865
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
2866
|
+
const contentRect = contentRef.current.getBoundingClientRect();
|
|
2867
|
+
const scrollX = window.scrollX;
|
|
2868
|
+
const scrollY = window.scrollY;
|
|
2869
|
+
let top = 0;
|
|
2870
|
+
let left = 0;
|
|
2871
|
+
switch (side) {
|
|
2872
|
+
case "bottom":
|
|
2873
|
+
top = triggerRect.bottom + sideOffset + scrollY;
|
|
2874
|
+
break;
|
|
2875
|
+
case "top":
|
|
2876
|
+
top = triggerRect.top - contentRect.height - sideOffset + scrollY;
|
|
2877
|
+
break;
|
|
2878
|
+
case "right":
|
|
2879
|
+
top = triggerRect.top + scrollY;
|
|
2880
|
+
left = triggerRect.right + sideOffset + scrollX;
|
|
2881
|
+
break;
|
|
2882
|
+
case "left":
|
|
2883
|
+
top = triggerRect.top + scrollY;
|
|
2884
|
+
left = triggerRect.left - contentRect.width - sideOffset + scrollX;
|
|
2885
|
+
break;
|
|
2886
|
+
}
|
|
2887
|
+
switch (align) {
|
|
2888
|
+
case "start":
|
|
2889
|
+
if (side === "top" || side === "bottom") {
|
|
2890
|
+
left = triggerRect.left + scrollX + alignOffset;
|
|
2891
|
+
} else {
|
|
2892
|
+
top += alignOffset;
|
|
2893
|
+
}
|
|
2894
|
+
break;
|
|
2895
|
+
case "center":
|
|
2896
|
+
if (side === "top" || side === "bottom") {
|
|
2897
|
+
left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2 + scrollX + alignOffset;
|
|
2898
|
+
} else {
|
|
2899
|
+
top += triggerRect.height / 2 - contentRect.height / 2 + alignOffset;
|
|
2900
|
+
}
|
|
2901
|
+
break;
|
|
2902
|
+
case "end":
|
|
2903
|
+
if (side === "top" || side === "bottom") {
|
|
2904
|
+
left = triggerRect.left + triggerRect.width - contentRect.width + scrollX + alignOffset;
|
|
2905
|
+
} else {
|
|
2906
|
+
top += triggerRect.height - contentRect.height + alignOffset;
|
|
2907
|
+
}
|
|
2908
|
+
break;
|
|
2909
|
+
}
|
|
2910
|
+
setPosition({ top, left });
|
|
2911
|
+
};
|
|
2912
|
+
requestAnimationFrame(() => {
|
|
2913
|
+
updatePosition();
|
|
2914
|
+
});
|
|
2915
|
+
window.addEventListener("resize", updatePosition);
|
|
2916
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
2917
|
+
return () => {
|
|
2918
|
+
window.removeEventListener("resize", updatePosition);
|
|
2919
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
2920
|
+
};
|
|
2921
|
+
}, [open, side, align, sideOffset, alignOffset, triggerRef]);
|
|
2922
|
+
React11.useEffect(() => {
|
|
2923
|
+
if (!open) return;
|
|
2924
|
+
const handleClickOutside = (event) => {
|
|
2925
|
+
if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
|
|
2926
|
+
setOpen(false);
|
|
2927
|
+
}
|
|
2928
|
+
};
|
|
2929
|
+
const handleEscape = (event) => {
|
|
2930
|
+
if (event.key === "Escape") {
|
|
2931
|
+
setOpen(false);
|
|
2932
|
+
}
|
|
2933
|
+
};
|
|
2934
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
2935
|
+
document.addEventListener("keydown", handleEscape);
|
|
2936
|
+
return () => {
|
|
2937
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
2938
|
+
document.removeEventListener("keydown", handleEscape);
|
|
2939
|
+
};
|
|
2940
|
+
}, [open, setOpen, triggerRef]);
|
|
2941
|
+
if (!open) return null;
|
|
2942
|
+
const content = /* @__PURE__ */ jsx(
|
|
2943
|
+
"div",
|
|
2944
|
+
{
|
|
2945
|
+
ref: (node) => {
|
|
2946
|
+
contentRef.current = node;
|
|
2947
|
+
if (typeof ref === "function") {
|
|
2948
|
+
ref(node);
|
|
2949
|
+
} else if (ref) {
|
|
2950
|
+
ref.current = node;
|
|
2951
|
+
}
|
|
2952
|
+
},
|
|
2953
|
+
className: cn(
|
|
2954
|
+
"bg-popover text-popover-foreground 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 ring-foreground/5 rounded-2xl shadow-2xl ring-1 z-50 min-w-48 max-h-96 overflow-hidden",
|
|
2955
|
+
className
|
|
2956
|
+
),
|
|
2957
|
+
style: {
|
|
2958
|
+
position: "absolute",
|
|
2959
|
+
top: `${position.top}px`,
|
|
2960
|
+
left: `${position.left}px`
|
|
2961
|
+
},
|
|
2962
|
+
...props,
|
|
2963
|
+
children
|
|
2964
|
+
}
|
|
2965
|
+
);
|
|
2966
|
+
return createPortal(content, document.body);
|
|
2967
|
+
}
|
|
2968
|
+
);
|
|
2969
|
+
PopoverContent.displayName = "PopoverContent";
|
|
2970
|
+
var ThreadPopover = ({
|
|
2971
|
+
className,
|
|
2972
|
+
buttonClassName,
|
|
2973
|
+
buttonVariant = "ghost",
|
|
2974
|
+
buttonSize = "icon",
|
|
2975
|
+
emptyState,
|
|
2976
|
+
onThreadSelect
|
|
2977
|
+
}) => {
|
|
2978
|
+
const [isOpen, setIsOpen] = React11.useState(false);
|
|
2979
|
+
useHotkeys(
|
|
2980
|
+
"h",
|
|
2981
|
+
(e) => {
|
|
2982
|
+
e.preventDefault();
|
|
2983
|
+
setIsOpen((prev) => !prev);
|
|
2984
|
+
},
|
|
2985
|
+
{
|
|
2986
|
+
enableOnFormTags: false,
|
|
2987
|
+
// Don't trigger when typing in form inputs
|
|
2988
|
+
enableOnContentEditable: false
|
|
2989
|
+
// Don't trigger in contenteditable elements
|
|
2990
|
+
}
|
|
2991
|
+
);
|
|
2992
|
+
const handleThreadSelect = (threadId) => {
|
|
2993
|
+
setIsOpen(false);
|
|
2994
|
+
onThreadSelect?.(threadId);
|
|
2995
|
+
};
|
|
2996
|
+
return /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
2997
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
2998
|
+
Button,
|
|
2999
|
+
{
|
|
3000
|
+
variant: buttonVariant,
|
|
3001
|
+
size: buttonSize,
|
|
3002
|
+
className: cn(buttonClassName),
|
|
3003
|
+
children: /* @__PURE__ */ jsx(IconHistory, { className: "size-4" })
|
|
3004
|
+
}
|
|
3005
|
+
) }),
|
|
3006
|
+
/* @__PURE__ */ jsx(
|
|
3007
|
+
PopoverContent,
|
|
3008
|
+
{
|
|
3009
|
+
className: cn("w-80 p-0", className),
|
|
3010
|
+
side: "bottom",
|
|
3011
|
+
align: "start",
|
|
3012
|
+
sideOffset: 8,
|
|
3013
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex flex-col h-[400px]", children: /* @__PURE__ */ jsx(
|
|
3014
|
+
ThreadList,
|
|
3015
|
+
{
|
|
3016
|
+
emptyState,
|
|
3017
|
+
onThreadSelect: handleThreadSelect,
|
|
3018
|
+
className: "h-full"
|
|
3019
|
+
}
|
|
3020
|
+
) })
|
|
3021
|
+
}
|
|
3022
|
+
)
|
|
3023
|
+
] });
|
|
3024
|
+
};
|
|
3025
|
+
var CreateThreadButton = ({
|
|
3026
|
+
className,
|
|
3027
|
+
variant = "ghost",
|
|
3028
|
+
size = "icon",
|
|
3029
|
+
children,
|
|
3030
|
+
onThreadCreated
|
|
3031
|
+
}) => {
|
|
3032
|
+
const { createThread } = useThreads();
|
|
3033
|
+
const [isCreating, setIsCreating] = React11.useState(false);
|
|
3034
|
+
const handleCreateThread = async () => {
|
|
3035
|
+
if (isCreating) return;
|
|
3036
|
+
try {
|
|
3037
|
+
setIsCreating(true);
|
|
3038
|
+
const threadId = await createThread();
|
|
3039
|
+
onThreadCreated?.(threadId);
|
|
3040
|
+
} catch (error) {
|
|
3041
|
+
console.error("Failed to create thread:", error);
|
|
3042
|
+
} finally {
|
|
3043
|
+
setIsCreating(false);
|
|
3044
|
+
}
|
|
3045
|
+
};
|
|
3046
|
+
useHotkeys(
|
|
3047
|
+
"n",
|
|
3048
|
+
(e) => {
|
|
3049
|
+
e.preventDefault();
|
|
3050
|
+
handleCreateThread();
|
|
3051
|
+
},
|
|
3052
|
+
{
|
|
3053
|
+
enableOnFormTags: false,
|
|
3054
|
+
// Don't trigger when typing in form inputs
|
|
3055
|
+
enableOnContentEditable: false
|
|
3056
|
+
// Don't trigger in contenteditable elements
|
|
3057
|
+
}
|
|
3058
|
+
);
|
|
3059
|
+
return /* @__PURE__ */ jsx(
|
|
3060
|
+
Button,
|
|
3061
|
+
{
|
|
3062
|
+
variant,
|
|
3063
|
+
size,
|
|
3064
|
+
onClick: handleCreateThread,
|
|
3065
|
+
disabled: isCreating,
|
|
3066
|
+
className: cn(className),
|
|
3067
|
+
children: /* @__PURE__ */ jsx(IconPlus, { className: "size-4" })
|
|
3068
|
+
}
|
|
3069
|
+
);
|
|
3070
|
+
};
|
|
2130
3071
|
function AlertDialog({ ...props }) {
|
|
2131
3072
|
return /* @__PURE__ */ jsx(AlertDialog$1.Root, { "data-slot": "alert-dialog", ...props });
|
|
2132
3073
|
}
|
|
@@ -2209,100 +3150,111 @@ function AlertDialogDescription({
|
|
|
2209
3150
|
}
|
|
2210
3151
|
);
|
|
2211
3152
|
}
|
|
2212
|
-
function DropdownMenu({ ...props }) {
|
|
2213
|
-
return /* @__PURE__ */ jsx(Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
2214
|
-
}
|
|
2215
|
-
function DropdownMenuTrigger({ ...props }) {
|
|
2216
|
-
return /* @__PURE__ */ jsx(Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
2217
|
-
}
|
|
2218
|
-
function DropdownMenuContent({
|
|
2219
|
-
align = "start",
|
|
2220
|
-
alignOffset = 0,
|
|
2221
|
-
side = "bottom",
|
|
2222
|
-
sideOffset = 4,
|
|
2223
|
-
className,
|
|
2224
|
-
...props
|
|
2225
|
-
}) {
|
|
2226
|
-
return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
|
|
2227
|
-
Menu.Positioner,
|
|
2228
|
-
{
|
|
2229
|
-
className: "isolate z-50 outline-none",
|
|
2230
|
-
align,
|
|
2231
|
-
alignOffset,
|
|
2232
|
-
side,
|
|
2233
|
-
sideOffset,
|
|
2234
|
-
children: /* @__PURE__ */ jsx(
|
|
2235
|
-
Menu.Popup,
|
|
2236
|
-
{
|
|
2237
|
-
"data-slot": "dropdown-menu-content",
|
|
2238
|
-
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),
|
|
2239
|
-
...props
|
|
2240
|
-
}
|
|
2241
|
-
)
|
|
2242
|
-
}
|
|
2243
|
-
) });
|
|
2244
|
-
}
|
|
2245
|
-
function DropdownMenuItem({
|
|
2246
|
-
className,
|
|
2247
|
-
inset,
|
|
2248
|
-
variant = "default",
|
|
2249
|
-
...props
|
|
2250
|
-
}) {
|
|
2251
|
-
return /* @__PURE__ */ jsx(
|
|
2252
|
-
Menu.Item,
|
|
2253
|
-
{
|
|
2254
|
-
"data-slot": "dropdown-menu-item",
|
|
2255
|
-
"data-inset": inset,
|
|
2256
|
-
"data-variant": variant,
|
|
2257
|
-
className: cn(
|
|
2258
|
-
"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",
|
|
2259
|
-
className
|
|
2260
|
-
),
|
|
2261
|
-
...props
|
|
2262
|
-
}
|
|
2263
|
-
);
|
|
2264
|
-
}
|
|
2265
3153
|
var AccountDialog = ({
|
|
2266
3154
|
className,
|
|
2267
|
-
variant,
|
|
3155
|
+
variant = "outline",
|
|
2268
3156
|
size
|
|
2269
3157
|
}) => {
|
|
2270
|
-
const { isLoading, isAuthenticated, login, logout } = useAuth();
|
|
2271
|
-
const [open, setOpen] =
|
|
2272
|
-
const [
|
|
3158
|
+
const { isLoading, isAuthenticated, user, login, logout } = useAuth();
|
|
3159
|
+
const [open, setOpen] = React11.useState(false);
|
|
3160
|
+
const [accountInfoOpen, setAccountInfoOpen] = React11.useState(false);
|
|
3161
|
+
const [error, setError] = React11.useState(null);
|
|
3162
|
+
const initials = React11.useMemo(() => {
|
|
3163
|
+
const name = user?.displayName || user?.name;
|
|
3164
|
+
if (!name) return "";
|
|
3165
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
3166
|
+
}, [user?.displayName, user?.name]);
|
|
2273
3167
|
const handleGoogleSignIn = async () => {
|
|
2274
3168
|
login();
|
|
2275
3169
|
};
|
|
2276
3170
|
if (isAuthenticated) {
|
|
2277
|
-
return /* @__PURE__ */ jsxs(
|
|
2278
|
-
/* @__PURE__ */
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
/* @__PURE__ */ jsx(
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
3171
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3172
|
+
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
3173
|
+
/* @__PURE__ */ jsx(
|
|
3174
|
+
DropdownMenuTrigger,
|
|
3175
|
+
{
|
|
3176
|
+
render: (props) => /* @__PURE__ */ jsx(
|
|
3177
|
+
Button,
|
|
3178
|
+
{
|
|
3179
|
+
variant,
|
|
3180
|
+
size: "icon",
|
|
3181
|
+
...props,
|
|
3182
|
+
className: cn("rounded-full", className),
|
|
3183
|
+
children: user?.picture ? /* @__PURE__ */ jsx(
|
|
3184
|
+
"img",
|
|
3185
|
+
{
|
|
3186
|
+
src: user.picture,
|
|
3187
|
+
alt: user.displayName || user.name,
|
|
3188
|
+
className: "size-7 rounded-full object-cover"
|
|
3189
|
+
}
|
|
3190
|
+
) : /* @__PURE__ */ jsx("div", { className: "flex size-7 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsx(IconUser, { className: "size-4" }) })
|
|
3191
|
+
}
|
|
3192
|
+
)
|
|
3193
|
+
}
|
|
3194
|
+
),
|
|
3195
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
|
|
3196
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-2", children: [
|
|
3197
|
+
user?.picture ? /* @__PURE__ */ jsx(
|
|
3198
|
+
"img",
|
|
3199
|
+
{
|
|
3200
|
+
src: user.picture,
|
|
3201
|
+
alt: user.displayName || user.name,
|
|
3202
|
+
className: "size-8 rounded-full object-cover"
|
|
3203
|
+
}
|
|
3204
|
+
) : /* @__PURE__ */ jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsx(IconUser, { className: "size-4" }) }),
|
|
3205
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-0.5 overflow-hidden", children: [
|
|
3206
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: user?.displayName || user?.name }),
|
|
3207
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: user?.email })
|
|
3208
|
+
] })
|
|
3209
|
+
] }),
|
|
3210
|
+
/* @__PURE__ */ jsx(Separator, { className: "my-1" }),
|
|
3211
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: () => setAccountInfoOpen(true), children: [
|
|
3212
|
+
/* @__PURE__ */ jsx(IconUser, { className: "mr-2 size-4" }),
|
|
3213
|
+
"Account Settings"
|
|
3214
|
+
] }),
|
|
3215
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: logout, className: "text-destructive", children: [
|
|
3216
|
+
/* @__PURE__ */ jsx(IconLogout, { className: "mr-2 size-4" }),
|
|
3217
|
+
"Logout"
|
|
3218
|
+
] })
|
|
3219
|
+
] })
|
|
3220
|
+
] }),
|
|
3221
|
+
/* @__PURE__ */ jsx(Dialog, { open: accountInfoOpen, onOpenChange: setAccountInfoOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
|
|
3222
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
3223
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Account Information" }),
|
|
3224
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: "Your account details and settings." })
|
|
3225
|
+
] }),
|
|
3226
|
+
/* @__PURE__ */ jsxs(DialogClose, { children: [
|
|
3227
|
+
/* @__PURE__ */ jsx(IconX, { className: "size-4" }),
|
|
3228
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
2300
3229
|
] }),
|
|
2301
|
-
/* @__PURE__ */ jsxs(
|
|
2302
|
-
/* @__PURE__ */
|
|
2303
|
-
|
|
3230
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 py-4", children: [
|
|
3231
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
3232
|
+
user?.picture ? /* @__PURE__ */ jsx(
|
|
3233
|
+
"img",
|
|
3234
|
+
{
|
|
3235
|
+
src: user.picture,
|
|
3236
|
+
alt: user.displayName || user.name,
|
|
3237
|
+
className: "size-16 rounded-full object-cover"
|
|
3238
|
+
}
|
|
3239
|
+
) : /* @__PURE__ */ jsx("div", { className: "flex size-16 items-center justify-center rounded-full bg-muted text-xl font-bold", children: initials || /* @__PURE__ */ jsx(IconUser, { className: "size-8 text-muted-foreground" }) }),
|
|
3240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
3241
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: user?.displayName || user?.name }),
|
|
3242
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: user?.email })
|
|
3243
|
+
] })
|
|
3244
|
+
] }),
|
|
3245
|
+
/* @__PURE__ */ jsx(Separator, {}),
|
|
3246
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
3247
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
3248
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "User ID" }),
|
|
3249
|
+
/* @__PURE__ */ jsx("p", { className: "font-mono text-xs truncate", children: user?.uid || user?.id })
|
|
3250
|
+
] }),
|
|
3251
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
3252
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "Created At" }),
|
|
3253
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs", children: user?.createdAt || "N/A" })
|
|
3254
|
+
] })
|
|
3255
|
+
] })
|
|
2304
3256
|
] })
|
|
2305
|
-
] })
|
|
3257
|
+
] }) })
|
|
2306
3258
|
] });
|
|
2307
3259
|
}
|
|
2308
3260
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -2344,7 +3296,42 @@ var AccountDialog = ({
|
|
|
2344
3296
|
] }) })
|
|
2345
3297
|
] });
|
|
2346
3298
|
};
|
|
3299
|
+
function ThemeToggle() {
|
|
3300
|
+
const { theme, setTheme, resolvedTheme } = useTheme();
|
|
3301
|
+
const cycleTheme = () => {
|
|
3302
|
+
if (theme === "light") {
|
|
3303
|
+
setTheme("dark");
|
|
3304
|
+
} else if (theme === "dark") {
|
|
3305
|
+
setTheme("system");
|
|
3306
|
+
} else {
|
|
3307
|
+
setTheme("light");
|
|
3308
|
+
}
|
|
3309
|
+
};
|
|
3310
|
+
const getIcon = () => {
|
|
3311
|
+
if (theme === "system") {
|
|
3312
|
+
return /* @__PURE__ */ jsx(IconDeviceDesktop, { className: "h-4 w-4" });
|
|
3313
|
+
}
|
|
3314
|
+
return resolvedTheme === "dark" ? /* @__PURE__ */ jsx(IconMoon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconSun, { className: "h-4 w-4" });
|
|
3315
|
+
};
|
|
3316
|
+
const getLabel = () => {
|
|
3317
|
+
if (theme === "system") {
|
|
3318
|
+
return "System";
|
|
3319
|
+
}
|
|
3320
|
+
return resolvedTheme === "dark" ? "Dark" : "Light";
|
|
3321
|
+
};
|
|
3322
|
+
return /* @__PURE__ */ jsx(
|
|
3323
|
+
Button,
|
|
3324
|
+
{
|
|
3325
|
+
variant: "ghost",
|
|
3326
|
+
size: "icon",
|
|
3327
|
+
onClick: cycleTheme,
|
|
3328
|
+
"aria-label": `Toggle theme (current: ${getLabel()})`,
|
|
3329
|
+
title: `Current: ${getLabel()}. Click to cycle: Light \u2192 Dark \u2192 System`,
|
|
3330
|
+
children: getIcon()
|
|
3331
|
+
}
|
|
3332
|
+
);
|
|
3333
|
+
}
|
|
2347
3334
|
|
|
2348
|
-
export { AccountDialog, AuthContext, AuthProvider, ChatFull, ChatPopup, ChatSidebar, Composer, MelonyClientProvider, MelonyContext, Thread, ThreadContext, ThreadList, ThreadProvider, UIRenderer, useAuth, useMelony, useThreads };
|
|
3335
|
+
export { AccountDialog, AuthContext, AuthProvider, ChatFull, ChatHeader, ChatPopup, ChatSidebar, Composer, CreateThreadButton, MelonyClientProvider, MelonyContext, ThemeProvider, ThemeToggle, Thread, ThreadContext, ThreadList, ThreadPopover, ThreadProvider, UIRenderer, groupEventsToMessages, useAuth, useMelony, useTheme, useThreads };
|
|
2349
3336
|
//# sourceMappingURL=index.js.map
|
|
2350
3337
|
//# sourceMappingURL=index.js.map
|