PageSourceSearch

https://amegaprint.ru/bitrix/templates/amega2020/js/mask.js

js amegaprint.ru collected 2026-10-06 17:46:24 UTC 147,657 bytes, 3,641 lines download raw bytes

vendor: 11,113 bytes, lines 1-253
1(function (global, factory) {
2    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3        typeof define === 'function' && define.amd ? define(['exports'], factory) :
4            (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.IMask = {}));
5})(this, (function (exports) { 'use strict';
6
7    /** Checks if value is string */
8    function isString(str) {
9        return typeof str === 'string' || str instanceof String;
10    }
11
12    /** Checks if value is object */
13    function isObject(obj) {
14        var _obj$constructor;
15        return typeof obj === 'object' && obj != null && (obj == null || (_obj$constructor = obj.constructor) == null ? void 0 : _obj$constructor.name) === 'Object';
16    }
17    function pick(obj, keys) {
18        if (Array.isArray(keys)) return pick(obj, (_, k) => keys.includes(k));
19        return Object.entries(obj).reduce((acc, _ref) => {
20            let [k, v] = _ref;
21            if (keys(v, k)) acc[k] = v;
22            return acc;
23        }, {});
24    }
25
26    /** Direction */
27    const DIRECTION = {
28        NONE: 'NONE',
29        LEFT: 'LEFT',
30        FORCE_LEFT: 'FORCE_LEFT',
31        RIGHT: 'RIGHT',
32        FORCE_RIGHT: 'FORCE_RIGHT'
33    };
34
35    /** Direction */
36
37    function forceDirection(direction) {
38        switch (direction) {
39            case DIRECTION.LEFT:
40                return DIRECTION.FORCE_LEFT;
41            case DIRECTION.RIGHT:
42                return DIRECTION.FORCE_RIGHT;
43            default:
44                return direction;
45        }
46    }
47
48    /** Escapes regular expression control chars */
49    function escapeRegExp(str) {
50        return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1');
51    }
52
53    // cloned from https://github.com/epoberezkin/fast-deep-equal with small changes
54    function objectIncludes(b, a) {
55        if (a === b) return true;
56        const arrA = Array.isArray(a),
57            arrB = Array.isArray(b);
58        let i;
59        if (arrA && arrB) {
60            if (a.length != b.length) return false;
61            for (i = 0; i < a.length; i++) if (!objectIncludes(a[i], b[i])) return false;
62            return true;
63        }
64        if (arrA != arrB) return false;
65        if (a && b && typeof a === 'object' && typeof b === 'object') {
66            const dateA = a instanceof Date,
67                dateB = b instanceof Date;
68            if (dateA && dateB) return a.getTime() == b.getTime();
69            if (dateA != dateB) return false;
70            const regexpA = a instanceof RegExp,
71                regexpB = b instanceof RegExp;
72            if (regexpA && regexpB) return a.toString() == b.toString();
73            if (regexpA != regexpB) return false;
74            const keys = Object.keys(a);
75            // if (keys.length !== Object.keys(b).length) return false;
76
77            for (i = 0; i < keys.length; i++) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
78            for (i = 0; i < keys.length; i++) if (!objectIncludes(b[keys[i]], a[keys[i]])) return false;
79            return true;
80        } else if (a && b && typeof a === 'function' && typeof b === 'function') {
81            return a.toString() === b.toString();
82        }
83        return false;
84    }
85
86    /** Selection range */
87
88    /** Provides details of changing input */
89    class ActionDetails {
90        /** Current input value */
91
92        /** Current cursor position */
93
94        /** Old input value */
95
96        /** Old selection */
97
98        constructor(opts) {
99            Object.assign(this, opts);
100
101            // double check if left part was changed (autofilling, other non-standard input triggers)
102            while (this.value.slice(0, this.startChangePos) !== this.oldValue.slice(0, this.startChangePos)) {
103                --this.oldSelection.start;
104            }
105            if (this.insertedCount) {
106                // double check right part
107                while (this.value.slice(this.cursorPos) !== this.oldValue.slice(this.oldSelection.end)) {
108                    if (this.value.length - this.cursorPos < this.oldValue.length - this.oldSelection.end) ++this.oldSelection.end;else ++this.cursorPos;
109                }
110            }
111        }
112
113        /** Start changing position */
114        get startChangePos() {
115            return Math.min(this.cursorPos, this.oldSelection.start);
116        }
117
118        /** Inserted symbols count */
119        get insertedCount() {
120            return this.cursorPos - this.startChangePos;
121        }
122
123        /** Inserted symbols */
124        get inserted() {
125            return this.value.substr(this.startChangePos, this.insertedCount);
126        }
127
128        /** Removed symbols count */
129        get removedCount() {
130            // Math.max for opposite operation
131            return Math.max(this.oldSelection.end - this.startChangePos ||
132                // for Delete
133                this.oldValue.length - this.value.length, 0);
134        }
135
136        /** Removed symbols */
137        get removed() {
138            return this.oldValue.substr(this.startChangePos, this.removedCount);
139        }
140
141        /** Unchanged head symbols */
142        get head() {
143            return this.value.substring(0, this.startChangePos);
144        }
145
146        /** Unchanged tail symbols */
147        get tail() {
148            return this.value.substring(this.startChangePos + this.insertedCount);
149        }
150
151        /** Remove direction */
152        get removeDirection() {
153            if (!this.removedCount || this.insertedCount) return DIRECTION.NONE;
154
155            // align right if delete at right
156            return (this.oldSelection.end === this.cursorPos || this.oldSelection.start === this.cursorPos) &&
157            // if not range removed (event with backspace)
158            this.oldSelection.end === this.oldSelection.start ? DIRECTION.RIGHT : DIRECTION.LEFT;
159        }
160    }
161
162    /** Applies mask on element */
163    function IMask(el, opts) {
164        // currently available only for input-like elements
165        return new IMask.InputMask(el, opts);
166    }
167
168    // TODO can't use overloads here because of https://github.com/microsoft/TypeScript/issues/50754
169    // export function maskedClass(mask: string): typeof MaskedPattern;
170    // export function maskedClass(mask: DateConstructor): typeof MaskedDate;
171    // export function maskedClass(mask: NumberConstructor): typeof MaskedNumber;
172    // export function maskedClass(mask: Array<any> | ArrayConstructor): typeof MaskedDynamic;
173    // export function maskedClass(mask: MaskedDate): typeof MaskedDate;
174    // export function maskedClass(mask: MaskedNumber): typeof MaskedNumber;
175    // export function maskedClass(mask: MaskedEnum): typeof MaskedEnum;
176    // export function maskedClass(mask: MaskedRange): typeof MaskedRange;
177    // export function maskedClass(mask: MaskedRegExp): typeof MaskedRegExp;
178    // export function maskedClass(mask: MaskedFunction): typeof MaskedFunction;
179    // export function maskedClass(mask: MaskedPattern): typeof MaskedPattern;
180    // export function maskedClass(mask: MaskedDynamic): typeof MaskedDynamic;
181    // export function maskedClass(mask: Masked): typeof Masked;
182    // export function maskedClass(mask: typeof Masked): typeof Masked;
183    // export function maskedClass(mask: typeof MaskedDate): typeof MaskedDate;
184    // export function maskedClass(mask: typeof MaskedNumber): typeof MaskedNumber;
185    // export function maskedClass(mask: typeof MaskedEnum): typeof MaskedEnum;
186    // export function maskedClass(mask: typeof MaskedRange): typeof MaskedRange;
187    // export function maskedClass(mask: typeof MaskedRegExp): typeof MaskedRegExp;
188    // export function maskedClass(mask: typeof MaskedFunction): typeof MaskedFunction;
189    // export function maskedClass(mask: typeof MaskedPattern): typeof MaskedPattern;
190    // export function maskedClass(mask: typeof MaskedDynamic): typeof MaskedDynamic;
191    // export function maskedClass<Mask extends typeof Masked> (mask: Mask): Mask;
192    // export function maskedClass(mask: RegExp): typeof MaskedRegExp;
193    // export function maskedClass(mask: (value: string, ...args: any[]) => boolean): typeof MaskedFunction;
194
195    /** Get Masked class by mask type */
196    function maskedClass(mask) /* TODO */{
197        if (mask == null) throw new Error('mask property should be defined');
198        if (mask instanceof RegExp) return IMask.MaskedRegExp;
199        if (isString(mask)) return IMask.MaskedPattern;
200        if (mask === Date) return IMask.MaskedDate;
201        if (mask === Number) return IMask.MaskedNumber;
202        if (Array.isArray(mask) || mask === Array) return IMask.MaskedDynamic;
203        if (IMask.Masked && mask.prototype instanceof IMask.Masked) return mask;
204        if (IMask.Masked && mask instanceof IMask.Masked) return mask.constructor;
205        if (mask instanceof Function) return IMask.MaskedFunction;
206        console.warn('Mask not found for mask', mask); // eslint-disable-line no-console
207        return IMask.Masked;
208    }
209    function normalizeOpts(opts) {
210        if (!opts) throw new Error('Options in not defined');
211        if (IMask.Masked) {
212            if (opts.prototype instanceof IMask.Masked) return {
213                mask: opts
214            };
215
216            /*
217        handle cases like:
218        1) opts = Masked
219        2) opts = { mask: Masked, ...instanceOpts }
220      */
221            const {
222                mask = undefined,
223                ...instanceOpts
224            } = opts instanceof IMask.Masked ? {
225                mask: opts
226            } : isObject(opts) && opts.mask instanceof IMask.Masked ? opts : {};
227            if (mask) {
228                const _mask = mask.mask;
229                return {
230                    ...pick(mask, (_, k) => !k.startsWith('_')),
231                    mask: mask.constructor,
232                    _mask,
233                    ...instanceOpts
234                };
235            }
236        }
237        if (!isObject(opts)) return {
238            mask: opts
239        };
240        return {
241            ...opts
242        };
243    }
244
245    // TODO can't use overloads here because of https://github.com/microsoft/TypeScript/issues/50754
246
247    // From masked
248    // export default function createMask<Opts extends Masked, ReturnMasked=Opts> (opts: Opts): ReturnMasked;
249    // // From masked class
250    // export default function createMask<Opts extends MaskedOptions<typeof Masked>, ReturnMasked extends Masked=InstanceType<Opts['mask']>> (opts: Opts): ReturnMasked;
251    // export default function createMask<Opts extends MaskedOptions<typeof MaskedDate>, ReturnMasked extends MaskedDate=MaskedDate<Opts['parent']>> (opts: Opts): ReturnMasked;
252    // export default function createMask<Opts extends MaskedOptions<typeof MaskedNumber>, ReturnMasked extends MaskedNumber=MaskedNumber<Opts['parent']>> (opts: Opts): ReturnMasked;
253    // export default function createMask<Opts extends MaskedOptions<typeof MaskedEnum>
vendor: 10,451 bytes, lines 253-472
253, ReturnMasked extends MaskedEnum=MaskedEnum<Opts['parent']>> (opts: Opts): ReturnMasked;
254    // export default function createMask<Opts extends MaskedOptions<typeof MaskedRange>, ReturnMasked extends MaskedRange=MaskedRange<Opts['parent']>> (opts: Opts): ReturnMasked;
255    // export default function createMask<Opts extends MaskedOptions<typeof MaskedRegExp>, ReturnMasked extends MaskedRegExp=MaskedRegExp<Opts['parent']>> (opts: Opts): ReturnMasked;
256    // export default function createMask<Opts extends MaskedOptions<typeof MaskedFunction>, ReturnMasked extends MaskedFunction=MaskedFunction<Opts['parent']>> (opts: Opts): ReturnMasked;
257    // export default function createMask<Opts extends MaskedOptions<typeof MaskedPattern>, ReturnMasked extends MaskedPattern=MaskedPattern<Opts['parent']>> (opts: Opts): ReturnMasked;
258    // export default function createMask<Opts extends MaskedOptions<typeof MaskedDynamic>, ReturnMasked extends MaskedDynamic=MaskedDynamic<Opts['parent']>> (opts: Opts): ReturnMasked;
259    // // From mask opts
260    // export default function createMask<Opts extends MaskedOptions<Masked>, ReturnMasked=Opts extends MaskedOptions<infer M> ? M : never> (opts: Opts): ReturnMasked;
261    // export default function createMask<Opts extends MaskedNumberOptions, ReturnMasked extends MaskedNumber=MaskedNumber<Opts['parent']>> (opts: Opts): ReturnMasked;
262    // export default function createMask<Opts extends MaskedDateFactoryOptions, ReturnMasked extends MaskedDate=MaskedDate<Opts['parent']>> (opts: Opts): ReturnMasked;
263    // export default function createMask<Opts extends MaskedEnumOptions, ReturnMasked extends MaskedEnum=MaskedEnum<Opts['parent']>> (opts: Opts): ReturnMasked;
264    // export default function createMask<Opts extends MaskedRangeOptions, ReturnMasked extends MaskedRange=MaskedRange<Opts['parent']>> (opts: Opts): ReturnMasked;
265    // export default function createMask<Opts extends MaskedPatternOptions, ReturnMasked extends MaskedPattern=MaskedPattern<Opts['parent']>> (opts: Opts): ReturnMasked;
266    // export default function createMask<Opts extends MaskedDynamicOptions, ReturnMasked extends MaskedDynamic=MaskedDynamic<Opts['parent']>> (opts: Opts): ReturnMasked;
267    // export default function createMask<Opts extends MaskedOptions<RegExp>, ReturnMasked extends MaskedRegExp=MaskedRegExp<Opts['parent']>> (opts: Opts): ReturnMasked;
268    // export default function createMask<Opts extends MaskedOptions<Function>, ReturnMasked extends MaskedFunction=MaskedFunction<Opts['parent']>> (opts: Opts): ReturnMasked;
269
270    /** Creates new {@link Masked} depending on mask type */
271    function createMask(opts) {
272        if (IMask.Masked && opts instanceof IMask.Masked) return opts;
273        const nOpts = normalizeOpts(opts);
274        const MaskedClass = maskedClass(nOpts.mask);
275        if (!MaskedClass) throw new Error("Masked class is not found for provided mask " + nOpts.mask + ", appropriate module needs to be imported manually before creating mask.");
276        if (nOpts.mask === MaskedClass) delete nOpts.mask;
277        if (nOpts._mask) {
278            nOpts.mask = nOpts._mask;
279            delete nOpts._mask;
280        }
281        return new MaskedClass(nOpts);
282    }
283    IMask.createMask = createMask;
284
285    /**  Generic element API to use with mask */
286    class MaskElement {
287        /** */
288
289        /** */
290
291        /** */
292
293        /** Safely returns selection start */
294        get selectionStart() {
295            let start;
296            try {
297                start = this._unsafeSelectionStart;
298            } catch {}
299            return start != null ? start : this.value.length;
300        }
301
302        /** Safely returns selection end */
303        get selectionEnd() {
304            let end;
305            try {
306                end = this._unsafeSelectionEnd;
307            } catch {}
308            return end != null ? end : this.value.length;
309        }
310
311        /** Safely sets element selection */
312        select(start, end) {
313            if (start == null || end == null || start === this.selectionStart && end === this.selectionEnd) return;
314            try {
315                this._unsafeSelect(start, end);
316            } catch {}
317        }
318
319        /** */
320        get isActive() {
321            return false;
322        }
323        /** */
324
325        /** */
326
327        /** */
328    }
329    IMask.MaskElement = MaskElement;
330
331    const KEY_Z = 90;
332    const KEY_Y = 89;
333
334    /** Bridge between HTMLElement and {@link Masked} */
335    class HTMLMaskElement extends MaskElement {
336        /** HTMLElement to use mask on */
337
338        constructor(input) {
339            super();
340            this.input = input;
341            this._onKeydown = this._onKeydown.bind(this);
342            this._onInput = this._onInput.bind(this);
343            this._onBeforeinput = this._onBeforeinput.bind(this);
344            this._onCompositionEnd = this._onCompositionEnd.bind(this);
345        }
346        get rootElement() {
347            var _this$input$getRootNo, _this$input$getRootNo2, _this$input;
348            return (_this$input$getRootNo = (_this$input$getRootNo2 = (_this$input = this.input).getRootNode) == null ? void 0 : _this$input$getRootNo2.call(_this$input)) != null ? _this$input$getRootNo : document;
349        }
350
351        /** Is element in focus */
352        get isActive() {
353            return this.input === this.rootElement.activeElement;
354        }
355
356        /** Binds HTMLElement events to mask internal events */
357        bindEvents(handlers) {
358            this.input.addEventListener('keydown', this._onKeydown);
359            this.input.addEventListener('input', this._onInput);
360            this.input.addEventListener('beforeinput', this._onBeforeinput);
361            this.input.addEventListener('compositionend', this._onCompositionEnd);
362            this.input.addEventListener('drop', handlers.drop);
363            this.input.addEventListener('click', handlers.click);
364            this.input.addEventListener('focus', handlers.focus);
365            this.input.addEventListener('blur', handlers.commit);
366            this._handlers = handlers;
367        }
368        _onKeydown(e) {
369            if (this._handlers.redo && (e.keyCode === KEY_Z && e.shiftKey && (e.metaKey || e.ctrlKey) || e.keyCode === KEY_Y && e.ctrlKey)) {
370                e.preventDefault();
371                return this._handlers.redo(e);
372            }
373            if (this._handlers.undo && e.keyCode === KEY_Z && (e.metaKey || e.ctrlKey)) {
374                e.preventDefault();
375                return this._handlers.undo(e);
376            }
377            if (!e.isComposing) this._handlers.selectionChange(e);
378        }
379        _onBeforeinput(e) {
380            if (e.inputType === 'historyUndo' && this._handlers.undo) {
381                e.preventDefault();
382                return this._handlers.undo(e);
383            }
384            if (e.inputType === 'historyRedo' && this._handlers.redo) {
385                e.preventDefault();
386                return this._handlers.redo(e);
387            }
388        }
389        _onCompositionEnd(e) {
390            this._handlers.input(e);
391        }
392        _onInput(e) {
393            if (!e.isComposing) this._handlers.input(e);
394        }
395
396        /** Unbinds HTMLElement events to mask internal events */
397        unbindEvents() {
398            this.input.removeEventListener('keydown', this._onKeydown);
399            this.input.removeEventListener('input', this._onInput);
400            this.input.removeEventListener('beforeinput', this._onBeforeinput);
401            this.input.removeEventListener('compositionend', this._onCompositionEnd);
402            this.input.removeEventListener('drop', this._handlers.drop);
403            this.input.removeEventListener('click', this._handlers.click);
404            this.input.removeEventListener('focus', this._handlers.focus);
405            this.input.removeEventListener('blur', this._handlers.commit);
406            this._handlers = {};
407        }
408    }
409    IMask.HTMLMaskElement = HTMLMaskElement;
410
411    /** Bridge between InputElement and {@link Masked} */
412    class HTMLInputMaskElement extends HTMLMaskElement {
413        /** InputElement to use mask on */
414
415        constructor(input) {
416            super(input);
417            this.input = input;
418        }
419
420        /** Returns InputElement selection start */
421        get _unsafeSelectionStart() {
422            return this.input.selectionStart != null ? this.input.selectionStart : this.value.length;
423        }
424
425        /** Returns InputElement selection end */
426        get _unsafeSelectionEnd() {
427            return this.input.selectionEnd;
428        }
429
430        /** Sets InputElement selection */
431        _unsafeSelect(start, end) {
432            this.input.setSelectionRange(start, end);
433        }
434        get value() {
435            return this.input.value;
436        }
437        set value(value) {
438            this.input.value = value;
439        }
440    }
441    IMask.HTMLMaskElement = HTMLMaskElement;
442
443    class HTMLContenteditableMaskElement extends HTMLMaskElement {
444        /** Returns HTMLElement selection start */
445        get _unsafeSelectionStart() {
446            const root = this.rootElement;
447            const selection = root.getSelection && root.getSelection();
448            const anchorOffset = selection && selection.anchorOffset;
449            const focusOffset = selection && selection.focusOffset;
450            if (focusOffset == null || anchorOffset == null || anchorOffset < focusOffset) {
451                return anchorOffset;
452            }
453            return focusOffset;
454        }
455
456        /** Returns HTMLElement selection end */
457        get _unsafeSelectionEnd() {
458            const root = this.rootElement;
459            const selection = root.getSelection && root.getSelection();
460            const anchorOffset = selection && selection.anchorOffset;
461            const focusOffset = selection && selection.focusOffset;
462            if (focusOffset == null || anchorOffset == null || anchorOffset > focusOffset) {
463                return anchorOffset;
464            }
465            return focusOffset;
466        }
467
468        /** Sets HTMLElement selection */
469        _unsafeSelect(start, end) {
470            if (!this.rootElement.createRange) return;
471            const range = this.rootElement.createRange();
472            range.setStart(this.input.firstChild || this.input, start);
vendor: 4,971 bytes, lines 473-615
473            range.setEnd(this.input.lastChild || this.input, end);
474            const root = this.rootElement;
475            const selection = root.getSelection && root.getSelection();
476            if (selection) {
477                selection.removeAllRanges();
478                selection.addRange(range);
479            }
480        }
481
482        /** HTMLElement value */
483        get value() {
484            return this.input.textContent || '';
485        }
486        set value(value) {
487            this.input.textContent = value;
488        }
489    }
490    IMask.HTMLContenteditableMaskElement = HTMLContenteditableMaskElement;
491
492    class InputHistory {
493        constructor() {
494            this.states = [];
495            this.currentIndex = 0;
496        }
497        get currentState() {
498            return this.states[this.currentIndex];
499        }
500        get isEmpty() {
501            return this.states.length === 0;
502        }
503        push(state) {
504            // if current index points before the last element then remove the future
505            if (this.currentIndex < this.states.length - 1) this.states.length = this.currentIndex + 1;
506            this.states.push(state);
507            if (this.states.length > InputHistory.MAX_LENGTH) this.states.shift();
508            this.currentIndex = this.states.length - 1;
509        }
510        go(steps) {
511            this.currentIndex = Math.min(Math.max(this.currentIndex + steps, 0), this.states.length - 1);
512            return this.currentState;
513        }
514        undo() {
515            return this.go(-1);
516        }
517        redo() {
518            return this.go(+1);
519        }
520        clear() {
521            this.states.length = 0;
522            this.currentIndex = 0;
523        }
524    }
525    InputHistory.MAX_LENGTH = 100;
526
527    /** Listens to element events and controls changes between element and {@link Masked} */
528    class InputMask {
529        /**
530         View element
531         */
532
533        /** Internal {@link Masked} model */
534
535        constructor(el, opts) {
536            this.el = el instanceof MaskElement ? el : el.isContentEditable && el.tagName !== 'INPUT' && el.tagName !== 'TEXTAREA' ? new HTMLContenteditableMaskElement(el) : new HTMLInputMaskElement(el);
537            this.masked = createMask(opts);
538            this._listeners = {};
539            this._value = '';
540            this._unmaskedValue = '';
541            this._rawInputValue = '';
542            this.history = new InputHistory();
543            this._saveSelection = this._saveSelection.bind(this);
544            this._onInput = this._onInput.bind(this);
545            this._onChange = this._onChange.bind(this);
546            this._onDrop = this._onDrop.bind(this);
547            this._onFocus = this._onFocus.bind(this);
548            this._onClick = this._onClick.bind(this);
549            this._onUndo = this._onUndo.bind(this);
550            this._onRedo = this._onRedo.bind(this);
551            this.alignCursor = this.alignCursor.bind(this);
552            this.alignCursorFriendly = this.alignCursorFriendly.bind(this);
553            this._bindEvents();
554
555            // refresh
556            this.updateValue();
557            this._onChange();
558        }
559        maskEquals(mask) {
560            var _this$masked;
561            return mask == null || ((_this$masked = this.masked) == null ? void 0 : _this$masked.maskEquals(mask));
562        }
563
564        /** Masked */
565        get mask() {
566            return this.masked.mask;
567        }
568        set mask(mask) {
569            if (this.maskEquals(mask)) return;
570            if (!(mask instanceof IMask.Masked) && this.masked.constructor === maskedClass(mask)) {
571                // TODO "any" no idea
572                this.masked.updateOptions({
573                    mask
574                });
575                return;
576            }
577            const masked = mask instanceof IMask.Masked ? mask : createMask({
578                mask
579            });
580            masked.unmaskedValue = this.masked.unmaskedValue;
581            this.masked = masked;
582        }
583
584        /** Raw value */
585        get value() {
586            return this._value;
587        }
588        set value(str) {
589            if (this.value === str) return;
590            this.masked.value = str;
591            this.updateControl('auto');
592        }
593
594        /** Unmasked value */
595        get unmaskedValue() {
596            return this._unmaskedValue;
597        }
598        set unmaskedValue(str) {
599            if (this.unmaskedValue === str) return;
600            this.masked.unmaskedValue = str;
601            this.updateControl('auto');
602        }
603
604        /** Raw input value */
605        get rawInputValue() {
606            return this._rawInputValue;
607        }
608        set rawInputValue(str) {
609            if (this.rawInputValue === str) return;
610            this.masked.rawInputValue = str;
611            this.updateControl();
612            this.alignCursor();
613        }
614
615        /** Typed unmasked value */
vendor: 4,416 bytes, lines 616-730
616        get typedValue() {
617            return this.masked.typedValue;
618        }
619        set typedValue(val) {
620            if (this.masked.typedValueEquals(val)) return;
621            this.masked.typedValue = val;
622            this.updateControl('auto');
623        }
624
625        /** Display value */
626        get displayValue() {
627            return this.masked.displayValue;
628        }
629
630        /** Starts listening to element events */
631        _bindEvents() {
632            this.el.bindEvents({
633                selectionChange: this._saveSelection,
634                input: this._onInput,
635                drop: this._onDrop,
636                click: this._onClick,
637                focus: this._onFocus,
638                commit: this._onChange,
639                undo: this._onUndo,
640                redo: this._onRedo
641            });
642        }
643
644        /** Stops listening to element events */
645        _unbindEvents() {
646            if (this.el) this.el.unbindEvents();
647        }
648
649        /** Fires custom event */
650        _fireEvent(ev, e) {
651            const listeners = this._listeners[ev];
652            if (!listeners) return;
653            listeners.forEach(l => l(e));
654        }
655
656        /** Current selection start */
657        get selectionStart() {
658            return this._cursorChanging ? this._changingCursorPos : this.el.selectionStart;
659        }
660
661        /** Current cursor position */
662        get cursorPos() {
663            return this._cursorChanging ? this._changingCursorPos : this.el.selectionEnd;
664        }
665        set cursorPos(pos) {
666            if (!this.el || !this.el.isActive) return;
667            this.el.select(pos, pos);
668            this._saveSelection();
669        }
670
671        /** Stores current selection */
672        _saveSelection( /* ev */
673        ) {
674            if (this.displayValue !== this.el.value) {
675                console.warn('Element value was changed outside of mask. Syncronize mask using `mask.updateValue()` to work properly.'); // eslint-disable-line no-console
676            }
677            this._selection = {
678                start: this.selectionStart,
679                end: this.cursorPos
680            };
681        }
682
683        /** Syncronizes model value from view */
684        updateValue() {
685            this.masked.value = this.el.value;
686            this._value = this.masked.value;
687            this._unmaskedValue = this.masked.unmaskedValue;
688            this._rawInputValue = this.masked.rawInputValue;
689        }
690
691        /** Syncronizes view from model value, fires change events */
692        updateControl(cursorPos) {
693            const newUnmaskedValue = this.masked.unmaskedValue;
694            const newValue = this.masked.value;
695            const newRawInputValue = this.masked.rawInputValue;
696            const newDisplayValue = this.displayValue;
697            const isChanged = this.unmaskedValue !== newUnmaskedValue || this.value !== newValue || this._rawInputValue !== newRawInputValue;
698            this._unmaskedValue = newUnmaskedValue;
699            this._value = newValue;
700            this._rawInputValue = newRawInputValue;
701            if (this.el.value !== newDisplayValue) this.el.value = newDisplayValue;
702            if (cursorPos === 'auto') this.alignCursor();else if (cursorPos != null) this.cursorPos = cursorPos;
703            if (isChanged) this._fireChangeEvents();
704            if (!this._historyChanging && (isChanged || this.history.isEmpty)) this.history.push({
705                unmaskedValue: newUnmaskedValue,
706                selection: {
707                    start: this.selectionStart,
708                    end: this.cursorPos
709                }
710            });
711        }
712
713        /** Updates options with deep equal check, recreates {@link Masked} model if mask type changes */
714        updateOptions(opts) {
715            const {
716                mask,
717                ...restOpts
718            } = opts; // TODO types, yes, mask is optional
719
720            const updateMask = !this.maskEquals(mask);
721            const updateOpts = this.masked.optionsIsChanged(restOpts);
722            if (updateMask) this.mask = mask;
723            if (updateOpts) this.masked.updateOptions(restOpts); // TODO
724
725            if (updateMask || updateOpts) this.updateControl();
726        }
727
728        /** Updates cursor */
729        updateCursor(cursorPos) {
730            if (cursorPos == null) return;
731            this.cursorPos = cursorPos;
732
733            // also queue change cursor for mobile browsers
734            this._delayUpdateCursor(cursorPos);
735        }
736
737        /** Delays cursor update to support mobile browsers */
738        _delayUpdateCursor(cursorPos) {
739            this._abortUpdateCursor();
740            this._changingCursorPos = cursorPos;
741            this._cursorChanging = setTimeout(() => {
742                if (!this.el) return; // if was destroyed
743                this.cursorPos = this._changingCursorPos;
744                this._abortUpdateCursor();
745            }, 10);
746        }
747
748        /** Fires custom events */
749        _fireChangeEvents() {
750            this._fireEvent('accept', this._inputEvent);
751            if (this.masked.isComplete) this._fireEvent('complete', this._inputEvent);
752        }
753
754        /** Aborts delayed cursor update */
755        _abortUpdateCursor() {
756            if (this._cursorChanging) {
757                clearTimeout(this._cursorChanging);
758                delete this._cursorChanging;
759            }
760        }
761
762        /** Aligns cursor to nearest available position */
763        alignCursor() {
vendor: 112,380 bytes, lines 764-3560
764            this.cursorPos = this.masked.nearestInputPos(this.masked.nearestInputPos(this.cursorPos, DIRECTION.LEFT));
765        }
766
767        /** Aligns cursor only if selection is empty */
768        alignCursorFriendly() {
769            if (this.selectionStart !== this.cursorPos) return; // skip if range is selected
770            this.alignCursor();
771        }
772
773        /** Adds listener on custom event */
774        on(ev, handler) {
775            if (!this._listeners[ev]) this._listeners[ev] = [];
776            this._listeners[ev].push(handler);
777            return this;
778        }
779
780        /** Removes custom event listener */
781        off(ev, handler) {
782            if (!this._listeners[ev]) return this;
783            if (!handler) {
784                delete this._listeners[ev];
785                return this;
786            }
787            const hIndex = this._listeners[ev].indexOf(handler);
788            if (hIndex >= 0) this._listeners[ev].splice(hIndex, 1);
789            return this;
790        }
791
792        /** Handles view input event */
793        _onInput(e) {
794            this._inputEvent = e;
795            this._abortUpdateCursor();
796            const details = new ActionDetails({
797                // new state
798                value: this.el.value,
799                cursorPos: this.cursorPos,
800                // old state
801                oldValue: this.displayValue,
802                oldSelection: this._selection
803            });
804            const oldRawValue = this.masked.rawInputValue;
805            const offset = this.masked.splice(details.startChangePos, details.removed.length, details.inserted, details.removeDirection, {
806                input: true,
807                raw: true
808            }).offset;
809
810            // force align in remove direction only if no input chars were removed
811            // otherwise we still need to align with NONE (to get out from fixed symbols for instance)
812            const removeDirection = oldRawValue === this.masked.rawInputValue ? details.removeDirection : DIRECTION.NONE;
813            let cursorPos = this.masked.nearestInputPos(details.startChangePos + offset, removeDirection);
814            if (removeDirection !== DIRECTION.NONE) cursorPos = this.masked.nearestInputPos(cursorPos, DIRECTION.NONE);
815            this.updateControl(cursorPos);
816            delete this._inputEvent;
817        }
818
819        /** Handles view change event and commits model value */
820        _onChange() {
821            if (this.displayValue !== this.el.value) this.updateValue();
822            this.masked.doCommit();
823            this.updateControl();
824            this._saveSelection();
825        }
826
827        /** Handles view drop event, prevents by default */
828        _onDrop(ev) {
829            ev.preventDefault();
830            ev.stopPropagation();
831        }
832
833        /** Restore last selection on focus */
834        _onFocus(ev) {
835            this.alignCursorFriendly();
836        }
837
838        /** Restore last selection on focus */
839        _onClick(ev) {
840            this.alignCursorFriendly();
841        }
842        _onUndo() {
843            this._applyHistoryState(this.history.undo());
844        }
845        _onRedo() {
846            this._applyHistoryState(this.history.redo());
847        }
848        _applyHistoryState(state) {
849            if (!state) return;
850            this._historyChanging = true;
851            this.unmaskedValue = state.unmaskedValue;
852            this.el.select(state.selection.start, state.selection.end);
853            this._saveSelection();
854            this._historyChanging = false;
855        }
856
857        /** Unbind view events and removes element reference */
858        destroy() {
859            this._unbindEvents();
860            this._listeners.length = 0;
861            delete this.el;
862        }
863    }
864    IMask.InputMask = InputMask;
865
866    /** Provides details of changing model value */
867    class ChangeDetails {
868        /** Inserted symbols */
869
870        /** Additional offset if any changes occurred before tail */
871
872        /** Raw inserted is used by dynamic mask */
873
874        /** Can skip chars */
875
876        static normalize(prep) {
877            return Array.isArray(prep) ? prep : [prep, new ChangeDetails()];
878        }
879        constructor(details) {
880            Object.assign(this, {
881                inserted: '',
882                rawInserted: '',
883                tailShift: 0,
884                skip: false
885            }, details);
886        }
887
888        /** Aggregate changes */
889        aggregate(details) {
890            this.inserted += details.inserted;
891            this.rawInserted += details.rawInserted;
892            this.tailShift += details.tailShift;
893            this.skip = this.skip || details.skip;
894            return this;
895        }
896
897        /** Total offset considering all changes */
898        get offset() {
899            return this.tailShift + this.inserted.length;
900        }
901        get consumed() {
902            return Boolean(this.rawInserted) || this.skip;
903        }
904        equals(details) {
905            return this.inserted === details.inserted && this.tailShift === details.tailShift && this.rawInserted === details.rawInserted && this.skip === details.skip;
906        }
907    }
908    IMask.ChangeDetails = ChangeDetails;
909
910    /** Provides details of continuous extracted tail */
911    class ContinuousTailDetails {
912        /** Tail value as string */
913
914        /** Tail start position */
915
916        /** Start position */
917
918        constructor(value, from, stop) {
919            if (value === void 0) {
920                value = '';
921            }
922            if (from === void 0) {
923                from = 0;
924            }
925            this.value = value;
926            this.from = from;
927            this.stop = stop;
928        }
929        toString() {
930            return this.value;
931        }
932        extend(tail) {
933            this.value += String(tail);
934        }
935        appendTo(masked) {
936            return masked.append(this.toString(), {
937                tail: true
938            }).aggregate(masked._appendPlaceholder());
939        }
940        get state() {
941            return {
942                value: this.value,
943                from: this.from,
944                stop: this.stop
945            };
946        }
947        set state(state) {
948            Object.assign(this, state);
949        }
950        unshift(beforePos) {
951            if (!this.value.length || beforePos != null && this.from >= beforePos) return '';
952            const shiftChar = this.value[0];
953            this.value = this.value.slice(1);
954            return shiftChar;
955        }
956        shift() {
957            if (!this.value.length) return '';
958            const shiftChar = this.value[this.value.length - 1];
959            this.value = this.value.slice(0, -1);
960            return shiftChar;
961        }
962    }
963
964    /** Append flags */
965
966    /** Extract flags */
967
968    // see https://github.com/microsoft/TypeScript/issues/6223
969
970    /** Provides common masking stuff */
971    class Masked {
972        /** */
973
974        /** */
975
976        /** Transforms value before mask processing */
977
978        /** Transforms each char before mask processing */
979
980        /** Validates if value is acceptable */
981
982        /** Does additional processing at the end of editing */
983
984        /** Format typed value to string */
985
986        /** Parse string to get typed value */
987
988        /** Enable characters overwriting */
989
990        /** */
991
992        /** */
993
994        /** */
995
996        /** */
997
998        constructor(opts) {
999            this._value = '';
1000            this._update({
1001                ...Masked.DEFAULTS,
1002                ...opts
1003            });
1004            this._initialized = true;
1005        }
1006
1007        /** Sets and applies new options */
1008        updateOptions(opts) {
1009            if (!this.optionsIsChanged(opts)) return;
1010            this.withValueRefresh(this._update.bind(this, opts));
1011        }
1012
1013        /** Sets new options */
1014        _update(opts) {
1015            Object.assign(this, opts);
1016        }
1017
1018        /** Mask state */
1019        get state() {
1020            return {
1021                _value: this.value,
1022                _rawInputValue: this.rawInputValue
1023            };
1024        }
1025        set state(state) {
1026            this._value = state._value;
1027        }
1028
1029        /** Resets value */
1030        reset() {
1031            this._value = '';
1032        }
1033        get value() {
1034            return this._value;
1035        }
1036        set value(value) {
1037            this.resolve(value, {
1038                input: true
1039            });
1040        }
1041
1042        /** Resolve new value */
1043        resolve(value, flags) {
1044            if (flags === void 0) {
1045                flags = {
1046                    input: true
1047                };
1048            }
1049            this.reset();
1050            this.append(value, flags, '');
1051            this.doCommit();
1052        }
1053        get unmaskedValue() {
1054            return this.value;
1055        }
1056        set unmaskedValue(value) {
1057            this.resolve(value, {});
1058        }
1059        get typedValue() {
1060            return this.parse ? this.parse(this.value, this) : this.unmaskedValue;
1061        }
1062        set typedValue(value) {
1063            if (this.format) {
1064                this.value = this.format(value, this);
1065            } else {
1066                this.unmaskedValue = String(value);
1067            }
1068        }
1069
1070        /** Value that includes raw user input */
1071        get rawInputValue() {
1072            return this.extractInput(0, this.displayValue.length, {
1073                raw: true
1074            });
1075        }
1076        set rawInputValue(value) {
1077            this.resolve(value, {
1078                raw: true
1079            });
1080        }
1081        get displayValue() {
1082            return this.value;
1083        }
1084        get isComplete() {
1085            return true;
1086        }
1087        get isFilled() {
1088            return this.isComplete;
1089        }
1090
1091        /** Finds nearest input position in direction */
1092        nearestInputPos(cursorPos, direction) {
1093            return cursorPos;
1094        }
1095        totalInputPositions(fromPos, toPos) {
1096            if (fromPos === void 0) {
1097                fromPos = 0;
1098            }
1099            if (toPos === void 0) {
1100                toPos = this.displayValue.length;
1101            }
1102            return Math.min(this.displayValue.length, toPos - fromPos);
1103        }
1104
1105        /** Extracts value in range considering flags */
1106        extractInput(fromPos, toPos, flags) {
1107            if (fromPos === void 0) {
1108                fromPos = 0;
1109            }
1110            if (toPos === void 0) {
1111                toPos = this.displayValue.length;
1112            }
1113            return this.displayValue.slice(fromPos, toPos);
1114        }
1115
1116        /** Extracts tail in range */
1117        extractTail(fromPos, toPos) {
1118            if (fromPos === void 0) {
1119                fromPos = 0;
1120            }
1121            if (toPos === void 0) {
1122                toPos = this.displayValue.length;
1123            }
1124            return new ContinuousTailDetails(this.extractInput(fromPos, toPos), fromPos);
1125        }
1126
1127        /** Appends tail */
1128        appendTail(tail) {
1129            if (isString(tail)) tail = new ContinuousTailDetails(String(tail));
1130            return tail.appendTo(this);
1131        }
1132
1133        /** Appends char */
1134        _appendCharRaw(ch, flags) {
1135            if (!ch) return new ChangeDetails();
1136            this._value += ch;
1137            return new ChangeDetails({
1138                inserted: ch,
1139                rawInserted: ch
1140            });
1141        }
1142
1143        /** Appends char */
1144        _appendChar(ch, flags, checkTail) {
1145            if (flags === void 0) {
1146                flags = {};
1147            }
1148            const consistentState = this.state;
1149            let details;
1150            [ch, details] = this.doPrepareChar(ch, flags);
1151            if (ch) {
1152                details = details.aggregate(this._appendCharRaw(ch, flags));
1153
1154                // TODO handle `skip`?
1155
1156                // try `autofix` lookahead
1157                if (!details.rawInserted && this.autofix === 'pad') {
1158                    const noFixState = this.state;
1159                    this.state = consistentState;
1160                    let fixDetails = this.pad(flags);
1161                    const chDetails = this._appendCharRaw(ch, flags);
1162                    fixDetails = fixDetails.aggregate(chDetails);
1163
1164                    // if fix was applied or
1165                    // if details are equal use skip restoring state optimization
1166                    if (chDetails.rawInserted || fixDetails.equals(details)) {
1167                        details = fixDetails;
1168                    } else {
1169                        this.state = noFixState;
1170                    }
1171                }
1172            }
1173            if (details.inserted) {
1174                let consistentTail;
1175                let appended = this.doValidate(flags) !== false;
1176                if (appended && checkTail != null) {
1177                    // validation ok, check tail
1178                    const beforeTailState = this.state;
1179                    if (this.overwrite === true) {
1180                        consistentTail = checkTail.state;
1181                        for (let i = 0; i < details.rawInserted.length; ++i) {
1182                            checkTail.unshift(this.displayValue.length - details.tailShift);
1183                        }
1184                    }
1185                    let tailDetails = this.appendTail(checkTail);
1186                    appended = tailDetails.rawInserted.length === checkTail.toString().length;
1187
1188                    // not ok, try shift
1189                    if (!(appended && tailDetails.inserted) && this.overwrite === 'shift') {
1190                        this.state = beforeTailState;
1191                        consistentTail = checkTail.state;
1192                        for (let i = 0; i < details.rawInserted.length; ++i) {
1193                            checkTail.shift();
1194                        }
1195                        tailDetails = this.appendTail(checkTail);
1196                        appended = tailDetails.rawInserted.length === checkTail.toString().length;
1197                    }
1198
1199                    // if ok, rollback state after tail
1200                    if (appended && tailDetails.inserted) this.state = beforeTailState;
1201                }
1202
1203                // revert all if something went wrong
1204                if (!appended) {
1205                    details = new ChangeDetails();
1206                    this.state = consistentState;
1207                    if (checkTail && consistentTail) checkTail.state = consistentTail;
1208                }
1209            }
1210            return details;
1211        }
1212
1213        /** Appends optional placeholder at the end */
1214        _appendPlaceholder() {
1215            return new ChangeDetails();
1216        }
1217
1218        /** Appends optional eager placeholder at the end */
1219        _appendEager() {
1220            return new ChangeDetails();
1221        }
1222
1223        /** Appends symbols considering flags */
1224        append(str, flags, tail) {
1225            if (!isString(str)) throw new Error('value should be string');
1226            const checkTail = isString(tail) ? new ContinuousTailDetails(String(tail)) : tail;
1227            if (flags != null && flags.tail) flags._beforeTailState = this.state;
1228            let details;
1229            [str, details] = this.doPrepare(str, flags);
1230            for (let ci = 0; ci < str.length; ++ci) {
1231                const d = this._appendChar(str[ci], flags, checkTail);
1232                if (!d.rawInserted && !this.doSkipInvalid(str[ci], flags, checkTail)) break;
1233                details.aggregate(d);
1234            }
1235            if ((this.eager === true || this.eager === 'append') && flags != null && flags.input && str) {
1236                details.aggregate(this._appendEager());
1237            }
1238
1239            // append tail but aggregate only tailShift
1240            if (checkTail != null) {
1241                details.tailShift += this.appendTail(checkTail).tailShift;
1242                // TODO it's a good idea to clear state after appending ends
1243                // but it causes bugs when one append calls another (when dynamic dispatch set rawInputValue)
1244                // this._resetBeforeTailState();
1245            }
1246            return details;
1247        }
1248        remove(fromPos, toPos) {
1249            if (fromPos === void 0) {
1250                fromPos = 0;
1251            }
1252            if (toPos === void 0) {
1253                toPos = this.displayValue.length;
1254            }
1255            this._value = this.displayValue.slice(0, fromPos) + this.displayValue.slice(toPos);
1256            return new ChangeDetails();
1257        }
1258
1259        /** Calls function and reapplies current value */
1260        withValueRefresh(fn) {
1261            if (this._refreshing || !this._initialized) return fn();
1262            this._refreshing = true;
1263            const rawInput = this.rawInputValue;
1264            const value = this.value;
1265            const ret = fn();
1266            this.rawInputValue = rawInput;
1267            // append lost trailing chars at the end
1268            if (this.value && this.value !== value && value.indexOf(this.value) === 0) {
1269                this.append(value.slice(this.displayValue.length), {}, '');
1270                this.doCommit();
1271            }
1272            delete this._refreshing;
1273            return ret;
1274        }
1275        runIsolated(fn) {
1276            if (this._isolated || !this._initialized) return fn(this);
1277            this._isolated = true;
1278            const state = this.state;
1279            const ret = fn(this);
1280            this.state = state;
1281            delete this._isolated;
1282            return ret;
1283        }
1284        doSkipInvalid(ch, flags, checkTail) {
1285            return Boolean(this.skipInvalid);
1286        }
1287
1288        /** Prepares string before mask processing */
1289        doPrepare(str, flags) {
1290            if (flags === void 0) {
1291                flags = {};
1292            }
1293            return ChangeDetails.normalize(this.prepare ? this.prepare(str, this, flags) : str);
1294        }
1295
1296        /** Prepares each char before mask processing */
1297        doPrepareChar(str, flags) {
1298            if (flags === void 0) {
1299                flags = {};
1300            }
1301            return ChangeDetails.normalize(this.prepareChar ? this.prepareChar(str, this, flags) : str);
1302        }
1303
1304        /** Validates if value is acceptable */
1305        doValidate(flags) {
1306            return (!this.validate || this.validate(this.value, this, flags)) && (!this.parent || this.parent.doValidate(flags));
1307        }
1308
1309        /** Does additional processing at the end of editing */
1310        doCommit() {
1311            if (this.commit) this.commit(this.value, this);
1312        }
1313        splice(start, deleteCount, inserted, removeDirection, flags) {
1314            if (inserted === void 0) {
1315                inserted = '';
1316            }
1317            if (removeDirection === void 0) {
1318                removeDirection = DIRECTION.NONE;
1319            }
1320            if (flags === void 0) {
1321                flags = {
1322                    input: true
1323                };
1324            }
1325            const tailPos = start + deleteCount;
1326            const tail = this.extractTail(tailPos);
1327            const eagerRemove = this.eager === true || this.eager === 'remove';
1328            let oldRawValue;
1329            if (eagerRemove) {
1330                removeDirection = forceDirection(removeDirection);
1331                oldRawValue = this.extractInput(0, tailPos, {
1332                    raw: true
1333                });
1334            }
1335            let startChangePos = start;
1336            const details = new ChangeDetails();
1337
1338            // if it is just deletion without insertion
1339            if (removeDirection !== DIRECTION.NONE) {
1340                startChangePos = this.nearestInputPos(start, deleteCount > 1 && start !== 0 && !eagerRemove ? DIRECTION.NONE : removeDirection);
1341
1342                // adjust tailShift if start was aligned
1343                details.tailShift = startChangePos - start;
1344            }
1345            details.aggregate(this.remove(startChangePos));
1346            if (eagerRemove && removeDirection !== DIRECTION.NONE && oldRawValue === this.rawInputValue) {
1347                if (removeDirection === DIRECTION.FORCE_LEFT) {
1348                    let valLength;
1349                    while (oldRawValue === this.rawInputValue && (valLength = this.displayValue.length)) {
1350                        details.aggregate(new ChangeDetails({
1351                            tailShift: -1
1352                        })).aggregate(this.remove(valLength - 1));
1353                    }
1354                } else if (removeDirection === DIRECTION.FORCE_RIGHT) {
1355                    tail.unshift();
1356                }
1357            }
1358            return details.aggregate(this.append(inserted, flags, tail));
1359        }
1360        maskEquals(mask) {
1361            return this.mask === mask;
1362        }
1363        optionsIsChanged(opts) {
1364            return !objectIncludes(this, opts);
1365        }
1366        typedValueEquals(value) {
1367            const tval = this.typedValue;
1368            return value === tval || Masked.EMPTY_VALUES.includes(value) && Masked.EMPTY_VALUES.includes(tval) || (this.format ? this.format(value, this) === this.format(this.typedValue, this) : false);
1369        }
1370        pad(flags) {
1371            return new ChangeDetails();
1372        }
1373    }
1374    Masked.DEFAULTS = {
1375        skipInvalid: true
1376    };
1377    Masked.EMPTY_VALUES = [undefined, null, ''];
1378    IMask.Masked = Masked;
1379
1380    class ChunksTailDetails {
1381        /** */
1382
1383        constructor(chunks, from) {
1384            if (chunks === void 0) {
1385                chunks = [];
1386            }
1387            if (from === void 0) {
1388                from = 0;
1389            }
1390            this.chunks = chunks;
1391            this.from = from;
1392        }
1393        toString() {
1394            return this.chunks.map(String).join('');
1395        }
1396        extend(tailChunk) {
1397            if (!String(tailChunk)) return;
1398            tailChunk = isString(tailChunk) ? new ContinuousTailDetails(String(tailChunk)) : tailChunk;
1399            const lastChunk = this.chunks[this.chunks.length - 1];
1400            const extendLast = lastChunk && (
1401                    // if stops are same or tail has no stop
1402                    lastChunk.stop === tailChunk.stop || tailChunk.stop == null) &&
1403                // if tail chunk goes just after last chunk
1404                tailChunk.from === lastChunk.from + lastChunk.toString().length;
1405            if (tailChunk instanceof ContinuousTailDetails) {
1406                // check the ability to extend previous chunk
1407                if (extendLast) {
1408                    // extend previous chunk
1409                    lastChunk.extend(tailChunk.toString());
1410                } else {
1411                    // append new chunk
1412                    this.chunks.push(tailChunk);
1413                }
1414            } else if (tailChunk instanceof ChunksTailDetails) {
1415                if (tailChunk.stop == null) {
1416                    // unwrap floating chunks to parent, keeping `from` pos
1417                    let firstTailChunk;
1418                    while (tailChunk.chunks.length && tailChunk.chunks[0].stop == null) {
1419                        firstTailChunk = tailChunk.chunks.shift(); // not possible to be `undefined` because length was checked above
1420                        firstTailChunk.from += tailChunk.from;
1421                        this.extend(firstTailChunk);
1422                    }
1423                }
1424
1425                // if tail chunk still has value
1426                if (tailChunk.toString()) {
1427                    // if chunks contains stops, then popup stop to container
1428                    tailChunk.stop = tailChunk.blockIndex;
1429                    this.chunks.push(tailChunk);
1430                }
1431            }
1432        }
1433        appendTo(masked) {
1434            if (!(masked instanceof IMask.MaskedPattern)) {
1435                const tail = new ContinuousTailDetails(this.toString());
1436                return tail.appendTo(masked);
1437            }
1438            const details = new ChangeDetails();
1439            for (let ci = 0; ci < this.chunks.length; ++ci) {
1440                const chunk = this.chunks[ci];
1441                const lastBlockIter = masked._mapPosToBlock(masked.displayValue.length);
1442                const stop = chunk.stop;
1443                let chunkBlock;
1444                if (stop != null && (
1445                    // if block not found or stop is behind lastBlock
1446                    !lastBlockIter || lastBlockIter.index <= stop)) {
1447                    if (chunk instanceof ChunksTailDetails ||
1448                        // for continuous block also check if stop is exist
1449                        masked._stops.indexOf(stop) >= 0) {
1450                        details.aggregate(masked._appendPlaceholder(stop));
1451                    }
1452                    chunkBlock = chunk instanceof ChunksTailDetails && masked._blocks[stop];
1453                }
1454                if (chunkBlock) {
1455                    const tailDetails = chunkBlock.appendTail(chunk);
1456                    details.aggregate(tailDetails);
1457
1458                    // get not inserted chars
1459                    const remainChars = chunk.toString().slice(tailDetails.rawInserted.length);
1460                    if (remainChars) details.aggregate(masked.append(remainChars, {
1461                        tail: true
1462                    }));
1463                } else {
1464                    details.aggregate(masked.append(chunk.toString(), {
1465                        tail: true
1466                    }));
1467                }
1468            }
1469            return details;
1470        }
1471        get state() {
1472            return {
1473                chunks: this.chunks.map(c => c.state),
1474                from: this.from,
1475                stop: this.stop,
1476                blockIndex: this.blockIndex
1477            };
1478        }
1479        set state(state) {
1480            const {
1481                chunks,
1482                ...props
1483            } = state;
1484            Object.assign(this, props);
1485            this.chunks = chunks.map(cstate => {
1486                const chunk = "chunks" in cstate ? new ChunksTailDetails() : new ContinuousTailDetails();
1487                chunk.state = cstate;
1488                return chunk;
1489            });
1490        }
1491        unshift(beforePos) {
1492            if (!this.chunks.length || beforePos != null && this.from >= beforePos) return '';
1493            const chunkShiftPos = beforePos != null ? beforePos - this.from : beforePos;
1494            let ci = 0;
1495            while (ci < this.chunks.length) {
1496                const chunk = this.chunks[ci];
1497                const shiftChar = chunk.unshift(chunkShiftPos);
1498                if (chunk.toString()) {
1499                    // chunk still contains value
1500                    // but not shifted - means no more available chars to shift
1501                    if (!shiftChar) break;
1502                    ++ci;
1503                } else {
1504                    // clean if chunk has no value
1505                    this.chunks.splice(ci, 1);
1506                }
1507                if (shiftChar) return shiftChar;
1508            }
1509            return '';
1510        }
1511        shift() {
1512            if (!this.chunks.length) return '';
1513            let ci = this.chunks.length - 1;
1514            while (0 <= ci) {
1515                const chunk = this.chunks[ci];
1516                const shiftChar = chunk.shift();
1517                if (chunk.toString()) {
1518                    // chunk still contains value
1519                    // but not shifted - means no more available chars to shift
1520                    if (!shiftChar) break;
1521                    --ci;
1522                } else {
1523                    // clean if chunk has no value
1524                    this.chunks.splice(ci, 1);
1525                }
1526                if (shiftChar) return shiftChar;
1527            }
1528            return '';
1529        }
1530    }
1531
1532    class PatternCursor {
1533        constructor(masked, pos) {
1534            this.masked = masked;
1535            this._log = [];
1536            const {
1537                offset,
1538                index
1539            } = masked._mapPosToBlock(pos) || (pos < 0 ?
1540                // first
1541                {
1542                    index: 0,
1543                    offset: 0
1544                } :
1545                // last
1546                {
1547                    index: this.masked._blocks.length,
1548                    offset: 0
1549                });
1550            this.offset = offset;
1551            this.index = index;
1552            this.ok = false;
1553        }
1554        get block() {
1555            return this.masked._blocks[this.index];
1556        }
1557        get pos() {
1558            return this.masked._blockStartPos(this.index) + this.offset;
1559        }
1560        get state() {
1561            return {
1562                index: this.index,
1563                offset: this.offset,
1564                ok: this.ok
1565            };
1566        }
1567        set state(s) {
1568            Object.assign(this, s);
1569        }
1570        pushState() {
1571            this._log.push(this.state);
1572        }
1573        popState() {
1574            const s = this._log.pop();
1575            if (s) this.state = s;
1576            return s;
1577        }
1578        bindBlock() {
1579            if (this.block) return;
1580            if (this.index < 0) {
1581                this.index = 0;
1582                this.offset = 0;
1583            }
1584            if (this.index >= this.masked._blocks.length) {
1585                this.index = this.masked._blocks.length - 1;
1586                this.offset = this.block.displayValue.length; // TODO this is stupid type error, `block` depends on index that was changed above
1587            }
1588        }
1589        _pushLeft(fn) {
1590            this.pushState();
1591            for (this.bindBlock(); 0 <= this.index; --this.index, this.offset = ((_this$block = this.block) == null ? void 0 : _this$block.displayValue.length) || 0) {
1592                var _this$block;
1593                if (fn()) return this.ok = true;
1594            }
1595            return this.ok = false;
1596        }
1597        _pushRight(fn) {
1598            this.pushState();
1599            for (this.bindBlock(); this.index < this.masked._blocks.length; ++this.index, this.offset = 0) {
1600                if (fn()) return this.ok = true;
1601            }
1602            return this.ok = false;
1603        }
1604        pushLeftBeforeFilled() {
1605            return this._pushLeft(() => {
1606                if (this.block.isFixed || !this.block.value) return;
1607                this.offset = this.block.nearestInputPos(this.offset, DIRECTION.FORCE_LEFT);
1608                if (this.offset !== 0) return true;
1609            });
1610        }
1611        pushLeftBeforeInput() {
1612            // cases:
1613            // filled input: 00|
1614            // optional empty input: 00[]|
1615            // nested block: XX<[]>|
1616            return this._pushLeft(() => {
1617                if (this.block.isFixed) return;
1618                this.offset = this.block.nearestInputPos(this.offset, DIRECTION.LEFT);
1619                return true;
1620            });
1621        }
1622        pushLeftBeforeRequired() {
1623            return this._pushLeft(() => {
1624                if (this.block.isFixed || this.block.isOptional && !this.block.value) return;
1625                this.offset = this.block.nearestInputPos(this.offset, DIRECTION.LEFT);
1626                return true;
1627            });
1628        }
1629        pushRightBeforeFilled() {
1630            return this._pushRight(() => {
1631                if (this.block.isFixed || !this.block.value) return;
1632                this.offset = this.block.nearestInputPos(this.offset, DIRECTION.FORCE_RIGHT);
1633                if (this.offset !== this.block.value.length) return true;
1634            });
1635        }
1636        pushRightBeforeInput() {
1637            return this._pushRight(() => {
1638                if (this.block.isFixed) return;
1639
1640                // const o = this.offset;
1641                this.offset = this.block.nearestInputPos(this.offset, DIRECTION.NONE);
1642                // HACK cases like (STILL DOES NOT WORK FOR NESTED)
1643                // aa|X
1644                // aa<X|[]>X_    - this will not work
1645                // if (o && o === this.offset && this.block instanceof PatternInputDefinition) continue;
1646                return true;
1647            });
1648        }
1649        pushRightBeforeRequired() {
1650            return this._pushRight(() => {
1651                if (this.block.isFixed || this.block.isOptional && !this.block.value) return;
1652
1653                // TODO check |[*]XX_
1654                this.offset = this.block.nearestInputPos(this.offset, DIRECTION.NONE);
1655                return true;
1656            });
1657        }
1658    }
1659
1660    class PatternFixedDefinition {
1661        /** */
1662
1663        /** */
1664
1665        /** */
1666
1667        /** */
1668
1669        /** */
1670
1671        /** */
1672
1673        constructor(opts) {
1674            Object.assign(this, opts);
1675            this._value = '';
1676            this.isFixed = true;
1677        }
1678        get value() {
1679            return this._value;
1680        }
1681        get unmaskedValue() {
1682            return this.isUnmasking ? this.value : '';
1683        }
1684        get rawInputValue() {
1685            return this._isRawInput ? this.value : '';
1686        }
1687        get displayValue() {
1688            return this.value;
1689        }
1690        reset() {
1691            this._isRawInput = false;
1692            this._value = '';
1693        }
1694        remove(fromPos, toPos) {
1695            if (fromPos === void 0) {
1696                fromPos = 0;
1697            }
1698            if (toPos === void 0) {
1699                toPos = this._value.length;
1700            }
1701            this._value = this._value.slice(0, fromPos) + this._value.slice(toPos);
1702            if (!this._value) this._isRawInput = false;
1703            return new ChangeDetails();
1704        }
1705        nearestInputPos(cursorPos, direction) {
1706            if (direction === void 0) {
1707                direction = DIRECTION.NONE;
1708            }
1709            const minPos = 0;
1710            const maxPos = this._value.length;
1711            switch (direction) {
1712                case DIRECTION.LEFT:
1713                case DIRECTION.FORCE_LEFT:
1714                    return minPos;
1715                case DIRECTION.NONE:
1716                case DIRECTION.RIGHT:
1717                case DIRECTION.FORCE_RIGHT:
1718                default:
1719                    return maxPos;
1720            }
1721        }
1722        totalInputPositions(fromPos, toPos) {
1723            if (fromPos === void 0) {
1724                fromPos = 0;
1725            }
1726            if (toPos === void 0) {
1727                toPos = this._value.length;
1728            }
1729            return this._isRawInput ? toPos - fromPos : 0;
1730        }
1731        extractInput(fromPos, toPos, flags) {
1732            if (fromPos === void 0) {
1733                fromPos = 0;
1734            }
1735            if (toPos === void 0) {
1736                toPos = this._value.length;
1737            }
1738            if (flags === void 0) {
1739                flags = {};
1740            }
1741            return flags.raw && this._isRawInput && this._value.slice(fromPos, toPos) || '';
1742        }
1743        get isComplete() {
1744            return true;
1745        }
1746        get isFilled() {
1747            return Boolean(this._value);
1748        }
1749        _appendChar(ch, flags) {
1750            if (flags === void 0) {
1751                flags = {};
1752            }
1753            if (this.isFilled) return new ChangeDetails();
1754            const appendEager = this.eager === true || this.eager === 'append';
1755            const appended = this.char === ch;
1756            const isResolved = appended && (this.isUnmasking || flags.input || flags.raw) && (!flags.raw || !appendEager) && !flags.tail;
1757            const details = new ChangeDetails({
1758                inserted: this.char,
1759                rawInserted: isResolved ? this.char : ''
1760            });
1761            this._value = this.char;
1762            this._isRawInput = isResolved && (flags.raw || flags.input);
1763            return details;
1764        }
1765        _appendEager() {
1766            return this._appendChar(this.char, {
1767                tail: true
1768            });
1769        }
1770        _appendPlaceholder() {
1771            const details = new ChangeDetails();
1772            if (this.isFilled) return details;
1773            this._value = details.inserted = this.char;
1774            return details;
1775        }
1776        extractTail() {
1777            return new ContinuousTailDetails('');
1778        }
1779        appendTail(tail) {
1780            if (isString(tail)) tail = new ContinuousTailDetails(String(tail));
1781            return tail.appendTo(this);
1782        }
1783        append(str, flags, tail) {
1784            const details = this._appendChar(str[0], flags);
1785            if (tail != null) {
1786                details.tailShift += this.appendTail(tail).tailShift;
1787            }
1788            return details;
1789        }
1790        doCommit() {}
1791        get state() {
1792            return {
1793                _value: this._value,
1794                _rawInputValue: this.rawInputValue
1795            };
1796        }
1797        set state(state) {
1798            this._value = state._value;
1799            this._isRawInput = Boolean(state._rawInputValue);
1800        }
1801        pad(flags) {
1802            return this._appendPlaceholder();
1803        }
1804    }
1805
1806    class PatternInputDefinition {
1807        /** */
1808
1809        /** */
1810
1811        /** */
1812
1813        /** */
1814
1815        /** */
1816
1817        /** */
1818
1819        /** */
1820
1821        /** */
1822
1823        constructor(opts) {
1824            const {
1825                parent,
1826                isOptional,
1827                placeholderChar,
1828                displayChar,
1829                lazy,
1830                eager,
1831                ...maskOpts
1832            } = opts;
1833            this.masked = createMask(maskOpts);
1834            Object.assign(this, {
1835                parent,
1836                isOptional,
1837                placeholderChar,
1838                displayChar,
1839                lazy,
1840                eager
1841            });
1842        }
1843        reset() {
1844            this.isFilled = false;
1845            this.masked.reset();
1846        }
1847        remove(fromPos, toPos) {
1848            if (fromPos === void 0) {
1849                fromPos = 0;
1850            }
1851            if (toPos === void 0) {
1852                toPos = this.value.length;
1853            }
1854            if (fromPos === 0 && toPos >= 1) {
1855                this.isFilled = false;
1856                return this.masked.remove(fromPos, toPos);
1857            }
1858            return new ChangeDetails();
1859        }
1860        get value() {
1861            return this.masked.value || (this.isFilled && !this.isOptional ? this.placeholderChar : '');
1862        }
1863        get unmaskedValue() {
1864            return this.masked.unmaskedValue;
1865        }
1866        get rawInputValue() {
1867            return this.masked.rawInputValue;
1868        }
1869        get displayValue() {
1870            return this.masked.value && this.displayChar || this.value;
1871        }
1872        get isComplete() {
1873            return Boolean(this.masked.value) || this.isOptional;
1874        }
1875        _appendChar(ch, flags) {
1876            if (flags === void 0) {
1877                flags = {};
1878            }
1879            if (this.isFilled) return new ChangeDetails();
1880            const state = this.masked.state;
1881            // simulate input
1882            let details = this.masked._appendChar(ch, this.currentMaskFlags(flags));
1883            if (details.inserted && this.doValidate(flags) === false) {
1884                details = new ChangeDetails();
1885                this.masked.state = state;
1886            }
1887            if (!details.inserted && !this.isOptional && !this.lazy && !flags.input) {
1888                details.inserted = this.placeholderChar;
1889            }
1890            details.skip = !details.inserted && !this.isOptional;
1891            this.isFilled = Boolean(details.inserted);
1892            return details;
1893        }
1894        append(str, flags, tail) {
1895            // TODO probably should be done via _appendChar
1896            return this.masked.append(str, this.currentMaskFlags(flags), tail);
1897        }
1898        _appendPlaceholder() {
1899            if (this.isFilled || this.isOptional) return new ChangeDetails();
1900            this.isFilled = true;
1901            return new ChangeDetails({
1902                inserted: this.placeholderChar
1903            });
1904        }
1905        _appendEager() {
1906            return new ChangeDetails();
1907        }
1908        extractTail(fromPos, toPos) {
1909            return this.masked.extractTail(fromPos, toPos);
1910        }
1911        appendTail(tail) {
1912            return this.masked.appendTail(tail);
1913        }
1914        extractInput(fromPos, toPos, flags) {
1915            if (fromPos === void 0) {
1916                fromPos = 0;
1917            }
1918            if (toPos === void 0) {
1919                toPos = this.value.length;
1920            }
1921            return this.masked.extractInput(fromPos, toPos, flags);
1922        }
1923        nearestInputPos(cursorPos, direction) {
1924            if (direction === void 0) {
1925                direction = DIRECTION.NONE;
1926            }
1927            const minPos = 0;
1928            const maxPos = this.value.length;
1929            const boundPos = Math.min(Math.max(cursorPos, minPos), maxPos);
1930            switch (direction) {
1931                case DIRECTION.LEFT:
1932                case DIRECTION.FORCE_LEFT:
1933                    return this.isComplete ? boundPos : minPos;
1934                case DIRECTION.RIGHT:
1935                case DIRECTION.FORCE_RIGHT:
1936                    return this.isComplete ? boundPos : maxPos;
1937                case DIRECTION.NONE:
1938                default:
1939                    return boundPos;
1940            }
1941        }
1942        totalInputPositions(fromPos, toPos) {
1943            if (fromPos === void 0) {
1944                fromPos = 0;
1945            }
1946            if (toPos === void 0) {
1947                toPos = this.value.length;
1948            }
1949            return this.value.slice(fromPos, toPos).length;
1950        }
1951        doValidate(flags) {
1952            return this.masked.doValidate(this.currentMaskFlags(flags)) && (!this.parent || this.parent.doValidate(this.currentMaskFlags(flags)));
1953        }
1954        doCommit() {
1955            this.masked.doCommit();
1956        }
1957        get state() {
1958            return {
1959                _value: this.value,
1960                _rawInputValue: this.rawInputValue,
1961                masked: this.masked.state,
1962                isFilled: this.isFilled
1963            };
1964        }
1965        set state(state) {
1966            this.masked.state = state.masked;
1967            this.isFilled = state.isFilled;
1968        }
1969        currentMaskFlags(flags) {
1970            var _flags$_beforeTailSta;
1971            return {
1972                ...flags,
1973                _beforeTailState: (flags == null || (_flags$_beforeTailSta = flags._beforeTailState) == null ? void 0 : _flags$_beforeTailSta.masked) || (flags == null ? void 0 : flags._beforeTailState)
1974            };
1975        }
1976        pad(flags) {
1977            return new ChangeDetails();
1978        }
1979    }
1980    PatternInputDefinition.DEFAULT_DEFINITIONS = {
1981        '0': /\d/,
1982        'a': /[\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/,
1983        // http://stackoverflow.com/a/22075070
1984        '*': /./
1985    };
1986
1987    /** Masking by RegExp */
1988    class MaskedRegExp extends Masked {
1989        /** */
1990
1991        /** Enable characters overwriting */
1992
1993        /** */
1994
1995        /** */
1996
1997        /** */
1998
1999        updateOptions(opts) {
2000            super.updateOptions(opts);
2001        }
2002        _update(opts) {
2003            const mask = opts.mask;
2004            if (mask) opts.validate = value => value.search(mask) >= 0;
2005            super._update(opts);
2006        }
2007    }
2008    IMask.MaskedRegExp = MaskedRegExp;
2009
2010    /** Pattern mask */
2011    class MaskedPattern extends Masked {
2012        /** */
2013
2014        /** */
2015
2016        /** Single char for empty input */
2017
2018        /** Single char for filled input */
2019
2020        /** Show placeholder only when needed */
2021
2022        /** Enable characters overwriting */
2023
2024        /** */
2025
2026        /** */
2027
2028        /** */
2029
2030        constructor(opts) {
2031            super({
2032                ...MaskedPattern.DEFAULTS,
2033                ...opts,
2034                definitions: Object.assign({}, PatternInputDefinition.DEFAULT_DEFINITIONS, opts == null ? void 0 : opts.definitions)
2035            });
2036        }
2037        updateOptions(opts) {
2038            super.updateOptions(opts);
2039        }
2040        _update(opts) {
2041            opts.definitions = Object.assign({}, this.definitions, opts.definitions);
2042            super._update(opts);
2043            this._rebuildMask();
2044        }
2045        _rebuildMask() {
2046            const defs = this.definitions;
2047            this._blocks = [];
2048            this.exposeBlock = undefined;
2049            this._stops = [];
2050            this._maskedBlocks = {};
2051            const pattern = this.mask;
2052            if (!pattern || !defs) return;
2053            let unmaskingBlock = false;
2054            let optionalBlock = false;
2055            for (let i = 0; i < pattern.length; ++i) {
2056                if (this.blocks) {
2057                    const p = pattern.slice(i);
2058                    const bNames = Object.keys(this.blocks).filter(bName => p.indexOf(bName) === 0);
2059                    // order by key length
2060                    bNames.sort((a, b) => b.length - a.length);
2061                    // use block name with max length
2062                    const bName = bNames[0];
2063                    if (bName) {
2064                        const {
2065                            expose,
2066                            repeat,
2067                            ...bOpts
2068                        } = normalizeOpts(this.blocks[bName]); // TODO type Opts<Arg & Extra>
2069                        const blockOpts = {
2070                            lazy: this.lazy,
2071                            eager: this.eager,
2072                            placeholderChar: this.placeholderChar,
2073                            displayChar: this.displayChar,
2074                            overwrite: this.overwrite,
2075                            autofix: this.autofix,
2076                            ...bOpts,
2077                            repeat,
2078                            parent: this
2079                        };
2080                        const maskedBlock = repeat != null ? new IMask.RepeatBlock(blockOpts /* TODO */) : createMask(blockOpts);
2081                        if (maskedBlock) {
2082                            this._blocks.push(maskedBlock);
2083                            if (expose) this.exposeBlock = maskedBlock;
2084
2085                            // store block index
2086                            if (!this._maskedBlocks[bName]) this._maskedBlocks[bName] = [];
2087                            this._maskedBlocks[bName].push(this._blocks.length - 1);
2088                        }
2089                        i += bName.length - 1;
2090                        continue;
2091                    }
2092                }
2093                let char = pattern[i];
2094                let isInput = (char in defs);
2095                if (char === MaskedPattern.STOP_CHAR) {
2096                    this._stops.push(this._blocks.length);
2097                    continue;
2098                }
2099                if (char === '{' || char === '}') {
2100                    unmaskingBlock = !unmaskingBlock;
2101                    continue;
2102                }
2103                if (char === '[' || char === ']') {
2104                    optionalBlock = !optionalBlock;
2105                    continue;
2106                }
2107                if (char === MaskedPattern.ESCAPE_CHAR) {
2108                    ++i;
2109                    char = pattern[i];
2110                    if (!char) break;
2111                    isInput = false;
2112                }
2113                const def = isInput ? new PatternInputDefinition({
2114                    isOptional: optionalBlock,
2115                    lazy: this.lazy,
2116                    eager: this.eager,
2117                    placeholderChar: this.placeholderChar,
2118                    displayChar: this.displayChar,
2119                    ...normalizeOpts(defs[char]),
2120                    parent: this
2121                }) : new PatternFixedDefinition({
2122                    char,
2123                    eager: this.eager,
2124                    isUnmasking: unmaskingBlock
2125                });
2126                this._blocks.push(def);
2127            }
2128        }
2129        get state() {
2130            return {
2131                ...super.state,
2132                _blocks: this._blocks.map(b => b.state)
2133            };
2134        }
2135        set state(state) {
2136            if (!state) {
2137                this.reset();
2138                return;
2139            }
2140            const {
2141                _blocks,
2142                ...maskedState
2143            } = state;
2144            this._blocks.forEach((b, bi) => b.state = _blocks[bi]);
2145            super.state = maskedState;
2146        }
2147        reset() {
2148            super.reset();
2149            this._blocks.forEach(b => b.reset());
2150        }
2151        get isComplete() {
2152            return this.exposeBlock ? this.exposeBlock.isComplete : this._blocks.every(b => b.isComplete);
2153        }
2154        get isFilled() {
2155            return this._blocks.every(b => b.isFilled);
2156        }
2157        get isFixed() {
2158            return this._blocks.every(b => b.isFixed);
2159        }
2160        get isOptional() {
2161            return this._blocks.every(b => b.isOptional);
2162        }
2163        doCommit() {
2164            this._blocks.forEach(b => b.doCommit());
2165            super.doCommit();
2166        }
2167        get unmaskedValue() {
2168            return this.exposeBlock ? this.exposeBlock.unmaskedValue : this._blocks.reduce((str, b) => str += b.unmaskedValue, '');
2169        }
2170        set unmaskedValue(unmaskedValue) {
2171            if (this.exposeBlock) {
2172                const tail = this.extractTail(this._blockStartPos(this._blocks.indexOf(this.exposeBlock)) + this.exposeBlock.displayValue.length);
2173                this.exposeBlock.unmaskedValue = unmaskedValue;
2174                this.appendTail(tail);
2175                this.doCommit();
2176            } else super.unmaskedValue = unmaskedValue;
2177        }
2178        get value() {
2179            return this.exposeBlock ? this.exposeBlock.value :
2180                // TODO return _value when not in change?
2181                this._blocks.reduce((str, b) => str += b.value, '');
2182        }
2183        set value(value) {
2184            if (this.exposeBlock) {
2185                const tail = this.extractTail(this._blockStartPos(this._blocks.indexOf(this.exposeBlock)) + this.exposeBlock.displayValue.length);
2186                this.exposeBlock.value = value;
2187                this.appendTail(tail);
2188                this.doCommit();
2189            } else super.value = value;
2190        }
2191        get typedValue() {
2192            return this.exposeBlock ? this.exposeBlock.typedValue : super.typedValue;
2193        }
2194        set typedValue(value) {
2195            if (this.exposeBlock) {
2196                const tail = this.extractTail(this._blockStartPos(this._blocks.indexOf(this.exposeBlock)) + this.exposeBlock.displayValue.length);
2197                this.exposeBlock.typedValue = value;
2198                this.appendTail(tail);
2199                this.doCommit();
2200            } else super.typedValue = value;
2201        }
2202        get displayValue() {
2203            return this._blocks.reduce((str, b) => str += b.displayValue, '');
2204        }
2205        appendTail(tail) {
2206            return super.appendTail(tail).aggregate(this._appendPlaceholder());
2207        }
2208        _appendEager() {
2209            var _this$_mapPosToBlock;
2210            const details = new ChangeDetails();
2211            let startBlockIndex = (_this$_mapPosToBlock = this._mapPosToBlock(this.displayValue.length)) == null ? void 0 : _this$_mapPosToBlock.index;
2212            if (startBlockIndex == null) return details;
2213
2214            // TODO test if it works for nested pattern masks
2215            if (this._blocks[startBlockIndex].isFilled) ++startBlockIndex;
2216            for (let bi = startBlockIndex; bi < this._blocks.length; ++bi) {
2217                const d = this._blocks[bi]._appendEager();
2218                if (!d.inserted) break;
2219                details.aggregate(d);
2220            }
2221            return details;
2222        }
2223        _appendCharRaw(ch, flags) {
2224            if (flags === void 0) {
2225                flags = {};
2226            }
2227            const blockIter = this._mapPosToBlock(this.displayValue.length);
2228            const details = new ChangeDetails();
2229            if (!blockIter) return details;
2230            for (let bi = blockIter.index, block; block = this._blocks[bi]; ++bi) {
2231                var _flags$_beforeTailSta;
2232                const blockDetails = block._appendChar(ch, {
2233                    ...flags,
2234                    _beforeTailState: (_flags$_beforeTailSta = flags._beforeTailState) == null || (_flags$_beforeTailSta = _flags$_beforeTailSta._blocks) == null ? void 0 : _flags$_beforeTailSta[bi]
2235                });
2236                details.aggregate(blockDetails);
2237                if (blockDetails.consumed) break; // go next char
2238            }
2239            return details;
2240        }
2241        extractTail(fromPos, toPos) {
2242            if (fromPos === void 0) {
2243                fromPos = 0;
2244            }
2245            if (toPos === void 0) {
2246                toPos = this.displayValue.length;
2247            }
2248            const chunkTail = new ChunksTailDetails();
2249            if (fromPos === toPos) return chunkTail;
2250            this._forEachBlocksInRange(fromPos, toPos, (b, bi, bFromPos, bToPos) => {
2251                const blockChunk = b.extractTail(bFromPos, bToPos);
2252                blockChunk.stop = this._findStopBefore(bi);
2253                blockChunk.from = this._blockStartPos(bi);
2254                if (blockChunk instanceof ChunksTailDetails) blockChunk.blockIndex = bi;
2255                chunkTail.extend(blockChunk);
2256            });
2257            return chunkTail;
2258        }
2259        extractInput(fromPos, toPos, flags) {
2260            if (fromPos === void 0) {
2261                fromPos = 0;
2262            }
2263            if (toPos === void 0) {
2264                toPos = this.displayValue.length;
2265            }
2266            if (flags === void 0) {
2267                flags = {};
2268            }
2269            if (fromPos === toPos) return '';
2270            let input = '';
2271            this._forEachBlocksInRange(fromPos, toPos, (b, _, fromPos, toPos) => {
2272                input += b.extractInput(fromPos, toPos, flags);
2273            });
2274            return input;
2275        }
2276        _findStopBefore(blockIndex) {
2277            let stopBefore;
2278            for (let si = 0; si < this._stops.length; ++si) {
2279                const stop = this._stops[si];
2280                if (stop <= blockIndex) stopBefore = stop;else break;
2281            }
2282            return stopBefore;
2283        }
2284
2285        /** Appends placeholder depending on laziness */
2286        _appendPlaceholder(toBlockIndex) {
2287            const details = new ChangeDetails();
2288            if (this.lazy && toBlockIndex == null) return details;
2289            const startBlockIter = this._mapPosToBlock(this.displayValue.length);
2290            if (!startBlockIter) return details;
2291            const startBlockIndex = startBlockIter.index;
2292            const endBlockIndex = toBlockIndex != null ? toBlockIndex : this._blocks.length;
2293            this._blocks.slice(startBlockIndex, endBlockIndex).forEach(b => {
2294                if (!b.lazy || toBlockIndex != null) {
2295                    var _blocks2;
2296                    details.aggregate(b._appendPlaceholder((_blocks2 = b._blocks) == null ? void 0 : _blocks2.length));
2297                }
2298            });
2299            return details;
2300        }
2301
2302        /** Finds block in pos */
2303        _mapPosToBlock(pos) {
2304            let accVal = '';
2305            for (let bi = 0; bi < this._blocks.length; ++bi) {
2306                const block = this._blocks[bi];
2307                const blockStartPos = accVal.length;
2308                accVal += block.displayValue;
2309                if (pos <= accVal.length) {
2310                    return {
2311                        index: bi,
2312                        offset: pos - blockStartPos
2313                    };
2314                }
2315            }
2316        }
2317        _blockStartPos(blockIndex) {
2318            return this._blocks.slice(0, blockIndex).reduce((pos, b) => pos += b.displayValue.length, 0);
2319        }
2320        _forEachBlocksInRange(fromPos, toPos, fn) {
2321            if (toPos === void 0) {
2322                toPos = this.displayValue.length;
2323            }
2324            const fromBlockIter = this._mapPosToBlock(fromPos);
2325            if (fromBlockIter) {
2326                const toBlockIter = this._mapPosToBlock(toPos);
2327                // process first block
2328                const isSameBlock = toBlockIter && fromBlockIter.index === toBlockIter.index;
2329                const fromBlockStartPos = fromBlockIter.offset;
2330                const fromBlockEndPos = toBlockIter && isSameBlock ? toBlockIter.offset : this._blocks[fromBlockIter.index].displayValue.length;
2331                fn(this._blocks[fromBlockIter.index], fromBlockIter.index, fromBlockStartPos, fromBlockEndPos);
2332                if (toBlockIter && !isSameBlock) {
2333                    // process intermediate blocks
2334                    for (let bi = fromBlockIter.index + 1; bi < toBlockIter.index; ++bi) {
2335                        fn(this._blocks[bi], bi, 0, this._blocks[bi].displayValue.length);
2336                    }
2337
2338                    // process last block
2339                    fn(this._blocks[toBlockIter.index], toBlockIter.index, 0, toBlockIter.offset);
2340                }
2341            }
2342        }
2343        remove(fromPos, toPos) {
2344            if (fromPos === void 0) {
2345                fromPos = 0;
2346            }
2347            if (toPos === void 0) {
2348                toPos = this.displayValue.length;
2349            }
2350            const removeDetails = super.remove(fromPos, toPos);
2351            this._forEachBlocksInRange(fromPos, toPos, (b, _, bFromPos, bToPos) => {
2352                removeDetails.aggregate(b.remove(bFromPos, bToPos));
2353            });
2354            return removeDetails;
2355        }
2356        nearestInputPos(cursorPos, direction) {
2357            if (direction === void 0) {
2358                direction = DIRECTION.NONE;
2359            }
2360            if (!this._blocks.length) return 0;
2361            const cursor = new PatternCursor(this, cursorPos);
2362            if (direction === DIRECTION.NONE) {
2363                // -------------------------------------------------
2364                // NONE should only go out from fixed to the right!
2365                // -------------------------------------------------
2366                if (cursor.pushRightBeforeInput()) return cursor.pos;
2367                cursor.popState();
2368                if (cursor.pushLeftBeforeInput()) return cursor.pos;
2369                return this.displayValue.length;
2370            }
2371
2372            // FORCE is only about a|* otherwise is 0
2373            if (direction === DIRECTION.LEFT || direction === DIRECTION.FORCE_LEFT) {
2374                // try to break fast when *|a
2375                if (direction === DIRECTION.LEFT) {
2376                    cursor.pushRightBeforeFilled();
2377                    if (cursor.ok && cursor.pos === cursorPos) return cursorPos;
2378                    cursor.popState();
2379                }
2380
2381                // forward flow
2382                cursor.pushLeftBeforeInput();
2383                cursor.pushLeftBeforeRequired();
2384                cursor.pushLeftBeforeFilled();
2385
2386                // backward flow
2387                if (direction === DIRECTION.LEFT) {
2388                    cursor.pushRightBeforeInput();
2389                    cursor.pushRightBeforeRequired();
2390                    if (cursor.ok && cursor.pos <= cursorPos) return cursor.pos;
2391                    cursor.popState();
2392                    if (cursor.ok && cursor.pos <= cursorPos) return cursor.pos;
2393                    cursor.popState();
2394                }
2395                if (cursor.ok) return cursor.pos;
2396                if (direction === DIRECTION.FORCE_LEFT) return 0;
2397                cursor.popState();
2398                if (cursor.ok) return cursor.pos;
2399                cursor.popState();
2400                if (cursor.ok) return cursor.pos;
2401                return 0;
2402            }
2403            if (direction === DIRECTION.RIGHT || direction === DIRECTION.FORCE_RIGHT) {
2404                // forward flow
2405                cursor.pushRightBeforeInput();
2406                cursor.pushRightBeforeRequired();
2407                if (cursor.pushRightBeforeFilled()) return cursor.pos;
2408                if (direction === DIRECTION.FORCE_RIGHT) return this.displayValue.length;
2409
2410                // backward flow
2411                cursor.popState();
2412                if (cursor.ok) return cursor.pos;
2413                cursor.popState();
2414                if (cursor.ok) return cursor.pos;
2415                return this.nearestInputPos(cursorPos, DIRECTION.LEFT);
2416            }
2417            return cursorPos;
2418        }
2419        totalInputPositions(fromPos, toPos) {
2420            if (fromPos === void 0) {
2421                fromPos = 0;
2422            }
2423            if (toPos === void 0) {
2424                toPos = this.displayValue.length;
2425            }
2426            let total = 0;
2427            this._forEachBlocksInRange(fromPos, toPos, (b, _, bFromPos, bToPos) => {
2428                total += b.totalInputPositions(bFromPos, bToPos);
2429            });
2430            return total;
2431        }
2432
2433        /** Get block by name */
2434        maskedBlock(name) {
2435            return this.maskedBlocks(name)[0];
2436        }
2437
2438        /** Get all blocks by name */
2439        maskedBlocks(name) {
2440            const indices = this._maskedBlocks[name];
2441            if (!indices) return [];
2442            return indices.map(gi => this._blocks[gi]);
2443        }
2444        pad(flags) {
2445            const details = new ChangeDetails();
2446            this._forEachBlocksInRange(0, this.displayValue.length, b => details.aggregate(b.pad(flags)));
2447            return details;
2448        }
2449    }
2450    MaskedPattern.DEFAULTS = {
2451        ...Masked.DEFAULTS,
2452        lazy: true,
2453        placeholderChar: '_'
2454    };
2455    MaskedPattern.STOP_CHAR = '`';
2456    MaskedPattern.ESCAPE_CHAR = '\\';
2457    MaskedPattern.InputDefinition = PatternInputDefinition;
2458    MaskedPattern.FixedDefinition = PatternFixedDefinition;
2459    IMask.MaskedPattern = MaskedPattern;
2460
2461    /** Pattern which accepts ranges */
2462    class MaskedRange extends MaskedPattern {
2463        /**
2464         Optionally sets max length of pattern.
2465         Used when pattern length is longer then `to` param length. Pads zeros at start in this case.
2466         */
2467
2468        /** Min bound */
2469
2470        /** Max bound */
2471
2472        get _matchFrom() {
2473            return this.maxLength - String(this.from).length;
2474        }
2475        constructor(opts) {
2476            super(opts); // mask will be created in _update
2477        }
2478        updateOptions(opts) {
2479            super.updateOptions(opts);
2480        }
2481        _update(opts) {
2482            const {
2483                to = this.to || 0,
2484                from = this.from || 0,
2485                maxLength = this.maxLength || 0,
2486                autofix = this.autofix,
2487                ...patternOpts
2488            } = opts;
2489            this.to = to;
2490            this.from = from;
2491            this.maxLength = Math.max(String(to).length, maxLength);
2492            this.autofix = autofix;
2493            const fromStr = String(this.from).padStart(this.maxLength, '0');
2494            const toStr = String(this.to).padStart(this.maxLength, '0');
2495            let sameCharsCount = 0;
2496            while (sameCharsCount < toStr.length && toStr[sameCharsCount] === fromStr[sameCharsCount]) ++sameCharsCount;
2497            patternOpts.mask = toStr.slice(0, sameCharsCount).replace(/0/g, '\\0') + '0'.repeat(this.maxLength - sameCharsCount);
2498            super._update(patternOpts);
2499        }
2500        get isComplete() {
2501            return super.isComplete && Boolean(this.value);
2502        }
2503        boundaries(str) {
2504            let minstr = '';
2505            let maxstr = '';
2506            const [, placeholder, num] = str.match(/^(\D*)(\d*)(\D*)/) || [];
2507            if (num) {
2508                minstr = '0'.repeat(placeholder.length) + num;
2509                maxstr = '9'.repeat(placeholder.length) + num;
2510            }
2511            minstr = minstr.padEnd(this.maxLength, '0');
2512            maxstr = maxstr.padEnd(this.maxLength, '9');
2513            return [minstr, maxstr];
2514        }
2515        doPrepareChar(ch, flags) {
2516            if (flags === void 0) {
2517                flags = {};
2518            }
2519            let details;
2520            [ch, details] = super.doPrepareChar(ch.replace(/\D/g, ''), flags);
2521            if (!ch) details.skip = !this.isComplete;
2522            return [ch, details];
2523        }
2524        _appendCharRaw(ch, flags) {
2525            if (flags === void 0) {
2526                flags = {};
2527            }
2528            if (!this.autofix || this.value.length + 1 > this.maxLength) return super._appendCharRaw(ch, flags);
2529            const fromStr = String(this.from).padStart(this.maxLength, '0');
2530            const toStr = String(this.to).padStart(this.maxLength, '0');
2531            const [minstr, maxstr] = this.boundaries(this.value + ch);
2532            if (Number(maxstr) < this.from) return super._appendCharRaw(fromStr[this.value.length], flags);
2533            if (Number(minstr) > this.to) {
2534                if (!flags.tail && this.autofix === 'pad' && this.value.length + 1 < this.maxLength) {
2535                    return super._appendCharRaw(fromStr[this.value.length], flags).aggregate(this._appendCharRaw(ch, flags));
2536                }
2537                return super._appendCharRaw(toStr[this.value.length], flags);
2538            }
2539            return super._appendCharRaw(ch, flags);
2540        }
2541        doValidate(flags) {
2542            const str = this.value;
2543            const firstNonZero = str.search(/[^0]/);
2544            if (firstNonZero === -1 && str.length <= this._matchFrom) return true;
2545            const [minstr, maxstr] = this.boundaries(str);
2546            return this.from <= Number(maxstr) && Number(minstr) <= this.to && super.doValidate(flags);
2547        }
2548        pad(flags) {
2549            const details = new ChangeDetails();
2550            if (this.value.length === this.maxLength) return details;
2551            const value = this.value;
2552            const padLength = this.maxLength - this.value.length;
2553            if (padLength) {
2554                this.reset();
2555                for (let i = 0; i < padLength; ++i) {
2556                    details.aggregate(super._appendCharRaw('0', flags));
2557                }
2558
2559                // append tail
2560                value.split('').forEach(ch => this._appendCharRaw(ch));
2561            }
2562            return details;
2563        }
2564    }
2565    IMask.MaskedRange = MaskedRange;
2566
2567    const DefaultPattern = 'd{.}`m{.}`Y';
2568
2569    // Make format and parse required when pattern is provided
2570
2571    /** Date mask */
2572    class MaskedDate extends MaskedPattern {
2573        static extractPatternOptions(opts) {
2574            const {
2575                mask,
2576                pattern,
2577                ...patternOpts
2578            } = opts;
2579            return {
2580                ...patternOpts,
2581                mask: isString(mask) ? mask : pattern
2582            };
2583        }
2584
2585        /** Pattern mask for date according to {@link MaskedDate#format} */
2586
2587        /** Start date */
2588
2589        /** End date */
2590
2591        /** Format typed value to string */
2592
2593        /** Parse string to get typed value */
2594
2595        constructor(opts) {
2596            super(MaskedDate.extractPatternOptions({
2597                ...MaskedDate.DEFAULTS,
2598                ...opts
2599            }));
2600        }
2601        updateOptions(opts) {
2602            super.updateOptions(opts);
2603        }
2604        _update(opts) {
2605            const {
2606                mask,
2607                pattern,
2608                blocks,
2609                ...patternOpts
2610            } = {
2611                ...MaskedDate.DEFAULTS,
2612                ...opts
2613            };
2614            const patternBlocks = Object.assign({}, MaskedDate.GET_DEFAULT_BLOCKS());
2615            // adjust year block
2616            if (opts.min) patternBlocks.Y.from = opts.min.getFullYear();
2617            if (opts.max) patternBlocks.Y.to = opts.max.getFullYear();
2618            if (opts.min && opts.max && patternBlocks.Y.from === patternBlocks.Y.to) {
2619                patternBlocks.m.from = opts.min.getMonth() + 1;
2620                patternBlocks.m.to = opts.max.getMonth() + 1;
2621                if (patternBlocks.m.from === patternBlocks.m.to) {
2622                    patternBlocks.d.from = opts.min.getDate();
2623                    patternBlocks.d.to = opts.max.getDate();
2624                }
2625            }
2626            Object.assign(patternBlocks, this.blocks, blocks);
2627            super._update({
2628                ...patternOpts,
2629                mask: isString(mask) ? mask : pattern,
2630                blocks: patternBlocks
2631            });
2632        }
2633        doValidate(flags) {
2634            const date = this.date;
2635            return super.doValidate(flags) && (!this.isComplete || this.isDateExist(this.value) && date != null && (this.min == null || this.min <= date) && (this.max == null || date <= this.max));
2636        }
2637
2638        /** Checks if date is exists */
2639        isDateExist(str) {
2640            return this.format(this.parse(str, this), this).indexOf(str) >= 0;
2641        }
2642
2643        /** Parsed Date */
2644        get date() {
2645            return this.typedValue;
2646        }
2647        set date(date) {
2648            this.typedValue = date;
2649        }
2650        get typedValue() {
2651            return this.isComplete ? super.typedValue : null;
2652        }
2653        set typedValue(value) {
2654            super.typedValue = value;
2655        }
2656        maskEquals(mask) {
2657            return mask === Date || super.maskEquals(mask);
2658        }
2659        optionsIsChanged(opts) {
2660            return super.optionsIsChanged(MaskedDate.extractPatternOptions(opts));
2661        }
2662    }
2663    MaskedDate.GET_DEFAULT_BLOCKS = () => ({
2664        d: {
2665            mask: MaskedRange,
2666            from: 1,
2667            to: 31,
2668            maxLength: 2
2669        },
2670        m: {
2671            mask: MaskedRange,
2672            from: 1,
2673            to: 12,
2674            maxLength: 2
2675        },
2676        Y: {
2677            mask: MaskedRange,
2678            from: 1900,
2679            to: 9999
2680        }
2681    });
2682    MaskedDate.DEFAULTS = {
2683        ...MaskedPattern.DEFAULTS,
2684        mask: Date,
2685        pattern: DefaultPattern,
2686        format: (date, masked) => {
2687            if (!date) return '';
2688            const day = String(date.getDate()).padStart(2, '0');
2689            const month = String(date.getMonth() + 1).padStart(2, '0');
2690            const year = date.getFullYear();
2691            return [day, month, year].join('.');
2692        },
2693        parse: (str, masked) => {
2694            const [day, month, year] = str.split('.').map(Number);
2695            return new Date(year, month - 1, day);
2696        }
2697    };
2698    IMask.MaskedDate = MaskedDate;
2699
2700    /** Dynamic mask for choosing appropriate mask in run-time */
2701    class MaskedDynamic extends Masked {
2702        constructor(opts) {
2703            super({
2704                ...MaskedDynamic.DEFAULTS,
2705                ...opts
2706            });
2707            this.currentMask = undefined;
2708        }
2709        updateOptions(opts) {
2710            super.updateOptions(opts);
2711        }
2712        _update(opts) {
2713            super._update(opts);
2714            if ('mask' in opts) {
2715                this.exposeMask = undefined;
2716                // mask could be totally dynamic with only `dispatch` option
2717                this.compiledMasks = Array.isArray(opts.mask) ? opts.mask.map(m => {
2718                    const {
2719                        expose,
2720                        ...maskOpts
2721                    } = normalizeOpts(m);
2722                    const masked = createMask({
2723                        overwrite: this._overwrite,
2724                        eager: this._eager,
2725                        skipInvalid: this._skipInvalid,
2726                        ...maskOpts
2727                    });
2728                    if (expose) this.exposeMask = masked;
2729                    return masked;
2730                }) : [];
2731
2732                // this.currentMask = this.doDispatch(''); // probably not needed but lets see
2733            }
2734        }
2735        _appendCharRaw(ch, flags) {
2736            if (flags === void 0) {
2737                flags = {};
2738            }
2739            const details = this._applyDispatch(ch, flags);
2740            if (this.currentMask) {
2741                details.aggregate(this.currentMask._appendChar(ch, this.currentMaskFlags(flags)));
2742            }
2743            return details;
2744        }
2745        _applyDispatch(appended, flags, tail) {
2746            if (appended === void 0) {
2747                appended = '';
2748            }
2749            if (flags === void 0) {
2750                flags = {};
2751            }
2752            if (tail === void 0) {
2753                tail = '';
2754            }
2755            const prevValueBeforeTail = flags.tail && flags._beforeTailState != null ? flags._beforeTailState._value : this.value;
2756            const inputValue = this.rawInputValue;
2757            const insertValue = flags.tail && flags._beforeTailState != null ? flags._beforeTailState._rawInputValue : inputValue;
2758            const tailValue = inputValue.slice(insertValue.length);
2759            const prevMask = this.currentMask;
2760            const details = new ChangeDetails();
2761            const prevMaskState = prevMask == null ? void 0 : prevMask.state;
2762
2763            // clone flags to prevent overwriting `_beforeTailState`
2764            this.currentMask = this.doDispatch(appended, {
2765                ...flags
2766            }, tail);
2767
2768            // restore state after dispatch
2769            if (this.currentMask) {
2770                if (this.currentMask !== prevMask) {
2771                    // if mask changed reapply input
2772                    this.currentMask.reset();
2773                    if (insertValue) {
2774                        this.currentMask.append(insertValue, {
2775                            raw: true
2776                        });
2777                        details.tailShift = this.currentMask.value.length - prevValueBeforeTail.length;
2778                    }
2779                    if (tailValue) {
2780                        details.tailShift += this.currentMask.append(tailValue, {
2781                            raw: true,
2782                            tail: true
2783                        }).tailShift;
2784                    }
2785                } else if (prevMaskState) {
2786                    // Dispatch can do something bad with state, so
2787                    // restore prev mask state
2788                    this.currentMask.state = prevMaskState;
2789                }
2790            }
2791            return details;
2792        }
2793        _appendPlaceholder() {
2794            const details = this._applyDispatch();
2795            if (this.currentMask) {
2796                details.aggregate(this.currentMask._appendPlaceholder());
2797            }
2798            return details;
2799        }
2800        _appendEager() {
2801            const details = this._applyDispatch();
2802            if (this.currentMask) {
2803                details.aggregate(this.currentMask._appendEager());
2804            }
2805            return details;
2806        }
2807        appendTail(tail) {
2808            const details = new ChangeDetails();
2809            if (tail) details.aggregate(this._applyDispatch('', {}, tail));
2810            return details.aggregate(this.currentMask ? this.currentMask.appendTail(tail) : super.appendTail(tail));
2811        }
2812        currentMaskFlags(flags) {
2813            var _flags$_beforeTailSta, _flags$_beforeTailSta2;
2814            return {
2815                ...flags,
2816                _beforeTailState: ((_flags$_beforeTailSta = flags._beforeTailState) == null ? void 0 : _flags$_beforeTailSta.currentMaskRef) === this.currentMask && ((_flags$_beforeTailSta2 = flags._beforeTailState) == null ? void 0 : _flags$_beforeTailSta2.currentMask) || flags._beforeTailState
2817            };
2818        }
2819        doDispatch(appended, flags, tail) {
2820            if (flags === void 0) {
2821                flags = {};
2822            }
2823            if (tail === void 0) {
2824                tail = '';
2825            }
2826            return this.dispatch(appended, this, flags, tail);
2827        }
2828        doValidate(flags) {
2829            return super.doValidate(flags) && (!this.currentMask || this.currentMask.doValidate(this.currentMaskFlags(flags)));
2830        }
2831        doPrepare(str, flags) {
2832            if (flags === void 0) {
2833                flags = {};
2834            }
2835            let [s, details] = super.doPrepare(str, flags);
2836            if (this.currentMask) {
2837                let currentDetails;
2838                [s, currentDetails] = super.doPrepare(s, this.currentMaskFlags(flags));
2839                details = details.aggregate(currentDetails);
2840            }
2841            return [s, details];
2842        }
2843        doPrepareChar(str, flags) {
2844            if (flags === void 0) {
2845                flags = {};
2846            }
2847            let [s, details] = super.doPrepareChar(str, flags);
2848            if (this.currentMask) {
2849                let currentDetails;
2850                [s, currentDetails] = super.doPrepareChar(s, this.currentMaskFlags(flags));
2851                details = details.aggregate(currentDetails);
2852            }
2853            return [s, details];
2854        }
2855        reset() {
2856            var _this$currentMask;
2857            (_this$currentMask = this.currentMask) == null || _this$currentMask.reset();
2858            this.compiledMasks.forEach(m => m.reset());
2859        }
2860        get value() {
2861            return this.exposeMask ? this.exposeMask.value : this.currentMask ? this.currentMask.value : '';
2862        }
2863        set value(value) {
2864            if (this.exposeMask) {
2865                this.exposeMask.value = value;
2866                this.currentMask = this.exposeMask;
2867                this._applyDispatch();
2868            } else super.value = value;
2869        }
2870        get unmaskedValue() {
2871            return this.exposeMask ? this.exposeMask.unmaskedValue : this.currentMask ? this.currentMask.unmaskedValue : '';
2872        }
2873        set unmaskedValue(unmaskedValue) {
2874            if (this.exposeMask) {
2875                this.exposeMask.unmaskedValue = unmaskedValue;
2876                this.currentMask = this.exposeMask;
2877                this._applyDispatch();
2878            } else super.unmaskedValue = unmaskedValue;
2879        }
2880        get typedValue() {
2881            return this.exposeMask ? this.exposeMask.typedValue : this.currentMask ? this.currentMask.typedValue : '';
2882        }
2883        set typedValue(typedValue) {
2884            if (this.exposeMask) {
2885                this.exposeMask.typedValue = typedValue;
2886                this.currentMask = this.exposeMask;
2887                this._applyDispatch();
2888                return;
2889            }
2890            let unmaskedValue = String(typedValue);
2891
2892            // double check it
2893            if (this.currentMask) {
2894                this.currentMask.typedValue = typedValue;
2895                unmaskedValue = this.currentMask.unmaskedValue;
2896            }
2897            this.unmaskedValue = unmaskedValue;
2898        }
2899        get displayValue() {
2900            return this.currentMask ? this.currentMask.displayValue : '';
2901        }
2902        get isComplete() {
2903            var _this$currentMask2;
2904            return Boolean((_this$currentMask2 = this.currentMask) == null ? void 0 : _this$currentMask2.isComplete);
2905        }
2906        get isFilled() {
2907            var _this$currentMask3;
2908            return Boolean((_this$currentMask3 = this.currentMask) == null ? void 0 : _this$currentMask3.isFilled);
2909        }
2910        remove(fromPos, toPos) {
2911            const details = new ChangeDetails();
2912            if (this.currentMask) {
2913                details.aggregate(this.currentMask.remove(fromPos, toPos))
2914                    // update with dispatch
2915                    .aggregate(this._applyDispatch());
2916            }
2917            return details;
2918        }
2919        get state() {
2920            var _this$currentMask4;
2921            return {
2922                ...super.state,
2923                _rawInputValue: this.rawInputValue,
2924                compiledMasks: this.compiledMasks.map(m => m.state),
2925                currentMaskRef: this.currentMask,
2926                currentMask: (_this$currentMask4 = this.currentMask) == null ? void 0 : _this$currentMask4.state
2927            };
2928        }
2929        set state(state) {
2930            const {
2931                compiledMasks,
2932                currentMaskRef,
2933                currentMask,
2934                ...maskedState
2935            } = state;
2936            if (compiledMasks) this.compiledMasks.forEach((m, mi) => m.state = compiledMasks[mi]);
2937            if (currentMaskRef != null) {
2938                this.currentMask = currentMaskRef;
2939                this.currentMask.state = currentMask;
2940            }
2941            super.state = maskedState;
2942        }
2943        extractInput(fromPos, toPos, flags) {
2944            return this.currentMask ? this.currentMask.extractInput(fromPos, toPos, flags) : '';
2945        }
2946        extractTail(fromPos, toPos) {
2947            return this.currentMask ? this.currentMask.extractTail(fromPos, toPos) : super.extractTail(fromPos, toPos);
2948        }
2949        doCommit() {
2950            if (this.currentMask) this.currentMask.doCommit();
2951            super.doCommit();
2952        }
2953        nearestInputPos(cursorPos, direction) {
2954            return this.currentMask ? this.currentMask.nearestInputPos(cursorPos, direction) : super.nearestInputPos(cursorPos, direction);
2955        }
2956        get overwrite() {
2957            return this.currentMask ? this.currentMask.overwrite : this._overwrite;
2958        }
2959        set overwrite(overwrite) {
2960            this._overwrite = overwrite;
2961        }
2962        get eager() {
2963            return this.currentMask ? this.currentMask.eager : this._eager;
2964        }
2965        set eager(eager) {
2966            this._eager = eager;
2967        }
2968        get skipInvalid() {
2969            return this.currentMask ? this.currentMask.skipInvalid : this._skipInvalid;
2970        }
2971        set skipInvalid(skipInvalid) {
2972            this._skipInvalid = skipInvalid;
2973        }
2974        get autofix() {
2975            return this.currentMask ? this.currentMask.autofix : this._autofix;
2976        }
2977        set autofix(autofix) {
2978            this._autofix = autofix;
2979        }
2980        maskEquals(mask) {
2981            return Array.isArray(mask) ? this.compiledMasks.every((m, mi) => {
2982                if (!mask[mi]) return;
2983                const {
2984                    mask: oldMask,
2985                    ...restOpts
2986                } = mask[mi];
2987                return objectIncludes(m, restOpts) && m.maskEquals(oldMask);
2988            }) : super.maskEquals(mask);
2989        }
2990        typedValueEquals(value) {
2991            var _this$currentMask5;
2992            return Boolean((_this$currentMask5 = this.currentMask) == null ? void 0 : _this$currentMask5.typedValueEquals(value));
2993        }
2994    }
2995    /** Currently chosen mask */
2996    /** Currently chosen mask */
2997    /** Compliled {@link Masked} options */
2998    /** Chooses {@link Masked} depending on input value */
2999    MaskedDynamic.DEFAULTS = {
3000        ...Masked.DEFAULTS,
3001        dispatch: (appended, masked, flags, tail) => {
3002            if (!masked.compiledMasks.length) return;
3003            const inputValue = masked.rawInputValue;
3004
3005            // simulate input
3006            const inputs = masked.compiledMasks.map((m, index) => {
3007                const isCurrent = masked.currentMask === m;
3008                const startInputPos = isCurrent ? m.displayValue.length : m.nearestInputPos(m.displayValue.length, DIRECTION.FORCE_LEFT);
3009                if (m.rawInputValue !== inputValue) {
3010                    m.reset();
3011                    m.append(inputValue, {
3012                        raw: true
3013                    });
3014                } else if (!isCurrent) {
3015                    m.remove(startInputPos);
3016                }
3017                m.append(appended, masked.currentMaskFlags(flags));
3018                m.appendTail(tail);
3019                return {
3020                    index,
3021                    weight: m.rawInputValue.length,
3022                    totalInputPositions: m.totalInputPositions(0, Math.max(startInputPos, m.nearestInputPos(m.displayValue.length, DIRECTION.FORCE_LEFT)))
3023                };
3024            });
3025
3026            // pop masks with longer values first
3027            inputs.sort((i1, i2) => i2.weight - i1.weight || i2.totalInputPositions - i1.totalInputPositions);
3028            return masked.compiledMasks[inputs[0].index];
3029        }
3030    };
3031    IMask.MaskedDynamic = MaskedDynamic;
3032
3033    /** Pattern which validates enum values */
3034    class MaskedEnum extends MaskedPattern {
3035        constructor(opts) {
3036            super({
3037                ...MaskedEnum.DEFAULTS,
3038                ...opts
3039            }); // mask will be created in _update
3040        }
3041        updateOptions(opts) {
3042            super.updateOptions(opts);
3043        }
3044        _update(opts) {
3045            const {
3046                enum: enum_,
3047                ...eopts
3048            } = opts;
3049            if (enum_) {
3050                const lengths = enum_.map(e => e.length);
3051                const requiredLength = Math.min(...lengths);
3052                const optionalLength = Math.max(...lengths) - requiredLength;
3053                eopts.mask = '*'.repeat(requiredLength);
3054                if (optionalLength) eopts.mask += '[' + '*'.repeat(optionalLength) + ']';
3055                this.enum = enum_;
3056            }
3057            super._update(eopts);
3058        }
3059        _appendCharRaw(ch, flags) {
3060            if (flags === void 0) {
3061                flags = {};
3062            }
3063            const matchFrom = Math.min(this.nearestInputPos(0, DIRECTION.FORCE_RIGHT), this.value.length);
3064            const matches = this.enum.filter(e => this.matchValue(e, this.unmaskedValue + ch, matchFrom));
3065            if (matches.length) {
3066                if (matches.length === 1) {
3067                    this._forEachBlocksInRange(0, this.value.length, (b, bi) => {
3068                        const mch = matches[0][bi];
3069                        if (bi >= this.value.length || mch === b.value) return;
3070                        b.reset();
3071                        b._appendChar(mch, flags);
3072                    });
3073                }
3074                const d = super._appendCharRaw(matches[0][this.value.length], flags);
3075                if (matches.length === 1) {
3076                    matches[0].slice(this.unmaskedValue.length).split('').forEach(mch => d.aggregate(super._appendCharRaw(mch)));
3077                }
3078                return d;
3079            }
3080            return new ChangeDetails({
3081                skip: !this.isComplete
3082            });
3083        }
3084        extractTail(fromPos, toPos) {
3085            if (fromPos === void 0) {
3086                fromPos = 0;
3087            }
3088            if (toPos === void 0) {
3089                toPos = this.displayValue.length;
3090            }
3091            // just drop tail
3092            return new ContinuousTailDetails('', fromPos);
3093        }
3094        remove(fromPos, toPos) {
3095            if (fromPos === void 0) {
3096                fromPos = 0;
3097            }
3098            if (toPos === void 0) {
3099                toPos = this.displayValue.length;
3100            }
3101            if (fromPos === toPos) return new ChangeDetails();
3102            const matchFrom = Math.min(super.nearestInputPos(0, DIRECTION.FORCE_RIGHT), this.value.length);
3103            let pos;
3104            for (pos = fromPos; pos >= 0; --pos) {
3105                const matches = this.enum.filter(e => this.matchValue(e, this.value.slice(matchFrom, pos), matchFrom));
3106                if (matches.length > 1) break;
3107            }
3108            const details = super.remove(pos, toPos);
3109            details.tailShift += pos - fromPos;
3110            return details;
3111        }
3112        get isComplete() {
3113            return this.enum.indexOf(this.value) >= 0;
3114        }
3115    }
3116    /** Match enum value */
3117    MaskedEnum.DEFAULTS = {
3118        ...MaskedPattern.DEFAULTS,
3119        matchValue: (estr, istr, matchFrom) => estr.indexOf(istr, matchFrom) === matchFrom
3120    };
3121    IMask.MaskedEnum = MaskedEnum;
3122
3123    /** Masking by custom Function */
3124    class MaskedFunction extends Masked {
3125        /** */
3126
3127        /** Enable characters overwriting */
3128
3129        /** */
3130
3131        /** */
3132
3133        /** */
3134
3135        updateOptions(opts) {
3136            super.updateOptions(opts);
3137        }
3138        _update(opts) {
3139            super._update({
3140                ...opts,
3141                validate: opts.mask
3142            });
3143        }
3144    }
3145    IMask.MaskedFunction = MaskedFunction;
3146
3147    var _MaskedNumber;
3148    /** Number mask */
3149    class MaskedNumber extends Masked {
3150        /** Single char */
3151
3152        /** Single char */
3153
3154        /** Array of single chars */
3155
3156        /** */
3157
3158        /** */
3159
3160        /** Digits after point */
3161
3162        /** Flag to remove leading and trailing zeros in the end of editing */
3163
3164        /** Flag to pad trailing zeros after point in the end of editing */
3165
3166        /** Enable characters overwriting */
3167
3168        /** */
3169
3170        /** */
3171
3172        /** */
3173
3174        /** Format typed value to string */
3175
3176        /** Parse string to get typed value */
3177
3178        constructor(opts) {
3179            super({
3180                ...MaskedNumber.DEFAULTS,
3181                ...opts
3182            });
3183        }
3184        updateOptions(opts) {
3185            super.updateOptions(opts);
3186        }
3187        _update(opts) {
3188            super._update(opts);
3189            this._updateRegExps();
3190        }
3191        _updateRegExps() {
3192            const start = '^' + (this.allowNegative ? '[+|\\-]?' : '');
3193            const mid = '\\d*';
3194            const end = (this.scale ? "(" + escapeRegExp(this.radix) + "\\d{0," + this.scale + "})?" : '') + '$';
3195            this._numberRegExp = new RegExp(start + mid + end);
3196            this._mapToRadixRegExp = new RegExp("[" + this.mapToRadix.map(escapeRegExp).join('') + "]", 'g');
3197            this._thousandsSeparatorRegExp = new RegExp(escapeRegExp(this.thousandsSeparator), 'g');
3198        }
3199        _removeThousandsSeparators(value) {
3200            return value.replace(this._thousandsSeparatorRegExp, '');
3201        }
3202        _insertThousandsSeparators(value) {
3203            // https://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
3204            const parts = value.split(this.radix);
3205            parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, this.thousandsSeparator);
3206            return parts.join(this.radix);
3207        }
3208        doPrepareChar(ch, flags) {
3209            if (flags === void 0) {
3210                flags = {};
3211            }
3212            const [prepCh, details] = super.doPrepareChar(this._removeThousandsSeparators(this.scale && this.mapToRadix.length && (
3213                /*
3214        radix should be mapped when
3215        1) input is done from keyboard = flags.input && flags.raw
3216        2) unmasked value is set = !flags.input && !flags.raw
3217        and should not be mapped when
3218        1) value is set = flags.input && !flags.raw
3219        2) raw value is set = !flags.input && flags.raw
3220      */
3221                flags.input && flags.raw || !flags.input && !flags.raw) ? ch.replace(this._mapToRadixRegExp, this.radix) : ch), flags);
3222            if (ch && !prepCh) details.skip = true;
3223            if (prepCh && !this.allowPositive && !this.value && prepCh !== '-') details.aggregate(this._appendChar('-'));
3224            return [prepCh, details];
3225        }
3226        _separatorsCount(to, extendOnSeparators) {
3227            if (extendOnSeparators === void 0) {
3228                extendOnSeparators = false;
3229            }
3230            let count = 0;
3231            for (let pos = 0; pos < to; ++pos) {
3232                if (this._value.indexOf(this.thousandsSeparator, pos) === pos) {
3233                    ++count;
3234                    if (extendOnSeparators) to += this.thousandsSeparator.length;
3235                }
3236            }
3237            return count;
3238        }
3239        _separatorsCountFromSlice(slice) {
3240            if (slice === void 0) {
3241                slice = this._value;
3242            }
3243            return this._separatorsCount(this._removeThousandsSeparators(slice).length, true);
3244        }
3245        extractInput(fromPos, toPos, flags) {
3246            if (fromPos === void 0) {
3247                fromPos = 0;
3248            }
3249            if (toPos === void 0) {
3250                toPos = this.displayValue.length;
3251            }
3252            [fromPos, toPos] = this._adjustRangeWithSeparators(fromPos, toPos);
3253            return this._removeThousandsSeparators(super.extractInput(fromPos, toPos, flags));
3254        }
3255        _appendCharRaw(ch, flags) {
3256            if (flags === void 0) {
3257                flags = {};
3258            }
3259            const prevBeforeTailValue = flags.tail && flags._beforeTailState ? flags._beforeTailState._value : this._value;
3260            const prevBeforeTailSeparatorsCount = this._separatorsCountFromSlice(prevBeforeTailValue);
3261            this._value = this._removeThousandsSeparators(this.value);
3262            const oldValue = this._value;
3263            this._value += ch;
3264            const num = this.number;
3265            let accepted = !isNaN(num);
3266            let skip = false;
3267            if (accepted) {
3268                let fixedNum;
3269                if (this.min != null && this.min < 0 && this.number < this.min) fixedNum = this.min;
3270                if (this.max != null && this.max > 0 && this.number > this.max) fixedNum = this.max;
3271                if (fixedNum != null) {
3272                    if (this.autofix) {
3273                        this._value = this.format(fixedNum, this).replace(MaskedNumber.UNMASKED_RADIX, this.radix);
3274                        skip || (skip = oldValue === this._value && !flags.tail); // if not changed on tail it's still ok to proceed
3275                    } else {
3276                        accepted = false;
3277                    }
3278                }
3279                accepted && (accepted = Boolean(this._value.match(this._numberRegExp)));
3280            }
3281            let appendDetails;
3282            if (!accepted) {
3283                this._value = oldValue;
3284                appendDetails = new ChangeDetails();
3285            } else {
3286                appendDetails = new ChangeDetails({
3287                    inserted: this._value.slice(oldValue.length),
3288                    rawInserted: skip ? '' : ch,
3289                    skip
3290                });
3291            }
3292            this._value = this._insertThousandsSeparators(this._value);
3293            const beforeTailValue = flags.tail && flags._beforeTailState ? flags._beforeTailState._value : this._value;
3294            const beforeTailSeparatorsCount = this._separatorsCountFromSlice(beforeTailValue);
3295            appendDetails.tailShift += (beforeTailSeparatorsCount - prevBeforeTailSeparatorsCount) * this.thousandsSeparator.length;
3296            return appendDetails;
3297        }
3298        _findSeparatorAround(pos) {
3299            if (this.thousandsSeparator) {
3300                const searchFrom = pos - this.thousandsSeparator.length + 1;
3301                const separatorPos = this.value.indexOf(this.thousandsSeparator, searchFrom);
3302                if (separatorPos <= pos) return separatorPos;
3303            }
3304            return -1;
3305        }
3306        _adjustRangeWithSeparators(from, to) {
3307            const separatorAroundFromPos = this._findSeparatorAround(from);
3308            if (separatorAroundFromPos >= 0) from = separatorAroundFromPos;
3309            const separatorAroundToPos = this._findSeparatorAround(to);
3310            if (separatorAroundToPos >= 0) to = separatorAroundToPos + this.thousandsSeparator.length;
3311            return [from, to];
3312        }
3313        remove(fromPos, toPos) {
3314            if (fromPos === void 0) {
3315                fromPos = 0;
3316            }
3317            if (toPos === void 0) {
3318                toPos = this.displayValue.length;
3319            }
3320            [fromPos, toPos] = this._adjustRangeWithSeparators(fromPos, toPos);
3321            const valueBeforePos = this.value.slice(0, fromPos);
3322            const valueAfterPos = this.value.slice(toPos);
3323            const prevBeforeTailSeparatorsCount = this._separatorsCount(valueBeforePos.length);
3324            this._value = this._insertThousandsSeparators(this._removeThousandsSeparators(valueBeforePos + valueAfterPos));
3325            const beforeTailSeparatorsCount = this._separatorsCountFromSlice(valueBeforePos);
3326            return new ChangeDetails({
3327                tailShift: (beforeTailSeparatorsCount - prevBeforeTailSeparatorsCount) * this.thousandsSeparator.length
3328            });
3329        }
3330        nearestInputPos(cursorPos, direction) {
3331            if (!this.thousandsSeparator) return cursorPos;
3332            switch (direction) {
3333                case DIRECTION.NONE:
3334                case DIRECTION.LEFT:
3335                case DIRECTION.FORCE_LEFT:
3336                {
3337                    const separatorAtLeftPos = this._findSeparatorAround(cursorPos - 1);
3338                    if (separatorAtLeftPos >= 0) {
3339                        const separatorAtLeftEndPos = separatorAtLeftPos + this.thousandsSeparator.length;
3340                        if (cursorPos < separatorAtLeftEndPos || this.value.length <= separatorAtLeftEndPos || direction === DIRECTION.FORCE_LEFT) {
3341                            return separatorAtLeftPos;
3342                        }
3343                    }
3344                    break;
3345                }
3346                case DIRECTION.RIGHT:
3347                case DIRECTION.FORCE_RIGHT:
3348                {
3349                    const separatorAtRightPos = this._findSeparatorAround(cursorPos);
3350                    if (separatorAtRightPos >= 0) {
3351                        return separatorAtRightPos + this.thousandsSeparator.length;
3352                    }
3353                }
3354            }
3355            return cursorPos;
3356        }
3357        doCommit() {
3358            if (this.value) {
3359                const number = this.number;
3360                let validnum = number;
3361
3362                // check bounds
3363                if (this.min != null) validnum = Math.max(validnum, this.min);
3364                if (this.max != null) validnum = Math.min(validnum, this.max);
3365                if (validnum !== number) this.unmaskedValue = this.format(validnum, this);
3366                let formatted = this.value;
3367                if (this.normalizeZeros) formatted = this._normalizeZeros(formatted);
3368                if (this.padFractionalZeros && this.scale > 0) formatted = this._padFractionalZeros(formatted);
3369                this._value = formatted;
3370            }
3371            super.doCommit();
3372        }
3373        _normalizeZeros(value) {
3374            const parts = this._removeThousandsSeparators(value).split(this.radix);
3375
3376            // remove leading zeros
3377            parts[0] = parts[0].replace(/^(\D*)(0*)(\d*)/, (match, sign, zeros, num) => sign + num);
3378            // add leading zero
3379            if (value.length && !/\d$/.test(parts[0])) parts[0] = parts[0] + '0';
3380            if (parts.length > 1) {
3381                parts[1] = parts[1].replace(/0*$/, ''); // remove trailing zeros
3382                if (!parts[1].length) parts.length = 1; // remove fractional
3383            }
3384            return this._insertThousandsSeparators(parts.join(this.radix));
3385        }
3386        _padFractionalZeros(value) {
3387            if (!value) return value;
3388            const parts = value.split(this.radix);
3389            if (parts.length < 2) parts.push('');
3390            parts[1] = parts[1].padEnd(this.scale, '0');
3391            return parts.join(this.radix);
3392        }
3393        doSkipInvalid(ch, flags, checkTail) {
3394            if (flags === void 0) {
3395                flags = {};
3396            }
3397            const dropFractional = this.scale === 0 && ch !== this.thousandsSeparator && (ch === this.radix || ch === MaskedNumber.UNMASKED_RADIX || this.mapToRadix.includes(ch));
3398            return super.doSkipInvalid(ch, flags, checkTail) && !dropFractional;
3399        }
3400        get unmaskedValue() {
3401            return this._removeThousandsSeparators(this._normalizeZeros(this.value)).replace(this.radix, MaskedNumber.UNMASKED_RADIX);
3402        }
3403        set unmaskedValue(unmaskedValue) {
3404            super.unmaskedValue = unmaskedValue;
3405        }
3406        get typedValue() {
3407            return this.parse(this.unmaskedValue, this);
3408        }
3409        set typedValue(n) {
3410            this.rawInputValue = this.format(n, this).replace(MaskedNumber.UNMASKED_RADIX, this.radix);
3411        }
3412
3413        /** Parsed Number */
3414        get number() {
3415            return this.typedValue;
3416        }
3417        set number(number) {
3418            this.typedValue = number;
3419        }
3420        get allowNegative() {
3421            return this.min != null && this.min < 0 || this.max != null && this.max < 0;
3422        }
3423        get allowPositive() {
3424            return this.min != null && this.min > 0 || this.max != null && this.max > 0;
3425        }
3426        typedValueEquals(value) {
3427            // handle  0 -> '' case (typed = 0 even if value = '')
3428            // for details see https://github.com/uNmAnNeR/imaskjs/issues/134
3429            return (super.typedValueEquals(value) || MaskedNumber.EMPTY_VALUES.includes(value) && MaskedNumber.EMPTY_VALUES.includes(this.typedValue)) && !(value === 0 && this.value === '');
3430        }
3431    }
3432    _MaskedNumber = MaskedNumber;
3433    MaskedNumber.UNMASKED_RADIX = '.';
3434    MaskedNumber.EMPTY_VALUES = [...Masked.EMPTY_VALUES, 0];
3435    MaskedNumber.DEFAULTS = {
3436        ...Masked.DEFAULTS,
3437        mask: Number,
3438        radix: ',',
3439        thousandsSeparator: '',
3440        mapToRadix: [_MaskedNumber.UNMASKED_RADIX],
3441        min: Number.MIN_SAFE_INTEGER,
3442        max: Number.MAX_SAFE_INTEGER,
3443        scale: 2,
3444        normalizeZeros: true,
3445        padFractionalZeros: false,
3446        parse: Number,
3447        format: n => n.toLocaleString('en-US', {
3448            useGrouping: false,
3449            maximumFractionDigits: 20
3450        })
3451    };
3452    IMask.MaskedNumber = MaskedNumber;
3453
3454    /** Mask pipe source and destination types */
3455    const PIPE_TYPE = {
3456        MASKED: 'value',
3457        UNMASKED: 'unmaskedValue',
3458        TYPED: 'typedValue'
3459    };
3460    /** Creates new pipe function depending on mask type, source and destination options */
3461    function createPipe(arg, from, to) {
3462        if (from === void 0) {
3463            from = PIPE_TYPE.MASKED;
3464        }
3465        if (to === void 0) {
3466            to = PIPE_TYPE.MASKED;
3467        }
3468        const masked = createMask(arg);
3469        return value => masked.runIsolated(m => {
3470            m[from] = value;
3471            return m[to];
3472        });
3473    }
3474
3475    /** Pipes value through mask depending on mask type, source and destination options */
3476    function pipe(value, mask, from, to) {
3477        return createPipe(mask, from, to)(value);
3478    }
3479    IMask.PIPE_TYPE = PIPE_TYPE;
3480    IMask.createPipe = createPipe;
3481    IMask.pipe = pipe;
3482
3483    /** Pattern mask */
3484    class RepeatBlock extends MaskedPattern {
3485        get repeatFrom() {
3486            var _ref;
3487            return (_ref = Array.isArray(this.repeat) ? this.repeat[0] : this.repeat === Infinity ? 0 : this.repeat) != null ? _ref : 0;
3488        }
3489        get repeatTo() {
3490            var _ref2;
3491            return (_ref2 = Array.isArray(this.repeat) ? this.repeat[1] : this.repeat) != null ? _ref2 : Infinity;
3492        }
3493        constructor(opts) {
3494            super(opts);
3495        }
3496        updateOptions(opts) {
3497            super.updateOptions(opts);
3498        }
3499        _update(opts) {
3500            var _ref3, _ref4, _this$_blocks;
3501            const {
3502                repeat,
3503                ...blockOpts
3504            } = normalizeOpts(opts); // TODO type
3505            this._blockOpts = Object.assign({}, this._blockOpts, blockOpts);
3506            const block = createMask(this._blockOpts);
3507            this.repeat = (_ref3 = (_ref4 = repeat != null ? repeat : block.repeat) != null ? _ref4 : this.repeat) != null ? _ref3 : Infinity; // TODO type
3508
3509            super._update({
3510                mask: 'm'.repeat(Math.max(this.repeatTo === Infinity && ((_this$_blocks = this._blocks) == null ? void 0 : _this$_blocks.length) || 0, this.repeatFrom)),
3511                blocks: {
3512                    m: block
3513                },
3514                eager: block.eager,
3515                overwrite: block.overwrite,
3516                skipInvalid: block.skipInvalid,
3517                lazy: block.lazy,
3518                placeholderChar: block.placeholderChar,
3519                displayChar: block.displayChar
3520            });
3521        }
3522        _allocateBlock(bi) {
3523            if (bi < this._blocks.length) return this._blocks[bi];
3524            if (this.repeatTo === Infinity || this._blocks.length < this.repeatTo) {
3525                this._blocks.push(createMask(this._blockOpts));
3526                this.mask += 'm';
3527                return this._blocks[this._blocks.length - 1];
3528            }
3529        }
3530        _appendCharRaw(ch, flags) {
3531            if (flags === void 0) {
3532                flags = {};
3533            }
3534            const details = new ChangeDetails();
3535            for (let bi = (_this$_mapPosToBlock$ = (_this$_mapPosToBlock = this._mapPosToBlock(this.displayValue.length)) == null ? void 0 : _this$_mapPosToBlock.index) != null ? _this$_mapPosToBlock$ : Math.max(this._blocks.length - 1, 0), block, allocated;
3536                // try to get a block or
3537                // try to allocate a new block if not allocated already
3538                 block = (_this$_blocks$bi = this._blocks[bi]) != null ? _this$_blocks$bi : allocated = !allocated && this._allocateBlock(bi); ++bi) {
3539                var _this$_mapPosToBlock$, _this$_mapPosToBlock, _this$_blocks$bi, _flags$_beforeTailSta;
3540                const blockDetails = block._appendChar(ch, {
3541                    ...flags,
3542                    _beforeTailState: (_flags$_beforeTailSta = flags._beforeTailState) == null || (_flags$_beforeTailSta = _flags$_beforeTailSta._blocks) == null ? void 0 : _flags$_beforeTailSta[bi]
3543                });
3544                if (blockDetails.skip && allocated) {
3545                    // remove the last allocated block and break
3546                    this._blocks.pop();
3547                    this.mask = this.mask.slice(1);
3548                    break;
3549                }
3550                details.aggregate(blockDetails);
3551                if (blockDetails.consumed) break; // go next char
3552            }
3553            return details;
3554        }
3555        _trimEmptyTail(fromPos, toPos) {
3556            var _this$_mapPosToBlock2, _this$_mapPosToBlock3;
3557            if (fromPos === void 0) {
3558                fromPos = 0;
3559            }
3560            const firstBlockIndex = Math.max(((_this$_mapPosToBlock2 = this._mapPosToBlock(fromPos)) == null ? void 0 : _this$_mapPosToBlock2.
vendor: 3,158 bytes, lines 3560-3641
3560index) || 0, this.repeatFrom, 0);
3561            let lastBlockIndex;
3562            if (toPos != null) lastBlockIndex = (_this$_mapPosToBlock3 = this._mapPosToBlock(toPos)) == null ? void 0 : _this$_mapPosToBlock3.index;
3563            if (lastBlockIndex == null) lastBlockIndex = this._blocks.length - 1;
3564            let removeCount = 0;
3565            for (let blockIndex = lastBlockIndex; firstBlockIndex <= blockIndex; --blockIndex, ++removeCount) {
3566                if (this._blocks[blockIndex].unmaskedValue) break;
3567            }
3568            if (removeCount) {
3569                this._blocks.splice(lastBlockIndex - removeCount + 1, removeCount);
3570                this.mask = this.mask.slice(removeCount);
3571            }
3572        }
3573        reset() {
3574            super.reset();
3575            this._trimEmptyTail();
3576        }
3577        remove(fromPos, toPos) {
3578            if (fromPos === void 0) {
3579                fromPos = 0;
3580            }
3581            if (toPos === void 0) {
3582                toPos = this.displayValue.length;
3583            }
3584            const removeDetails = super.remove(fromPos, toPos);
3585            this._trimEmptyTail(fromPos, toPos);
3586            return removeDetails;
3587        }
3588        totalInputPositions(fromPos, toPos) {
3589            if (fromPos === void 0) {
3590                fromPos = 0;
3591            }
3592            if (toPos == null && this.repeatTo === Infinity) return Infinity;
3593            return super.totalInputPositions(fromPos, toPos);
3594        }
3595        get state() {
3596            return super.state;
3597        }
3598        set state(state) {
3599            this._blocks.length = state._blocks.length;
3600            this.mask = this.mask.slice(0, this._blocks.length);
3601            super.state = state;
3602        }
3603    }
3604    IMask.RepeatBlock = RepeatBlock;
3605
3606    try {
3607        globalThis.IMask = IMask;
3608    } catch {}
3609
3610    exports.ChangeDetails = ChangeDetails;
3611    exports.ChunksTailDetails = ChunksTailDetails;
3612    exports.DIRECTION = DIRECTION;
3613    exports.HTMLContenteditableMaskElement = HTMLContenteditableMaskElement;
3614    exports.HTMLInputMaskElement = HTMLInputMaskElement;
3615    exports.HTMLMaskElement = HTMLMaskElement;
3616    exports.InputMask = InputMask;
3617    exports.MaskElement = MaskElement;
3618    exports.Masked = Masked;
3619    exports.MaskedDate = MaskedDate;
3620    exports.MaskedDynamic = MaskedDynamic;
3621    exports.MaskedEnum = MaskedEnum;
3622    exports.MaskedFunction = MaskedFunction;
3623    exports.MaskedNumber = MaskedNumber;
3624    exports.MaskedPattern = MaskedPattern;
3625    exports.MaskedRange = MaskedRange;
3626    exports.MaskedRegExp = MaskedRegExp;
3627    exports.PIPE_TYPE = PIPE_TYPE;
3628    exports.PatternFixedDefinition = PatternFixedDefinition;
3629    exports.PatternInputDefinition = PatternInputDefinition;
3630    exports.RepeatBlock = RepeatBlock;
3631    exports.createMask = createMask;
3632    exports.createPipe = createPipe;
3633    exports.default = IMask;
3634    exports.forceDirection = forceDirection;
3635    exports.normalizeOpts = normalizeOpts;
3636    exports.pipe = pipe;
3637
3638    Object.defineProperty(exports, '__esModule', { value: true });
3639
3640}));
3641//# sourceMappingURL=imask.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.