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

@dgkit/clipboard

v0.1.1

Published

SSR-safe Angular clipboard helper with signal-based operation state.

Readme

@dgkit/clipboard

An SSR-safe Angular clipboard helper with signal-based operation state. The command stays a plain async method; only the state you render is reactive.

  • status()idlecopyingcopied / failed, as a signal
  • ✅ Automatic status reset (configurable), cleared on destroy
  • ✅ Graceful execCommand fallback for insecure contexts / older browsers
  • ✅ SSR-safe — no browser globals touched on the server
  • ✅ Zoneless-friendly — state changes are signal writes, no NgZone

Installation

pnpm add @dgkit/clipboard

Compatibility

Works with Angular 18, 19, 20 and 21.

| Peer dependency | Supported range | | ----------------- | -------------------- | | @angular/core | >=18.0.0 <22.0.0 | | @angular/common | >=18.0.0 <22.0.0 | | rxjs | ^6.5.3 or ^7.4.0 |

Angular and RxJS are peer dependencies — never bundled into the package.

Quick start

import { Component } from '@angular/core';
import { injectClipboard } from '@dgkit/clipboard';

@Component({
  standalone: true,
  template: `
    <button
      (click)="clipboard.copy('value')"
      [disabled]="!clipboard.isSupported()"
    >
      @switch (clipboard.status()) {
        @case ('copied') {
          Copied!
        }
        @case ('failed') {
          Failed
        }
        @case ('copying') {
          Copying…
        }
        @default {
          Copy
        }
      }
    </button>
  `,
})
export class CopyButton {
  protected readonly clipboard = injectClipboard();
}

API

const clipboard = injectClipboard(options?);

await clipboard.copy('value'); // Promise<boolean>

clipboard.status();      // Signal<'idle' | 'copying' | 'copied' | 'failed'>
clipboard.error();       // Signal<unknown>          — last failure cause
clipboard.copied();      // Signal<string | undefined> — last copied value
clipboard.isSupported(); // Signal<boolean>
clipboard.reset();       // back to 'idle' immediately

Options

| Option | Type | Default | Description | | ------------ | --------- | ------- | ----------------------------------------------------------------------- | | resetAfter | number | 2000 | ms before copied/failed reverts to idle. 0 disables auto-reset. | | fallback | boolean | true | Allow the legacy document.execCommand('copy') path. |

copy() resolves true on success and false on failure — it never rejects, so you can safely call it from a template without an unhandled rejection.

Behavior details

Strategy

  1. navigator.clipboard.writeText() when available (secure contexts).
  2. Otherwise, if fallback is enabled, a temporary off-screen <textarea> plus document.execCommand('copy'). The element is always removed, even if the command throws.
  3. If neither is possible, isSupported() is false and copy() resolves false with an Error in error().

Teardown

A pending reset timer is cleared when the injection context is destroyed, and a copy still in flight will not write state into a destroyed host — so no ExpressionChanged surprises and no leaked timers.

SSR

On the server nothing is touched: isSupported() is false and copy() resolves false. No consumer guards required.

License

MIT