Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 1 addition & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,7 @@ yarn add react-native-text-input-mask
# Installation

<details>
<summary><b>For RN >= 0.61</b></summary>

#### iOS

1. Add following lines to your target in `Podfile`
```
use_frameworks!
pod 'RNInputMask', :path => '../node_modules/react-native-text-input-mask/ios/InputMask'
```
2. Run following command
```bash
cd ios && pod install
```

#### Android

No need to do anything.

</details>

<details>
<summary><b>For RN = 0.60.*</b></summary>
<summary><b>For RN >= 0.60 </b></summary>

#### iOS

Expand Down
18 changes: 18 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, { ForwardRefExoticComponent, PropsWithoutRef, RefAttributes} from "react";
import { TextInputProps, TextInput } from "react-native";

export type onChangeTextMask = (
formatted?: string,
extracted?: string
) => void;

export interface TextInputMaskProps
extends Omit<TextInputProps, "onChangeText"> {
maskDefaultValue?: boolean;
mask?: string;
onChangeText?: onChangeTextMask;
}

declare const TextInputMask : ForwardRefExoticComponent<PropsWithoutRef<TextInputMaskProps> & RefAttributes<TextInput>>;

export default TextInputMask;
143 changes: 90 additions & 53 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,108 @@
import React, { Component } from 'react'
import React, { useEffect, useRef, useImperativeHandle, useCallback } from "react";

import {
TextInput,
findNodeHandle,
NativeModules,
Platform
} from 'react-native'
} from "react-native";

const mask = NativeModules.RNTextInputMask.mask
const unmask = NativeModules.RNTextInputMask.unmask
const setMask = NativeModules.RNTextInputMask.setMask
export { mask, unmask, setMask }
const mask = NativeModules.RNTextInputMask.mask;
const unmask = NativeModules.RNTextInputMask.unmask;
const setMask = NativeModules.RNTextInputMask.setMask;
export { mask, unmask, setMask };

export default class TextInputMask extends Component {
static defaultProps = {
maskDefaultValue: true,
}
function TextInputMask(props, ref){
const inputRef = useRef();
const prevMask = useRef(props.mask)
const prevValue = useRef(props.value)
const masked = useRef(false);
const isMounted = useRef(false);

masked = false
const setNativeMask = useCallback(
(newInputMask)=>{
inputRef.current && setMask(findNodeHandle(inputRef.current), newInputMask);
},[inputRef.current]);

componentDidMount() {
if (this.props.maskDefaultValue &&
this.props.mask &&
this.props.value) {
mask(this.props.mask, '' + this.props.value, text =>
this.input && this.input.setNativeProps({ text }),
)
}
const setNativeTextMask = useCallback((value, inputMask)=>{
inputMask && mask(
inputMask,
"" + value,
text =>{
inputRef.current && inputRef.current.setNativeProps({ text });
prevValue.current = ""+ value;
}
);
},[inputRef.current, prevValue.current]);

if (this.props.mask && !this.masked) {
this.masked = true
setMask(findNodeHandle(this.input), this.props.mask)
const onChangeText = useCallback(masked => {
if(masked === prevValue.current) return;
if (props.mask) {
const _unmasked = unmask(props.mask, masked, unmasked => {
props.onChangeText && props.onChangeText(masked, unmasked);
});
} else {
props.onChangeText && props.onChangeText(masked);
}
},[props.onChangeText,prevValue.current])

useImperativeHandle(ref,()=>({
isFocused : ()=>{
return inputRef.current && inputRef.current.isFocused()
},
focus: ()=>{
return inputRef.current && inputRef.current.focus();
},
blur : ()=>{
return inputRef.current && inputRef.current.blur();
},
clear: ()=>{
return inputRef.current && inputRef.current.clear();
},
setNativeProps : ({ mask: inputMask, text, ...nativeProps})=>{
if( (inputMask || props.mask) && (text || props.value)) setNativeTextMask(text || props.value, inputMask || props.mask);
if(inputMask !== props.mask) setNativeMask(inputMask);
return Object.keys(nativeProps).length && inputRef.current && inputRef.current.setNativeProps(nativeProps)
}
}

componentWillReceiveProps(nextProps) {
if (nextProps.mask && (this.props.value !== nextProps.value)) {
mask(this.props.mask, '' + nextProps.value, text =>
this.input && this.input.setNativeProps({ text })
);
}));
useEffect(() => {
if (props.maskDefaultValue && props.mask && props.value) setNativeTextMask(props.value, props.mask)
if (props.mask && !masked.current) {
setNativeMask(props.mask);
masked.current = true;
}

if (this.props.mask !== nextProps.mask) {
setMask(findNodeHandle(this.input), nextProps.mask)
isMounted.current = true;
return ()=>{
isMounted.current = false
}
}, []);

// Check if value change
if(props.value !== prevValue.current){
isMounted.current && setNativeTextMask(props.value,props.mask);
}
//Check if mask change
if(props.mask !== prevMask.current){
isMounted.current && setNativeMask(props.mask);
prevMask.current = props.mask;
}

render() {
return (<TextInput
{...this.props}
return (
<TextInput
ref={inputRef}
{...props}
value={undefined}
ref={ref => {
this.input = ref
if (typeof this.props.refInput === 'function') {
this.props.refInput(ref)
}
}}
multiline={this.props.mask && Platform.OS === 'ios' ? false : this.props.multiline}
onChangeText={masked => {
if (this.props.mask) {
const _unmasked = unmask(this.props.mask, masked, unmasked => {
this.props.onChangeText && this.props.onChangeText(masked, unmasked)
})
} else {
this.props.onChangeText && this.props.onChangeText(masked)
}
}}
/>);
}
multiline={props.mask && Platform.OS === "ios" ? false : props.multiline}
onChangeText={onChangeText}
/>
);
}

TextInputMask = React.forwardRef(TextInputMask);

TextInputMask.defaultProps = {
maskDefaultValue: true
};

export default React.memo(TextInputMask,(prevProps,nextProps)=>prevProps.mask === nextProps.mask && prevProps.value === nextProps.value);
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-text-input-mask",
"version": "2.0.0",
"version": "2.0.1",
"description": "Text input mask for React Native.",
"main": "index.js",
"repository": {
Expand Down