@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.
- package/CHANGELOG.md +9 -3
- package/dist/json/attributes.json +3261 -3241
- package/dist/json/importMap-labs.json +24 -24
- package/dist/json/importMap.json +202 -202
- package/dist/json/tags.json +5 -0
- package/dist/json/web-types.json +6129 -6059
- package/dist/vuetify-labs.cjs +204 -25
- package/dist/vuetify-labs.css +4800 -4798
- package/dist/vuetify-labs.d.ts +129 -67
- package/dist/vuetify-labs.esm.js +204 -25
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +204 -25
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.cjs +166 -16
- package/dist/vuetify.cjs.map +1 -1
- package/dist/vuetify.css +3987 -3985
- package/dist/vuetify.d.ts +119 -67
- package/dist/vuetify.esm.js +166 -16
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +166 -16
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +710 -688
- package/dist/vuetify.min.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/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/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 +67 -67
- 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.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
|
*/
|
@@ -5468,6 +5468,69 @@
|
|
5468
5468
|
};
|
5469
5469
|
}
|
5470
5470
|
|
5471
|
+
// Utilities
|
5472
|
+
|
5473
|
+
// Types
|
5474
|
+
|
5475
|
+
// Composables
|
5476
|
+
const makeChunksProps = propsFactory({
|
5477
|
+
chunkCount: {
|
5478
|
+
type: [Number, String],
|
5479
|
+
default: null
|
5480
|
+
},
|
5481
|
+
chunkWidth: {
|
5482
|
+
type: [Number, String],
|
5483
|
+
default: null
|
5484
|
+
},
|
5485
|
+
chunkGap: {
|
5486
|
+
type: [Number, String],
|
5487
|
+
default: 4
|
5488
|
+
}
|
5489
|
+
}, 'chunks');
|
5490
|
+
function useChunks(props, containerWidth) {
|
5491
|
+
const hasChunks = vue.toRef(() => !!props.chunkCount || !!props.chunkWidth);
|
5492
|
+
const chunkWidth = vue.computed(() => {
|
5493
|
+
const containerSize = vue.toValue(containerWidth);
|
5494
|
+
if (!containerSize) {
|
5495
|
+
return 0;
|
5496
|
+
}
|
5497
|
+
if (!props.chunkCount) {
|
5498
|
+
return Number(props.chunkWidth);
|
5499
|
+
}
|
5500
|
+
const count = Number(props.chunkCount);
|
5501
|
+
const availableWidth = containerSize - Number(props.chunkGap) * (count - 1);
|
5502
|
+
return availableWidth / count;
|
5503
|
+
});
|
5504
|
+
const chunkGap = vue.toRef(() => Number(props.chunkGap));
|
5505
|
+
const chunksMaskStyles = vue.computed(() => {
|
5506
|
+
if (!hasChunks.value) {
|
5507
|
+
return {};
|
5508
|
+
}
|
5509
|
+
const chunkGapPx = convertToUnit(chunkGap.value);
|
5510
|
+
const chunkWidthPx = convertToUnit(chunkWidth.value);
|
5511
|
+
return {
|
5512
|
+
maskRepeat: 'repeat-x',
|
5513
|
+
maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
|
5514
|
+
maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
|
5515
|
+
};
|
5516
|
+
});
|
5517
|
+
function snapValueToChunk(val) {
|
5518
|
+
const containerSize = vue.toValue(containerWidth);
|
5519
|
+
if (!containerSize) {
|
5520
|
+
return val;
|
5521
|
+
}
|
5522
|
+
const gapRelativeSize = 100 * chunkGap.value / containerSize;
|
5523
|
+
const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;
|
5524
|
+
const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize);
|
5525
|
+
return clamp(0, filledChunks * chunkRelativeSize - gapRelativeSize / 2, 100);
|
5526
|
+
}
|
5527
|
+
return {
|
5528
|
+
hasChunks,
|
5529
|
+
chunksMaskStyles,
|
5530
|
+
snapValueToChunk
|
5531
|
+
};
|
5532
|
+
}
|
5533
|
+
|
5471
5534
|
const makeVProgressLinearProps = propsFactory({
|
5472
5535
|
absolute: Boolean,
|
5473
5536
|
active: {
|
@@ -5502,6 +5565,7 @@
|
|
5502
5565
|
stream: Boolean,
|
5503
5566
|
striped: Boolean,
|
5504
5567
|
roundedBar: Boolean,
|
5568
|
+
...makeChunksProps(),
|
5505
5569
|
...makeComponentProps(),
|
5506
5570
|
...makeLocationProps({
|
5507
5571
|
location: 'top'
|
@@ -5520,6 +5584,7 @@
|
|
5520
5584
|
let {
|
5521
5585
|
slots
|
5522
5586
|
} = _ref;
|
5587
|
+
const root = vue.ref();
|
5523
5588
|
const progress = useProxiedModel(props, 'modelValue');
|
5524
5589
|
const {
|
5525
5590
|
isRtl,
|
@@ -5561,6 +5626,24 @@
|
|
5561
5626
|
const isReversed = vue.computed(() => isRtl.value !== props.reverse);
|
5562
5627
|
const transition = vue.computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
|
5563
5628
|
const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
|
5629
|
+
const containerWidth = vue.shallowRef(0);
|
5630
|
+
const {
|
5631
|
+
hasChunks,
|
5632
|
+
chunksMaskStyles,
|
5633
|
+
snapValueToChunk
|
5634
|
+
} = useChunks(props, containerWidth);
|
5635
|
+
useToggleScope(hasChunks, () => {
|
5636
|
+
const {
|
5637
|
+
resizeRef
|
5638
|
+
} = useResizeObserver(entries => containerWidth.value = entries[0].contentRect.width);
|
5639
|
+
vue.watchEffect(() => resizeRef.value = root.value);
|
5640
|
+
});
|
5641
|
+
const bufferWidth = vue.computed(() => {
|
5642
|
+
return hasChunks.value ? snapValueToChunk(normalizedBuffer.value) : normalizedBuffer.value;
|
5643
|
+
});
|
5644
|
+
const barWidth = vue.computed(() => {
|
5645
|
+
return hasChunks.value ? snapValueToChunk(normalizedValue.value) : normalizedValue.value;
|
5646
|
+
});
|
5564
5647
|
function handleClick(e) {
|
5565
5648
|
if (!intersectionRef.value) return;
|
5566
5649
|
const {
|
@@ -5571,8 +5654,11 @@
|
|
5571
5654
|
const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
|
5572
5655
|
progress.value = Math.round(value / width * max.value);
|
5573
5656
|
}
|
5657
|
+
vue.watchEffect(() => {
|
5658
|
+
intersectionRef.value = root.value;
|
5659
|
+
});
|
5574
5660
|
useRender(() => vue.createVNode(props.tag, {
|
5575
|
-
"ref":
|
5661
|
+
"ref": root,
|
5576
5662
|
"class": vue.normalizeClass(['v-progress-linear', {
|
5577
5663
|
'v-progress-linear--absolute': props.absolute,
|
5578
5664
|
'v-progress-linear--active': props.active && isIntersecting.value,
|
@@ -5587,7 +5673,7 @@
|
|
5587
5673
|
height: props.active ? convertToUnit(height.value) : 0,
|
5588
5674
|
'--v-progress-linear-height': convertToUnit(height.value),
|
5589
5675
|
...(props.absolute ? locationStyles.value : {})
|
5590
|
-
}, props.style]),
|
5676
|
+
}, chunksMaskStyles.value, props.style]),
|
5591
5677
|
"role": "progressbar",
|
5592
5678
|
"aria-hidden": props.active ? 'false' : 'true',
|
5593
5679
|
"aria-valuemin": "0",
|
@@ -5617,7 +5703,7 @@
|
|
5617
5703
|
"class": vue.normalizeClass(['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined]),
|
5618
5704
|
"style": vue.normalizeStyle([bufferColorStyles.value, {
|
5619
5705
|
opacity: parseFloat(props.bufferOpacity),
|
5620
|
-
width: convertToUnit(
|
5706
|
+
width: convertToUnit(bufferWidth.value, '%')
|
5621
5707
|
}])
|
5622
5708
|
}, null), vue.createVNode(vue.Transition, {
|
5623
5709
|
"name": transition.value
|
@@ -5625,7 +5711,7 @@
|
|
5625
5711
|
default: () => [!props.indeterminate ? vue.createElementVNode("div", {
|
5626
5712
|
"class": vue.normalizeClass(['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined]),
|
5627
5713
|
"style": vue.normalizeStyle([barColorStyles.value, {
|
5628
|
-
width: convertToUnit(
|
5714
|
+
width: convertToUnit(barWidth.value, '%')
|
5629
5715
|
}])
|
5630
5716
|
}, null) : vue.createElementVNode("div", {
|
5631
5717
|
"class": "v-progress-linear__indeterminate"
|
@@ -24383,6 +24469,42 @@
|
|
24383
24469
|
return item.isDirectory ? `${path}/${item.name}` : path;
|
24384
24470
|
}
|
24385
24471
|
|
24472
|
+
// Utilities
|
24473
|
+
// Composables
|
24474
|
+
const makeFileFilterProps = propsFactory({
|
24475
|
+
filterByType: String
|
24476
|
+
}, 'file-accept');
|
24477
|
+
function useFileFilter(props) {
|
24478
|
+
const fileFilter = vue.computed(() => props.filterByType ? createFilter(props.filterByType) : null);
|
24479
|
+
function filterAccepted(files) {
|
24480
|
+
if (fileFilter.value) {
|
24481
|
+
const accepted = files.filter(fileFilter.value);
|
24482
|
+
return {
|
24483
|
+
accepted,
|
24484
|
+
rejected: files.filter(f => !accepted.includes(f))
|
24485
|
+
};
|
24486
|
+
}
|
24487
|
+
return {
|
24488
|
+
accepted: files,
|
24489
|
+
rejected: []
|
24490
|
+
};
|
24491
|
+
}
|
24492
|
+
return {
|
24493
|
+
filterAccepted
|
24494
|
+
};
|
24495
|
+
}
|
24496
|
+
function createFilter(v) {
|
24497
|
+
const types = v.split(',').map(x => x.trim().toLowerCase());
|
24498
|
+
const extensionsToMatch = types.filter(x => x.startsWith('.'));
|
24499
|
+
const wildcards = types.filter(x => x.endsWith('/*'));
|
24500
|
+
const typesToMatch = types.filter(x => !extensionsToMatch.includes(x) && !wildcards.includes(x));
|
24501
|
+
return file => {
|
24502
|
+
const extension = file.name.split('.').at(-1)?.toLowerCase() ?? '';
|
24503
|
+
const typeGroup = file.type.split('/').at(0)?.toLowerCase() ?? '';
|
24504
|
+
return typesToMatch.includes(file.type) || extensionsToMatch.includes(`.${extension}`) || wildcards.includes(`${typeGroup}/*`);
|
24505
|
+
};
|
24506
|
+
}
|
24507
|
+
|
24386
24508
|
// Types
|
24387
24509
|
|
24388
24510
|
const makeVFileInputProps = propsFactory({
|
@@ -24415,6 +24537,7 @@
|
|
24415
24537
|
return wrapInArray(val).every(v => v != null && typeof v === 'object');
|
24416
24538
|
}
|
24417
24539
|
},
|
24540
|
+
...makeFileFilterProps(),
|
24418
24541
|
...makeVFieldProps({
|
24419
24542
|
clearable: true
|
24420
24543
|
})
|
@@ -24427,7 +24550,8 @@
|
|
24427
24550
|
'click:control': e => true,
|
24428
24551
|
'mousedown:control': e => true,
|
24429
24552
|
'update:focused': focused => true,
|
24430
|
-
'update:modelValue': files => true
|
24553
|
+
'update:modelValue': files => true,
|
24554
|
+
rejected: files => true
|
24431
24555
|
},
|
24432
24556
|
setup(props, _ref) {
|
24433
24557
|
let {
|
@@ -24438,6 +24562,9 @@
|
|
24438
24562
|
const {
|
24439
24563
|
t
|
24440
24564
|
} = useLocale();
|
24565
|
+
const {
|
24566
|
+
filterAccepted
|
24567
|
+
} = useFileFilter(props);
|
24441
24568
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
|
24442
24569
|
const {
|
24443
24570
|
isFocused,
|
@@ -24511,14 +24638,38 @@
|
|
24511
24638
|
e.stopImmediatePropagation();
|
24512
24639
|
isDragging.value = false;
|
24513
24640
|
if (!inputRef.value || !hasFilesOrFolders(e)) return;
|
24641
|
+
const allDroppedFiles = await handleDrop(e);
|
24642
|
+
selectAccepted(allDroppedFiles);
|
24643
|
+
}
|
24644
|
+
function onFileSelection(e) {
|
24645
|
+
if (!e.target || e.repack) return; // prevent loop
|
24646
|
+
|
24647
|
+
if (!props.filterByType) {
|
24648
|
+
const target = e.target;
|
24649
|
+
model.value = [...(target.files ?? [])];
|
24650
|
+
} else {
|
24651
|
+
selectAccepted([...e.target.files]);
|
24652
|
+
}
|
24653
|
+
}
|
24654
|
+
function selectAccepted(files) {
|
24514
24655
|
const dataTransfer = new DataTransfer();
|
24515
|
-
|
24656
|
+
const {
|
24657
|
+
accepted,
|
24658
|
+
rejected
|
24659
|
+
} = filterAccepted(files);
|
24660
|
+
if (rejected.length) {
|
24661
|
+
emit('rejected', rejected);
|
24662
|
+
}
|
24663
|
+
for (const file of accepted) {
|
24516
24664
|
dataTransfer.items.add(file);
|
24517
24665
|
}
|
24518
24666
|
inputRef.value.files = dataTransfer.files;
|
24519
|
-
|
24667
|
+
model.value = [...dataTransfer.files];
|
24668
|
+
const event = new Event('change', {
|
24520
24669
|
bubbles: true
|
24521
|
-
})
|
24670
|
+
});
|
24671
|
+
event.repack = true;
|
24672
|
+
inputRef.value.dispatchEvent(event);
|
24522
24673
|
}
|
24523
24674
|
vue.watch(model, newValue => {
|
24524
24675
|
const hasModelReset = !Array.isArray(newValue) || !newValue.length;
|
@@ -24535,6 +24686,8 @@
|
|
24535
24686
|
...inputProps
|
24536
24687
|
} = VInput.filterProps(props);
|
24537
24688
|
const fieldProps = VField.filterProps(props);
|
24689
|
+
const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
|
24690
|
+
const inputAccept = expectsDirectory ? undefined : props.filterByType ?? String(attrs.accept);
|
24538
24691
|
return vue.createVNode(VInput, vue.mergeProps({
|
24539
24692
|
"ref": vInputRef,
|
24540
24693
|
"modelValue": props.multiple ? model.value : model.value[0],
|
@@ -24588,6 +24741,7 @@
|
|
24588
24741
|
return vue.createElementVNode(vue.Fragment, null, [vue.createElementVNode("input", vue.mergeProps({
|
24589
24742
|
"ref": inputRef,
|
24590
24743
|
"type": "file",
|
24744
|
+
"accept": inputAccept,
|
24591
24745
|
"readonly": isReadonly.value,
|
24592
24746
|
"disabled": isDisabled.value,
|
24593
24747
|
"multiple": props.multiple,
|
@@ -24597,11 +24751,7 @@
|
|
24597
24751
|
if (isReadonly.value) e.preventDefault();
|
24598
24752
|
onFocus();
|
24599
24753
|
},
|
24600
|
-
"onChange":
|
24601
|
-
if (!e.target) return;
|
24602
|
-
const target = e.target;
|
24603
|
-
model.value = [...(target.files ?? [])];
|
24604
|
-
},
|
24754
|
+
"onChange": onFileSelection,
|
24605
24755
|
"onDragleave": onDragleave,
|
24606
24756
|
"onFocus": onFocus,
|
24607
24757
|
"onBlur": blur
|
@@ -31396,7 +31546,7 @@
|
|
31396
31546
|
};
|
31397
31547
|
});
|
31398
31548
|
}
|
31399
|
-
const version$1 = "3.9.0-dev.2025-07-
|
31549
|
+
const version$1 = "3.9.0-dev.2025-07-16";
|
31400
31550
|
createVuetify$1.version = version$1;
|
31401
31551
|
|
31402
31552
|
// Vue's inject() can only be used in setup
|
@@ -31421,7 +31571,7 @@
|
|
31421
31571
|
...options
|
31422
31572
|
});
|
31423
31573
|
};
|
31424
|
-
const version = "3.9.0-dev.2025-07-
|
31574
|
+
const version = "3.9.0-dev.2025-07-16";
|
31425
31575
|
createVuetify.version = version;
|
31426
31576
|
|
31427
31577
|
exports.blueprints = index;
|