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-image-forge

v1.2.1

Published

A signals-native, dependency-free Angular image editing library using the Canvas API

Readme

ngx-image-forge

A signals-native, dependency-free Angular image editing library using the Canvas API.

CI npm license

Live demo →


Features

  • Signals-first — internal state is pure signals, OnPush throughout
  • Zoneless-compatible — works with provideExperimentalZonelessChangeDetection()
  • Zero runtime dependencies — pure Canvas API, no third-party image libraries
  • Three usage patterns — embedded component, trigger directive, or programmatic service
  • Non-destructive transforms — rotate, flip, and crop are composed on export, never on the original
  • Aspect ratio constraints — free, fixed numeric ratio (e.g. 16/9), or 1 for square
  • Circular crop — circular clip mask applied at export time
  • Output control — JPEG, PNG, or WebP with configurable quality and max dimensions
  • Touch support — drag and resize handles work on mobile
  • Accessible — keyboard-navigable overlay, focus management on open/close

Requirements

  • Angular 19+

Installation

npm install ngx-image-forge
# or
pnpm add ngx-image-forge

Usage

There are three ways to use ngx-image-forge. Pick the one that fits your workflow.


1. Embedded component

Drop <ngx-image-editor> directly into your template and control it via a viewChild reference. Best for dedicated editing pages.

import { NgxImageEditorComponent, NgxCroppedImage } from 'ngx-image-forge';

@Component({
  imports: [NgxImageEditorComponent],
  template: `
    <ngx-image-editor [image]="file" [aspectRatio]="1" #editor style="height: 500px" />
    <button (click)="crop(editor)">Crop</button>
  `,
})
export class MyComponent {
  file: File | null = null;

  crop(editor: NgxImageEditorComponent): void {
    const result: NgxCroppedImage = editor.crop();
    console.log(result.dataUrl, result.blob);
  }
}

2. Trigger directive

Attach ngxImageEditorTrigger to any clickable element. Clicking it opens a full-screen overlay; the result is emitted via (forgeResult). Best for inline "edit" buttons next to images.

import { NgxImageEditorTriggerDirective, NgxCroppedImage } from 'ngx-image-forge';

@Component({
  imports: [NgxImageEditorTriggerDirective],
  template: `
    <button
      ngxImageEditorTrigger
      [triggerImage]="file"
      [triggerAspectRatio]="16 / 9"
      (forgeResult)="onResult($event)"
    >
      Edit image
    </button>
  `,
})
export class MyComponent {
  file: File | null = null;

  onResult(result: NgxCroppedImage | null): void {
    if (result) console.log('Cropped!', result.dataUrl);
  }
}

3. Programmatic service

Inject NgxImageForgeService and call open() anywhere. Returns an Observable that emits once with the result (or null on cancel). Best for flows where the editor is opened from a service or complex logic.

import { NgxImageForgeService, NgxCroppedImage } from 'ngx-image-forge';

@Component({ ... })
export class MyComponent {
  private readonly forge = inject(NgxImageForgeService);

  openEditor(file: File): void {
    this.forge.open({ image: file, aspectRatio: 1, roundCrop: true }).subscribe(result => {
      if (result) console.log('Cropped!', result.dataUrl);
    });
  }
}

NgxImageEditorComponent inputs

| Input | Type | Default | Description | |---|---|---|---| | image | File \| string \| null | null | Source image — a File object or a URL string | | aspectRatio | number \| 'free' | 'free' | Crop constraint — a ratio (e.g. 16/9) or 'free' | | maxWidth | number | 0 | Maximum output width in px; 0 = unconstrained | | maxHeight | number | 0 | Maximum output height in px; 0 = unconstrained | | quality | number | 0.92 | JPEG/WebP encoding quality, 0–1 | | outputFormat | 'jpeg' \| 'png' \| 'webp' | 'jpeg' | Output MIME type | | roundCrop | boolean | false | Apply circular clip mask to the crop output | | minCropWidth | number | 50 | Minimum crop rectangle width in canvas px | | minCropHeight | number | 50 | Minimum crop rectangle height in canvas px | | handleSize | number | 10 | Side length in px of each resize handle square | | handleHitArea | number | 16 | Hit-test radius in px around each handle (increase for touch) | | overlayOpacity | number | 0.55 | Opacity of the dark overlay outside the crop rectangle | | cropBorderColor | string | '#ffffff' | CSS colour of the crop rectangle border | | cropBorderWidth | number | 1.5 | Width in px of the crop rectangle border | | handleColor | string | '#ffffff' | CSS colour of the resize handles |

NgxImageEditorComponent outputs

| Output | Payload | Description | |---|---|---| | imageLoaded | { naturalWidth: number; naturalHeight: number } | Fires when the image has loaded and is ready for editing | | loadError | string \| Event | Fires when the image fails to load | | imageCropped | NgxCroppedImage | Fires immediately after a successful crop() call |

NgxImageEditorComponent methods

| Method | Description | |---|---| | crop() | Performs the crop synchronously and returns an NgxCroppedImage. Throws if no image is loaded. | | reset() | Restores rotation, flip, and crop rectangle to their initial state. | | rotate(degrees) | Rotates the image by the given angle. Use multiples of 90 for lossless steps. | | setRotation(degrees) | Sets the exact rotation angle in degrees. | | flipHorizontal() | Toggles horizontal flip. | | flipVertical() | Toggles vertical flip. |


[ngxImageEditorTrigger] directive inputs

| Input | Type | Default | Description | |---|---|---|---| | triggerImage | File \| string \| null | null | Source image | | triggerAspectRatio | number \| 'free' | 'free' | Aspect ratio constraint | | triggerMaxWidth | number | 0 | Maximum output width in px | | triggerMaxHeight | number | 0 | Maximum output height in px | | triggerQuality | number | 0.92 | JPEG/WebP encoding quality | | triggerOutputFormat | 'jpeg' \| 'png' \| 'webp' | 'jpeg' | Output MIME type | | triggerRoundCrop | boolean | false | Apply circular clip mask |

Output: (forgeResult) — emits NgxCroppedImage on confirm, null on cancel.


NgxCroppedImage

The object returned by crop() and emitted by all result outputs.

| Field | Type | Description | |---|---|---| | blob | Blob | Cropped image as a Blob, ready for upload | | dataUrl | string | Base64 data URL, suitable for <img src> | | width | number | Output width in px | | height | number | Output height in px | | originalWidth | number | Natural width of the source image in px | | originalHeight | number | Natural height of the source image in px |


Contributing

Pull requests are welcome. For significant changes please open an issue first.

git clone https://github.com/HoplaGeiss/ngx-image-forge.git
cd ngx-image-forge
pnpm install
ng serve   # starts the demo app at localhost:4200

License

MIT