Skip to content

Commit

Permalink
Fix event type in useCSVReader (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bunlong committed Jan 27, 2022
1 parent d749484 commit 2cabe6e
Showing 1 changed file with 88 additions and 76 deletions.
164 changes: 88 additions & 76 deletions src/useCSVReader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, {
useEffect,
ReactNode,
useRef,
CSSProperties,
} from 'react';
import PapaParse, { ParseResult } from 'papaparse';
import { CustomConfig } from './model';
Expand Down Expand Up @@ -54,7 +55,7 @@ export interface Props<T> {
}

export interface ProgressBarComponentProp {
style?: any;
style?: CSSProperties;
className?: string;
}

Expand All @@ -80,8 +81,8 @@ function useCSVReaderComponent<T = any>() {
onDragOver,
onDragLeave,
}: Props<T>) => {
const inputRef: any = useRef<ReactNode>(null);
const rootRef: any = useRef<ReactNode>(null);
const inputRef = useRef<HTMLInputElement>(null);
const rootRef = useRef<HTMLDivElement>(null);
const dragTargetsRef = useRef([]);

const [state, dispatch] = useReducer(reducer, initialState);
Expand All @@ -93,12 +94,15 @@ function useCSVReaderComponent<T = any>() {
isFileDialogActive,
} = state;

const onDocumentDrop = (event: DragEvent) => {
if (rootRef.current && rootRef.current.contains(event.target)) {
const onDocumentDrop = (e: DragEvent) => {
// FIX: Type 'EventTarget' is not assignable to type 'Node'
// SOLUTION: event.target as Node
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239
if (rootRef.current && rootRef.current.contains(e.target as Node)) {
// If we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
return;
}
event.preventDefault();
e.preventDefault();
dragTargetsRef.current = [];
};

Expand All @@ -125,17 +129,19 @@ function useCSVReaderComponent<T = any>() {
return noDrag ? null : composeHandler(fn);
};

const stopPropagation = (event: Event) => {
const stopPropagation = (e: Event) => {
if (noDragEventsBubbling) {
event.stopPropagation();
e.stopPropagation();
}
};

const allowDrop = (event: any) => {
event.preventDefault(event);
const allowDrop = (e: DragEvent) => {
e.preventDefault();
// Persist here because we need the event later after getFilesFromEvent() is done
event.persist();
stopPropagation(event);
// Only for React 16
// React 17 no event pooling
(e as any).persist();
stopPropagation(e);
};

const setDisplayProgressBar = (display: string) => {
Expand Down Expand Up @@ -180,7 +186,7 @@ function useCSVReaderComponent<T = any>() {
const openFileDialog = useCallback(() => {
if (inputRef.current && state.displayProgressBar) {
dispatch({ type: 'openDialog' });
inputRef.current.value = null;
inputRef.current.value = '';
inputRef.current.click();
}
}, [dispatch]);
Expand All @@ -192,10 +198,7 @@ function useCSVReaderComponent<T = any>() {
setTimeout(() => {
if (inputRef.current) {
const { files } = inputRef.current;

if (!files.length) {
dispatch({ type: 'closeDialog' });
}
files && !files.length && dispatch({ type: 'closeDialog' });
}
}, 300);
}
Expand Down Expand Up @@ -224,44 +227,48 @@ function useCSVReaderComponent<T = any>() {
}, [inputRef, noClick]);

const onDropCb = useCallback(
(event: any) => {
allowDrop(event);
(e: DragEvent) => {
allowDrop(e);

setProgressBarPercentage(0);

dragTargetsRef.current = [];

if (isEventWithFiles(event)) {
if (isPropagationStopped(event) && !noDragEventsBubbling) {
if (isEventWithFiles(e)) {
if (isPropagationStopped(e) && !noDragEventsBubbling) {
return;
}

const acceptedFiles = [] as any;
const fileRejections = [] as any;
const acceptedFiles: any = [];
const fileRejections: any = [];
// FIX: event.target type (EventTarget) has no files
// https://github.com/microsoft/TypeScript/issues/31816
const target = e.target as HTMLInputElement;
const files =
event.target.files ||
(event.dataTransfer && event.dataTransfer.files);
Array.from(files).forEach((file) => {
const [accepted, acceptError] = fileAccepted(file, accept);
const [sizeMatch, sizeError] = fileMatchSize(
file,
minSize,
maxSize,
);
const customErrors = validator ? validator(file as File) : null;

if (accepted && sizeMatch && !customErrors) {
acceptedFiles.push(file);
} else {
let errors = [acceptError, sizeError];

if (customErrors) {
errors = errors.concat(customErrors);
target.files || (e.dataTransfer && e.dataTransfer.files);
if (files) {
Array.from(files).forEach((file) => {
const [accepted, acceptError] = fileAccepted(file, accept);
const [sizeMatch, sizeError] = fileMatchSize(
file,
minSize,
maxSize,
);
const customErrors = validator ? validator(file as File) : null;

if (accepted && sizeMatch && !customErrors) {
acceptedFiles.push(file);
} else {
let errors = [acceptError, sizeError];

if (customErrors) {
errors = errors.concat(customErrors);
}

fileRejections.push({ file, errors: errors.filter((e) => e) });
}

fileRejections.push({ file, errors: errors.filter((e) => e) });
}
});
});
}

if (
(!multiple && acceptedFiles.length > 1) ||
Expand All @@ -287,11 +294,11 @@ function useCSVReaderComponent<T = any>() {
// }

if (fileRejections.length > 0 && onUploadRejected) {
onUploadRejected(fileRejections, event);
onUploadRejected(fileRejections, e);
}

if (acceptedFiles.length > 0 && onUploadAccepted) {
let configs = {} as any;
let configs: any = {};
const data: any = [];
const errors: any = [];
const meta: any = [];
Expand Down Expand Up @@ -371,8 +378,8 @@ function useCSVReaderComponent<T = any>() {
],
);

const onInputElementClick = useCallback((event) => {
stopPropagation(event);
const onInputElementClick = useCallback((e: Event) => {
stopPropagation(e);
}, []);
// ============

Expand All @@ -382,16 +389,16 @@ function useCSVReaderComponent<T = any>() {
};

const onDragEnterCb = useCallback(
(event: DragEvent) => {
allowDrop(event);
(e: DragEvent) => {
allowDrop(e);

dragTargetsRef.current = [
...dragTargetsRef.current,
event.target,
e.target,
] as never[];

if (isEventWithFiles(event)) {
if (isPropagationStopped(event) && !noDragEventsBubbling) {
if (isEventWithFiles(e)) {
if (isPropagationStopped(e) && !noDragEventsBubbling) {
return;
}

Expand All @@ -402,26 +409,26 @@ function useCSVReaderComponent<T = any>() {
});

if (onDragEnter) {
onDragEnter(event);
onDragEnter(e);
}
}
},
[onDragEnter, noDragEventsBubbling],
);

const onDragOverCb = useCallback(
(event: DragEvent) => {
allowDrop(event);
(e: DragEvent) => {
allowDrop(e);

const hasFiles = isEventWithFiles(event);
if (hasFiles && event.dataTransfer) {
const hasFiles = isEventWithFiles(e);
if (hasFiles && e.dataTransfer) {
try {
event.dataTransfer.dropEffect = 'copy';
e.dataTransfer.dropEffect = 'copy';
} catch {}
}

if (hasFiles && onDragOver) {
onDragOver(event);
onDragOver(e);
}

return false;
Expand All @@ -430,16 +437,16 @@ function useCSVReaderComponent<T = any>() {
);

const onDragLeaveCb = useCallback(
(event: DragEvent) => {
allowDrop(event);
(e: DragEvent) => {
allowDrop(e);

// Only deactivate once the dropzone and all children have been left
const targets = dragTargetsRef.current.filter(
(target) => rootRef.current && rootRef.current.contains(target),
);
// Make sure to remove a target present multiple times only once
// (Firefox may fire dragenter/dragleave multiple times on the same element)
const targetIdx = targets.indexOf(event.target as never);
const targetIdx = targets.indexOf(e.target as never);
if (targetIdx !== -1) {
targets.splice(targetIdx, 1);
}
Expand All @@ -454,23 +461,26 @@ function useCSVReaderComponent<T = any>() {
draggedFiles: [],
});

if (isEventWithFiles(event) && onDragLeave) {
onDragLeave(event);
if (isEventWithFiles(e) && onDragLeave) {
onDragLeave(e);
}
},
[rootRef, onDragLeave, noDragEventsBubbling],
);

// Cb to open the file dialog when SPACE/ENTER occurs on the dropzone
const onKeyDownCb = useCallback(
(event: KeyboardEvent) => {
(e: KeyboardEvent) => {
// Ignore keyboard events bubbling up the DOM tree
if (!rootRef.current || !rootRef.current.isEqualNode(event.target)) {
if (
!rootRef.current ||
!rootRef.current.isEqualNode(e.target as Node)
) {
return;
}

if (event.key === 'Space' || event.key === 'Enter') {
event.preventDefault();
if (e.key === 'Space' || e.key === 'Enter') {
e.preventDefault();
openFileDialog();
}
},
Expand Down Expand Up @@ -572,11 +582,13 @@ function useCSVReaderComponent<T = any>() {
);
// ===========

const removeFileProgrammaticallyCb = useCallback((event: Event) => {
inputRef.current.value = '';
dispatch({ type: 'reset' });
// To prevent a parents onclick event from firing when a child is clicked
event.stopPropagation();
const removeFileProgrammaticallyCb = useCallback((e: Event) => {
if (inputRef.current) {
inputRef.current.value = '';
dispatch({ type: 'reset' });
// To prevent a parents onclick event from firing when a child is clicked
e.stopPropagation();
}
}, []);

const getRemoveFileProps = useMemo(
Expand All @@ -598,7 +610,7 @@ function useCSVReaderComponent<T = any>() {
);
};

const CSVReader = useMemo(() => CSVReaderComponent, []) as any;
const CSVReader = useMemo(() => CSVReaderComponent, []);

return CSVReader;
}
Expand Down

0 comments on commit 2cabe6e

Please sign in to comment.