The `<Dropzone />` is a wrapper component using `useDropzone` hook of `react-dropzone` library to handle drag 'n' drop and select files from the file dialog. It has a `<div>` as root and a hidden `<input />`. See their [documentation](https://react-dropzone.js.org/) for more information.

### Props

The props are composited of `DropzoneOptions`, `inputProps` and any other HTML attributes.

#### DropzoneOptions

The `useDropzone` takes an option object to initiate the hook. These are all the options, some of them are set with default values

```
{
    accept, // {string[]}
    minSize, // number, default: 0
    maxSize, // number, default: Infinity
    maxFiles, // number, default: 0
    preventDropOnDocument, // bool, default: true
    noClick,  // bool, default: false
    noKeyboard, // bool, default: false
    noDrag, // bool, default: false
    noDragEventsBubbling, // bool, default: false
    disabled,  // bool, default: false,
    onDrop, // function
    onDropAccepted, // function
    onDropRejected, // function
    getFilesFromEvent, // function
    onFileDialogCancel, // function
    onFileDialogOpen, // function
    onError, // function
    validator, // function
    useFsAccessApi: true,
    autoFocus,  // bool, default: false
    multiple // bool, default: true,
    onDragEnter, // function
    onDragLeave, // function
    onDragOver, // function
}
```

These options can be set as the props of `<Dropzone />`. They are extracted and passed to `useDropzone` under the hood.

```
<Dropzone disabled />
```

#### inputProps

There are two props getters, `getRootProps` and `getInputProps` returned from `useDropzone` hook. They are two functions that return objects with properties used to create the drag 'n' drop zone. They are applied to the root `<div>` and the `<input />`

```
const Dropzone() {
  const {getRootProps, getInputProps} = useDropzone()

  return (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
    </div>
  )
}
```

The `inputProps` is meant to be used whenever you want to add other props to the inner `<input />` element.

```
<Dropzone
    inputProps={
        id: 'input-id',
        name: 'input-name',
        ...
    }
/>
```

### children

The optional `children` prop is a function with `state` object as argument returned from `useDropzone` and returns a JSX element.

```
const Component = (state: DropzoneState) => <p>Drag 'n' drop files here</p>

<Dropzone>
    {Component}
</Dropzone>
```

These are the fields of the `state`:

```
{
    open: () => void;
    isFocused: boolean;
    isDragActive: boolean;
    isDragAccept: boolean;
    isDragReject: boolean;
    isFileDialogActive: boolean;
    acceptedFiles: File[];
    fileRejections: FileRejection[];
    rootRef: React.RefObject<HTMLElement>;
    inputRef: React.RefObject<HTMLInputElement>;
}
```

### Opening file dialog programmatically

You can programmatically invoke the default OS file prompt; just use the `open` method passed to the `children`.

**Note** that we need to set `noClick` and `noKeyboard` to be `true` when use the `open` method to avoid opening the file dialog twice. This is because `getRootProps` applies `onClick` to the root `<div>` to open the dialog under the hood.

```
<Dropzone noClick noKeyboard>
    {({open}) => <button onClick={open}>Select files</button>}
</Dropzone>
```

### Custom validation

We can customize the validation rules through the `validator` prop.

```
const maxLength = 10

// custom validation rule
const nameLengthValidator = (file: File): DropzoneFileError | void => {
  if (file.name.length <= maxLength) {
    return
  }

  return {
    code: 'name-too-large',
    message: `Name is larger than ${maxLength} characters`,
  }
}

<Dropzone validator={nameLengthValidator} />
```
