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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@anhnch/react-native-pincode

v1.3.0

Published

Pin Code component for React Native

Downloads

592

Readme

React Native Pin Code

This component is inspired by https://github.com/jarden-digital/react-native-pincode. The layout looks similar but I rewrite in typescript, simpler, organized and just enough options. I also add the Reset PIN code feature which allows users to remove the pin code if they fotgot.

The options look intimidating but don't worry. Almost all of them are optional.

NOTE:

  • The component doesn't block the app and asks the user to enter code for you. It just renders the Enter PIN screen, and you should style the component to cover the whole screen with absolute position, for instance. The best way is to place the component in your App component and use the state management tool to switch the visibility. Check the example below.
  • The component doesn't handle persisting the pin code for you, you have to use AsyncStorage, MMKV, KeyChain on your own.

Basic usage

import { useMMKV, useMMKVString } from 'react-native-mmkv';
import { PinCode, PinCodeT } from '@anhnch/react-native-pincode';

const Screen = () => {
  const mmkv = useMMKV();
  const [pin, setPin] = useMMKVString('@pin', mmkv);
  const [pinMode, setPinMode] = useState(PinCodeT.Modes.Enter);
  const [pinVisible, setPinVisible] = useState(pin ? true : false);

  return <View>
    <PinCode pin={pin} mode={pinMode} visible={pinVisible} 
      styles={{ 
        main: { ...StyleSheets.absoluteFillObject, zIndex: 99 }
      }}
      onSet={newPin => {
        setPin(newPin);
        setPinVisible(false);
      }}
      onSetCancel={() => setPinVisible(false)}
      onReset={() => setPin(undefined)}
      onEnter={() => setPinVisible(false)}
    />
  </View>
}

Properties

| Name | Description | Required | Default | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | | visible | Show/hide the component | true | false | | mode | The component has 4 modes:enter: user has to enter the PIN to accessset: set up new PINlocked: lock the user from accessing and count down.reset: allow user to remove PIN. | true | enter | | options | Specify how the component works. Check the options below | false | | | textOptions | Customize the text content of the PinCode if you want to change the language or content. Check the options below | false | | | styles | Setting the styles to customize how PinCode should look. Check the style options below | false | | | onEnter | Triggered when the mode is enter and the user has entered the correct PIN. The application should hide the PinCode component and show its own content.Parameters:pin (string, optional): the entered PIN | true | | | onSet | Triggered when the user has successfully set the new pin. The application should persist the pin in this event.Parameters:pin (string, optional): the set PIN | true | | | onSetCancel | Triggered when the mode is set and user cancels the setting pin. The app should hide the pin code | true | | | onReset | Called when the user has confirmed to reset the pin. The application may clear the content, history, anything that belongs to the user if necessary | false | | | onModeChanged | Called when the mode changes.Parameters:lastMode: the previous modenewMode: the changed to mode | false | |

Options

| Name | Description | Required | Default | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ------- | | pinLength | Number of digits | false | 4 | | maxAttempt | The number of attempts when entering PIN. When user enters wrong PIN for a number of times, the Locked screen is shown. | false | 10 | | lockDuration | The duration (miliseconds) the screen is locked if the user enters wrong pin many times. | false | 60000 | | disableLock | By default, the locked screen is shown when maxAttempt has reached. Set this to true to disable the locked mode. | false | false | | allowReset | If true, the "Forgot PIN?" button is displayed at the bottom of the enter screen | false | true | | backSpace | On enter/set mode the "Delete" button is used to delete the entered digit. But you can pass an <Icon name='backspace' size={24} /> to display an icon instead. | false | | | lockedIcon | On the locked screen the "Locked" text is shown above the countdown. But you can pass an <Icon name='lock' size={24} /> to display an icon instead. | false | | | retryLockDuration | A short duration (miliseconds) between attempts. This is also the timeout to hide the error message. | false | 1000 |

Text Options

The text options are grouped by mode for the ease to find.

Enter mode text options

| Name | Description | Required | Default | Type | | ---------- | --------------------------------------- | -------- | ---------------------------- | ------ | | title | the Enter screen title | false | Enter PIN | string | | subTitle | the Enter screen sub title | false | Enter 4-digit PIN to access. | string | | error | error message when user enter wrong PIN | false | Wrong PIN! Try again. | string | | backSpace | the text of the backspace button | false | Delete | string | | footerText | the text of the footer button | false | Forgot PIN? | string |

Set mode text options

| Name | Description | Required | Default | Type | | ---------- | ------------------------------------------------- | -------- | ----------------------------------------- | ------ | | title | the Set screen title | false | Set up a new PIN | string | | subTitle | the Set screen sub title | false | Enter 4 digits. | string | | repeat | Prompt to enter pin one more time to avoid typos | false | Enter new PIN again. | string | | error | the error message when repeated PIN doesn't match | false | PIN don't match. Start the process again. | string | | backSpace | the text of the backspace button | false | Delete | string | | cancel | the cancel button | false | Cancel | string |

Locked mode text options

| Name | Description | Required | Default | Type | | ---------- | -------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------- | ------ | | title | the Locked mode title | false | Locked | string | | subTitle | the Locked mode sub title | false | Your have entered wrong PIN many times.The app is temporarily locked. | string | | lockedText | the locked text (this can be replaced with icon) by using the lockIcon option | false | Locked | string | | footerText | the Locked mode footer | false | | string |

Reset mode text options

| Name | Description | Required | Default | Type | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------ | ------ | | title | The Reset screen title | false | Forgot PIN? | string | | subTitle | The Reset screen sub title. You can use the {{maxAttempt}} and {{lockDuration}} placeholders to display the maxAttempt and lockDuration (in minutes) in the sub title. | false | Remove the PIN may wipe out the app data and settings. | string | | resetButton | Label of the reset button | false | Reset | string | | confirm | The message to ask the user to confirm the resetting | false | Are you sure you want remove the PIN? | string | | confirmButton | Label of the confirm button | false | Confirm | string | | footerText | The footer text | false | Back | string |

Styles options

The styles are grouped by mode. All mode layout has 3 sections: header, content, footer. The default values can be accessed by importing the DEFAULT from the package

import { DEFAULT } from '@anhnch/react-native-pin-code';
// DEFAULT.Styles.enter
// DEFAULT.Styles.set

Enter mode styles

| Name | Description | Required | Type | | ------------------ | ------------------------------------------------------------------------------- | -------- | --------- | | header | Style of the header container which wraps: title, subTitle, and errorText | false | ViewStyle | | title | Style of the title | false | TextStyle | | subTitle | Style of the sub title | false | TextStyle | | errorText | Style of the error | false | TextStyle | | content | Style of the container which wraps pinContainer and buttonContainer | false | ViewStyle | | pinContainer | Style of the container which wraps the pins (dots/circles) | false | ViewStyle | | pin | Style of the pins (dots/circles) | false | ViewStyle | | enteredPin | Style of the entered pins (big dots/circles) | false | ViewStyle | | buttonContainer | Style of the View that wraps the number buttons and the backspace button | false | ViewStyle | | buttonRow | Style of the View that wraps the rows of number buttons | false | ViewStyle | | button | Style which wraps digit buttons | false | ViewStyle | | buttonText | Style of the number button's label | false | TextStyle | | buttonTextDisabled | Style of the button text if disabled | false | TextStyle | | footer | Style of the footer container | false | ViewStyle | | footerText | Style the footer text | false | TextStyle |

Set mode styles

Same as the enter mode styles, but without the buttonTextDisabled

Locked mode styles

| Name | Description | Required | Type | | ------------------ | ------------------------------------------------------------------------------- | -------- | --------- | | header | Style of the header container which wraps: title, subTitle | false | ViewStyle | | title | Style of the title | false | TextStyle | | subTitle | Style of the sub title | false | TextStyle | | content | Style of the container which wraps the lock text/icon and the CountDown | false | ViewStyle | | countdown | Style of the container that wraps the CountDown | false | ViewStyle | | countdownText | Style of the remaining time | false | TextStyle | | lock | Style of the lock text. You can render a lock icon instead by setting lockIcon| false | TextStyle | | footer | Style of the footer container | false | ViewStyle | | footerText | Style the footer text | false | TextStyle |

Reset mode styles

| Name | Description | Required | Type | | ------------------ | ------------------------------------------------------------------------------- | -------- | --------- | | header | Style of the header container which wraps: title, subTitle | false | ViewStyle | | title | Style of the title | false | TextStyle | | subTitle | Style of the sub title | false | TextStyle | | content | Style of the container which wraps the lock text/icon and the CountDown | false | ViewStyle | | resetButton | Styles of the reset button | false | ViewStyle | | confirmText | Style of the confirm message | false | TextStyle | | footer | Style of the footer container | false | ViewStyle | | footerText | Style the footer text | false | TextStyle |

Example

Here is an example how to use Recoil to switch visibility and mode; and use MMKV to persist the pin code.

import React, { useEffect } from 'react';
import { View, StyleSheet, AppState, AppStateStatus, Text, Button } from 'react-native';
import { RecoilRoot, useRecoilState, atom } from 'recoil';
import { NavigationContainer, } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useMMKV, useMMKVString } from 'react-native-mmkv';
import { PinCode, PinCodeT } from '@anhnch/react-native-pincode';

const MainStack = createStackNavigator();

const PinCodeVisibleAtom = atom({
    key: 'common.PinCodeVisibleAtom',
    default: true
})

const PinCodeModeAtom = atom({
    key: 'common.PinCodeModeAtom',
    default: PinCodeT.Modes.Enter
})

const customTextes: PinCodeT.TextOptions = {
  enter: {
    subTitle: 'Enter PIN to access.',
  },
  set: {
    subTitle: 'Enter {{pinLength}} digits.'
  },
  locked: {
    title: 'Locked',
    subTitle: `Wrong PIN {{maxAttempt}} times.\nTemporarily locked in {{lockDuration}}.`
  }
};

const EnterAndSet: PinCodeT.EnterSetStyles = {
    header: { justifyContent: 'flex-start', alignItems: 'center', minHeight: 100 },
    title: { fontSize: 24 }
}

const customStyles:PinCodeT.Styles = { 
  main: { ...StyleSheet.absoluteFillObject, zIndex: 99, backgroundColor: 'blue' },
  enter: {
    ...EnterAndSet,
    buttonTextDisabled: { color: 'gray' },
  },
  set: EnterAndSet,
  locked: {
    countdown: { borderColor: 'black' },
    countdownText: { color: 'black' },
  },
  reset: {
    confirmText: { color: 'red' },
  }
}

const HomeScreen = () => {
    const [pinVisible, setPinVisible] = useRecoilState(PinCodeVisibleAtom);
    const [pinMode, setPinMode] = useRecoilState(PinCodeModeAtom);

    return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text style={{ fontSize: 30, marginBottom: 30, fontWeight: 'bold' }}>React Native Pin Code</Text>
        <Button title='Show PinCode Enter' onPress={() => {
          setPinMode(PinCodeT.Modes.Enter);
          setPinVisible(true);
        }} />
        <Button title='Set a new PIN' onPress={() => {
          setPinMode(PinCodeT.Modes.Set);
          setPinVisible(true);
        }} />
    </View>
}

const App = () => {
    return <>
      <NavigationContainer fallback={<Text>Loading</Text>}>
          <MainStack.Navigator initialRouteName="Home">
              <MainStack.Screen name="Home" component={HomeScreen} />
          </MainStack.Navigator>
      </NavigationContainer>
      <PinCodeComp />
    </>;
}

const PinCodeComp = () => {
  const mmkv = useMMKV();
  const [pin, setPin] = useMMKVString('@pin', mmkv);
  const [pinVisible, setPinVisible] = useRecoilValue(PinCodeVisibleAtom);
  const [pinMode, setPinMode] = useRecoilValue(PinCodeModeAtom);

  return <PinCode pin={pin} visible={visible} mode={pinMode}
      options={{
        backSpace: <Icon name='backspace' size={24} color='white' />,
        lockIcon: <Icon name='lock' size={24} color='white' />,
        retryLockDuration: 1000,
        maxAttempt: 5
      }}
      textOptions={customTextes}
      styles={customStyles} 
      onEnter={() => setPinVisible(false)}
      onSet={newPin => {
          setPin(newPin);
          setPinVisible(false);
      }}
      onSetCancel={() => setPinVisible(false)}
      onReset={() => setPin(undefined)}
    />
}

export default () => <RecoilRoot><App /></RecoilRoot>;