import { d as _inherits, e as _createSuper, a as _classCallCheck, _ as _createClass, g as _get, h as _getPrototypeOf, b as _objectWithoutProperties, i as _set } from '../_rollupPluginBabelHelpers-a0b34764.js'; import { DIRECTION, forceDirection } from '../core/utils.js'; import ChangeDetails from '../core/change-details.js'; import Masked from './base.js'; import PatternInputDefinition, { DEFAULT_INPUT_DEFINITIONS } from './pattern/input-definition.js'; import PatternFixedDefinition from './pattern/fixed-definition.js'; import ChunksTailDetails from './pattern/chunk-tail-details.js'; import createMask from './factory.js'; import IMask from '../core/holder.js'; import './regexp.js'; import '../core/continuous-tail-details.js'; var _excluded = ["_blocks"]; /** 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); var _super = _createSuper(MaskedPattern); /** */ /** */ /** 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={} does not work opts.definitions = Object.assign({}, DEFAULT_INPUT_DEFINITIONS, opts.definitions); return _super.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) { // $FlowFixMe no ideas 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: "state", get: function get() { return Object.assign({}, _get(_getPrototypeOf(MaskedPattern.prototype), "state", this), { _blocks: this._blocks.map(function (b) { return b.state; }) }); }, set: function set(state) { var _blocks = state._blocks, maskedState = _objectWithoutProperties(state, _excluded); this._blocks.forEach(function (b, bi) { return b.state = _blocks[bi]; }); _set(_getPrototypeOf(MaskedPattern.prototype), "state", maskedState, this, true); } /** @override */ }, { key: "reset", value: function reset() { _get(_getPrototypeOf(MaskedPattern.prototype), "reset", this).call(this); this._blocks.forEach(function (b) { return b.reset(); }); } /** @override */ }, { key: "isComplete", get: function get() { return this._blocks.every(function (b) { return b.isComplete; }); } /** @override */ }, { key: "doCommit", value: function doCommit() { this._blocks.forEach(function (b) { return b.doCommit(); }); _get(_getPrototypeOf(MaskedPattern.prototype), "doCommit", this).call(this); } /** @override */ }, { key: "unmaskedValue", get: function get() { return this._blocks.reduce(function (str, b) { return str += b.unmaskedValue; }, ''); }, set: function set(unmaskedValue) { _set(_getPrototypeOf(MaskedPattern.prototype), "unmaskedValue", unmaskedValue, this, true); } /** @override */ }, { key: "value", get: function get() { // TODO return _value when not in change? return this._blocks.reduce(function (str, b) { return str += b.value; }, ''); }, set: function set(value) { _set(_getPrototypeOf(MaskedPattern.prototype), "value", value, this, true); } /** @override */ }, { key: "appendTail", 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] : {}; 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 blockDetails = _block._appendChar(ch, flags); var skip = blockDetails.skip; details.aggregate(blockDetails); if (skip || blockDetails.rawInserted) break; // go next char } return details; } /** @override */ }, { key: "extractTail", value: function extractTail() { var _this2 = this; 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 chunkTail = new ChunksTailDetails(); if (fromPos === toPos) return chunkTail; this._forEachBlocksInRange(fromPos, toPos, function (b, bi, bFromPos, bToPos) { var blockChunk = b.extractTail(bFromPos, bToPos); blockChunk.stop = _this2._findStopBefore(bi); blockChunk.from = _this2._blockStartPos(bi); if (blockChunk instanceof ChunksTailDetails) blockChunk.blockIndex = bi; chunkTail.extend(blockChunk); }); return chunkTail; } /** @override */ }, { 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] : {}; if (fromPos === toPos) return ''; var input = ''; this._forEachBlocksInRange(fromPos, toPos, function (b, _, fromPos, toPos) { input += b.extractInput(fromPos, toPos, flags); }); return input; } }, { key: "_findStopBefore", value: function _findStopBefore(blockIndex) { var stopBefore; for (var si = 0; si < this._stops.length; ++si) { var stop = this._stops[si]; if (stop <= blockIndex) stopBefore = stop;else break; } return stopBefore; } /** Appends placeholder depending on laziness */ }, { key: "_appendPlaceholder", value: function _appendPlaceholder(toBlockIndex) { var _this3 = this; var details = new ChangeDetails(); if (this.lazy && toBlockIndex == null) return details; var startBlockIter = this._mapPosToBlock(this.value.length); if (!startBlockIter) return details; var startBlockIndex = startBlockIter.index; var endBlockIndex = toBlockIndex != null ? toBlockIndex : this._blocks.length; this._blocks.slice(startBlockIndex, endBlockIndex).forEach(function (b) { if (!b.lazy || toBlockIndex != null) { // $FlowFixMe `_blocks` may not be present var args = b._blocks != null ? [b._blocks.length] : []; var bDetails = b._appendPlaceholder.apply(b, args); _this3._value += bDetails.inserted; details.aggregate(bDetails); } }); return details; } /** Finds block in pos */ }, { key: "_mapPosToBlock", value: function _mapPosToBlock(pos) { var accVal = ''; for (var bi = 0; bi < this._blocks.length; ++bi) { var _block2 = this._blocks[bi]; var blockStartPos = accVal.length; accVal += _block2.value; if (pos <= accVal.length) { return { index: bi, offset: pos - blockStartPos }; } } } /** */ }, { key: "_blockStartPos", value: function _blockStartPos(blockIndex) { return this._blocks.slice(0, blockIndex).reduce(function (pos, b) { return pos += b.value.length; }, 0); } /** */ }, { key: "_forEachBlocksInRange", value: function _forEachBlocksInRange(fromPos) { var toPos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.value.length; var fn = arguments.length > 2 ? arguments[2] : undefined; var fromBlockIter = this._mapPosToBlock(fromPos); if (fromBlockIter) { var toBlockIter = this._mapPosToBlock(toPos); // process first block var isSameBlock = toBlockIter && fromBlockIter.index === toBlockIter.index; var fromBlockStartPos = fromBlockIter.offset; var fromBlockEndPos = toBlockIter && isSameBlock ? toBlockIter.offset : this._blocks[fromBlockIter.index].value.length; fn(this._blocks[fromBlockIter.index], fromBlockIter.index, fromBlockStartPos, fromBlockEndPos); if (toBlockIter && !isSameBlock) { // process intermediate blocks for (var bi = fromBlockIter.index + 1; bi < toBlockIter.index; ++bi) { fn(this._blocks[bi], bi, 0, this._blocks[bi].value.length); } // process last block fn(this._blocks[toBlockIter.index], toBlockIter.index, 0, toBlockIter.offset); } } } /** @override */ }, { 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; var removeDetails = _get(_getPrototypeOf(MaskedPattern.prototype), "remove", this).call(this, fromPos, toPos); this._forEachBlocksInRange(fromPos, toPos, function (b, _, bFromPos, bToPos) { removeDetails.aggregate(b.remove(bFromPos, bToPos)); }); return removeDetails; } /** @override */ }, { key: "nearestInputPos", value: function nearestInputPos(cursorPos) { var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DIRECTION.NONE; // TODO refactor - extract alignblock var beginBlockData = this._mapPosToBlock(cursorPos) || { index: 0, offset: 0 }; var beginBlockOffset = beginBlockData.offset, beginBlockIndex = beginBlockData.index; var beginBlock = this._blocks[beginBlockIndex]; if (!beginBlock) return cursorPos; var beginBlockCursorPos = beginBlockOffset; // if position inside block - try to adjust it if (beginBlockCursorPos !== 0 && beginBlockCursorPos < beginBlock.value.length) { beginBlockCursorPos = beginBlock.nearestInputPos(beginBlockOffset, forceDirection(direction)); } var cursorAtRight = beginBlockCursorPos === beginBlock.value.length; var cursorAtLeft = beginBlockCursorPos === 0; // cursor is INSIDE first block (not at bounds) if (!cursorAtLeft && !cursorAtRight) return this._blockStartPos(beginBlockIndex) + beginBlockCursorPos; var searchBlockIndex = cursorAtRight ? beginBlockIndex + 1 : beginBlockIndex; if (direction === DIRECTION.NONE) { // NONE direction used to calculate start input position if no chars were removed // FOR NONE: // - // input|any // -> // any|input // <- // filled-input|any // check if first block at left is input if (searchBlockIndex > 0) { var blockIndexAtLeft = searchBlockIndex - 1; var blockAtLeft = this._blocks[blockIndexAtLeft]; var blockInputPos = blockAtLeft.nearestInputPos(0, DIRECTION.NONE); // is input if (!blockAtLeft.value.length || blockInputPos !== blockAtLeft.value.length) { return this._blockStartPos(searchBlockIndex); } } // -> var firstInputAtRight = searchBlockIndex; for (var bi = firstInputAtRight; bi < this._blocks.length; ++bi) { var blockAtRight = this._blocks[bi]; var _blockInputPos = blockAtRight.nearestInputPos(0, DIRECTION.NONE); if (!blockAtRight.value.length || _blockInputPos !== blockAtRight.value.length) { return this._blockStartPos(bi) + _blockInputPos; } } // <- // find first non-fixed symbol for (var _bi = searchBlockIndex - 1; _bi >= 0; --_bi) { var _block3 = this._blocks[_bi]; var _blockInputPos2 = _block3.nearestInputPos(0, DIRECTION.NONE); // is input if (!_block3.value.length || _blockInputPos2 !== _block3.value.length) { return this._blockStartPos(_bi) + _block3.value.length; } } return cursorPos; } if (direction === DIRECTION.LEFT || direction === DIRECTION.FORCE_LEFT) { // - // any|filled-input // <- // any|first not empty is not-len-aligned // not-0-aligned|any // -> // any|not-len-aligned or end // check if first block at right is filled input var firstFilledBlockIndexAtRight; for (var _bi2 = searchBlockIndex; _bi2 < this._blocks.length; ++_bi2) { if (this._blocks[_bi2].value) { firstFilledBlockIndexAtRight = _bi2; break; } } if (firstFilledBlockIndexAtRight != null) { var filledBlock = this._blocks[firstFilledBlockIndexAtRight]; var _blockInputPos3 = filledBlock.nearestInputPos(0, DIRECTION.RIGHT); if (_blockInputPos3 === 0 && filledBlock.unmaskedValue.length) { // filled block is input return this._blockStartPos(firstFilledBlockIndexAtRight) + _blockInputPos3; } } // <- // find this vars var firstFilledInputBlockIndex = -1; var firstEmptyInputBlockIndex; // TODO consider nested empty inputs for (var _bi3 = searchBlockIndex - 1; _bi3 >= 0; --_bi3) { var _block4 = this._blocks[_bi3]; var _blockInputPos4 = _block4.nearestInputPos(_block4.value.length, DIRECTION.FORCE_LEFT); if (!_block4.value || _blockInputPos4 !== 0) firstEmptyInputBlockIndex = _bi3; if (_blockInputPos4 !== 0) { if (_blockInputPos4 !== _block4.value.length) { // aligned inside block - return immediately return this._blockStartPos(_bi3) + _blockInputPos4; } else { // found filled firstFilledInputBlockIndex = _bi3; break; } } } if (direction === DIRECTION.LEFT) { // try find first empty input before start searching position only when not forced for (var _bi4 = firstFilledInputBlockIndex + 1; _bi4 <= Math.min(searchBlockIndex, this._blocks.length - 1); ++_bi4) { var _block5 = this._blocks[_bi4]; var _blockInputPos5 = _block5.nearestInputPos(0, DIRECTION.NONE); var blockAlignedPos = this._blockStartPos(_bi4) + _blockInputPos5; if (blockAlignedPos > cursorPos) break; // if block is not lazy input if (_blockInputPos5 !== _block5.value.length) return blockAlignedPos; } } // process overflow if (firstFilledInputBlockIndex >= 0) { return this._blockStartPos(firstFilledInputBlockIndex) + this._blocks[firstFilledInputBlockIndex].value.length; } // for lazy if has aligned left inside fixed and has came to the start - use start position if (direction === DIRECTION.FORCE_LEFT || this.lazy && !this.extractInput() && !isInput(this._blocks[searchBlockIndex])) { return 0; } if (firstEmptyInputBlockIndex != null) { return this._blockStartPos(firstEmptyInputBlockIndex); } // find first input for (var _bi5 = searchBlockIndex; _bi5 < this._blocks.length; ++_bi5) { var _block6 = this._blocks[_bi5]; var _blockInputPos6 = _block6.nearestInputPos(0, DIRECTION.NONE); // is input if (!_block6.value.length || _blockInputPos6 !== _block6.value.length) { return this._blockStartPos(_bi5) + _blockInputPos6; } } return 0; } if (direction === DIRECTION.RIGHT || direction === DIRECTION.FORCE_RIGHT) { // -> // any|not-len-aligned and filled // any|not-len-aligned // <- // not-0-aligned or start|any var firstInputBlockAlignedIndex; var firstInputBlockAlignedPos; for (var _bi6 = searchBlockIndex; _bi6 < this._blocks.length; ++_bi6) { var _block7 = this._blocks[_bi6]; var _blockInputPos7 = _block7.nearestInputPos(0, DIRECTION.NONE); if (_blockInputPos7 !== _block7.value.length) { firstInputBlockAlignedPos = this._blockStartPos(_bi6) + _blockInputPos7; firstInputBlockAlignedIndex = _bi6; break; } } if (firstInputBlockAlignedIndex != null && firstInputBlockAlignedPos != null) { for (var _bi7 = firstInputBlockAlignedIndex; _bi7 < this._blocks.length; ++_bi7) { var _block8 = this._blocks[_bi7]; var _blockInputPos8 = _block8.nearestInputPos(0, DIRECTION.FORCE_RIGHT); if (_blockInputPos8 !== _block8.value.length) { return this._blockStartPos(_bi7) + _blockInputPos8; } } return direction === DIRECTION.FORCE_RIGHT ? this.value.length : firstInputBlockAlignedPos; } for (var _bi8 = Math.min(searchBlockIndex, this._blocks.length - 1); _bi8 >= 0; --_bi8) { var _block9 = this._blocks[_bi8]; var _blockInputPos9 = _block9.nearestInputPos(_block9.value.length, DIRECTION.LEFT); if (_blockInputPos9 !== 0) { var alignedPos = this._blockStartPos(_bi8) + _blockInputPos9; if (alignedPos >= cursorPos) return alignedPos; break; } } } return cursorPos; } /** Get block by name */ }, { key: "maskedBlock", value: function maskedBlock(name) { return this.maskedBlocks(name)[0]; } /** Get all blocks by name */ }, { key: "maskedBlocks", value: function maskedBlocks(name) { var _this4 = this; var indices = this._maskedBlocks[name]; if (!indices) return []; return indices.map(function (gi) { return _this4._blocks[gi]; }); } }]); return MaskedPattern; }(Masked); MaskedPattern.DEFAULTS = { lazy: true, placeholderChar: '_' }; MaskedPattern.STOP_CHAR = '`'; MaskedPattern.ESCAPE_CHAR = '\\'; MaskedPattern.InputDefinition = PatternInputDefinition; MaskedPattern.FixedDefinition = PatternFixedDefinition; function isInput(block) { if (!block) return false; var value = block.value; return !value || block.nearestInputPos(0, DIRECTION.NONE) !== value.length; } IMask.MaskedPattern = MaskedPattern; export { MaskedPattern as default };