├── .gitignore
├── .npmignore
├── example
├── components
│ ├── Snippet
│ │ ├── snippet.css
│ │ └── index.js
│ ├── Layout
│ │ ├── index.js
│ │ ├── layout.css
│ │ └── fonts.css
│ └── ComponentSnippet
│ │ ├── componentSnippet.css
│ │ └── index.js
└── index.js
├── .babelrc
├── prettier.config.js
├── docs
└── index.html
├── .eslintrc.js
├── CHANGELOG.md
├── webpack.config.js
├── README.md
├── package.json
└── src
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | logs
2 | *.log
3 | npm-debug.log.*
4 | node_modules
5 | dist
6 | !docs/dist
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | docs
2 | node_modules
3 | .eslintrc.js
4 | .gitignore
5 | yarn.lock
6 | webpack.config.js
7 |
--------------------------------------------------------------------------------
/example/components/Snippet/snippet.css:
--------------------------------------------------------------------------------
1 | .wrapper{
2 | background: #f8f9f9!important;
3 | font-size: 0.9em;
4 | }
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "env",
4 | "react"
5 | ],
6 | "plugins": [
7 | ["transform-object-rest-spread"]
8 | ]
9 | }
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "singleQuote": false,
3 | "trailingComma": "es5",
4 | "bracketSpacing": true,
5 | "jsxBracketSameLine": true,
6 | "printWidth": 100,
7 | "parser": "babylon",
8 | }
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-numeric
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/components/Layout/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styles from "./layout.css";
3 | import "./fonts.css";
4 |
5 | const Layout = props => {
6 | return {props.children}
;
7 | };
8 |
9 | export default Layout;
10 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | "eslint:recommended",
4 | "plugin:react/recommended",
5 | "prettier",
6 | ],
7 | plugins: [
8 | "react",
9 | "prettier",
10 | ],
11 | rules: {
12 | },
13 | parser: "babel-eslint",
14 | env: {
15 | "es6": true,
16 | "node": true,
17 | "browser": true,
18 | "jest": true,
19 | },
20 | };
--------------------------------------------------------------------------------
/example/components/Snippet/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styles from "./snippet.css";
3 | import SyntaxHighlighter from "react-syntax-highlighter/prism";
4 | import dark from "react-syntax-highlighter/styles/prism/coy.js";
5 |
6 | const ComponentSnippet = props => {
7 | return (
8 |
9 | {props.children}
10 |
11 | );
12 | };
13 |
14 | export default ComponentSnippet;
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 |
8 | ## [1.0.0] - 2019-07-02
9 | ### Added
10 | `autoFocus`, `placeholder` `unselectable`, `size` and `id` props for input added by [@sbusch](https://github.com/sbusch)
11 | Added changelog
12 |
13 | ### Changed
14 | - `prop-types` moved to peer dependencies from dependencies.
15 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const HtmlWebpackPlugin = require('html-webpack-plugin')
3 |
4 | module.exports = {
5 | entry: path.resolve("./example/index.js"),
6 | output: {
7 | path: path.resolve("./docs"),
8 | filename: "[name].js"
9 | },
10 | module: {
11 | rules: [
12 | {
13 | test: /\.js$/,
14 | loader: "babel-loader",
15 | exclude: /node_modules/
16 | },
17 | {
18 | test: /\.css$/,
19 | use: ["style-loader", "css-loader?modules"],
20 | include: path.resolve("./example")
21 | },
22 | {
23 | test: /\.css$/,
24 | use: ["style-loader", "css-loader"],
25 | include: /node_modules/
26 | },
27 | {
28 | test: /\.(jpg|png)$/,
29 | use: ["file-loader"]
30 | }
31 | ]
32 | },
33 | devServer: {
34 | publicPath: "/",
35 | contentBase: path.join(__dirname, "example"),
36 | hot: true
37 | },
38 | plugins: [new HtmlWebpackPlugin({
39 | title: 'react-numeric',
40 | })],
41 | };
42 |
--------------------------------------------------------------------------------
/example/components/ComponentSnippet/componentSnippet.css:
--------------------------------------------------------------------------------
1 | .wrapper{
2 | background: #f8f9f9;
3 | font-size: 0.9em;
4 | margin-top: 2em;
5 | margin-bottom: 6em;
6 | position: relative;
7 | }
8 |
9 | .content{
10 | position: relative;
11 | z-index: 1;
12 | background: #f8f9f9!important;
13 | }
14 |
15 | .preview{
16 | display: flex;
17 | justify-content: center;
18 | align-items: center;
19 | min-height: 12em;
20 | }
21 |
22 | .code{
23 | background: #f8f9f9!important;
24 | }
25 |
26 | .buttons{
27 | position: absolute;
28 | top: 100%;
29 | right: 0em;
30 | }
31 |
32 | .button{
33 | background-color: rgb(248, 249, 249);
34 | padding: 1em;
35 | border: 1px solid transparent;
36 | font-size: 0.8em;
37 | cursor: pointer;
38 | outline: 0;
39 | color: #3d91ff;
40 | }
41 |
42 | .button:hover{
43 | border-color: #3d91ff;
44 | }
45 |
46 | .button:first-child{
47 | border-bottom-left-radius: 4px;
48 | }
49 |
50 | .button:last-child{
51 | border-bottom-right-radius: 4px;
52 | }
53 |
54 | .passiveButton{
55 | background: #f1f2f2;
56 | color: #666666;
57 | }
58 |
59 | input{
60 | font-size: 1.6em;
61 | padding: 0.5em;
62 | }
63 |
64 | input:focus{
65 | outline:2px solid #3d91ff;
66 | }
--------------------------------------------------------------------------------
/example/components/Layout/layout.css:
--------------------------------------------------------------------------------
1 | html{
2 | height: 100%;
3 | background-color: #e7eff2;
4 | color: #637381;
5 | overflow-y: scroll;
6 | font-family: 'Open Sans', sans-serif;
7 | font-size: 16px;
8 | }
9 |
10 | body{
11 | min-height: 100vh;
12 | margin: 0;
13 | padding: 2em;
14 | text-align: center;
15 |
16 | }
17 |
18 | .wrapper{
19 | padding: 40px 40px 40px 48px;
20 | /* box-shadow: 0 12px 36px rgba(0,0,0,.2); */
21 | background-color: #fff;
22 | max-width: 970px;
23 | margin: 6em auto 0 auto;
24 | text-align: left;
25 | }
26 |
27 | h1{
28 | font-size: 2.5em;
29 | font-weight: 600;
30 | color: #161d25;
31 | font-family: 'PT Sans', sans-serif;
32 | max-width: 600px;
33 | }
34 |
35 | h2{
36 | color: #161d25;
37 | font-size: 1.6em;
38 | font-weight: 400;
39 | font-family: 'PT Sans', sans-serif;
40 | max-width: 600px;
41 | }
42 |
43 | blockquote{
44 | font-size: 1.6em;
45 | font-weight: 400;
46 | font-family: 'PT Sans', sans-serif;
47 | box-shadow: -7px 0px #3ecf8e;
48 | margin: 1em 0.3em;
49 | padding-left: 1em;
50 | max-width: 600px;
51 | }
52 |
53 | .blockquote{
54 | font-size: 1.6em;
55 | font-weight: 400;
56 | font-family: 'PT Sans', sans-serif;
57 | margin: 0.3em;
58 | max-width: 600px;
59 | }
60 |
61 | p{
62 | font-weight: 500;
63 | max-width: 600px;
64 | }
65 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-numeric
2 |
3 | []()
4 | [](https://www.npmjs.com/package/react-numeric)
5 |
6 |
7 | A react component for formatted number form fields
8 | > react-numeric is a wrapper component for [autonumeric](https://github.com/autoNumeric/autoNumeric).
9 |
10 | ## Installition
11 |
12 | ```sh
13 | yarn add react-numeric
14 | # or
15 | npm install react-numeric --save
16 | ```
17 |
18 | ## Usage
19 |
20 | ```jsx
21 | import ReactNumeric from 'react-numeric';
22 |
23 | export function USDMoneyInput(props){
24 | const { value } = props; // number typed
25 | return (
26 | {
33 | console.log(event.target.value); // '1,234.5 $'
34 | console.log(value); // 1234.5
35 | }}
36 | />
37 | );
38 | }
39 |
40 | // You can use predefinedOptions
41 | import { predefinedOptions } from 'react-numeric';
42 |
43 | export function PossitiveUSDMoneyInput(props){
44 | const { value } = props; // number typed
45 | return (
46 | this.setState({ value })}
50 | />
51 | );
52 | }
53 |
54 | // if you want to store value as string typed
55 | export function NumberInput(props){
56 | const { value } = props; // string typed
57 | return (
58 | this.setState({ value })}
62 | />
63 | );
64 | }
65 | ```
66 |
--------------------------------------------------------------------------------
/example/components/ComponentSnippet/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styles from "./componentSnippet.css";
3 | import SyntaxHighlighter from "react-syntax-highlighter/prism";
4 | import dark from "react-syntax-highlighter/styles/prism/coy.js";
5 | import cx from "classnames";
6 | import PropTypes from "prop-types";
7 |
8 | class ComponentSnippet extends React.Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | mode: props.initialMode,
13 | };
14 | }
15 |
16 | render() {
17 | const { mode } = this.state;
18 | const { preview, code } = this.props;
19 | return (
20 |
21 |
22 | {mode === "code" ? (
23 |
24 | {code}
25 |
26 | ) : (
27 |
{preview}
28 | )}
29 |
30 |
31 |
38 |
45 |
46 |
47 | );
48 | }
49 | }
50 |
51 | ComponentSnippet.propTypes = {
52 | initialMode: PropTypes.oneOf(["preview", "code"]),
53 | };
54 |
55 | ComponentSnippet.defaultProps = {
56 | initialMode: "preview",
57 | };
58 |
59 | export default ComponentSnippet;
60 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-numeric",
3 | "description": "A react component for formatted number form fields",
4 | "version": "1.0.0",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/mkg0/react-numeric"
8 | },
9 | "main": "dist/index.js",
10 | "keywords": [
11 | "autonumeric",
12 | "currency",
13 | "money",
14 | "monetary",
15 | "Euro",
16 | "Dollar",
17 | "Pound",
18 | "number",
19 | "numeric",
20 | "format",
21 | "react",
22 | "numeric"
23 | ],
24 | "author": "Mehmet Kamil Morcay (https://github.com/mkg0)",
25 | "license": "MIT",
26 | "dependencies": {
27 | "autonumeric": "^4.4.0"
28 | },
29 | "devDependencies": {
30 | "babel-cli": "^6.26.0",
31 | "babel-eslint": "^8.2.2",
32 | "babel-loader": "^7.1.4",
33 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
34 | "babel-preset-env": "^1.6.1",
35 | "babel-preset-react": "^6.24.1",
36 | "classnames": "^2.2.5",
37 | "css-loader": "^0.28.11",
38 | "eslint": "^4.19.1",
39 | "eslint-config-prettier": "^2.9.0",
40 | "eslint-plugin-prettier": "^2.6.0",
41 | "eslint-plugin-react": "^7.7.0",
42 | "html-webpack-plugin": "^3.2.0",
43 | "prettier": "^1.11.1",
44 | "react": "^16.2.0",
45 | "react-dom": "^16.2.0",
46 | "react-syntax-highlighter": "^7.0.1",
47 | "style-loader": "^0.20.3",
48 | "webpack": "^4.5.0",
49 | "webpack-cli": "^2.0.14",
50 | "webpack-dev-server": "^3.1.3"
51 | },
52 | "peerDependencies": {
53 | "react": ">=15.0.0",
54 | "prop-types": "^15.6.1"
55 | },
56 | "scripts": {
57 | "build": "yarn build-library && yarn build-demo",
58 | "build-library": "NODE_ENV=production babel ./src --out-dir ./dist",
59 | "build-demo": "webpack -p",
60 | "clear": "rm -rf dist docs",
61 | "prebuild": "yarn clear && yarn lint",
62 | "dev": "webpack-dev-server --hot --mode 'development'",
63 | "lint": "eslint 'src/**/*.js'",
64 | "prettier": "prettier src/**/*.js example/**/*.js --write"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import ReactDOM from "react-dom";
3 | import ReactNumeric, { predefinedOptions } from "../src";
4 | import Snippet from "./components/Snippet";
5 | import ComponentSnippet from "./components/ComponentSnippet";
6 |
7 | import Layout from "./components/Layout";
8 |
9 | class DemoPage extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.state = {
13 | intro: 12345,
14 | example1: 12345,
15 | example2: "12345",
16 | example3: 12345,
17 | };
18 | }
19 | render() {
20 | return (
21 |
22 | react-numeric
23 | A react component for formatted numeric values.
24 |
25 | react-numeric is a wrapper component of{" "}
26 |
27 | autonumeric
28 | .
29 |
30 |
31 | {
39 | this.setState({ value });
40 | }} />
41 | `}
42 | preview={
43 | {
46 | console.info("onChange", params);
47 | this.setState({ intro: params[1] });
48 | }}
49 | />
50 | }
51 | />
52 | Installition
53 |
54 | {`
55 | yarn add react-numeric
56 | `}
57 |
58 | If you don't use yarn
59 |
60 | {`
61 | npm install react-numeric --save
62 | `}
63 |
64 |
65 | Usage & Demos
66 |
67 | this.setState({example1: value}) }} />
77 | `}
78 | preview={
79 |
80 | {
87 | console.info("onChange", params);
88 | this.setState({ example1: params[1] });
89 | }}
90 | />
91 |
92 | }
93 | />
94 | if you want to store value as string typed
95 | this.setState({example2: value}) }} />
102 | `}
103 | preview={
104 | {
108 | console.info("onChange", params);
109 | this.setState({ example2: params[1] });
110 | }}
111 | />
112 | }
113 | />
114 |
115 | You can use predefinedOptions
116 | this.setState({example3: value}) }} />
123 | `}
124 | preview={
125 | {
129 | console.info("onChange", params);
130 | this.setState({ example3: params[1] });
131 | }}
132 | />
133 | }
134 | />
135 |
136 | );
137 | }
138 | }
139 |
140 | const root = document.createElement("div");
141 | document.body.appendChild(root);
142 | ReactDOM.render(, root);
143 |
--------------------------------------------------------------------------------
/example/components/Layout/fonts.css:
--------------------------------------------------------------------------------
1 | /* cyrillic-ext */
2 | @font-face {
3 | font-family: 'Open Sans';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFWJ0bf8pkAp6a.woff2) format('woff2');
7 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
8 | }
9 | /* cyrillic */
10 | @font-face {
11 | font-family: 'Open Sans';
12 | font-style: normal;
13 | font-weight: 400;
14 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFUZ0bf8pkAp6a.woff2) format('woff2');
15 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
16 | }
17 | /* greek-ext */
18 | @font-face {
19 | font-family: 'Open Sans';
20 | font-style: normal;
21 | font-weight: 400;
22 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFWZ0bf8pkAp6a.woff2) format('woff2');
23 | unicode-range: U+1F00-1FFF;
24 | }
25 | /* greek */
26 | @font-face {
27 | font-family: 'Open Sans';
28 | font-style: normal;
29 | font-weight: 400;
30 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVp0bf8pkAp6a.woff2) format('woff2');
31 | unicode-range: U+0370-03FF;
32 | }
33 | /* vietnamese */
34 | @font-face {
35 | font-family: 'Open Sans';
36 | font-style: normal;
37 | font-weight: 400;
38 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFWp0bf8pkAp6a.woff2) format('woff2');
39 | unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
40 | }
41 | /* latin-ext */
42 | @font-face {
43 | font-family: 'Open Sans';
44 | font-style: normal;
45 | font-weight: 400;
46 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFW50bf8pkAp6a.woff2) format('woff2');
47 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
48 | }
49 | /* latin */
50 | @font-face {
51 | font-family: 'Open Sans';
52 | font-style: normal;
53 | font-weight: 400;
54 | src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2) format('woff2');
55 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
56 | }
57 | /* cyrillic-ext */
58 | @font-face {
59 | font-family: 'PT Sans';
60 | font-style: normal;
61 | font-weight: 400;
62 | src: local('PT Sans'), local('PTSans-Regular'), url(https://fonts.gstatic.com/s/ptsans/v9/jizaRExUiTo99u79D0-ExcOPIDUg-g.woff2) format('woff2');
63 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
64 | }
65 | /* cyrillic */
66 | @font-face {
67 | font-family: 'PT Sans';
68 | font-style: normal;
69 | font-weight: 400;
70 | src: local('PT Sans'), local('PTSans-Regular'), url(https://fonts.gstatic.com/s/ptsans/v9/jizaRExUiTo99u79D0aExcOPIDUg-g.woff2) format('woff2');
71 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
72 | }
73 | /* latin-ext */
74 | @font-face {
75 | font-family: 'PT Sans';
76 | font-style: normal;
77 | font-weight: 400;
78 | src: local('PT Sans'), local('PTSans-Regular'), url(https://fonts.gstatic.com/s/ptsans/v9/jizaRExUiTo99u79D0yExcOPIDUg-g.woff2) format('woff2');
79 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
80 | }
81 | /* latin */
82 | @font-face {
83 | font-family: 'PT Sans';
84 | font-style: normal;
85 | font-weight: 400;
86 | src: local('PT Sans'), local('PTSans-Regular'), url(https://fonts.gstatic.com/s/ptsans/v9/jizaRExUiTo99u79D0KExcOPIDU.woff2) format('woff2');
87 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
88 | }
89 | /* cyrillic-ext */
90 | @font-face {
91 | font-family: 'PT Sans';
92 | font-style: normal;
93 | font-weight: 700;
94 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(https://fonts.gstatic.com/s/ptsans/v9/jizfRExUiTo99u79B_mh0OOtLR8a8zILig.woff2) format('woff2');
95 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
96 | }
97 | /* cyrillic */
98 | @font-face {
99 | font-family: 'PT Sans';
100 | font-style: normal;
101 | font-weight: 700;
102 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(https://fonts.gstatic.com/s/ptsans/v9/jizfRExUiTo99u79B_mh0OqtLR8a8zILig.woff2) format('woff2');
103 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
104 | }
105 | /* latin-ext */
106 | @font-face {
107 | font-family: 'PT Sans';
108 | font-style: normal;
109 | font-weight: 700;
110 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(https://fonts.gstatic.com/s/ptsans/v9/jizfRExUiTo99u79B_mh0OCtLR8a8zILig.woff2) format('woff2');
111 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
112 | }
113 | /* latin */
114 | @font-face {
115 | font-family: 'PT Sans';
116 | font-style: normal;
117 | font-weight: 700;
118 | src: local('PT Sans Bold'), local('PTSans-Bold'), url(https://fonts.gstatic.com/s/ptsans/v9/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2) format('woff2');
119 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
120 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import AutoNumeric from "autonumeric";
4 |
5 | export default class ReactNumeric extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | this.getValue = this.getValue.bind(this);
9 | this.callEventHandler = this.callEventHandler.bind(this);
10 | }
11 | componentDidMount() {
12 | this.autonumeric = new AutoNumeric(this.input, this.props.value, {
13 | ...this.props.preDefined,
14 | ...this.props,
15 | onChange: undefined,
16 | onFocus: undefined,
17 | onBlur: undefined,
18 | onKeyPress: undefined,
19 | onKeyUp: undefined,
20 | onKeyDown: undefined,
21 | watchExternalChanges: false,
22 | });
23 | }
24 | componentWillUnmount() {
25 | if (this.autonumeric) this.autonumeric.remove();
26 | }
27 |
28 | componentWillReceiveProps(newProps) {
29 | const isOptionsChanged =
30 | JSON.stringify({ ...this.props, value: undefined }) !==
31 | JSON.stringify({ ...newProps, value: undefined });
32 | const isValueChanged =
33 | this.props.value !== newProps.value && this.getValue() !== newProps.value;
34 | if (isValueChanged) {
35 | this.autonumeric.set(newProps.value);
36 | }
37 | if (isOptionsChanged) {
38 | this.autonumeric.update({
39 | ...newProps.preDefined,
40 | ...newProps,
41 | onChange: undefined,
42 | onFocus: undefined,
43 | onBlur: undefined,
44 | onKeyPress: undefined,
45 | onKeyUp: undefined,
46 | onKeyDown: undefined,
47 | watchExternalChanges: false,
48 | });
49 | }
50 | }
51 | getValue() {
52 | if (!this.autonumeric) return;
53 | const valueMapper = {
54 | string: numeric => numeric.getNumericString(),
55 | number: numeric => numeric.getNumber(),
56 | };
57 | return valueMapper[this.props.outputFormat](this.autonumeric);
58 | }
59 | callEventHandler(event, eventName) {
60 | if (!this.props[eventName]) return;
61 | this.props[eventName](event, this.getValue());
62 | }
63 | render() {
64 | const inputProps = {};
65 | [
66 | "id",
67 | "className",
68 | "style",
69 | "disabled",
70 | "type",
71 | "name",
72 | "tabIndex",
73 | "unselectable",
74 | "size",
75 | "autoFocus",
76 | "placeholder",
77 | ].forEach(prop => (inputProps[prop] = this.props[prop]));
78 | return (
79 | (this.input = ref)}
81 | onChange={e => this.callEventHandler(e, "onChange")}
82 | onFocus={e => this.callEventHandler(e, "onFocus")}
83 | onBlur={e => this.callEventHandler(e, "onBlur")}
84 | onKeyPress={e => this.callEventHandler(e, "onKeyPress")}
85 | onKeyUp={e => this.callEventHandler(e, "onKeyUp")}
86 | onKeyDown={e => this.callEventHandler(e, "onKeyDown")}
87 | {...inputProps}
88 | />
89 | );
90 | }
91 | }
92 |
93 | ReactNumeric.propTypes = {
94 | type: PropTypes.oneOf(["text", "tel", "hidden"]),
95 | id: PropTypes.string,
96 | className: PropTypes.string,
97 | style: PropTypes.object,
98 | disabled: PropTypes.bool,
99 | name: PropTypes.string,
100 | tabIndex: PropTypes.number,
101 | unselectable: PropTypes.bool,
102 | size: PropTypes.number,
103 | autoFocus: PropTypes.bool,
104 | placeholder: PropTypes.string,
105 | value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
106 | onChange: PropTypes.func,
107 | onFocus: PropTypes.func,
108 | onBlur: PropTypes.func,
109 | onKeyPress: PropTypes.func,
110 | onKeyUp: PropTypes.func,
111 | onKeyDown: PropTypes.func,
112 | allowDecimalPadding: PropTypes.bool,
113 | caretPositionOnFocus: PropTypes.number,
114 | createLocalList: PropTypes.bool,
115 | currencySymbol: PropTypes.string,
116 | currencySymbolPlacement: PropTypes.string,
117 | decimalCharacter: PropTypes.string,
118 | decimalCharacterAlternative: PropTypes.string,
119 | decimalPlaces: PropTypes.number,
120 | decimalPlacesRawValue: PropTypes.number,
121 | decimalPlacesShownOnBlur: PropTypes.number,
122 | decimalPlacesShownOnFocus: PropTypes.number,
123 | defaultValueOverride: PropTypes.string,
124 | digitalGroupSpacing: PropTypes.string,
125 | digitGroupSeparator: PropTypes.string,
126 | divisorWhenUnfocused: PropTypes.number,
127 | emptyInputBehavior: PropTypes.oneOf(["null", "focus", "press", "always", "zero"]),
128 | eventBubbles: PropTypes.bool,
129 | eventIsCancelable: PropTypes.bool,
130 | failOnUnknownOption: PropTypes.bool,
131 | formatOnPageLoad: PropTypes.bool,
132 | historySize: PropTypes.number,
133 | isCancellable: PropTypes.bool,
134 | leadingZero: PropTypes.oneOf(["allow", "deny", "keep"]),
135 | maximumValue: PropTypes.string,
136 | minimumValue: PropTypes.string,
137 | modifyValueOnWheel: PropTypes.bool,
138 | negativeBracketsTypeOnBlur: PropTypes.string,
139 | negativePositiveSignPlacement: PropTypes.oneOf(["l", "r", "p", "s"]),
140 | negativeSignCharacter: PropTypes.string,
141 | noEventListeners: PropTypes.bool,
142 | onInvalidPaste: PropTypes.oneOf(["error", "ignore", "clamp", "truncate", "replace"]),
143 | outputFormat: PropTypes.oneOf(["string", "number"]),
144 | overrideMinMaxLimits: PropTypes.oneOf(["ceiling", "floor", "ignore"]),
145 | positiveSignCharacter: PropTypes.string,
146 | rawValueDivisor: PropTypes.number,
147 | readOnly: PropTypes.bool,
148 | roundingMethod: PropTypes.string,
149 | saveValueToSessionStorage: PropTypes.bool,
150 | selectNumberOnly: PropTypes.bool,
151 | selectOnFocus: PropTypes.bool,
152 | serializeSpaces: PropTypes.string,
153 | showOnlyNumbersOnFocus: PropTypes.bool,
154 | showPositiveSign: PropTypes.bool,
155 | showWarnings: PropTypes.bool,
156 | styleRules: PropTypes.object,
157 | suffixText: PropTypes.string,
158 | symbolWhenUnfocused: PropTypes.string,
159 | unformatOnHover: PropTypes.bool,
160 | unformatOnSubmit: PropTypes.bool,
161 | valuesToStrings: PropTypes.object,
162 | wheelOn: PropTypes.oneOf(["focus", "hover"]),
163 | wheelStep: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
164 | preDefined: PropTypes.object,
165 | };
166 |
167 | ReactNumeric.defaultProps = {
168 | type: "text",
169 | outputFormat: "number",
170 | preDefined: {},
171 | className: "asdf",
172 | };
173 |
174 | export const predefinedOptions = AutoNumeric.getPredefinedOptions();
175 |
--------------------------------------------------------------------------------