npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@input-kit/dropzone

v0.1.0

Published

File dropzone

Downloads

82

Readme

@input-kit/dropzone

Headless file dropzone hook and component for React. Fully typed, keyboard accessible, with image preview support and automatic cleanup of object URLs.

Comparison with react-dropzone

| Feature | @input-kit/dropzone | react-dropzone | |---|---|---| | Bundle size | ~4 KB | ~20 KB | | Dependencies | zero | file-selector | | TypeScript | full | full | | Keyboard (Space/Enter) | yes | yes | | Image previews | built-in | manual (onDrop) | | File type accept format | string/string[] | MIME object { 'image/*': ['.png'] } | | Object URL cleanup | auto on unmount | manual | | SSR | safe | safe |

Installation

npm install @input-kit/dropzone

Quick Start

import { useDropzone } from '@input-kit/dropzone';

function MyDropzone() {
  const { getRootProps, getInputProps, files, removeFile } = useDropzone({
    accept: 'image/*',
    maxFiles: 5,
    maxSize: 5 * 1024 * 1024, // 5 MB
  });

  return (
    <div {...getRootProps()} style={{ border: '2px dashed #ccc', padding: 32 }}>
      <input {...getInputProps()} />
      <p>Drag files here or press Space / Enter to browse</p>
      {files.map(f => (
        <div key={f.id}>
          {f.preview && <img src={f.preview} width={80} alt={f.name} />}
          <span>{f.name}</span>
          <button onClick={() => removeFile(f.id)}>Remove</button>
        </div>
      ))}
    </div>
  );
}

Drop-in Dropzone component

import { Dropzone } from '@input-kit/dropzone';

<Dropzone
  accept="image/*,.pdf"
  maxSize={10 * 1024 * 1024}
  maxFiles={3}
  onDrop={(files) => console.log(files)}
  onRemove={(file) => console.log('removed', file.name)}
/>

API

useDropzone(options?)

const {
  files,          // FileWithPreview[] — accepted files
  isDragActive,   // boolean — drag is over the zone
  isDragAccept,   // boolean — all dragged files appear valid
  isDragReject,   // boolean — some dragged files appear invalid
  getRootProps,   // () => root element props (drag, click, keyboard)
  getInputProps,  // () => hidden <input> props
  open,           // () => void — programmatically open file dialog
  removeFile,     // (id: string) => void — remove a file and revoke its preview URL
  clearFiles,     // () => void — remove all files
} = useDropzone(options);

UseDropzoneOptions

| Option | Type | Default | Description | |---|---|---|---| | accept | string \| string[] | — | Accepted MIME types or extensions. e.g. 'image/*', ['.pdf', '.docx'] | | maxSize | number | Infinity | Maximum file size in bytes | | maxFiles | number | Infinity | Maximum number of accepted files | | multiple | boolean | true | Allow multiple files | | disabled | boolean | false | Disable all interaction | | onDrop | (accepted, rejected) => void | — | Called after every drop | | onDropAccepted | (files) => void | — | Called when at least one file is accepted | | onDropRejected | (rejections) => void | — | Called when at least one file is rejected | | validator | (file) => FileRejection \| null | — | Custom per-file validator |

FileWithPreview

Extends File with two additional fields:

| Field | Type | Description | |---|---|---| | id | string | Unique ID for use as React key | | preview | string \| undefined | Object URL for image files (revoked automatically on removal/unmount) |

FileRejection

interface FileRejection {
  file: File;
  errors: FileError[];
}

interface FileError {
  code: 'file-too-large' | 'file-invalid-type' | 'too-many-files' | 'custom';
  message: string;
}

DropzoneProps

| Prop | Type | Default | Description | |---|---|---|---| | accept | string \| string[] | — | Accepted types/extensions | | maxSize | number | — | Max file size in bytes | | maxFiles | number | — | Max accepted file count | | multiple | boolean | true | Allow multiple files | | disabled | boolean | false | Disable interaction | | onDrop | (files: File[]) => void | — | Called with accepted files | | onRemove | (file: FileWithPreview) => void | — | Called when a file is removed | | showPreview | boolean | true | Show built-in file list preview | | className | string | — | Class for the outer wrapper | | style | CSSProperties | — | Style for the outer wrapper | | children | ReactNode \| ((state: { isDragActive }) => ReactNode) | — | Custom render content |

Keyboard Accessibility

The root element receives tabIndex={0}, role="button", and an aria-label. Space and Enter open the file dialog, matching the behaviour of react-dropzone.

File Type Validation

Accepts the same accept string as the HTML <input type="file"> attribute:

useDropzone({ accept: 'image/png,image/jpeg' })
useDropzone({ accept: ['.pdf', '.docx', 'image/*'] })

Note: Browsers do not expose MIME types during drag events for security reasons. isDragAccept and isDragReject are best-effort during drag and are reliable only after the drop.

Notes vs react-dropzone

  • react-dropzone's accept format is { 'image/*': ['.png'] } (MIME object)
  • @input-kit/dropzone uses the simpler HTML accept string format consistently
  • Image preview URLs are generated automatically and revoked on removeFile, clearFiles, or component unmount — no manual cleanup needed
  • react-dropzone has noClick, noDrag, noKeyboard escape hatches; this package does not currently expose them

TypeScript

import type { FileWithPreview, FileRejection, FileError, UseDropzoneOptions, DropzoneProps } from '@input-kit/dropzone';

License

MIT © Harshit