UNPKG

svelte-imask

Version:

IMask action and component for Svelte 3

1,635 lines (1,366 loc) 132 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.imask = {})); }(this, (function (exports) { 'use strict'; function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); } function _set(target, property, value, receiver, isStrict) { var s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } /** Checks if value is string */ function isString(str) { return typeof str === 'string' || str instanceof String; } /** Direction @prop {string} NONE @prop {string} LEFT @prop {string} FORCE_LEFT @prop {string} RIGHT @prop {string} FORCE_RIGHT */ var DIRECTION = { NONE: 'NONE', LEFT: 'LEFT', FORCE_LEFT: 'FORCE_LEFT', RIGHT: 'RIGHT', FORCE_RIGHT: 'FORCE_RIGHT' /** Direction @enum {string} */ }; /** */ function forceDirection(direction) { switch (direction) { case DIRECTION.LEFT: return DIRECTION.FORCE_LEFT; case DIRECTION.RIGHT: return DIRECTION.FORCE_RIGHT; default: return direction; } } /** Escapes regular expression control chars */ function escapeRegExp(str) { return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'); } // cloned from https://github.com/epoberezkin/fast-deep-equal with small changes function objectIncludes(b, a) { if (a === b) return true; var arrA = Array.isArray(a), arrB = Array.isArray(b), i; if (arrA && arrB) { if (a.length != b.length) return false; for (i = 0; i < a.length; i++) { if (!objectIncludes(a[i], b[i])) return false; } return true; } if (arrA != arrB) return false; if (a && b && _typeof(a) === 'object' && _typeof(b) === 'object') { var dateA = a instanceof Date, dateB = b instanceof Date; if (dateA && dateB) return a.getTime() == b.getTime(); if (dateA != dateB) return false; var regexpA = a instanceof RegExp, regexpB = b instanceof RegExp; if (regexpA && regexpB) return a.toString() == b.toString(); if (regexpA != regexpB) return false; var keys = Object.keys(a); // if (keys.length !== Object.keys(b).length) return false; for (i = 0; i < keys.length; i++) { if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; } for (i = 0; i < keys.length; i++) { if (!objectIncludes(b[keys[i]], a[keys[i]])) return false; } return true; } else if (a && b && typeof a === 'function' && typeof b === 'function') { return a.toString() === b.toString(); } return false; } /* eslint-disable no-undef */ var g = typeof window !== 'undefined' && window || typeof global !== 'undefined' && global.global === global && global || typeof self !== 'undefined' && self.self === self && self || {}; /* eslint-enable no-undef */ /** Selection range */ /** Provides details of changing input */ var ActionDetails = /*#__PURE__*/ function () { /** Current input value */ /** Current cursor position */ /** Old input value */ /** Old selection */ function ActionDetails(value, cursorPos, oldValue, oldSelection) { _classCallCheck(this, ActionDetails); this.value = value; this.cursorPos = cursorPos; this.oldValue = oldValue; this.oldSelection = oldSelection; // double check if left part was changed (autofilling, other non-standard input triggers) while (this.value.slice(0, this.startChangePos) !== this.oldValue.slice(0, this.startChangePos)) { --this.oldSelection.start; } } /** Start changing position @readonly */ _createClass(ActionDetails, [{ key: "startChangePos", get: function get() { return Math.min(this.cursorPos, this.oldSelection.start); } /** Inserted symbols count @readonly */ }, { key: "insertedCount", get: function get() { return this.cursorPos - this.startChangePos; } /** Inserted symbols @readonly */ }, { key: "inserted", get: function get() { return this.value.substr(this.startChangePos, this.insertedCount); } /** Removed symbols count @readonly */ }, { key: "removedCount", get: function get() { // Math.max for opposite operation return Math.max(this.oldSelection.end - this.startChangePos || // for Delete this.oldValue.length - this.value.length, 0); } /** Removed symbols @readonly */ }, { key: "removed", get: function get() { return this.oldValue.substr(this.startChangePos, this.removedCount); } /** Unchanged head symbols @readonly */ }, { key: "head", get: function get() { return this.value.substring(0, this.startChangePos); } /** Unchanged tail symbols @readonly */ }, { key: "tail", get: function get() { return this.value.substring(this.startChangePos + this.insertedCount); } /** Remove direction @readonly */ }, { key: "removeDirection", get: function get() { if (!this.removedCount || this.insertedCount) return DIRECTION.NONE; // align right if delete at right or if range removed (event with backspace) return this.oldSelection.end === this.cursorPos || this.oldSelection.start === this.cursorPos ? DIRECTION.RIGHT : DIRECTION.LEFT; } }]); return ActionDetails; }(); /** Provides details of changing model value @param {Object} [details] @param {string} [details.inserted] - Inserted symbols @param {boolean} [details.skip] - Can skip chars @param {number} [details.removeCount] - Removed symbols count @param {number} [details.tailShift] - Additional offset if any changes occurred before tail */ var ChangeDetails = /*#__PURE__*/ function () { /** Inserted symbols */ /** Can skip chars */ /** Additional offset if any changes occurred before tail */ /** Raw inserted is used by dynamic mask */ function ChangeDetails(details) { _classCallCheck(this, ChangeDetails); Object.assign(this, { inserted: '', rawInserted: '', skip: false, tailShift: 0 }, details); } /** Aggregate changes @returns {ChangeDetails} `this` */ _createClass(ChangeDetails, [{ key: "aggregate", value: function aggregate(details) { this.rawInserted += details.rawInserted; this.skip = this.skip || details.skip; this.inserted += details.inserted; this.tailShift += details.tailShift; return this; } /** Total offset considering all changes */ }, { key: "offset", get: function get() { return this.tailShift + this.inserted.length; } }]); return ChangeDetails; }(); /** Provides details of continuous extracted tail */ var ContinuousTailDetails = /*#__PURE__*/ function () { /** Tail value as string */ /** Tail start position */ /** Start position */ function ContinuousTailDetails() { var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var stop = arguments.length > 2 ? arguments[2] : undefined; _classCallCheck(this, ContinuousTailDetails); this.value = value; this.from = from; this.stop = stop; } _createClass(ContinuousTailDetails, [{ key: "toString", value: function toString() { return this.value; } }, { key: "extend", value: function extend(tail) { this.value += String(tail); } }, { key: "appendTo", value: function appendTo(masked) { return masked.append(this.toString(), { tail: true }).aggregate(masked._appendPlaceholder()); } }, { key: "shiftBefore", value: function shiftBefore(pos) { if (this.from >= pos || !this.value.length) return ''; var shiftChar = this.value[0]; this.value = this.value.slice(1); return shiftChar; } }, { key: "state", get: function get() { return { value: this.value, from: this.from, stop: this.stop }; }, set: function set(state) { Object.assign(this, state); } }]); return ContinuousTailDetails; }(); /** Provides common masking stuff */ var Masked = /*#__PURE__*/ function () { // $Shape<MaskedOptions>; TODO after fix https://github.com/facebook/flow/issues/4773 /** @type {Mask} */ /** */ // $FlowFixMe no ideas /** Transforms value before mask processing */ /** Validates if value is acceptable */ /** Does additional processing in the end of editing */ /** Enable characters overwriting */ /** */ function Masked(opts) { _classCallCheck(this, Masked); this._value = ''; this._update(opts); this.isInitialized = true; } /** Sets and applies new options */ _createClass(Masked, [{ key: "updateOptions", value: function updateOptions(opts) { if (!Object.keys(opts).length) return; this.withValueRefresh(this._update.bind(this, opts)); } /** Sets new options @protected */ }, { key: "_update", value: function _update(opts) { Object.assign(this, opts); } /** Mask state */ }, { key: "reset", /** Resets value */ value: function reset() { this._value = ''; } /** */ }, { key: "resolve", /** Resolve new value */ value: function resolve(value) { this.reset(); this.append(value, { input: true }, ''); this.doCommit(); return this.value; } /** */ }, { key: "nearestInputPos", /** Finds nearest input position in direction */ value: function nearestInputPos(cursorPos, direction) { return cursorPos; } /** Extracts value in range considering flags */ }, { key: "extractInput", value: function extractInput() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; return this.value.slice(fromPos, toPos); } /** Extracts tail in range */ }, { key: "extractTail", value: function extractTail() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; return new ContinuousTailDetails(this.extractInput(fromPos, toPos), fromPos); } /** Appends tail */ // $FlowFixMe no ideas }, { key: "appendTail", value: function appendTail(tail) { if (isString(tail)) tail = new ContinuousTailDetails(String(tail)); return tail.appendTo(this); } /** Appends char */ }, { key: "_appendCharRaw", value: function _appendCharRaw(ch) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; ch = this.doPrepare(ch, flags); if (!ch) return new ChangeDetails(); this._value += ch; return new ChangeDetails({ inserted: ch, rawInserted: ch }); } /** Appends char */ }, { key: "_appendChar", value: function _appendChar(ch) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var checkTail = arguments.length > 2 ? arguments[2] : undefined; var consistentState = this.state; var details = this._appendCharRaw(ch, flags); if (details.inserted) { var consistentTail; var appended = this.doValidate(flags) !== false; if (appended && checkTail != null) { // validation ok, check tail var beforeTailState = this.state; if (this.overwrite) { consistentTail = checkTail.state; checkTail.shiftBefore(this.value.length); } var tailDetails = this.appendTail(checkTail); appended = tailDetails.rawInserted === checkTail.toString(); // if ok, rollback state after tail if (appended && tailDetails.inserted) this.state = beforeTailState; } // revert all if something went wrong if (!appended) { details.rawInserted = details.inserted = ''; this.state = consistentState; if (checkTail && consistentTail) checkTail.state = consistentTail; } } return details; } /** Appends optional placeholder at end */ }, { key: "_appendPlaceholder", value: function _appendPlaceholder() { return new ChangeDetails(); } /** Appends symbols considering flags */ // $FlowFixMe no ideas }, { key: "append", value: function append(str, flags, tail) { if (!isString(str)) throw new Error('value should be string'); var details = new ChangeDetails(); var checkTail = isString(tail) ? new ContinuousTailDetails(String(tail)) : tail; if (flags.tail) flags._beforeTailState = this.state; for (var ci = 0; ci < str.length; ++ci) { details.aggregate(this._appendChar(str[ci], flags, checkTail)); } // append tail but aggregate only tailShift if (checkTail != null) { details.tailShift += this.appendTail(checkTail).tailShift; // TODO it's a good idea to clear state after appending ends // but it causes bugs when one append calls another (when dynamic dispatch set rawInputValue) // this._resetBeforeTailState(); } return details; } /** */ }, { key: "remove", value: function remove() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; this._value = this.value.slice(0, fromPos) + this.value.slice(toPos); return new ChangeDetails(); } /** Calls function and reapplies current value */ }, { key: "withValueRefresh", value: function withValueRefresh(fn) { if (this._refreshing || !this.isInitialized) return fn(); this._refreshing = true; var unmasked = this.unmaskedValue; var value = this.value; var ret = fn(); // try to update with raw value first to keep fixed chars if (this.resolve(value) !== value) { // or fallback to unmasked this.unmaskedValue = unmasked; } delete this._refreshing; return ret; } /** Prepares string before mask processing @protected */ }, { key: "doPrepare", value: function doPrepare(str) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return this.prepare ? this.prepare(str, this, flags) : str; } /** Validates if value is acceptable @protected */ }, { key: "doValidate", value: function doValidate(flags) { return (!this.validate || this.validate(this.value, this, flags)) && (!this.parent || this.parent.doValidate(flags)); } /** Does additional processing in the end of editing @protected */ }, { key: "doCommit", value: function doCommit() { if (this.commit) this.commit(this.value, this); } /** */ }, { key: "splice", value: function splice(start, deleteCount, inserted, removeDirection) { var tailPos = start + deleteCount; var tail = this.extractTail(tailPos); var startChangePos = this.nearestInputPos(start, removeDirection); var changeDetails = new ChangeDetails({ tailShift: startChangePos - start // adjust tailShift if start was aligned }).aggregate(this.remove(startChangePos)).aggregate(this.append(inserted, { input: true }, tail)); return changeDetails; } }, { key: "state", get: function get() { return { _value: this.value }; }, set: function set(state) { this._value = state._value; } }, { key: "value", get: function get() { return this._value; }, set: function set(value) { this.resolve(value); } }, { key: "unmaskedValue", get: function get() { return this.value; }, set: function set(value) { this.reset(); this.append(value, {}, ''); this.doCommit(); } /** */ }, { key: "typedValue", get: function get() { return this.unmaskedValue; }, set: function set(value) { this.unmaskedValue = value; } /** Value that includes raw user input */ }, { key: "rawInputValue", get: function get() { return this.extractInput(0, this.value.length, { raw: true }); }, set: function set(value) { this.reset(); this.append(value, { raw: true }, ''); this.doCommit(); } /** */ }, { key: "isComplete", get: function get() { return true; } }]); return Masked; }(); /** Get Masked class by mask type */ function maskedClass(mask) { if (mask == null) { throw new Error('mask property should be defined'); } if (mask instanceof RegExp) return g.IMask.MaskedRegExp; if (isString(mask)) return g.IMask.MaskedPattern; if (mask instanceof Date || mask === Date) return g.IMask.MaskedDate; if (mask instanceof Number || typeof mask === 'number' || mask === Number) return g.IMask.MaskedNumber; if (Array.isArray(mask) || mask === Array) return g.IMask.MaskedDynamic; // $FlowFixMe if (mask.prototype instanceof g.IMask.Masked) return mask; // $FlowFixMe if (mask instanceof Function) return g.IMask.MaskedFunction; console.warn('Mask not found for mask', mask); // eslint-disable-line no-console return g.IMask.Masked; } /** Creates new {@link Masked} depending on mask type */ function createMask(opts) { opts = Object.assign({}, opts); var mask = opts.mask; if (mask instanceof g.IMask.Masked) return mask; var MaskedClass = maskedClass(mask); return new MaskedClass(opts); } var DEFAULT_INPUT_DEFINITIONS = { '0': /\d/, '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]/, // http://stackoverflow.com/a/22075070 '*': /./ }; /** */ var PatternInputDefinition = /*#__PURE__*/ function () { /** */ /** */ /** */ /** */ /** */ /** */ function PatternInputDefinition(opts) { _classCallCheck(this, PatternInputDefinition); var mask = opts.mask, blockOpts = _objectWithoutProperties(opts, ["mask"]); this.masked = createMask({ mask: mask }); Object.assign(this, blockOpts); } _createClass(PatternInputDefinition, [{ key: "reset", value: function reset() { this._isFilled = false; this.masked.reset(); } }, { key: "remove", value: function remove() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; if (fromPos === 0 && toPos >= 1) { this._isFilled = false; return this.masked.remove(fromPos, toPos); } return new ChangeDetails(); } }, { key: "_appendChar", value: function _appendChar(str) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (this._isFilled) return new ChangeDetails(); var state = this.masked.state; // simulate input var details = this.masked._appendChar(str, flags); if (details.inserted && this.doValidate(flags) === false) { details.inserted = details.rawInserted = ''; this.masked.state = state; } if (!details.inserted && !this.isOptional && !this.lazy && !flags.input) { details.inserted = this.placeholderChar; } details.skip = !details.inserted && !this.isOptional; this._isFilled = Boolean(details.inserted); return details; } }, { key: "append", value: function append() { var _this$masked; return (_this$masked = this.masked).append.apply(_this$masked, arguments); } }, { key: "_appendPlaceholder", value: function _appendPlaceholder() { var details = new ChangeDetails(); if (this._isFilled || this.isOptional) return details; this._isFilled = true; details.inserted = this.placeholderChar; return details; } }, { key: "extractTail", value: function extractTail() { var _this$masked2; return (_this$masked2 = this.masked).extractTail.apply(_this$masked2, arguments); } }, { key: "appendTail", value: function appendTail() { var _this$masked3; return (_this$masked3 = this.masked).appendTail.apply(_this$masked3, arguments); } }, { key: "extractInput", value: function extractInput() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; var flags = arguments.length > 2 ? arguments[2] : undefined; return this.masked.extractInput(fromPos, toPos, flags); } }, { key: "nearestInputPos", value: function nearestInputPos(cursorPos) { var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DIRECTION.NONE; var minPos = 0; var maxPos = this.value.length; var boundPos = Math.min(Math.max(cursorPos, minPos), maxPos); switch (direction) { case DIRECTION.LEFT: case DIRECTION.FORCE_LEFT: return this.isComplete ? boundPos : minPos; case DIRECTION.RIGHT: case DIRECTION.FORCE_RIGHT: return this.isComplete ? boundPos : maxPos; case DIRECTION.NONE: default: return boundPos; } } }, { key: "doValidate", value: function doValidate() { var _this$masked4, _this$parent; return (_this$masked4 = this.masked).doValidate.apply(_this$masked4, arguments) && (!this.parent || (_this$parent = this.parent).doValidate.apply(_this$parent, arguments)); } }, { key: "doCommit", value: function doCommit() { this.masked.doCommit(); } }, { key: "value", get: function get() { return this.masked.value || (this._isFilled && !this.isOptional ? this.placeholderChar : ''); } }, { key: "unmaskedValue", get: function get() { return this.masked.unmaskedValue; } }, { key: "isComplete", get: function get() { return Boolean(this.masked.value) || this.isOptional; } }, { key: "state", get: function get() { return { masked: this.masked.state, _isFilled: this._isFilled }; }, set: function set(state) { this.masked.state = state.masked; this._isFilled = state._isFilled; } }]); return PatternInputDefinition; }(); var PatternFixedDefinition = /*#__PURE__*/ function () { /** */ /** */ /** */ /** */ function PatternFixedDefinition(opts) { _classCallCheck(this, PatternFixedDefinition); Object.assign(this, opts); this._value = ''; } _createClass(PatternFixedDefinition, [{ key: "reset", value: function reset() { this._isRawInput = false; this._value = ''; } }, { key: "remove", value: function remove() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._value.length; this._value = this._value.slice(0, fromPos) + this._value.slice(toPos); if (!this._value) this._isRawInput = false; return new ChangeDetails(); } }, { key: "nearestInputPos", value: function nearestInputPos(cursorPos) { var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DIRECTION.NONE; var minPos = 0; var maxPos = this._value.length; switch (direction) { case DIRECTION.LEFT: case DIRECTION.FORCE_LEFT: return minPos; case DIRECTION.NONE: case DIRECTION.RIGHT: case DIRECTION.FORCE_RIGHT: default: return maxPos; } } }, { key: "extractInput", value: function extractInput() { var fromPos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._value.length; var flags = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return flags.raw && this._isRawInput && this._value.slice(fromPos, toPos) || ''; } }, { key: "_appendChar", value: function _appendChar(str) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var details = new ChangeDetails(); if (this._value) return details; var appended = this.char === str[0]; var isResolved = appended && (this.isUnmasking || flags.input || flags.raw) && !flags.tail; if (isResolved) details.rawInserted = this.char; this._value = details.inserted = this.char; this._isRawInput = isResolved && (flags.raw || flags.input); return details; } }, { key: "_appendPlaceholder", value: function _appendPlaceholder() { var details = new ChangeDetails(); if (this._value) return details; this._value = details.inserted = this.char; return details; } }, { key: "extractTail", value: function extractTail() { var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; return new ContinuousTailDetails(''); } // $FlowFixMe no ideas }, { key: "appendTail", value: function appendTail(tail) { if (isString(tail)) tail = new ContinuousTailDetails(String(tail)); return tail.appendTo(this); } }, { key: "append", value: function append(str, flags, tail) { var details = this._appendChar(str, flags); if (tail != null) { details.tailShift += this.appendTail(tail).tailShift; } return details; } }, { key: "doCommit", value: function doCommit() {} }, { key: "value", get: function get() { return this._value; } }, { key: "unmaskedValue", get: function get() { return this.isUnmasking ? this.value : ''; } }, { key: "isComplete", get: function get() { return true; } }, { key: "state", get: function get() { return { _value: this._value, _isRawInput: this._isRawInput }; }, set: function set(state) { Object.assign(this, state); } }]); return PatternFixedDefinition; }(); var ChunksTailDetails = /*#__PURE__*/ function () { /** */ function ChunksTailDetails() { var chunks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; _classCallCheck(this, ChunksTailDetails); this.chunks = chunks; this.from = from; } _createClass(ChunksTailDetails, [{ key: "toString", value: function toString() { return this.chunks.map(String).join(''); } // $FlowFixMe no ideas }, { key: "extend", value: function extend(tailChunk) { if (!String(tailChunk)) return; if (isString(tailChunk)) tailChunk = new ContinuousTailDetails(String(tailChunk)); var lastChunk = this.chunks[this.chunks.length - 1]; var extendLast = lastChunk && ( // if stops are same or tail has no stop lastChunk.stop === tailChunk.stop || tailChunk.stop == null) && // if tail chunk goes just after last chunk tailChunk.from === lastChunk.from + lastChunk.toString().length; if (tailChunk instanceof ContinuousTailDetails) { // check the ability to extend previous chunk if (extendLast) { // extend previous chunk lastChunk.extend(tailChunk.toString()); } else { // append new chunk this.chunks.push(tailChunk); } } else if (tailChunk instanceof ChunksTailDetails) { if (tailChunk.stop == null) { // unwrap floating chunks to parent, keeping `from` pos var firstTailChunk; while (tailChunk.chunks.length && tailChunk.chunks[0].stop == null) { firstTailChunk = tailChunk.chunks.shift(); firstTailChunk.from += tailChunk.from; this.extend(firstTailChunk); } } // if tail chunk still has value if (tailChunk.toString()) { // if chunks contains stops, then popup stop to container tailChunk.stop = tailChunk.blockIndex; this.chunks.push(tailChunk); } } } }, { key: "appendTo", value: function appendTo(masked) { if (!(masked instanceof g.IMask.MaskedPattern)) { var tail = new ContinuousTailDetails(this.toString()); return tail.appendTo(masked); } var details = new ChangeDetails(); for (var ci = 0; ci < this.chunks.length && !details.skip; ++ci) { var chunk = this.chunks[ci]; var lastBlockIter = masked._mapPosToBlock(masked.value.length); var stop = chunk.stop; var chunkBlock = void 0; if (stop && ( // if block not found or stop is behind lastBlock !lastBlockIter || lastBlockIter.index <= stop)) { if (chunk instanceof ChunksTailDetails || // for continuous block also check if stop is exist masked._stops.indexOf(stop) >= 0) { details.aggregate(masked._appendPlaceholder(stop)); } chunkBlock = chunk instanceof ChunksTailDetails && masked._blocks[stop]; } if (chunkBlock) { var tailDetails = chunkBlock.appendTail(chunk); tailDetails.skip = false; // always ignore skip, it will be set on last details.aggregate(tailDetails); masked._value += tailDetails.inserted; // get not inserted chars var remainChars = chunk.toString().slice(tailDetails.rawInserted.length); if (remainChars) details.aggregate(masked.append(remainChars, { tail: true })); } else { details.aggregate(masked.append(chunk.toString(), { tail: true })); } } return details; } }, { key: "shiftBefore", value: function shiftBefore(pos) { if (this.from >= pos || !this.chunks.length) return ''; var chunkShiftPos = pos - this.from; var ci = 0; while (ci < this.chunks.length) { var chunk = this.chunks[ci]; var shiftChar = chunk.shiftBefore(chunkShiftPos); if (chunk.toString()) { // chunk still contains value // but not shifted - means no more available chars to shift if (!shiftChar) break; ++ci; } else { // clean if chunk has no value this.chunks.splice(ci, 1); } if (shiftChar) return shiftChar; } return ''; } }, { key: "state", get: function get() { return { chunks: this.chunks.map(function (c) { return c.state; }), from: this.from, stop: this.stop, blockIndex: this.blockIndex }; }, set: function set(state) { var chunks = state.chunks, props = _objectWithoutProperties(state, ["chunks"]); Object.assign(this, props); this.chunks = chunks.map(function (cstate) { var chunk = "chunks" in cstate ? new ChunksTailDetails() : new ContinuousTailDetails(); // $FlowFixMe already checked above chunk.state = cstate; return chunk; }); } }]); return ChunksTailDetails; }(); /** Pattern mask @param {Object} opts @param {Object} opts.blocks @param {Object} opts.definitions @param {string} opts.placeholderChar @param {boolean} opts.lazy */ var MaskedPattern = /*#__PURE__*/ function (_Masked) { _inherits(MaskedPattern, _Masked); /** */ /** */ /** Single char for empty input */ /** Show placeholder only when needed */ function MaskedPattern() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, MaskedPattern); // TODO type $Shape<MaskedPatternOptions>={} does not work opts.definitions = Object.assign({}, DEFAULT_INPUT_DEFINITIONS, opts.definitions); return _possibleConstructorReturn(this, _getPrototypeOf(MaskedPattern).call(this, Object.assign({}, MaskedPattern.DEFAULTS, {}, opts))); } /** @override @param {Object} opts */ _createClass(MaskedPattern, [{ key: "_update", value: function _update() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; opts.definitions = Object.assign({}, this.definitions, opts.definitions); _get(_getPrototypeOf(MaskedPattern.prototype), "_update", this).call(this, opts); this._rebuildMask(); } /** */ }, { key: "_rebuildMask", value: function _rebuildMask() { var _this = this; var defs = this.definitions; this._blocks = []; this._stops = []; this._maskedBlocks = {}; var pattern = this.mask; if (!pattern || !defs) return; var unmaskingBlock = false; var optionalBlock = false; for (var i = 0; i < pattern.length; ++i) { if (this.blocks) { var _ret = function () { var p = pattern.slice(i); var bNames = Object.keys(_this.blocks).filter(function (bName) { return p.indexOf(bName) === 0; }); // order by key length bNames.sort(function (a, b) { return b.length - a.length; }); // use block name with max length var bName = bNames[0]; if (bName) { var maskedBlock = createMask(Object.assign({ parent: _this, lazy: _this.lazy, placeholderChar: _this.placeholderChar, overwrite: _this.overwrite }, _this.blocks[bName])); if (maskedBlock) { _this._blocks.push(maskedBlock); // store block index if (!_this._maskedBlocks[bName]) _this._maskedBlocks[bName] = []; _this._maskedBlocks[bName].push(_this._blocks.length - 1); } i += bName.length - 1; return "continue"; } }(); if (_ret === "continue") continue; } var char = pattern[i]; var _isInput = char in defs; if (char === MaskedPattern.STOP_CHAR) { this._stops.push(this._blocks.length); continue; } if (char === '{' || char === '}') { unmaskingBlock = !unmaskingBlock; continue; } if (char === '[' || char === ']') { optionalBlock = !optionalBlock; continue; } if (char === MaskedPattern.ESCAPE_CHAR) { ++i; char = pattern[i]; if (!char) break; _isInput = false; } var def = _isInput ? new PatternInputDefinition({ parent: this, lazy: this.lazy, placeholderChar: this.placeholderChar, mask: defs[char], isOptional: optionalBlock }) : new PatternFixedDefinition({ char: char, isUnmasking: unmaskingBlock }); this._blocks.push(def); } } /** @override */ }, { key: "reset", /** @override */ value: function reset() { _get(_getPrototypeOf(MaskedPattern.prototype), "reset", this).call(this); this._blocks.forEach(function (b) { return b.reset(); }); } /** @override */ }, { key: "doCommit", /** @override */ value: function doCommit() { this._blocks.forEach(function (b) { return b.doCommit(); }); _get(_getPrototypeOf(MaskedPattern.prototype), "doCommit", this).call(this); } /** @override */ }, { key: "appendTail", /** @override */ value: function appendTail(tail) { return _get(_getPrototypeOf(MaskedPattern.prototype), "appendTail", this).call(this, tail).aggregate(this._appendPlaceholder()); } /** @override */ }, { key: "_appendCharRaw", value: function _appendCharRaw(ch) { var flags = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; ch = this.doPrepare(ch, flags); var blockIter = this._mapPosToBlock(this.value.length); var details = new ChangeDetails(); if (!blockIter) return details; for (var bi = blockIter.index;; ++bi) { var _block = this._blocks[bi]; if (!_block) break; var block