PageSourceSearch

https://www.amihay.com/wp-content/plugins/booking/vendors/imask/dist/imask.js?ver=10.14.6

js amihay.com collected 2026-09-24 14:11:49 UTC 124,186 bytes, 3,641 lines download raw bytes

vendor: 124,186 bytes, lines 1-3641
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>, 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);
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 */
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() {
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.index) || 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.