primevue
Version:
PrimeVue is a premium UI library for Vue featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock, wh
543 lines (537 loc) • 20.8 kB
JavaScript
import { getUserAgent } from '@primeuix/utils/dom';
import BaseDirective from '@primevue/core/basedirective';
import MaskStyle from 'primevue/mask/style';
var BaseMask = BaseDirective.extend({
style: MaskStyle
});
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
var CARET_TIMEOUT = 10;
var STATE_KEYS = ['$_pmaskMask', '$_pmaskSlotChar', '$_pmaskAutoClear', '$_pmaskUnmask', '$_pmaskTests', '$_pmaskBuffer', '$_pmaskDefaultBuffer', '$_pmaskDefs', '$_pmaskLen', '$_pmaskPartialPosition', '$_pmaskFirstNonMaskPos', '$_pmaskLastReqPos', '$_pmaskAndroidChrome', '$_pmaskAndroid', '$_pmaskIPhone', '$_pmaskCurrentVal', '$_pmaskFocusText', '$_pmaskOldVal', '$_pmaskFocus', '$_pmaskCursor', '$_pmaskInternal', '$_pmaskExpectedWriteback', '$_pmaskOnChange'];
var Mask = BaseMask.extend('mask', {
mounted: function mounted(el, options) {
var target = this.getTarget(el);
if (!target) return;
el.$_pmaskTarget = target;
this.initTarget(target, options);
},
updated: function updated(el, options) {
var target = this.getTarget(el);
var previousTarget = el.$_pmaskTarget;
if (previousTarget && previousTarget !== target) {
this.cleanupTarget(previousTarget);
}
el.$_pmaskTarget = target;
if (!target) return;
if (previousTarget !== target) {
this.initTarget(target, options);
return;
}
var previousMask = target.$_pmaskMask;
var previousSlotChar = target.$_pmaskSlotChar;
this.applyOptions(target, options);
if (previousMask !== target.$_pmaskMask || previousSlotChar !== target.$_pmaskSlotChar) {
this.clearCaretTimer(target);
this.init(target);
return;
}
// After updateModel emitted a value that differs from the masked display, Vue may have
// written that emitted value back into the DOM via v-model. Restore the masked string here.
if (target.$_pmaskExpectedWriteback) {
target.$_pmaskExpectedWriteback = false;
var expectedMasked = target.$_pmaskBuffer.join('');
if (target.value !== expectedMasked) {
target.value = expectedMasked;
}
this.restoreCursor(target);
target.$_pmaskCursor = null;
return;
}
this.syncExternalValue(target);
},
unmounted: function unmounted(el) {
var target = el.$_pmaskTarget || this.getTarget(el);
if (!target) return;
this.cleanupTarget(target);
el.$_pmaskTarget = null;
},
methods: {
getTarget: function getTarget(el) {
if (!el) return null;
if (el.tagName === 'INPUT') return el;
return el.querySelector('input') || null;
},
applyOptions: function applyOptions(target, options) {
var _value$mask;
var value = options.value;
var isObject = value !== null && _typeof(value) === 'object' && !Array.isArray(value);
target.$_pmaskMask = isObject ? (_value$mask = value.mask) !== null && _value$mask !== void 0 ? _value$mask : null : value !== null && value !== void 0 ? value : null;
target.$_pmaskSlotChar = isObject && value.slotChar !== undefined ? value.slotChar : '_';
target.$_pmaskAutoClear = isObject && value.autoClear === false ? false : true;
target.$_pmaskUnmask = isObject ? !!value.unmask : false;
target.$_pmaskOnChange = isObject && typeof value.onChange === 'function' ? value.onChange : null;
},
initTarget: function initTarget(target, options) {
this.applyOptions(target, options);
this.bindEvents(target);
target.setAttribute('data-pd-mask', true);
this.init(target);
},
clearCaretTimer: function clearCaretTimer(target) {
if (target.$_pmaskCaretTimeout) {
clearTimeout(target.$_pmaskCaretTimeout);
target.$_pmaskCaretTimeout = null;
}
},
clearState: function clearState(target) {
for (var _i = 0, _STATE_KEYS = STATE_KEYS; _i < _STATE_KEYS.length; _i++) {
var key = _STATE_KEYS[_i];
target[key] = null;
}
},
cleanupTarget: function cleanupTarget(target) {
this.clearCaretTimer(target);
this.unbindEvents(target);
this.clearState(target);
target.removeAttribute('data-pd-mask');
},
bindEvents: function bindEvents(target) {
var _this = this;
target.$_pmaskInputEvent = function (event) {
return _this.onInput(event, target);
};
target.$_pmaskFocusEvent = function (event) {
return _this.onFocus(event, target);
};
target.$_pmaskBlurEvent = function (event) {
return _this.onBlur(event, target);
};
target.$_pmaskKeyDownEvent = function (event) {
return _this.onKeyDown(event, target);
};
target.$_pmaskKeyPressEvent = function (event) {
return _this.onKeyPress(event, target);
};
target.addEventListener('input', target.$_pmaskInputEvent);
target.addEventListener('focus', target.$_pmaskFocusEvent);
target.addEventListener('blur', target.$_pmaskBlurEvent);
target.addEventListener('keydown', target.$_pmaskKeyDownEvent);
target.addEventListener('keypress', target.$_pmaskKeyPressEvent);
},
unbindEvents: function unbindEvents(target) {
target.removeEventListener('input', target.$_pmaskInputEvent);
target.removeEventListener('focus', target.$_pmaskFocusEvent);
target.removeEventListener('blur', target.$_pmaskBlurEvent);
target.removeEventListener('keydown', target.$_pmaskKeyDownEvent);
target.removeEventListener('keypress', target.$_pmaskKeyPressEvent);
target.$_pmaskInputEvent = null;
target.$_pmaskFocusEvent = null;
target.$_pmaskBlurEvent = null;
target.$_pmaskKeyDownEvent = null;
target.$_pmaskKeyPressEvent = null;
},
init: function init(target) {
var mask = target.$_pmaskMask;
target.$_pmaskTests = [];
target.$_pmaskPartialPosition = mask ? mask.length : 0;
target.$_pmaskLen = mask ? mask.length : 0;
target.$_pmaskFirstNonMaskPos = null;
target.$_pmaskLastReqPos = 0;
target.$_pmaskDefs = {
9: '[0-9]',
a: '[A-Za-z]',
'*': '[A-Za-z0-9]'
};
var ua = getUserAgent();
target.$_pmaskAndroidChrome = /chrome/i.test(ua) && /android/i.test(ua);
target.$_pmaskAndroid = /android/i.test(ua);
target.$_pmaskIPhone = /iphone/i.test(ua);
var maskTokens = mask ? mask.split('') : '';
for (var i = 0; i < maskTokens.length; i++) {
var c = maskTokens[i];
if (c === '?') {
target.$_pmaskLen--;
target.$_pmaskPartialPosition = i;
} else if (target.$_pmaskDefs[c]) {
target.$_pmaskTests.push(new RegExp(target.$_pmaskDefs[c]));
if (target.$_pmaskFirstNonMaskPos === null) {
target.$_pmaskFirstNonMaskPos = target.$_pmaskTests.length - 1;
}
if (i < target.$_pmaskPartialPosition) {
target.$_pmaskLastReqPos = target.$_pmaskTests.length - 1;
}
} else {
target.$_pmaskTests.push(null);
}
}
target.$_pmaskBuffer = [];
for (var _i2 = 0; _i2 < maskTokens.length; _i2++) {
var _c = maskTokens[_i2];
if (_c !== '?') {
if (target.$_pmaskDefs[_c]) target.$_pmaskBuffer.push(this.getPlaceholder(target, _i2));else target.$_pmaskBuffer.push(_c);
}
}
target.$_pmaskDefaultBuffer = target.$_pmaskBuffer.join('');
if (target.value) {
this.checkVal(target);
this.updateModel(target);
}
target.$_pmaskFocusText = target.value;
},
syncExternalValue: function syncExternalValue(target) {
if (!target.$_pmaskTests || !target.$_pmaskTests.length) return;
if (target.$_pmaskInternal) return;
var expectedMasked = target.$_pmaskBuffer.join('');
if (!target.value) {
if (expectedMasked !== target.$_pmaskDefaultBuffer) {
this.checkVal(target, true);
this.writeBuffer(target);
}
return;
}
if (target.value !== expectedMasked) {
this.checkVal(target, true);
this.writeBuffer(target);
}
},
saveCursor: function saveCursor(target) {
if (target === document.activeElement) {
target.$_pmaskCursor = {
start: target.selectionStart,
end: target.selectionEnd
};
} else {
target.$_pmaskCursor = null;
}
},
restoreCursor: function restoreCursor(target) {
var cursor = target.$_pmaskCursor;
if (!cursor || target !== document.activeElement) return;
try {
target.setSelectionRange(cursor.start, cursor.end);
} catch (_unused) {
// ignore — input may not be in selectable state
}
},
caret: function caret(target, first, last) {
var _target$selectionStar, _target$selectionEnd;
if (typeof first === 'number') {
if (!target.offsetParent || target !== document.activeElement) return;
var begin = first;
var end = typeof last === 'number' ? last : begin;
if (target.setSelectionRange) {
target.setSelectionRange(begin, end);
}
return;
}
return {
begin: (_target$selectionStar = target.selectionStart) !== null && _target$selectionStar !== void 0 ? _target$selectionStar : 0,
end: (_target$selectionEnd = target.selectionEnd) !== null && _target$selectionEnd !== void 0 ? _target$selectionEnd : 0
};
},
getPlaceholder: function getPlaceholder(target, i) {
var slotChar = target.$_pmaskSlotChar;
if (i < slotChar.length) {
return slotChar.charAt(i);
}
return slotChar.charAt(0);
},
seekNext: function seekNext(target, pos) {
while (++pos < target.$_pmaskLen && !target.$_pmaskTests[pos]) {}
return pos;
},
seekPrev: function seekPrev(target, pos) {
while (--pos >= 0 && !target.$_pmaskTests[pos]) {}
return pos;
},
shiftL: function shiftL(target, begin, end) {
var i, j;
if (begin < 0) {
return;
}
for (i = begin, j = this.seekNext(target, end); i < target.$_pmaskLen; i++) {
if (target.$_pmaskTests[i]) {
if (j < target.$_pmaskLen && target.$_pmaskTests[i].test(target.$_pmaskBuffer[j])) {
target.$_pmaskBuffer[i] = target.$_pmaskBuffer[j];
target.$_pmaskBuffer[j] = this.getPlaceholder(target, j);
} else {
break;
}
j = this.seekNext(target, j);
}
}
this.writeBuffer(target);
this.caret(target, Math.max(target.$_pmaskFirstNonMaskPos, begin));
},
shiftR: function shiftR(target, pos) {
var i, c, j, t;
for (i = pos, c = this.getPlaceholder(target, pos); i < target.$_pmaskLen; i++) {
if (target.$_pmaskTests[i]) {
j = this.seekNext(target, i);
t = target.$_pmaskBuffer[i];
target.$_pmaskBuffer[i] = c;
if (j < target.$_pmaskLen && target.$_pmaskTests[j].test(t)) {
c = t;
} else {
break;
}
}
}
},
clearBuffer: function clearBuffer(target, start, end) {
for (var i = start; i < end && i < target.$_pmaskLen; i++) {
if (target.$_pmaskTests[i]) {
target.$_pmaskBuffer[i] = this.getPlaceholder(target, i);
}
}
},
writeBuffer: function writeBuffer(target) {
target.value = target.$_pmaskBuffer.join('');
},
checkVal: function checkVal(target, allow) {
var test = target.value;
var lastMatch = -1;
var i, c, pos;
for (i = 0, pos = 0; i < target.$_pmaskLen; i++) {
if (target.$_pmaskTests[i]) {
target.$_pmaskBuffer[i] = this.getPlaceholder(target, i);
while (pos++ < test.length) {
c = test.charAt(pos - 1);
if (target.$_pmaskTests[i].test(c)) {
target.$_pmaskBuffer[i] = c;
lastMatch = i;
break;
}
}
if (pos > test.length) {
this.clearBuffer(target, i + 1, target.$_pmaskLen);
break;
}
} else {
if (target.$_pmaskBuffer[i] === test.charAt(pos)) {
pos++;
}
if (i < target.$_pmaskPartialPosition) {
lastMatch = i;
}
}
}
if (allow) {
this.writeBuffer(target);
} else if (lastMatch + 1 < target.$_pmaskPartialPosition) {
if (target.$_pmaskAutoClear || target.$_pmaskBuffer.join('') === target.$_pmaskDefaultBuffer) {
if (target.value) target.value = '';
this.clearBuffer(target, 0, target.$_pmaskLen);
} else {
this.writeBuffer(target);
}
} else {
this.writeBuffer(target);
target.value = target.value.substring(0, lastMatch + 1);
}
return target.$_pmaskPartialPosition ? i : target.$_pmaskFirstNonMaskPos;
},
getUnmaskedValue: function getUnmaskedValue(target) {
var unmaskedBuffer = [];
for (var i = 0; i < target.$_pmaskBuffer.length; i++) {
var c = target.$_pmaskBuffer[i];
if (target.$_pmaskTests[i] && c !== this.getPlaceholder(target, i)) {
unmaskedBuffer.push(c);
}
}
return unmaskedBuffer.join('');
},
unmaskValue: function unmaskValue(target, value) {
var unmaskedBuffer = [];
var chars = value.split('');
for (var i = 0; i < chars.length; i++) {
var c = chars[i];
if (target.$_pmaskTests[i] && c !== this.getPlaceholder(target, i)) {
unmaskedBuffer.push(c);
}
}
return unmaskedBuffer.join('');
},
updateModel: function updateModel(target) {
var masked = target.value;
if (target.$_pmaskCurrentVal === masked) return;
target.$_pmaskCurrentVal = masked;
var unmaskedValue = this.getUnmaskedValue(target);
var valueToEmit = target.$_pmaskUnmask ? unmaskedValue : masked;
var finalValue = target.$_pmaskDefaultBuffer !== valueToEmit ? valueToEmit : '';
if (target.$_pmaskOnChange) {
var maskedValue = target.$_pmaskDefaultBuffer !== masked ? masked : '';
target.$_pmaskOnChange({
value: maskedValue,
rawValue: unmaskedValue
});
}
this.saveCursor(target);
target.$_pmaskInternal = true;
// Vue's v-model reads target.value at the moment 'input' fires, so when the value we emit
// (finalValue) differs from the masked display, we briefly swap target.value, dispatch, then
// restore the masked string. The next directive `updated` consumes $_pmaskExpectedWriteback
// to undo Vue's writeback if it tries to push finalValue back into the DOM.
if (target.$_pmaskUnmask) {
target.$_pmaskExpectedWriteback = true;
target.value = finalValue;
target.dispatchEvent(new Event('input', {
bubbles: true
}));
target.value = masked;
} else if (finalValue === '' && masked !== '') {
target.$_pmaskExpectedWriteback = true;
target.value = '';
target.dispatchEvent(new Event('input', {
bubbles: true
}));
target.value = masked;
} else {
target.dispatchEvent(new Event('input', {
bubbles: true
}));
}
target.$_pmaskInternal = false;
this.restoreCursor(target);
},
handleAndroidInput: function handleAndroidInput(event, target) {
var curVal = target.value;
var pos = this.caret(target);
if (target.$_pmaskOldVal && target.$_pmaskOldVal.length && target.$_pmaskOldVal.length > curVal.length) {
this.checkVal(target, true);
while (pos.begin > 0 && !target.$_pmaskTests[pos.begin - 1]) pos.begin--;
if (pos.begin === 0) {
while (pos.begin < target.$_pmaskFirstNonMaskPos && !target.$_pmaskTests[pos.begin]) pos.begin++;
}
this.caret(target, pos.begin, pos.begin);
} else {
this.checkVal(target, true);
while (pos.begin < target.$_pmaskLen && !target.$_pmaskTests[pos.begin]) pos.begin++;
this.caret(target, pos.begin, pos.begin);
}
},
handleInputChange: function handleInputChange(event, target) {
if (target.readOnly) return;
var pos = this.checkVal(target, true);
this.caret(target, pos);
},
onInput: function onInput(event, target) {
if (target.$_pmaskInternal) return;
if (event.isComposing) return;
if (target.$_pmaskAndroidChrome) this.handleAndroidInput(event, target);else this.handleInputChange(event, target);
this.updateModel(target);
},
onFocus: function onFocus(event, target) {
var _this2 = this;
if (target.readOnly) {
return;
}
target.$_pmaskFocus = true;
target.$_pmaskFocusText = target.value;
this.clearCaretTimer(target);
if (!target.value || target.value === target.$_pmaskDefaultBuffer) {
target.$_pmaskCaretTimeout = setTimeout(function () {
target.$_pmaskCaretTimeout = null;
if (typeof document === 'undefined') return;
if (target !== document.activeElement) return;
_this2.caret(target, 0, 0);
}, CARET_TIMEOUT);
} else {
var pos = this.checkVal(target);
target.$_pmaskCaretTimeout = setTimeout(function () {
target.$_pmaskCaretTimeout = null;
if (typeof document === 'undefined') return;
if (target !== document.activeElement) return;
_this2.writeBuffer(target);
if (pos === target.$_pmaskMask.replace('?', '').length) {
_this2.caret(target, 0, pos);
} else {
_this2.caret(target, pos);
}
}, CARET_TIMEOUT);
}
},
onBlur: function onBlur(event, target) {
if (target.readOnly) {
return;
}
target.$_pmaskFocus = false;
this.checkVal(target);
this.updateModel(target);
if (target.value !== target.$_pmaskFocusText) {
target.dispatchEvent(new Event('change', {
bubbles: true
}));
}
},
onKeyDown: function onKeyDown(event, target) {
if (target.readOnly) {
return;
}
var k = event.code;
var pos, begin, end;
target.$_pmaskOldVal = target.value;
if (k === 'Backspace' || k === 'Delete' || target.$_pmaskIPhone && k === 'Escape') {
pos = this.caret(target);
begin = pos.begin;
end = pos.end;
if (end - begin === 0) {
if (k === 'Delete') {
begin = this.seekNext(target, begin - 1);
end = this.seekNext(target, begin);
} else {
begin = this.seekPrev(target, begin);
}
}
this.clearBuffer(target, begin, end);
this.shiftL(target, begin, end - 1);
this.updateModel(target);
event.preventDefault();
} else if (k === 'Enter') {
target.blur();
this.updateModel(target);
} else if (k === 'Escape') {
target.value = target.$_pmaskFocusText;
this.caret(target, 0, this.checkVal(target));
this.updateModel(target);
event.preventDefault();
}
},
onKeyPress: function onKeyPress(event, target) {
var _this3 = this;
if (target.readOnly) {
return;
}
var k = event.code;
var pos = this.caret(target);
var p, c, next;
if (event.ctrlKey || event.altKey || event.metaKey || event.shiftKey || event.key === 'CapsLock' || event.key === 'Escape' || event.key === 'Tab') {
return;
} else if (k && k !== 'Enter') {
if (pos.end - pos.begin !== 0) {
this.clearBuffer(target, pos.begin, pos.end);
this.shiftL(target, pos.begin, pos.end - 1);
}
p = this.seekNext(target, pos.begin - 1);
if (p < target.$_pmaskLen) {
c = event.key;
if (target.$_pmaskTests[p].test(c)) {
this.shiftR(target, p);
target.$_pmaskBuffer[p] = c;
this.writeBuffer(target);
next = this.seekNext(target, p);
if (target.$_pmaskAndroid) {
setTimeout(function () {
_this3.caret(target, next);
}, 0);
} else {
this.caret(target, next);
}
}
}
event.preventDefault();
}
this.updateModel(target);
}
}
});
export { Mask as default };