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

ng2-multi-modal

v2.0.0

Published

Signals-based, zoneless multi-window modal library for Angular 20, 21 & 22. Draggable, resizable, maximizable, minimizable (dock), themeable and accessible.

Readme

ng2-multi-modal

A powerful, signals-based, zoneless multi-window modal library for Angular. Windows can be dragged, resized, maximized, minimized (to a dock), stacked with automatic z-index/focus management, themed, and made fully accessible. Create them declaratively in a template or imperatively through a service — including rendering a component as content with injected data and an awaitable result.

  • ✅ Angular 20, 21 and 22 — single published build
  • ✅ 100% signals, OnPush, no zone.js required
  • ✅ SSR-safe (no direct window/document access)
  • ✅ Accessible: role="dialog", focus trap, keyboard control, localized labels
  • ✅ 7 built-in themes + ~70 CSS custom properties
  • ✅ No runtime dependencies beyond tslib

screenshot

Compatibility

| ng2-multi-modal | Angular | Node | TypeScript | | --------------- | ------------------ | -------------------------------------- | ---------- | | 2.x | 20 · 21 · 22 | ^20.19 || ^22.12 || >=24 | ≥ 5.8 | | 1.x | 19 | 18.19+ / 20.11+ | 5.5–5.7 |

The library is compiled in Angular's partial (Ivy) format against the lowest supported major (20), so a single package links cleanly into apps running 20, 21 or 22. Every release is verified by CI building a real consumer app on each version.

Installation

npm install ng2-multi-modal

Setup

ng2-multi-modal is zoneless-first. Register the (optional) global config provider and, if your app is not already zoneless, enable zoneless change detection:

import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core';
import { provideNg2MultiModal } from 'ng2-multi-modal';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZonelessChangeDetection(), // not needed on Angular 22 (zoneless by default)
    provideNg2MultiModal({
      theme: 'auto',        // 'light' | 'dark' | 'auto' (follows prefers-color-scheme)
      language: 'es',       // 'en' | 'es' (or your own via `locale`)
      zIndexBase: 1000,
      closeOnEscape: true,
    }),
  ],
};

Import the styles once (global stylesheet). Either the convenience bundle:

@use 'ng2-multi-modal/styles.css';

…or pick the structural sheet + the theme(s) you want:

@use 'ng2-multi-modal/styles/style.css';
@use 'ng2-multi-modal/styles/theme/default.css';
@use 'ng2-multi-modal/styles/theme/default-dark.css';
/* other themes: macos, material-design, ant-design, win11, glass */

Usage

Open with the service

import { Component, inject } from '@angular/core';
import { Ng2MultiModalService } from 'ng2-multi-modal';

@Component({ /* … */ })
export class AppComponent {
  private readonly modal = inject(Ng2MultiModalService);

  openText() {
    this.modal.open('Hello world', { title: 'Greeting', width: 360, height: 200 });
  }

  openTemplate(tpl: TemplateRef<unknown>) {
    this.modal.open(tpl, { title: 'From a template', theme: 'dark' });
  }
}

Open a component as content (with data + result)

import { ModalRef, NG2_MODAL_DATA } from 'ng2-multi-modal';

@Component({
  template: `<h3>Hi {{ data.name }}</h3>
             <button (click)="ref.close('ok')">OK</button>`,
})
export class MyDialog {
  readonly data = inject<{ name: string }>(NG2_MODAL_DATA);
  readonly ref = inject<ModalRef<string>>(ModalRef);
}

// caller
const ref = this.modal.open<string, { name: string }>(MyDialog, {
  title: 'Confirm',
  data: { name: 'Ada' },
  blocking: true,
});
ref.afterClosed().subscribe(result => console.log(result)); // 'ok'

Declarative usage

<ng2-multi-modal title="My window" [theme]="'auto'" (onClose)="onClosed()">
  <p>Any projected content goes here.</p>
</ng2-multi-modal>

API

Ng2MultiModalService

| Member | Description | | ------ | ----------- | | open<R, D>(content?, options?): ModalRef<R, D> | Open a window. content = TemplateRef | component class | string. | | create(config) | @deprecated v1 compatibility wrapper (returns a Promise). | | bringToFront(id) / select(id) | Raise / select a window. | | addToDock(win) / removeFromDock(win) | Dock management. | | getRef(id) | Get the ModalRef of an open window. | | closeAll() | Close every open window. | | setLocale(lang) | Switch language. | | language, locale, dockTheme, prefersDark, selectedWindow, minimizedModals | Reactive signals. |

ModalRef<R, D>

afterClosed(): Observable<R> · close(result?) · maximize() · minimize() · restore() · focus() · bringToFront() · componentInstance · contentRef · data · id · minimized / maximized signals.

ModalOptions / component inputs

title, icon, align (leftTop|rightTop|leftBottom|rightBottom), width, height, minWidth, minHeight, offsetX, offsetY, zIndex, closable, maximizable, minimizable, resizable, draggable, outOfBounds, loading, loadingTip, theme (light|dark|auto), contentScrollable, bodyStyle, closeOnNavigation, minimized, maximized, and the v2 additions: blocking, closeOnEscape, closeOnBackdropClick, restoreFocus, ariaLabel, ariaDescribedBy, panelClass, animate, data.

Outputs: onReady, onClose, onResize, onMaximize, onMaximizeRestore, onMinimize, onMinimizeRestore, onSelected, onMove.

Theming

Override any CSS custom property globally (:root / .ng-modal-theme-light) or per dark theme (.ng-modal-theme-dark). Rules ship inside @layer ng2-multi-modal, so your app styles win without specificity hacks.

:root {
  --window-border-radius: 14px;
  --window-title-bar-bg-color: #101828;
  --window-title-bar-color: #fff;
  --focus-ring-color: #22d3ee;
}

Common variables (see styles/theme/_tokens.scss for the full catalog): --window-bg-color, --window-body-bg-color, --window-body-color, --window-border-radius, --window-box-shadow, --selected-window-box-shadow, --window-back-drop-filter, --window-title-bar-* (height, color, bg-color, radius, border, text-align, font-*), --win-icon-*, --close-icon-bg-color-hover, --window-body-padding, --content-radius, --scrollbar-thumb, --back-drop-bg-color, --loading-*, --dock-*, --focus-ring-color.

Built-in themes: default, default-dark, macos, material-design, ant-design, win11, glass. theme: 'auto' follows the OS prefers-color-scheme; animations respect prefers-reduced-motion; below 600px windows go full-screen.

Accessibility

  • role="dialog", aria-modal (in blocking mode), aria-labelledby/aria-label.
  • Window controls are real <button>s with localized aria-labels.
  • Escape closes (when closeOnEscape + closable); a lightweight focus trap and focus restoration run in blocking mode.
  • Keyboard move/resize: focus the title bar, then arrow keys move (Shift = larger step, Alt = resize).

i18n

Built-in en and es. Override or add strings via the config provider:

provideNg2MultiModal({
  language: 'es',
  locale: { es: { close: 'Cerrar ventana' } },
});

Migrating from v1

  • Ng2MultiModalService.create(config)open(content, options) returning a ModalRef (create() still works, deprecated). Options are now plain values, not signals.
  • provideAnimations() is no longer required — animations are pure CSS.
  • Theme file materia-design.cssmaterial-design.css; new win11 and glass themes.
  • New provideNg2MultiModal() for global defaults & i18n, plus NG2_MODAL_DATA for component content.
  • Deep style imports are now declared in exports; a combined ng2-multi-modal/styles.css is available.

Development

npm install
npm run build:lib     # compile styles + library + patch exports
npm test              # library unit tests (headless Chrome)
npm start             # run the demo app (projects/demo)

License

MIT © Adrian Duardo