@vuetify/nightly 3.9.0-dev.2025-07-15 → 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 (45) hide show
  1. package/CHANGELOG.md +9 -3
  2. package/dist/json/attributes.json +3261 -3241
  3. package/dist/json/importMap-labs.json +24 -24
  4. package/dist/json/importMap.json +202 -202
  5. package/dist/json/tags.json +5 -0
  6. package/dist/json/web-types.json +6129 -6059
  7. package/dist/vuetify-labs.cjs +204 -25
  8. package/dist/vuetify-labs.css +4800 -4798
  9. package/dist/vuetify-labs.d.ts +129 -67
  10. package/dist/vuetify-labs.esm.js +204 -25
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +204 -25
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +166 -16
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +3987 -3985
  17. package/dist/vuetify.d.ts +119 -67
  18. package/dist/vuetify.esm.js +166 -16
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +166 -16
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +710 -688
  24. package/dist/vuetify.min.js.map +1 -1
  25. package/lib/components/VFileInput/VFileInput.d.ts +15 -0
  26. package/lib/components/VFileInput/VFileInput.js +38 -9
  27. package/lib/components/VFileInput/VFileInput.js.map +1 -1
  28. package/lib/components/VProgressLinear/VProgressLinear.css +1 -1
  29. package/lib/components/VProgressLinear/VProgressLinear.d.ts +75 -0
  30. package/lib/components/VProgressLinear/VProgressLinear.js +32 -6
  31. package/lib/components/VProgressLinear/VProgressLinear.js.map +1 -1
  32. package/lib/components/VProgressLinear/VProgressLinear.sass +2 -2
  33. package/lib/components/VProgressLinear/chunks.d.ts +55 -0
  34. package/lib/components/VProgressLinear/chunks.js +62 -0
  35. package/lib/components/VProgressLinear/chunks.js.map +1 -0
  36. package/lib/composables/fileFilter.d.ts +18 -0
  37. package/lib/composables/fileFilter.js +38 -0
  38. package/lib/composables/fileFilter.js.map +1 -0
  39. package/lib/entry-bundler.js +1 -1
  40. package/lib/framework.d.ts +67 -67
  41. package/lib/framework.js +1 -1
  42. package/lib/labs/VFileUpload/VFileUpload.d.ts +15 -0
  43. package/lib/labs/VFileUpload/VFileUpload.js +39 -9
  44. package/lib/labs/VFileUpload/VFileUpload.js.map +1 -1
  45. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.9.0-dev.2025-07-15
2
+ * Vuetify v3.9.0-dev.2025-07-16
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -5186,6 +5186,69 @@ function useLocation(props) {
5186
5186
  };
5187
5187
  }
5188
5188
 
5189
+ // Utilities
5190
+
5191
+ // Types
5192
+
5193
+ // Composables
5194
+ const makeChunksProps = propsFactory({
5195
+ chunkCount: {
5196
+ type: [Number, String],
5197
+ default: null
5198
+ },
5199
+ chunkWidth: {
5200
+ type: [Number, String],
5201
+ default: null
5202
+ },
5203
+ chunkGap: {
5204
+ type: [Number, String],
5205
+ default: 4
5206
+ }
5207
+ }, 'chunks');
5208
+ function useChunks(props, containerWidth) {
5209
+ const hasChunks = toRef(() => !!props.chunkCount || !!props.chunkWidth);
5210
+ const chunkWidth = computed(() => {
5211
+ const containerSize = toValue(containerWidth);
5212
+ if (!containerSize) {
5213
+ return 0;
5214
+ }
5215
+ if (!props.chunkCount) {
5216
+ return Number(props.chunkWidth);
5217
+ }
5218
+ const count = Number(props.chunkCount);
5219
+ const availableWidth = containerSize - Number(props.chunkGap) * (count - 1);
5220
+ return availableWidth / count;
5221
+ });
5222
+ const chunkGap = toRef(() => Number(props.chunkGap));
5223
+ const chunksMaskStyles = computed(() => {
5224
+ if (!hasChunks.value) {
5225
+ return {};
5226
+ }
5227
+ const chunkGapPx = convertToUnit(chunkGap.value);
5228
+ const chunkWidthPx = convertToUnit(chunkWidth.value);
5229
+ return {
5230
+ maskRepeat: 'repeat-x',
5231
+ maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
5232
+ maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
5233
+ };
5234
+ });
5235
+ function snapValueToChunk(val) {
5236
+ const containerSize = toValue(containerWidth);
5237
+ if (!containerSize) {
5238
+ return val;
5239
+ }
5240
+ const gapRelativeSize = 100 * chunkGap.value / containerSize;
5241
+ const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;
5242
+ const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize);
5243
+ return clamp(0, filledChunks * chunkRelativeSize - gapRelativeSize / 2, 100);
5244
+ }
5245
+ return {
5246
+ hasChunks,
5247
+ chunksMaskStyles,
5248
+ snapValueToChunk
5249
+ };
5250
+ }
5251
+
5189
5252
  const makeVProgressLinearProps = propsFactory({
5190
5253
  absolute: Boolean,
5191
5254
  active: {
@@ -5220,6 +5283,7 @@ const makeVProgressLinearProps = propsFactory({
5220
5283
  stream: Boolean,
5221
5284
  striped: Boolean,
5222
5285
  roundedBar: Boolean,
5286
+ ...makeChunksProps(),
5223
5287
  ...makeComponentProps(),
5224
5288
  ...makeLocationProps({
5225
5289
  location: 'top'
@@ -5238,6 +5302,7 @@ const VProgressLinear = genericComponent()({
5238
5302
  let {
5239
5303
  slots
5240
5304
  } = _ref;
5305
+ const root = ref();
5241
5306
  const progress = useProxiedModel(props, 'modelValue');
5242
5307
  const {
5243
5308
  isRtl,
@@ -5279,6 +5344,24 @@ const VProgressLinear = genericComponent()({
5279
5344
  const isReversed = computed(() => isRtl.value !== props.reverse);
5280
5345
  const transition = computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
5281
5346
  const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
5347
+ const containerWidth = shallowRef(0);
5348
+ const {
5349
+ hasChunks,
5350
+ chunksMaskStyles,
5351
+ snapValueToChunk
5352
+ } = useChunks(props, containerWidth);
5353
+ useToggleScope(hasChunks, () => {
5354
+ const {
5355
+ resizeRef
5356
+ } = useResizeObserver(entries => containerWidth.value = entries[0].contentRect.width);
5357
+ watchEffect(() => resizeRef.value = root.value);
5358
+ });
5359
+ const bufferWidth = computed(() => {
5360
+ return hasChunks.value ? snapValueToChunk(normalizedBuffer.value) : normalizedBuffer.value;
5361
+ });
5362
+ const barWidth = computed(() => {
5363
+ return hasChunks.value ? snapValueToChunk(normalizedValue.value) : normalizedValue.value;
5364
+ });
5282
5365
  function handleClick(e) {
5283
5366
  if (!intersectionRef.value) return;
5284
5367
  const {
@@ -5289,8 +5372,11 @@ const VProgressLinear = genericComponent()({
5289
5372
  const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
5290
5373
  progress.value = Math.round(value / width * max.value);
5291
5374
  }
5375
+ watchEffect(() => {
5376
+ intersectionRef.value = root.value;
5377
+ });
5292
5378
  useRender(() => createVNode(props.tag, {
5293
- "ref": intersectionRef,
5379
+ "ref": root,
5294
5380
  "class": normalizeClass(['v-progress-linear', {
5295
5381
  'v-progress-linear--absolute': props.absolute,
5296
5382
  'v-progress-linear--active': props.active && isIntersecting.value,
@@ -5305,7 +5391,7 @@ const VProgressLinear = genericComponent()({
5305
5391
  height: props.active ? convertToUnit(height.value) : 0,
5306
5392
  '--v-progress-linear-height': convertToUnit(height.value),
5307
5393
  ...(props.absolute ? locationStyles.value : {})
5308
- }, props.style]),
5394
+ }, chunksMaskStyles.value, props.style]),
5309
5395
  "role": "progressbar",
5310
5396
  "aria-hidden": props.active ? 'false' : 'true',
5311
5397
  "aria-valuemin": "0",
@@ -5335,7 +5421,7 @@ const VProgressLinear = genericComponent()({
5335
5421
  "class": normalizeClass(['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined]),
5336
5422
  "style": normalizeStyle([bufferColorStyles.value, {
5337
5423
  opacity: parseFloat(props.bufferOpacity),
5338
- width: convertToUnit(normalizedBuffer.value, '%')
5424
+ width: convertToUnit(bufferWidth.value, '%')
5339
5425
  }])
5340
5426
  }, null), createVNode(Transition, {
5341
5427
  "name": transition.value
@@ -5343,7 +5429,7 @@ const VProgressLinear = genericComponent()({
5343
5429
  default: () => [!props.indeterminate ? createElementVNode("div", {
5344
5430
  "class": normalizeClass(['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined]),
5345
5431
  "style": normalizeStyle([barColorStyles.value, {
5346
- width: convertToUnit(normalizedValue.value, '%')
5432
+ width: convertToUnit(barWidth.value, '%')
5347
5433
  }])
5348
5434
  }, null) : createElementVNode("div", {
5349
5435
  "class": "v-progress-linear__indeterminate"
@@ -24101,6 +24187,42 @@ function appendIfDirectory(path, item) {
24101
24187
  return item.isDirectory ? `${path}/${item.name}` : path;
24102
24188
  }
24103
24189
 
24190
+ // Utilities
24191
+ // Composables
24192
+ const makeFileFilterProps = propsFactory({
24193
+ filterByType: String
24194
+ }, 'file-accept');
24195
+ function useFileFilter(props) {
24196
+ const fileFilter = computed(() => props.filterByType ? createFilter(props.filterByType) : null);
24197
+ function filterAccepted(files) {
24198
+ if (fileFilter.value) {
24199
+ const accepted = files.filter(fileFilter.value);
24200
+ return {
24201
+ accepted,
24202
+ rejected: files.filter(f => !accepted.includes(f))
24203
+ };
24204
+ }
24205
+ return {
24206
+ accepted: files,
24207
+ rejected: []
24208
+ };
24209
+ }
24210
+ return {
24211
+ filterAccepted
24212
+ };
24213
+ }
24214
+ function createFilter(v) {
24215
+ const types = v.split(',').map(x => x.trim().toLowerCase());
24216
+ const extensionsToMatch = types.filter(x => x.startsWith('.'));
24217
+ const wildcards = types.filter(x => x.endsWith('/*'));
24218
+ const typesToMatch = types.filter(x => !extensionsToMatch.includes(x) && !wildcards.includes(x));
24219
+ return file => {
24220
+ const extension = file.name.split('.').at(-1)?.toLowerCase() ?? '';
24221
+ const typeGroup = file.type.split('/').at(0)?.toLowerCase() ?? '';
24222
+ return typesToMatch.includes(file.type) || extensionsToMatch.includes(`.${extension}`) || wildcards.includes(`${typeGroup}/*`);
24223
+ };
24224
+ }
24225
+
24104
24226
  // Types
24105
24227
 
24106
24228
  const makeVFileInputProps = propsFactory({
@@ -24133,6 +24255,7 @@ const makeVFileInputProps = propsFactory({
24133
24255
  return wrapInArray(val).every(v => v != null && typeof v === 'object');
24134
24256
  }
24135
24257
  },
24258
+ ...makeFileFilterProps(),
24136
24259
  ...makeVFieldProps({
24137
24260
  clearable: true
24138
24261
  })
@@ -24145,7 +24268,8 @@ const VFileInput = genericComponent()({
24145
24268
  'click:control': e => true,
24146
24269
  'mousedown:control': e => true,
24147
24270
  'update:focused': focused => true,
24148
- 'update:modelValue': files => true
24271
+ 'update:modelValue': files => true,
24272
+ rejected: files => true
24149
24273
  },
24150
24274
  setup(props, _ref) {
24151
24275
  let {
@@ -24156,6 +24280,9 @@ const VFileInput = genericComponent()({
24156
24280
  const {
24157
24281
  t
24158
24282
  } = useLocale();
24283
+ const {
24284
+ filterAccepted
24285
+ } = useFileFilter(props);
24159
24286
  const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
24160
24287
  const {
24161
24288
  isFocused,
@@ -24229,14 +24356,38 @@ const VFileInput = genericComponent()({
24229
24356
  e.stopImmediatePropagation();
24230
24357
  isDragging.value = false;
24231
24358
  if (!inputRef.value || !hasFilesOrFolders(e)) return;
24359
+ const allDroppedFiles = await handleDrop(e);
24360
+ selectAccepted(allDroppedFiles);
24361
+ }
24362
+ function onFileSelection(e) {
24363
+ if (!e.target || e.repack) return; // prevent loop
24364
+
24365
+ if (!props.filterByType) {
24366
+ const target = e.target;
24367
+ model.value = [...(target.files ?? [])];
24368
+ } else {
24369
+ selectAccepted([...e.target.files]);
24370
+ }
24371
+ }
24372
+ function selectAccepted(files) {
24232
24373
  const dataTransfer = new DataTransfer();
24233
- for (const file of await handleDrop(e)) {
24374
+ const {
24375
+ accepted,
24376
+ rejected
24377
+ } = filterAccepted(files);
24378
+ if (rejected.length) {
24379
+ emit('rejected', rejected);
24380
+ }
24381
+ for (const file of accepted) {
24234
24382
  dataTransfer.items.add(file);
24235
24383
  }
24236
24384
  inputRef.value.files = dataTransfer.files;
24237
- inputRef.value.dispatchEvent(new Event('change', {
24385
+ model.value = [...dataTransfer.files];
24386
+ const event = new Event('change', {
24238
24387
  bubbles: true
24239
- }));
24388
+ });
24389
+ event.repack = true;
24390
+ inputRef.value.dispatchEvent(event);
24240
24391
  }
24241
24392
  watch(model, newValue => {
24242
24393
  const hasModelReset = !Array.isArray(newValue) || !newValue.length;
@@ -24253,6 +24404,8 @@ const VFileInput = genericComponent()({
24253
24404
  ...inputProps
24254
24405
  } = VInput.filterProps(props);
24255
24406
  const fieldProps = VField.filterProps(props);
24407
+ const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
24408
+ const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
24256
24409
  return createVNode(VInput, mergeProps({
24257
24410
  "ref": vInputRef,
24258
24411
  "modelValue": props.multiple ? model.value : model.value[0],
@@ -24306,6 +24459,7 @@ const VFileInput = genericComponent()({
24306
24459
  return createElementVNode(Fragment, null, [createElementVNode("input", mergeProps({
24307
24460
  "ref": inputRef,
24308
24461
  "type": "file",
24462
+ "accept": inputAccept,
24309
24463
  "readonly": isReadonly.value,
24310
24464
  "disabled": isDisabled.value,
24311
24465
  "multiple": props.multiple,
@@ -24315,11 +24469,7 @@ const VFileInput = genericComponent()({
24315
24469
  if (isReadonly.value) e.preventDefault();
24316
24470
  onFocus();
24317
24471
  },
24318
- "onChange": e => {
24319
- if (!e.target) return;
24320
- const target = e.target;
24321
- model.value = [...(target.files ?? [])];
24322
- },
24472
+ "onChange": onFileSelection,
24323
24473
  "onDragleave": onDragleave,
24324
24474
  "onFocus": onFocus,
24325
24475
  "onBlur": blur
@@ -31824,6 +31974,7 @@ const makeVFileUploadProps = propsFactory({
31824
31974
  },
31825
31975
  showSize: Boolean,
31826
31976
  name: String,
31977
+ ...makeFileFilterProps(),
31827
31978
  ...makeDelayProps(),
31828
31979
  ...makeDensityProps(),
31829
31980
  ...pick(makeVDividerProps({
@@ -31836,11 +31987,13 @@ const VFileUpload = genericComponent()({
31836
31987
  inheritAttrs: false,
31837
31988
  props: makeVFileUploadProps(),
31838
31989
  emits: {
31839
- 'update:modelValue': files => true
31990
+ 'update:modelValue': files => true,
31991
+ rejected: files => true
31840
31992
  },
31841
31993
  setup(props, _ref) {
31842
31994
  let {
31843
31995
  attrs,
31996
+ emit,
31844
31997
  slots
31845
31998
  } = _ref;
31846
31999
  const {
@@ -31849,6 +32002,9 @@ const VFileUpload = genericComponent()({
31849
32002
  const {
31850
32003
  densityClasses
31851
32004
  } = useDensity(props);
32005
+ const {
32006
+ filterAccepted
32007
+ } = useFileFilter(props);
31852
32008
  const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
31853
32009
  const isDragging = shallowRef(false);
31854
32010
  const vSheetRef = ref(null);
@@ -31870,14 +32026,38 @@ const VFileUpload = genericComponent()({
31870
32026
  e.stopImmediatePropagation();
31871
32027
  isDragging.value = false;
31872
32028
  if (!inputRef.value) return;
32029
+ const allDroppedFiles = await handleDrop(e);
32030
+ selectAccepted(allDroppedFiles);
32031
+ }
32032
+ function onFileSelection(e) {
32033
+ if (!e.target || e.repack) return; // prevent loop
32034
+
32035
+ if (!props.filterByType) {
32036
+ const target = e.target;
32037
+ model.value = [...(target.files ?? [])];
32038
+ } else {
32039
+ selectAccepted([...e.target.files]);
32040
+ }
32041
+ }
32042
+ function selectAccepted(files) {
31873
32043
  const dataTransfer = new DataTransfer();
31874
- for (const file of await handleDrop(e)) {
32044
+ const {
32045
+ accepted,
32046
+ rejected
32047
+ } = filterAccepted(files);
32048
+ if (rejected.length) {
32049
+ emit('rejected', rejected);
32050
+ }
32051
+ for (const file of accepted) {
31875
32052
  dataTransfer.items.add(file);
31876
32053
  }
31877
32054
  inputRef.value.files = dataTransfer.files;
31878
- inputRef.value.dispatchEvent(new Event('change', {
32055
+ model.value = [...dataTransfer.files];
32056
+ const event = new Event('change', {
31879
32057
  bubbles: true
31880
- }));
32058
+ });
32059
+ event.repack = true;
32060
+ inputRef.value.dispatchEvent(event);
31881
32061
  }
31882
32062
  function onClick() {
31883
32063
  inputRef.value?.click();
@@ -31895,17 +32075,16 @@ const VFileUpload = genericComponent()({
31895
32075
  const cardProps = VSheet.filterProps(props);
31896
32076
  const dividerProps = VDivider.filterProps(props);
31897
32077
  const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
32078
+ const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
32079
+ const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
31898
32080
  const inputNode = createElementVNode("input", mergeProps({
31899
32081
  "ref": inputRef,
31900
32082
  "type": "file",
32083
+ "accept": inputAccept,
31901
32084
  "disabled": props.disabled,
31902
32085
  "multiple": props.multiple,
31903
32086
  "name": props.name,
31904
- "onChange": e => {
31905
- if (!e.target) return;
31906
- const target = e.target;
31907
- model.value = [...(target.files ?? [])];
31908
- }
32087
+ "onChange": onFileSelection
31909
32088
  }, inputAttrs), null);
31910
32089
  return createElementVNode(Fragment, null, [createVNode(VSheet, mergeProps({
31911
32090
  "ref": vSheetRef
@@ -33682,7 +33861,7 @@ function createVuetify$1() {
33682
33861
  };
33683
33862
  });
33684
33863
  }
33685
- const version$1 = "3.9.0-dev.2025-07-15";
33864
+ const version$1 = "3.9.0-dev.2025-07-16";
33686
33865
  createVuetify$1.version = version$1;
33687
33866
 
33688
33867
  // Vue's inject() can only be used in setup
@@ -33980,7 +34159,7 @@ var index = /*#__PURE__*/Object.freeze({
33980
34159
 
33981
34160
  /* eslint-disable local-rules/sort-imports */
33982
34161
 
33983
- const version = "3.9.0-dev.2025-07-15";
34162
+ const version = "3.9.0-dev.2025-07-16";
33984
34163
 
33985
34164
  /* eslint-disable local-rules/sort-imports */
33986
34165