├── .all-contributorsrc ├── .gitignore ├── .npmrc ├── .prettierrc ├── LICENSE ├── README.md ├── docs ├── Currency.js ├── Currency.mdx ├── Date.js ├── Date.mdx └── Home.mdx ├── doczrc.js ├── now.json ├── package.json └── src ├── index.js └── useInputMask.js /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "use-input-mask", 3 | "projectOwner": "elsangedy", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": true, 11 | "commitConvention": "none", 12 | "contributors": [ 13 | { 14 | "login": "elsangedy", 15 | "name": "Munir Ahmed Elsangedy", 16 | "avatar_url": "https://avatars3.githubusercontent.com/u/5339664?v=4", 17 | "profile": "https://munir.dev", 18 | "contributions": [ 19 | "code", 20 | "doc" 21 | ] 22 | }, 23 | { 24 | "login": "renatorib", 25 | "name": "Renato Ribeiro", 26 | "avatar_url": "https://avatars2.githubusercontent.com/u/3277185?v=4", 27 | "profile": "http://twitter.com/renatorib_", 28 | "contributions": [ 29 | "doc" 30 | ] 31 | } 32 | ], 33 | "contributorsPerLine": 7 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | .docz 63 | dist 64 | build 65 | 66 | .DS_Store 67 | package-lock.json 68 | yarn.lock 69 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=http://registry.npmjs.org/ 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": false, 6 | "singleQuote": true, 7 | "trailingComma": "all", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false, 10 | "proseWrap": "always" 11 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2019 Kent C. Dodds 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # use-input-mask 2 | ![MIT License][license-badge] 3 | [![downloads][downloads-badge]][npmcharts] 4 | [![PRs Welcome][prs-badge]][prs] 5 | [![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors) 6 | 7 | ## Installation 8 | 9 | ```bash 10 | $ yarn add use-input-mask 11 | # or 12 | $ npm i use-input-mask 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```jsx 18 | import React from 'react' 19 | 20 | import useInputMask from 'use-input-mask' 21 | 22 | import { createAutoCorrectedDatePipe } from "text-mask-addons"; 23 | 24 | const MyDateInput = props => { 25 | const input = useRef(null); 26 | 27 | const autoCorrectedDatePipe = createAutoCorrectedDatePipe("dd/mm/yyyy HH:MM"); 28 | 29 | const onChange = useInputMask({ 30 | input, 31 | onChange: props.onChange, 32 | mask: [/\d/, /\d/, "/", /\d/, /\d/, "/", /\d/, /\d/, /\d/, /\d/], 33 | pipe: autoCorrectedDatePipe, 34 | keepCharPositions: true 35 | }); 36 | 37 | return ; 38 | }; 39 | 40 | export default MyDateInput 41 | ``` 42 | 43 | ## Roadmap 44 | * [ ] tests 45 | * [ ] ci/cd 46 | * [ ] semantic-release 47 | * [ ] docs 48 | * [x] all-contributors 49 | 50 | ## Inspiration 51 | 52 | [text-mask](https://github.com/text-mask/text-mask) 53 | 54 | ## Contributors 55 | 56 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
Munir Ahmed Elsangedy
Munir Ahmed Elsangedy

💻 📖
Renato Ribeiro
Renato Ribeiro

📖
67 | 68 | 69 | 70 | 71 | 72 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 73 | 74 | ## LIENSE 75 | 76 | MIT 77 | 78 | [license-badge]: https://img.shields.io/npm/l/use-input-mask.svg?style=flat-square 79 | [downloads-badge]: https://img.shields.io/npm/dm/use-input-mask.svg?style=flat-square 80 | [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square 81 | [prs]: http://makeapullrequest.com 82 | [npmcharts]: http://npmcharts.com/compare/use-input-mask 83 | -------------------------------------------------------------------------------- /docs/Currency.js: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react' 2 | 3 | import useInputMask from '../src' 4 | 5 | import { createNumberMask } from 'text-mask-addons' 6 | 7 | const CurrencyInput = props => { 8 | const input = useRef(null) 9 | 10 | const maskMoney = createNumberMask({ 11 | prefix: 'R$ ', 12 | includeThousandsSeparator: true, 13 | thousandsSeparatorSymbol: '.', 14 | allowDecimal: true, 15 | integerLimit: 9, 16 | decimalSymbol: ',', 17 | requireDecimal: true, 18 | }) 19 | 20 | const onChange = useInputMask({ 21 | input, 22 | onChange: props.onChange, 23 | mask: value => { 24 | const mask = maskMoney(value) 25 | 26 | const decimalsRegex = /,([0-9]{1,2})/ 27 | const result = decimalsRegex.exec(value) 28 | 29 | if (!!result && result[1].length < 2) { 30 | mask.push('0') 31 | } else if (!result) { 32 | mask.push('00') 33 | } 34 | 35 | return mask 36 | }, 37 | }) 38 | 39 | return 40 | } 41 | 42 | export default CurrencyInput 43 | -------------------------------------------------------------------------------- /docs/Currency.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Currency 3 | menu: Examples 4 | --- 5 | 6 | import { Playground } from 'docz' 7 | 8 | import CurrencyInput from './Currency' 9 | 10 | # Currency 11 | 12 | 13 | console.log(e.target.value)} 15 | placeholder="Currency input" 16 | /> 17 | 18 | 19 | ## Code 20 | 21 | ```js 22 | import React, { useRef } from 'react' 23 | 24 | import useInputMask from 'use-input-mask' 25 | 26 | import { createNumberMask } from 'text-mask-addons' 27 | 28 | const CurrencyInput = props => { 29 | const input = useRef(null) 30 | 31 | const maskMoney = createNumberMask({ 32 | prefix: 'R$ ', 33 | includeThousandsSeparator: true, 34 | thousandsSeparatorSymbol: '.', 35 | allowDecimal: true, 36 | integerLimit: 9, 37 | decimalSymbol: ',', 38 | requireDecimal: true, 39 | }) 40 | 41 | const onChange = useInputMask({ 42 | input, 43 | onChange: props.onChange, 44 | mask: value => { 45 | const mask = maskMoney(value) 46 | 47 | const decimalsRegex = /,([0-9]{1,2})/ 48 | const result = decimalsRegex.exec(value) 49 | 50 | if (!!result && result[1].length < 2) { 51 | mask.push('0') 52 | } else if (!result) { 53 | mask.push('00') 54 | } 55 | 56 | return mask 57 | }, 58 | }) 59 | 60 | return 61 | } 62 | 63 | export default CurrencyInput 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/Date.js: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react' 2 | 3 | import useInputMask from '../src' 4 | 5 | import { createAutoCorrectedDatePipe } from 'text-mask-addons' 6 | 7 | const DateInput = props => { 8 | const input = useRef(null) 9 | 10 | const autoCorrectedDatePipe = createAutoCorrectedDatePipe('dd/mm/yyyy HH:MM') 11 | 12 | const onChange = useInputMask({ 13 | input, 14 | onChange: props.onChange, 15 | mask: [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/], 16 | pipe: autoCorrectedDatePipe, 17 | placeholder: 'Please enter a date', 18 | keepCharPositions: true, 19 | }) 20 | 21 | return 22 | } 23 | 24 | export default DateInput 25 | -------------------------------------------------------------------------------- /docs/Date.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Date 3 | menu: Examples 4 | --- 5 | 6 | import { Playground } from 'docz' 7 | 8 | import DateInput from './Date' 9 | 10 | # Date 11 | 12 | 13 | console.log(e.target.value)} 15 | placeholder="Date input" 16 | /> 17 | 18 | 19 | ## Code 20 | 21 | ```js 22 | import React, { useRef } from 'react' 23 | 24 | import useInputMask from 'use-input-mask' 25 | 26 | import { createAutoCorrectedDatePipe } from 'text-mask-addons' 27 | 28 | const DateInput = props => { 29 | const input = useRef(null) 30 | 31 | const autoCorrectedDatePipe = createAutoCorrectedDatePipe('dd/mm/yyyy HH:MM') 32 | 33 | const onChange = useInputMask({ 34 | input, 35 | onChange: props.onChange, 36 | mask: [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/], 37 | pipe: autoCorrectedDatePipe, 38 | placeholder: 'Please enter a date', 39 | keepCharPositions: true, 40 | }) 41 | 42 | return 43 | } 44 | 45 | export default DateInput 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/Home.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Home 3 | route: / 4 | --- 5 | 6 | # Getting Started 7 | 8 | https://github.com/elsangedy/use-input-mask 9 | 10 | https://github.com/text-mask/text-mask 11 | 12 | ## Install 13 | 14 | ```bash 15 | yarn add use-input-mask 16 | ``` 17 | 18 | ## Hook 19 | 20 | ```js 21 | import useInputMask from 'use-input-mask' 22 | 23 | const onChange = useInputMask({ 24 | input, 25 | onChange, 26 | guide, 27 | keepCharPositions, 28 | mask, 29 | pipe, 30 | placeholderChar, 31 | showMask, 32 | initialValue, 33 | }) 34 | ``` 35 | -------------------------------------------------------------------------------- /doczrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | dest: '/dist', 3 | codeSandbox: false, 4 | repository: 'https://github.com/elsangedy/use-input-mask', 5 | menu: [ 6 | 'Home', 7 | { 8 | name: 'Examples', 9 | menu: ['Date', 'Currency'], 10 | }, 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "use-input-mask", 4 | "alias": "use-input-mask.now.sh", 5 | "public": true, 6 | "builds": [ 7 | { "src": "package.json", "use": "@now/static-build" } 8 | ] 9 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "use-input-mask", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "author": { 6 | "name": "Munir Ahmed Elsangedy", 7 | "email": "elsangedy@gmail.com", 8 | "url": "https://munir.dev" 9 | }, 10 | "homepage": "https://use-input-mask.now.sh", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/elsangedy/use-input-mask.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/elsangedy/use-input-mask/issues" 17 | }, 18 | "main": "dist/use-input-mask.cjs.js", 19 | "module": "dist/use-input-mask.esm.js", 20 | "files": [ 21 | "dist" 22 | ], 23 | "scripts": { 24 | "now-build": "yarn build:docs", 25 | "dev": "docz dev", 26 | "build:docs": "docz build", 27 | "build": "kcd-scripts build --bundle", 28 | "add-contributor": "all-contributors add" 29 | }, 30 | "dependencies": { 31 | "@babel/runtime": "^7.5.5", 32 | "text-mask-core": "^5.1.2" 33 | }, 34 | "peerDependencies": { 35 | "react": ">=16.8" 36 | }, 37 | "devDependencies": { 38 | "all-contributors-cli": "^6.8.1", 39 | "docz": "^1.2.0", 40 | "docz-theme-default": "^1.2.0", 41 | "kcd-scripts": "^1.4.0", 42 | "react": "^16.8.6", 43 | "react-dom": "^16.8.6", 44 | "text-mask-addons": "^3.8.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './useInputMask' 2 | -------------------------------------------------------------------------------- /src/useInputMask.js: -------------------------------------------------------------------------------- 1 | import { useLayoutEffect, useRef } from 'react' 2 | 3 | const { createTextMaskInputElement } = require('text-mask-core') 4 | 5 | function useInputMask({ 6 | guide, 7 | input: inputRef, 8 | keepCharPositions, 9 | mask, 10 | onChange, 11 | pipe, 12 | placeholderChar, 13 | showMask, 14 | initialValue = '', 15 | }) { 16 | const textMaskRef = useRef(null) 17 | 18 | useLayoutEffect(() => { 19 | if (!inputRef.current) { 20 | return 21 | } 22 | 23 | textMaskRef.current = createTextMaskInputElement({ 24 | guide, 25 | inputElement: inputRef.current, 26 | keepCharPositions, 27 | mask, 28 | pipe, 29 | placeholderChar, 30 | showMask, 31 | }) 32 | 33 | textMaskRef.current.update(initialValue) 34 | }, [ 35 | inputRef, 36 | guide, 37 | keepCharPositions, 38 | mask, 39 | pipe, 40 | placeholderChar, 41 | showMask, 42 | initialValue, 43 | ]) 44 | 45 | return event => { 46 | if (textMaskRef.current) { 47 | textMaskRef.current.update() 48 | } 49 | 50 | if (typeof onChange === 'function') { 51 | onChange(event) 52 | } 53 | } 54 | } 55 | 56 | export default useInputMask 57 | --------------------------------------------------------------------------------