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

react-native-spoiler-view

v1.0.0

Published

Telegram-style spoiler effect for React Native with native particle animations

Readme

react-native-spoiler-view

Telegram-style spoiler content for React Native, rendered with native particles.

Features

  • Controlled and uncontrolled reveal state
  • Touch-origin circular reveal
  • Three particle depth/opacity tiers
  • Hidden descendants are blocked from touch, VoiceOver, and TalkBack
  • Runtime-safe configuration with bounded particle work
  • Platform-native particle rendering on iOS and Android
  • Shared Android ambient texture work instead of per-view simulation
  • Core Animation ambient particles on iOS

Compatibility

The package is maintained against two integration lanes:

| Lane | React Native | React | Reanimated | Gesture Handler | | --- | --- | --- | --- | --- | | Legacy | 0.73.x | 18.x | 3.15.5 | 2.18.x | | Current | 0.86.x | 19.x | 4.5.x + Worklets 0.10.x | 3.x |

Reanimated 4 requires React Native's New Architecture and react-native-worklets. Select dependency versions that support your React Native version rather than installing unrelated latest majors.

Installation

Install the component and the compatible native peers:

npm install react-native-spoiler-view \
  react-native-reanimated \
  react-native-gesture-handler

For Reanimated 4, also install Worklets:

npm install react-native-worklets

React Native Community CLI apps using Reanimated 4 must put the Worklets plugin last in babel.config.js:

module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: ['react-native-worklets/plugin'],
};

Wrap the application near its root with GestureHandlerRootView:

import { GestureHandlerRootView } from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <YourApp />
    </GestureHandlerRootView>
  );
}

Follow the native installation instructions for Reanimated and Gesture Handler, then run CocoaPods for iOS.

Usage

Uncontrolled

import { Text } from 'react-native';
import { SpoilerView } from 'react-native-spoiler-view';

<SpoilerView accessibilityRevealLabel="Hidden message">
  <Text>This is a secret message.</Text>
</SpoilerView>;

The component owns its reveal state. Tapping toggles between hidden and revealed.

Controlled

const [revealed, setRevealed] = useState(false);

<SpoilerView
  revealed={revealed}
  onReveal={() => setRevealed(true)}
  onHide={() => setRevealed(false)}
  accessibilityRevealLabel="Hidden account number"
>
  <Text>1234 5678 9012 3456</Text>
</SpoilerView>;

In controlled mode, callbacks request a state change. The component animates only when the revealed prop changes, so a parent may accept or reject the request without visual desynchronization.

Custom particles

<SpoilerView
  config={{
    particleCount: 300,
    particleColor: 'rgba(255, 100, 100, 1)',
    particleSizeRange: [0.5, 1.5],
    revealDuration: 400,
  }}
>
  <Image source={secretImage} />
</SpoilerView>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | children | ReactNode | required | Content hidden by the spoiler | | revealed | boolean | uncontrolled | Parent-owned reveal state | | enabled | boolean | true | Enables reveal/hide gestures | | onReveal | () => void | — | Reveal request callback | | onHide | () => void | — | Hide request callback | | config | Partial<SpoilerConfig> | — | Particle and animation overrides | | style | StyleProp<ViewStyle> | — | Container style | | accessibilityRevealLabel | string | Hidden content | Label announced while hidden | | accessibilityRevealHint | string | Double tap to reveal | Reveal action hint | | accessibilityHideLabel | string | Hide content | Action label exposed while revealed | | accessibilityHideHint | string | Double tap to hide | Hide action hint |

Configuration

interface SpoilerConfig {
  particleCount: number;                // Default target/cap 180; maximum 1000
  particleDensity?: number;             // Default 0.055 per logical px², capped at 1000 total
  particleSizeRange: [number, number];  // Default [0.45, 0.8]
  particleColor: string;                // Default rgba(80, 80, 80, 1)
  overlayColor: string;                 // Default transparent
  noiseSpeed: number;                   // Ambient motion speed, default 0.3
  driftAmount: number;                  // Maximum ambient drift, default 1
  revealDuration: number;               // Default 500 ms
}

Unsafe numeric inputs are normalized at runtime. Particle work is always capped by MAX_PARTICLE_COUNT, which is exported for consumers that expose configuration controls. Providing particleCount without particleDensity opts into a fixed target. With density, particleCount is the per-view cap, keeping the canonical dust adaptive without allowing a large spoiler to monopolize the frame budget.

Development

npm install
npm run check

The example application is the maintained iOS and Android integration harness.

License

MIT