@signalapp/minimask
Version:
Simple HTML input masking
179 lines (175 loc) • 5.06 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/minimask.ts
var minimask_exports = {};
__export(minimask_exports, {
createCreditCardExpirationFormatter: () => createCreditCardExpirationFormatter,
minimask: () => minimask
});
module.exports = __toCommonJS(minimask_exports);
// src/getNextInputState.ts
function getNextInputState(formatter, prevValue, prevStart, prevEnd, isDeleting) {
let value = "";
let start = null;
let end = null;
let cursor = 0;
let lastIndex = 0;
for (let token of formatter(prevValue)) {
value += token.char;
if (isDeleting && token.mask) continue;
while (cursor <= token.index) {
if (cursor === prevStart) start ??= lastIndex;
if (cursor === prevEnd) end ??= lastIndex;
cursor += 1;
}
lastIndex = value.length;
}
if (isDeleting && end === null) {
value = value.slice(0, lastIndex);
}
start ??= value.length;
end ??= value.length;
return { value, start, end };
}
// src/formatters/cc-exp.ts
function isDigit(char) {
return /\d/.test(char);
}
function createCreditCardExpirationFormatter() {
return function creditCardExpirationFormatter(input) {
let chars = input.split("");
let index = 0;
let char = chars[index];
function next() {
char = chars[++index];
}
function take() {
if (char == null) throw new Error();
let token = { char, index, mask: false };
next();
return token;
}
if (char == "/") {
return [];
}
while (char != null && !isDigit(char)) {
next();
}
if (char == null) {
return [];
}
let month1 = take();
let month2;
if (month1.char === "0") {
if (char == null || !isDigit(char) || char === "0") {
return [month1];
} else {
month2 = take();
}
} else if (month1.char === "1") {
if (char == null) {
return [month1];
} else if (char === "0" || char === "1" || char === "2") {
month2 = take();
} else {
month2 = month1;
month1 = null;
}
} else {
month2 = month1;
month1 = null;
}
let slashIndex = null;
if (char != null && !isDigit(char)) {
slashIndex = index;
} else {
slashIndex = month2.index;
month1 ??= { char: "0", index: month2.index, mask: false };
}
let year = [];
while (char != null) {
if (isDigit(char)) {
year.push(take());
if (year.length >= 4) {
break;
}
} else {
next();
}
}
if (year.length >= 4) {
year = year.slice(2, 4);
} else {
year = year.slice(0, 2);
}
let tokens = [];
if (month1 != null) tokens.push(month1);
if (month2 != null) tokens.push(month2);
if (month2 != null) {
tokens.push({ char: "/", index: slashIndex, mask: true });
}
return tokens.concat(year);
};
}
// src/minimask.ts
var DELETE_BACKWARD = /* @__PURE__ */ new Set([
"deleteContentBackward",
"deleteWordBackward",
"deleteSoftLineBackward",
"deleteHardLineBackward"
]);
function minimask(input, formatter) {
let history = [input.value];
let historyIndex = 0;
let onInput = (event) => {
const inputType = event.inputType;
if (inputType === "historyUndo") {
historyIndex = Math.max(historyIndex - 1, 0);
input.value = history[historyIndex];
} else if (inputType === "historyRedo") {
historyIndex = Math.min(historyIndex + 1, history.length - 1);
input.value = history[historyIndex];
} else {
let isDeleting = DELETE_BACKWARD.has(inputType);
let { value, start, end } = getNextInputState(
formatter,
input.value,
input.selectionStart ?? 0,
input.selectionEnd ?? 0,
isDeleting
);
input.value = value;
input.setSelectionRange(start, end);
if (value !== history[historyIndex]) {
historyIndex++;
history.splice(historyIndex, Infinity, input.value);
}
}
};
input.addEventListener("input", onInput);
return function unsubscribe() {
input.removeEventListener("input", onInput);
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createCreditCardExpirationFormatter,
minimask
});
//# sourceMappingURL=minimask.cjs.map