useDropZone
Turns any element into a file drop zone. Tracks drag-over state and validates file types before accepting drops.
Basic drop zone
Section titled “Basic drop zone”import { function useRef$<T extends Element = Element>(externalRef?: React.Ref<T> | null): Ref$<T>
Creates an observable element ref. Can be used as a drop-in replacement for
useRef, composed with callback refs, or used with forwardRef.
The element is wrapped with opaqueObject to prevent legendapp/state
from making DOM properties reactive (deep observation).
useRef$, import useDropZone
useDropZone } from "@usels/core";
function function MyDropZone(): React.JSX.Element
MyDropZone() { const const el$: Ref$<HTMLDivElement>
el$ = useRef$<HTMLDivElement>(externalRef?: React.Ref<HTMLDivElement> | undefined): Ref$<HTMLDivElement>
Creates an observable element ref. Can be used as a drop-in replacement for
useRef, composed with callback refs, or used with forwardRef.
The element is wrapped with opaqueObject to prevent legendapp/state
from making DOM properties reactive (deep observation).
useRef$<interface HTMLDivElement
HTMLDivElement>(); const { const files$: any
files$, const isOverDropZone$: any
isOverDropZone$ } = import useDropZone
useDropZone(const el$: Ref$<HTMLDivElement>
el$, { onDrop: (files: any) => any
onDrop: (files: any
files) => any
console.any
log(files: any
files), });
return ( <React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div React.RefAttributes<HTMLDivElement>.ref?: React.Ref<HTMLDivElement> | undefined
Allows getting a ref to the component instance.
Once the component unmounts, React will set ref.current to null
(or call the ref with null if you passed a callback ref).
ref={const el$: Ref$<HTMLDivElement>
el$} React.HTMLAttributes<HTMLDivElement>.style?: React.CSSProperties | undefined
style={{ StandardShorthandProperties<string | number, string & {}>.background?: Property.Background<string | number> | undefined
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Syntax: <bg-layer>#? , <final-bg-layer>
| Chrome | Firefox | Safari | Edge | IE |
| :----: | :-----: | :----: | :----: | :---: |
| 1 | 1 | 1 | 12 | 4 |
background: const isOverDropZone$: any
isOverDropZone$.any
get() ? "#e0e7ff" : "#f9fafb" }}> Drop files here </React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> );}Filter by file type
Section titled “Filter by file type”import { function useRef$<T extends Element = Element>(externalRef?: React.Ref<T> | null): Ref$<T>
Creates an observable element ref. Can be used as a drop-in replacement for
useRef, composed with callback refs, or used with forwardRef.
The element is wrapped with opaqueObject to prevent legendapp/state
from making DOM properties reactive (deep observation).
useRef$, import useDropZone
useDropZone } from "@usels/core";
function function ImageDropZone(): void
ImageDropZone() { const const el$: Ref$<HTMLDivElement>
el$ = useRef$<HTMLDivElement>(externalRef?: React.Ref<HTMLDivElement> | undefined): Ref$<HTMLDivElement>
Creates an observable element ref. Can be used as a drop-in replacement for
useRef, composed with callback refs, or used with forwardRef.
The element is wrapped with opaqueObject to prevent legendapp/state
from making DOM properties reactive (deep observation).
useRef$<interface HTMLDivElement
HTMLDivElement>(); const { const files$: any
files$ } = import useDropZone
useDropZone(const el$: Ref$<HTMLDivElement>
el$, { dataTypes: {}
dataTypes: ["image/png", "image/jpeg", "image/webp"], }); // ...}Custom validation
Section titled “Custom validation”const { files$ } = useDropZone(el$, { checkValidity: (items) => Array.from(items).every((item) => item.type.startsWith("image/")),});Single file only
Section titled “Single file only”const { files$ } = useDropZone(el$, { multiple: false, onDrop: (files) => files && uploadFile(files[0]),});Shorthand (onDrop only)
Section titled “Shorthand (onDrop only)”const { files$ } = useDropZone(el$, (files, event) => { if (files) processFiles(files);});Type Declarations
Section titled “Type Declarations”export interface UseDropZoneOptions { dataTypes?: string[] | ((types: readonly string[]) => boolean); checkValidity?: (items: DataTransferItemList) => boolean; onDrop?: (files: File[] | null, event: DragEvent) => void; onEnter?: (files: File[] | null, event: DragEvent) => void; onLeave?: (files: File[] | null, event: DragEvent) => void; onOver?: (files: File[] | null, event: DragEvent) => void; multiple?: boolean; preventDefaultForUnhandled?: boolean;}export interface UseDropZoneReturn { files$: Observable<File[] | null>; isOverDropZone$: Observable<boolean>;}export declare function useDropZone(target: MaybeElement, options?: DeepMaybeObservable<UseDropZoneOptions> | UseDropZoneOptions["onDrop"]): UseDropZoneReturn;Source
Section titled “Source”Contributors
Section titled “Contributors”- tigerwest
Changelog
Section titled “Changelog”a7392ab2026-03-06 - feat(core,browser): add sync strategy hooks (tigerwest)