@melony/react 0.1.23 → 0.1.25
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 +682 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +174 -43
- package/dist/index.d.ts +174 -43
- package/dist/index.js +613 -346
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React11 from 'react';
|
|
2
|
+
import React11__default, { createContext, useState, useCallback, useEffect, useMemo, useContext, useRef } from 'react';
|
|
3
3
|
import { NuqsAdapter } from 'nuqs/adapters/react';
|
|
4
4
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -9,13 +9,13 @@ import { clsx } from 'clsx';
|
|
|
9
9
|
import { twMerge } from 'tailwind-merge';
|
|
10
10
|
import { Button as Button$1 } from '@base-ui/react/button';
|
|
11
11
|
import { cva } from 'class-variance-authority';
|
|
12
|
+
import { mergeProps } from '@base-ui/react/merge-props';
|
|
13
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
12
14
|
import * as ICONS from '@tabler/icons-react';
|
|
13
|
-
import { IconChevronDown, IconLoader2, IconArrowUp,
|
|
15
|
+
import { IconPaperclip, IconX, IconPlus, IconChevronDown, IconLoader2, IconArrowUp, IconMessage, IconTrash, IconHistory, IconArrowLeft, IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightExpand, IconLayoutSidebarRightCollapse, IconUser, IconLogout, IconBrandGoogle, IconDeviceDesktop, IconMoon, IconSun, IconCheck, IconSelector, IconChevronUp } from '@tabler/icons-react';
|
|
14
16
|
import { Menu } from '@base-ui/react/menu';
|
|
15
17
|
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
16
18
|
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
17
|
-
import { mergeProps } from '@base-ui/react/merge-props';
|
|
18
|
-
import { useRender } from '@base-ui/react/use-render';
|
|
19
19
|
import { Input as Input$1 } from '@base-ui/react/input';
|
|
20
20
|
import { Select as Select$1 } from '@base-ui/react/select';
|
|
21
21
|
import { createPortal } from 'react-dom';
|
|
@@ -63,14 +63,12 @@ var MelonyContextProviderInner = ({
|
|
|
63
63
|
children,
|
|
64
64
|
client,
|
|
65
65
|
initialEvents,
|
|
66
|
-
configApi,
|
|
67
66
|
setContextValue
|
|
68
67
|
}) => {
|
|
69
68
|
const [state, setState] = useState(client.getState());
|
|
70
69
|
const { data: config } = useQuery({
|
|
71
|
-
queryKey: ["melony-config",
|
|
72
|
-
queryFn: () => client.getConfig(
|
|
73
|
-
enabled: !!configApi,
|
|
70
|
+
queryKey: ["melony-config", client.url],
|
|
71
|
+
queryFn: () => client.getConfig(),
|
|
74
72
|
staleTime: Infinity
|
|
75
73
|
});
|
|
76
74
|
useEffect(() => {
|
|
@@ -85,17 +83,56 @@ var MelonyContextProviderInner = ({
|
|
|
85
83
|
unsubscribe();
|
|
86
84
|
};
|
|
87
85
|
}, [client]);
|
|
86
|
+
const reset = useCallback(
|
|
87
|
+
(events) => client.reset(events),
|
|
88
|
+
[client]
|
|
89
|
+
);
|
|
90
|
+
const dispatchClientAction = useCallback(
|
|
91
|
+
async (event) => {
|
|
92
|
+
if (!event.type.startsWith("client:")) return false;
|
|
93
|
+
switch (event.type) {
|
|
94
|
+
case "client:navigate": {
|
|
95
|
+
const url = event.data?.url;
|
|
96
|
+
if (url) {
|
|
97
|
+
window.history.pushState(null, "", url);
|
|
98
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
case "client:open-url": {
|
|
103
|
+
const { url, target = "_blank" } = event.data || {};
|
|
104
|
+
if (url) {
|
|
105
|
+
window.open(url, target);
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
case "client:copy": {
|
|
110
|
+
const { text } = event.data || {};
|
|
111
|
+
if (text) {
|
|
112
|
+
await navigator.clipboard.writeText(text);
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
case "client:reset": {
|
|
117
|
+
reset([]);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
default:
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
[client, reset]
|
|
125
|
+
);
|
|
88
126
|
const sendEvent = useCallback(
|
|
89
127
|
async (event, options) => {
|
|
128
|
+
const handled = await dispatchClientAction(event);
|
|
129
|
+
if (handled) return;
|
|
90
130
|
const generator = client.sendEvent(event, options);
|
|
91
|
-
for await (const
|
|
131
|
+
for await (const incomingEvent of generator) {
|
|
132
|
+
await dispatchClientAction(incomingEvent);
|
|
92
133
|
}
|
|
93
134
|
},
|
|
94
|
-
[client]
|
|
95
|
-
);
|
|
96
|
-
const reset = useCallback(
|
|
97
|
-
(events) => client.reset(events),
|
|
98
|
-
[client]
|
|
135
|
+
[client, dispatchClientAction]
|
|
99
136
|
);
|
|
100
137
|
const value = useMemo(
|
|
101
138
|
() => ({
|
|
@@ -117,8 +154,7 @@ var MelonyClientProvider = ({
|
|
|
117
154
|
children,
|
|
118
155
|
client,
|
|
119
156
|
initialEvents,
|
|
120
|
-
queryClient = defaultQueryClient
|
|
121
|
-
configApi
|
|
157
|
+
queryClient = defaultQueryClient
|
|
122
158
|
}) => {
|
|
123
159
|
const [contextValue, setContextValue] = useState(void 0);
|
|
124
160
|
return /* @__PURE__ */ jsx(MelonyContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(
|
|
@@ -126,7 +162,6 @@ var MelonyClientProvider = ({
|
|
|
126
162
|
{
|
|
127
163
|
client,
|
|
128
164
|
initialEvents,
|
|
129
|
-
configApi,
|
|
130
165
|
setContextValue,
|
|
131
166
|
children
|
|
132
167
|
}
|
|
@@ -377,6 +412,47 @@ var useThreads = () => {
|
|
|
377
412
|
}
|
|
378
413
|
return context;
|
|
379
414
|
};
|
|
415
|
+
function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
|
|
416
|
+
const [screenSize, setScreenSize] = useState(() => {
|
|
417
|
+
if (typeof window === "undefined") {
|
|
418
|
+
return {
|
|
419
|
+
width: 1024,
|
|
420
|
+
height: 768,
|
|
421
|
+
isMobile: false,
|
|
422
|
+
isTablet: false,
|
|
423
|
+
isDesktop: true
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
const width = window.innerWidth;
|
|
427
|
+
return {
|
|
428
|
+
width,
|
|
429
|
+
height: window.innerHeight,
|
|
430
|
+
isMobile: width < mobileBreakpoint,
|
|
431
|
+
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
432
|
+
isDesktop: width >= tabletBreakpoint
|
|
433
|
+
};
|
|
434
|
+
});
|
|
435
|
+
useEffect(() => {
|
|
436
|
+
if (typeof window === "undefined") return;
|
|
437
|
+
const updateScreenSize = () => {
|
|
438
|
+
const width = window.innerWidth;
|
|
439
|
+
const height = window.innerHeight;
|
|
440
|
+
setScreenSize({
|
|
441
|
+
width,
|
|
442
|
+
height,
|
|
443
|
+
isMobile: width < mobileBreakpoint,
|
|
444
|
+
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
445
|
+
isDesktop: width >= tabletBreakpoint
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
updateScreenSize();
|
|
449
|
+
window.addEventListener("resize", updateScreenSize);
|
|
450
|
+
return () => {
|
|
451
|
+
window.removeEventListener("resize", updateScreenSize);
|
|
452
|
+
};
|
|
453
|
+
}, [mobileBreakpoint, tabletBreakpoint]);
|
|
454
|
+
return screenSize;
|
|
455
|
+
}
|
|
380
456
|
function cn(...inputs) {
|
|
381
457
|
return twMerge(clsx(inputs));
|
|
382
458
|
}
|
|
@@ -437,6 +513,45 @@ function Textarea({ className, ...props }) {
|
|
|
437
513
|
}
|
|
438
514
|
);
|
|
439
515
|
}
|
|
516
|
+
var badgeVariants = cva(
|
|
517
|
+
"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",
|
|
518
|
+
{
|
|
519
|
+
variants: {
|
|
520
|
+
variant: {
|
|
521
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
522
|
+
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
523
|
+
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",
|
|
524
|
+
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
|
|
525
|
+
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
526
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
defaultVariants: {
|
|
530
|
+
variant: "default"
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
);
|
|
534
|
+
function Badge({
|
|
535
|
+
className,
|
|
536
|
+
variant = "default",
|
|
537
|
+
render,
|
|
538
|
+
...props
|
|
539
|
+
}) {
|
|
540
|
+
return useRender({
|
|
541
|
+
defaultTagName: "span",
|
|
542
|
+
props: mergeProps(
|
|
543
|
+
{
|
|
544
|
+
className: cn(badgeVariants({ className, variant }))
|
|
545
|
+
},
|
|
546
|
+
props
|
|
547
|
+
),
|
|
548
|
+
render,
|
|
549
|
+
state: {
|
|
550
|
+
slot: "badge",
|
|
551
|
+
variant
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
440
555
|
function DropdownMenu({ ...props }) {
|
|
441
556
|
return /* @__PURE__ */ jsx(Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
442
557
|
}
|
|
@@ -563,11 +678,18 @@ function Composer({
|
|
|
563
678
|
className,
|
|
564
679
|
options = [],
|
|
565
680
|
autoFocus = false,
|
|
566
|
-
defaultSelectedIds = []
|
|
681
|
+
defaultSelectedIds = [],
|
|
682
|
+
fileAttachments
|
|
567
683
|
}) {
|
|
568
|
-
const
|
|
684
|
+
const enabled = fileAttachments?.enabled || false;
|
|
685
|
+
const accept = fileAttachments?.accept;
|
|
686
|
+
const maxFiles = fileAttachments?.maxFiles ?? 10;
|
|
687
|
+
const maxFileSize = fileAttachments?.maxFileSize ?? 10 * 1024 * 1024;
|
|
688
|
+
const [selectedOptions, setSelectedOptions] = React11__default.useState(
|
|
569
689
|
() => new Set(defaultSelectedIds)
|
|
570
690
|
);
|
|
691
|
+
const [attachedFiles, setAttachedFiles] = React11__default.useState([]);
|
|
692
|
+
const fileInputRef = React11__default.useRef(null);
|
|
571
693
|
const toggleOption = (id, groupOptions, type = "multiple") => {
|
|
572
694
|
const next = new Set(selectedOptions);
|
|
573
695
|
if (type === "single") {
|
|
@@ -587,7 +709,38 @@ function Composer({
|
|
|
587
709
|
}
|
|
588
710
|
setSelectedOptions(next);
|
|
589
711
|
};
|
|
590
|
-
const
|
|
712
|
+
const handleFileSelect = (e) => {
|
|
713
|
+
const files = Array.from(e.target.files || []);
|
|
714
|
+
const validFiles = files.filter((file) => {
|
|
715
|
+
if (file.size > maxFileSize) {
|
|
716
|
+
console.warn(
|
|
717
|
+
`File ${file.name} exceeds maximum size of ${maxFileSize} bytes`
|
|
718
|
+
);
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
return true;
|
|
722
|
+
});
|
|
723
|
+
const remainingSlots = maxFiles - attachedFiles.length;
|
|
724
|
+
const filesToAdd = validFiles.slice(0, remainingSlots);
|
|
725
|
+
if (filesToAdd.length < validFiles.length) {
|
|
726
|
+
console.warn(
|
|
727
|
+
`Only ${filesToAdd.length} files can be added (max: ${maxFiles})`
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
setAttachedFiles((prev) => [...prev, ...filesToAdd]);
|
|
731
|
+
if (fileInputRef.current) {
|
|
732
|
+
fileInputRef.current.value = "";
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
const handleRemoveFile = (index) => {
|
|
736
|
+
setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
737
|
+
};
|
|
738
|
+
const formatFileSize = (bytes) => {
|
|
739
|
+
if (bytes < 1024) return bytes + " B";
|
|
740
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
741
|
+
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
742
|
+
};
|
|
743
|
+
const handleInternalSubmit = async () => {
|
|
591
744
|
const state = {};
|
|
592
745
|
options.forEach((group) => {
|
|
593
746
|
const selectedInGroup = group.options.filter(
|
|
@@ -604,12 +757,52 @@ function Composer({
|
|
|
604
757
|
}
|
|
605
758
|
}
|
|
606
759
|
});
|
|
760
|
+
if (attachedFiles.length > 0) {
|
|
761
|
+
const filePromises = attachedFiles.map((file) => {
|
|
762
|
+
return new Promise((resolve, reject) => {
|
|
763
|
+
const reader = new FileReader();
|
|
764
|
+
reader.onload = () => {
|
|
765
|
+
try {
|
|
766
|
+
const base64 = reader.result;
|
|
767
|
+
if (!base64) {
|
|
768
|
+
reject(new Error("FileReader returned empty result"));
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
resolve({
|
|
772
|
+
name: file.name,
|
|
773
|
+
type: file.type,
|
|
774
|
+
size: file.size,
|
|
775
|
+
data: base64
|
|
776
|
+
});
|
|
777
|
+
} catch (error) {
|
|
778
|
+
reject(error);
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
reader.onerror = (error) => {
|
|
782
|
+
reject(new Error(`Failed to read file ${file.name}: ${error}`));
|
|
783
|
+
};
|
|
784
|
+
reader.onabort = () => {
|
|
785
|
+
reject(new Error(`File read aborted for ${file.name}`));
|
|
786
|
+
};
|
|
787
|
+
reader.readAsDataURL(file);
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
try {
|
|
791
|
+
const convertedFiles = await Promise.all(filePromises);
|
|
792
|
+
if (convertedFiles.length > 0) {
|
|
793
|
+
state.files = convertedFiles;
|
|
794
|
+
}
|
|
795
|
+
} catch (error) {
|
|
796
|
+
console.error("Failed to convert files to base64:", error);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
607
799
|
onSubmit(state);
|
|
800
|
+
setAttachedFiles([]);
|
|
608
801
|
};
|
|
609
802
|
const handleKeyDown = (e) => {
|
|
610
803
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
611
804
|
e.preventDefault();
|
|
612
|
-
handleInternalSubmit();
|
|
805
|
+
handleInternalSubmit().catch(console.error);
|
|
613
806
|
}
|
|
614
807
|
};
|
|
615
808
|
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: [
|
|
@@ -625,59 +818,171 @@ function Composer({
|
|
|
625
818
|
}
|
|
626
819
|
),
|
|
627
820
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
|
|
628
|
-
/* @__PURE__ */
|
|
629
|
-
|
|
630
|
-
(o) => selectedOptions.has(o.id)
|
|
631
|
-
);
|
|
632
|
-
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : `${group.label} (${selectedInGroup.length})`;
|
|
633
|
-
const isSingle = group.type === "single";
|
|
634
|
-
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
821
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
822
|
+
enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
635
823
|
/* @__PURE__ */ jsx(
|
|
636
|
-
|
|
824
|
+
"input",
|
|
637
825
|
{
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
),
|
|
646
|
-
children: [
|
|
647
|
-
label,
|
|
648
|
-
/* @__PURE__ */ jsx(IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
649
|
-
]
|
|
650
|
-
}
|
|
651
|
-
)
|
|
826
|
+
ref: fileInputRef,
|
|
827
|
+
type: "file",
|
|
828
|
+
multiple: true,
|
|
829
|
+
accept,
|
|
830
|
+
onChange: handleFileSelect,
|
|
831
|
+
className: "hidden",
|
|
832
|
+
disabled: isLoading || attachedFiles.length >= maxFiles
|
|
652
833
|
}
|
|
653
834
|
),
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
835
|
+
attachedFiles.length === 0 ? /* @__PURE__ */ jsx(
|
|
836
|
+
Button,
|
|
837
|
+
{
|
|
838
|
+
type: "button",
|
|
839
|
+
variant: "ghost",
|
|
840
|
+
size: "sm",
|
|
841
|
+
onClick: () => fileInputRef.current?.click(),
|
|
842
|
+
disabled: isLoading,
|
|
843
|
+
className: "text-muted-foreground",
|
|
844
|
+
title: "Attach file",
|
|
845
|
+
children: /* @__PURE__ */ jsx(IconPaperclip, { className: "h-4 w-4" })
|
|
846
|
+
}
|
|
847
|
+
) : /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
848
|
+
/* @__PURE__ */ jsx(
|
|
849
|
+
DropdownMenuTrigger,
|
|
659
850
|
{
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
851
|
+
render: /* @__PURE__ */ jsxs(
|
|
852
|
+
Button,
|
|
853
|
+
{
|
|
854
|
+
type: "button",
|
|
855
|
+
variant: "ghost",
|
|
856
|
+
size: "sm",
|
|
857
|
+
className: "text-muted-foreground gap-2",
|
|
858
|
+
title: `${attachedFiles.length} files attached`,
|
|
859
|
+
children: [
|
|
860
|
+
/* @__PURE__ */ jsx(IconPaperclip, { className: "h-4 w-4" }),
|
|
861
|
+
/* @__PURE__ */ jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
|
|
862
|
+
]
|
|
863
|
+
}
|
|
864
|
+
)
|
|
865
|
+
}
|
|
866
|
+
),
|
|
867
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", className: "w-64", children: [
|
|
868
|
+
/* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
869
|
+
/* @__PURE__ */ jsxs(DropdownMenuLabel, { children: [
|
|
870
|
+
"Attached Files (",
|
|
871
|
+
attachedFiles.length,
|
|
872
|
+
"/",
|
|
873
|
+
maxFiles,
|
|
874
|
+
")"
|
|
875
|
+
] }),
|
|
876
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
877
|
+
attachedFiles.map((file, index) => /* @__PURE__ */ jsxs(
|
|
878
|
+
DropdownMenuItem,
|
|
879
|
+
{
|
|
880
|
+
className: "flex items-center justify-between group",
|
|
881
|
+
onSelect: (e) => e.preventDefault(),
|
|
882
|
+
children: [
|
|
883
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
884
|
+
/* @__PURE__ */ jsx(
|
|
885
|
+
"span",
|
|
886
|
+
{
|
|
887
|
+
className: "truncate text-sm",
|
|
888
|
+
title: file.name,
|
|
889
|
+
children: file.name
|
|
890
|
+
}
|
|
891
|
+
),
|
|
892
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatFileSize(file.size) })
|
|
893
|
+
] }),
|
|
894
|
+
/* @__PURE__ */ jsx(
|
|
895
|
+
Button,
|
|
896
|
+
{
|
|
897
|
+
type: "button",
|
|
898
|
+
variant: "ghost",
|
|
899
|
+
size: "icon",
|
|
900
|
+
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
901
|
+
onClick: () => handleRemoveFile(index),
|
|
902
|
+
children: /* @__PURE__ */ jsx(IconX, { className: "h-3 w-3" })
|
|
903
|
+
}
|
|
904
|
+
)
|
|
905
|
+
]
|
|
906
|
+
},
|
|
907
|
+
index
|
|
908
|
+
))
|
|
909
|
+
] }),
|
|
910
|
+
attachedFiles.length < maxFiles && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
911
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
912
|
+
/* @__PURE__ */ jsxs(
|
|
913
|
+
DropdownMenuItem,
|
|
914
|
+
{
|
|
915
|
+
onSelect: (e) => {
|
|
916
|
+
e.preventDefault();
|
|
917
|
+
fileInputRef.current?.click();
|
|
918
|
+
},
|
|
919
|
+
className: "text-primary focus:text-primary",
|
|
920
|
+
children: [
|
|
921
|
+
/* @__PURE__ */ jsx(IconPlus, { className: "mr-2 h-4 w-4" }),
|
|
922
|
+
/* @__PURE__ */ jsx("span", { children: "Add more files" })
|
|
923
|
+
]
|
|
924
|
+
}
|
|
925
|
+
)
|
|
926
|
+
] })
|
|
927
|
+
] })
|
|
928
|
+
] })
|
|
929
|
+
] }),
|
|
930
|
+
options.map((group) => {
|
|
931
|
+
const selectedInGroup = group.options.filter(
|
|
932
|
+
(o) => selectedOptions.has(o.id)
|
|
933
|
+
);
|
|
934
|
+
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : group.label;
|
|
935
|
+
const isSingle = group.type === "single";
|
|
936
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
937
|
+
/* @__PURE__ */ jsx(
|
|
938
|
+
DropdownMenuTrigger,
|
|
939
|
+
{
|
|
940
|
+
render: /* @__PURE__ */ jsxs(
|
|
941
|
+
Button,
|
|
942
|
+
{
|
|
943
|
+
variant: "ghost",
|
|
944
|
+
size: "sm",
|
|
945
|
+
className: cn(
|
|
946
|
+
"gap-2",
|
|
947
|
+
selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
|
|
948
|
+
),
|
|
949
|
+
children: [
|
|
950
|
+
label,
|
|
951
|
+
selectedInGroup.length > 1 && /* @__PURE__ */ jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: selectedInGroup.length }),
|
|
952
|
+
/* @__PURE__ */ jsx(IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
953
|
+
]
|
|
954
|
+
}
|
|
955
|
+
)
|
|
956
|
+
}
|
|
957
|
+
),
|
|
958
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "w-56", children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
959
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: group.label }),
|
|
960
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
961
|
+
group.options.map((option) => /* @__PURE__ */ jsx(
|
|
962
|
+
DropdownMenuCheckboxItem,
|
|
963
|
+
{
|
|
964
|
+
checked: selectedOptions.has(option.id),
|
|
965
|
+
onCheckedChange: () => toggleOption(
|
|
966
|
+
option.id,
|
|
967
|
+
group.options,
|
|
968
|
+
isSingle ? "single" : "multiple"
|
|
969
|
+
),
|
|
970
|
+
onSelect: (e) => e.preventDefault(),
|
|
971
|
+
children: option.label
|
|
972
|
+
},
|
|
973
|
+
option.id
|
|
974
|
+
))
|
|
975
|
+
] }) })
|
|
976
|
+
] }, group.id);
|
|
977
|
+
})
|
|
978
|
+
] }),
|
|
674
979
|
/* @__PURE__ */ jsx(
|
|
675
980
|
Button,
|
|
676
981
|
{
|
|
677
982
|
type: "submit",
|
|
678
|
-
disabled: !value.trim() && !isLoading || isLoading,
|
|
983
|
+
disabled: !value.trim() && attachedFiles.length === 0 && !isLoading || isLoading,
|
|
679
984
|
size: "icon-lg",
|
|
680
|
-
onClick: handleInternalSubmit,
|
|
985
|
+
onClick: () => handleInternalSubmit().catch(console.error),
|
|
681
986
|
children: isLoading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsx(IconArrowUp, { className: "h-5 w-5" })
|
|
682
987
|
}
|
|
683
988
|
)
|
|
@@ -814,8 +1119,6 @@ var Col = ({
|
|
|
814
1119
|
gap = "sm",
|
|
815
1120
|
align = "start",
|
|
816
1121
|
justify = "start",
|
|
817
|
-
wrap = "nowrap",
|
|
818
|
-
flex = 1,
|
|
819
1122
|
width,
|
|
820
1123
|
height,
|
|
821
1124
|
padding,
|
|
@@ -865,13 +1168,11 @@ var Col = ({
|
|
|
865
1168
|
gapClasses[gap] || "gap-2",
|
|
866
1169
|
alignClasses[align] || "items-start",
|
|
867
1170
|
justifyClasses[justify] || "justify-start",
|
|
868
|
-
wrap === "wrap" ? "flex-wrap" : "flex-nowrap",
|
|
869
1171
|
overflow && overflowClasses[overflow],
|
|
870
1172
|
position && positionClasses[position],
|
|
871
1173
|
className
|
|
872
1174
|
),
|
|
873
1175
|
style: {
|
|
874
|
-
flex,
|
|
875
1176
|
width,
|
|
876
1177
|
height,
|
|
877
1178
|
padding,
|
|
@@ -1305,45 +1606,6 @@ var Icon = ({
|
|
|
1305
1606
|
}
|
|
1306
1607
|
);
|
|
1307
1608
|
};
|
|
1308
|
-
var badgeVariants = cva(
|
|
1309
|
-
"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",
|
|
1310
|
-
{
|
|
1311
|
-
variants: {
|
|
1312
|
-
variant: {
|
|
1313
|
-
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
1314
|
-
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
1315
|
-
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",
|
|
1316
|
-
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
|
|
1317
|
-
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
1318
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
1319
|
-
}
|
|
1320
|
-
},
|
|
1321
|
-
defaultVariants: {
|
|
1322
|
-
variant: "default"
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
);
|
|
1326
|
-
function Badge({
|
|
1327
|
-
className,
|
|
1328
|
-
variant = "default",
|
|
1329
|
-
render,
|
|
1330
|
-
...props
|
|
1331
|
-
}) {
|
|
1332
|
-
return useRender({
|
|
1333
|
-
defaultTagName: "span",
|
|
1334
|
-
props: mergeProps(
|
|
1335
|
-
{
|
|
1336
|
-
className: cn(badgeVariants({ className, variant }))
|
|
1337
|
-
},
|
|
1338
|
-
props
|
|
1339
|
-
),
|
|
1340
|
-
render,
|
|
1341
|
-
state: {
|
|
1342
|
-
slot: "badge",
|
|
1343
|
-
variant
|
|
1344
|
-
}
|
|
1345
|
-
});
|
|
1346
|
-
}
|
|
1347
1609
|
var Badge2 = ({
|
|
1348
1610
|
label,
|
|
1349
1611
|
variant = "primary",
|
|
@@ -1932,9 +2194,9 @@ var Select2 = ({
|
|
|
1932
2194
|
defaultValue,
|
|
1933
2195
|
value,
|
|
1934
2196
|
disabled,
|
|
1935
|
-
onValueChange: handleValueChange,
|
|
2197
|
+
onValueChange: (value2) => handleValueChange(value2 || ""),
|
|
1936
2198
|
children: [
|
|
1937
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx(SelectValue, {
|
|
2199
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
1938
2200
|
/* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1939
2201
|
]
|
|
1940
2202
|
}
|
|
@@ -1964,7 +2226,6 @@ var Label2 = ({
|
|
|
1964
2226
|
var Checkbox = ({
|
|
1965
2227
|
label,
|
|
1966
2228
|
name,
|
|
1967
|
-
value = "on",
|
|
1968
2229
|
checked,
|
|
1969
2230
|
defaultChecked,
|
|
1970
2231
|
disabled,
|
|
@@ -1979,46 +2240,37 @@ var Checkbox = ({
|
|
|
1979
2240
|
...onChangeAction,
|
|
1980
2241
|
data: {
|
|
1981
2242
|
name: name || "",
|
|
1982
|
-
value,
|
|
1983
2243
|
checked: e.target.checked
|
|
1984
2244
|
}
|
|
1985
2245
|
});
|
|
1986
2246
|
}
|
|
1987
2247
|
};
|
|
1988
|
-
return /* @__PURE__ */ jsxs(
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
{
|
|
2011
|
-
htmlFor: name,
|
|
2012
|
-
value: label,
|
|
2013
|
-
className: cn(
|
|
2014
|
-
"cursor-pointer select-none text-sm font-medium leading-none",
|
|
2015
|
-
disabled && "cursor-not-allowed opacity-50"
|
|
2016
|
-
)
|
|
2017
|
-
}
|
|
2248
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), style, children: [
|
|
2249
|
+
/* @__PURE__ */ jsx(
|
|
2250
|
+
"input",
|
|
2251
|
+
{
|
|
2252
|
+
type: "checkbox",
|
|
2253
|
+
name,
|
|
2254
|
+
id: name,
|
|
2255
|
+
checked,
|
|
2256
|
+
defaultChecked,
|
|
2257
|
+
disabled,
|
|
2258
|
+
onChange: handleChange,
|
|
2259
|
+
className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
|
|
2260
|
+
}
|
|
2261
|
+
),
|
|
2262
|
+
label && /* @__PURE__ */ jsx(
|
|
2263
|
+
Label2,
|
|
2264
|
+
{
|
|
2265
|
+
htmlFor: name,
|
|
2266
|
+
value: label,
|
|
2267
|
+
className: cn(
|
|
2268
|
+
"cursor-pointer select-none text-sm font-medium leading-none",
|
|
2269
|
+
disabled && "cursor-not-allowed opacity-50"
|
|
2018
2270
|
)
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
);
|
|
2271
|
+
}
|
|
2272
|
+
)
|
|
2273
|
+
] });
|
|
2022
2274
|
};
|
|
2023
2275
|
var RadioGroup = ({
|
|
2024
2276
|
name,
|
|
@@ -2341,12 +2593,14 @@ function Thread({
|
|
|
2341
2593
|
});
|
|
2342
2594
|
const starterPrompts = localStarterPrompts ?? config?.starterPrompts;
|
|
2343
2595
|
const options = localOptions ?? config?.options;
|
|
2596
|
+
const fileAttachments = config?.fileAttachments;
|
|
2344
2597
|
const allDefaultSelectedIds = useMemo(() => {
|
|
2345
|
-
const defaultSelectedIdsFromOptions = options?.flatMap(
|
|
2346
|
-
(group) => group.defaultSelectedIds ?? []
|
|
2347
|
-
) ?? [];
|
|
2598
|
+
const defaultSelectedIdsFromOptions = options?.flatMap((group) => group.defaultSelectedIds ?? []) ?? [];
|
|
2348
2599
|
return [
|
|
2349
|
-
.../* @__PURE__ */ new Set([
|
|
2600
|
+
.../* @__PURE__ */ new Set([
|
|
2601
|
+
...defaultSelectedIdsFromOptions,
|
|
2602
|
+
...defaultSelectedIds ?? []
|
|
2603
|
+
])
|
|
2350
2604
|
];
|
|
2351
2605
|
}, [options, defaultSelectedIds]);
|
|
2352
2606
|
const [input, setInput] = useState("");
|
|
@@ -2356,13 +2610,14 @@ function Thread({
|
|
|
2356
2610
|
}, [messages]);
|
|
2357
2611
|
const handleSubmit = async (state, overrideInput) => {
|
|
2358
2612
|
const text = (overrideInput ?? input).trim();
|
|
2359
|
-
|
|
2613
|
+
const hasFiles = state?.files && Array.isArray(state.files) && state.files.length > 0;
|
|
2614
|
+
if (!text && !hasFiles || isLoading) return;
|
|
2360
2615
|
if (!overrideInput) setInput("");
|
|
2361
2616
|
await sendEvent(
|
|
2362
2617
|
{
|
|
2363
2618
|
type: "text",
|
|
2364
2619
|
role: "user",
|
|
2365
|
-
data: { content: text }
|
|
2620
|
+
data: { content: text || "" }
|
|
2366
2621
|
},
|
|
2367
2622
|
{ state: { ...state, threadId: activeThreadId ?? void 0 } }
|
|
2368
2623
|
);
|
|
@@ -2420,7 +2675,8 @@ function Thread({
|
|
|
2420
2675
|
isLoading,
|
|
2421
2676
|
options,
|
|
2422
2677
|
autoFocus,
|
|
2423
|
-
defaultSelectedIds: allDefaultSelectedIds
|
|
2678
|
+
defaultSelectedIds: allDefaultSelectedIds,
|
|
2679
|
+
fileAttachments
|
|
2424
2680
|
}
|
|
2425
2681
|
) }) })
|
|
2426
2682
|
]
|
|
@@ -2428,20 +2684,36 @@ function Thread({
|
|
|
2428
2684
|
);
|
|
2429
2685
|
}
|
|
2430
2686
|
function ChatHeader({
|
|
2431
|
-
title,
|
|
2432
2687
|
leftContent,
|
|
2433
2688
|
rightContent,
|
|
2434
2689
|
className,
|
|
2435
|
-
titleClassName,
|
|
2436
2690
|
children
|
|
2437
2691
|
}) {
|
|
2438
2692
|
if (children) {
|
|
2439
|
-
return /* @__PURE__ */ jsx(
|
|
2693
|
+
return /* @__PURE__ */ jsx(
|
|
2694
|
+
"div",
|
|
2695
|
+
{
|
|
2696
|
+
className: cn(
|
|
2697
|
+
"px-2 border-b border-border h-14 flex items-center shrink-0",
|
|
2698
|
+
className
|
|
2699
|
+
),
|
|
2700
|
+
children
|
|
2701
|
+
}
|
|
2702
|
+
);
|
|
2440
2703
|
}
|
|
2441
|
-
return /* @__PURE__ */ jsxs(
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2704
|
+
return /* @__PURE__ */ jsxs(
|
|
2705
|
+
"div",
|
|
2706
|
+
{
|
|
2707
|
+
className: cn(
|
|
2708
|
+
"px-2 border-b border-border h-14 flex items-center justify-between shrink-0",
|
|
2709
|
+
className
|
|
2710
|
+
),
|
|
2711
|
+
children: [
|
|
2712
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: leftContent }),
|
|
2713
|
+
rightContent && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 shrink-0 ml-2", children: rightContent })
|
|
2714
|
+
]
|
|
2715
|
+
}
|
|
2716
|
+
);
|
|
2445
2717
|
}
|
|
2446
2718
|
var ThreadList = ({
|
|
2447
2719
|
className,
|
|
@@ -2492,58 +2764,43 @@ var ThreadList = ({
|
|
|
2492
2764
|
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2493
2765
|
return d.toLocaleDateString();
|
|
2494
2766
|
};
|
|
2495
|
-
return /* @__PURE__ */
|
|
2496
|
-
/* @__PURE__ */ jsx(
|
|
2497
|
-
|
|
2767
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col h-full", className), children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading && threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground" }) }) : threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-muted-foreground", children: emptyState || /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2768
|
+
/* @__PURE__ */ jsx(IconMessage, { className: "size-8 mx-auto opacity-50" }),
|
|
2769
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No threads yet" }),
|
|
2770
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
|
|
2771
|
+
] }) }) : /* @__PURE__ */ jsx("div", { className: "p-2 space-y-1", children: threads.map((thread) => {
|
|
2772
|
+
const isActive = thread.id === activeThreadId;
|
|
2773
|
+
return /* @__PURE__ */ jsxs(
|
|
2774
|
+
"div",
|
|
2498
2775
|
{
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2776
|
+
onClick: () => handleThreadClick(thread.id),
|
|
2777
|
+
className: cn(
|
|
2778
|
+
"group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
|
|
2779
|
+
isActive ? "bg-muted" : "hover:bg-muted"
|
|
2780
|
+
),
|
|
2503
2781
|
children: [
|
|
2504
|
-
/* @__PURE__ */ jsx(
|
|
2505
|
-
|
|
2782
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2783
|
+
/* @__PURE__ */ jsx("p", { className: cn("text-sm font-medium truncate"), children: thread.title || `Thread ${thread.id.slice(0, 8)}` }),
|
|
2784
|
+
thread.updatedAt && /* @__PURE__ */ jsx("span", { className: cn("text-xs shrink-0"), children: formatDate(thread.updatedAt) })
|
|
2785
|
+
] }) }),
|
|
2786
|
+
/* @__PURE__ */ jsx(
|
|
2787
|
+
Button,
|
|
2788
|
+
{
|
|
2789
|
+
variant: "ghost",
|
|
2790
|
+
size: "icon-xs",
|
|
2791
|
+
onClick: (e) => handleDelete(e, thread.id),
|
|
2792
|
+
className: cn(
|
|
2793
|
+
"opacity-0 group-hover:opacity-100 transition-opacity shrink-0",
|
|
2794
|
+
isActive && "hover:bg-primary-foreground/20"
|
|
2795
|
+
),
|
|
2796
|
+
children: /* @__PURE__ */ jsx(IconTrash, { className: "size-3" })
|
|
2797
|
+
}
|
|
2798
|
+
)
|
|
2506
2799
|
]
|
|
2507
|
-
}
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No threads yet" }),
|
|
2512
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
|
|
2513
|
-
] }) }) : /* @__PURE__ */ jsx("div", { className: "p-2 space-y-1", children: threads.map((thread) => {
|
|
2514
|
-
const isActive = thread.id === activeThreadId;
|
|
2515
|
-
return /* @__PURE__ */ jsxs(
|
|
2516
|
-
"div",
|
|
2517
|
-
{
|
|
2518
|
-
onClick: () => handleThreadClick(thread.id),
|
|
2519
|
-
className: cn(
|
|
2520
|
-
"group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
|
|
2521
|
-
isActive ? "bg-muted" : "hover:bg-muted"
|
|
2522
|
-
),
|
|
2523
|
-
children: [
|
|
2524
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2525
|
-
/* @__PURE__ */ jsx("p", { className: cn("text-sm font-medium truncate"), children: thread.title || `Thread ${thread.id.slice(0, 8)}` }),
|
|
2526
|
-
thread.updatedAt && /* @__PURE__ */ jsx("span", { className: cn("text-xs shrink-0"), children: formatDate(thread.updatedAt) })
|
|
2527
|
-
] }) }),
|
|
2528
|
-
/* @__PURE__ */ jsx(
|
|
2529
|
-
Button,
|
|
2530
|
-
{
|
|
2531
|
-
variant: "ghost",
|
|
2532
|
-
size: "icon-xs",
|
|
2533
|
-
onClick: (e) => handleDelete(e, thread.id),
|
|
2534
|
-
className: cn(
|
|
2535
|
-
"opacity-0 group-hover:opacity-100 transition-opacity shrink-0",
|
|
2536
|
-
isActive && "hover:bg-primary-foreground/20"
|
|
2537
|
-
),
|
|
2538
|
-
children: /* @__PURE__ */ jsx(IconTrash, { className: "size-3" })
|
|
2539
|
-
}
|
|
2540
|
-
)
|
|
2541
|
-
]
|
|
2542
|
-
},
|
|
2543
|
-
thread.id
|
|
2544
|
-
);
|
|
2545
|
-
}) }) })
|
|
2546
|
-
] });
|
|
2800
|
+
},
|
|
2801
|
+
thread.id
|
|
2802
|
+
);
|
|
2803
|
+
}) }) }) });
|
|
2547
2804
|
};
|
|
2548
2805
|
function ChatPopup({
|
|
2549
2806
|
title = "Chat",
|
|
@@ -2672,6 +2929,16 @@ function ChatSidebar({
|
|
|
2672
2929
|
) })
|
|
2673
2930
|
] });
|
|
2674
2931
|
}
|
|
2932
|
+
var ChatSidebarContext = createContext(
|
|
2933
|
+
void 0
|
|
2934
|
+
);
|
|
2935
|
+
function useChatSidebar() {
|
|
2936
|
+
const context = useContext(ChatSidebarContext);
|
|
2937
|
+
if (context === void 0) {
|
|
2938
|
+
throw new Error("useChatSidebar must be used within a ChatSidebarProvider");
|
|
2939
|
+
}
|
|
2940
|
+
return context;
|
|
2941
|
+
}
|
|
2675
2942
|
function ChatFull({
|
|
2676
2943
|
title = "Chat",
|
|
2677
2944
|
placeholder = "Message the AI",
|
|
@@ -2683,134 +2950,134 @@ function ChatFull({
|
|
|
2683
2950
|
rightSidebar,
|
|
2684
2951
|
leftSidebarClassName,
|
|
2685
2952
|
rightSidebarClassName,
|
|
2686
|
-
leftSidebarCollapsible = false,
|
|
2687
|
-
rightSidebarCollapsible = false,
|
|
2688
|
-
defaultLeftSidebarCollapsed = false,
|
|
2689
|
-
defaultRightSidebarCollapsed = false,
|
|
2690
|
-
leftSidebarCollapsed: controlledLeftCollapsed,
|
|
2691
|
-
rightSidebarCollapsed: controlledRightCollapsed,
|
|
2692
|
-
onLeftSidebarCollapseChange,
|
|
2693
|
-
onRightSidebarCollapseChange,
|
|
2694
2953
|
autoFocus = false,
|
|
2695
2954
|
defaultSelectedIds
|
|
2696
2955
|
}) {
|
|
2697
|
-
const
|
|
2698
|
-
|
|
2699
|
-
)
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
);
|
|
2703
|
-
const leftCollapsed = controlledLeftCollapsed !== void 0 ? controlledLeftCollapsed : internalLeftCollapsed;
|
|
2704
|
-
const rightCollapsed = controlledRightCollapsed !== void 0 ? controlledRightCollapsed : internalRightCollapsed;
|
|
2705
|
-
const handleLeftToggle = () => {
|
|
2706
|
-
const newCollapsed = !leftCollapsed;
|
|
2707
|
-
if (controlledLeftCollapsed === void 0) {
|
|
2708
|
-
setInternalLeftCollapsed(newCollapsed);
|
|
2956
|
+
const { isMobile, isTablet } = useScreenSize();
|
|
2957
|
+
const isSmallScreen = isMobile || isTablet;
|
|
2958
|
+
const [internalLeftCollapsed, setInternalLeftCollapsed] = useState(() => {
|
|
2959
|
+
if (typeof window !== "undefined") {
|
|
2960
|
+
return window.innerWidth < 1024;
|
|
2709
2961
|
}
|
|
2710
|
-
|
|
2711
|
-
};
|
|
2712
|
-
const
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
setInternalRightCollapsed(newCollapsed);
|
|
2962
|
+
return false;
|
|
2963
|
+
});
|
|
2964
|
+
const [internalRightCollapsed, setInternalRightCollapsed] = useState(() => {
|
|
2965
|
+
if (typeof window !== "undefined") {
|
|
2966
|
+
return window.innerWidth < 1024;
|
|
2716
2967
|
}
|
|
2717
|
-
|
|
2718
|
-
};
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2968
|
+
return false;
|
|
2969
|
+
});
|
|
2970
|
+
useEffect(() => {
|
|
2971
|
+
if (isSmallScreen) {
|
|
2972
|
+
setInternalLeftCollapsed(true);
|
|
2973
|
+
setInternalRightCollapsed(true);
|
|
2974
|
+
}
|
|
2975
|
+
}, [isSmallScreen]);
|
|
2976
|
+
const leftCollapsed = internalLeftCollapsed;
|
|
2977
|
+
const rightCollapsed = internalRightCollapsed;
|
|
2978
|
+
const handleLeftToggle = useCallback((collapsed) => {
|
|
2979
|
+
setInternalLeftCollapsed(collapsed);
|
|
2980
|
+
}, []);
|
|
2981
|
+
const handleRightToggle = useCallback((collapsed) => {
|
|
2982
|
+
setInternalRightCollapsed(collapsed);
|
|
2983
|
+
}, []);
|
|
2984
|
+
const contextValue = useMemo(
|
|
2985
|
+
() => ({
|
|
2986
|
+
leftCollapsed,
|
|
2987
|
+
rightCollapsed,
|
|
2988
|
+
setLeftCollapsed: handleLeftToggle,
|
|
2989
|
+
setRightCollapsed: handleRightToggle,
|
|
2990
|
+
leftCollapsible: true,
|
|
2991
|
+
rightCollapsible: true
|
|
2992
|
+
}),
|
|
2993
|
+
[leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
|
|
2994
|
+
);
|
|
2995
|
+
return /* @__PURE__ */ jsx(ChatSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
|
|
2996
|
+
"div",
|
|
2997
|
+
{
|
|
2998
|
+
className: cn("flex flex-col h-full w-full bg-background", className),
|
|
2999
|
+
children: [
|
|
3000
|
+
title && /* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
3001
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden flex relative", children: [
|
|
3002
|
+
leftSidebar && /* @__PURE__ */ jsx(
|
|
3003
|
+
"div",
|
|
3004
|
+
{
|
|
3005
|
+
className: cn(
|
|
3006
|
+
"flex-shrink-0 border-r border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3007
|
+
leftCollapsed ? "w-0 border-r-0 min-w-0" : "",
|
|
3008
|
+
!leftCollapsed && leftSidebarClassName
|
|
3009
|
+
),
|
|
3010
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: leftSidebar })
|
|
3011
|
+
}
|
|
3012
|
+
),
|
|
3013
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx(
|
|
3014
|
+
Thread,
|
|
3015
|
+
{
|
|
3016
|
+
placeholder,
|
|
3017
|
+
starterPrompts,
|
|
3018
|
+
options,
|
|
3019
|
+
autoFocus,
|
|
3020
|
+
defaultSelectedIds
|
|
3021
|
+
}
|
|
3022
|
+
) }),
|
|
3023
|
+
rightSidebar && /* @__PURE__ */ jsx(
|
|
3024
|
+
"div",
|
|
3025
|
+
{
|
|
3026
|
+
className: cn(
|
|
3027
|
+
"flex-shrink-0 border-l border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3028
|
+
rightCollapsed ? "w-0 border-l-0 min-w-0" : "",
|
|
3029
|
+
!rightCollapsed && rightSidebarClassName
|
|
3030
|
+
),
|
|
3031
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: rightSidebar })
|
|
3032
|
+
}
|
|
3033
|
+
)
|
|
3034
|
+
] })
|
|
3035
|
+
]
|
|
3036
|
+
}
|
|
3037
|
+
) });
|
|
3038
|
+
}
|
|
3039
|
+
function SidebarToggle({ side, className }) {
|
|
3040
|
+
const {
|
|
3041
|
+
leftCollapsed,
|
|
3042
|
+
rightCollapsed,
|
|
3043
|
+
setLeftCollapsed,
|
|
3044
|
+
setRightCollapsed,
|
|
3045
|
+
leftCollapsible,
|
|
3046
|
+
rightCollapsible
|
|
3047
|
+
} = useChatSidebar();
|
|
3048
|
+
if (side === "left") {
|
|
3049
|
+
if (!leftCollapsible) return null;
|
|
3050
|
+
return /* @__PURE__ */ jsx(
|
|
3051
|
+
Button,
|
|
3052
|
+
{
|
|
3053
|
+
variant: "ghost",
|
|
3054
|
+
onClick: () => setLeftCollapsed(!leftCollapsed),
|
|
3055
|
+
"aria-label": leftCollapsed ? "Expand left sidebar" : "Collapse left sidebar",
|
|
3056
|
+
className: cn("", className),
|
|
3057
|
+
children: leftCollapsed ? /* @__PURE__ */ jsx(IconLayoutSidebarLeftExpand, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconLayoutSidebarLeftCollapse, { className: "h-4 w-4" })
|
|
3058
|
+
}
|
|
3059
|
+
);
|
|
3060
|
+
}
|
|
3061
|
+
if (side === "right") {
|
|
3062
|
+
if (!rightCollapsible) return null;
|
|
3063
|
+
return /* @__PURE__ */ jsx(
|
|
3064
|
+
Button,
|
|
3065
|
+
{
|
|
3066
|
+
variant: "ghost",
|
|
3067
|
+
onClick: () => setRightCollapsed(!rightCollapsed),
|
|
3068
|
+
"aria-label": rightCollapsed ? "Expand right sidebar" : "Collapse right sidebar",
|
|
3069
|
+
className: cn("", className),
|
|
3070
|
+
children: rightCollapsed ? /* @__PURE__ */ jsx(IconLayoutSidebarRightExpand, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconLayoutSidebarRightCollapse, { className: "h-4 w-4" })
|
|
3071
|
+
}
|
|
3072
|
+
);
|
|
3073
|
+
}
|
|
3074
|
+
return null;
|
|
2808
3075
|
}
|
|
2809
|
-
var PopoverContext =
|
|
3076
|
+
var PopoverContext = React11.createContext(
|
|
2810
3077
|
void 0
|
|
2811
3078
|
);
|
|
2812
3079
|
function usePopoverContext() {
|
|
2813
|
-
const context =
|
|
3080
|
+
const context = React11.useContext(PopoverContext);
|
|
2814
3081
|
if (!context) {
|
|
2815
3082
|
throw new Error("Popover components must be used within a Popover");
|
|
2816
3083
|
}
|
|
@@ -2822,10 +3089,10 @@ function Popover({
|
|
|
2822
3089
|
open: controlledOpen,
|
|
2823
3090
|
onOpenChange
|
|
2824
3091
|
}) {
|
|
2825
|
-
const [internalOpen, setInternalOpen] =
|
|
2826
|
-
const triggerRef =
|
|
3092
|
+
const [internalOpen, setInternalOpen] = React11.useState(defaultOpen);
|
|
3093
|
+
const triggerRef = React11.useRef(null);
|
|
2827
3094
|
const open = controlledOpen ?? internalOpen;
|
|
2828
|
-
const setOpen =
|
|
3095
|
+
const setOpen = React11.useCallback(
|
|
2829
3096
|
(newOpen) => {
|
|
2830
3097
|
if (controlledOpen === void 0) {
|
|
2831
3098
|
setInternalOpen(newOpen);
|
|
@@ -2834,7 +3101,7 @@ function Popover({
|
|
|
2834
3101
|
},
|
|
2835
3102
|
[controlledOpen, onOpenChange]
|
|
2836
3103
|
);
|
|
2837
|
-
const value =
|
|
3104
|
+
const value = React11.useMemo(
|
|
2838
3105
|
() => ({
|
|
2839
3106
|
open,
|
|
2840
3107
|
setOpen,
|
|
@@ -2844,15 +3111,15 @@ function Popover({
|
|
|
2844
3111
|
);
|
|
2845
3112
|
return /* @__PURE__ */ jsx(PopoverContext.Provider, { value, children });
|
|
2846
3113
|
}
|
|
2847
|
-
var PopoverTrigger =
|
|
3114
|
+
var PopoverTrigger = React11.forwardRef(
|
|
2848
3115
|
({ asChild, className, children, ...props }, ref) => {
|
|
2849
3116
|
const { setOpen, triggerRef } = usePopoverContext();
|
|
2850
3117
|
const handleClick = (e) => {
|
|
2851
3118
|
setOpen(true);
|
|
2852
3119
|
props.onClick?.(e);
|
|
2853
3120
|
};
|
|
2854
|
-
if (asChild &&
|
|
2855
|
-
return
|
|
3121
|
+
if (asChild && React11.isValidElement(children)) {
|
|
3122
|
+
return React11.cloneElement(children, {
|
|
2856
3123
|
ref: (node) => {
|
|
2857
3124
|
triggerRef.current = node;
|
|
2858
3125
|
if (typeof children.ref === "function") {
|
|
@@ -2884,7 +3151,7 @@ var PopoverTrigger = React10.forwardRef(
|
|
|
2884
3151
|
}
|
|
2885
3152
|
);
|
|
2886
3153
|
PopoverTrigger.displayName = "PopoverTrigger";
|
|
2887
|
-
var PopoverContent =
|
|
3154
|
+
var PopoverContent = React11.forwardRef(
|
|
2888
3155
|
({
|
|
2889
3156
|
className,
|
|
2890
3157
|
side = "bottom",
|
|
@@ -2895,9 +3162,9 @@ var PopoverContent = React10.forwardRef(
|
|
|
2895
3162
|
...props
|
|
2896
3163
|
}, ref) => {
|
|
2897
3164
|
const { open, setOpen, triggerRef } = usePopoverContext();
|
|
2898
|
-
const [position, setPosition] =
|
|
2899
|
-
const contentRef =
|
|
2900
|
-
|
|
3165
|
+
const [position, setPosition] = React11.useState({ top: 0, left: 0 });
|
|
3166
|
+
const contentRef = React11.useRef(null);
|
|
3167
|
+
React11.useEffect(() => {
|
|
2901
3168
|
if (!open || !triggerRef.current) return;
|
|
2902
3169
|
const updatePosition = () => {
|
|
2903
3170
|
if (!triggerRef.current || !contentRef.current) return;
|
|
@@ -2958,7 +3225,7 @@ var PopoverContent = React10.forwardRef(
|
|
|
2958
3225
|
window.removeEventListener("scroll", updatePosition, true);
|
|
2959
3226
|
};
|
|
2960
3227
|
}, [open, side, align, sideOffset, alignOffset, triggerRef]);
|
|
2961
|
-
|
|
3228
|
+
React11.useEffect(() => {
|
|
2962
3229
|
if (!open) return;
|
|
2963
3230
|
const handleClickOutside = (event) => {
|
|
2964
3231
|
if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
|
|
@@ -3014,7 +3281,7 @@ var ThreadPopover = ({
|
|
|
3014
3281
|
emptyState,
|
|
3015
3282
|
onThreadSelect
|
|
3016
3283
|
}) => {
|
|
3017
|
-
const [isOpen, setIsOpen] =
|
|
3284
|
+
const [isOpen, setIsOpen] = React11.useState(false);
|
|
3018
3285
|
useHotkeys(
|
|
3019
3286
|
"h",
|
|
3020
3287
|
(e) => {
|
|
@@ -3069,7 +3336,7 @@ var CreateThreadButton = ({
|
|
|
3069
3336
|
onThreadCreated
|
|
3070
3337
|
}) => {
|
|
3071
3338
|
const { createThread } = useThreads();
|
|
3072
|
-
const [isCreating, setIsCreating] =
|
|
3339
|
+
const [isCreating, setIsCreating] = React11.useState(false);
|
|
3073
3340
|
const handleCreateThread = async () => {
|
|
3074
3341
|
if (isCreating) return;
|
|
3075
3342
|
try {
|
|
@@ -3195,10 +3462,10 @@ var AccountDialog = ({
|
|
|
3195
3462
|
size
|
|
3196
3463
|
}) => {
|
|
3197
3464
|
const { isLoading, isAuthenticated, user, login, logout } = useAuth();
|
|
3198
|
-
const [open, setOpen] =
|
|
3199
|
-
const [accountInfoOpen, setAccountInfoOpen] =
|
|
3200
|
-
const [error, setError] =
|
|
3201
|
-
const initials =
|
|
3465
|
+
const [open, setOpen] = React11.useState(false);
|
|
3466
|
+
const [accountInfoOpen, setAccountInfoOpen] = React11.useState(false);
|
|
3467
|
+
const [error, setError] = React11.useState(null);
|
|
3468
|
+
const initials = React11.useMemo(() => {
|
|
3202
3469
|
const name = user?.displayName || user?.name;
|
|
3203
3470
|
if (!name) return "";
|
|
3204
3471
|
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
@@ -3371,6 +3638,6 @@ function ThemeToggle() {
|
|
|
3371
3638
|
);
|
|
3372
3639
|
}
|
|
3373
3640
|
|
|
3374
|
-
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 };
|
|
3641
|
+
export { AccountDialog, AuthContext, AuthProvider, Badge2 as Badge, Box, Button2 as Button, Card2 as Card, Chart, ChatFull, ChatHeader, ChatPopup, ChatSidebar, ChatSidebarContext, Checkbox, Col, Composer, CreateThreadButton, Divider, Form, Heading, Image, Input2 as Input, Label2 as Label, List, ListItem, MelonyClientProvider, MelonyContext, RadioGroup, Row, Select2 as Select, SidebarToggle, Spacer, Text, Textarea2 as Textarea, ThemeProvider, ThemeToggle, Thread, ThreadContext, ThreadList, ThreadPopover, ThreadProvider, UIRenderer, groupEventsToMessages, useAuth, useChatSidebar, useMelony, useScreenSize, useTheme, useThreads };
|
|
3375
3642
|
//# sourceMappingURL=index.js.map
|
|
3376
3643
|
//# sourceMappingURL=index.js.map
|