Skip to content

Clipboard paste

usePaste feeds the same addFiles path as drop and click, so validation and the queue stay consistent.

tsx
import { useRef } from 'react';
import { useUploader, useDropzone, usePaste } from 'react-upload-kit';

const ACCEPT = ['image/*'];

function ImageUploader({ adapter }) {
  const surfaceRef = useRef<HTMLDivElement>(null);

  const uploader = useUploader({
    adapter,
    accept: ACCEPT,
    maxFileSize: 8 * 1024 * 1024,
    autoUpload: true,
  });

  const dropzone = useDropzone({
    onDrop: uploader.addFiles,
    accept: ACCEPT,
  });

  usePaste({
    onPaste: uploader.addFiles,
    accept: ACCEPT,
    targetRef: surfaceRef,
  });

  return (
    <div ref={surfaceRef} tabIndex={0}>
      <div {...dropzone.getRootProps()}>
        <input {...dropzone.getInputProps()} />
        Drop, click, or paste an image
      </div>
    </div>
  );
}

Scope the listener

targetRefBehaviour
Omitteddocument listener — any paste on the page
Container refOnly pastes that target that subtree

Use a container when the page has text fields. The user can still paste a screenshot after focusing the dropzone (tabIndex={0}).

enabled: false detaches the listener (for example while a modal is closed).

Screenshots from the OS clipboard are usually image/png. accept: ['image/*'] is the practical default. If you need PDFs from paste, test the browser: many will not put a PDF on clipboardData.items as a file.

Released under the MIT License.