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

@rizalsk/react-content-guard

v1.0.2

Published

React/Next.js components for content protection: clipboard guard, screen protection, copy prevention, and drag-drop blocking.

Readme

@rizalsk/react-content-guard

React/Next.js components for protecting content from copying, screen recording, drag-drop, and clipboard misuse.

Requirements

This library has no bundled dependencies. react and react-dom are expected to already be present in your project. If you haven't installed zustand yet, add it:

npm install zustand

| Package | Version | |-------------|---------| | react | >=18 | | react-dom | >=18 | | zustand | >=5 |

Installation

npm install @rizalsk/react-content-guard

Changelog

v1.0.2

AppClipboardBoundary

  • Fixed paste priority: OS clipboard now takes precedence over internal clipboard. Since internal copies always wipe the OS clipboard, any non-empty OS clipboard text is guaranteed to be the most recently copied content — it will be pasted instead of stale internal clipboard data.
  • Added onCut handler — Ctrl/Cmd+X now correctly cuts text from editable targets (input, textarea, contenteditable) while routing the content to the internal clipboard.

InternalCopyAliasBoundary

  • Fixed Ctrl/Cmd+X (cut): text is now stored internally and deleted from the source, instead of only being copied.
  • Added Cut and Delete actions to the right-click context menu.
    • Cut — copies selection to internal clipboard, wipes OS clipboard, and deletes the selected text (only enabled on editable targets).
    • Delete — removes the selected text without copying (only enabled on editable targets).
    • Copy/Cut/Delete are greyed out when disabled (no selection, or target is read-only).

Components

ScreenProtector

Protects content from screen recording and DevTools inspection. Blurs content when a screenshot is detected and shows an overlay when DevTools is open.

import { ScreenProtector } from '@rizalsk/react-content-guard'

<ScreenProtector
  enabled={true}
  latchTitle="Protected Content"
  latchMessage="Click here to display the content again."
  devTools={true}
  devtoolsTitle="Restricted Access"
  devtoolsMessage="Close developer tools to continue."
>
  {children}
</ScreenProtector>

| Prop | Type | Default | Description | |------|------|---------|-------------| | enabled | boolean | true | Enable or disable all protection | | devTools | boolean | true | Detect and block DevTools | | devtoolsTitle | string | "Protected Content" | Overlay title when DevTools detected | | devtoolsMessage | string | "Developer tools detected..." | Overlay message | | latchTitle | string | "Content Hidden" | Title shown on screenshot latch overlay | | latchMessage | string | "Click to show the content again." | Message on latch overlay | | latchBackgroundVariant | ProtectorCanvasVariant | "grid" | Background pattern of overlay | | latchBackgroundColor | string | "#0b0f1a" | Overlay background color | | latchPatternColor | string | "#4f9eff" | Overlay pattern/foreground color | | latchPatternOpacity | number | 0.08 | Overlay pattern opacity (0–1) | | latchAnimationPaused | boolean | false | Pause the overlay animation | | overlayTextColor | string | "#f5f5f5" | Text and icon color for all overlays | | recordingFlicker | boolean | true | Enable anti-recording watermark | | recordingFlickerMode | "auto" \| "temporal" \| "chromatic" \| "scan" \| "static" | "auto" | Flicker mode | | recordingFlickerIntensity | number | 0.06 | Watermark intensity (0–1) | | recordingFlickerText | string | "PROTECTED" | Watermark text |


AppClipboardBoundary

Intercepts copy, cut, and paste events within its boundary, routing them through an internal clipboard store (backed by zustand). Prevents content from leaking to the OS clipboard.

Paste priority: OS clipboard always wins when it has content. Internal clipboard is used as a fallback. This ensures that text copied outside the app (after an internal copy) is always pasted correctly.

import { AppClipboardBoundary } from '@rizalsk/react-content-guard'

<AppClipboardBoundary
  enabled={true}
  onWarning={(msg) => console.warn(msg)}
>
  {children}
</AppClipboardBoundary>

| Prop | Type | Default | Description | |------|------|---------|-------------| | enabled | boolean | true | Enable clipboard interception | | className | string | — | CSS class for wrapper div | | onWarning | (msg: string) => void | console.warn | Called when paste fails (no content or non-editable target) |

Escape hatch: Add data-allow-native-copy="true" or data-allow-native-paste="true" to any child element to bypass interception for that element.


InternalCopyAliasBoundary

Intercepts copy and cut events, blocks the OS clipboard, and routes text to the internal store. Provides a custom right-click context menu with Copy, Cut, and Delete actions.

import { InternalCopyAliasBoundary } from '@rizalsk/react-content-guard'

<InternalCopyAliasBoundary enabled={true} restoreDelay={100}>
  {children}
</InternalCopyAliasBoundary>

| Prop | Type | Default | Description | |------|------|---------|-------------| | enabled | boolean | true | Enable interception | | className | string | — | CSS class for wrapper div | | restoreDelay | number | 100 | Delay (ms) before wiping OS clipboard after copy/cut |

Context menu actions:

| Action | Keyboard | Editable only | Description | |--------|----------|---------------|-------------| | Copy | Ctrl/Cmd+C | No | Copies selection to internal clipboard, wipes OS clipboard | | Cut | Ctrl/Cmd+X | Yes | Copies selection to internal clipboard, deletes source text, wipes OS clipboard | | Delete | — | Yes | Deletes selected text without copying |

Copy/Cut/Delete are greyed out when no text is selected, or when the target is read-only (for Cut/Delete).

Escape hatch: Add data-allow-native-copy="true" to bypass copy/cut interception, or data-allow-native-contextmenu="true" to allow the native right-click menu.


CopyExtensionProtector

Prevents browser extensions and native events from reading selected content by clearing the selection after a short delay.

import { CopyExtensionProtector } from '@rizalsk/react-content-guard'

<CopyExtensionProtector enabled={true} clearDelay={120}>
  {children}
</CopyExtensionProtector>

| Prop | Type | Default | Description | |------|------|---------|-------------| | enabled | boolean | true | Enable protection | | className | string | — | CSS class for wrapper div | | clearDelay | number | 120 | Delay (ms) before clearing selection |

Escape hatch: Add data-allow-native-copy="true" to any child to bypass selection clearing for that element.


CopyProtector

Simple component that blocks copy events and disables text selection via CSS.

import { CopyProtector } from '@rizalsk/react-content-guard'

<CopyProtector
  enabled={true}
  onWarning={(msg) => console.warn(msg)}
>
  {children}
</CopyProtector>

| Prop | Type | Default | Description | |------|------|---------|-------------| | enabled | boolean | true | Enable copy blocking | | className | string | — | CSS class for wrapper div | | onWarning | (msg: string) => void | console.warn | Called when a copy attempt is blocked |


NoDragDropBoundary

Prevents drag-and-drop of content out of the boundary.

import { NoDragDropBoundary } from '@rizalsk/react-content-guard'

<NoDragDropBoundary enabled={true} className="my-boundary">
  {children}
</NoDragDropBoundary>

| Prop | Type | Default | Description | |------|------|---------|-------------| | enabled | boolean | true | Enable drag-drop blocking | | className | string | — | CSS class for wrapper div |

Escape hatch: Add data-allow-drag="true" to any child element to allow dragging that specific element.


Hooks

useSecureCopy

Copies data to the internal clipboard store and wipes the OS clipboard so the content cannot be pasted outside the application.

import { useSecureCopy } from '@rizalsk/react-content-guard'

function MyComponent() {
  const { secureCopy } = useSecureCopy()

  const handleCopy = () => {
    secureCopy({
      source: 'global',
      type: 'text',
      text: 'sensitive content',
    })
  }

  return <button onClick={handleCopy}>Copy</button>
}

useAppClipboardStore

Direct access to the internal clipboard zustand store. Useful for reading or clearing clipboard state from anywhere in the app.

import { useAppClipboardStore } from '@rizalsk/react-content-guard'

function MyComponent() {
  const payload = useAppClipboardStore((s) => s.payload)
  const clearClipboard = useAppClipboardStore((s) => s.clearClipboard)

  return (
    <div>
      <p>Internal clipboard: {payload?.text ?? '(empty)'}</p>
      <button onClick={clearClipboard}>Clear</button>
    </div>
  )
}

Full Example

import {
  ScreenProtector,
  AppClipboardBoundary,
  NoDragDropBoundary,
  InternalCopyAliasBoundary,
  CopyProtector,
} from '@rizalsk/react-content-guard'

<ScreenProtector
  latchBackgroundVariant="rings"
  latchBackgroundColor="#dbddf1ff"
  latchPatternColor="#0e719eff"
  overlayTextColor="#30323fff"
  latchPatternOpacity={0.23}
  latchAnimationPaused={false}
  enabled={true}
>
  <AppClipboardBoundary enabled={true}>
    <NoDragDropBoundary className="nara-no-drag" enabled={true}>
      <InternalCopyAliasBoundary enabled={true} restoreDelay={100}>
        <NoDragDropBoundary className="nara-no-drag" enabled={true}>
          <CopyProtector className="h-100" enabled={true}>
            {children}
          </CopyProtector>
        </NoDragDropBoundary>
      </InternalCopyAliasBoundary>
    </NoDragDropBoundary>
  </AppClipboardBoundary>
</ScreenProtector>

onWarning Callback

AppClipboardBoundary and CopyProtector accept an onWarning prop instead of depending on any UI library. Wire it to your preferred notification system:

// with react-hot-toast
import toast from 'react-hot-toast'
<AppClipboardBoundary onWarning={(msg) => toast(msg)}>

// with sonner
import { toast } from 'sonner'
<AppClipboardBoundary onWarning={(msg) => toast.warning(msg)}>

// with antd
import { App } from 'antd'
const { message } = App.useApp()
<AppClipboardBoundary onWarning={(msg) => message.warning(msg)}>

// default — console.warn (no UI notification)
<AppClipboardBoundary>

License

MIT © rizalsk