Skip to content

Commit

Permalink
fix: dropzone behavior (#980)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusmarminge authored Oct 7, 2024
1 parent d4d453d commit e53bc01
Show file tree
Hide file tree
Showing 23 changed files with 729 additions and 683 deletions.
8 changes: 8 additions & 0 deletions .changeset/honest-scissors-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@uploadthing/svelte": patch
"@uploadthing/react": patch
"@uploadthing/solid": patch
"@uploadthing/vue": patch
---

fix: file picker would open twice when clicking the input element on the dropzone
6 changes: 6 additions & 0 deletions examples/backend-adapters/client-vue/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ function alert(message: string) {
console.log('uploaded', file);
alert('Upload complete');
},
onUploadAborted: () => {
alert('Upload Aborted');
},
onUploadError: (error) => {
console.error(error, error.cause);
alert('Upload failed');
Expand All @@ -38,6 +41,9 @@ function alert(message: string) {
console.log('uploaded', file);
alert('Upload complete');
},
onUploadAborted: () => {
alert('Upload Aborted');
},
onUploadError: (error) => {
console.error(error, error.cause);
alert('Upload failed');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { withUt } from "uploadthing/tw";

/** @type {import('tailwindcss').Config} */
export default withUt({
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
Expand Down
4 changes: 1 addition & 3 deletions examples/minimal-solidstart/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"module": "Preserve",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"allowJs": true,
Expand Down
3 changes: 3 additions & 0 deletions examples/minimal-sveltekit/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import "@uploadthing/svelte/styles.css";
const uploader = createUploader("videoAndImage", {
onUploadAborted: () => {
alert("Upload Aborted");
},
onClientUploadComplete: (res) => {
console.log(`onClientUploadComplete`, res);
alert("Upload Completed");
Expand Down
76 changes: 38 additions & 38 deletions packages/react/src/components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ export function UploadButton<
// since the ErrorMessage messes it up otherwise
const $props = props as unknown as UploadButtonProps<TRouter, TEndpoint> &
UploadThingInternalProps;
const fileRouteInput = "input" in $props ? $props.input : undefined;

const {
mode = "auto",
Expand All @@ -103,7 +102,6 @@ export function UploadButton<
const acRef = useRef(new AbortController());

const fileInputRef = useRef<HTMLInputElement>(null);
const labelRef = useRef<HTMLLabelElement>(null);
const [uploadProgress, setUploadProgress] = useState(
$props.__internal_upload_progress ?? 0,
);
Expand Down Expand Up @@ -132,21 +130,49 @@ export function UploadButton<
onBeforeUploadBegin: $props.onBeforeUploadBegin,
},
);
const { fileTypes, multiple } = generatePermittedFileTypes(routeConfig);

const disabled = !!($props.__internal_button_disabled ?? $props.disabled);
const state = (() => {
const ready = $props.__internal_state === "ready" || fileTypes.length > 0;

if ($props.__internal_state) return $props.__internal_state;
if (disabled) return "disabled";
if (!ready) return "readying";
if (ready && !isUploading) return "ready";
return "uploading";
})();

const uploadFiles = useCallback(
(files: File[]) => {
startUpload(files, fileRouteInput).catch((e) => {
const input = "input" in $props ? $props.input : undefined;
startUpload(files, input).catch((e) => {
if (e instanceof UploadAbortedError) {
void $props.onUploadAborted?.();
} else {
throw e;
}
});
},
[$props, startUpload, fileRouteInput],
[$props, startUpload],
);

const { fileTypes, multiple } = generatePermittedFileTypes(routeConfig);
const onUploadClick = (e: React.MouseEvent) => {
if (state === "uploading") {
e.preventDefault();
e.stopPropagation();

acRef.current.abort();
acRef.current = new AbortController();
return;
}
if (mode === "manual" && files.length > 0) {
e.preventDefault();
e.stopPropagation();

uploadFiles(files);
}
};

const inputProps = useMemo(
() => ({
Expand All @@ -165,24 +191,14 @@ export function UploadButton<
return;
}

void uploadFiles(selectedFiles);
uploadFiles(selectedFiles);
},
disabled: fileTypes.length === 0,
tabIndex: fileTypes.length === 0 ? -1 : 0,
disabled,
tabIndex: disabled ? -1 : 0,
}),
[$props, fileTypes, mode, multiple, uploadFiles],
[$props, disabled, fileTypes, mode, multiple, uploadFiles],
);

if ($props.__internal_button_disabled) inputProps.disabled = true;
if ($props.disabled) inputProps.disabled = true;

const state = (() => {
if ($props.__internal_state) return $props.__internal_state;
if (inputProps.disabled) return "disabled";
if (!inputProps.disabled && !isUploading) return "ready";
return "uploading";
})();

usePaste((event) => {
if (!appendOnPaste) return;
if (document.activeElement !== fileInputRef.current) return;
Expand All @@ -199,7 +215,7 @@ export function UploadButton<
return filesToUpload;
});

if (mode === "auto") void uploadFiles(files);
if (mode === "auto") uploadFiles(files);
});

const styleFieldArg = {
Expand All @@ -221,7 +237,7 @@ export function UploadButton<
return "Loading...";
}
case "uploading": {
if (uploadProgress === 100) return <Spinner />;
if (uploadProgress >= 100) return <Spinner />;
return (
<span className="z-50">
<span className="block group-hover:hidden">{uploadProgress}%</span>
Expand Down Expand Up @@ -305,23 +321,7 @@ export function UploadButton<
style={styleFieldToCssObject($props.appearance?.button, styleFieldArg)}
data-state={state}
data-ut-element="button"
ref={labelRef}
onClick={(e) => {
if (state === "uploading") {
e.preventDefault();
e.stopPropagation();

acRef.current.abort();
acRef.current = new AbortController();
return;
}
if (mode === "manual" && files.length > 0) {
e.preventDefault();
e.stopPropagation();

uploadFiles(files);
}
}}
onClick={onUploadClick}
>
<input {...inputProps} className="sr-only" />
{renderButton()}
Expand Down
Loading

0 comments on commit e53bc01

Please sign in to comment.