RIFM

React Input Format & Mask, tiny (≈800b) component to transform any input co...

README

Путин Убийца



RIFM - React Input Format & Mask


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


Highlights


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

Example


Rifm offers both a Render Prop and a Hook API:

Render Prop


  1. ``` js
  2. import { Rifm } from 'rifm';
  3. import { TextField } from '@material-ui/core';

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

  8. ...

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

  10.   <Rifm
  11.     value={value}
  12.     onChange={setValue}
  13.     format={numberFormat}
  14.   >
  15.     {({ value, onChange }) => (
  16.       <TextField
  17.         type="tel"
  18.         value={value}
  19.         onChange={onChange}
  20.       />
  21.     )}
  22.   </Rifm>

  23. ...
  24. ```

Hook


  1. ``` js
  2. import { useRifm } from 'rifm';
  3. import { TextField } from '@material-ui/core';

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

  8. ...

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

  10.   const rifm = useRifm({
  11.     value,
  12.     onChange: setValue,
  13.     format: numberFormat
  14.   })

  15.   <TextField
  16.     type="tel"
  17.     value={rifm.value}
  18.     onChange={rifm.onChange}
  19.   />

  20. ...
  21. ```

Install


  1. ```sh
  2. yarn add rifm
  3. ```

API


Terminology


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.

Input Props


These are accepted by the Rifm component as props and the useRifm hook as named arguments.

ProptypedefaultDescription
------------:----------------------------:------:------------------------------------------------------------------------------------------------------------------------------------------------------------
**accept**RegExp/\d/gRegular
**format**string|
**value**string|
**onChange**string|
**children**({|
**mask**boolean|
**replace**string|
**append**string|

Output Props


These will be passed into the children render prop for the Rifm component as named arguments, and returned from the useRifm hook as an object.

ProptypedefaultDescription
------------:---------------------:------:---------------------------------------------------------------
**value**string|
**onChange**SyntheticEvent|

See the Demo there are a lot of examples there.

Thanks


@TrySound for incredible help and support on this