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

ngx-photo-uploader

v1.2.0

Published

Angular standalone photo uploader with preview, drag & drop, camera capture and Reactive Forms support

Downloads

605

Readme

Photo Uploader — Angular

Standalone Angular component for uploading images via click, drag & drop, or camera, with built-in preview and full Reactive Forms support.

Features

  • Standalone component (no NgModule required)
  • Multiple image selection
  • Automatic preview (blob URLs via URL.createObjectURL)
  • Drag & drop with visual feedback
  • Paste images from the clipboard (Ctrl + V)
  • Camera capture (getUserMedia)
  • Image compression (maxWidth, maxHeight, quality)
  • EXIF orientation correction (rotated phone photos display correctly)
  • Drag thumbnails to reorder
  • Reactive Forms integration (ControlValueAccessor)
  • Automatic disabled / enabled state with Forms
  • Visual invalid state (NgControl)
  • Reusable validators included
  • Configurable visual inputs
  • No third-party dependencies — only Angular packages required

Requirements

  • Angular 16+

Installation

npm install ngx-photo-uploader

Basic usage

With Reactive Forms

import { Component } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { PhotoUploaderComponent, photoMaxFiles, photoMaxSize } from 'ngx-photo-uploader';

@Component({
  standalone: true,
  imports: [ReactiveFormsModule, PhotoUploaderComponent],
  template: `
    <form [formGroup]="form">
      <photo-uploader formControlName="photos"></photo-uploader>
    </form>
  `
})
export class ExampleComponent {
  form = this.fb.group({
    photos: [
      [] as File[],
      [Validators.required, photoMaxFiles(3), photoMaxSize(2 * 1024 * 1024)]
    ]
  });

  constructor(private fb: FormBuilder) {}
}

The control value is always File[], ready for FormData, REST APIs, or multipart uploads.

⚠️ Note: Validators.required does not flag empty arrays in Angular. Use the bundled photoRequired validator instead.

Configurable inputs

| Input | Type | Default | Description | | --------------- | ------- | ------------------ | --------------------------- | | multiple | boolean | true | Allow multiple photos | | accept | string | image/* | Accepted file types | | maxFiles | number | unlimited | Maximum number of photos | | maxWidth | number | unlimited | Max width in px (keeps aspect ratio) | | maxHeight | number | unlimited | Max height in px (keeps aspect ratio) | | quality | number | 0.9 | JPEG/WebP compression quality (0-1) | | height | string | 200px | Container height | | thumbnailSize | number | 100 | Thumbnail size (px) | | gap | number | 10 | Space between thumbnails (px) | | rounded | number | 10 | Corner radius (px) | | placeholder | string | Default text | Placeholder text |

Example

<photo-uploader
  formControlName="photos"
  [multiple]="true"
  [maxFiles]="5"
  height="280px"
  [thumbnailSize]="120"
  [gap]="16"
  [rounded]="16"
  placeholder="Drag your team photos here"
></photo-uploader>

Camera

The component includes a "Use camera" button to capture images directly from the device:

  • Mobile friendly
  • Uses the rear camera (facingMode: environment)
  • The capture is automatically converted to a File (JPEG)
  • Tracks are stopped on close to avoid leaks

Requires a HTTPS connection (or localhost) due to getUserMedia.

Paste from clipboard

Press Ctrl + V (or Cmd + V on macOS) anywhere on the page to paste an image from the clipboard (e.g. screenshots). Pasted images are processed exactly like uploaded ones, so maxFiles, validators and compression all apply.

The paste is not intercepted when the focus is inside an input or textarea.

Image compression

Set maxWidth and/or maxHeight to automatically scale down images before they are emitted as File. The aspect ratio is preserved and the file is re-encoded with the configured quality.

<photo-uploader
  formControlName="photos"
  [maxWidth]="1024"
  [maxHeight]="768"
  [quality]="0.8"
></photo-uploader>
  • Only JPEG, PNG and WebP images are compressed; GIF and SVG are kept as-is.
  • Images already within the limits are left untouched (no re-encoding).
  • Compression also applies to camera captures and pasted images.

EXIF orientation

Photos taken with a phone or camera often carry an EXIF orientation flag (rotation), so they appear rotated in browsers. When compression is enabled, the component reads the flag from JPEG files and bakes the correct rotation into the re-encoded image — the emitted file no longer depends on the EXIF flag and always displays upright.

  • EXIF is read from JPEG files only; PNG and WebP are re-encoded as-is and GIF/SVG are never touched.
  • Applied on upload, camera capture and paste.
  • Without compression settings, the original file is preserved as-is; the preview still displays correctly because browsers render images with EXIF orientation by default (image-orientation: from-image).

Image reordering

Thumbnails are draggable: drag a thumbnail and drop it on another position to reorder the photos. The emitted File[] follows the new order, so the images are uploaded in the order the user left them.

  • Only the order changes — files are not re-encoded on reorder.
  • Works with Reactive Forms: the control value reflects the new order immediately.

Bundled validators

The library exports reusable validators:

import {
  photoRequired,
  photoMaxFiles,
  photoMaxSize,
  photoAllowedTypes
} from 'ngx-photo-uploader';
this.form = this.fb.group({
  photos: [
    [] as File[],
    [
      photoRequired,
      photoMaxFiles(5),
      photoMaxSize(2 * 1024 * 1024),
      photoAllowedTypes(['image/png', 'image/jpeg'])
    ]
  ]
});

Error handling

<div *ngIf="form.controls.photos.touched">
  <small *ngIf="form.controls.photos.errors?.required">
    You must upload at least one image
  </small>
  <small *ngIf="form.controls.photos.errors?.maxFiles">
    Maximum {{ form.controls.photos.errors.maxFiles.max }} images
  </small>
  <small *ngIf="form.controls.photos.errors?.maxSize">
    The file {{ form.controls.photos.errors.maxSize.fileName }}
    exceeds the allowed size
  </small>
</div>

Accessibility & states

  • Automatic disabled state with Forms
  • Visual invalid state (red border) via NgControl
  • Aria-labels on thumbnails (Imagen N), remove buttons (Eliminar foto N) and upload icon (decorative, aria-hidden)
  • Native <button> elements for camera, capture/cancel and clear actions — keyboard accessible

Roadmap

  • ✅ Image compression (maxWidth, maxHeight, quality)
  • ✅ Paste from clipboard (Ctrl + V)
  • ✅ EXIF orientation correction
  • ✅ Image reordering
  • Accessible file picker (focusable drop zone, role="button" + keyboard)
  • Keyboard drag-reorder (move thumbnails with arrow keys / buttons)
  • Focus management and visible focus indicators
  • ARIA live regions for upload feedback
  • Sufficient color contrast (WCAG 2.2 AA)
  • Cropping support
  • Theme customization
  • i18n

License

MIT