imask
Version:
vanilla javascript input mask
105 lines (102 loc) • 3.29 kB
JavaScript
import MaskedPattern from './pattern.js';
import IMask from '../core/holder.js';
import ChangeDetails from '../core/change-details.js';
import { DIRECTION } from '../core/utils.js';
import ContinuousTailDetails from '../core/continuous-tail-details.js';
import './base.js';
import './factory.js';
import './pattern/chunk-tail-details.js';
import './pattern/cursor.js';
import './pattern/fixed-definition.js';
import './pattern/input-definition.js';
import './regexp.js';
/** Pattern which validates enum values */
class MaskedEnum extends MaskedPattern {
constructor(opts) {
super({
...MaskedEnum.DEFAULTS,
...opts
}); // mask will be created in _update
}
updateOptions(opts) {
super.updateOptions(opts);
}
_update(opts) {
const {
enum: enum_,
...eopts
} = opts;
if (enum_) {
const lengths = enum_.map(e => e.length);
const requiredLength = Math.min(...lengths);
const optionalLength = Math.max(...lengths) - requiredLength;
eopts.mask = '*'.repeat(requiredLength);
if (optionalLength) eopts.mask += '[' + '*'.repeat(optionalLength) + ']';
this.enum = enum_;
}
super._update(eopts);
}
_appendCharRaw(ch, flags) {
if (flags === void 0) {
flags = {};
}
const matchFrom = Math.min(this.nearestInputPos(0, DIRECTION.FORCE_RIGHT), this.value.length);
const matches = this.enum.filter(e => this.matchValue(e, this.unmaskedValue + ch, matchFrom));
if (matches.length) {
if (matches.length === 1) {
this._forEachBlocksInRange(0, this.value.length, (b, bi) => {
const mch = matches[0][bi];
if (bi >= this.value.length || mch === b.value) return;
b.reset();
b._appendChar(mch, flags);
});
}
const d = super._appendCharRaw(matches[0][this.value.length], flags);
if (matches.length === 1) {
matches[0].slice(this.unmaskedValue.length).split('').forEach(mch => d.aggregate(super._appendCharRaw(mch)));
}
return d;
}
return new ChangeDetails({
skip: !this.isComplete
});
}
extractTail(fromPos, toPos) {
if (fromPos === void 0) {
fromPos = 0;
}
if (toPos === void 0) {
toPos = this.displayValue.length;
}
// just drop tail
return new ContinuousTailDetails('', fromPos);
}
remove(fromPos, toPos) {
if (fromPos === void 0) {
fromPos = 0;
}
if (toPos === void 0) {
toPos = this.displayValue.length;
}
if (fromPos === toPos) return new ChangeDetails();
const matchFrom = Math.min(super.nearestInputPos(0, DIRECTION.FORCE_RIGHT), this.value.length);
let pos;
for (pos = fromPos; pos >= 0; --pos) {
const matches = this.enum.filter(e => this.matchValue(e, this.value.slice(matchFrom, pos), matchFrom));
if (matches.length > 1) break;
}
const details = super.remove(pos, toPos);
details.tailShift += pos - fromPos;
return details;
}
get isComplete() {
return this.enum.indexOf(this.value) >= 0;
}
}
/** Match enum value */
MaskedEnum.DEFAULTS = {
...MaskedPattern.DEFAULTS,
matchValue: (estr, istr, matchFrom) => estr.indexOf(istr, matchFrom) === matchFrom
};
IMask.MaskedEnum = MaskedEnum;
export { MaskedEnum as default };