Major overhaul to the theme and now functioning.

This commit is contained in:
2026-01-05 16:07:30 -05:00
parent 5823ca3c39
commit a475dfeab6
5218 changed files with 1643729 additions and 13229 deletions
@@ -0,0 +1 @@
export * from './mask.js';
@@ -0,0 +1,2 @@
export * from "./mask.js";
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":[],"sources":["../../../src/composables/mask/index.ts"],"sourcesContent":["export * from './mask'\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,34 @@
// Types
import type { PropType } from 'vue';
export interface MaskProps {
mask: string | MaskOptions | undefined;
}
export interface MaskOptions {
mask: string;
tokens: Record<string, MaskItem>;
}
export declare const makeMaskProps: <Defaults extends {
mask?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
mask: unknown extends Defaults["mask"] ? PropType<string | MaskOptions> : {
type: PropType<unknown extends Defaults["mask"] ? string | MaskOptions : string | MaskOptions | Defaults["mask"]>;
default: unknown extends Defaults["mask"] ? string | MaskOptions : Defaults["mask"] | NonNullable<string | MaskOptions>;
};
};
export type MaskItem = {
convert?: (char: string) => string;
} & ({
pattern?: never;
test: (char: string) => boolean;
} | {
pattern: RegExp;
test?: never;
});
export declare const defaultDelimiters: RegExp;
export declare function isMaskDelimiter(char: string): boolean;
export declare function useMask(props: MaskProps): {
isValid: (text: string) => boolean;
isComplete: (text: string) => boolean;
mask: (text: string | null | undefined) => string;
unmask: (text: string | null) => string | null;
};
@@ -0,0 +1,164 @@
// Utilities
import { computed } from 'vue';
import { isObject, propsFactory } from "../../util/index.js"; // Types
export const makeMaskProps = propsFactory({
mask: [String, Object]
}, 'mask');
export const defaultDelimiters = /[-!$%^&*()_+|~=`{}[\]:";'<>?,./\\ ]/;
const presets = {
'credit-card': '#### - #### - #### - ####',
date: '##/##/####',
'date-time': '##/##/#### ##:##',
'iso-date': '####-##-##',
'iso-date-time': '####-##-## ##:##',
phone: '(###) ### - ####',
social: '###-##-####',
time: '##:##',
'time-with-seconds': '##:##:##'
};
export function isMaskDelimiter(char) {
return char ? defaultDelimiters.test(char) : false;
}
const defaultTokens = {
'#': {
pattern: /[0-9]/
},
A: {
pattern: /[A-Z]/i,
convert: v => v.toUpperCase()
},
a: {
pattern: /[a-z]/i,
convert: v => v.toLowerCase()
},
N: {
pattern: /[0-9A-Z]/i,
convert: v => v.toUpperCase()
},
n: {
pattern: /[0-9a-z]/i,
convert: v => v.toLowerCase()
},
X: {
pattern: defaultDelimiters
}
};
export function useMask(props) {
const mask = computed(() => {
if (typeof props.mask === 'string') {
if (props.mask in presets) return presets[props.mask];
return props.mask;
}
return props.mask?.mask ?? '';
});
const tokens = computed(() => {
return {
...defaultTokens,
...(isObject(props.mask) ? props.mask.tokens : null)
};
});
function isMask(char) {
return char in tokens.value;
}
function maskValidates(mask, char) {
if (char == null || !isMask(mask)) return false;
const item = tokens.value[mask];
if (item.pattern) return item.pattern.test(char);
return item.test(char);
}
function convert(mask, char) {
const item = tokens.value[mask];
return item.convert ? item.convert(char) : char;
}
function maskText(text) {
const trimmedText = text?.trim().replace(/\s+/g, ' ');
if (trimmedText == null) return '';
if (!mask.value.length || !trimmedText.length) return trimmedText;
let textIndex = 0;
let maskIndex = 0;
let newText = '';
while (maskIndex < mask.value.length) {
const mchar = mask.value[maskIndex];
const tchar = trimmedText[textIndex];
// Escaped character in mask, the next mask character is inserted
if (mchar === '\\') {
newText += mask.value[maskIndex + 1];
maskIndex += 2;
continue;
}
if (!isMask(mchar)) {
newText += mchar;
if (tchar === mchar) {
textIndex++;
}
} else if (maskValidates(mchar, tchar)) {
newText += convert(mchar, tchar);
textIndex++;
} else {
break;
}
maskIndex++;
}
return newText;
}
function unmaskText(text) {
if (text == null) return null;
if (!mask.value.length || !text.length) return text;
let textIndex = 0;
let maskIndex = 0;
let newText = '';
while (true) {
const mchar = mask.value[maskIndex];
const tchar = text[textIndex];
if (tchar == null) break;
if (mchar == null) {
newText += tchar;
textIndex++;
continue;
}
// Escaped character in mask, skip the next input character
if (mchar === '\\') {
if (tchar === mask.value[maskIndex + 1]) {
textIndex++;
}
maskIndex += 2;
continue;
}
if (maskValidates(mchar, tchar)) {
// masked char
newText += tchar;
textIndex++;
maskIndex++;
continue;
} else if (mchar !== tchar) {
// input doesn't match mask, skip forward until it does
while (true) {
const mchar = mask.value[maskIndex++];
if (mchar == null || maskValidates(mchar, tchar)) break;
}
continue;
}
textIndex++;
maskIndex++;
}
return newText;
}
function isValid(text) {
if (!text) return false;
return unmaskText(text) === unmaskText(maskText(text));
}
function isComplete(text) {
if (!text) return false;
const maskedText = maskText(text);
return maskedText.length === mask.value.length && isValid(text);
}
return {
isValid,
isComplete,
mask: maskText,
unmask: unmaskText
};
}
//# sourceMappingURL=mask.js.map
File diff suppressed because one or more lines are too long