@vuetify/nightly 3.8.9-dev.2025-06-11 → 3.8.9-dev.2025-06-13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -3
- package/dist/json/attributes.json +3441 -3169
- package/dist/json/importMap-labs.json +40 -36
- package/dist/json/importMap.json +166 -166
- package/dist/json/tags.json +74 -1
- package/dist/json/web-types.json +6884 -5821
- package/dist/vuetify-labs.cjs +357 -47
- package/dist/vuetify-labs.css +5881 -5870
- package/dist/vuetify-labs.d.ts +8448 -1672
- package/dist/vuetify-labs.esm.js +357 -47
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +357 -47
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.cjs +111 -47
- package/dist/vuetify.cjs.map +1 -1
- package/dist/vuetify.css +5075 -5064
- package/dist/vuetify.d.ts +1499 -1302
- package/dist/vuetify.esm.js +111 -47
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +111 -47
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +1063 -1057
- package/dist/vuetify.min.js.map +1 -1
- package/lib/components/VAutocomplete/VAutocomplete.d.ts +21 -7
- package/lib/components/VCombobox/VCombobox.d.ts +21 -7
- package/lib/components/VDatePicker/VDatePicker.d.ts +70 -5
- package/lib/components/VDatePicker/VDatePicker.js +10 -4
- package/lib/components/VDatePicker/VDatePicker.js.map +1 -1
- package/lib/components/VKbd/VKbd.css +13 -2
- package/lib/components/VKbd/VKbd.d.ts +221 -0
- package/lib/components/VKbd/VKbd.js +55 -0
- package/lib/components/VKbd/VKbd.js.map +1 -0
- package/lib/components/VKbd/VKbd.sass +2 -1
- package/lib/components/VKbd/_variables.scss +12 -1
- package/lib/components/VKbd/index.d.ts +1 -95
- package/lib/components/VKbd/index.js +1 -4
- package/lib/components/VKbd/index.js.map +1 -1
- package/lib/components/VMenu/VMenu.d.ts +13 -0
- package/lib/components/VMenu/VMenu.js +2 -1
- package/lib/components/VMenu/VMenu.js.map +1 -1
- package/lib/components/VNumberInput/VNumberInput.d.ts +11 -0
- package/lib/components/VNumberInput/VNumberInput.js +37 -29
- package/lib/components/VNumberInput/VNumberInput.js.map +1 -1
- package/lib/components/VSelect/VSelect.d.ts +33 -11
- package/lib/components/VSpeedDial/VSpeedDial.d.ts +13 -0
- package/lib/composables/locale.d.ts +5 -1
- package/lib/composables/locale.js.map +1 -1
- package/lib/composables/mask.d.ts +38 -0
- package/lib/composables/mask.js +183 -0
- package/lib/composables/mask.js.map +1 -0
- package/lib/composables/theme.js +3 -3
- package/lib/composables/theme.js.map +1 -1
- package/lib/entry-bundler.d.ts +1 -0
- package/lib/entry-bundler.js +1 -1
- package/lib/framework.d.ts +67 -63
- package/lib/framework.js +1 -1
- package/lib/labs/VMaskInput/VMaskInput.d.ts +6993 -0
- package/lib/labs/VMaskInput/VMaskInput.js +67 -0
- package/lib/labs/VMaskInput/VMaskInput.js.map +1 -0
- package/lib/labs/VMaskInput/index.d.ts +1 -0
- package/lib/labs/VMaskInput/index.js +2 -0
- package/lib/labs/VMaskInput/index.js.map +1 -0
- package/lib/labs/components.d.ts +1 -0
- package/lib/labs/components.js +1 -0
- package/lib/labs/components.js.map +1 -1
- package/lib/labs/entry-bundler.d.ts +1 -0
- package/lib/locale/adapters/vue-i18n.js +6 -1
- package/lib/locale/adapters/vue-i18n.js.map +1 -1
- package/lib/locale/adapters/vuetify.js +7 -1
- package/lib/locale/adapters/vuetify.js.map +1 -1
- package/lib/util/helpers.d.ts +2 -1
- package/lib/util/helpers.js +12 -7
- package/lib/util/helpers.js.map +1 -1
- package/package.json +1 -1
package/dist/vuetify-labs.esm.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* Vuetify v3.8.9-dev.2025-06-
|
2
|
+
* Vuetify v3.8.9-dev.2025-06-13
|
3
3
|
* Forged by John Leider
|
4
4
|
* Released under the MIT License.
|
5
5
|
*/
|
@@ -588,18 +588,23 @@ function checkPrintable(e) {
|
|
588
588
|
function isPrimitive(value) {
|
589
589
|
return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint';
|
590
590
|
}
|
591
|
-
function
|
592
|
-
|
591
|
+
function escapeForRegex(sign) {
|
592
|
+
return '\\^$*+?.()|{}[]'.includes(sign) ? `\\${sign}` : sign;
|
593
|
+
}
|
594
|
+
function extractNumber(text, decimalDigitsLimit, decimalSeparator) {
|
595
|
+
const onlyValidCharacters = new RegExp(`[\\d\\-${escapeForRegex(decimalSeparator)}]`);
|
596
|
+
const cleanText = text.split('').filter(x => onlyValidCharacters.test(x)).filter((x, i, all) => i === 0 && /[-]/.test(x) ||
|
593
597
|
// sign allowed at the start
|
594
|
-
x ===
|
598
|
+
x === decimalSeparator && i === all.indexOf(x) ||
|
595
599
|
// decimal separator allowed only once
|
596
600
|
/\d/.test(x)).join('');
|
597
601
|
if (decimalDigitsLimit === 0) {
|
598
|
-
return cleanText.split(
|
602
|
+
return cleanText.split(decimalSeparator)[0];
|
599
603
|
}
|
600
|
-
|
601
|
-
|
602
|
-
|
604
|
+
const decimalPart = new RegExp(`${escapeForRegex(decimalSeparator)}\\d`);
|
605
|
+
if (decimalDigitsLimit !== null && decimalPart.test(cleanText)) {
|
606
|
+
const parts = cleanText.split(decimalSeparator);
|
607
|
+
return [parts[0], parts[1].substring(0, decimalDigitsLimit)].join(decimalSeparator);
|
603
608
|
}
|
604
609
|
return cleanText;
|
605
610
|
}
|
@@ -2175,6 +2180,10 @@ function createNumberFunction(current, fallback) {
|
|
2175
2180
|
return numberFormat.format(value);
|
2176
2181
|
};
|
2177
2182
|
}
|
2183
|
+
function inferDecimalSeparator(current, fallback) {
|
2184
|
+
const format = createNumberFunction(current, fallback);
|
2185
|
+
return format(0.1).includes(',') ? ',' : '.';
|
2186
|
+
}
|
2178
2187
|
function useProvided(props, prop, provided) {
|
2179
2188
|
const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
|
2180
2189
|
|
@@ -2197,6 +2206,7 @@ function createProvideFunction(state) {
|
|
2197
2206
|
current,
|
2198
2207
|
fallback,
|
2199
2208
|
messages,
|
2209
|
+
decimalSeparator: toRef(() => inferDecimalSeparator(current, fallback)),
|
2200
2210
|
t: createTranslateFunction(current, fallback, messages),
|
2201
2211
|
n: createNumberFunction(current, fallback),
|
2202
2212
|
provide: createProvideFunction({
|
@@ -2219,6 +2229,7 @@ function createVuetifyAdapter(options) {
|
|
2219
2229
|
current,
|
2220
2230
|
fallback,
|
2221
2231
|
messages,
|
2232
|
+
decimalSeparator: toRef(() => options?.decimalSeparator ?? inferDecimalSeparator(current, fallback)),
|
2222
2233
|
t: createTranslateFunction(current, fallback, messages),
|
2223
2234
|
n: createNumberFunction(current, fallback),
|
2224
2235
|
provide: createProvideFunction({
|
@@ -2383,8 +2394,8 @@ function genDefaults$2() {
|
|
2383
2394
|
'activated-opacity': 0.12,
|
2384
2395
|
'pressed-opacity': 0.12,
|
2385
2396
|
'dragged-opacity': 0.08,
|
2386
|
-
'theme-kbd': '#
|
2387
|
-
'theme-on-kbd': '#
|
2397
|
+
'theme-kbd': '#EEEEEE',
|
2398
|
+
'theme-on-kbd': '#000000',
|
2388
2399
|
'theme-code': '#F5F5F5',
|
2389
2400
|
'theme-on-code': '#000000'
|
2390
2401
|
}
|
@@ -2420,7 +2431,7 @@ function genDefaults$2() {
|
|
2420
2431
|
'activated-opacity': 0.12,
|
2421
2432
|
'pressed-opacity': 0.16,
|
2422
2433
|
'dragged-opacity': 0.08,
|
2423
|
-
'theme-kbd': '#
|
2434
|
+
'theme-kbd': '#424242',
|
2424
2435
|
'theme-on-kbd': '#FFFFFF',
|
2425
2436
|
'theme-code': '#343434',
|
2426
2437
|
'theme-on-code': '#CCCCCC'
|
@@ -11630,6 +11641,7 @@ const makeVMenuProps = propsFactory({
|
|
11630
11641
|
// disableKeys: Boolean,
|
11631
11642
|
id: String,
|
11632
11643
|
submenu: Boolean,
|
11644
|
+
disableInitialFocus: Boolean,
|
11633
11645
|
...omit(makeVOverlayProps({
|
11634
11646
|
closeDelay: 250,
|
11635
11647
|
closeOnContentClick: true,
|
@@ -11704,7 +11716,7 @@ const VMenu = genericComponent()({
|
|
11704
11716
|
watch(isActive, val => {
|
11705
11717
|
if (val) {
|
11706
11718
|
parent?.register();
|
11707
|
-
if (IN_BROWSER) {
|
11719
|
+
if (IN_BROWSER && !props.disableInitialFocus) {
|
11708
11720
|
document.addEventListener('focusin', onFocusIn, {
|
11709
11721
|
once: true
|
11710
11722
|
});
|
@@ -23005,7 +23017,9 @@ const VDatePicker = genericComponent()({
|
|
23005
23017
|
"max": maxDate.value,
|
23006
23018
|
"year": year.value,
|
23007
23019
|
"allowedMonths": allowedMonths
|
23008
|
-
}),
|
23020
|
+
}), {
|
23021
|
+
...pick(slots, ['month'])
|
23022
|
+
}) : viewMode.value === 'year' ? createVNode(VDatePickerYears, mergeProps({
|
23009
23023
|
"key": "date-picker-years"
|
23010
23024
|
}, datePickerYearsProps, {
|
23011
23025
|
"modelValue": year.value,
|
@@ -23013,7 +23027,9 @@ const VDatePicker = genericComponent()({
|
|
23013
23027
|
"min": minDate.value,
|
23014
23028
|
"max": maxDate.value,
|
23015
23029
|
"allowedYears": allowedYears
|
23016
|
-
}),
|
23030
|
+
}), {
|
23031
|
+
...pick(slots, ['year'])
|
23032
|
+
}) : createVNode(VDatePickerMonth, mergeProps({
|
23017
23033
|
"key": "date-picker-month"
|
23018
23034
|
}, datePickerMonthProps, {
|
23019
23035
|
"modelValue": model.value,
|
@@ -23024,7 +23040,9 @@ const VDatePicker = genericComponent()({
|
|
23024
23040
|
"onUpdate:year": [$event => year.value = $event, onUpdateYear],
|
23025
23041
|
"min": minDate.value,
|
23026
23042
|
"max": maxDate.value
|
23027
|
-
}),
|
23043
|
+
}), {
|
23044
|
+
...pick(slots, ['day'])
|
23045
|
+
})]
|
23028
23046
|
})]),
|
23029
23047
|
actions: slots.actions
|
23030
23048
|
});
|
@@ -24334,8 +24352,47 @@ const VItem = genericComponent()({
|
|
24334
24352
|
}
|
24335
24353
|
});
|
24336
24354
|
|
24337
|
-
|
24338
|
-
|
24355
|
+
const makeVKbdProps = propsFactory({
|
24356
|
+
...makeBorderProps(),
|
24357
|
+
...makeComponentProps(),
|
24358
|
+
...makeRoundedProps(),
|
24359
|
+
...makeTagProps({
|
24360
|
+
tag: 'kbd'
|
24361
|
+
}),
|
24362
|
+
...makeThemeProps(),
|
24363
|
+
...makeElevationProps(),
|
24364
|
+
color: String
|
24365
|
+
}, 'VKbd');
|
24366
|
+
const VKbd = genericComponent()({
|
24367
|
+
name: 'VKbd',
|
24368
|
+
props: makeVKbdProps(),
|
24369
|
+
setup(props, _ref) {
|
24370
|
+
let {
|
24371
|
+
slots
|
24372
|
+
} = _ref;
|
24373
|
+
const {
|
24374
|
+
themeClasses
|
24375
|
+
} = provideTheme(props);
|
24376
|
+
const {
|
24377
|
+
borderClasses
|
24378
|
+
} = useBorder(props);
|
24379
|
+
const {
|
24380
|
+
roundedClasses
|
24381
|
+
} = useRounded(props);
|
24382
|
+
const {
|
24383
|
+
backgroundColorClasses,
|
24384
|
+
backgroundColorStyles
|
24385
|
+
} = useBackgroundColor(() => props.color);
|
24386
|
+
const {
|
24387
|
+
elevationClasses
|
24388
|
+
} = useElevation(props);
|
24389
|
+
useRender(() => createVNode(props.tag, {
|
24390
|
+
"class": normalizeClass(['v-kbd', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
|
24391
|
+
"style": normalizeStyle([backgroundColorStyles.value, props.style])
|
24392
|
+
}, slots));
|
24393
|
+
return {};
|
24394
|
+
}
|
24395
|
+
});
|
24339
24396
|
|
24340
24397
|
const makeVLayoutProps = propsFactory({
|
24341
24398
|
...makeComponentProps(),
|
@@ -25177,6 +25234,10 @@ const makeVNumberInputProps = propsFactory({
|
|
25177
25234
|
type: Number,
|
25178
25235
|
default: null
|
25179
25236
|
},
|
25237
|
+
decimalSeparator: {
|
25238
|
+
type: String,
|
25239
|
+
validator: v => !v || v.length === 1
|
25240
|
+
},
|
25180
25241
|
...omit(makeVTextFieldProps(), ['modelValue', 'validationValue'])
|
25181
25242
|
}, 'VNumberInput');
|
25182
25243
|
const VNumberInput = genericComponent()({
|
@@ -25202,21 +25263,24 @@ const VNumberInput = genericComponent()({
|
|
25202
25263
|
const form = useForm(props);
|
25203
25264
|
const controlsDisabled = computed(() => form.isDisabled.value || form.isReadonly.value);
|
25204
25265
|
const isFocused = shallowRef(props.focused);
|
25266
|
+
const {
|
25267
|
+
decimalSeparator: decimalSeparatorFromLocale
|
25268
|
+
} = useLocale();
|
25269
|
+
const decimalSeparator = computed(() => props.decimalSeparator?.[0] || decimalSeparatorFromLocale.value);
|
25205
25270
|
function correctPrecision(val) {
|
25206
25271
|
let precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.precision;
|
25207
|
-
|
25208
|
-
|
25209
|
-
|
25210
|
-
|
25211
|
-
|
25212
|
-
return Number(fixed).toString(); // trim zeros
|
25272
|
+
let trim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
25273
|
+
const fixed = precision == null ? String(val) : val.toFixed(precision);
|
25274
|
+
if (isFocused.value && trim) {
|
25275
|
+
return Number(fixed).toString() // trim zeros
|
25276
|
+
.replace('.', decimalSeparator.value);
|
25213
25277
|
}
|
25214
|
-
if (
|
25215
|
-
|
25216
|
-
const [baseDigits, fractionDigits] = fixed.split('.');
|
25217
|
-
fixed = [baseDigits, fractionDigits.replace(new RegExp(`0{1,${trimLimit}}$`), '')].filter(Boolean).join('.');
|
25278
|
+
if (props.minFractionDigits === null || precision !== null && precision < props.minFractionDigits) {
|
25279
|
+
return fixed.replace('.', decimalSeparator.value);
|
25218
25280
|
}
|
25219
|
-
|
25281
|
+
let [baseDigits, fractionDigits] = fixed.split('.');
|
25282
|
+
fractionDigits = (fractionDigits ?? '').padEnd(props.minFractionDigits, '0').replace(new RegExp(`(?<=\\d{${props.minFractionDigits}})0`, 'g'), '');
|
25283
|
+
return [baseDigits, fractionDigits].filter(Boolean).join(decimalSeparator.value);
|
25220
25284
|
}
|
25221
25285
|
const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(Number(val), props.min, props.max));
|
25222
25286
|
const _inputText = shallowRef(null);
|
@@ -25233,8 +25297,11 @@ const VNumberInput = genericComponent()({
|
|
25233
25297
|
if (val === null || val === '') {
|
25234
25298
|
model.value = null;
|
25235
25299
|
_inputText.value = null;
|
25236
|
-
|
25237
|
-
|
25300
|
+
return;
|
25301
|
+
}
|
25302
|
+
const parsedValue = Number(val.replace(decimalSeparator.value, '.'));
|
25303
|
+
if (!isNaN(parsedValue) && parsedValue <= props.max && parsedValue >= props.min) {
|
25304
|
+
model.value = parsedValue;
|
25238
25305
|
_inputText.value = val;
|
25239
25306
|
}
|
25240
25307
|
}
|
@@ -25305,24 +25372,24 @@ const VNumberInput = genericComponent()({
|
|
25305
25372
|
selectionEnd
|
25306
25373
|
} = inputElement ?? {};
|
25307
25374
|
const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
|
25308
|
-
const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision);
|
25375
|
+
const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision, decimalSeparator.value);
|
25309
25376
|
|
25310
|
-
//
|
25311
|
-
//
|
25312
|
-
//
|
25313
|
-
if (
|
25377
|
+
// Allow only numbers, "-" and {decimal separator}
|
25378
|
+
// Allow "-" and {decimal separator} only once
|
25379
|
+
// Allow "-" only at the start
|
25380
|
+
if (!new RegExp(`^-?\\d*${escapeForRegex(decimalSeparator.value)}?\\d*$`).test(potentialNewInputVal)) {
|
25314
25381
|
e.preventDefault();
|
25315
25382
|
inputElement.value = potentialNewNumber;
|
25316
25383
|
}
|
25317
25384
|
if (props.precision == null) return;
|
25318
25385
|
|
25319
25386
|
// Ignore decimal digits above precision limit
|
25320
|
-
if (potentialNewInputVal.split(
|
25387
|
+
if (potentialNewInputVal.split(decimalSeparator.value)[1]?.length > props.precision) {
|
25321
25388
|
e.preventDefault();
|
25322
25389
|
inputElement.value = potentialNewNumber;
|
25323
25390
|
}
|
25324
25391
|
// Ignore decimal separator when precision = 0
|
25325
|
-
if (props.precision === 0 && potentialNewInputVal.includes(
|
25392
|
+
if (props.precision === 0 && potentialNewInputVal.includes(decimalSeparator.value)) {
|
25326
25393
|
e.preventDefault();
|
25327
25394
|
inputElement.value = potentialNewNumber;
|
25328
25395
|
}
|
@@ -25374,19 +25441,16 @@ const VNumberInput = genericComponent()({
|
|
25374
25441
|
if (controlsDisabled.value) return;
|
25375
25442
|
if (!vTextFieldRef.value) return;
|
25376
25443
|
const actualText = vTextFieldRef.value.value;
|
25377
|
-
|
25378
|
-
|
25444
|
+
const parsedValue = Number(actualText.replace(decimalSeparator.value, '.'));
|
25445
|
+
if (actualText && !isNaN(parsedValue)) {
|
25446
|
+
inputText.value = correctPrecision(clamp(parsedValue, props.min, props.max));
|
25379
25447
|
} else {
|
25380
25448
|
inputText.value = null;
|
25381
25449
|
}
|
25382
25450
|
}
|
25383
25451
|
function formatInputValue() {
|
25384
25452
|
if (controlsDisabled.value) return;
|
25385
|
-
|
25386
|
-
inputText.value = null;
|
25387
|
-
return;
|
25388
|
-
}
|
25389
|
-
inputText.value = correctPrecision(model.value);
|
25453
|
+
inputText.value = model.value !== null && !isNaN(model.value) ? correctPrecision(model.value, props.precision, false) : null;
|
25390
25454
|
}
|
25391
25455
|
function trimDecimalZeros() {
|
25392
25456
|
if (controlsDisabled.value) return;
|
@@ -25394,7 +25458,7 @@ const VNumberInput = genericComponent()({
|
|
25394
25458
|
inputText.value = null;
|
25395
25459
|
return;
|
25396
25460
|
}
|
25397
|
-
inputText.value = model.value.toString();
|
25461
|
+
inputText.value = model.value.toString().replace('.', decimalSeparator.value);
|
25398
25462
|
}
|
25399
25463
|
function onFocus() {
|
25400
25464
|
trimDecimalZeros();
|
@@ -30490,6 +30554,251 @@ const VIconBtn = genericComponent()({
|
|
30490
30554
|
}
|
30491
30555
|
});
|
30492
30556
|
|
30557
|
+
// Utilities
|
30558
|
+
|
30559
|
+
// Types
|
30560
|
+
|
30561
|
+
const makeMaskProps = propsFactory({
|
30562
|
+
mask: [String, Object],
|
30563
|
+
returnMaskedValue: Boolean
|
30564
|
+
}, 'mask');
|
30565
|
+
const defaultDelimiters = /[-!$%^&*()_+|~=`{}[\]:";'<>?,./\\ ]/;
|
30566
|
+
const presets = {
|
30567
|
+
'credit-card': '#### - #### - #### - ####',
|
30568
|
+
date: '##/##/####',
|
30569
|
+
'date-time': '##/##/#### ##:##',
|
30570
|
+
'iso-date': '####-##-##',
|
30571
|
+
'iso-date-time': '####-##-## ##:##',
|
30572
|
+
phone: '(###) ### - ####',
|
30573
|
+
social: '###-##-####',
|
30574
|
+
time: '##:##',
|
30575
|
+
'time-with-seconds': '##:##:##'
|
30576
|
+
};
|
30577
|
+
function isMaskDelimiter(char) {
|
30578
|
+
return char ? defaultDelimiters.test(char) : false;
|
30579
|
+
}
|
30580
|
+
const defaultTokens = {
|
30581
|
+
'#': {
|
30582
|
+
pattern: /[0-9]/
|
30583
|
+
},
|
30584
|
+
A: {
|
30585
|
+
pattern: /[A-Z]/i,
|
30586
|
+
convert: v => v.toUpperCase()
|
30587
|
+
},
|
30588
|
+
a: {
|
30589
|
+
pattern: /[a-z]/i,
|
30590
|
+
convert: v => v.toLowerCase()
|
30591
|
+
},
|
30592
|
+
N: {
|
30593
|
+
pattern: /[0-9A-Z]/i,
|
30594
|
+
convert: v => v.toUpperCase()
|
30595
|
+
},
|
30596
|
+
n: {
|
30597
|
+
pattern: /[0-9a-z]/i,
|
30598
|
+
convert: v => v.toLowerCase()
|
30599
|
+
},
|
30600
|
+
X: {
|
30601
|
+
pattern: defaultDelimiters
|
30602
|
+
}
|
30603
|
+
};
|
30604
|
+
function useMask(props, inputRef) {
|
30605
|
+
const mask = computed(() => {
|
30606
|
+
if (typeof props.mask === 'string') {
|
30607
|
+
if (props.mask in presets) return presets[props.mask];
|
30608
|
+
return props.mask;
|
30609
|
+
}
|
30610
|
+
return props.mask?.mask ?? '';
|
30611
|
+
});
|
30612
|
+
const tokens = computed(() => {
|
30613
|
+
return {
|
30614
|
+
...defaultTokens,
|
30615
|
+
...(isObject(props.mask) ? props.mask.tokens : null)
|
30616
|
+
};
|
30617
|
+
});
|
30618
|
+
const selection = shallowRef(0);
|
30619
|
+
const lazySelection = shallowRef(0);
|
30620
|
+
function isMask(char) {
|
30621
|
+
return char in tokens.value;
|
30622
|
+
}
|
30623
|
+
function maskValidates(mask, char) {
|
30624
|
+
if (char == null || !isMask(mask)) return false;
|
30625
|
+
const item = tokens.value[mask];
|
30626
|
+
if (item.pattern) return item.pattern.test(char);
|
30627
|
+
return item.test(char);
|
30628
|
+
}
|
30629
|
+
function convert(mask, char) {
|
30630
|
+
const item = tokens.value[mask];
|
30631
|
+
return item.convert ? item.convert(char) : char;
|
30632
|
+
}
|
30633
|
+
function maskText(text) {
|
30634
|
+
const trimmedText = text?.trim().replace(/\s+/g, ' ');
|
30635
|
+
if (trimmedText == null) return '';
|
30636
|
+
if (!mask.value.length || !trimmedText.length) return trimmedText;
|
30637
|
+
let textIndex = 0;
|
30638
|
+
let maskIndex = 0;
|
30639
|
+
let newText = '';
|
30640
|
+
while (maskIndex < mask.value.length) {
|
30641
|
+
const mchar = mask.value[maskIndex];
|
30642
|
+
const tchar = trimmedText[textIndex];
|
30643
|
+
|
30644
|
+
// Escaped character in mask, the next mask character is inserted
|
30645
|
+
if (mchar === '\\') {
|
30646
|
+
newText += mask.value[maskIndex + 1];
|
30647
|
+
maskIndex += 2;
|
30648
|
+
continue;
|
30649
|
+
}
|
30650
|
+
if (!isMask(mchar)) {
|
30651
|
+
newText += mchar;
|
30652
|
+
if (tchar === mchar) {
|
30653
|
+
textIndex++;
|
30654
|
+
}
|
30655
|
+
} else if (maskValidates(mchar, tchar)) {
|
30656
|
+
newText += convert(mchar, tchar);
|
30657
|
+
textIndex++;
|
30658
|
+
} else {
|
30659
|
+
break;
|
30660
|
+
}
|
30661
|
+
maskIndex++;
|
30662
|
+
}
|
30663
|
+
return newText;
|
30664
|
+
}
|
30665
|
+
function unmaskText(text) {
|
30666
|
+
if (text == null) return null;
|
30667
|
+
if (!mask.value.length || !text.length) return text;
|
30668
|
+
let textIndex = 0;
|
30669
|
+
let maskIndex = 0;
|
30670
|
+
let newText = '';
|
30671
|
+
while (true) {
|
30672
|
+
const mchar = mask.value[maskIndex];
|
30673
|
+
const tchar = text[textIndex];
|
30674
|
+
if (tchar == null) break;
|
30675
|
+
if (mchar == null) {
|
30676
|
+
newText += tchar;
|
30677
|
+
textIndex++;
|
30678
|
+
continue;
|
30679
|
+
}
|
30680
|
+
|
30681
|
+
// Escaped character in mask, skip the next input character
|
30682
|
+
if (mchar === '\\') {
|
30683
|
+
if (tchar === mask.value[maskIndex + 1]) {
|
30684
|
+
textIndex++;
|
30685
|
+
}
|
30686
|
+
maskIndex += 2;
|
30687
|
+
continue;
|
30688
|
+
}
|
30689
|
+
if (maskValidates(mchar, tchar)) {
|
30690
|
+
// masked char
|
30691
|
+
newText += tchar;
|
30692
|
+
textIndex++;
|
30693
|
+
maskIndex++;
|
30694
|
+
continue;
|
30695
|
+
} else if (mchar !== tchar) {
|
30696
|
+
// input doesn't match mask, skip forward until it does
|
30697
|
+
while (true) {
|
30698
|
+
const mchar = mask.value[maskIndex++];
|
30699
|
+
if (mchar == null || maskValidates(mchar, tchar)) break;
|
30700
|
+
}
|
30701
|
+
continue;
|
30702
|
+
}
|
30703
|
+
textIndex++;
|
30704
|
+
maskIndex++;
|
30705
|
+
}
|
30706
|
+
return newText;
|
30707
|
+
}
|
30708
|
+
function setCaretPosition(newSelection) {
|
30709
|
+
selection.value = newSelection;
|
30710
|
+
inputRef.value && inputRef.value.setSelectionRange(selection.value, selection.value);
|
30711
|
+
}
|
30712
|
+
function resetSelections() {
|
30713
|
+
if (!inputRef.value?.selectionEnd) return;
|
30714
|
+
selection.value = inputRef.value.selectionEnd;
|
30715
|
+
lazySelection.value = 0;
|
30716
|
+
for (let index = 0; index < selection.value; index++) {
|
30717
|
+
isMaskDelimiter(inputRef.value.value[index]) || lazySelection.value++;
|
30718
|
+
}
|
30719
|
+
}
|
30720
|
+
function updateRange() {
|
30721
|
+
if (!inputRef.value) return;
|
30722
|
+
resetSelections();
|
30723
|
+
let selection = 0;
|
30724
|
+
const newValue = inputRef.value.value;
|
30725
|
+
if (newValue) {
|
30726
|
+
for (let index = 0; index < newValue.length; index++) {
|
30727
|
+
if (lazySelection.value <= 0) break;
|
30728
|
+
isMaskDelimiter(newValue[index]) || lazySelection.value--;
|
30729
|
+
selection++;
|
30730
|
+
}
|
30731
|
+
}
|
30732
|
+
setCaretPosition(selection);
|
30733
|
+
}
|
30734
|
+
return {
|
30735
|
+
updateRange,
|
30736
|
+
maskText,
|
30737
|
+
unmaskText
|
30738
|
+
};
|
30739
|
+
}
|
30740
|
+
|
30741
|
+
// Types
|
30742
|
+
|
30743
|
+
const makeVMaskInputProps = propsFactory({
|
30744
|
+
...makeVTextFieldProps(),
|
30745
|
+
...makeMaskProps()
|
30746
|
+
}, 'VMaskInput');
|
30747
|
+
const VMaskInput = genericComponent()({
|
30748
|
+
name: 'VMaskInput',
|
30749
|
+
props: makeVMaskInputProps(),
|
30750
|
+
emits: {
|
30751
|
+
'update:modelValue': val => true
|
30752
|
+
},
|
30753
|
+
setup(props, _ref) {
|
30754
|
+
let {
|
30755
|
+
slots,
|
30756
|
+
emit
|
30757
|
+
} = _ref;
|
30758
|
+
const vTextFieldRef = ref();
|
30759
|
+
const {
|
30760
|
+
maskText,
|
30761
|
+
updateRange,
|
30762
|
+
unmaskText
|
30763
|
+
} = useMask(props, vTextFieldRef);
|
30764
|
+
const returnMaskedValue = computed(() => props.mask && props.returnMaskedValue);
|
30765
|
+
const model = useProxiedModel(props, 'modelValue', undefined,
|
30766
|
+
// Always display masked value in input when mask is applied
|
30767
|
+
val => props.mask ? maskText(unmaskText(val)) : val, val => {
|
30768
|
+
if (props.mask) {
|
30769
|
+
const valueBeforeChange = unmaskText(model.value);
|
30770
|
+
// E.g. mask is #-# and the input value is '2-23'
|
30771
|
+
// model-value should be enforced to '2-2'
|
30772
|
+
const enforcedMaskedValue = maskText(unmaskText(val));
|
30773
|
+
const newUnmaskedValue = unmaskText(enforcedMaskedValue);
|
30774
|
+
if (newUnmaskedValue === valueBeforeChange) {
|
30775
|
+
vTextFieldRef.value.value = enforcedMaskedValue;
|
30776
|
+
}
|
30777
|
+
val = newUnmaskedValue;
|
30778
|
+
updateRange();
|
30779
|
+
return returnMaskedValue.value ? maskText(val) : val;
|
30780
|
+
}
|
30781
|
+
return val;
|
30782
|
+
});
|
30783
|
+
onBeforeMount(() => {
|
30784
|
+
if (props.returnMaskedValue) {
|
30785
|
+
emit('update:modelValue', model.value);
|
30786
|
+
}
|
30787
|
+
});
|
30788
|
+
useRender(() => {
|
30789
|
+
const textFieldProps = VTextField.filterProps(props);
|
30790
|
+
return createVNode(VTextField, mergeProps(textFieldProps, {
|
30791
|
+
"modelValue": model.value,
|
30792
|
+
"onUpdate:modelValue": $event => model.value = $event,
|
30793
|
+
"ref": vTextFieldRef
|
30794
|
+
}), {
|
30795
|
+
...slots
|
30796
|
+
});
|
30797
|
+
});
|
30798
|
+
return forwardRefs({}, vTextFieldRef);
|
30799
|
+
}
|
30800
|
+
});
|
30801
|
+
|
30493
30802
|
// Types
|
30494
30803
|
|
30495
30804
|
const makeVStepperVerticalActionsProps = propsFactory({
|
@@ -31995,6 +32304,7 @@ var components = /*#__PURE__*/Object.freeze({
|
|
31995
32304
|
VListSubheader: VListSubheader,
|
31996
32305
|
VLocaleProvider: VLocaleProvider,
|
31997
32306
|
VMain: VMain,
|
32307
|
+
VMaskInput: VMaskInput,
|
31998
32308
|
VMenu: VMenu,
|
31999
32309
|
VMessages: VMessages,
|
32000
32310
|
VNavigationDrawer: VNavigationDrawer,
|
@@ -32392,7 +32702,7 @@ function createVuetify$1() {
|
|
32392
32702
|
};
|
32393
32703
|
});
|
32394
32704
|
}
|
32395
|
-
const version$1 = "3.8.9-dev.2025-06-
|
32705
|
+
const version$1 = "3.8.9-dev.2025-06-13";
|
32396
32706
|
createVuetify$1.version = version$1;
|
32397
32707
|
|
32398
32708
|
// Vue's inject() can only be used in setup
|
@@ -32690,7 +33000,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
32690
33000
|
|
32691
33001
|
/* eslint-disable local-rules/sort-imports */
|
32692
33002
|
|
32693
|
-
const version = "3.8.9-dev.2025-06-
|
33003
|
+
const version = "3.8.9-dev.2025-06-13";
|
32694
33004
|
|
32695
33005
|
/* eslint-disable local-rules/sort-imports */
|
32696
33006
|
|