@melony/react 0.1.23 → 0.1.24
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 +202 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -6
- package/dist/index.d.ts +12 -6
- package/dist/index.js +203 -70
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
3
|
import { ClientState, MelonyClient } from 'melony/client';
|
|
4
|
-
import { Role, Event, UINode } from 'melony';
|
|
4
|
+
import { Role, Event, Config, UINode } from 'melony';
|
|
5
5
|
import { QueryClient } from '@tanstack/react-query';
|
|
6
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
7
|
|
|
@@ -65,10 +65,7 @@ interface MelonyContextValue extends ClientState {
|
|
|
65
65
|
}) => Promise<void>;
|
|
66
66
|
reset: (events?: Event[]) => void;
|
|
67
67
|
client: MelonyClient;
|
|
68
|
-
config?:
|
|
69
|
-
starterPrompts: any[];
|
|
70
|
-
options: any[];
|
|
71
|
-
};
|
|
68
|
+
config?: Config;
|
|
72
69
|
}
|
|
73
70
|
declare const MelonyContext: React__default.Context<MelonyContextValue | undefined>;
|
|
74
71
|
interface MelonyClientProviderProps {
|
|
@@ -156,8 +153,17 @@ interface ComposerProps {
|
|
|
156
153
|
options?: ComposerOptionGroup[];
|
|
157
154
|
autoFocus?: boolean;
|
|
158
155
|
defaultSelectedIds?: string[];
|
|
156
|
+
fileAttachments?: {
|
|
157
|
+
enabled?: boolean;
|
|
158
|
+
accept?: string;
|
|
159
|
+
maxFiles?: number;
|
|
160
|
+
maxFileSize?: number;
|
|
161
|
+
};
|
|
162
|
+
accept?: string;
|
|
163
|
+
maxFiles?: number;
|
|
164
|
+
maxFileSize?: number;
|
|
159
165
|
}
|
|
160
|
-
declare function Composer({ value, onChange, onSubmit, placeholder, isLoading, className, options, autoFocus, defaultSelectedIds, }: ComposerProps): react_jsx_runtime.JSX.Element;
|
|
166
|
+
declare function Composer({ value, onChange, onSubmit, placeholder, isLoading, className, options, autoFocus, defaultSelectedIds, fileAttachments, accept: legacyAccept, maxFiles: legacyMaxFiles, maxFileSize: legacyMaxFileSize, }: ComposerProps): react_jsx_runtime.JSX.Element;
|
|
161
167
|
|
|
162
168
|
interface ChatHeaderProps {
|
|
163
169
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
3
|
import { ClientState, MelonyClient } from 'melony/client';
|
|
4
|
-
import { Role, Event, UINode } from 'melony';
|
|
4
|
+
import { Role, Event, Config, UINode } from 'melony';
|
|
5
5
|
import { QueryClient } from '@tanstack/react-query';
|
|
6
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
7
|
|
|
@@ -65,10 +65,7 @@ interface MelonyContextValue extends ClientState {
|
|
|
65
65
|
}) => Promise<void>;
|
|
66
66
|
reset: (events?: Event[]) => void;
|
|
67
67
|
client: MelonyClient;
|
|
68
|
-
config?:
|
|
69
|
-
starterPrompts: any[];
|
|
70
|
-
options: any[];
|
|
71
|
-
};
|
|
68
|
+
config?: Config;
|
|
72
69
|
}
|
|
73
70
|
declare const MelonyContext: React__default.Context<MelonyContextValue | undefined>;
|
|
74
71
|
interface MelonyClientProviderProps {
|
|
@@ -156,8 +153,17 @@ interface ComposerProps {
|
|
|
156
153
|
options?: ComposerOptionGroup[];
|
|
157
154
|
autoFocus?: boolean;
|
|
158
155
|
defaultSelectedIds?: string[];
|
|
156
|
+
fileAttachments?: {
|
|
157
|
+
enabled?: boolean;
|
|
158
|
+
accept?: string;
|
|
159
|
+
maxFiles?: number;
|
|
160
|
+
maxFileSize?: number;
|
|
161
|
+
};
|
|
162
|
+
accept?: string;
|
|
163
|
+
maxFiles?: number;
|
|
164
|
+
maxFileSize?: number;
|
|
159
165
|
}
|
|
160
|
-
declare function Composer({ value, onChange, onSubmit, placeholder, isLoading, className, options, autoFocus, defaultSelectedIds, }: ComposerProps): react_jsx_runtime.JSX.Element;
|
|
166
|
+
declare function Composer({ value, onChange, onSubmit, placeholder, isLoading, className, options, autoFocus, defaultSelectedIds, fileAttachments, accept: legacyAccept, maxFiles: legacyMaxFiles, maxFileSize: legacyMaxFileSize, }: ComposerProps): react_jsx_runtime.JSX.Element;
|
|
161
167
|
|
|
162
168
|
interface ChatHeaderProps {
|
|
163
169
|
/**
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ 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
12
|
import * as ICONS from '@tabler/icons-react';
|
|
13
|
-
import { IconChevronDown, IconLoader2, IconArrowUp, IconPlus, IconMessage, IconTrash, IconHistory,
|
|
13
|
+
import { IconX, IconPaperclip, IconChevronDown, IconLoader2, IconArrowUp, IconPlus, IconMessage, IconTrash, IconHistory, IconArrowLeft, IconChevronLeft, IconChevronRight, IconUser, IconLogout, IconBrandGoogle, IconDeviceDesktop, IconMoon, IconSun, IconCheck, IconChevronUp, IconSelector } from '@tabler/icons-react';
|
|
14
14
|
import { Menu } from '@base-ui/react/menu';
|
|
15
15
|
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
16
16
|
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
@@ -563,11 +563,22 @@ function Composer({
|
|
|
563
563
|
className,
|
|
564
564
|
options = [],
|
|
565
565
|
autoFocus = false,
|
|
566
|
-
defaultSelectedIds = []
|
|
566
|
+
defaultSelectedIds = [],
|
|
567
|
+
fileAttachments,
|
|
568
|
+
// Legacy props for backward compatibility
|
|
569
|
+
accept: legacyAccept,
|
|
570
|
+
maxFiles: legacyMaxFiles,
|
|
571
|
+
maxFileSize: legacyMaxFileSize
|
|
567
572
|
}) {
|
|
573
|
+
const enabled = fileAttachments?.enabled !== false;
|
|
574
|
+
const accept = fileAttachments?.accept ?? legacyAccept;
|
|
575
|
+
const maxFiles = fileAttachments?.maxFiles ?? legacyMaxFiles ?? 10;
|
|
576
|
+
const maxFileSize = fileAttachments?.maxFileSize ?? legacyMaxFileSize ?? 10 * 1024 * 1024;
|
|
568
577
|
const [selectedOptions, setSelectedOptions] = React10__default.useState(
|
|
569
578
|
() => new Set(defaultSelectedIds)
|
|
570
579
|
);
|
|
580
|
+
const [attachedFiles, setAttachedFiles] = React10__default.useState([]);
|
|
581
|
+
const fileInputRef = React10__default.useRef(null);
|
|
571
582
|
const toggleOption = (id, groupOptions, type = "multiple") => {
|
|
572
583
|
const next = new Set(selectedOptions);
|
|
573
584
|
if (type === "single") {
|
|
@@ -587,7 +598,34 @@ function Composer({
|
|
|
587
598
|
}
|
|
588
599
|
setSelectedOptions(next);
|
|
589
600
|
};
|
|
590
|
-
const
|
|
601
|
+
const handleFileSelect = (e) => {
|
|
602
|
+
const files = Array.from(e.target.files || []);
|
|
603
|
+
const validFiles = files.filter((file) => {
|
|
604
|
+
if (file.size > maxFileSize) {
|
|
605
|
+
console.warn(`File ${file.name} exceeds maximum size of ${maxFileSize} bytes`);
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
return true;
|
|
609
|
+
});
|
|
610
|
+
const remainingSlots = maxFiles - attachedFiles.length;
|
|
611
|
+
const filesToAdd = validFiles.slice(0, remainingSlots);
|
|
612
|
+
if (filesToAdd.length < validFiles.length) {
|
|
613
|
+
console.warn(`Only ${filesToAdd.length} files can be added (max: ${maxFiles})`);
|
|
614
|
+
}
|
|
615
|
+
setAttachedFiles((prev) => [...prev, ...filesToAdd]);
|
|
616
|
+
if (fileInputRef.current) {
|
|
617
|
+
fileInputRef.current.value = "";
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
const handleRemoveFile = (index) => {
|
|
621
|
+
setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
622
|
+
};
|
|
623
|
+
const formatFileSize = (bytes) => {
|
|
624
|
+
if (bytes < 1024) return bytes + " B";
|
|
625
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
626
|
+
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
627
|
+
};
|
|
628
|
+
const handleInternalSubmit = async () => {
|
|
591
629
|
const state = {};
|
|
592
630
|
options.forEach((group) => {
|
|
593
631
|
const selectedInGroup = group.options.filter(
|
|
@@ -604,85 +642,178 @@ function Composer({
|
|
|
604
642
|
}
|
|
605
643
|
}
|
|
606
644
|
});
|
|
645
|
+
if (attachedFiles.length > 0) {
|
|
646
|
+
const filePromises = attachedFiles.map((file) => {
|
|
647
|
+
return new Promise((resolve, reject) => {
|
|
648
|
+
const reader = new FileReader();
|
|
649
|
+
reader.onload = () => {
|
|
650
|
+
try {
|
|
651
|
+
const base64 = reader.result;
|
|
652
|
+
if (!base64) {
|
|
653
|
+
reject(new Error("FileReader returned empty result"));
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
const base64Data = base64.includes(",") ? base64.split(",")[1] : base64;
|
|
657
|
+
resolve({
|
|
658
|
+
name: file.name,
|
|
659
|
+
type: file.type,
|
|
660
|
+
size: file.size,
|
|
661
|
+
data: base64Data
|
|
662
|
+
});
|
|
663
|
+
} catch (error) {
|
|
664
|
+
reject(error);
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
reader.onerror = (error) => {
|
|
668
|
+
reject(new Error(`Failed to read file ${file.name}: ${error}`));
|
|
669
|
+
};
|
|
670
|
+
reader.onabort = () => {
|
|
671
|
+
reject(new Error(`File read aborted for ${file.name}`));
|
|
672
|
+
};
|
|
673
|
+
reader.readAsDataURL(file);
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
try {
|
|
677
|
+
const convertedFiles = await Promise.all(filePromises);
|
|
678
|
+
if (convertedFiles.length > 0) {
|
|
679
|
+
state.files = convertedFiles;
|
|
680
|
+
}
|
|
681
|
+
} catch (error) {
|
|
682
|
+
console.error("Failed to convert files to base64:", error);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
607
685
|
onSubmit(state);
|
|
686
|
+
setAttachedFiles([]);
|
|
608
687
|
};
|
|
609
688
|
const handleKeyDown = (e) => {
|
|
610
689
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
611
690
|
e.preventDefault();
|
|
612
|
-
handleInternalSubmit();
|
|
691
|
+
handleInternalSubmit().catch(console.error);
|
|
613
692
|
}
|
|
614
693
|
};
|
|
615
|
-
return /* @__PURE__ */
|
|
616
|
-
/* @__PURE__ */ jsx(
|
|
617
|
-
|
|
694
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex flex-col w-full", className), children: [
|
|
695
|
+
enabled && attachedFiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-2 flex flex-wrap gap-2", children: attachedFiles.map((file, index) => /* @__PURE__ */ jsxs(
|
|
696
|
+
"div",
|
|
618
697
|
{
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
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",
|
|
624
|
-
autoFocus
|
|
625
|
-
}
|
|
626
|
-
),
|
|
627
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
|
|
628
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: options.map((group) => {
|
|
629
|
-
const selectedInGroup = group.options.filter(
|
|
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: [
|
|
698
|
+
className: "flex items-center gap-2 px-3 py-1.5 bg-muted rounded-lg text-sm",
|
|
699
|
+
children: [
|
|
700
|
+
/* @__PURE__ */ jsx("span", { className: "truncate max-w-[200px]", title: file.name, children: file.name }),
|
|
701
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: formatFileSize(file.size) }),
|
|
635
702
|
/* @__PURE__ */ jsx(
|
|
636
|
-
|
|
703
|
+
"button",
|
|
637
704
|
{
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
className: cn(
|
|
644
|
-
selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
|
|
645
|
-
),
|
|
646
|
-
children: [
|
|
647
|
-
label,
|
|
648
|
-
/* @__PURE__ */ jsx(IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
649
|
-
]
|
|
650
|
-
}
|
|
651
|
-
)
|
|
705
|
+
type: "button",
|
|
706
|
+
onClick: () => handleRemoveFile(index),
|
|
707
|
+
className: "ml-1 hover:bg-muted-foreground/20 rounded p-0.5 transition-colors",
|
|
708
|
+
"aria-label": "Remove file",
|
|
709
|
+
children: /* @__PURE__ */ jsx(IconX, { className: "h-3.5 w-3.5" })
|
|
652
710
|
}
|
|
653
|
-
)
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
{
|
|
660
|
-
checked: selectedOptions.has(option.id),
|
|
661
|
-
onCheckedChange: () => toggleOption(
|
|
662
|
-
option.id,
|
|
663
|
-
group.options,
|
|
664
|
-
isSingle ? "single" : "multiple"
|
|
665
|
-
),
|
|
666
|
-
onSelect: (e) => e.preventDefault(),
|
|
667
|
-
children: option.label
|
|
668
|
-
},
|
|
669
|
-
option.id
|
|
670
|
-
))
|
|
671
|
-
] }) })
|
|
672
|
-
] }, group.id);
|
|
673
|
-
}) }),
|
|
711
|
+
)
|
|
712
|
+
]
|
|
713
|
+
},
|
|
714
|
+
index
|
|
715
|
+
)) }),
|
|
716
|
+
/* @__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: [
|
|
674
717
|
/* @__PURE__ */ jsx(
|
|
675
|
-
|
|
718
|
+
Textarea,
|
|
676
719
|
{
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
720
|
+
value,
|
|
721
|
+
onChange: (e) => onChange(e.target.value),
|
|
722
|
+
onKeyDown: handleKeyDown,
|
|
723
|
+
placeholder,
|
|
724
|
+
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",
|
|
725
|
+
autoFocus
|
|
682
726
|
}
|
|
683
|
-
)
|
|
727
|
+
),
|
|
728
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
|
|
729
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
730
|
+
enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
731
|
+
/* @__PURE__ */ jsx(
|
|
732
|
+
"input",
|
|
733
|
+
{
|
|
734
|
+
ref: fileInputRef,
|
|
735
|
+
type: "file",
|
|
736
|
+
multiple: true,
|
|
737
|
+
accept,
|
|
738
|
+
onChange: handleFileSelect,
|
|
739
|
+
className: "hidden",
|
|
740
|
+
disabled: isLoading || attachedFiles.length >= maxFiles
|
|
741
|
+
}
|
|
742
|
+
),
|
|
743
|
+
/* @__PURE__ */ jsx(
|
|
744
|
+
Button,
|
|
745
|
+
{
|
|
746
|
+
type: "button",
|
|
747
|
+
variant: "ghost",
|
|
748
|
+
size: "sm",
|
|
749
|
+
onClick: () => fileInputRef.current?.click(),
|
|
750
|
+
disabled: isLoading || attachedFiles.length >= maxFiles,
|
|
751
|
+
className: "text-muted-foreground",
|
|
752
|
+
title: attachedFiles.length >= maxFiles ? `Maximum ${maxFiles} files allowed` : "Attach file",
|
|
753
|
+
children: /* @__PURE__ */ jsx(IconPaperclip, { className: "h-4 w-4" })
|
|
754
|
+
}
|
|
755
|
+
)
|
|
756
|
+
] }),
|
|
757
|
+
options.map((group) => {
|
|
758
|
+
const selectedInGroup = group.options.filter(
|
|
759
|
+
(o) => selectedOptions.has(o.id)
|
|
760
|
+
);
|
|
761
|
+
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : `${group.label} (${selectedInGroup.length})`;
|
|
762
|
+
const isSingle = group.type === "single";
|
|
763
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
764
|
+
/* @__PURE__ */ jsx(
|
|
765
|
+
DropdownMenuTrigger,
|
|
766
|
+
{
|
|
767
|
+
render: /* @__PURE__ */ jsxs(
|
|
768
|
+
Button,
|
|
769
|
+
{
|
|
770
|
+
variant: "ghost",
|
|
771
|
+
size: "sm",
|
|
772
|
+
className: cn(
|
|
773
|
+
selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
|
|
774
|
+
),
|
|
775
|
+
children: [
|
|
776
|
+
label,
|
|
777
|
+
/* @__PURE__ */ jsx(IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
)
|
|
781
|
+
}
|
|
782
|
+
),
|
|
783
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "w-56", children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
784
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: group.label }),
|
|
785
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
786
|
+
group.options.map((option) => /* @__PURE__ */ jsx(
|
|
787
|
+
DropdownMenuCheckboxItem,
|
|
788
|
+
{
|
|
789
|
+
checked: selectedOptions.has(option.id),
|
|
790
|
+
onCheckedChange: () => toggleOption(
|
|
791
|
+
option.id,
|
|
792
|
+
group.options,
|
|
793
|
+
isSingle ? "single" : "multiple"
|
|
794
|
+
),
|
|
795
|
+
onSelect: (e) => e.preventDefault(),
|
|
796
|
+
children: option.label
|
|
797
|
+
},
|
|
798
|
+
option.id
|
|
799
|
+
))
|
|
800
|
+
] }) })
|
|
801
|
+
] }, group.id);
|
|
802
|
+
})
|
|
803
|
+
] }),
|
|
804
|
+
/* @__PURE__ */ jsx(
|
|
805
|
+
Button,
|
|
806
|
+
{
|
|
807
|
+
type: "submit",
|
|
808
|
+
disabled: !value.trim() && attachedFiles.length === 0 && !isLoading || isLoading,
|
|
809
|
+
size: "icon-lg",
|
|
810
|
+
onClick: () => handleInternalSubmit().catch(console.error),
|
|
811
|
+
children: isLoading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsx(IconArrowUp, { className: "h-5 w-5" })
|
|
812
|
+
}
|
|
813
|
+
)
|
|
814
|
+
] })
|
|
684
815
|
] })
|
|
685
|
-
] })
|
|
816
|
+
] });
|
|
686
817
|
}
|
|
687
818
|
function Card({
|
|
688
819
|
className,
|
|
@@ -2356,13 +2487,14 @@ function Thread({
|
|
|
2356
2487
|
}, [messages]);
|
|
2357
2488
|
const handleSubmit = async (state, overrideInput) => {
|
|
2358
2489
|
const text = (overrideInput ?? input).trim();
|
|
2359
|
-
|
|
2490
|
+
const hasFiles = state?.files && Array.isArray(state.files) && state.files.length > 0;
|
|
2491
|
+
if (!text && !hasFiles || isLoading) return;
|
|
2360
2492
|
if (!overrideInput) setInput("");
|
|
2361
2493
|
await sendEvent(
|
|
2362
2494
|
{
|
|
2363
2495
|
type: "text",
|
|
2364
2496
|
role: "user",
|
|
2365
|
-
data: { content: text }
|
|
2497
|
+
data: { content: text || "" }
|
|
2366
2498
|
},
|
|
2367
2499
|
{ state: { ...state, threadId: activeThreadId ?? void 0 } }
|
|
2368
2500
|
);
|
|
@@ -2420,7 +2552,8 @@ function Thread({
|
|
|
2420
2552
|
isLoading,
|
|
2421
2553
|
options,
|
|
2422
2554
|
autoFocus,
|
|
2423
|
-
defaultSelectedIds: allDefaultSelectedIds
|
|
2555
|
+
defaultSelectedIds: allDefaultSelectedIds,
|
|
2556
|
+
fileAttachments: config?.fileAttachments
|
|
2424
2557
|
}
|
|
2425
2558
|
) }) })
|
|
2426
2559
|
]
|