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

@reeq/react-native-passkit

v0.2.1

Published

React native wrapper over Google Wallet (PayClient) and Apple PassKit. Includes Google Pay and Apple Wallet buttons.

Readme

@reeq/react-native-passkit

React Native wrapper over Google Wallet (PayClient on Android) and Apple PassKit (on iOS). Includes the native "Add to Apple Wallet" and "Save to Google Pay" buttons.

New Architecture only. Starting with 0.2.0 this library is a TurboModule + Fabric component and requires React Native's New Architecture. The legacy bridge (Old Architecture) is no longer supported. If you are on the Old Architecture, stay on 0.1.x.

Note on the 0.2.0 rewrite. The migration from the Old Architecture to the New Architecture (TurboModule + Fabric) was done with the help of an AI assistant (Claude), not hand-written by the maintainer. It builds and runs, but mistakes can slip through — if you hit a bug or something looks off, please open an issue (or a PR). It's genuinely appreciated.

Requirements

| | Minimum | | --- | --- | | React Native | 0.76+ (New Architecture is the default from 0.76) | | New Architecture | Required (newArchEnabled=true / Fabric + TurboModules) | | iOS deployment target | 15.1+ (inherited from React Native) | | Android minSdkVersion | 24+ | | Android compileSdkVersion | 34+ (the library compiles against 36) | | Kotlin | 1.9+ (the library builds with 2.0.21) | | JDK | 17 |

Verified against React Native 0.85.

Upgrading from 0.1.x to 0.2.0

The public JavaScript/TypeScript API is unchangedcanAddPasses, addPass, addPassJWT, containsPass, <AddPassButton />, addPassResultListener, and useAddPassResult keep the exact same signatures. For most apps the upgrade is just bumping the dependency and rebuilding; no code changes are required.

The only breaking change is the platform baseline: 0.2.0 runs on the New Architecture only.

  1. Be on React Native 0.76 or newer with the New Architecture enabled. It is on by default from 0.76. If you explicitly disabled it, re-enable it:
    • Android — android/gradle.properties: newArchEnabled=true
    • iOS — reinstall pods with the New Architecture (default in 0.76+): cd ios && RCT_NEW_ARCH_ENABLED=1 pod install
  2. Android — raise minSdkVersion to at least 24 in android/build.gradle if you are lower. (It was 21 in 0.1.x.) Make sure you build with JDK 17.
  3. iOS — bump your deployment target to 15.1+ if it is lower, then run pod install.
  4. Remove any manual native linking for this package (old react-native link / manually added packages or pods). The module is autolinked on the New Architecture.
  5. Update the dependency and rebuild from scratch:
    yarn add @reeq/react-native-passkit@^0.2.0
    # iOS
    cd ios && pod install && cd ..
    # clear Metro cache so the new view config is picked up
    yarn start --reset-cache

If you previously imported any internal/native module names directly (e.g. NativeModules.PasskitModule), switch to the public exports above — the underlying native module/component names changed for codegen and are not part of the public API.

Installation

npm install @reeq/react-native-passkit
# --- or ---
yarn add @reeq/react-native-passkit

iOS

cd ios && pod install

Android

No extra steps — the module is autolinked. It depends on com.google.android.gms:play-services-pay, which is pulled in automatically.

Usage

import {
  AddPassButton,
  addPass,
  canAddPasses,
  containsPass,
} from '@reeq/react-native-passkit';

const handleAddPass = async () => {
  try {
    const pass = 'BASE_64_ENCODED_PASS';

    if (!(await canAddPasses())) {
      return;
    }

    if (await containsPass(pass)) {
      return;
    }

    await addPass(pass);
  } catch (err) {
    console.log(err);
  }
};

<AddPassButton
  variant={{ android: 'light', ios: 'dark-outline' }}
  onPress={handleAddPass}
/>;

Components

AddPassButton

Platform: iOS / Android

type AndroidVariant = 'dark' | 'light' | 'light-outline';
type IOSVariant = 'dark' | 'dark-outline';

interface AddPassButtonProps extends ViewProps {
  variant?: {
    ios?: IOSVariant; // default: 'dark-outline'
    android?: AndroidVariant; // default: 'dark'
  };
  onPress?: () => void;
}

The button ships with a default size (iOS 260×60, Android 288×44). Override it with style:

import { AddPassButton } from '@reeq/react-native-passkit';
import { Platform } from 'react-native';

<AddPassButton
  variant={{ android: 'light', ios: 'dark' }}
  onPress={() => console.log("I'm pressed")}
  style={{
    height: Platform.select({ android: 44, ios: 60 }),
    width: Platform.select({ android: 288, ios: 260 }),
  }}
/>;

API

addPass(base64EncodedPass: string): Promise<void>

Platform: iOS / Android

import { addPass } from '@reeq/react-native-passkit';

await addPass('BASE_64_ENCODED_PASS');

addPassJWT(passJWT: string): Promise<void>

Platform: Android (no-op on iOS)

import { addPassJWT } from '@reeq/react-native-passkit';

await addPassJWT('JWT_SIGNED_PASS');

canAddPasses(): Promise<boolean>

Platform: iOS / Android

import { canAddPasses } from '@reeq/react-native-passkit';

const canAdd = await canAddPasses(); // true / false

containsPass(base64EncodedPass: string): Promise<boolean>

Platform: iOS (resolves false on Android)

import { containsPass } from '@reeq/react-native-passkit';

const hasPassInWallet = await containsPass('BASE_64_ENCODED_PASS'); // true / false

addPassResultListener(callback): () => void

Platform: iOS / Android

type AddPassResultStatus = 'success' | 'cancelled' | 'error';
type AddPassResultErrorType = 'api' | 'unexpected';

interface AddPassResultEvent {
  status: AddPassResultStatus;
  errorType?: AddPassResultErrorType;
  message?: string;
}

type addPassResultListener = (
  callback: (event: AddPassResultEvent) => void
) => () => void; // returns an unsubscribe function
import { addPassResultListener } from '@reeq/react-native-passkit';
import { useEffect } from 'react';

useEffect(() => {
  const unsubscribe = addPassResultListener((event) => {
    console.log(event); // { status: 'success' }
  });
  return unsubscribe;
}, []);

useAddPassResult(): AddPassResultEvent | undefined

Platform: iOS / Android

A hook wrapper over addPassResultListener.

import { useAddPassResult } from '@reeq/react-native-passkit';

const passAddResult = useAddPassResult();

console.log(passAddResult); // { status: 'success' }

How to create a pass

iOS

  • pass-js — a pass creation library for Node.js

Android

Localization

iOS

By default the iOS add-pass button is not localized. To enable the languages you want to support, add them in Xcode under the Localizations list in the Info tab of the project. The button's localization changes automatically based on the user's locale.

Android

By default Android applies localization for all available languages. To restrict the app to specific languages, set resConfigs in android/app/build.gradle:

android {
  defaultConfig {
    resConfigs "en", "da", "uk" // English, Danish, Ukrainian
  }
}

Contributing

License

MIT


Made with create-react-native-library