Skip to content

Commit 669d535

Browse files
committed
feat: allow-custom-validation-and-controlled-behaviour-in-file-uploader
1 parent ab6d59b commit 669d535

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

src/lib/form/file-uploader.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ interface FileUploaderProps {
2525
/** Whether the drop target is disabled. If true, the drop target will not accept any drops. */
2626
isDisabled?: boolean;
2727
className?: string;
28+
/** Provide a custom validation function, returning false invalidates the file */
29+
validationFunction?: (file?: File) => boolean;
30+
/** Provide File for controlled behaviour */
31+
selectedFile?: File;
2832
}
2933

3034
/** Allows to upload a file by either dropping it on the dropzone or
@@ -37,8 +41,12 @@ function FileUploader({
3741
acceptedFileTypes,
3842
fileTriggerProps,
3943
isDisabled = false,
44+
validationFunction,
45+
selectedFile,
4046
}: Readonly<FileUploaderProps>) {
41-
const [fileSelected, setFileSelected] = useState<File>();
47+
const [fileSelected, setFileSelected] = useState<File | undefined>(
48+
selectedFile,
49+
);
4250

4351
return (
4452
<div className={cn("box-border h-fit w-50", className)}>
@@ -71,6 +79,8 @@ function FileUploader({
7179

7280
if (item) {
7381
const file = await item.getFile();
82+
const validated = validationFunction?.(file) ?? true;
83+
if (!validated) return;
7484
setFileSelected(file);
7585
callback(file);
7686
}
@@ -82,6 +92,8 @@ function FileUploader({
8292
onSelect={(e) => {
8393
if (e) {
8494
const file = e[0];
95+
const validated = validationFunction?.(file) ?? true;
96+
if (!validated) return;
8597
setFileSelected(file);
8698
callback(file);
8799
}
@@ -109,7 +121,7 @@ function FileUploader({
109121
</FileTrigger>
110122
</DropZone>
111123
{msg && (
112-
<div className="mt-4 flex items-start">
124+
<div className="mt-4 flex items-center">
113125
{variant === "success" && (
114126
<SuccessIcon className="fill-klerosUIComponentsSuccess mr-2 max-w-4 min-w-4" />
115127
)}

src/stories/fileuploader.stories.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,35 @@ export const FileUploaderWithAcceptedTypes: Story = {
6464
variant: "info",
6565
},
6666
};
67+
68+
export const FileUploaderWithCustomValidation: Story = {
69+
args: {
70+
themeUI: "dark",
71+
backgroundUI: "light",
72+
className: "w-[500px]",
73+
callback: () => {},
74+
acceptedFileTypes: ["image/png"],
75+
msg: "This will not accept any file and invalidate",
76+
variant: "info",
77+
validationFunction: () => {
78+
return false;
79+
},
80+
},
81+
};
82+
83+
export const FileUploaderWithControlledBehaviour: Story = {
84+
args: {
85+
themeUI: "dark",
86+
backgroundUI: "light",
87+
className: "w-[500px]",
88+
callback: () => {},
89+
acceptedFileTypes: ["image/png"],
90+
msg: "This will show test.txt selected by default",
91+
variant: "info",
92+
selectedFile: new File(
93+
["hello world"], // file contents
94+
"test.txt", // file name
95+
{ type: "text/plain" }, // MIME type
96+
),
97+
},
98+
};

0 commit comments

Comments
 (0)