@skbkontur/react-imask
Version:
React input mask
210 lines • 8.26 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = IMaskMixin;
const react_1 = __importDefault(require("react"));
const prop_types_1 = __importDefault(require("prop-types"));
const imask_1 = __importDefault(require("@skbkontur/imask"));
const MASK_PROPS = {
// common
mask: prop_types_1.default.oneOfType([
prop_types_1.default.array,
prop_types_1.default.func,
prop_types_1.default.string,
prop_types_1.default.instanceOf(RegExp),
prop_types_1.default.oneOf([Date, Number, imask_1.default.Masked]),
prop_types_1.default.instanceOf(imask_1.default.Masked),
]),
value: prop_types_1.default.any,
unmask: prop_types_1.default.oneOfType([
prop_types_1.default.bool,
prop_types_1.default.oneOf(['typed']),
]),
prepare: prop_types_1.default.func,
prepareChar: prop_types_1.default.func,
validate: prop_types_1.default.func,
commit: prop_types_1.default.func,
overwrite: prop_types_1.default.oneOfType([
prop_types_1.default.bool,
prop_types_1.default.oneOf(['shift']),
]),
eager: prop_types_1.default.oneOfType([
prop_types_1.default.bool,
prop_types_1.default.oneOf(['append', 'remove']),
]),
skipInvalid: prop_types_1.default.bool,
// events
onAccept: prop_types_1.default.func,
onComplete: prop_types_1.default.func,
// pattern
placeholderChar: prop_types_1.default.string,
displayChar: prop_types_1.default.string,
lazy: prop_types_1.default.bool,
definitions: prop_types_1.default.object,
blocks: prop_types_1.default.object,
// enum
enum: prop_types_1.default.arrayOf(prop_types_1.default.string),
// range
maxLength: prop_types_1.default.number,
from: prop_types_1.default.number,
to: prop_types_1.default.number,
// date
pattern: prop_types_1.default.string,
format: prop_types_1.default.func,
parse: prop_types_1.default.func,
autofix: prop_types_1.default.oneOfType([
prop_types_1.default.bool,
prop_types_1.default.oneOf(['pad']),
]),
// number
radix: prop_types_1.default.string,
thousandsSeparator: prop_types_1.default.string,
mapToRadix: prop_types_1.default.arrayOf(prop_types_1.default.string),
scale: prop_types_1.default.number,
normalizeZeros: prop_types_1.default.bool,
padFractionalZeros: prop_types_1.default.bool,
min: prop_types_1.default.oneOfType([
prop_types_1.default.number,
prop_types_1.default.instanceOf(Date),
]),
max: prop_types_1.default.oneOfType([
prop_types_1.default.number,
prop_types_1.default.instanceOf(Date),
]),
// dynamic
dispatch: prop_types_1.default.func,
// ref
inputRef: prop_types_1.default.oneOfType([
prop_types_1.default.func,
prop_types_1.default.shape({ current: prop_types_1.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) {
const MaskedComponent = class extends react_1.default.Component {
constructor(props) {
super(props);
this._inputRef = this._inputRef.bind(this);
}
componentDidMount() {
if (!this.props.mask)
return;
this.initMask();
}
componentDidUpdate() {
var _a;
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) {
if (((_a = this.element) === null || _a === void 0 ? void 0 : _a.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 = this._extractMaskOptionsFromProps(this.props)) {
this.maskRef = (0, imask_1.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_1.default.createElement(ComposedComponent, {
...this._extractNonMaskProps(this.props),
inputRef: this._inputRef,
});
}
};
const nestedComponentName = ComposedComponent.displayName || ComposedComponent.name || 'Component';
MaskedComponent.displayName = `IMask(${nestedComponentName})`;
MaskedComponent.propTypes = MASK_PROPS;
return react_1.default.forwardRef(
// @ts-ignore~
(props, ref) => react_1.default.createElement(MaskedComponent, { ...props, ref }));
}
//# sourceMappingURL=mixin.js.map