@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
  */
@@ -5464,6 +5464,69 @@ function useLocation(props) {
5464
5464
  };
5465
5465
  }
5466
5466
 
5467
+ // Utilities
5468
+
5469
+ // Types
5470
+
5471
+ // Composables
5472
+ const makeChunksProps = propsFactory({
5473
+ chunkCount: {
5474
+ type: [Number, String],
5475
+ default: null
5476
+ },
5477
+ chunkWidth: {
5478
+ type: [Number, String],
5479
+ default: null
5480
+ },
5481
+ chunkGap: {
5482
+ type: [Number, String],
5483
+ default: 4
5484
+ }
5485
+ }, 'chunks');
5486
+ function useChunks(props, containerWidth) {
5487
+ const hasChunks = toRef(() => !!props.chunkCount || !!props.chunkWidth);
5488
+ const chunkWidth = computed(() => {
5489
+ const containerSize = toValue(containerWidth);
5490
+ if (!containerSize) {
5491
+ return 0;
5492
+ }
5493
+ if (!props.chunkCount) {
5494
+ return Number(props.chunkWidth);
5495
+ }
5496
+ const count = Number(props.chunkCount);
5497
+ const availableWidth = containerSize - Number(props.chunkGap) * (count - 1);
5498
+ return availableWidth / count;
5499
+ });
5500
+ const chunkGap = toRef(() => Number(props.chunkGap));
5501
+ const chunksMaskStyles = computed(() => {
5502
+ if (!hasChunks.value) {
5503
+ return {};
5504
+ }
5505
+ const chunkGapPx = convertToUnit(chunkGap.value);
5506
+ const chunkWidthPx = convertToUnit(chunkWidth.value);
5507
+ return {
5508
+ maskRepeat: 'repeat-x',
5509
+ maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
5510
+ maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
5511
+ };
5512
+ });
5513
+ function snapValueToChunk(val) {
5514
+ const containerSize = toValue(containerWidth);
5515
+ if (!containerSize) {
5516
+ return val;
5517
+ }
5518
+ const gapRelativeSize = 100 * chunkGap.value / containerSize;
5519
+ const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;
5520
+ const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize);
5521
+ return clamp(0, filledChunks * chunkRelativeSize - gapRelativeSize / 2, 100);
5522
+ }
5523
+ return {
5524
+ hasChunks,
5525
+ chunksMaskStyles,
5526
+ snapValueToChunk
5527
+ };
5528
+ }
5529
+
5467
5530
  const makeVProgressLinearProps = propsFactory({
5468
5531
  absolute: Boolean,
5469
5532
  active: {
@@ -5498,6 +5561,7 @@ const makeVProgressLinearProps = propsFactory({
5498
5561
  stream: Boolean,
5499
5562
  striped: Boolean,
5500
5563
  roundedBar: Boolean,
5564
+ ...makeChunksProps(),
5501
5565
  ...makeComponentProps(),
5502
5566
  ...makeLocationProps({
5503
5567
  location: 'top'
@@ -5516,6 +5580,7 @@ const VProgressLinear = genericComponent()({
5516
5580
  let {
5517
5581
  slots
5518
5582
  } = _ref;
5583
+ const root = ref();
5519
5584
  const progress = useProxiedModel(props, 'modelValue');
5520
5585
  const {
5521
5586
  isRtl,
@@ -5557,6 +5622,24 @@ const VProgressLinear = genericComponent()({
5557
5622
  const isReversed = computed(() => isRtl.value !== props.reverse);
5558
5623
  const transition = computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
5559
5624
  const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
5625
+ const containerWidth = shallowRef(0);
5626
+ const {
5627
+ hasChunks,
5628
+ chunksMaskStyles,
5629
+ snapValueToChunk
5630
+ } = useChunks(props, containerWidth);
5631
+ useToggleScope(hasChunks, () => {
5632
+ const {
5633
+ resizeRef
5634
+ } = useResizeObserver(entries => containerWidth.value = entries[0].contentRect.width);
5635
+ watchEffect(() => resizeRef.value = root.value);
5636
+ });
5637
+ const bufferWidth = computed(() => {
5638
+ return hasChunks.value ? snapValueToChunk(normalizedBuffer.value) : normalizedBuffer.value;
5639
+ });
5640
+ const barWidth = computed(() => {
5641
+ return hasChunks.value ? snapValueToChunk(normalizedValue.value) : normalizedValue.value;
5642
+ });
5560
5643
  function handleClick(e) {
5561
5644
  if (!intersectionRef.value) return;
5562
5645
  const {
@@ -5567,8 +5650,11 @@ const VProgressLinear = genericComponent()({
5567
5650
  const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
5568
5651
  progress.value = Math.round(value / width * max.value);
5569
5652
  }
5653
+ watchEffect(() => {
5654
+ intersectionRef.value = root.value;
5655
+ });
5570
5656
  useRender(() => createVNode(props.tag, {
5571
- "ref": intersectionRef,
5657
+ "ref": root,
5572
5658
  "class": normalizeClass(['v-progress-linear', {
5573
5659
  'v-progress-linear--absolute': props.absolute,
5574
5660
  'v-progress-linear--active': props.active && isIntersecting.value,
@@ -5583,7 +5669,7 @@ const VProgressLinear = genericComponent()({
5583
5669
  height: props.active ? convertToUnit(height.value) : 0,
5584
5670
  '--v-progress-linear-height': convertToUnit(height.value),
5585
5671
  ...(props.absolute ? locationStyles.value : {})
5586
- }, props.style]),
5672
+ }, chunksMaskStyles.value, props.style]),
5587
5673
  "role": "progressbar",
5588
5674
  "aria-hidden": props.active ? 'false' : 'true',
5589
5675
  "aria-valuemin": "0",
@@ -5613,7 +5699,7 @@ const VProgressLinear = genericComponent()({
5613
5699
  "class": normalizeClass(['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined]),
5614
5700
  "style": normalizeStyle([bufferColorStyles.value, {
5615
5701
  opacity: parseFloat(props.bufferOpacity),
5616
- width: convertToUnit(normalizedBuffer.value, '%')
5702
+ width: convertToUnit(bufferWidth.value, '%')
5617
5703
  }])
5618
5704
  }, null), createVNode(Transition, {
5619
5705
  "name": transition.value
@@ -5621,7 +5707,7 @@ const VProgressLinear = genericComponent()({
5621
5707
  default: () => [!props.indeterminate ? createElementVNode("div", {
5622
5708
  "class": normalizeClass(['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined]),
5623
5709
  "style": normalizeStyle([barColorStyles.value, {
5624
- width: convertToUnit(normalizedValue.value, '%')
5710
+ width: convertToUnit(barWidth.value, '%')
5625
5711
  }])
5626
5712
  }, null) : createElementVNode("div", {
5627
5713
  "class": "v-progress-linear__indeterminate"
@@ -24379,6 +24465,42 @@ function appendIfDirectory(path, item) {
24379
24465
  return item.isDirectory ? `${path}/${item.name}` : path;
24380
24466
  }
24381
24467
 
24468
+ // Utilities
24469
+ // Composables
24470
+ const makeFileFilterProps = propsFactory({
24471
+ filterByType: String
24472
+ }, 'file-accept');
24473
+ function useFileFilter(props) {
24474
+ const fileFilter = computed(() => props.filterByType ? createFilter(props.filterByType) : null);
24475
+ function filterAccepted(files) {
24476
+ if (fileFilter.value) {
24477
+ const accepted = files.filter(fileFilter.value);
24478
+ return {
24479
+ accepted,
24480
+ rejected: files.filter(f => !accepted.includes(f))
24481
+ };
24482
+ }
24483
+ return {
24484
+ accepted: files,
24485
+ rejected: []
24486
+ };
24487
+ }
24488
+ return {
24489
+ filterAccepted
24490
+ };
24491
+ }
24492
+ function createFilter(v) {
24493
+ const types = v.split(',').map(x => x.trim().toLowerCase());
24494
+ const extensionsToMatch = types.filter(x => x.startsWith('.'));
24495
+ const wildcards = types.filter(x => x.endsWith('/*'));
24496
+ const typesToMatch = types.filter(x => !extensionsToMatch.includes(x) && !wildcards.includes(x));
24497
+ return file => {
24498
+ const extension = file.name.split('.').at(-1)?.toLowerCase() ?? '';
24499
+ const typeGroup = file.type.split('/').at(0)?.toLowerCase() ?? '';
24500
+ return typesToMatch.includes(file.type) || extensionsToMatch.includes(`.${extension}`) || wildcards.includes(`${typeGroup}/*`);
24501
+ };
24502
+ }
24503
+
24382
24504
  // Types
24383
24505
 
24384
24506
  const makeVFileInputProps = propsFactory({
@@ -24411,6 +24533,7 @@ const makeVFileInputProps = propsFactory({
24411
24533
  return wrapInArray(val).every(v => v != null && typeof v === 'object');
24412
24534
  }
24413
24535
  },
24536
+ ...makeFileFilterProps(),
24414
24537
  ...makeVFieldProps({
24415
24538
  clearable: true
24416
24539
  })
@@ -24423,7 +24546,8 @@ const VFileInput = genericComponent()({
24423
24546
  'click:control': e => true,
24424
24547
  'mousedown:control': e => true,
24425
24548
  'update:focused': focused => true,
24426
- 'update:modelValue': files => true
24549
+ 'update:modelValue': files => true,
24550
+ rejected: files => true
24427
24551
  },
24428
24552
  setup(props, _ref) {
24429
24553
  let {
@@ -24434,6 +24558,9 @@ const VFileInput = genericComponent()({
24434
24558
  const {
24435
24559
  t
24436
24560
  } = useLocale();
24561
+ const {
24562
+ filterAccepted
24563
+ } = useFileFilter(props);
24437
24564
  const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
24438
24565
  const {
24439
24566
  isFocused,
@@ -24507,14 +24634,38 @@ const VFileInput = genericComponent()({
24507
24634
  e.stopImmediatePropagation();
24508
24635
  isDragging.value = false;
24509
24636
  if (!inputRef.value || !hasFilesOrFolders(e)) return;
24637
+ const allDroppedFiles = await handleDrop(e);
24638
+ selectAccepted(allDroppedFiles);
24639
+ }
24640
+ function onFileSelection(e) {
24641
+ if (!e.target || e.repack) return; // prevent loop
24642
+
24643
+ if (!props.filterByType) {
24644
+ const target = e.target;
24645
+ model.value = [...(target.files ?? [])];
24646
+ } else {
24647
+ selectAccepted([...e.target.files]);
24648
+ }
24649
+ }
24650
+ function selectAccepted(files) {
24510
24651
  const dataTransfer = new DataTransfer();
24511
- for (const file of await handleDrop(e)) {
24652
+ const {
24653
+ accepted,
24654
+ rejected
24655
+ } = filterAccepted(files);
24656
+ if (rejected.length) {
24657
+ emit('rejected', rejected);
24658
+ }
24659
+ for (const file of accepted) {
24512
24660
  dataTransfer.items.add(file);
24513
24661
  }
24514
24662
  inputRef.value.files = dataTransfer.files;
24515
- inputRef.value.dispatchEvent(new Event('change', {
24663
+ model.value = [...dataTransfer.files];
24664
+ const event = new Event('change', {
24516
24665
  bubbles: true
24517
- }));
24666
+ });
24667
+ event.repack = true;
24668
+ inputRef.value.dispatchEvent(event);
24518
24669
  }
24519
24670
  watch(model, newValue => {
24520
24671
  const hasModelReset = !Array.isArray(newValue) || !newValue.length;
@@ -24531,6 +24682,8 @@ const VFileInput = genericComponent()({
24531
24682
  ...inputProps
24532
24683
  } = VInput.filterProps(props);
24533
24684
  const fieldProps = VField.filterProps(props);
24685
+ const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
24686
+ const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
24534
24687
  return createVNode(VInput, mergeProps({
24535
24688
  "ref": vInputRef,
24536
24689
  "modelValue": props.multiple ? model.value : model.value[0],
@@ -24584,6 +24737,7 @@ const VFileInput = genericComponent()({
24584
24737
  return createElementVNode(Fragment, null, [createElementVNode("input", mergeProps({
24585
24738
  "ref": inputRef,
24586
24739
  "type": "file",
24740
+ "accept": inputAccept,
24587
24741
  "readonly": isReadonly.value,
24588
24742
  "disabled": isDisabled.value,
24589
24743
  "multiple": props.multiple,
@@ -24593,11 +24747,7 @@ const VFileInput = genericComponent()({
24593
24747
  if (isReadonly.value) e.preventDefault();
24594
24748
  onFocus();
24595
24749
  },
24596
- "onChange": e => {
24597
- if (!e.target) return;
24598
- const target = e.target;
24599
- model.value = [...(target.files ?? [])];
24600
- },
24750
+ "onChange": onFileSelection,
24601
24751
  "onDragleave": onDragleave,
24602
24752
  "onFocus": onFocus,
24603
24753
  "onBlur": blur
@@ -31392,7 +31542,7 @@ function createVuetify$1() {
31392
31542
  };
31393
31543
  });
31394
31544
  }
31395
- const version$1 = "3.9.0-dev.2025-07-15";
31545
+ const version$1 = "3.9.0-dev.2025-07-16";
31396
31546
  createVuetify$1.version = version$1;
31397
31547
 
31398
31548
  // Vue's inject() can only be used in setup
@@ -31417,7 +31567,7 @@ const createVuetify = function () {
31417
31567
  ...options
31418
31568
  });
31419
31569
  };
31420
- const version = "3.9.0-dev.2025-07-15";
31570
+ const version = "3.9.0-dev.2025-07-16";
31421
31571
  createVuetify.version = version;
31422
31572
 
31423
31573
  export { index as blueprints, components, createVuetify, directives, useDate, useDefaults, useDisplay, useGoTo, useHotkey, useLayout, useLocale, useRtl, useTheme, version };