104 lines
3.2 KiB
JavaScript
104 lines
3.2 KiB
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 };
|