1.3.0 • Published 1 year ago

@anhnch/react-native-pincode v1.3.0

Weekly downloads
24
License
MIT
Repository
github
Last release
1 year ago

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

NameDescriptionRequiredDefault
visibleShow/hide the componenttruefalse
modeThe 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.trueenter
optionsSpecify how the component works. Check the options belowfalse
textOptionsCustomize the text content of the PinCode if you want to change the language or content. Check the options belowfalse
stylesSetting the styles to customize how PinCode should look. Check the style options belowfalse
onEnterTriggered 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 PINtrue
onSetTriggered when the user has successfully set the new pin. The application should persist the pin in this event.Parameters:pin (string, optional): the set PINtrue
onSetCancelTriggered when the mode is set and user cancels the setting pin. The app should hide the pin codetrue
onResetCalled when the user has confirmed to reset the pin. The application may clear the content, history, anything that belongs to the user if necessaryfalse
onModeChangedCalled when the mode changes.Parameters:lastMode: the previous modenewMode: the changed to modefalse

Options

NameDescriptionRequiredDefault
pinLengthNumber of digitsfalse4
maxAttemptThe number of attempts when entering PIN. When user enters wrong PIN for a number of times, the Locked screen is shown.false10
lockDurationThe duration (miliseconds) the screen is locked if the user enters wrong pin many times.false60000
disableLockBy default, the locked screen is shown when maxAttempt has reached. Set this to true to disable the locked mode.falsefalse
allowResetIf true, the "Forgot PIN?" button is displayed at the bottom of the enter screenfalsetrue
backSpaceOn 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
lockedIconOn 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
retryLockDurationA short duration (miliseconds) between attempts. This is also the timeout to hide the error message.false1000

Text Options

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

Enter mode text options

NameDescriptionRequiredDefaultType
titlethe Enter screen titlefalseEnter PINstring
subTitlethe Enter screen sub titlefalseEnter 4-digit PIN to access.string
errorerror message when user enter wrong PINfalseWrong PIN! Try again.string
backSpacethe text of the backspace buttonfalseDeletestring
footerTextthe text of the footer buttonfalseForgot PIN?string

Set mode text options

NameDescriptionRequiredDefaultType
titlethe Set screen titlefalseSet up a new PINstring
subTitlethe Set screen sub titlefalseEnter 4 digits.string
repeatPrompt to enter pin one more time to avoid typosfalseEnter new PIN again.string
errorthe error message when repeated PIN doesn't matchfalsePIN don't match. Start the process again.string
backSpacethe text of the backspace buttonfalseDeletestring
cancelthe cancel buttonfalseCancelstring

Locked mode text options

NameDescriptionRequiredDefaultType
titlethe Locked mode titlefalseLockedstring
subTitlethe Locked mode sub titlefalseYour have entered wrong PIN many times.The app is temporarily locked.string
lockedTextthe locked text (this can be replaced with icon) by using the lockIcon optionfalseLockedstring
footerTextthe Locked mode footerfalsestring

Reset mode text options

NameDescriptionRequiredDefaultType
titleThe Reset screen titlefalseForgot PIN?string
subTitleThe Reset screen sub title. You can use the {{maxAttempt}} and {{lockDuration}} placeholders to display the maxAttempt and lockDuration (in minutes) in the sub title.falseRemove the PIN may wipe out the app data and settings.string
resetButtonLabel of the reset buttonfalseResetstring
confirmThe message to ask the user to confirm the resettingfalseAre you sure you want remove the PIN?string
confirmButtonLabel of the confirm buttonfalseConfirmstring
footerTextThe footer textfalseBackstring

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

NameDescriptionRequiredType
headerStyle of the header container which wraps: title, subTitle, and errorTextfalseViewStyle
titleStyle of the titlefalseTextStyle
subTitleStyle of the sub titlefalseTextStyle
errorTextStyle of the errorfalseTextStyle
contentStyle of the container which wraps pinContainer and buttonContainerfalseViewStyle
pinContainerStyle of the container which wraps the pins (dots/circles)falseViewStyle
pinStyle of the pins (dots/circles)falseViewStyle
enteredPinStyle of the entered pins (big dots/circles)falseViewStyle
buttonContainerStyle of the View that wraps the number buttons and the backspace buttonfalseViewStyle
buttonRowStyle of the View that wraps the rows of number buttonsfalseViewStyle
buttonStyle which wraps digit buttonsfalseViewStyle
buttonTextStyle of the number button's labelfalseTextStyle
buttonTextDisabledStyle of the button text if disabledfalseTextStyle
footerStyle of the footer containerfalseViewStyle
footerTextStyle the footer textfalseTextStyle

Set mode styles

Same as the enter mode styles, but without the buttonTextDisabled

Locked mode styles

NameDescriptionRequiredType
headerStyle of the header container which wraps: title, subTitlefalseViewStyle
titleStyle of the titlefalseTextStyle
subTitleStyle of the sub titlefalseTextStyle
contentStyle of the container which wraps the lock text/icon and the CountDownfalseViewStyle
countdownStyle of the container that wraps the CountDownfalseViewStyle
countdownTextStyle of the remaining timefalseTextStyle
lockStyle of the lock text. You can render a lock icon instead by setting lockIconfalseTextStyle
footerStyle of the footer containerfalseViewStyle
footerTextStyle the footer textfalseTextStyle

Reset mode styles

NameDescriptionRequiredType
headerStyle of the header container which wraps: title, subTitlefalseViewStyle
titleStyle of the titlefalseTextStyle
subTitleStyle of the sub titlefalseTextStyle
contentStyle of the container which wraps the lock text/icon and the CountDownfalseViewStyle
resetButtonStyles of the reset buttonfalseViewStyle
confirmTextStyle of the confirm messagefalseTextStyle
footerStyle of the footer containerfalseViewStyle
footerTextStyle the footer textfalseTextStyle

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>;
1.3.0

1 year ago

1.2.5

3 years ago

1.2.4

3 years ago

1.2.3

3 years ago

1.2.2

3 years ago

1.2.1

3 years ago

1.1.4

3 years ago

1.1.0

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.0.0

3 years ago