Skip to content
React Input Format & Mask, tiny (≈800b) component to transform any input component into formatted or masked input. Supports number, date, phone, currency, credit card, etc
JavaScript TypeScript
Branch: master
Clone or download
Latest commit 1fbce78 Oct 21, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
pages Fix rifm version Oct 21, 2019
src Rifm mask change (#86) Oct 19, 2019
tests Rifm mask change (#86) Oct 19, 2019
.gitignore Add website page with codesandbox examples (#57) May 25, 2019
.prettierignore Ignore out May 27, 2019
.size-snapshot.json Rifm mask change (#86) Oct 19, 2019
LICENSE Rifm mask change (#86) Oct 19, 2019
next.config.js Deploy codesandbox example to gh-pages (#59) May 26, 2019
rollup.config.js Remove babel runtime from dependencies Oct 21, 2019
tsconfig.json Rifm mask change (#86) Oct 19, 2019

RIFM - React Input Format & Mask

Is a tiny (≈ 800b) component to transform any input component into formatted or masked input.



  • Requires React 16.8+
  • Dependency free
  • Tiny (≈ 800b)
  • Supports any input.
  • Can mask input, format and more
  • Small readable source
  • flow + typescript definitions


import { Rifm } from 'rifm';
import TextField from '@material-ui/core/TextField';
import { css } from 'emotion';

const numberFormat = (str: string) => {
  const r = parseInt(str.replace(/[^\d]+/gi, ''), 10);
  return r ? r.toLocaleString('en') : '';


  const [value, setValue] = React.useState('')

    {({ value, onChange }) => (
        className={css({input: {textAlign:"right"}})}



yarn add rifm



Rifm is based on simple idea (*):

  • format operation applied to input value after edit doesn't change the order of some symbols before cursor

* This is not always true, but we solve some edge cases where it's not.

Imagine you have simple integer number formatter with ` as thousands separator and current input state is 123`4|67 ("|" shows current cursor position).

User press 5 then formatted input must be equal to 1`234`5|67.

The overall order of elements has changed (was 1->2->3->`->4->... became 1->`->2->3->4...) but the order of digits before cursor hasn't changed (was 1->2->3->4 and hasn't changed).

The same is true for float numbers formatting, dates and more. Symbols with preserved order are different and depends on format. We call this kind of symbols - "accepted" symbols.

Rifm solves only one task - find the right place for cursor after formatting.

Knowledge about what symbols are "accepted" and cursor position after any user action is enough to find the final cursor position.

Most operations which are not covered with above idea like case enforcements, masks guides, floating point ","=>"." replacement can be done using simple postprocessing step - replace. This operation works well if you need to change input value without loosing cursor position.

And finaly masks - masks are usually is format with replace editing mode + some small cursor visual hacks.


Prop type default Description
accept RegExp (optional) /\d/g Regular expression to detect "accepted" symbols
format string => string format function
value string input value
onChange string => void event fired on input change
children ({ value, onChange }) => Node value and onChange handler you need to pass to underlying input element
mask boolean (optional) use replace input mode if true, use cursor visual hacks if prop provided
replace string => string (optional) format postprocessor allows you to fully replace any/all symbol/s preserving cursor
append string => string (optional) format postprocessor called only if cursor is in the last position and new symbols added, used for specific use-case to add non accepted symbol when you type

See the Demo there are a lot of examples there.


@TrySound for incredible help and support on this

You can’t perform that action at this time.