Skip to content

Commit

Permalink
Copy ReactDropdown files
Browse files Browse the repository at this point in the history
  • Loading branch information
yosipy committed Jul 27, 2024
1 parent 3523b5c commit 2f9f339
Show file tree
Hide file tree
Showing 9 changed files with 542 additions and 18 deletions.
9 changes: 0 additions & 9 deletions lib/Example.tsx

This file was deleted.

144 changes: 144 additions & 0 deletions lib/ReactDropzoneVV.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import type { FC, HTMLProps, ReactNode } from "react"
import { useCallback, useEffect } from "react"
import type { UseReactDropzoneVV } from "./useReactDropzoneVV"
import { classifyByAcceptability, ensureError } from "./utils"

export type ReactDropzoneVVProps = HTMLProps<HTMLDivElement> & {
reactDropzoneVV: UseReactDropzoneVV
inputProps?: HTMLProps<HTMLInputElement>
children: ReactNode
}

export const ReactDropzoneVV: FC<ReactDropzoneVVProps> = ({
reactDropzoneVV,
inputProps,
children,
...props
}) => {
const onDragEnterDiv = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
event.stopPropagation()
reactDropzoneVV.setIsDragging(true)
},
[reactDropzoneVV.setIsDragging]
)

const onDragLeaveDiv = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
event.stopPropagation()
if (!event.currentTarget.contains(event.relatedTarget as Node)) {
reactDropzoneVV.setIsDragging(false)
}
},
[reactDropzoneVV.setIsDragging]
)

const onDragOverDiv = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
event.stopPropagation()
if (!reactDropzoneVV.isDragging) reactDropzoneVV.setIsDragging(true)
},
[reactDropzoneVV.isDragging, reactDropzoneVV.setIsDragging]
)

const dependenciesForDivideByAcceptability = [
reactDropzoneVV.accept,
reactDropzoneVV.multiple,
]

const onDropDiv = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
try {
event.preventDefault()
event.stopPropagation()
reactDropzoneVV.setIsDragging(false)

const files = Array.from(event.dataTransfer.files)

if (reactDropzoneVV.onDrop) reactDropzoneVV.onDrop(files)
const classifiedFiles = classifyByAcceptability(files, {
accept: reactDropzoneVV.accept,
multiple: reactDropzoneVV.multiple,
})
if (reactDropzoneVV.onSelect) reactDropzoneVV.onSelect(classifiedFiles)
} catch (error) {
if (reactDropzoneVV.onError) reactDropzoneVV.onError(ensureError(error))
}
},
[
...dependenciesForDivideByAcceptability,
reactDropzoneVV.setIsDragging,
reactDropzoneVV.onDrop,
reactDropzoneVV.onSelect,
]
)

const onClickDiv = () => {
reactDropzoneVV.open()
}

const onChangeInput = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
try {
const files = Array.from(event.target.files || [])
if (files.length > 0) {
const classifiedFiles = classifyByAcceptability(files, {
accept: reactDropzoneVV.accept,
multiple: reactDropzoneVV.multiple,
})
if (reactDropzoneVV.onSelect)
reactDropzoneVV.onSelect(classifiedFiles)
}
event.target.value = ""
} catch (error) {
if (reactDropzoneVV.onError) reactDropzoneVV.onError(ensureError(error))
}
},
[...dependenciesForDivideByAcceptability, reactDropzoneVV.onSelect]
)

useEffect(() => {
const handleDocumentDrop = (event: DragEvent) => {
event.preventDefault()
event.stopPropagation()
}

if (reactDropzoneVV.disabledDropOnDocment) {
document.addEventListener("dragover", handleDocumentDrop)
document.addEventListener("drop", handleDocumentDrop)
}

return () => {
if (reactDropzoneVV.disabledDropOnDocment) {
document.removeEventListener("dragover", handleDocumentDrop)
document.removeEventListener("drop", handleDocumentDrop)
}
}
}, [reactDropzoneVV.disabledDropOnDocment])

return (
<div
{...props}
onDragEnter={reactDropzoneVV.disabled ? undefined : onDragEnterDiv}
onDragLeave={reactDropzoneVV.disabled ? undefined : onDragLeaveDiv}
onDragOver={reactDropzoneVV.disabled ? undefined : onDragOverDiv}
onDrop={reactDropzoneVV.disabled ? undefined : onDropDiv}
onClick={reactDropzoneVV.disabled ? undefined : onClickDiv}
>
<input
accept={reactDropzoneVV.accept}
disabled={reactDropzoneVV.disabled}
multiple={reactDropzoneVV.multiple}
ref={reactDropzoneVV.inputRef}
style={{ display: "none" }}
type="file"
{...inputProps}
onChange={onChangeInput}
/>
{children}
</div>
)
}
6 changes: 0 additions & 6 deletions lib/example.test.ts

This file was deleted.

1 change: 0 additions & 1 deletion lib/example.ts

This file was deleted.

6 changes: 4 additions & 2 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from "./Example"
export * from "./example"
export * from "./ReactDropzoneVV"
export * from "./useReactDropzoneVV"
export * from "./utils"
export * from "./types"
13 changes: 13 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type RejectedCode = "more-than-one-file" | "accept-violations"

export type ClassifiedFile<CustonRejectedCode extends string = RejectedCode> =
| {
status: "accepted"
file: File
errorCode: undefined
}
| {
status: "rejected"
file: File
errorCode: RejectedCode | CustonRejectedCode
}
73 changes: 73 additions & 0 deletions lib/useReactDropzoneVV.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useRef, useState } from "react"
import type { ClassifiedFile } from "./types"

export type UseReactDropzoneVVProps = {
accept?: string
disabled?: boolean
disabledDropOnDocment?: boolean
multiple?: boolean
onDrop?: (files: File[]) => void
onSelect?: (classifiedFiles: ClassifiedFile[]) => void
onError?: (error: Error) => void
}

export type UseReactDropzoneVV = {
accept: string
setAccept: React.Dispatch<React.SetStateAction<string>>
disabled: boolean
setDisabled: React.Dispatch<React.SetStateAction<boolean>>
disabledDropOnDocment: boolean
setDisabledDropOnDocment: React.Dispatch<React.SetStateAction<boolean>>
multiple: boolean
setMultiple: React.Dispatch<React.SetStateAction<boolean>>
isDragging: boolean
setIsDragging: React.Dispatch<React.SetStateAction<boolean>>
inputRef: React.RefObject<HTMLInputElement>
open: () => void
onDrop?: (files: File[]) => void
onSelect?: (classifiedFiles: ClassifiedFile[]) => void
onError?: (error: Error) => void
}

export const useReactDropzoneVV = ({
accept: tAccept = "",
disabled: tDisabled = false,
disabledDropOnDocment: tDisabledDropOnDocment = false,
multiple: tMultiple = true,
onDrop,
onSelect,
onError,
}: UseReactDropzoneVVProps = {}): UseReactDropzoneVV => {
const [accept, setAccept] = useState<string>(tAccept)
const [disabled, setDisabled] = useState<boolean>(tDisabled)
const [disabledDropOnDocment, setDisabledDropOnDocment] = useState<boolean>(
tDisabledDropOnDocment,
)
const [multiple, setMultiple] = useState<boolean>(tMultiple)

const [isDragging, setIsDragging] = useState(false)

const inputRef = useRef<HTMLInputElement>(null)

const open = () => {
inputRef.current?.click()
}

return {
accept,
setAccept,
disabled,
setDisabled,
disabledDropOnDocment,
setDisabledDropOnDocment,
multiple,
setMultiple,
isDragging,
setIsDragging,
inputRef,
open,
onDrop,
onSelect,
onError,
}
}
Loading

0 comments on commit 2f9f339

Please sign in to comment.