A small package for converting a DragEvent or file input to a list of File objects.
📖 Documentation & live playground →
You can install this package from NPM:
npm add file-selectorFor CDN usage, load the ESM build directly from a CDN such as esm.sh or jsDelivr:
<script type="module">
import {fromEvent} from "https://esm.sh/file-selector";
document.addEventListener("drop", async evt => {
const files = await fromEvent(evt);
console.log(files);
});
</script>Convert a DragEvent to File objects:
import {fromEvent} from "file-selector";
document.addEventListener("drop", async evt => {
const files = await fromEvent(evt);
console.log(files);
});Convert a change event for an input type file to File objects:
import {fromEvent} from "file-selector";
const input = document.getElementById("myInput");
input.addEventListener("change", async evt => {
const files = await fromEvent(evt);
console.log(files);
});Convert FileSystemFileHandle items to File objects:
import {fromEvent} from "file-selector";
// Open file picker
const handles = await window.showOpenFilePicker({multiple: true});
// Get the files
const files = await fromEvent(handles);
console.log(files);NOTE The above is experimental and subject to change.
Convert a DragEvent to File objects:
const {fromEvent} = require("file-selector");
document.addEventListener("drop", async evt => {
const files = await fromEvent(evt);
console.log(files);
});When the browser doesn't set a File's type, fromEvent infers one from the file extension. By default it uses a small built-in table of the most common types, keeping the bundle lean.
If you need broader coverage, import the full extension-to-MIME table from the file-selector/mime subpath and pass it via the mimeTypes option. Because it's a separate entry point, the full table (~1,200 entries) is only included in your bundle when you import it:
import {fromEvent} from "file-selector";
import {COMMON_MIME_TYPES} from "file-selector/mime";
const files = await fromEvent(evt, {mimeTypes: COMMON_MIME_TYPES});You can also pass your own Map<extension, mimeType> to restrict or extend the lookup:
const files = await fromEvent(evt, {mimeTypes: new Map([["dwg", "image/vnd.dwg"]])});Most browser support basic File selection with drag 'n' drop or file input:
For folder drop we use the FileSystem API which has very limited support:
- DataTransferItem.getAsFile()
- DataTransferItem.webkitGetAsEntry()
- FileSystemEntry
- FileSystemFileEntry.file()
- FileSystemDirectoryEntry.createReader()
- FileSystemDirectoryReader.readEntries()
Checkout the organization CONTRIBUTING.md.
Development requires Node.js >= 20. Install the dependencies with:
npm installThe project is built with tsdown (Rolldown), type-checked with TypeScript, tested with Vitest and linted/formatted with oxlint and oxfmt.
| Command | Description |
|---|---|
npm test |
Run the test suite in watch mode. |
npm run test:cov |
Run the tests once with coverage (runs type-check, lint and format check first). |
npm run type-check |
Type-check the sources without emitting. |
npm run lint |
Lint the sources (oxlint). |
npm run lint:fix |
Apply safe lint fixes. |
npm run lint:type-aware |
Type-aware lint via tsgolint (alpha). |
npm run format |
Format the sources (oxfmt). |
npm run format:check |
Check formatting without writing. |
npm run build |
Build the outputs into dist/. |
npm run dev |
Build in watch mode. |
npm run docs:dev |
Run the Vocs docs site locally. |
npm run docs:build |
Build the docs site into site/. |
npm run docs:preview |
Preview the built docs site. |
npm run hooks:install |
Install the git hooks (prek install). |
npm run hooks:run |
Run every git hook over the whole repo. |
The build emits into dist/:
dist/index.js— ES moduledist/index.cjs— CommonJS moduledist/index.d.ts— TypeScript declarations
Git hooks are managed with prek, a fast Rust drop-in for the pre-commit framework (configured in .pre-commit-config.yaml). On commit they format and lint the staged files with oxfmt/oxlint, and check the message against Conventional Commits — the same convention semantic-release uses to cut releases.
prek is a standalone binary, so install it once (e.g. uv tool install prek, brew install prek, or see the install docs). npm install then wires up the hooks automatically; run npm run hooks:install to (re)install them by hand. The hooks are optional — CI enforces the same lint, format and commit checks — but they catch issues before you push.
Support us with a monthly donation and help us continue our activities. [Become a backer]
Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]
MIT
