UNPKG

react-imask

Version:
311 lines (302 loc) 11.9 kB
'use strict'; var IMask = require('imask'); var React = require('react'); var PropTypes = require('prop-types'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var IMask__default = /*#__PURE__*/_interopDefault(IMask); var React__default = /*#__PURE__*/_interopDefault(React); var PropTypes__default = /*#__PURE__*/_interopDefault(PropTypes); const MASK_PROPS = { // common mask: PropTypes__default.default.oneOfType([PropTypes__default.default.array, PropTypes__default.default.func, PropTypes__default.default.string, PropTypes__default.default.instanceOf(RegExp), PropTypes__default.default.oneOf([Date, Number, IMask__default.default.Masked]), PropTypes__default.default.instanceOf(IMask__default.default.Masked)]), value: PropTypes__default.default.any, unmask: PropTypes__default.default.oneOfType([PropTypes__default.default.bool, PropTypes__default.default.oneOf(['typed'])]), prepare: PropTypes__default.default.func, prepareChar: PropTypes__default.default.func, validate: PropTypes__default.default.func, commit: PropTypes__default.default.func, overwrite: PropTypes__default.default.oneOfType([PropTypes__default.default.bool, PropTypes__default.default.oneOf(['shift'])]), eager: PropTypes__default.default.oneOfType([PropTypes__default.default.bool, PropTypes__default.default.oneOf(['append', 'remove'])]), skipInvalid: PropTypes__default.default.bool, // events onAccept: PropTypes__default.default.func, onComplete: PropTypes__default.default.func, // pattern placeholderChar: PropTypes__default.default.string, displayChar: PropTypes__default.default.string, lazy: PropTypes__default.default.bool, definitions: PropTypes__default.default.object, blocks: PropTypes__default.default.object, // enum enum: PropTypes__default.default.arrayOf(PropTypes__default.default.string), // range maxLength: PropTypes__default.default.number, from: PropTypes__default.default.number, to: PropTypes__default.default.number, // date pattern: PropTypes__default.default.string, format: PropTypes__default.default.func, parse: PropTypes__default.default.func, autofix: PropTypes__default.default.oneOfType([PropTypes__default.default.bool, PropTypes__default.default.oneOf(['pad'])]), // number radix: PropTypes__default.default.string, thousandsSeparator: PropTypes__default.default.string, mapToRadix: PropTypes__default.default.arrayOf(PropTypes__default.default.string), scale: PropTypes__default.default.number, normalizeZeros: PropTypes__default.default.bool, padFractionalZeros: PropTypes__default.default.bool, min: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.instanceOf(Date)]), max: PropTypes__default.default.oneOfType([PropTypes__default.default.number, PropTypes__default.default.instanceOf(Date)]), // dynamic dispatch: PropTypes__default.default.func, // ref inputRef: PropTypes__default.default.oneOfType([PropTypes__default.default.func, PropTypes__default.default.shape({ current: PropTypes__default.default.object })]) }; const MASK_PROPS_NAMES = Object.keys(MASK_PROPS).filter(p => p !== 'value'); const NON_MASK_OPTIONS_NAMES = ['value', 'unmask', 'onAccept', 'onComplete', 'inputRef']; const MASK_OPTIONS_NAMES = MASK_PROPS_NAMES.filter(pName => NON_MASK_OPTIONS_NAMES.indexOf(pName) < 0); function IMaskMixin(ComposedComponent) { var _Class; const MaskedComponent = (_Class = class MaskedComponent extends React__default.default.Component { constructor(props) { super(props); this._inputRef = this._inputRef.bind(this); } componentDidMount() { if (!this.props.mask) return; this.initMask(); } componentDidUpdate() { const props = this.props; const maskOptions = this._extractMaskOptionsFromProps(props); if (maskOptions.mask) { if (this.maskRef) { this.maskRef.updateOptions(maskOptions); // TODO fix if ('value' in props && props.value !== undefined) this.maskValue = props.value; } else { this.initMask(maskOptions); } } else { this.destroyMask(); if ('value' in props && props.value !== undefined) { var _this$element; if ((_this$element = this.element) != null && _this$element.isContentEditable && this.element.tagName !== 'INPUT' && this.element.tagName !== 'TEXTAREA') this.element.textContent = props.value;else this.element.value = props.value; } } } componentWillUnmount() { this.destroyMask(); } _inputRef(el) { this.element = el; if (this.props.inputRef) { if (Object.prototype.hasOwnProperty.call(this.props.inputRef, 'current')) this.props.inputRef.current = el;else this.props.inputRef(el); } } initMask(maskOptions) { if (maskOptions === void 0) { maskOptions = this._extractMaskOptionsFromProps(this.props); } this.maskRef = IMask__default.default(this.element, maskOptions).on('accept', this._onAccept.bind(this)).on('complete', this._onComplete.bind(this)); if ('value' in this.props && this.props.value !== undefined) this.maskValue = this.props.value; } destroyMask() { if (this.maskRef) { this.maskRef.destroy(); delete this.maskRef; } } _extractMaskOptionsFromProps(props) { const { ...cloneProps } = props; // keep only mask options Object.keys(cloneProps).filter(prop => MASK_OPTIONS_NAMES.indexOf(prop) < 0).forEach(nonMaskProp => { delete cloneProps[nonMaskProp]; }); return cloneProps; } _extractNonMaskProps(props) { const { ...cloneProps } = props; MASK_PROPS_NAMES.forEach(maskProp => { if (maskProp !== 'maxLength') delete cloneProps[maskProp]; }); if (!('defaultValue' in cloneProps)) cloneProps.defaultValue = props.mask ? '' : cloneProps.value; delete cloneProps.value; return cloneProps; } get maskValue() { if (!this.maskRef) return ''; if (this.props.unmask === 'typed') return this.maskRef.typedValue; if (this.props.unmask) return this.maskRef.unmaskedValue; return this.maskRef.value; } set maskValue(value) { if (!this.maskRef) return; value = value == null && this.props.unmask !== 'typed' ? '' : value; if (this.props.unmask === 'typed') this.maskRef.typedValue = value;else if (this.props.unmask) this.maskRef.unmaskedValue = value;else this.maskRef.value = value; } _onAccept(e) { if (this.props.onAccept && this.maskRef) this.props.onAccept(this.maskValue, this.maskRef, e); } _onComplete(e) { if (this.props.onComplete && this.maskRef) this.props.onComplete(this.maskValue, this.maskRef, e); } render() { return React__default.default.createElement(ComposedComponent, { ...this._extractNonMaskProps(this.props), inputRef: this._inputRef }); } }, _Class.displayName = void 0, _Class.propTypes = void 0, _Class); const nestedComponentName = ComposedComponent.displayName || ComposedComponent.name || 'Component'; MaskedComponent.displayName = "IMask(" + nestedComponentName + ")"; MaskedComponent.propTypes = MASK_PROPS; return React__default.default.forwardRef((props, ref) => React__default.default.createElement(MaskedComponent, { ...props, ref })); } const IMaskInputClass = IMaskMixin(_ref => { let { inputRef, ...props } = _ref; return React__default.default.createElement('input', { ...props, ref: inputRef }); }); const IMaskInputFn = (props, ref) => React__default.default.createElement(IMaskInputClass, { ...props, ref }) // TODO fix no idea ; const IMaskInput = React__default.default.forwardRef(IMaskInputFn); function useIMask(opts, _temp) { let { onAccept, onComplete, ref = React.useRef(null), defaultValue, defaultUnmaskedValue, defaultTypedValue } = _temp === void 0 ? {} : _temp; const maskRef = React.useRef(null); const [lastAcceptState, setLastAcceptState] = React.useState({}); const [value, setValue] = React.useState(''); const [unmaskedValue, setUnmaskedValue] = React.useState(''); const [typedValue, setTypedValue] = React.useState(); const _destroyMask = React.useCallback(() => { var _maskRef$current; (_maskRef$current = maskRef.current) == null || _maskRef$current.destroy(); maskRef.current = null; }, []); const storeLastAcceptedValues = React.useCallback(() => { const m = maskRef.current; if (!m) return; setLastAcceptState({ value: m.value, unmaskedValue: m.unmaskedValue, typedValue: m.typedValue }); setTypedValue(m.typedValue); setUnmaskedValue(m.unmaskedValue); setValue(m.value); }, []); const _onAccept = React.useCallback(event => { const m = maskRef.current; if (!m) return; storeLastAcceptedValues(); onAccept == null || onAccept(m.value, m, event); }, [onAccept]); const _onComplete = React.useCallback(event => maskRef.current && (onComplete == null ? void 0 : onComplete(maskRef.current.value, maskRef.current, event)), [onComplete]); React.useEffect(() => { const { value: lastAcceptValue, ...state } = lastAcceptState; const mask = maskRef.current; if (!mask || value === undefined) return; if (lastAcceptValue !== value) { mask.value = value; if (mask.value !== value) _onAccept(); } setLastAcceptState(state); }, [value]); React.useEffect(() => { const { unmaskedValue: lastAcceptUnmaskedValue, ...state } = lastAcceptState; const mask = maskRef.current; if (!mask || unmaskedValue === undefined) return; if (lastAcceptUnmaskedValue !== unmaskedValue) { mask.unmaskedValue = unmaskedValue; if (mask.unmaskedValue !== unmaskedValue) _onAccept(); } setLastAcceptState(state); }, [unmaskedValue]); React.useEffect(() => { const { typedValue: lastAcceptTypedValue, ...state } = lastAcceptState; const mask = maskRef.current; if (!mask || typedValue === undefined) return; if (lastAcceptTypedValue !== typedValue) { mask.typedValue = typedValue; if (!mask.masked.typedValueEquals(typedValue)) _onAccept(); } setLastAcceptState(state); }, [typedValue]); React.useEffect(() => { const el = ref.current; if (!el || !(opts != null && opts.mask)) return _destroyMask(); const mask = maskRef.current; if (!mask) { if (el && opts != null && opts.mask) { maskRef.current = IMask__default.default(el, opts); storeLastAcceptedValues(); if (defaultValue !== undefined) setValue(defaultValue); if (defaultUnmaskedValue !== undefined) setUnmaskedValue(defaultUnmaskedValue); if (defaultTypedValue !== undefined) setTypedValue(defaultTypedValue); } } else { mask == null || mask.updateOptions(opts); // TODO fix no idea } }, [opts, _destroyMask, _onAccept]); React.useEffect(() => { if (!maskRef.current) return; const mask = maskRef.current; mask.on('accept', _onAccept); mask.on('complete', _onComplete); return () => { mask.off('accept', _onAccept); mask.off('complete', _onComplete); }; }, [_onAccept, _onComplete]); React.useEffect(() => _destroyMask, [_destroyMask]); return { ref, maskRef, value, setValue, unmaskedValue, setUnmaskedValue, typedValue, setTypedValue }; } Object.defineProperty(exports, "IMask", { enumerable: true, get: function () { return IMask__default.default; } }); exports.IMaskInput = IMaskInput; exports.IMaskMixin = IMaskMixin; exports.useIMask = useIMask; //# sourceMappingURL=react-imask.cjs.map