@vuetify/nightly 3.9.2-master.2025-07-29 → 3.9.3-dev.2025-07-30
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 +6 -62
- package/dist/json/attributes.json +4301 -4281
- package/dist/json/importMap-labs.json +26 -26
- package/dist/json/importMap.json +188 -188
- package/dist/json/tags.json +5 -0
- package/dist/json/web-types.json +7597 -7527
- package/dist/vuetify-labs.cjs +228 -33
- package/dist/vuetify-labs.css +5466 -5464
- package/dist/vuetify-labs.d.ts +134 -71
- package/dist/vuetify-labs.esm.js +228 -33
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +228 -33
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.cjs +190 -24
- package/dist/vuetify.cjs.map +1 -1
- package/dist/vuetify.css +5163 -5161
- package/dist/vuetify.d.ts +124 -71
- package/dist/vuetify.esm.js +190 -24
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +190 -24
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +731 -708
- package/dist/vuetify.min.js.map +1 -1
- package/lib/components/VAutocomplete/VAutocomplete.js +1 -0
- package/lib/components/VAutocomplete/VAutocomplete.js.map +1 -1
- package/lib/components/VCombobox/VCombobox.js +11 -6
- package/lib/components/VCombobox/VCombobox.js.map +1 -1
- package/lib/components/VFileInput/VFileInput.d.ts +15 -0
- package/lib/components/VFileInput/VFileInput.js +38 -9
- package/lib/components/VFileInput/VFileInput.js.map +1 -1
- package/lib/components/VList/VList.js +2 -1
- package/lib/components/VList/VList.js.map +1 -1
- package/lib/components/VList/VListItem.js +7 -1
- package/lib/components/VList/VListItem.js.map +1 -1
- package/lib/components/VProgressLinear/VProgressLinear.css +1 -1
- package/lib/components/VProgressLinear/VProgressLinear.d.ts +75 -0
- package/lib/components/VProgressLinear/VProgressLinear.js +32 -6
- package/lib/components/VProgressLinear/VProgressLinear.js.map +1 -1
- package/lib/components/VProgressLinear/VProgressLinear.sass +1 -1
- package/lib/components/VProgressLinear/chunks.d.ts +55 -0
- package/lib/components/VProgressLinear/chunks.js +62 -0
- package/lib/components/VProgressLinear/chunks.js.map +1 -0
- package/lib/components/VSelect/VSelect.js +1 -0
- package/lib/components/VSelect/VSelect.js.map +1 -1
- package/lib/composables/fileFilter.d.ts +18 -0
- package/lib/composables/fileFilter.js +38 -0
- package/lib/composables/fileFilter.js.map +1 -0
- package/lib/composables/theme.d.ts +1 -0
- package/lib/composables/theme.js +3 -1
- package/lib/composables/theme.js.map +1 -1
- package/lib/entry-bundler.js +1 -1
- package/lib/entry-bundler.js.map +1 -1
- package/lib/framework.d.ts +72 -71
- package/lib/framework.js +1 -1
- package/lib/framework.js.map +1 -1
- package/lib/labs/VFileUpload/VFileUpload.d.ts +15 -0
- package/lib/labs/VFileUpload/VFileUpload.js +39 -9
- package/lib/labs/VFileUpload/VFileUpload.js.map +1 -1
- package/package.json +1 -1
package/dist/vuetify-labs.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* Vuetify v3.9.
|
2
|
+
* Vuetify v3.9.3-dev.2025-07-30
|
3
3
|
* Forged by John Leider
|
4
4
|
* Released under the MIT License.
|
5
5
|
*/
|
@@ -2695,6 +2695,7 @@
|
|
2695
2695
|
return acc;
|
2696
2696
|
});
|
2697
2697
|
const current = vue.toRef(() => computedThemes.value[name.value]);
|
2698
|
+
const isSystem = vue.toRef(() => _name.value === 'system');
|
2698
2699
|
const styles = vue.computed(() => {
|
2699
2700
|
const lines = [];
|
2700
2701
|
const important = parsedOptions.unimportant ? '' : ' !important';
|
@@ -2782,7 +2783,7 @@
|
|
2782
2783
|
}
|
2783
2784
|
}
|
2784
2785
|
function change(themeName) {
|
2785
|
-
if (!themeNames.value.includes(themeName)) {
|
2786
|
+
if (themeName !== 'system' && !themeNames.value.includes(themeName)) {
|
2786
2787
|
consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
|
2787
2788
|
return;
|
2788
2789
|
}
|
@@ -2815,6 +2816,7 @@
|
|
2815
2816
|
cycle,
|
2816
2817
|
toggle,
|
2817
2818
|
isDisabled: parsedOptions.isDisabled,
|
2819
|
+
isSystem,
|
2818
2820
|
name,
|
2819
2821
|
themes,
|
2820
2822
|
current,
|
@@ -5254,6 +5256,69 @@
|
|
5254
5256
|
};
|
5255
5257
|
}
|
5256
5258
|
|
5259
|
+
// Utilities
|
5260
|
+
|
5261
|
+
// Types
|
5262
|
+
|
5263
|
+
// Composables
|
5264
|
+
const makeChunksProps = propsFactory({
|
5265
|
+
chunkCount: {
|
5266
|
+
type: [Number, String],
|
5267
|
+
default: null
|
5268
|
+
},
|
5269
|
+
chunkWidth: {
|
5270
|
+
type: [Number, String],
|
5271
|
+
default: null
|
5272
|
+
},
|
5273
|
+
chunkGap: {
|
5274
|
+
type: [Number, String],
|
5275
|
+
default: 4
|
5276
|
+
}
|
5277
|
+
}, 'chunks');
|
5278
|
+
function useChunks(props, containerWidth) {
|
5279
|
+
const hasChunks = vue.toRef(() => !!props.chunkCount || !!props.chunkWidth);
|
5280
|
+
const chunkWidth = vue.computed(() => {
|
5281
|
+
const containerSize = vue.toValue(containerWidth);
|
5282
|
+
if (!containerSize) {
|
5283
|
+
return 0;
|
5284
|
+
}
|
5285
|
+
if (!props.chunkCount) {
|
5286
|
+
return Number(props.chunkWidth);
|
5287
|
+
}
|
5288
|
+
const count = Number(props.chunkCount);
|
5289
|
+
const availableWidth = containerSize - Number(props.chunkGap) * (count - 1);
|
5290
|
+
return availableWidth / count;
|
5291
|
+
});
|
5292
|
+
const chunkGap = vue.toRef(() => Number(props.chunkGap));
|
5293
|
+
const chunksMaskStyles = vue.computed(() => {
|
5294
|
+
if (!hasChunks.value) {
|
5295
|
+
return {};
|
5296
|
+
}
|
5297
|
+
const chunkGapPx = convertToUnit(chunkGap.value);
|
5298
|
+
const chunkWidthPx = convertToUnit(chunkWidth.value);
|
5299
|
+
return {
|
5300
|
+
maskRepeat: 'repeat-x',
|
5301
|
+
maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
|
5302
|
+
maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
|
5303
|
+
};
|
5304
|
+
});
|
5305
|
+
function snapValueToChunk(val) {
|
5306
|
+
const containerSize = vue.toValue(containerWidth);
|
5307
|
+
if (!containerSize) {
|
5308
|
+
return val;
|
5309
|
+
}
|
5310
|
+
const gapRelativeSize = 100 * chunkGap.value / containerSize;
|
5311
|
+
const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;
|
5312
|
+
const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize);
|
5313
|
+
return clamp(0, filledChunks * chunkRelativeSize - gapRelativeSize / 2, 100);
|
5314
|
+
}
|
5315
|
+
return {
|
5316
|
+
hasChunks,
|
5317
|
+
chunksMaskStyles,
|
5318
|
+
snapValueToChunk
|
5319
|
+
};
|
5320
|
+
}
|
5321
|
+
|
5257
5322
|
const makeVProgressLinearProps = propsFactory({
|
5258
5323
|
absolute: Boolean,
|
5259
5324
|
active: {
|
@@ -5288,6 +5353,7 @@
|
|
5288
5353
|
stream: Boolean,
|
5289
5354
|
striped: Boolean,
|
5290
5355
|
roundedBar: Boolean,
|
5356
|
+
...makeChunksProps(),
|
5291
5357
|
...makeComponentProps(),
|
5292
5358
|
...makeLocationProps({
|
5293
5359
|
location: 'top'
|
@@ -5306,6 +5372,7 @@
|
|
5306
5372
|
let {
|
5307
5373
|
slots
|
5308
5374
|
} = _ref;
|
5375
|
+
const root = vue.ref();
|
5309
5376
|
const progress = useProxiedModel(props, 'modelValue');
|
5310
5377
|
const {
|
5311
5378
|
isRtl,
|
@@ -5347,6 +5414,24 @@
|
|
5347
5414
|
const isReversed = vue.computed(() => isRtl.value !== props.reverse);
|
5348
5415
|
const transition = vue.computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
|
5349
5416
|
const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
|
5417
|
+
const containerWidth = vue.shallowRef(0);
|
5418
|
+
const {
|
5419
|
+
hasChunks,
|
5420
|
+
chunksMaskStyles,
|
5421
|
+
snapValueToChunk
|
5422
|
+
} = useChunks(props, containerWidth);
|
5423
|
+
useToggleScope(hasChunks, () => {
|
5424
|
+
const {
|
5425
|
+
resizeRef
|
5426
|
+
} = useResizeObserver(entries => containerWidth.value = entries[0].contentRect.width);
|
5427
|
+
vue.watchEffect(() => resizeRef.value = root.value);
|
5428
|
+
});
|
5429
|
+
const bufferWidth = vue.computed(() => {
|
5430
|
+
return hasChunks.value ? snapValueToChunk(normalizedBuffer.value) : normalizedBuffer.value;
|
5431
|
+
});
|
5432
|
+
const barWidth = vue.computed(() => {
|
5433
|
+
return hasChunks.value ? snapValueToChunk(normalizedValue.value) : normalizedValue.value;
|
5434
|
+
});
|
5350
5435
|
function handleClick(e) {
|
5351
5436
|
if (!intersectionRef.value) return;
|
5352
5437
|
const {
|
@@ -5357,8 +5442,11 @@
|
|
5357
5442
|
const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
|
5358
5443
|
progress.value = Math.round(value / width * max.value);
|
5359
5444
|
}
|
5445
|
+
vue.watchEffect(() => {
|
5446
|
+
intersectionRef.value = root.value;
|
5447
|
+
});
|
5360
5448
|
useRender(() => vue.createVNode(props.tag, {
|
5361
|
-
"ref":
|
5449
|
+
"ref": root,
|
5362
5450
|
"class": vue.normalizeClass(['v-progress-linear', {
|
5363
5451
|
'v-progress-linear--absolute': props.absolute,
|
5364
5452
|
'v-progress-linear--active': props.active && isIntersecting.value,
|
@@ -5374,7 +5462,7 @@
|
|
5374
5462
|
height: props.active ? convertToUnit(height.value) : 0,
|
5375
5463
|
'--v-progress-linear-height': convertToUnit(height.value),
|
5376
5464
|
...(props.absolute ? locationStyles.value : {})
|
5377
|
-
}, props.style]),
|
5465
|
+
}, chunksMaskStyles.value, props.style]),
|
5378
5466
|
"role": "progressbar",
|
5379
5467
|
"aria-hidden": props.active ? 'false' : 'true',
|
5380
5468
|
"aria-valuemin": "0",
|
@@ -5404,7 +5492,7 @@
|
|
5404
5492
|
"class": vue.normalizeClass(['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined]),
|
5405
5493
|
"style": vue.normalizeStyle([bufferColorStyles.value, {
|
5406
5494
|
opacity: parseFloat(props.bufferOpacity),
|
5407
|
-
width: convertToUnit(
|
5495
|
+
width: convertToUnit(bufferWidth.value, '%')
|
5408
5496
|
}])
|
5409
5497
|
}, null), vue.createVNode(vue.Transition, {
|
5410
5498
|
"name": transition.value
|
@@ -5412,7 +5500,7 @@
|
|
5412
5500
|
default: () => [!props.indeterminate ? vue.createElementVNode("div", {
|
5413
5501
|
"class": vue.normalizeClass(['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined]),
|
5414
5502
|
"style": vue.normalizeStyle([barColorStyles.value, {
|
5415
|
-
width: convertToUnit(
|
5503
|
+
width: convertToUnit(barWidth.value, '%')
|
5416
5504
|
}])
|
5417
5505
|
}, null) : vue.createElementVNode("div", {
|
5418
5506
|
"class": "v-progress-linear__indeterminate"
|
@@ -9616,6 +9704,11 @@
|
|
9616
9704
|
const isLink = vue.toRef(() => props.link !== false && link.isLink.value);
|
9617
9705
|
const isSelectable = vue.computed(() => !!list && (root.selectable.value || root.activatable.value || props.value != null));
|
9618
9706
|
const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || isSelectable.value));
|
9707
|
+
const role = vue.computed(() => list ? isSelectable.value ? 'option' : 'listitem' : undefined);
|
9708
|
+
const ariaSelected = vue.computed(() => {
|
9709
|
+
if (!isSelectable.value) return undefined;
|
9710
|
+
return root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value;
|
9711
|
+
});
|
9619
9712
|
const roundedProps = vue.toRef(() => props.rounded || props.nav);
|
9620
9713
|
const color = vue.toRef(() => props.color ?? props.activeColor);
|
9621
9714
|
const variantProps = vue.toRef(() => ({
|
@@ -9719,7 +9812,8 @@
|
|
9719
9812
|
}, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
|
9720
9813
|
"style": [colorStyles.value, dimensionStyles.value, props.style],
|
9721
9814
|
"tabindex": isClickable.value ? list ? -2 : 0 : undefined,
|
9722
|
-
"aria-selected":
|
9815
|
+
"aria-selected": ariaSelected.value,
|
9816
|
+
"role": role.value,
|
9723
9817
|
"onClick": onClick,
|
9724
9818
|
"onKeydown": isClickable.value && !isLink.value && onKeyDown
|
9725
9819
|
}, link.linkProps), {
|
@@ -10219,6 +10313,7 @@
|
|
10219
10313
|
const activeColor = vue.toRef(() => props.activeColor);
|
10220
10314
|
const baseColor = vue.toRef(() => props.baseColor);
|
10221
10315
|
const color = vue.toRef(() => props.color);
|
10316
|
+
const isSelectable = vue.toRef(() => props.selectable || props.activatable);
|
10222
10317
|
createList({
|
10223
10318
|
filterable: props.filterable
|
10224
10319
|
});
|
@@ -10290,7 +10385,7 @@
|
|
10290
10385
|
}, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class]),
|
10291
10386
|
"style": vue.normalizeStyle([backgroundColorStyles.value, dimensionStyles.value, props.style]),
|
10292
10387
|
"tabindex": props.disabled ? -1 : 0,
|
10293
|
-
"role":
|
10388
|
+
"role": isSelectable.value ? 'listbox' : 'list',
|
10294
10389
|
"aria-activedescendant": undefined,
|
10295
10390
|
"onFocusin": onFocusin,
|
10296
10391
|
"onFocusout": onFocusout,
|
@@ -13369,6 +13464,7 @@
|
|
13369
13464
|
"onKeydown": onListKeydown,
|
13370
13465
|
"onFocusin": onFocusin,
|
13371
13466
|
"tabindex": "-1",
|
13467
|
+
"selectable": true,
|
13372
13468
|
"aria-live": "polite",
|
13373
13469
|
"aria-label": `${props.label}-list`,
|
13374
13470
|
"color": props.itemColor ?? props.color
|
@@ -13988,6 +14084,7 @@
|
|
13988
14084
|
"onFocusin": onFocusin,
|
13989
14085
|
"onFocusout": onFocusout,
|
13990
14086
|
"tabindex": "-1",
|
14087
|
+
"selectable": true,
|
13991
14088
|
"aria-live": "polite",
|
13992
14089
|
"color": props.itemColor ?? props.color
|
13993
14090
|
}, listEvents, props.listProps), {
|
@@ -18801,19 +18898,23 @@
|
|
18801
18898
|
get: () => {
|
18802
18899
|
return _search.value;
|
18803
18900
|
},
|
18804
|
-
set: val => {
|
18901
|
+
set: async val => {
|
18805
18902
|
_search.value = val ?? '';
|
18806
18903
|
if (!props.multiple && !hasSelectionSlot.value) {
|
18807
18904
|
model.value = [transformItem$3(props, val)];
|
18808
18905
|
vue.nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0));
|
18809
18906
|
}
|
18810
18907
|
if (val && props.multiple && props.delimiters?.length) {
|
18811
|
-
const
|
18908
|
+
const signsToMatch = props.delimiters.map(escapeForRegex).join('|');
|
18909
|
+
const values = val.split(new RegExp(`(?:${signsToMatch})+`));
|
18812
18910
|
if (values.length > 1) {
|
18813
|
-
|
18911
|
+
for (let v of values) {
|
18814
18912
|
v = v.trim();
|
18815
|
-
if (v)
|
18816
|
-
|
18913
|
+
if (v) {
|
18914
|
+
select(transformItem$3(props, v));
|
18915
|
+
await vue.nextTick();
|
18916
|
+
}
|
18917
|
+
}
|
18817
18918
|
_search.value = '';
|
18818
18919
|
}
|
18819
18920
|
}
|
@@ -19095,6 +19196,7 @@
|
|
19095
19196
|
"selected": selectedValues.value,
|
19096
19197
|
"selectStrategy": props.multiple ? 'independent' : 'single-independent',
|
19097
19198
|
"onMousedown": e => e.preventDefault(),
|
19199
|
+
"selectable": true,
|
19098
19200
|
"onKeydown": onListKeydown,
|
19099
19201
|
"onFocusin": onFocusin,
|
19100
19202
|
"onFocusout": onFocusout,
|
@@ -24211,6 +24313,42 @@
|
|
24211
24313
|
return item.isDirectory ? `${path}/${item.name}` : path;
|
24212
24314
|
}
|
24213
24315
|
|
24316
|
+
// Utilities
|
24317
|
+
// Composables
|
24318
|
+
const makeFileFilterProps = propsFactory({
|
24319
|
+
filterByType: String
|
24320
|
+
}, 'file-accept');
|
24321
|
+
function useFileFilter(props) {
|
24322
|
+
const fileFilter = vue.computed(() => props.filterByType ? createFilter(props.filterByType) : null);
|
24323
|
+
function filterAccepted(files) {
|
24324
|
+
if (fileFilter.value) {
|
24325
|
+
const accepted = files.filter(fileFilter.value);
|
24326
|
+
return {
|
24327
|
+
accepted,
|
24328
|
+
rejected: files.filter(f => !accepted.includes(f))
|
24329
|
+
};
|
24330
|
+
}
|
24331
|
+
return {
|
24332
|
+
accepted: files,
|
24333
|
+
rejected: []
|
24334
|
+
};
|
24335
|
+
}
|
24336
|
+
return {
|
24337
|
+
filterAccepted
|
24338
|
+
};
|
24339
|
+
}
|
24340
|
+
function createFilter(v) {
|
24341
|
+
const types = v.split(',').map(x => x.trim().toLowerCase());
|
24342
|
+
const extensionsToMatch = types.filter(x => x.startsWith('.'));
|
24343
|
+
const wildcards = types.filter(x => x.endsWith('/*'));
|
24344
|
+
const typesToMatch = types.filter(x => !extensionsToMatch.includes(x) && !wildcards.includes(x));
|
24345
|
+
return file => {
|
24346
|
+
const extension = file.name.split('.').at(-1)?.toLowerCase() ?? '';
|
24347
|
+
const typeGroup = file.type.split('/').at(0)?.toLowerCase() ?? '';
|
24348
|
+
return typesToMatch.includes(file.type) || extensionsToMatch.includes(`.${extension}`) || wildcards.includes(`${typeGroup}/*`);
|
24349
|
+
};
|
24350
|
+
}
|
24351
|
+
|
24214
24352
|
// Types
|
24215
24353
|
|
24216
24354
|
const makeVFileInputProps = propsFactory({
|
@@ -24243,6 +24381,7 @@
|
|
24243
24381
|
return wrapInArray(val).every(v => v != null && typeof v === 'object');
|
24244
24382
|
}
|
24245
24383
|
},
|
24384
|
+
...makeFileFilterProps(),
|
24246
24385
|
...makeVFieldProps({
|
24247
24386
|
clearable: true
|
24248
24387
|
})
|
@@ -24255,7 +24394,8 @@
|
|
24255
24394
|
'click:control': e => true,
|
24256
24395
|
'mousedown:control': e => true,
|
24257
24396
|
'update:focused': focused => true,
|
24258
|
-
'update:modelValue': files => true
|
24397
|
+
'update:modelValue': files => true,
|
24398
|
+
rejected: files => true
|
24259
24399
|
},
|
24260
24400
|
setup(props, _ref) {
|
24261
24401
|
let {
|
@@ -24266,6 +24406,9 @@
|
|
24266
24406
|
const {
|
24267
24407
|
t
|
24268
24408
|
} = useLocale();
|
24409
|
+
const {
|
24410
|
+
filterAccepted
|
24411
|
+
} = useFileFilter(props);
|
24269
24412
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
|
24270
24413
|
const {
|
24271
24414
|
isFocused,
|
@@ -24339,14 +24482,38 @@
|
|
24339
24482
|
e.stopImmediatePropagation();
|
24340
24483
|
isDragging.value = false;
|
24341
24484
|
if (!inputRef.value || !hasFilesOrFolders(e)) return;
|
24485
|
+
const allDroppedFiles = await handleDrop(e);
|
24486
|
+
selectAccepted(allDroppedFiles);
|
24487
|
+
}
|
24488
|
+
function onFileSelection(e) {
|
24489
|
+
if (!e.target || e.repack) return; // prevent loop
|
24490
|
+
|
24491
|
+
if (!props.filterByType) {
|
24492
|
+
const target = e.target;
|
24493
|
+
model.value = [...(target.files ?? [])];
|
24494
|
+
} else {
|
24495
|
+
selectAccepted([...e.target.files]);
|
24496
|
+
}
|
24497
|
+
}
|
24498
|
+
function selectAccepted(files) {
|
24342
24499
|
const dataTransfer = new DataTransfer();
|
24343
|
-
|
24500
|
+
const {
|
24501
|
+
accepted,
|
24502
|
+
rejected
|
24503
|
+
} = filterAccepted(files);
|
24504
|
+
if (rejected.length) {
|
24505
|
+
emit('rejected', rejected);
|
24506
|
+
}
|
24507
|
+
for (const file of accepted) {
|
24344
24508
|
dataTransfer.items.add(file);
|
24345
24509
|
}
|
24346
24510
|
inputRef.value.files = dataTransfer.files;
|
24347
|
-
|
24511
|
+
model.value = [...dataTransfer.files];
|
24512
|
+
const event = new Event('change', {
|
24348
24513
|
bubbles: true
|
24349
|
-
})
|
24514
|
+
});
|
24515
|
+
event.repack = true;
|
24516
|
+
inputRef.value.dispatchEvent(event);
|
24350
24517
|
}
|
24351
24518
|
vue.watch(model, newValue => {
|
24352
24519
|
const hasModelReset = !Array.isArray(newValue) || !newValue.length;
|
@@ -24363,6 +24530,8 @@
|
|
24363
24530
|
...inputProps
|
24364
24531
|
} = VInput.filterProps(props);
|
24365
24532
|
const fieldProps = VField.filterProps(props);
|
24533
|
+
const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
|
24534
|
+
const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
|
24366
24535
|
return vue.createVNode(VInput, vue.mergeProps({
|
24367
24536
|
"ref": vInputRef,
|
24368
24537
|
"modelValue": props.multiple ? model.value : model.value[0],
|
@@ -24418,6 +24587,7 @@
|
|
24418
24587
|
return vue.createElementVNode(vue.Fragment, null, [vue.createElementVNode("input", vue.mergeProps({
|
24419
24588
|
"ref": inputRef,
|
24420
24589
|
"type": "file",
|
24590
|
+
"accept": inputAccept,
|
24421
24591
|
"readonly": isReadonly.value,
|
24422
24592
|
"disabled": isDisabled.value,
|
24423
24593
|
"multiple": props.multiple,
|
@@ -24427,11 +24597,7 @@
|
|
24427
24597
|
if (isReadonly.value) e.preventDefault();
|
24428
24598
|
onFocus();
|
24429
24599
|
},
|
24430
|
-
"onChange":
|
24431
|
-
if (!e.target) return;
|
24432
|
-
const target = e.target;
|
24433
|
-
model.value = [...(target.files ?? [])];
|
24434
|
-
},
|
24600
|
+
"onChange": onFileSelection,
|
24435
24601
|
"onDragleave": onDragleave,
|
24436
24602
|
"onFocus": onFocus,
|
24437
24603
|
"onBlur": blur
|
@@ -31951,6 +32117,7 @@
|
|
31951
32117
|
},
|
31952
32118
|
showSize: Boolean,
|
31953
32119
|
name: String,
|
32120
|
+
...makeFileFilterProps(),
|
31954
32121
|
...makeDelayProps(),
|
31955
32122
|
...makeDensityProps(),
|
31956
32123
|
...pick(makeVDividerProps({
|
@@ -31963,11 +32130,13 @@
|
|
31963
32130
|
inheritAttrs: false,
|
31964
32131
|
props: makeVFileUploadProps(),
|
31965
32132
|
emits: {
|
31966
|
-
'update:modelValue': files => true
|
32133
|
+
'update:modelValue': files => true,
|
32134
|
+
rejected: files => true
|
31967
32135
|
},
|
31968
32136
|
setup(props, _ref) {
|
31969
32137
|
let {
|
31970
32138
|
attrs,
|
32139
|
+
emit,
|
31971
32140
|
slots
|
31972
32141
|
} = _ref;
|
31973
32142
|
const {
|
@@ -31976,6 +32145,9 @@
|
|
31976
32145
|
const {
|
31977
32146
|
densityClasses
|
31978
32147
|
} = useDensity(props);
|
32148
|
+
const {
|
32149
|
+
filterAccepted
|
32150
|
+
} = useFileFilter(props);
|
31979
32151
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
|
31980
32152
|
const isDragging = vue.shallowRef(false);
|
31981
32153
|
const vSheetRef = vue.ref(null);
|
@@ -31997,14 +32169,38 @@
|
|
31997
32169
|
e.stopImmediatePropagation();
|
31998
32170
|
isDragging.value = false;
|
31999
32171
|
if (!inputRef.value) return;
|
32172
|
+
const allDroppedFiles = await handleDrop(e);
|
32173
|
+
selectAccepted(allDroppedFiles);
|
32174
|
+
}
|
32175
|
+
function onFileSelection(e) {
|
32176
|
+
if (!e.target || e.repack) return; // prevent loop
|
32177
|
+
|
32178
|
+
if (!props.filterByType) {
|
32179
|
+
const target = e.target;
|
32180
|
+
model.value = [...(target.files ?? [])];
|
32181
|
+
} else {
|
32182
|
+
selectAccepted([...e.target.files]);
|
32183
|
+
}
|
32184
|
+
}
|
32185
|
+
function selectAccepted(files) {
|
32000
32186
|
const dataTransfer = new DataTransfer();
|
32001
|
-
|
32187
|
+
const {
|
32188
|
+
accepted,
|
32189
|
+
rejected
|
32190
|
+
} = filterAccepted(files);
|
32191
|
+
if (rejected.length) {
|
32192
|
+
emit('rejected', rejected);
|
32193
|
+
}
|
32194
|
+
for (const file of accepted) {
|
32002
32195
|
dataTransfer.items.add(file);
|
32003
32196
|
}
|
32004
32197
|
inputRef.value.files = dataTransfer.files;
|
32005
|
-
|
32198
|
+
model.value = [...dataTransfer.files];
|
32199
|
+
const event = new Event('change', {
|
32006
32200
|
bubbles: true
|
32007
|
-
})
|
32201
|
+
});
|
32202
|
+
event.repack = true;
|
32203
|
+
inputRef.value.dispatchEvent(event);
|
32008
32204
|
}
|
32009
32205
|
function onClick() {
|
32010
32206
|
inputRef.value?.click();
|
@@ -32022,17 +32218,16 @@
|
|
32022
32218
|
const cardProps = VSheet.filterProps(props);
|
32023
32219
|
const dividerProps = VDivider.filterProps(props);
|
32024
32220
|
const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
|
32221
|
+
const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
|
32222
|
+
const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
|
32025
32223
|
const inputNode = vue.createElementVNode("input", vue.mergeProps({
|
32026
32224
|
"ref": inputRef,
|
32027
32225
|
"type": "file",
|
32226
|
+
"accept": inputAccept,
|
32028
32227
|
"disabled": props.disabled,
|
32029
32228
|
"multiple": props.multiple,
|
32030
32229
|
"name": props.name,
|
32031
|
-
"onChange":
|
32032
|
-
if (!e.target) return;
|
32033
|
-
const target = e.target;
|
32034
|
-
model.value = [...(target.files ?? [])];
|
32035
|
-
}
|
32230
|
+
"onChange": onFileSelection
|
32036
32231
|
}, inputAttrs), null);
|
32037
32232
|
return vue.createElementVNode(vue.Fragment, null, [vue.createVNode(VSheet, vue.mergeProps({
|
32038
32233
|
"ref": vSheetRef
|
@@ -35137,7 +35332,7 @@
|
|
35137
35332
|
};
|
35138
35333
|
});
|
35139
35334
|
}
|
35140
|
-
const version$1 = "3.9.
|
35335
|
+
const version$1 = "3.9.3-dev.2025-07-30";
|
35141
35336
|
createVuetify$1.version = version$1;
|
35142
35337
|
|
35143
35338
|
// Vue's inject() can only be used in setup
|
@@ -35435,7 +35630,7 @@
|
|
35435
35630
|
|
35436
35631
|
/* eslint-disable local-rules/sort-imports */
|
35437
35632
|
|
35438
|
-
const version = "3.9.
|
35633
|
+
const version = "3.9.3-dev.2025-07-30";
|
35439
35634
|
|
35440
35635
|
/* eslint-disable local-rules/sort-imports */
|
35441
35636
|
|