react-currency-input-field
Advanced tools
| name: Main | ||
| on: | ||
| push: | ||
| branches: | ||
| - master | ||
| jobs: | ||
| install-build-and-test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v1 | ||
| - name: Install dependencies | ||
| run: | | ||
| npm install | ||
| npm install react | ||
| - name: Build package | ||
| run: npm run build | ||
| - name: Run tests | ||
| run: npm run test | ||
| - name: Configure CI Git User | ||
| run: | | ||
| git remote rm origin | ||
| git remote add origin "https://$USER_NAME:$GITHUB_PERSONAL_ACCESS_TOKEN@github.com/cchanxzy/React-Currency-Input-Field.git" | ||
| git fetch origin | ||
| git config --global user.email "actions@github.com" | ||
| git config --global user.name "GitHub Actions" | ||
| env: | ||
| GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.GITHUB_PERSONAL_ACCESS_TOKEN }} | ||
| USER_NAME: ${{ secrets.USER_NAME }} | ||
| - name: Prepare new release | ||
| run: | | ||
| npm run release | ||
| git push --follow-tags origin HEAD:master | ||
| release: | ||
| needs: install-build-and-test | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v1 | ||
| - uses: actions/setup-node@v1 | ||
| with: | ||
| node-version: 12 | ||
| registry-url: https://registry.npmjs.org/ | ||
| - name: Publish to NPM | ||
| run: npm publish | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} |
| { | ||
| "trailingComma": "es5", | ||
| "printWidth": 100, | ||
| "semi": true, | ||
| "singleQuote": true | ||
| } |
Sorry, the diff of this file is not supported yet
| import { shallow } from 'enzyme'; | ||
| import React from 'react'; | ||
| import CurrencyInput from '../CurrencyInput'; | ||
| describe('<CurrencyInput /> component', () => { | ||
| it('Renders without error', () => { | ||
| const id = 'validationCustom01'; | ||
| const placeholder = '£1,000'; | ||
| const className = 'form-control'; | ||
| const view = shallow( | ||
| <CurrencyInput id={id} placeholder={placeholder} className={className} onChange={jest.fn()} /> | ||
| ); | ||
| const input = view.find('#validationCustom01'); | ||
| expect(input).toMatchSnapshot(); | ||
| expect(input.prop('id')).toBe(id); | ||
| expect(input.prop('placeholder')).toBe(placeholder); | ||
| expect(input.prop('className')).toBe(className); | ||
| }); | ||
| it('should allow input change value', () => { | ||
| const onChange = jest.fn(); | ||
| const view = shallow( | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="£1,000" | ||
| className="form-control" | ||
| prefix="£" | ||
| onChange={onChange} | ||
| /> | ||
| ); | ||
| const input = view.find('#validationCustom01'); | ||
| input.simulate('change', { target: { value: '100' } }); | ||
| expect(onChange).toBeCalledWith(100); | ||
| }); | ||
| it('should allow empty value change', () => { | ||
| const onChange = jest.fn(); | ||
| const view = shallow( | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="£1,000" | ||
| className="form-control" | ||
| prefix="£" | ||
| onChange={onChange} | ||
| /> | ||
| ); | ||
| const input = view.find('#validationCustom01'); | ||
| input.simulate('change', { target: { value: '' } }); | ||
| expect(onChange).toBeCalledWith(null); | ||
| }); | ||
| it('should not allow string value change', () => { | ||
| const onChange = jest.fn(); | ||
| const view = shallow( | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="£1,000" | ||
| className="form-control" | ||
| prefix="£" | ||
| onChange={onChange} | ||
| /> | ||
| ); | ||
| const input = view.find('#validationCustom01'); | ||
| input.simulate('change', { target: { value: 'aakoa' } }); | ||
| expect(onChange).toBeCalledWith(NaN); | ||
| }); | ||
| }); |
| import { addCommas, checkIsValidNumber, removeCommas } from '../utilities'; | ||
| describe('addCommas', () => { | ||
| it('should remove commas in string', () => { | ||
| const value = addCommas(1000000); | ||
| expect(value).toEqual('1,000,000'); | ||
| }); | ||
| }); | ||
| describe('removeCommas', () => { | ||
| it('should remove commas in string', () => { | ||
| const value = removeCommas('1,000,000'); | ||
| expect(value).toEqual('1000000'); | ||
| }); | ||
| }); | ||
| describe('checkIsValidNumber', () => { | ||
| it('should return true if value is number', () => { | ||
| const check = checkIsValidNumber(1); | ||
| expect(check).toBe(true); | ||
| }); | ||
| it('should return true if value is 0', () => { | ||
| const check = checkIsValidNumber(0); | ||
| expect(check).toBe(true); | ||
| }); | ||
| it('should return false if value less than 0', () => { | ||
| const check = checkIsValidNumber(-1); | ||
| expect(check).toBe(false); | ||
| }); | ||
| it('should return false if value is not a number', () => { | ||
| const check = checkIsValidNumber('abc' as any); | ||
| expect(check).toBe(false); | ||
| }); | ||
| }); |
@@ -6,3 +6,3 @@ name: PR | ||
| jobs: | ||
| build: | ||
| install-build-and-test: | ||
| runs-on: ubuntu-latest | ||
@@ -12,9 +12,11 @@ | ||
| - uses: actions/checkout@v1 | ||
| - name: Dependencies | ||
| - name: Install dependencies | ||
| run: | | ||
| npm install | ||
| npm install react | ||
| - name: Test | ||
| - name: Build package | ||
| run: npm run build | ||
| - name: Run tests | ||
| run: npm run test | ||
| - name: Build | ||
| run: npm run build | ||
| - name: Prepare new release | ||
| run: npm run release -- --dry-run |
+42
-0
@@ -5,2 +5,44 @@ # Changelog | ||
| ### [0.0.47](https://github.com/cchanxzy/React-Currency-Input-Field/compare/v0.10.0...v0.0.47) (2019-09-08) | ||
| ## 0.10.0 (2019-09-08) | ||
| ### ⚠ BREAKING CHANGES | ||
| * removed limit prop | ||
| * removed limit prop, updated tests and examples ([ed24b8e](https://github.com/cchanxzy/React-Currency-Input-Field/commit/ed24b8e)) | ||
| ### Bug Fixes | ||
| * updated packages ([7e80871](https://github.com/cchanxzy/React-Currency-Input-Field/commit/7e80871)) | ||
| ## 0.1.0 (2019-09-08) | ||
| ### ⚠ BREAKING CHANGES | ||
| * removed limit prop | ||
| * removed limit prop, updated tests and examples ([ed24b8e](https://github.com/cchanxzy/React-Currency-Input-Field/commit/ed24b8e)) | ||
| ### Bug Fixes | ||
| * updated packages ([7e80871](https://github.com/cchanxzy/React-Currency-Input-Field/commit/7e80871)) | ||
| ### 0.0.47 (2019-09-08) | ||
| ### Bug Fixes | ||
| * updated packages ([7e80871](https://github.com/cchanxzy/React-Currency-Input-Field/commit/7e80871)) | ||
| ### Features | ||
| * upating tests and examples ([e18c23a](https://github.com/cchanxzy/React-Currency-Input-Field/commit/e18c23a)) | ||
| ### 0.0.46 (2019-08-29) | ||
@@ -7,0 +49,0 @@ |
+10
-7
| { | ||
| "name": "react-currency-input-field", | ||
| "version": "0.0.46", | ||
| "version": "0.0.47", | ||
| "description": "React input field component for currency and numbers", | ||
@@ -33,3 +33,3 @@ "main": "dist/index.js", | ||
| "@types/enzyme": "^3.1.14", | ||
| "@types/jest": "^23.3.2", | ||
| "@types/jest": "^24.0.18", | ||
| "@types/react": "^16.4.14", | ||
@@ -43,2 +43,4 @@ "@types/react-dom": "^16.0.7", | ||
| "jest": "^25.0.0", | ||
| "prettier": "^1.18.2", | ||
| "react": "^16.9.0", | ||
| "react-dom": "^16.5.2", | ||
@@ -48,5 +50,8 @@ "react-hot-loader": "^4.3.11", | ||
| "standard-version": "^7.0.0", | ||
| "ts-jest": "^23.10.1", | ||
| "ts-jest": "^24.0.2", | ||
| "tslint": "^5.11.0", | ||
| "tslint-config-airbnb": "^5.11.0", | ||
| "tslint-config-prettier": "^1.18.0", | ||
| "tslint-plugin-prettier": "^2.0.1", | ||
| "tslint-react": "^4.0.0", | ||
| "typescript": "^3.0.3", | ||
@@ -58,4 +63,5 @@ "webpack": "^4.19.1", | ||
| "peerDependencies": { | ||
| "react": "^16.5.2" | ||
| "react": "^16.9.0" | ||
| }, | ||
| "dependencies": {}, | ||
| "jest": { | ||
@@ -77,5 +83,2 @@ "verbose": true, | ||
| }, | ||
| "dependencies": { | ||
| "react": "^16.9.0" | ||
| }, | ||
| "config": { | ||
@@ -82,0 +85,0 @@ "commitizen": { |
@@ -1,4 +0,4 @@ | ||
| import React, { PureComponent } from 'react'; | ||
| import React, { FC, useState } from 'react'; | ||
| import { addCommas, removeCommas, checkIsValidNumber } from './utilities'; | ||
| import { addCommas, checkIsValidNumber, removeCommas } from './utilities'; | ||
@@ -8,79 +8,53 @@ interface IProps { | ||
| className?: string; | ||
| limit?: number; | ||
| onChange: (value: number | null) => void; | ||
| placeholder?: string; | ||
| prefix?: string; | ||
| handleError?: () => void; | ||
| onChange: (value: number) => void; | ||
| placeholder?: string; | ||
| } | ||
| interface IState { | ||
| value: string; | ||
| } | ||
| export const CurrencyInput: FC<IProps> = ({ id, className, onChange, placeholder, prefix }) => { | ||
| const [value, setValue] = useState(''); | ||
| export class CurrencyInput extends PureComponent<IProps, IState> { | ||
| private constructor(props: IProps) { | ||
| super(props); | ||
| this.state = { | ||
| value: '', | ||
| }; | ||
| this.processChange = this.processChange.bind(this); | ||
| } | ||
| processChange(event: React.ChangeEvent<HTMLInputElement>) { | ||
| const processChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
| const { | ||
| target: { value }, | ||
| target: { value: eventVal }, | ||
| } = event; | ||
| const { onChange, limit, prefix } = this.props; | ||
| let stringValue = eventVal; | ||
| let stringValue = value; | ||
| if (prefix) { | ||
| stringValue = value.replace(prefix, ''); | ||
| stringValue = stringValue.replace(prefix, ''); | ||
| } | ||
| if (stringValue === '' || stringValue === null) { | ||
| this.setState({ | ||
| value: '', | ||
| }); | ||
| onChange(null); | ||
| return false; | ||
| return setValue(''); | ||
| } | ||
| let intValue = parseInt(removeCommas(stringValue), 10); | ||
| const intValue = parseInt(removeCommas(stringValue), 10); | ||
| const max = limit || 9999999999999; | ||
| if (checkIsValidNumber(intValue)) { | ||
| let newValue = addCommas(intValue); | ||
| if (checkIsValidNumber(intValue, max)) { | ||
| let setValue = addCommas(intValue); | ||
| if (prefix) { | ||
| setValue = `${prefix}${setValue}`; | ||
| newValue = `${prefix}${newValue}`; | ||
| } | ||
| this.setState({ value: setValue }); | ||
| setValue(newValue); | ||
| } | ||
| onChange(intValue); | ||
| } | ||
| }; | ||
| render() { | ||
| const { className, id, handleError, placeholder } = this.props; | ||
| return ( | ||
| <input | ||
| type="string" | ||
| id={id} | ||
| className={className} | ||
| onChange={processChange} | ||
| placeholder={placeholder} | ||
| value={value} | ||
| /> | ||
| ); | ||
| }; | ||
| const { value } = this.state; | ||
| return ( | ||
| <input | ||
| type="string" | ||
| id={id} | ||
| className={className} | ||
| onChange={this.processChange} | ||
| placeholder={placeholder} | ||
| value={value} | ||
| /> | ||
| ); | ||
| } | ||
| } | ||
| export default CurrencyInput; |
@@ -1,16 +0,11 @@ | ||
| export const addCommas = (value: number) => | ||
| value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); | ||
| export const addCommas = (value: number) => value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); | ||
| export const removeCommas = (value: string) => value.replace(/,/g, ''); | ||
| export const removeCommas = (value: string): string => value.replace(/,/g, ''); | ||
| export const checkIsValidNumber = (input: number, limit: number) => { | ||
| if (input === 0) { | ||
| return true; | ||
| } | ||
| if (input < 0 || Number.isNaN(input)) { | ||
| export const checkIsValidNumber = (input: number) => { | ||
| if (input < 0 || isNaN(input)) { | ||
| return false; | ||
| } | ||
| return input <= limit; | ||
| return true; | ||
| }; |
@@ -1,73 +0,44 @@ | ||
| import React, { PureComponent } from 'react'; | ||
| import { hot } from 'react-hot-loader'; | ||
| import React, { FC, useState } from 'react'; | ||
| import CurrencyInput from '../components/CurrencyInput'; | ||
| interface IState { | ||
| errorMessage: string; | ||
| inputClass: string; | ||
| } | ||
| export const Example1: FC = () => { | ||
| const limit = 1000; | ||
| const prefix = '£'; | ||
| export class Example extends PureComponent<{}, IState> { | ||
| private constructor(props: {}) { | ||
| super(props); | ||
| const [errorMessage, setErrorMessage] = useState(); | ||
| const [className, setClassName] = useState(); | ||
| this.state = { | ||
| errorMessage: '', | ||
| inputClass: '', | ||
| }; | ||
| this.validateValue = this.validateValue.bind(this); | ||
| } | ||
| private limit = 1000; | ||
| private prefix = '£'; | ||
| private validateValue(value: number) { | ||
| if (Number.isNaN(value)) { | ||
| this.setState({ | ||
| errorMessage: 'Please enter a valid number', | ||
| inputClass: 'is-invalid', | ||
| }); | ||
| } else if (value >= this.limit) { | ||
| this.setState({ | ||
| errorMessage: `Please enter a value equal or lower than ${this.prefix}${ | ||
| this.limit | ||
| }`, | ||
| inputClass: 'is-invalid', | ||
| }); | ||
| } else if (value === null) { | ||
| this.setState({ | ||
| inputClass: '', | ||
| }); | ||
| const validateValue = (value: number | null) => { | ||
| if (value === null) { | ||
| setClassName(''); | ||
| } else if (Number.isNaN(value)) { | ||
| setErrorMessage('Please enter a valid number'); | ||
| setClassName('is-invalid'); | ||
| } else if (value > limit) { | ||
| setErrorMessage(`Max: ${prefix}${limit}`); | ||
| setClassName('is-invalid'); | ||
| } else { | ||
| this.setState({ | ||
| inputClass: 'is-valid', | ||
| }); | ||
| setClassName('is-valid'); | ||
| } | ||
| } | ||
| }; | ||
| public render() { | ||
| return ( | ||
| <form className="needs-validation"> | ||
| <div className="form-row"> | ||
| <div className="col-sm-12"> | ||
| <label htmlFor="validationCustom01"> | ||
| Please enter a value (max £1,000) | ||
| </label> | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="£1,000" | ||
| className={`form-control ${this.state.inputClass}`} | ||
| onChange={this.validateValue} | ||
| limit={this.limit} | ||
| prefix={this.prefix} | ||
| /> | ||
| <div className="invalid-feedback">{this.state.errorMessage}</div> | ||
| </div> | ||
| return ( | ||
| <form className="needs-validation"> | ||
| <div className="form-row"> | ||
| <div className="col-sm-12"> | ||
| <label htmlFor="validationCustom01">Please enter a value (max £1,000)</label> | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="£1,000" | ||
| className={`form-control ${className}`} | ||
| onChange={validateValue} | ||
| prefix={prefix} | ||
| /> | ||
| <div className="invalid-feedback">{errorMessage}</div> | ||
| </div> | ||
| </form> | ||
| ); | ||
| } | ||
| } | ||
| </div> | ||
| </form> | ||
| ); | ||
| }; | ||
| export default hot(module)(Example); | ||
| export default Example1; |
@@ -1,63 +0,39 @@ | ||
| import React, { PureComponent } from 'react'; | ||
| import React, { FC, useState } from 'react'; | ||
| import { hot } from 'react-hot-loader'; | ||
| import CurrencyInput from '../components/CurrencyInput'; | ||
| interface IState { | ||
| errorMessage: string; | ||
| inputClass: string; | ||
| } | ||
| export const Example2: FC = () => { | ||
| const [errorMessage, setErrorMessage] = useState(); | ||
| const [className, setClassName] = useState(); | ||
| export class Example extends PureComponent<{}, IState> { | ||
| private constructor(props: {}) { | ||
| super(props); | ||
| this.state = { | ||
| errorMessage: '', | ||
| inputClass: '', | ||
| }; | ||
| this.validateValue = this.validateValue.bind(this); | ||
| } | ||
| private prefix = '$'; | ||
| private suffix = '.00'; | ||
| private validateValue(value: number) { | ||
| if (Number.isNaN(value)) { | ||
| this.setState({ | ||
| errorMessage: 'Please enter a valid number', | ||
| inputClass: 'is-invalid', | ||
| }); | ||
| } else if (value === null) { | ||
| this.setState({ | ||
| inputClass: '', | ||
| }); | ||
| const validateValue = (value: number | null) => { | ||
| if (value === null) { | ||
| setClassName(''); | ||
| } else if (Number.isNaN(value)) { | ||
| setErrorMessage('Please enter a valid number'); | ||
| setClassName('is-invalid'); | ||
| } else { | ||
| this.setState({ | ||
| inputClass: 'is-valid', | ||
| }); | ||
| setClassName('is-valid'); | ||
| } | ||
| } | ||
| }; | ||
| public render() { | ||
| return ( | ||
| <form className="needs-validation"> | ||
| <div className="form-row"> | ||
| <div className="col-sm-12"> | ||
| <label htmlFor="validationCustom01">Please input a value:</label> | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="$1999" | ||
| className={`form-control ${this.state.inputClass}`} | ||
| onChange={this.validateValue} | ||
| prefix={this.prefix} | ||
| /> | ||
| <div className="invalid-feedback">{this.state.errorMessage}</div> | ||
| </div> | ||
| return ( | ||
| <form className="needs-validation"> | ||
| <div className="form-row"> | ||
| <div className="col-sm-12"> | ||
| <label htmlFor="validationCustom01">Please input a value:</label> | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="$1999" | ||
| className={`form-control ${className}`} | ||
| onChange={validateValue} | ||
| prefix={'$'} | ||
| /> | ||
| <div className="invalid-feedback">{errorMessage}</div> | ||
| </div> | ||
| </form> | ||
| ); | ||
| } | ||
| } | ||
| </div> | ||
| </form> | ||
| ); | ||
| }; | ||
| export default hot(module)(Example); | ||
| export default hot(module)(Example2); |
+14
-9
| { | ||
| "compilerOptions": { | ||
| "outDir": "./dist/", | ||
| "sourceMap": true, | ||
| "noImplicitAny": true, | ||
| "module": "commonJs", | ||
| "target": "es5", | ||
| "lib": ["dom", "dom.iterable", "esnext"], | ||
| "allowJs": true, | ||
| "skipLibCheck": true, | ||
| "esModuleInterop": true, | ||
| "allowSyntheticDefaultImports": true, | ||
| "strict": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "module": "esnext", | ||
| "moduleResolution": "node", | ||
| "target": "es6", | ||
| "jsx": "react", | ||
| "esModuleInterop": true, | ||
| "declaration": true | ||
| "resolveJsonModule": true, | ||
| "isolatedModules": true, | ||
| "noEmit": true, | ||
| "jsx": "react" | ||
| }, | ||
| "include": ["./src/**/*"] | ||
| "include": ["src"] | ||
| } |
+7
-10
| { | ||
| "defaultSeverity": "error", | ||
| "extends": [ | ||
| "tslint:recommended", | ||
| "tslint-react", | ||
| "tslint-config-airbnb" | ||
| ], | ||
| "jsRules": {}, | ||
| "rules": {}, | ||
| "rulesDirectory": [] | ||
| } | ||
| "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"], | ||
| "rulesDirectory": ["tslint-plugin-prettier"], | ||
| "rules": { | ||
| "prettier": true, | ||
| "interface-name": false | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet
| import { shallow } from 'enzyme'; | ||
| import React from 'react'; | ||
| import CurrencyInput from '../../src/components/CurrencyInput'; | ||
| describe('<CurrencyInput /> component', () => { | ||
| test('Renders without error', () => { | ||
| const view = shallow( | ||
| <CurrencyInput | ||
| id="validationCustom01" | ||
| placeholder="£1,000" | ||
| className="form-control" | ||
| onChange={() => {}} | ||
| /> | ||
| ); | ||
| const component = view.find('#settings__checkbox'); | ||
| expect(component).toMatchSnapshot(); | ||
| }); | ||
| }); |
| name: CI | ||
| on: | ||
| push: | ||
| branches: | ||
| - master | ||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v1 | ||
| - name: Dependencies | ||
| run: | | ||
| npm install | ||
| npm install react | ||
| - name: Test | ||
| run: npm run test | ||
| - name: Build | ||
| run: npm run build | ||
| - name: Release | ||
| run: npm run release | ||
| - name: Publish | ||
| run: | | ||
| echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ./.npmrc | ||
| npm publish |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
40848
9.22%1
-50%28
7.69%387
2.65%28
21.74%- Removed