From 85529728e581b95466fca05f71e747f517754dc5 Mon Sep 17 00:00:00 2001 From: jxom Date: Sun, 4 Feb 2018 21:22:10 +1100 Subject: [PATCH] Flowify --- .flowconfig | 11 ++++ package-lock.json | 14 +++-- package.json | 6 ++- rollup.config.js | 6 +-- src/index.js | 133 +++++++++++++++++++++++++--------------------- 5 files changed, 98 insertions(+), 72 deletions(-) create mode 100644 .flowconfig diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..1fed445 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,11 @@ +[ignore] + +[include] + +[libs] + +[lints] + +[options] + +[strict] diff --git a/package-lock.json b/package-lock.json index 568e6c4..1492d3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1709,14 +1709,14 @@ "dev": true, "requires": { "babel-runtime": "6.26.0", - "core-js": "2.5.1", + "core-js": "2.5.3", "regenerator-runtime": "0.10.5" }, "dependencies": { "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", "dev": true }, "regenerator-runtime": { @@ -3870,6 +3870,12 @@ "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", "dev": true }, + "flow-bin": { + "version": "0.64.0", + "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.64.0.tgz", + "integrity": "sha1-3dP7Oxg6sas1pdXeycr167ze0Wc=", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", diff --git a/package.json b/package.json index 4932170..a6a8294 100644 --- a/package.json +++ b/package.json @@ -15,17 +15,17 @@ "prepublish": "npm run build", "lint": "eslint src/", "fix": "npm run lint -- --fix && npm run prettier", + "flow": "flow", "prettier": "prettier --config .prettierrc --write 'src/**/*.js'", "prettier:list-diff": "prettier --config .prettierrc --list-different 'src/**/*.js'", "storybook": "start-storybook -p 9001 -c .storybook", "storybook:build": "build-storybook -c .storybook -o docs/", - "test": "npm run lint && npm run prettier:list-diff" + "test": "npm run lint && npm run flow && npm run prettier:list-diff" }, "dependencies": { "babel-loader": "^7.1.2", "credit-card-type": "^6.1.0", "payment": "^2.3.0", - "prop-types": "^15.6.0", "styled-components": "^2.2.3" }, "devDependencies": { @@ -37,6 +37,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-object-rest-spread": "6.26.0", "babel-preset-env": "^1.6.1", + "babel-preset-flow": "^6.23.0", "babel-preset-react": "^6.24.1", "eslint": "^4.11.0", "eslint-config-react-app": "^2.0.1", @@ -44,6 +45,7 @@ "eslint-plugin-jsx-a11y": "^6.0.2", "eslint-plugin-prettier": "^2.3.1", "eslint-plugin-react": "^7.4.0", + "flow-bin": "^0.64.0", "prettier": "^1.8.2", "react": "^16.1.1", "react-dom": "^16.1.1", diff --git a/rollup.config.js b/rollup.config.js index 376f669..8258af9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,7 +9,6 @@ export default { globals: { react: 'React', 'react-dom': 'ReactDOM', - 'prop-types': 'PropTypes', payment: 'payment', 'credit-card-type': 'creditCardType', 'styled-components': 'styled' @@ -20,12 +19,11 @@ export default { 'react-dom', 'credit-card-type', 'payment', - 'styled-components', - 'prop-types' + 'styled-components' ], plugins: [ babel({ - presets: [['env', { modules: false }], 'react'], + presets: [['env', { modules: false }], 'react', 'flow'], plugins: [ 'external-helpers', 'transform-class-properties', diff --git a/src/index.js b/src/index.js index 7384dce..1a3b391 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ +// @flow + import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import payment from 'payment'; import creditCardType from 'credit-card-type'; import styled from 'styled-components'; @@ -66,29 +67,35 @@ const CARD_TYPES = { amex: 'AMERICAN_EXPRESS' }; -class CreditCardInput extends Component { - static propTypes = { - cardExpiryInputProps: PropTypes.object, - cardNumberInputProps: PropTypes.object, - cardCVCInputProps: PropTypes.object, - cardImageClassName: PropTypes.string, - cardImageStyle: PropTypes.object, - containerClassName: PropTypes.string, - containerStyle: PropTypes.object, - dangerTextClassName: PropTypes.string, - dangerTextStyle: PropTypes.object, - fieldClassName: PropTypes.string, - fieldStyle: PropTypes.object, - inputComponent: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.object, - PropTypes.string - ]), - inputClassName: PropTypes.string, - inputStyle: PropTypes.object, - invalidClassName: PropTypes.string, - invalidStyle: PropTypes.object - }; +type Props = { + cardExpiryInputProps: Object, + cardNumberInputProps: Object, + cardCVCInputProps: Object, + cardImageClassName: string, + cardImageStyle: Object, + containerClassName: string, + containerStyle: Object, + dangerTextClassName: string, + dangerTextStyle: Object, + fieldClassName: string, + fieldStyle: Object, + inputComponent: Function | Object | string, + inputClassName: string, + inputStyle: Object, + invalidClassName: string, + invalidStyle: Object +}; +type State = { + cardImage: string, + cardNumberLength: number, + cardNumber: string, + errorText: ?string +}; + +class CreditCardInput extends Component { + cardExpiryField: any; + cardNumberField: any; + cvcField: any; static defaultProps = { cardExpiryInputProps: {}, @@ -109,7 +116,7 @@ class CreditCardInput extends Component { invalidStyle: {} }; - constructor(props) { + constructor(props: Props) { super(props); this.state = { cardImage: images.placeholder, @@ -117,26 +124,17 @@ class CreditCardInput extends Component { cardNumber: props.cardNumberInputProps.value, errorText: null }; - this.handleCardNumberBlur = this.handleCardNumberBlur.bind(this); - this.handleCardNumberChange = this.handleCardNumberChange.bind(this); - this.handleCardExpiryBlur = this.handleCardExpiryBlur.bind(this); - this.handleCardExpiryChange = this.handleCardExpiryChange.bind(this); - this.handleCVCBlur = this.handleCVCBlur.bind(this); - this.handleCVCChange = this.handleCVCChange.bind(this); - this.handleKeyDown = this.handleKeyDown.bind(this); - this.setFieldInvalid = this.setFieldInvalid.bind(this); - this.setFieldValid = this.setFieldValid.bind(this); } - componentDidMount() { + componentDidMount = () => { const { cardNumber } = this.state; const cardType = payment.fns.cardType(cardNumber); this.setState({ cardImage: images[cardType] || images.placeholder }); - } + }; - handleCardNumberBlur(e) { + handleCardNumberBlur = (e: SyntheticInputEvent<*>) => { if (!payment.fns.validateCardNumber(e.target.value)) { this.setFieldInvalid('Card number is invalid'); } @@ -145,9 +143,9 @@ class CreditCardInput extends Component { if (cardNumberInputProps.onBlur) { cardNumberInputProps.onBlur(e); } - } + }; - handleCardNumberChange(e) { + handleCardNumberChange = (e: SyntheticInputEvent<*>) => { const cardNumber = e.target.value; const cardNumberLength = cardNumber.split(' ').join('').length; const cardType = payment.fns.cardType(cardNumber); @@ -170,7 +168,7 @@ class CreditCardInput extends Component { length === cardNumberLength && payment.fns.validateCardNumber(cardNumber) ) { - document.getElementById('card-expiry').focus(); + this.cardExpiryField.focus(); break; } if (cardNumberLength === lastCardTypeLength) { @@ -183,9 +181,9 @@ class CreditCardInput extends Component { if (cardNumberInputProps.onChange) { cardNumberInputProps.onChange(e); } - } + }; - handleCardExpiryBlur(e) { + handleCardExpiryBlur = (e: SyntheticInputEvent<*>) => { if (!payment.fns.validateCardExpiry(e.target.value)) { this.setFieldInvalid('Expiry date is invalid'); } @@ -194,9 +192,9 @@ class CreditCardInput extends Component { if (cardExpiryInputProps.onBlur) { cardExpiryInputProps.onBlur(e); } - } + }; - handleCardExpiryChange(e) { + handleCardExpiryChange = (e: SyntheticInputEvent<*>) => { const cardExpiry = e.target.value; const cardExpiryLength = cardExpiry.split(' / ').join('').length; payment.formatCardExpiry(document.getElementById('card-expiry')); @@ -204,7 +202,7 @@ class CreditCardInput extends Component { this.setFieldValid(); if (cardExpiryLength >= 4) { if (payment.fns.validateCardExpiry(cardExpiry)) { - document.getElementById('cvc').focus(); + this.cvcField.focus(); } else { this.setFieldInvalid('Expiry date is invalid'); } @@ -214,9 +212,9 @@ class CreditCardInput extends Component { if (cardExpiryInputProps.onChange) { cardExpiryInputProps.onChange(e); } - } + }; - handleCVCBlur(e) { + handleCVCBlur = (e: SyntheticInputEvent<*>) => { if (!payment.fns.validateCardCVC(e.target.value)) { this.setFieldInvalid('CVC is invalid'); } @@ -225,9 +223,9 @@ class CreditCardInput extends Component { if (cardCVCInputProps.onBlur) { cardCVCInputProps.onBlur(e); } - } + }; - handleCVCChange(e) { + handleCVCChange = (e: SyntheticInputEvent<*>) => { const CVC = e.target.value; const CVCLength = CVC.length; payment.formatCardCVC(document.getElementById('cvc')); @@ -244,29 +242,31 @@ class CreditCardInput extends Component { if (cardCVCInputProps.onChange) { cardCVCInputProps.onChange(e); } - } + }; - handleKeyDown(targetFocusId) { - return e => { + handleKeyDown = (ref: any) => { + return (e: SyntheticInputEvent<*>) => { if (e.keyCode === BACKSPACE_KEY_CODE && !e.target.value) { - document.getElementById(targetFocusId).focus(); + ref.focus(); } }; - } + }; - setFieldInvalid(errorText) { + setFieldInvalid = (errorText: string) => { const { invalidClassName } = this.props; + // $FlowFixMe document.getElementById('field-wrapper').classList.add(invalidClassName); this.setState({ errorText }); - } + }; - setFieldValid(errorText) { + setFieldValid = () => { const { invalidClassName } = this.props; + // $FlowFixMe document.getElementById('field-wrapper').classList.remove(invalidClassName); this.setState({ errorText: null }); - } + }; - render() { + render = () => { const { cardImage, errorText } = this.state; const { cardExpiryInputProps, @@ -304,6 +304,9 @@ class CreditCardInput extends Component { > { + this.cardNumberField = cardNumberField; + }} autoComplete="cc-number" className={`credit-card-input ${inputClassName}`} pattern="[0-9]*" @@ -318,6 +321,9 @@ class CreditCardInput extends Component { { + this.cardExpiryField = cardExpiryField; + }} autoComplete="cc-exp" className={`credit-card-input ${inputClassName}`} pattern="[0-9]*" @@ -327,12 +333,15 @@ class CreditCardInput extends Component { {...cardExpiryInputProps} onBlur={this.handleCardExpiryBlur} onChange={this.handleCardExpiryChange} - onKeyDown={this.handleKeyDown('card-number')} + onKeyDown={this.handleKeyDown(this.cardNumberField)} /> { + this.cvcField = cvcField; + }} autoComplete="cc-csc" className={`credit-card-input ${inputClassName}`} pattern="[0-9]*" @@ -342,7 +351,7 @@ class CreditCardInput extends Component { {...cardCVCInputProps} onBlur={this.handleCVCBlur} onChange={this.handleCVCChange} - onKeyDown={this.handleKeyDown('card-expiry')} + onKeyDown={this.handleKeyDown(this.cardExpiryField)} /> @@ -353,7 +362,7 @@ class CreditCardInput extends Component { )} ); - } + }; } export default CreditCardInput;