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

reanimated-pause-state

v0.1.1

Published

Pause Reanimated animations and inspect their state at any frame

Readme

reanimated-pause-state

Pause Reanimated animations and capture state snapshots for debugging and design review.

What it does

  • Pause/resume animations created with Reanimated factory functions
  • Capture animation state snapshots with current values, timing, and source locations
  • Filter snapshots by component name, file, or line proximity
  • Generate prompt-ready markdown for LLM-assisted debugging

Zero overhead in production - all functionality is gated behind __DEV__.

Getting Started

1. Install

npm install reanimated-pause-state

2. Add Babel plugin

// babel.config.js
module.exports = {
  presets: ['babel-preset-expo'],
  plugins: [
    'reanimated-pause-state/babel',  // MUST be first
    'react-native-reanimated/plugin', // MUST be last
  ],
};

3. Clear cache and restart

npx expo start --clear

4. Add pause control to your app

import { pause, resume, getSnapshotMarkdown } from 'reanimated-pause-state';
import * as Clipboard from 'expo-clipboard';

// In a dev menu, button, or shake handler:
const handlePause = () => {
  pause();
  const markdown = getSnapshotMarkdown();
  Clipboard.setStringAsync(markdown);
  Alert.alert('Copied', 'Animation state copied to clipboard');
};

Now paste into Claude or your team chat with full animation context.

Usage

import {
  pause,
  resume,
  toggle,
  snapshotNow,
  getSnapshotMarkdown,
  isInstalled,
  isPaused
} from 'reanimated-pause-state';

// Verify setup
console.log('Plugin installed:', isInstalled());

// Pause animations
pause();

// Take a snapshot of current animation state
const snapshot = snapshotNow();
console.log(snapshot);
// {
//   timestamp: 1706123456789,
//   animations: [
//     {
//       sharedValueName: 'translateX',
//       type: 'repeat',
//       values: { from: 0, to: 200, current: 127.5 },
//       callsite: { file: 'MyScreen.tsx', line: 42 },
//       ...
//     }
//   ]
// }

// Get markdown for pasting into Claude/LLM
const markdown = getSnapshotMarkdown();

// Resume
resume();

API

Core Functions

| Function | Returns | Description | |----------|---------|-------------| | isInstalled() | boolean | Check if Babel plugin is configured | | isPaused() | boolean | Check if animations are paused | | pause() | PauseSnapshot | Pause all animations, return snapshot | | resume() | void | Resume all animations | | toggle() | PauseSnapshot \| null | Toggle pause state |

Snapshot Functions

snapshotNow(opts?: SnapshotOptions): PauseSnapshot

Take a snapshot of current animation state with optional filtering.

// All animations
snapshotNow()

// Filter by file
snapshotNow({ filterFile: 'MyScreen.tsx' })

// Filter by file + line proximity
snapshotNow({
  filterFile: 'MyScreen.tsx',
  filterLine: 42,
  proximityThreshold: 200
})

// Limit results
snapshotNow({ maxAnimations: 5 })

getSnapshotMarkdown(opts?: SnapshotOptions): string

Get snapshot as prompt-ready markdown.

const markdown = getSnapshotMarkdown({ filterFile: 'MyScreen.tsx' });
// ## Animation State at Pause
//
// ### `translateX` (repeat)
//
// | Property | Value |
// |----------|-------|
// | **Current** | `127.50` |
// | From → To | 0 → 200 |
// | Progress | 63.7% |
// | Location | `MyScreen.tsx:42` |

getSnapshotJSON(opts?: SnapshotOptions): string

Get snapshot as JSON string for logging or export.

const json = getSnapshotJSON({ filterFile: 'MyScreen.tsx' });
console.log(json);
// {
//   "timestamp": 1706123456789,
//   "animations": [...],
//   "totalCount": 3,
//   "summary": "3 animation(s) captured"
// }

SnapshotOptions

| Option | Type | Default | Description | |--------|------|---------|-------------| | filterComponent | string | - | Partial match on React component name (case-insensitive) | | filterFile | string | - | Partial match on callsite file path | | filterLine | number | - | Center line for proximity filter (requires filterFile) | | proximityThreshold | number | 200 | Max line distance from filterLine | | maxAnimations | number | 20 | Maximum animations to return |

Types

interface PauseSnapshot {
  timestamp: number;
  timestampISO: string;
  animations: AnimationSnapshot[];
  totalCount: number;
  summary: string;
}

interface AnimationSnapshot {
  id: string;
  type: 'timing' | 'spring' | 'decay' | 'repeat' | 'sequence' | 'delay';
  sharedValueName?: string;  // e.g., 'translateX', 'scale'
  componentName?: string;    // React component where animation is defined
  callsite: {
    file: string;
    line: number;
    column?: number;
  };
  values: {
    from: number;
    to: number;
    current: number;  // actual value at snapshot time
  };
  timing: {
    startTime: number;
    elapsed: number;
    duration?: number;
    progress?: number;  // 0-100 for timing animations
  };
  config: { type: string; config: Record<string, any> };
  description: string;
}

Filtering

By Component Name

Find animations defined in a specific React component:

snapshotNow({ filterComponent: 'PulsingCircle' })

Matching is case-insensitive and partial, so 'pulsing' would also match.

By File

Find animations defined in a specific file:

snapshotNow({ filterFile: 'MyScreen.tsx' })

By File + Line Proximity

Narrow down to animations near a specific line:

snapshotNow({
  filterFile: 'MyScreen.tsx',
  filterLine: 42,
  proximityThreshold: 200  // within 200 lines
})

How it Works

  1. Babel plugin wraps animation factories (withTiming, withSpring, etc.) to track metadata including component name
  2. Runtime captures SharedValue references and registers animations with their source context
  3. On pause reads current values from SharedValues (synced from UI thread)
  4. Filtering matches by component name (primary), file path, or line proximity

Instrumented Functions

  • withTiming
  • withSpring
  • withDecay
  • withRepeat
  • withSequence
  • withDelay

Best Practices for Accurate Tracking

For the best animation tracking experience, follow these tips:

1. Use Named Function Components

The babel plugin captures the enclosing function name. Named components enable accurate filtering.

// Good - named component
function PulsingCircle() {
  const scale = useSharedValue(1);
  // ...
}

// Good - named const
const PulsingCircle = () => {
  const scale = useSharedValue(1);
  // ...
};

// Less ideal - anonymous inline
export default () => {
  const scale = useSharedValue(1);
  // ...
};

2. Use Descriptive SharedValue Names

SharedValue variable names appear in snapshots, making debugging easier.

// Good - descriptive names
const translateX = useSharedValue(0);
const opacity = useSharedValue(1);
const scale = useSharedValue(1);

// Harder to debug
const sv1 = useSharedValue(0);
const val = useSharedValue(1);

3. Keep Animations Close to Their SharedValues

The babel plugin tracks the file and line where animations are defined. Keep them together for accurate filtering.

// Good - animation near SharedValue
function MyComponent() {
  const translateX = useSharedValue(0);

  const animate = () => {
    translateX.value = withSpring(100);  // Line 5
  };
}

// Split across files is harder to track
// animation-utils.ts
export const startAnimation = (sv) => {
  sv.value = withSpring(100);  // Tracked here, not in component
};

4. Babel Plugin Order Matters

The plugin MUST run before Reanimated's plugin:

// babel.config.js
module.exports = {
  plugins: [
    'reanimated-pause-state/babel',  // First!
    'react-native-reanimated/plugin', // Last!
  ],
};

5. SharedValues Passed as Props

When SharedValues are passed as props, animations are tracked at the call site:

function Parent() {
  const scale = useSharedValue(1);
  return <Child scale={scale} />;
}

function Child({ scale }) {
  const animate = () => {
    scale.value = withSpring(2);  // Tracked as "Child" component
  };
}

Annotating Child will show the animation. Annotating Parent won't (the filter won't match, but you'll still see all animations with their SharedValue names).

Limitations

  • Only affects animations created via instrumented factory calls
  • Does not pause native animations (Lottie, navigation transitions)
  • Dynamic toValue (computed at runtime) won't be captured in config
  • Spring animations don't have duration/progress (physics-based)

Requirements

  • React Native 0.70+
  • react-native-reanimated >= 3.0.0 (peer dependency)
// package.json
{
  "dependencies": {
    "react-native-reanimated": "^3.0.0",
    "reanimated-pause-state": "^0.1.0"
  }
}

License

MIT