From 3a2b3d530a0d065ceace32cf482afa976b0ba5c8 Mon Sep 17 00:00:00 2001 From: yosipy Date: Mon, 2 Sep 2024 05:09:07 +0900 Subject: [PATCH] feat: add noClick & noDrag --- lib/ReactDropzoneVV.test.tsx | 70 +++++++++++++++++++++++++++++++++++- lib/ReactDropzoneVV.tsx | 34 ++++++++++++++---- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/lib/ReactDropzoneVV.test.tsx b/lib/ReactDropzoneVV.test.tsx index 32bfc2d..6a241ce 100644 --- a/lib/ReactDropzoneVV.test.tsx +++ b/lib/ReactDropzoneVV.test.tsx @@ -14,6 +14,8 @@ type Props = { accept?: string disabled?: boolean multiple?: boolean + noClick?: boolean + noDrag?: boolean } const TestComponent: FC = (props) => { @@ -31,6 +33,8 @@ const TestComponent: FC = (props) => { accept={props.accept} disabled={props.disabled} multiple={props.multiple} + noClick={props.noClick} + noDrag={props.noDrag} onSelect={handleSelect} > dropzone @@ -39,7 +43,12 @@ const TestComponent: FC = (props) => { } describe("ReactDropzoneVV", () => { - afterEach(cleanup) + afterEach(() => { + cleanup() + + acceptedFiles = [] + fileRejections = [] + }) describe("accept", () => { test("sets 'accept' props in ", async () => { @@ -97,4 +106,63 @@ describe("ReactDropzoneVV", () => { expect(container.querySelector("input")).toHaveProperty("multiple", false) }) }) + + describe("noClick", () => { + const example = (noClick: boolean) => { + const { container } = render() + const inputElem = container.querySelector("input") + + if (!inputElem) throw new Error("inputElem is null") + fireEvent.change(inputElem, { + target: { files: [file] }, + }) + } + + describe("noClick is true", () => { + test("acceptedFiles and fileRejections is empty array", async () => { + example(true) + + expect(acceptedFiles.length).toBe(0) + expect(fileRejections.length).toBe(0) + }) + }) + + describe("noClick is false", () => { + test("acceptedFiles or fileRejections is non-empty array", async () => { + example(false) + + expect(acceptedFiles.length).toBe(1) + expect(fileRejections.length).toBe(0) + }) + }) + }) + + describe("noDrag", () => { + const example = (noDrag: boolean) => { + const { getByText } = render() + const dropzone = getByText(/dropzone/i) + + fireEvent.drop(dropzone, { + dataTransfer: { files: [file] }, + }) + } + + describe("noDrag is true", () => { + test("acceptedFiles and fileRejections is empty array", async () => { + example(true) + + expect(acceptedFiles.length).toBe(0) + expect(fileRejections.length).toBe(0) + }) + }) + + describe("noDrag is false", () => { + test("acceptedFiles or fileRejections is non-empty array", async () => { + example(false) + + expect(acceptedFiles.length).toBe(1) + expect(fileRejections.length).toBe(0) + }) + }) + }) }) diff --git a/lib/ReactDropzoneVV.tsx b/lib/ReactDropzoneVV.tsx index afe14c4..74b0f5c 100644 --- a/lib/ReactDropzoneVV.tsx +++ b/lib/ReactDropzoneVV.tsx @@ -24,18 +24,22 @@ export type ReactDropzoneVVProps = Omit< accept?: string disabled?: boolean multiple?: boolean + noClick?: boolean + noDrag?: boolean onDrop?: (files: File[]) => void onSelect?: (props: OnSelectProps) => void onError?: (error: Error) => void } export const ReactDropzoneVV: FC = ({ + children, + reactDropzoneVV: { setIsDragging, isDragging, inputRef, openSelector }, + inputProps, accept = "", disabled = false, multiple = true, - reactDropzoneVV: { setIsDragging, isDragging, inputRef, openSelector }, - children, - inputProps, + noClick = false, + noDrag = false, onDrop, onSelect, onError, @@ -45,31 +49,40 @@ export const ReactDropzoneVV: FC = ({ (event: React.DragEvent) => { event.preventDefault() event.stopPropagation() + + if (noDrag) return + setIsDragging(true) }, - [setIsDragging] + [noDrag, setIsDragging] ) const handleDragLeaveDiv = useCallback( (event: React.DragEvent) => { event.preventDefault() event.stopPropagation() + + if (noDrag) return + if (!event.currentTarget.contains(event.relatedTarget as Node)) { setIsDragging(false) } }, - [setIsDragging] + [noDrag, setIsDragging] ) const handleDragOverDiv = useCallback( (event: React.DragEvent) => { event.preventDefault() event.stopPropagation() + + if (noDrag) return + if (!isDragging) { setIsDragging(true) } }, - [isDragging, setIsDragging] + [noDrag, isDragging, setIsDragging] ) const handleDropDiv = useCallback( @@ -77,6 +90,9 @@ export const ReactDropzoneVV: FC = ({ try { event.preventDefault() event.stopPropagation() + + if (noDrag) return + setIsDragging(false) const files = Array.from(event.dataTransfer.files) @@ -102,15 +118,19 @@ export const ReactDropzoneVV: FC = ({ } } }, - [accept, multiple, setIsDragging, onDrop, onSelect, onError] + [accept, multiple, noDrag, setIsDragging, onDrop, onSelect, onError] ) const handleClickDiv = () => { + if (noClick) return + openSelector() } const handleChangeInput = useCallback( (event: React.ChangeEvent) => { + if (noClick) return + try { const files = Array.from(event.target.files || []) if (files.length > 0) {