Masked input component for React. Forked from https://github.com/sanniassin/react-input-mask.
npm install @ajreed79/react-input-maskInput masking component for React. Made with attention to UX. Compatible with Chrome 70+. Should work with recent versions of modern browsers.
npm install @ajreed79/react-input-mask --save`Properties
$3
Mask string. Default format characters are:
9: 0-9
a: A-Z, a-z
*: A-Z, a-z, 0-9Any character can be escaped with a backslash. It will appear as a double backslash in JS strings. For example, a German phone mask with unremoveable prefix +49 will look like mask="+4\\9 99 999 99" or mask={'+4\\\\9 99 999 99'}
$3
Character to cover unfilled parts of the mask. Default character is "\_". If set to null or empty string, unfilled parts will be empty as in ordinary input.$3
Defines format characters with characters as a keys and corresponding RegExp strings as a values. Default ones:
`js
{
'9': '[0-9]',
'a': '[A-Za-z]',
'*': '[A-Za-z0-9]'
}
`$3
Show mask when input is empty and has no focus.$3
Use inputRef instead of ref if you need input node to manage focus, selection, etc.inputRef is required when using a children function and must point to the INPUT DOM element.Experimental :fire:
The following props are considered experimental because they are more prone to issues and are likely to be changed in the future. Use with caution.$3
In case you need to implement more complex masking behavior, you can provide beforeMaskedValueChange function to change masked value and cursor position before it will be applied to the input. beforeMaskedValueChange receives following arguments:
1. newState (object): New input state. Contains value and selection fields. selection is null on input blur or when function is called before input mount. Example: { value: '12/1_/____', selection: { start: 4, end: 4 } }
2. oldState (object): Input state before change. Contains value and selection fields. selection is null on input focus or when function is called before input mount.
3. userInput (string): Raw entered or pasted string. null if user didn't enter anything (e.g. triggered by deletion or rerender due to props change).
4. maskOptions (object): Mask options. Example:
`js
{
mask: '99/99/9999',
maskChar: '_',
alwaysShowMask: false,
formatChars: {
'9': '[0-9]',
'a': '[A-Za-z]',
'*': '[A-Za-z0-9]'
},
permanents: [2, 5] // permanents is an array of indexes of the non-editable characters in the mask
}
`beforeMaskedValueChange must return an object with following fields:
1. value (string): New value.
2. selection (object): New selection. If selection in newState argument is null, it must be null too.Please note that
beforeMaskedValueChange executes more often than onChange and must be pure.$3
To use another component instead of regular
pass render function as a children. Function receives props argument which contains props that aren't used by react-input-mask's internals. I.e. it passes down every prop except the following ones: onChange, onPaste, onMouseDown, onFocus, onBlur, value, disabled, readOnly. These properties, if used, should always be passed directly to react-input-mask instead of children and shouldn't be altered in chldren's function.
`jsx
import React from 'react';
import InputMask from '@ajreed79/react-input-mask';
import MaterialInput from '@material-ui/core/Input';// Will work fine
const Input = (props) => (
{(inputProps) => }
);
// Will throw an error because InputMask's and children's onChange aren't the same
const InvalidInput = (props) => (
{(inputProps) => }
);
`Examples
`jsx
import React from 'react';
import InputMask from '@ajreed79/react-input-mask';class PhoneInput extends React.Component {
render() {
return ;
}
}
`Mask for ZIP Code. Uses beforeMaskedValueChange to omit trailing minus if it wasn't entered by user:
`jsx
import React from 'react';
import InputMask from '@ajreed79/react-input-mask';class Input extends React.Component {
state = {
value: ''
}
onChange = (event) => {
this.setState({
value: event.target.value
});
}
beforeMaskedValueChange = (newState, oldState, userInput) => {
var { value } = newState;
var selection = newState.selection;
var cursorPosition = selection ? selection.start : null;
// keep minus if entered by user
if (value.endsWith('-') && userInput !== '-' && !this.state.value.endsWith('-')) {
if (cursorPosition === value.length) {
cursorPosition--;
selection = { start: cursorPosition, end: cursorPosition };
}
value = value.slice(0, -1);
}
return {
value,
selection
};
}
render() {
return ;
}
}
`Known Issues
$3
Browser's autofill requires either empty value in input or value which exactly matches beginning of the autofilled value. I.e. autofilled value "+1 (555) 123-4567" will work with "+1" or "+1 (5", but won't work with "+1 (\_\_\_) \_\_\_-\_\_\_\_" or "1 (555)". There are several possible solutions:
1. Set maskChar to null and trim space after "+1" with beforeMaskedValueChange` if no more digits are entered.Please note that it might lead to worse user experience (should I enter +1 if input is empty?). You should choose what's more important to your users — smooth typing experience or autofill. Phone and ZIP code inputs are very likely to be autofilled and it's a good idea to care about it, while security confirmation code in two-factor authorization shouldn't care about autofill at all.