@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +14 -3
  2. package/dist/json/attributes.json +3826 -3806
  3. package/dist/json/importMap-labs.json +24 -24
  4. package/dist/json/importMap.json +168 -168
  5. package/dist/json/tags.json +5 -0
  6. package/dist/json/web-types.json +6992 -6922
  7. package/dist/vuetify-labs.cjs +216 -27
  8. package/dist/vuetify-labs.css +4659 -4657
  9. package/dist/vuetify-labs.d.ts +119 -57
  10. package/dist/vuetify-labs.esm.js +216 -27
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +216 -27
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +178 -18
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +4036 -4034
  17. package/dist/vuetify.d.ts +109 -57
  18. package/dist/vuetify.esm.js +178 -18
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +178 -18
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +718 -696
  24. package/dist/vuetify.min.js.map +1 -1
  25. package/lib/components/VAutocomplete/VAutocomplete.js +1 -0
  26. package/lib/components/VAutocomplete/VAutocomplete.js.map +1 -1
  27. package/lib/components/VCombobox/VCombobox.js +1 -0
  28. package/lib/components/VCombobox/VCombobox.js.map +1 -1
  29. package/lib/components/VFileInput/VFileInput.d.ts +15 -0
  30. package/lib/components/VFileInput/VFileInput.js +38 -9
  31. package/lib/components/VFileInput/VFileInput.js.map +1 -1
  32. package/lib/components/VList/VList.js +2 -1
  33. package/lib/components/VList/VList.js.map +1 -1
  34. package/lib/components/VList/VListItem.js +7 -1
  35. package/lib/components/VList/VListItem.js.map +1 -1
  36. package/lib/components/VProgressLinear/VProgressLinear.css +1 -1
  37. package/lib/components/VProgressLinear/VProgressLinear.d.ts +75 -0
  38. package/lib/components/VProgressLinear/VProgressLinear.js +32 -6
  39. package/lib/components/VProgressLinear/VProgressLinear.js.map +1 -1
  40. package/lib/components/VProgressLinear/VProgressLinear.sass +2 -2
  41. package/lib/components/VProgressLinear/chunks.d.ts +55 -0
  42. package/lib/components/VProgressLinear/chunks.js +62 -0
  43. package/lib/components/VProgressLinear/chunks.js.map +1 -0
  44. package/lib/components/VSelect/VSelect.js +1 -0
  45. package/lib/components/VSelect/VSelect.js.map +1 -1
  46. package/lib/composables/fileFilter.d.ts +18 -0
  47. package/lib/composables/fileFilter.js +38 -0
  48. package/lib/composables/fileFilter.js.map +1 -0
  49. package/lib/entry-bundler.js +1 -1
  50. package/lib/framework.d.ts +57 -57
  51. package/lib/framework.js +1 -1
  52. package/lib/labs/VFileUpload/VFileUpload.d.ts +15 -0
  53. package/lib/labs/VFileUpload/VFileUpload.js +39 -9
  54. package/lib/labs/VFileUpload/VFileUpload.js.map +1 -1
  55. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.9.0-dev.2025-07-08
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": intersectionRef,
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(normalizedBuffer.value, '%')
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(normalizedValue.value, '%')
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": isSelectable.value ? root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value : undefined,
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": "listbox",
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
- for (const file of await handleDrop(e)) {
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
- inputRef.value.dispatchEvent(new Event('change', {
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": e => {
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
- for (const file of await handleDrop(e)) {
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
- inputRef.value.dispatchEvent(new Event('change', {
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": e => {
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-08";
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-08";
34166
+ const version = "3.9.0-dev.2025-07-16";
33978
34167
 
33979
34168
  /* eslint-disable local-rules/sort-imports */
33980
34169