import React from 'react' import PropTypes from 'prop-types' import createTextMaskInputElement from '../../core/src/createTextMaskInputElement' import {isNil} from '../../core/src/utilities' export default class MaskedInput extends React.PureComponent { constructor(...args) { super(...args) this.setRef = this.setRef.bind(this) this.onBlur = this.onBlur.bind(this) this.onChange = this.onChange.bind(this) } setRef(inputElement) { this.inputElement = inputElement } initTextMask() { const {props, props: {value}} = this this.textMaskInputElement = createTextMaskInputElement({ inputElement: this.inputElement, ...props, }) this.textMaskInputElement.update(value) } componentDidMount() { this.initTextMask() } componentDidUpdate(prevProps) { // Getting props affecting value const {value, pipe, mask, guide, placeholderChar, showMask} = this.props // Сalculate that settings was changed: // - `pipe` converting to string, to compare function content // - `mask` converting to string, to compare values or function content // - `keepCharPositions` exludes, because it affect only cursor position const settings = {guide, placeholderChar, showMask} const isPipeChanged = typeof pipe === 'function' && typeof prevProps.pipe === 'function' ? pipe.toString() !== prevProps.pipe.toString() : isNil(pipe) && !isNil(prevProps.pipe) || !isNil(pipe) && isNil(prevProps.pipe) const isMaskChanged = mask.toString() !== prevProps.mask.toString() const isSettingChanged = Object.keys(settings).some(prop => settings[prop] !== prevProps[prop]) || isMaskChanged || isPipeChanged // Сalculate that value was changed const isValueChanged = value !== this.inputElement.value // Check value and settings to prevent duplicating update() call if (isValueChanged || isSettingChanged) { this.initTextMask() } } render() { const {render, ...props} = this.props delete props.mask delete props.guide delete props.pipe delete props.placeholderChar delete props.keepCharPositions delete props.value delete props.onBlur delete props.onChange delete props.showMask return render(this.setRef, { onBlur: this.onBlur, onChange: this.onChange, defaultValue: this.props.value, ...props, }) } onChange(event) { this.textMaskInputElement.update() if (typeof this.props.onChange === 'function') { this.props.onChange(event) } } onBlur(event) { if (typeof this.props.onBlur === 'function') { this.props.onBlur(event) } } } MaskedInput.propTypes = { mask: PropTypes.oneOfType([ PropTypes.array, PropTypes.func, PropTypes.bool, PropTypes.shape({ mask: PropTypes.oneOfType([PropTypes.array, PropTypes.func]), pipe: PropTypes.func, }), ]).isRequired, guide: PropTypes.bool, value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), pipe: PropTypes.func, placeholderChar: PropTypes.string, keepCharPositions: PropTypes.bool, showMask: PropTypes.bool, } MaskedInput.defaultProps = { render: (ref, props) => } export {default as conformToMask} from '../../core/src/conformToMask.js'