Every paste becomes { type, data, files }. No more guessing which clipboardData API to call.
Screenshots, pasted PNGs, copied images from the web — all detected as type: 'image' with a File you can preview or upload.
Paste from a file explorer and get all files via result.files. Image or document — classified automatically.
Image > File > HTML > Text. When Word pastes include both HTML and text, you get the richest format by default.
Only care about images? Pass types: ['image']. Unmatched pastes fall through untouched.
Pure TypeScript class you drop into any project. No framework coupling, no bloat. ~0.8kB gzipped.
Try pasting a screenshot, a file, rich text from a document, or plain text.
npm install paste-rich
yarn add paste-rich
pnpm add paste-rich
<script type="module"> import PasteRich from 'https://esm.sh/paste-rich'; </script>
import PasteRich from 'paste-rich'; const pr = new PasteRich({ target: '#editor', onPaste: (result) => { console.log(result.type); // 'image' | 'file' | 'html' | 'text' console.log(result.data); // File or string console.log(result.files); // File[] }, });
import PasteRich from 'paste-rich'; const pr = new PasteRich({ target: '#drop-zone', types: ['image'], onPaste: ({ data }) => { const url = URL.createObjectURL(data); document.getElementById('preview').src = url; }, });
import { useEffect, useRef } from 'react'; import PasteRich from 'paste-rich'; function usePasteRich(ref, onPaste) { const pr = useRef(null); useEffect(() => { if (!ref.current) return; pr.current = new PasteRich({ target: ref.current, onPaste, }); return () => pr.current?.destroy(); }, [ref, onPaste]); }
import PasteRich from 'paste-rich'; new PasteRich({ types: ['image'], onPaste: async ({ data }) => { const form = new FormData(); form.append('image', data); await fetch('/api/upload', { method: 'POST', body: form, }); }, });
| Option | Type | Default | Description |
|---|---|---|---|
| target | HTMLElement | string | document | Element or CSS selector to listen for paste events on. |
| onPaste | (result: PasteResult) => void | — | Required. Called with the normalized paste result. |
| types | PasteType[] | all | Filter to specific types. Unmatched pastes are ignored. |
| preventDefault | boolean | true | Whether to prevent the default paste behavior. |
| Member | Type | Description |
|---|---|---|
| result.type | 'image' | 'file' | 'html' | 'text' | Detected paste type (highest priority match). |
| result.data | string | File | Primary data. File for image/file, string for html/text. |
| result.files | File[] | All files from the paste. Empty for text/html-only. |
| .destroy() | void | Remove the paste listener and clean up. |
| [Symbol.dispose]() | void | Alias for destroy(). Enables using syntax. |