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

@mainframework/dropzone

v1.0.24

Published

A file selection package, without all of the re-rendering issues that come with other dropzone packages

Readme

@mainframework/dropzone

A React package that allows for the selection of files through drag and drop or the File Dialog API. Re-rendering is kept to a minimum, helping with application performance.

Installation

npm i @mainframework/dropzone
# or
yarn add @mainframework/dropzone

Running Tests

yarn test
# or
npm run test

Hook Configuration

The useFileSelector hook accepts optional configuration:

const { ... } = useFileSelector({
  maximumUploadCount: 5,      // Default: 30
  maximumFileSize: 5e6,       // Default: 5 MB
  acceptedTypes: defaultTypeExtensions,  // MIME type map, see below
});

Hook Exports

The hook returns the following:

Properties

| Export | Type | Description | | -------------- | ------------ | ------------------------------------------------------------------------------------------------------------- | | validFiles | FileData[] | Files that passed validation (accepted type, size, and count). Each item has id, file, url, and type. | | invalidFiles | File[] | Files the user selected that failed validation (wrong type or rejected). |

Methods

| Export | Signature | Description | | --------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | clearCache | () => void | Clears both validFiles and invalidFiles, and revokes blob URLs to free memory. | | getValidFileStreams | () => (File \| Blob)[] | Returns the raw File or Blob instances from validFiles for upload or further processing. | | onCancel | () => void | Same as clearCache; use when the user cancels selection. | | onIdChange | (index: number, id: string, files: FileData[]) => void | Renames a file by ID. Pass the index, new ID, and current validFiles array. | | onRemoveFile | (index: number) => void | Removes the file at the given index from validFiles and revokes its blob URL. | | clearBlobs | () => void | Revokes blob URLs for all valid files to free memory. Does not clear the arrays. | | clearBlob | (file: File) => void | Revokes the blob URL for a single File instance. |

Error State

| Export | Type | Description | | ---------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | maxUploadError | { status: boolean; message: string } | Reflects whether the max upload count was exceeded. Check status and show message in your UI. | | maxFileSizeError | { status: boolean; message: string } | Reflects whether a file exceeded the max size. Check status and show message in your UI. | | setMaximumUploadsExceeded | (status?: boolean, fileCount?: number, maximumUploads?: number) => void | Sets the max upload error state. Call with true and counts to show the error; call with false to clear. | | setMaximumFileSizeExceeded | (status?: boolean) => void | Sets the max file size error state. Call with true to show the error; call with false to clear. |

Component

| Export | Description | | -------------- | ------------------------------------------------------------------------------------------------------------------------------ | | FileSelector | A pre-wired dropzone component. Renders a clickable area and hidden file input, with drag-and-drop handlers bound to the hook. |

FileSelector Props

When rendering FileSelector, you can pass:

| Prop | Type | Default | Description | | --------------------------- | -------- | --------------------------------------------------------- | -------------------------------------------- | | inputId | string | auto-generated | ID for the file input (for aria-controls). | | acceptTypes | string | .png, .jpg, .jpeg, .pdf, .svg, ... | accept attribute for the file input. | | messageParagraph | string | "Drag 'n' drop some files here, or click to select files" | Text shown in the dropzone. | | inputClassName | string | "hiddenInput" | CSS classes for the hidden input. | | clickableAreaClassName | string | Tailwind dropzone styles | CSS classes for the clickable area. | | dropZoneWrapperClassName | string | Tailwind wrapper styles | CSS classes for the outer wrapper. | | messageParagraphClassName | string | Tailwind text styles | CSS classes for the message text. | | ariaLabel | string | "File upload drop zone" | Accessible name for the drop zone. | | ariaDescribedBy | string | — | ID of element that describes the drop zone. | | ariaLabelButton | string | "Choose files to upload" | Accessible label for the button. | | ariaLabelledBy | string | — | ID of element that labels the button. |

Default Accepted Types

The package validates files against a MIME type map. You can override it via acceptedTypes in the hook config:

export const defaultTypeExtensions: Record<string, string> = {
  "image/png": ".png",
  "image/jpeg": ".jpeg",
  "image/jpg": ".jpg",
  "image/svg+xml": ".svg",
  "application/pdf": ".pdf",
  "application/msword": ".doc",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
};

Usage Example

import { useFileSelector } from "@mainframework/dropzone";

export const App = () => {
  const {
    validFiles,
    invalidFiles,
    onIdChange,
    onCancel,
    onRemoveFile,
    FileSelector,
    maxUploadError,
    maxFileSizeError,
  } = useFileSelector({
    maximumUploadCount: 5,
    maximumFileSize: 5e6,
  });

  const onSelect = () => {
    if (Array.isArray(validFiles)) {
      // Use validFiles for upload or preview
    }
  };

  return (
    <>
      <FileSelector messageParagraph="Drop files here or click to select" acceptTypes=".png,.jpg,.jpeg,.pdf" />

      {maxUploadError.status && <p role="alert">{maxUploadError.message}</p>}
      {maxFileSizeError.status && <p role="alert">{maxFileSizeError.message}</p>}

      {validFiles.length > 0 && (
        <PreviewImages
          validFiles={validFiles}
          onChange={onIdChange}
          onSelect={onSelect}
          onCancel={onCancel}
          onRemoveFile={onRemoveFile}
        />
      )}
    </>
  );
};

Manipulating validFiles in a Preview Component

As an example, when building a preview component (e.g. PreviewImages), use the hook’s methods to update validFiles based on user actions:

| User action | Hook method | How to use it | | ------------------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Remove a single file | onRemoveFile | Call onRemoveFile(index) when the user removes one file. The index is the position in validFiles (e.g. from a list key or map index). The hook removes that item and revokes its blob URL. | | Rename a file | onIdChange | Call onIdChange(index, newId, validFiles) when the user changes a file’s name. Pass the index, the new ID (filename without extension), and the current validFiles array. The hook updates the file’s id and file in place. | | Clear all files | onCancel | Call onCancel() when the user cancels or clears the selection. The hook clears validFiles and invalidFiles and revokes all blob URLs. |

Example PreviewImages wiring:

const PreviewImages = ({ validFiles, onChange, onCancel, onRemoveFile }) => (
  <div>
    {validFiles.map((fileData, index) => (
      <div key={fileData.id}>
        <img src={fileData.url} alt={fileData.id} />
        <input value={fileData.id} onChange={(e) => onChange(index, e.target.value, validFiles)} />
        <button onClick={() => onRemoveFile(index)}>Remove</button>
      </div>
    ))}
    <button onClick={onCancel}>Clear all</button>
  </div>
);
  • onRemoveFile(index) — removes the file at index from validFiles.
  • onChange(index, newId, validFiles) — renames the file at index to newId; pass the current validFiles so the hook can update state.
  • onCancel() — clears all files and frees blob URLs.