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

@khafagaa/react-native-sheet-pro

v1.0.1

Published

A flexible sheet/modal library for React Native. Supports bottom sheets, center popups, and position-based content (top, center, bottom).

Readme

Sheet Library

A flexible, reusable sheet/modal library for React Native. Supports bottom sheets, middle popups, and top toasts. Position your sheet content anywhere — top, center, or bottom — using justifyContent in your component styles.

Installation

npm install @khafagaa/react-native-sheet-pro

OR

yarn add @khafagaa/react-native-sheet-pro

Dependencies

Make sure you have these peer dependencies installed:

# npm
npm install react-native-gesture-handler react-native-reanimated @react-native-community/blur

# or yarn
yarn add react-native-gesture-handler react-native-reanimated @react-native-community/blur

React Native & Reanimated Compatibility

| React Native | Reanimated | Worklets | Babel plugin | | ----------------- | ---------- | -------- | -------------------------------- | | 0.74 (Legacy) | 3.x | — | react-native-reanimated/plugin | | 0.78–0.82 | 4.1.x | 0.5.x | react-native-worklets/plugin | | 0.80–0.84 | 4.2.x | 0.7.x | react-native-worklets/plugin |

RN 0.74: Use Reanimated 3.x. No react-native-worklets needed. Use react-native-reanimated/plugin in Babel.

RN 0.78–0.82 (e.g. 0.79): Use Reanimated 4.1.x + Worklets 0.5.x:

yarn add react-native-reanimated@^4.1.0 react-native-worklets@^0.5.0

RN 0.80+: Use Reanimated 4.2.x + Worklets 0.7.x:

yarn add react-native-reanimated@^4.2.0 react-native-worklets@^0.7.0

For Reanimated 4.x, add the worklets plugin to babel.config.js (as a separate plugin, not inside module-resolver):

plugins: [
  'react-native-worklets/plugin',
  // ... other plugins like module-resolver
];

Quick Start

1. Define Your Enums

// enums.ts
export enum SheetEnums {
  ALERT = 'Alert',
  CONFIRM = 'Confirm',
  TOAST = 'Toast',
}

2. Create Your Sheet Components

// sheets/AlertSheet.tsx
const AlertSheet = ({title, message, onClose}) => (
  <View style={styles.container}>
    <Text>{title}</Text>
    <Text>{message}</Text>
    <Button title="Close" onPress={onClose} />
  </View>
);

3. Set Up in App

import {SheetHandler, SheetHandlerRef} from '@khafagaa/react-native-sheet-pro';

<SheetHandler
  ref={SheetHandlerRef}
  sheetEnums={SheetEnums}
  sheetComponents={{
    [SheetEnums.ALERT]: AlertSheet,
    [SheetEnums.CONFIRM]: ConfirmSheet,
  }}
  defaultSheetConfig={{
    [SheetEnums.ALERT]: {disablePan: false, blur: true},
    [SheetEnums.CONFIRM]: {disablePan: true, blur: true},
  }}
/>;

4. Show Sheets

import {showSheet, hideSheet} from '@khafagaa/react-native-sheet-pro';

// Show
showSheet({
  type: SheetEnums.ALERT,
  props: {
    title: 'Hello',
    message: 'World',
    onClose: () => hideSheet(),
  },
});

// Hide
hideSheet();

Position Examples

You can place sheet content anywhere on the screen by using justifyContent in your component's container style. Here are three sample components for each position:

1. Top Sheet (flex-start)

Content anchored at the top of the modal. Ideal for banners, notifications, or top-aligned actions.

// TopSheetExample.tsx
import React from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import {hideSheet} from '@khafagaa/react-native-sheet-pro';

const TopSheetExample = () => (
  <SafeAreaView style={styles.container}>
    <View style={styles.content}>
      <Text style={styles.title}>Top Sheet</Text>
      <Text style={styles.subtitle}>Content at flex-start</Text>
      <TouchableOpacity onPress={() => hideSheet()}>
        <Text style={styles.button}>Close</Text>
      </TouchableOpacity>
    </View>
  </SafeAreaView>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'flex-start', // ← Top position
    alignItems: 'center',
    paddingTop: 48,
  },
  content: {
    backgroundColor: 'white',
    padding: 24,
    borderRadius: 16,
    minWidth: 280,
    alignItems: 'center',
  },
  title: {fontSize: 18, fontWeight: '600', marginBottom: 8},
  subtitle: {fontSize: 14, color: '#666', marginBottom: 16},
  button: {fontSize: 16, color: '#007AFF', fontWeight: '500'},
});

Top Sheet


2. Center Sheet (center)

Content centered in the modal. Ideal for dialogs, confirmations, or alerts.

// CenterSheetExample.tsx
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {hideSheet} from '@khafagaa/react-native-sheet-pro';

const CenterSheetExample = () => (
  <View style={styles.container}>
    <View style={styles.content}>
      <Text style={styles.title}>Center Sheet</Text>
      <Text style={styles.subtitle}>Content at center</Text>
      <TouchableOpacity onPress={() => hideSheet()}>
        <Text style={styles.button}>Close</Text>
      </TouchableOpacity>
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center', // ← Center position
    alignItems: 'center',
  },
  content: {
    backgroundColor: 'white',
    padding: 24,
    borderRadius: 16,
    minWidth: 280,
    alignItems: 'center',
  },
  title: {fontSize: 18, fontWeight: '600', marginBottom: 8},
  subtitle: {fontSize: 14, color: '#666', marginBottom: 16},
  button: {fontSize: 16, color: '#007AFF', fontWeight: '500'},
});

Center Sheet


3. Bottom Sheet (flex-end)

Content anchored at the bottom. Ideal for action sheets, toasts, or bottom-anchored content.

// BottomSheetExample.tsx
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {hideSheet} from '@khafagaa/react-native-sheet-pro';

const BottomSheetExample = () => (
  <View style={styles.container}>
    <View style={styles.content}>
      <Text style={styles.title}>Bottom Sheet</Text>
      <Text style={styles.subtitle}>Content at flex-end</Text>
      <TouchableOpacity onPress={() => hideSheet()}>
        <Text style={styles.button}>Close</Text>
      </TouchableOpacity>
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'flex-end', // ← Bottom position
  },
  content: {
    backgroundColor: 'white',
    padding: 44,
    borderRadius: 16,
    minWidth: 280,
    alignItems: 'center',
  },
  title: {fontSize: 18, fontWeight: '600', marginBottom: 8},
  subtitle: {fontSize: 14, color: '#666', marginBottom: 16},
  button: {fontSize: 16, color: '#007AFF', fontWeight: '500'},
});

Bottom Sheet


Registering all three

In this project, the sheet setup lives in App.tsxAppWrapperBottomSheetWrapper. Add the position examples (Top, Center, Bottom) to your SheetHandler in BottomSheetWrapper:

import {
  SheetHandler,
  SheetHandlerRef,
  TopSheetExample,
  CenterSheetExample,
  BottomSheetExample,
} from '@khafagaa/react-native-sheet-pro';

enum SheetEnums {
  TOP = 'Top',
  CENTER = 'Center',
  BOTTOM = 'Bottom',
}

<SheetHandler
  ref={SheetHandlerRef}
  sheetEnums={SheetEnums}
  sheetComponents={{
    [SheetEnums.TOP]: TopSheetExample,
    [SheetEnums.CENTER]: CenterSheetExample,
    [SheetEnums.BOTTOM]: BottomSheetExample,
  }}
/>;

Pause Functionality

The pause feature lets you block the next sheet from showing when needed. Use it when another part of your app needs to prevent sheets from appearing (e.g. during navigation, transitions, or critical flows).

Purpose

  • Navigation: Block sheets during screen transitions
  • Critical UI: Prevent sheets when another overlay or flow is active
  • Flow control: Temporarily suppress sheet display in specific scenarios

How it works

  1. Set the pause flag before the sheet would normally show
  2. The next showSheet() call is blocked and the flag is cleared
  3. Later showSheet() calls work as usual

Setup

Pass storageHelper and pauseStorageKey to SheetHandler:

import {appStorage} from '@helpers/mmkv';
import {AppStorageEnums} from '@constants/enums';

<SheetHandler
  storageHelper={{
    getBoolean: (key: string) => appStorage.getBoolean(key) ?? false,
    set: (key: string, value: boolean) => appStorage.set(key, value),
  }}
  pauseStorageKey={AppStorageEnums.PAUSE_ALL_BOTTOM_SHEET}
  // ... other props
/>;

Usage

To block the next sheet:

import {appStorage} from '@helpers/mmkv';
import {AppStorageEnums} from '@constants/enums';

// Before navigation or when you want to block the next sheet
appStorage.set(AppStorageEnums.PAUSE_ALL_BOTTOM_SHEET, true);
navigation.navigate('SomeScreen');

Example: block during navigation

const onNavigateAway = () => {
  appStorage.set(AppStorageEnums.PAUSE_ALL_BOTTOM_SHEET, true);
  navigation.navigate('OtherScreen');
};

If a sheet tries to show right before or during this navigation, it will be blocked and the flag will be cleared automatically.

Benefits of sheetEnums

The sheetEnums prop enables validation that helps catch configuration errors early:

  1. Missing component check — The library compares sheetEnums with sheetComponents. If an enum value has no matching component, an alert is shown listing the missing ones (e.g. "No component provided for sheet enum: AlertSheet").

  2. Wrong type at runtime — If you call showSheet({ type: 'UnknownType' }) with a type that has no component, a toast appears: "No component found for sheet type" instead of a blank or broken sheet.

Sheet Warning - Missing Component

No component found - Toast

API Reference

SheetHandler Props

| Prop | Type | Required | Description | | -------------------- | ------------------------ | -------- | ------------------------------------------------------------------------------------- | | sheetEnums | Record<string, T> | ✅ | Your enum object. Used to validate sheetComponents and surface missing/wrong types. | | sheetComponents | Record<T, Component> | ✅ | Mapping of enum to components | | defaultSheetConfig | Record<T, SheetConfig> | ❌ | Default config per sheet | | storageHelper | {getBoolean, set} | ❌ | Storage for pause functionality | | pauseStorageKey | string | ❌ | Storage key (default: 'PAUSE_ALL_SHEETS') |

SheetConfig

{
  disablePan?: boolean;  // Disable swipe-to-close (default: false)
  blur?: boolean;        // Use blur backdrop (default: false)
}

Sheet Listeners

Subscribe to sheet show/hide events for analytics, state sync, or pause/resume logic:

import {
  registerSheetShowListener,
  registerSheetHideListener,
} from '@khafagaa/react-native-sheet-pro';

useEffect(() => {
  const unsubscribeShow = registerSheetShowListener(sheetState => {
    if (!sheetState?.type) return;
    // Sheet opened: track analytics, pause video, etc.
  });

  const unsubscribeHide = registerSheetHideListener(() => {
    // Sheet closed: resume video, refresh data, reset form
  });

  return () => {
    unsubscribeShow();
    unsubscribeHide();
  };
}, []);

Demo: See src/hooks/useSheetListenersDemo.ts in this project for a working example.

Override Config Per Call

showSheet({
  type: SheetEnums.ALERT,
  props: {
    title: 'Hello',
    // Override config
    disablePanGestureHandler: false,
    blur: true,
  },
});

Exports

import {
  // Helper functions (recommended)
  showSheet,
  hideSheet,
  getCurrentSheet,

  // Main components
  SheetHandler,
  SheetHandlerRef,
  Sheet,

  // Factory (for advanced usage)
  createSheetLibrary,

  // Listeners
  registerSheetShowListener,
  registerSheetHideListener,

  // Types
  SheetConfig,
  CurrentSheetState,
  SheetHandlerRefType,
  SheetProviderProps,
  ShowSheetParams,
} from '@khafagaa/react-native-sheet-pro';