Skip to content

Commit

Permalink
Do not extend the utility component anymore
Browse files Browse the repository at this point in the history
  • Loading branch information
igorlima committed Apr 28, 2019
1 parent 2751de5 commit 1d84d1d
Show file tree
Hide file tree
Showing 8 changed files with 765 additions and 502 deletions.
136 changes: 136 additions & 0 deletions src/card-cvc-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// @flow

import { Component } from 'react';
import payment from 'payment';
import { checkIsNumeric, handleKeyDown, inputRenderer } from './utils';
import {
formatCvc,
hasCVCReachedMaxLength,
isHighlighted
} from './utils/formatter';

type Props = {
autoAdvance: Function,
cardCVCInputProps: Object,
cardNumber: ?string,
customTextLabels: Object,
enableZipInput: boolean,
inputClassName: string,
setback: Function,
setFieldInvalid: Function,
setFieldValid: Function,
showZip: boolean
};

type State = {};

class CardCVCInput extends Component<Props, State> {
cardExpiryField: any;
cvcField: any;

static defaultProps = {
autoAdvance: () => {},
cardCVCInputProps: {},
cardNumber: '',
customTextLabels: {},
enableZipInput: false,
inputClassName: '',
setback: () => {},
setFieldInvalid: () => {},
setFieldValid: () => {},
showZip: false
};

handleCardCVCBlur = (
{ onBlur }: { onBlur?: ?Function } = { onBlur: null }
) => (e: SyntheticInputEvent<*>) => {
const { customTextLabels } = this.props;
if (!payment.fns.validateCardCVC(e.target.value)) {
this.props.setFieldInvalid(
customTextLabels.invalidCvc || 'CVC is invalid'
);
}

const { cardCVCInputProps } = this.props;
cardCVCInputProps.onBlur && cardCVCInputProps.onBlur(e);
onBlur && onBlur(e);
};

handleCardCVCChange = (
{ onChange }: { onChange?: ?Function } = { onChange: null }
) => (e: SyntheticInputEvent<*>) => {
const {
autoAdvance,
cardNumber,
customTextLabels,
enableZipInput,
showZip
} = this.props;
const value = formatCvc(e.target.value);
this.cvcField.value = value;
const CVC = value;
const CVCLength = CVC.length;
const isZipFieldAvailable = enableZipInput && showZip;
const cardType = payment.fns.cardType(cardNumber);

this.props.setFieldValid();
if (CVCLength >= 4) {
if (!payment.fns.validateCardCVC(CVC, cardType)) {
this.props.setFieldInvalid(
customTextLabels.invalidCvc || 'CVC is invalid'
);
}
}

if (isZipFieldAvailable && hasCVCReachedMaxLength(cardType, CVCLength)) {
autoAdvance && autoAdvance();
}

const { cardCVCInputProps } = this.props;
cardCVCInputProps.onChange && cardCVCInputProps.onChange(e);
onChange && onChange(e);
};

handleCardCVCKeyPress = (e: any) => {
const cardType = payment.fns.cardType(this.props.cardNumber);
const value = e.target.value;
checkIsNumeric(e);
if (value && !isHighlighted()) {
const valueLength = value.split(' / ').join('').length;
if (hasCVCReachedMaxLength(cardType, valueLength)) {
e.preventDefault();
}
}
};

focus = () => {
this.cvcField.focus();
};

render = () => {
const { cardCVCInputProps, inputClassName, customTextLabels } = this.props;

return inputRenderer({
handleCardCVCChange: onChange => this.handleCardCVCChange({ onChange }),
handleCardCVCBlur: onBlur => this.handleCardCVCBlur({ onBlur }),
props: {
id: 'cvc',
ref: cvcField => {
this.cvcField = cvcField;
},
maxLength: '5',
autoComplete: 'off',
className: `credit-card-input ${inputClassName}`,
placeholder: customTextLabels.cvcPlaceholder || 'CVC',
type: 'tel',
...cardCVCInputProps,
onBlur: this.handleCardCVCBlur(),
onChange: this.handleCardCVCChange(),
onKeyDown: handleKeyDown(this.props.setback),
onKeyPress: this.handleCardCVCKeyPress
}
});
};
}

export default CardCVCInput;
130 changes: 130 additions & 0 deletions src/card-expiry-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// @flow

import { Component } from 'react';
import {
checkIsNumeric,
handleKeyDown,
inputRenderer,
isMonthDashKey
} from './utils';
import { formatExpiry, isHighlighted } from './utils/formatter';
import isExpiryInvalid from './utils/is-expiry-invalid';

type Props = {
autoAdvance: Function,
cardExpiryInputProps: Object,
customTextLabels: Object,
inputClassName: string,
setback: Function,
setFieldInvalid: Function,
setFieldValid: Function
};

type State = {};

class CardExpiryInput extends Component<Props, State> {
cardExpiryField: any;
cardNumberField: any;
cvcField: any;

static defaultProps = {
autoAdvance: () => {},
cardExpiryInputProps: {},
customTextLabels: {},
inputClassName: '',
setback: () => {},
setFieldInvalid: () => {},
setFieldValid: () => {}
};

handleCardExpiryBlur = (
{ onBlur }: { onBlur?: ?Function } = { onBlur: null }
) => (e: SyntheticInputEvent<*>) => {
const { customTextLabels } = this.props;
const cardExpiry = e.target.value.split(' / ').join('/');
const expiryError = isExpiryInvalid(
cardExpiry,
customTextLabels.expiryError
);
if (expiryError) {
this.props.setFieldInvalid(expiryError);
}

const { cardExpiryInputProps } = this.props;
cardExpiryInputProps.onBlur && cardExpiryInputProps.onBlur(e);
onBlur && onBlur(e);
};

handleCardExpiryChange = (
{ onChange }: { onChange?: ?Function } = { onChange: null }
) => (e: SyntheticInputEvent<*>) => {
const { customTextLabels, autoAdvance } = this.props;

this.cardExpiryField.value = formatExpiry(e);
const value = this.cardExpiryField.value.split(' / ').join('/');

this.props.setFieldValid();

const expiryError = isExpiryInvalid(value, customTextLabels.expiryError);
if (value.length > 4) {
if (expiryError) {
this.props.setFieldInvalid(expiryError);
} else {
autoAdvance && autoAdvance();
}
}

const { cardExpiryInputProps } = this.props;
cardExpiryInputProps.onChange && cardExpiryInputProps.onChange(e);
onChange && onChange(e);
};

handleCardExpiryKeyPress = (e: any) => {
const value = e.target.value;

if (!isMonthDashKey(e)) {
checkIsNumeric(e);
}

if (value && !isHighlighted()) {
const valueLength = value.split(' / ').join('').length;
if (valueLength >= 4) {
e.preventDefault();
}
}
};

focus = () => {
this.cardExpiryField.focus();
};

render = () => {
const {
cardExpiryInputProps,
inputClassName,
customTextLabels
} = this.props;
return inputRenderer({
handleCardExpiryChange: onChange =>
this.handleCardExpiryChange({ onChange }),
handleCardExpiryBlur: onBlur => this.handleCardExpiryBlur({ onBlur }),
props: {
id: 'card-expiry',
ref: cardExpiryField => {
this.cardExpiryField = cardExpiryField;
},
autoComplete: 'cc-exp',
className: `credit-card-input ${inputClassName}`,
placeholder: customTextLabels.expiryPlaceholder || 'MM/YY',
type: 'tel',
...cardExpiryInputProps,
onBlur: this.handleCardExpiryBlur(),
onChange: this.handleCardExpiryChange(),
onKeyDown: handleKeyDown(this.props.setback),
onKeyPress: this.handleCardExpiryKeyPress
}
});
};
}

export default CardExpiryInput;
Loading

0 comments on commit 1d84d1d

Please sign in to comment.