@vuetify/nightly 3.9.0-dev.2025-07-08 → 3.9.0-dev.2025-07-16
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 +14 -3
- package/dist/json/attributes.json +3826 -3806
- package/dist/json/importMap-labs.json +24 -24
- package/dist/json/importMap.json +168 -168
- package/dist/json/tags.json +5 -0
- package/dist/json/web-types.json +6992 -6922
- package/dist/vuetify-labs.cjs +216 -27
- package/dist/vuetify-labs.css +4659 -4657
- package/dist/vuetify-labs.d.ts +119 -57
- package/dist/vuetify-labs.esm.js +216 -27
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +216 -27
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.cjs +178 -18
- package/dist/vuetify.cjs.map +1 -1
- package/dist/vuetify.css +4036 -4034
- package/dist/vuetify.d.ts +109 -57
- package/dist/vuetify.esm.js +178 -18
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +178 -18
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +718 -696
- 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 +1 -0
- 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 +2 -2
- 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/entry-bundler.js +1 -1
- package/lib/framework.d.ts +57 -57
- package/lib/framework.js +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.cjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* Vuetify v3.9.0-dev.2025-07-
|
2
|
+
* Vuetify v3.9.0-dev.2025-07-16
|
3
3
|
* Forged by John Leider
|
4
4
|
* Released under the MIT License.
|
5
5
|
*/
|
@@ -5190,6 +5190,69 @@
|
|
5190
5190
|
};
|
5191
5191
|
}
|
5192
5192
|
|
5193
|
+
// Utilities
|
5194
|
+
|
5195
|
+
// Types
|
5196
|
+
|
5197
|
+
// Composables
|
5198
|
+
const makeChunksProps = propsFactory({
|
5199
|
+
chunkCount: {
|
5200
|
+
type: [Number, String],
|
5201
|
+
default: null
|
5202
|
+
},
|
5203
|
+
chunkWidth: {
|
5204
|
+
type: [Number, String],
|
5205
|
+
default: null
|
5206
|
+
},
|
5207
|
+
chunkGap: {
|
5208
|
+
type: [Number, String],
|
5209
|
+
default: 4
|
5210
|
+
}
|
5211
|
+
}, 'chunks');
|
5212
|
+
function useChunks(props, containerWidth) {
|
5213
|
+
const hasChunks = vue.toRef(() => !!props.chunkCount || !!props.chunkWidth);
|
5214
|
+
const chunkWidth = vue.computed(() => {
|
5215
|
+
const containerSize = vue.toValue(containerWidth);
|
5216
|
+
if (!containerSize) {
|
5217
|
+
return 0;
|
5218
|
+
}
|
5219
|
+
if (!props.chunkCount) {
|
5220
|
+
return Number(props.chunkWidth);
|
5221
|
+
}
|
5222
|
+
const count = Number(props.chunkCount);
|
5223
|
+
const availableWidth = containerSize - Number(props.chunkGap) * (count - 1);
|
5224
|
+
return availableWidth / count;
|
5225
|
+
});
|
5226
|
+
const chunkGap = vue.toRef(() => Number(props.chunkGap));
|
5227
|
+
const chunksMaskStyles = vue.computed(() => {
|
5228
|
+
if (!hasChunks.value) {
|
5229
|
+
return {};
|
5230
|
+
}
|
5231
|
+
const chunkGapPx = convertToUnit(chunkGap.value);
|
5232
|
+
const chunkWidthPx = convertToUnit(chunkWidth.value);
|
5233
|
+
return {
|
5234
|
+
maskRepeat: 'repeat-x',
|
5235
|
+
maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
|
5236
|
+
maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
|
5237
|
+
};
|
5238
|
+
});
|
5239
|
+
function snapValueToChunk(val) {
|
5240
|
+
const containerSize = vue.toValue(containerWidth);
|
5241
|
+
if (!containerSize) {
|
5242
|
+
return val;
|
5243
|
+
}
|
5244
|
+
const gapRelativeSize = 100 * chunkGap.value / containerSize;
|
5245
|
+
const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;
|
5246
|
+
const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize);
|
5247
|
+
return clamp(0, filledChunks * chunkRelativeSize - gapRelativeSize / 2, 100);
|
5248
|
+
}
|
5249
|
+
return {
|
5250
|
+
hasChunks,
|
5251
|
+
chunksMaskStyles,
|
5252
|
+
snapValueToChunk
|
5253
|
+
};
|
5254
|
+
}
|
5255
|
+
|
5193
5256
|
const makeVProgressLinearProps = propsFactory({
|
5194
5257
|
absolute: Boolean,
|
5195
5258
|
active: {
|
@@ -5224,6 +5287,7 @@
|
|
5224
5287
|
stream: Boolean,
|
5225
5288
|
striped: Boolean,
|
5226
5289
|
roundedBar: Boolean,
|
5290
|
+
...makeChunksProps(),
|
5227
5291
|
...makeComponentProps(),
|
5228
5292
|
...makeLocationProps({
|
5229
5293
|
location: 'top'
|
@@ -5242,6 +5306,7 @@
|
|
5242
5306
|
let {
|
5243
5307
|
slots
|
5244
5308
|
} = _ref;
|
5309
|
+
const root = vue.ref();
|
5245
5310
|
const progress = useProxiedModel(props, 'modelValue');
|
5246
5311
|
const {
|
5247
5312
|
isRtl,
|
@@ -5283,6 +5348,24 @@
|
|
5283
5348
|
const isReversed = vue.computed(() => isRtl.value !== props.reverse);
|
5284
5349
|
const transition = vue.computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
|
5285
5350
|
const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
|
5351
|
+
const containerWidth = vue.shallowRef(0);
|
5352
|
+
const {
|
5353
|
+
hasChunks,
|
5354
|
+
chunksMaskStyles,
|
5355
|
+
snapValueToChunk
|
5356
|
+
} = useChunks(props, containerWidth);
|
5357
|
+
useToggleScope(hasChunks, () => {
|
5358
|
+
const {
|
5359
|
+
resizeRef
|
5360
|
+
} = useResizeObserver(entries => containerWidth.value = entries[0].contentRect.width);
|
5361
|
+
vue.watchEffect(() => resizeRef.value = root.value);
|
5362
|
+
});
|
5363
|
+
const bufferWidth = vue.computed(() => {
|
5364
|
+
return hasChunks.value ? snapValueToChunk(normalizedBuffer.value) : normalizedBuffer.value;
|
5365
|
+
});
|
5366
|
+
const barWidth = vue.computed(() => {
|
5367
|
+
return hasChunks.value ? snapValueToChunk(normalizedValue.value) : normalizedValue.value;
|
5368
|
+
});
|
5286
5369
|
function handleClick(e) {
|
5287
5370
|
if (!intersectionRef.value) return;
|
5288
5371
|
const {
|
@@ -5293,8 +5376,11 @@
|
|
5293
5376
|
const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
|
5294
5377
|
progress.value = Math.round(value / width * max.value);
|
5295
5378
|
}
|
5379
|
+
vue.watchEffect(() => {
|
5380
|
+
intersectionRef.value = root.value;
|
5381
|
+
});
|
5296
5382
|
useRender(() => vue.createVNode(props.tag, {
|
5297
|
-
"ref":
|
5383
|
+
"ref": root,
|
5298
5384
|
"class": vue.normalizeClass(['v-progress-linear', {
|
5299
5385
|
'v-progress-linear--absolute': props.absolute,
|
5300
5386
|
'v-progress-linear--active': props.active && isIntersecting.value,
|
@@ -5309,7 +5395,7 @@
|
|
5309
5395
|
height: props.active ? convertToUnit(height.value) : 0,
|
5310
5396
|
'--v-progress-linear-height': convertToUnit(height.value),
|
5311
5397
|
...(props.absolute ? locationStyles.value : {})
|
5312
|
-
}, props.style]),
|
5398
|
+
}, chunksMaskStyles.value, props.style]),
|
5313
5399
|
"role": "progressbar",
|
5314
5400
|
"aria-hidden": props.active ? 'false' : 'true',
|
5315
5401
|
"aria-valuemin": "0",
|
@@ -5339,7 +5425,7 @@
|
|
5339
5425
|
"class": vue.normalizeClass(['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined]),
|
5340
5426
|
"style": vue.normalizeStyle([bufferColorStyles.value, {
|
5341
5427
|
opacity: parseFloat(props.bufferOpacity),
|
5342
|
-
width: convertToUnit(
|
5428
|
+
width: convertToUnit(bufferWidth.value, '%')
|
5343
5429
|
}])
|
5344
5430
|
}, null), vue.createVNode(vue.Transition, {
|
5345
5431
|
"name": transition.value
|
@@ -5347,7 +5433,7 @@
|
|
5347
5433
|
default: () => [!props.indeterminate ? vue.createElementVNode("div", {
|
5348
5434
|
"class": vue.normalizeClass(['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined]),
|
5349
5435
|
"style": vue.normalizeStyle([barColorStyles.value, {
|
5350
|
-
width: convertToUnit(
|
5436
|
+
width: convertToUnit(barWidth.value, '%')
|
5351
5437
|
}])
|
5352
5438
|
}, null) : vue.createElementVNode("div", {
|
5353
5439
|
"class": "v-progress-linear__indeterminate"
|
@@ -9562,6 +9648,11 @@
|
|
9562
9648
|
const isLink = vue.toRef(() => props.link !== false && link.isLink.value);
|
9563
9649
|
const isSelectable = vue.computed(() => !!list && (root.selectable.value || root.activatable.value || props.value != null));
|
9564
9650
|
const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || isSelectable.value));
|
9651
|
+
const role = vue.computed(() => list ? isSelectable.value ? 'option' : 'listitem' : undefined);
|
9652
|
+
const ariaSelected = vue.computed(() => {
|
9653
|
+
if (!isSelectable.value) return undefined;
|
9654
|
+
return root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value;
|
9655
|
+
});
|
9565
9656
|
const roundedProps = vue.toRef(() => props.rounded || props.nav);
|
9566
9657
|
const color = vue.toRef(() => props.color ?? props.activeColor);
|
9567
9658
|
const variantProps = vue.toRef(() => ({
|
@@ -9665,7 +9756,8 @@
|
|
9665
9756
|
}, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
|
9666
9757
|
"style": [colorStyles.value, dimensionStyles.value, props.style],
|
9667
9758
|
"tabindex": isClickable.value ? list ? -2 : 0 : undefined,
|
9668
|
-
"aria-selected":
|
9759
|
+
"aria-selected": ariaSelected.value,
|
9760
|
+
"role": role.value,
|
9669
9761
|
"onClick": onClick,
|
9670
9762
|
"onKeydown": isClickable.value && !isLink.value && onKeyDown
|
9671
9763
|
}, link.linkProps), {
|
@@ -10157,6 +10249,7 @@
|
|
10157
10249
|
const activeColor = vue.toRef(() => props.activeColor);
|
10158
10250
|
const baseColor = vue.toRef(() => props.baseColor);
|
10159
10251
|
const color = vue.toRef(() => props.color);
|
10252
|
+
const isSelectable = vue.toRef(() => props.selectable || props.activatable);
|
10160
10253
|
createList({
|
10161
10254
|
filterable: props.filterable
|
10162
10255
|
});
|
@@ -10226,7 +10319,7 @@
|
|
10226
10319
|
}, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class]),
|
10227
10320
|
"style": vue.normalizeStyle([backgroundColorStyles.value, dimensionStyles.value, props.style]),
|
10228
10321
|
"tabindex": props.disabled ? -1 : 0,
|
10229
|
-
"role":
|
10322
|
+
"role": isSelectable.value ? 'listbox' : 'list',
|
10230
10323
|
"aria-activedescendant": undefined,
|
10231
10324
|
"onFocusin": onFocusin,
|
10232
10325
|
"onFocusout": onFocusout,
|
@@ -13291,6 +13384,7 @@
|
|
13291
13384
|
"onKeydown": onListKeydown,
|
13292
13385
|
"onFocusin": onFocusin,
|
13293
13386
|
"tabindex": "-1",
|
13387
|
+
"selectable": true,
|
13294
13388
|
"aria-live": "polite",
|
13295
13389
|
"aria-label": `${props.label}-list`,
|
13296
13390
|
"color": props.itemColor ?? props.color
|
@@ -13910,6 +14004,7 @@
|
|
13910
14004
|
"onFocusin": onFocusin,
|
13911
14005
|
"onFocusout": onFocusout,
|
13912
14006
|
"tabindex": "-1",
|
14007
|
+
"selectable": true,
|
13913
14008
|
"aria-live": "polite",
|
13914
14009
|
"color": props.itemColor ?? props.color
|
13915
14010
|
}, listEvents, props.listProps), {
|
@@ -18997,6 +19092,7 @@
|
|
18997
19092
|
"selected": selectedValues.value,
|
18998
19093
|
"selectStrategy": props.multiple ? 'independent' : 'single-independent',
|
18999
19094
|
"onMousedown": e => e.preventDefault(),
|
19095
|
+
"selectable": true,
|
19000
19096
|
"onKeydown": onListKeydown,
|
19001
19097
|
"onFocusin": onFocusin,
|
19002
19098
|
"onFocusout": onFocusout,
|
@@ -24095,6 +24191,42 @@
|
|
24095
24191
|
return item.isDirectory ? `${path}/${item.name}` : path;
|
24096
24192
|
}
|
24097
24193
|
|
24194
|
+
// Utilities
|
24195
|
+
// Composables
|
24196
|
+
const makeFileFilterProps = propsFactory({
|
24197
|
+
filterByType: String
|
24198
|
+
}, 'file-accept');
|
24199
|
+
function useFileFilter(props) {
|
24200
|
+
const fileFilter = vue.computed(() => props.filterByType ? createFilter(props.filterByType) : null);
|
24201
|
+
function filterAccepted(files) {
|
24202
|
+
if (fileFilter.value) {
|
24203
|
+
const accepted = files.filter(fileFilter.value);
|
24204
|
+
return {
|
24205
|
+
accepted,
|
24206
|
+
rejected: files.filter(f => !accepted.includes(f))
|
24207
|
+
};
|
24208
|
+
}
|
24209
|
+
return {
|
24210
|
+
accepted: files,
|
24211
|
+
rejected: []
|
24212
|
+
};
|
24213
|
+
}
|
24214
|
+
return {
|
24215
|
+
filterAccepted
|
24216
|
+
};
|
24217
|
+
}
|
24218
|
+
function createFilter(v) {
|
24219
|
+
const types = v.split(',').map(x => x.trim().toLowerCase());
|
24220
|
+
const extensionsToMatch = types.filter(x => x.startsWith('.'));
|
24221
|
+
const wildcards = types.filter(x => x.endsWith('/*'));
|
24222
|
+
const typesToMatch = types.filter(x => !extensionsToMatch.includes(x) && !wildcards.includes(x));
|
24223
|
+
return file => {
|
24224
|
+
const extension = file.name.split('.').at(-1)?.toLowerCase() ?? '';
|
24225
|
+
const typeGroup = file.type.split('/').at(0)?.toLowerCase() ?? '';
|
24226
|
+
return typesToMatch.includes(file.type) || extensionsToMatch.includes(`.${extension}`) || wildcards.includes(`${typeGroup}/*`);
|
24227
|
+
};
|
24228
|
+
}
|
24229
|
+
|
24098
24230
|
// Types
|
24099
24231
|
|
24100
24232
|
const makeVFileInputProps = propsFactory({
|
@@ -24127,6 +24259,7 @@
|
|
24127
24259
|
return wrapInArray(val).every(v => v != null && typeof v === 'object');
|
24128
24260
|
}
|
24129
24261
|
},
|
24262
|
+
...makeFileFilterProps(),
|
24130
24263
|
...makeVFieldProps({
|
24131
24264
|
clearable: true
|
24132
24265
|
})
|
@@ -24139,7 +24272,8 @@
|
|
24139
24272
|
'click:control': e => true,
|
24140
24273
|
'mousedown:control': e => true,
|
24141
24274
|
'update:focused': focused => true,
|
24142
|
-
'update:modelValue': files => true
|
24275
|
+
'update:modelValue': files => true,
|
24276
|
+
rejected: files => true
|
24143
24277
|
},
|
24144
24278
|
setup(props, _ref) {
|
24145
24279
|
let {
|
@@ -24150,6 +24284,9 @@
|
|
24150
24284
|
const {
|
24151
24285
|
t
|
24152
24286
|
} = useLocale();
|
24287
|
+
const {
|
24288
|
+
filterAccepted
|
24289
|
+
} = useFileFilter(props);
|
24153
24290
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
|
24154
24291
|
const {
|
24155
24292
|
isFocused,
|
@@ -24223,14 +24360,38 @@
|
|
24223
24360
|
e.stopImmediatePropagation();
|
24224
24361
|
isDragging.value = false;
|
24225
24362
|
if (!inputRef.value || !hasFilesOrFolders(e)) return;
|
24363
|
+
const allDroppedFiles = await handleDrop(e);
|
24364
|
+
selectAccepted(allDroppedFiles);
|
24365
|
+
}
|
24366
|
+
function onFileSelection(e) {
|
24367
|
+
if (!e.target || e.repack) return; // prevent loop
|
24368
|
+
|
24369
|
+
if (!props.filterByType) {
|
24370
|
+
const target = e.target;
|
24371
|
+
model.value = [...(target.files ?? [])];
|
24372
|
+
} else {
|
24373
|
+
selectAccepted([...e.target.files]);
|
24374
|
+
}
|
24375
|
+
}
|
24376
|
+
function selectAccepted(files) {
|
24226
24377
|
const dataTransfer = new DataTransfer();
|
24227
|
-
|
24378
|
+
const {
|
24379
|
+
accepted,
|
24380
|
+
rejected
|
24381
|
+
} = filterAccepted(files);
|
24382
|
+
if (rejected.length) {
|
24383
|
+
emit('rejected', rejected);
|
24384
|
+
}
|
24385
|
+
for (const file of accepted) {
|
24228
24386
|
dataTransfer.items.add(file);
|
24229
24387
|
}
|
24230
24388
|
inputRef.value.files = dataTransfer.files;
|
24231
|
-
|
24389
|
+
model.value = [...dataTransfer.files];
|
24390
|
+
const event = new Event('change', {
|
24232
24391
|
bubbles: true
|
24233
|
-
})
|
24392
|
+
});
|
24393
|
+
event.repack = true;
|
24394
|
+
inputRef.value.dispatchEvent(event);
|
24234
24395
|
}
|
24235
24396
|
vue.watch(model, newValue => {
|
24236
24397
|
const hasModelReset = !Array.isArray(newValue) || !newValue.length;
|
@@ -24247,6 +24408,8 @@
|
|
24247
24408
|
...inputProps
|
24248
24409
|
} = VInput.filterProps(props);
|
24249
24410
|
const fieldProps = VField.filterProps(props);
|
24411
|
+
const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
|
24412
|
+
const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
|
24250
24413
|
return vue.createVNode(VInput, vue.mergeProps({
|
24251
24414
|
"ref": vInputRef,
|
24252
24415
|
"modelValue": props.multiple ? model.value : model.value[0],
|
@@ -24300,6 +24463,7 @@
|
|
24300
24463
|
return vue.createElementVNode(vue.Fragment, null, [vue.createElementVNode("input", vue.mergeProps({
|
24301
24464
|
"ref": inputRef,
|
24302
24465
|
"type": "file",
|
24466
|
+
"accept": inputAccept,
|
24303
24467
|
"readonly": isReadonly.value,
|
24304
24468
|
"disabled": isDisabled.value,
|
24305
24469
|
"multiple": props.multiple,
|
@@ -24309,11 +24473,7 @@
|
|
24309
24473
|
if (isReadonly.value) e.preventDefault();
|
24310
24474
|
onFocus();
|
24311
24475
|
},
|
24312
|
-
"onChange":
|
24313
|
-
if (!e.target) return;
|
24314
|
-
const target = e.target;
|
24315
|
-
model.value = [...(target.files ?? [])];
|
24316
|
-
},
|
24476
|
+
"onChange": onFileSelection,
|
24317
24477
|
"onDragleave": onDragleave,
|
24318
24478
|
"onFocus": onFocus,
|
24319
24479
|
"onBlur": blur
|
@@ -31818,6 +31978,7 @@
|
|
31818
31978
|
},
|
31819
31979
|
showSize: Boolean,
|
31820
31980
|
name: String,
|
31981
|
+
...makeFileFilterProps(),
|
31821
31982
|
...makeDelayProps(),
|
31822
31983
|
...makeDensityProps(),
|
31823
31984
|
...pick(makeVDividerProps({
|
@@ -31830,11 +31991,13 @@
|
|
31830
31991
|
inheritAttrs: false,
|
31831
31992
|
props: makeVFileUploadProps(),
|
31832
31993
|
emits: {
|
31833
|
-
'update:modelValue': files => true
|
31994
|
+
'update:modelValue': files => true,
|
31995
|
+
rejected: files => true
|
31834
31996
|
},
|
31835
31997
|
setup(props, _ref) {
|
31836
31998
|
let {
|
31837
31999
|
attrs,
|
32000
|
+
emit,
|
31838
32001
|
slots
|
31839
32002
|
} = _ref;
|
31840
32003
|
const {
|
@@ -31843,6 +32006,9 @@
|
|
31843
32006
|
const {
|
31844
32007
|
densityClasses
|
31845
32008
|
} = useDensity(props);
|
32009
|
+
const {
|
32010
|
+
filterAccepted
|
32011
|
+
} = useFileFilter(props);
|
31846
32012
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
|
31847
32013
|
const isDragging = vue.shallowRef(false);
|
31848
32014
|
const vSheetRef = vue.ref(null);
|
@@ -31864,14 +32030,38 @@
|
|
31864
32030
|
e.stopImmediatePropagation();
|
31865
32031
|
isDragging.value = false;
|
31866
32032
|
if (!inputRef.value) return;
|
32033
|
+
const allDroppedFiles = await handleDrop(e);
|
32034
|
+
selectAccepted(allDroppedFiles);
|
32035
|
+
}
|
32036
|
+
function onFileSelection(e) {
|
32037
|
+
if (!e.target || e.repack) return; // prevent loop
|
32038
|
+
|
32039
|
+
if (!props.filterByType) {
|
32040
|
+
const target = e.target;
|
32041
|
+
model.value = [...(target.files ?? [])];
|
32042
|
+
} else {
|
32043
|
+
selectAccepted([...e.target.files]);
|
32044
|
+
}
|
32045
|
+
}
|
32046
|
+
function selectAccepted(files) {
|
31867
32047
|
const dataTransfer = new DataTransfer();
|
31868
|
-
|
32048
|
+
const {
|
32049
|
+
accepted,
|
32050
|
+
rejected
|
32051
|
+
} = filterAccepted(files);
|
32052
|
+
if (rejected.length) {
|
32053
|
+
emit('rejected', rejected);
|
32054
|
+
}
|
32055
|
+
for (const file of accepted) {
|
31869
32056
|
dataTransfer.items.add(file);
|
31870
32057
|
}
|
31871
32058
|
inputRef.value.files = dataTransfer.files;
|
31872
|
-
|
32059
|
+
model.value = [...dataTransfer.files];
|
32060
|
+
const event = new Event('change', {
|
31873
32061
|
bubbles: true
|
31874
|
-
})
|
32062
|
+
});
|
32063
|
+
event.repack = true;
|
32064
|
+
inputRef.value.dispatchEvent(event);
|
31875
32065
|
}
|
31876
32066
|
function onClick() {
|
31877
32067
|
inputRef.value?.click();
|
@@ -31889,17 +32079,16 @@
|
|
31889
32079
|
const cardProps = VSheet.filterProps(props);
|
31890
32080
|
const dividerProps = VDivider.filterProps(props);
|
31891
32081
|
const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
|
32082
|
+
const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
|
32083
|
+
const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
|
31892
32084
|
const inputNode = vue.createElementVNode("input", vue.mergeProps({
|
31893
32085
|
"ref": inputRef,
|
31894
32086
|
"type": "file",
|
32087
|
+
"accept": inputAccept,
|
31895
32088
|
"disabled": props.disabled,
|
31896
32089
|
"multiple": props.multiple,
|
31897
32090
|
"name": props.name,
|
31898
|
-
"onChange":
|
31899
|
-
if (!e.target) return;
|
31900
|
-
const target = e.target;
|
31901
|
-
model.value = [...(target.files ?? [])];
|
31902
|
-
}
|
32091
|
+
"onChange": onFileSelection
|
31903
32092
|
}, inputAttrs), null);
|
31904
32093
|
return vue.createElementVNode(vue.Fragment, null, [vue.createVNode(VSheet, vue.mergeProps({
|
31905
32094
|
"ref": vSheetRef
|
@@ -33676,7 +33865,7 @@
|
|
33676
33865
|
};
|
33677
33866
|
});
|
33678
33867
|
}
|
33679
|
-
const version$1 = "3.9.0-dev.2025-07-
|
33868
|
+
const version$1 = "3.9.0-dev.2025-07-16";
|
33680
33869
|
createVuetify$1.version = version$1;
|
33681
33870
|
|
33682
33871
|
// Vue's inject() can only be used in setup
|
@@ -33974,7 +34163,7 @@
|
|
33974
34163
|
|
33975
34164
|
/* eslint-disable local-rules/sort-imports */
|
33976
34165
|
|
33977
|
-
const version = "3.9.0-dev.2025-07-
|
34166
|
+
const version = "3.9.0-dev.2025-07-16";
|
33978
34167
|
|
33979
34168
|
/* eslint-disable local-rules/sort-imports */
|
33980
34169
|
|