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-press-guard

v1.0.2

Published

A React Native & Expo package to prevent double taps and rapid presses. Features async locks, cooldown tracking, and optional haptic feedback.

Readme

react-native-press-guard

A fully type-safe React Native & Expo package to gracefully prevent double taps, rapid presses, and manage async button states. Supports lock modes, cooldowns, progress tracking, and optional built-in haptic feedback.

Zero dependencies*. (*Optionally integrates dynamically with expo-haptics).

Installation

npm install react-native-press-guard
# or
yarn add react-native-press-guard

Features

  • Double-tap prevention: Automatically locks your button until the async onPress promise resolves.
  • Cooldown mode: Prevent rapid tapping by setting a custom millisecond cooldown.
  • Hybrid mode: Wait for the promise to resolve, then enforce the cooldown.
  • Drop-in Component: Use <PressGuard> exactly like a React Native <Pressable>.
  • Custom Hook: Build your own guarded components using usePressGuard.
  • HOC Wrapper: Wrap existing components with withPressGuard(YourComponent).
  • Render Props: Exposes isLocked, progress, and unlock states.
  • Optional Haptics: Automatically uses expo-haptics (if installed in your app) for rich feedback on press, success, and error events.

🚀 Quick Start: <PressGuard> Component

<PressGuard> is a drop-in replacement for the standard <Pressable>.

import { PressGuard } from "react-native-press-guard";
import { Text } from "react-native";

export default function App() {
  const submitData = async () => {
    await fetch("https://api.example.com/submit", { method: "POST" });
  };

  return (
    <PressGuard
      onPress={submitData}
      mode="promise"
      haptics={{ press: "Light", success: "Success" }}
      style={({ pressed }) => [{ opacity: pressed ? 0.7 : 1 }]}
    >
      {({ isLocked }) => <Text>{isLocked ? "Submitting..." : "Submit"}</Text>}
    </PressGuard>
  );
}

🎣 The usePressGuard Hook

If you want more control, use the hook directly inside your own custom button.

import React from "react";
import { TouchableOpacity, Text, View } from "react-native";
import { usePressGuard } from "react-native-press-guard";

export const MySafeButton = ({ onPress }) => {
  const {
    onPress: guardedPress,
    isLocked,
    progress,
  } = usePressGuard(onPress, {
    mode: "cooldown",
    cooldown: 2000,
    haptics: { press: "Medium" },
  });

  return (
    <TouchableOpacity onPress={guardedPress} disabled={isLocked}>
      <Text>Tap Me</Text>
      {isLocked && (
        <View
          style={{
            height: 4,
            width: `${progress * 100}%`,
            backgroundColor: "red",
          }}
        />
      )}
    </TouchableOpacity>
  );
};

📦 HOC: withPressGuard

You can wrap any component that accepts an onPress and disabled prop.

import { Button } from "react-native";
import { withPressGuard } from "react-native-press-guard";

// Now it's perfectly safe!
const SafeButton = withPressGuard(Button, { mode: "promise" });

export default () => (
  <SafeButton title="Press Me" onPress={async () => await doWork()} />
);

🛠 Advanced Usage

⚙️ Progress Animation

When using cooldown or hybrid mode, usePressGuard (and <PressGuard>) exposes a progress value between 0 and 1. This uses requestAnimationFrame to give you butter-smooth updates for building cooldown pie-charts, loaders, or progress bars.

<PressGuard onPress={syncAction} mode="cooldown" cooldown={3000}>
  {({ isLocked, progress }) => (
    <View style={{ opacity: isLocked ? 0.5 : 1 }}>
      <Text>Send Message</Text>
      {isLocked && <Text>Wait {Math.round((1 - progress) * 3)}s</Text>}
    </View>
  )}
</PressGuard>

💫 Haptic Feedback (Optional)

If your app has expo-haptics installed (npx expo install expo-haptics), you can trigger haptic feedback automatically at different lifecycle stages.

Options available: 'Light' | 'Medium' | 'Heavy' | 'Success' | 'Warning' | 'Error'

<PressGuard
  onPress={asyncAction}
  haptics={{
    press: "Medium", // Triggered immediately when pressed
    success: "Success", // Triggered when promise resolves
    error: "Error", // Triggered if promise rejects
    cooldownStart: "Light", // Triggered when cooldown phase begins
    cooldownEnd: "Light", // Triggered when button is unlocked
  }}
>
  <Text>Haptic Button</Text>
</PressGuard>

API Reference

UsePressGuardOptions

| Property | Type | Default | Description | | ----------- | ------------------------------------- | ----------- | ----------------------------------------------------------- | | mode | 'promise' \| 'cooldown' \| 'hybrid' | 'promise' | Behavior mode. | | cooldown | number | 1000 | Cooldown duration in ms. Native to cooldown and hybrid. | | disabled | boolean | false | Disable the press guard completely. | | haptics | object | {} | Haptic feedback configuration object map. | | onSuccess | (res: T) => void | undefined | Callback fired when promise successfully resolves. | | onError | (err: Error) => void | undefined | Callback fired when promise rejects or handler throws. |

mode Types

  • promise: Unlocks automatically when the returned Promise resolves or rejects.
  • cooldown: Regardless of standard functions or promises, locks strictly for the cooldown ms duration after the tap.
  • hybrid: Wait for the promise to resolve, but wait at least the cooldown duration before unlocking.

📝 License

MIT