@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-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"
|
@@ -24105,6 +24191,42 @@
|
|
24105
24191
|
return item.isDirectory ? `${path}/${item.name}` : path;
|
24106
24192
|
}
|
24107
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
|
+
|
24108
24230
|
// Types
|
24109
24231
|
|
24110
24232
|
const makeVFileInputProps = propsFactory({
|
@@ -24137,6 +24259,7 @@
|
|
24137
24259
|
return wrapInArray(val).every(v => v != null && typeof v === 'object');
|
24138
24260
|
}
|
24139
24261
|
},
|
24262
|
+
...makeFileFilterProps(),
|
24140
24263
|
...makeVFieldProps({
|
24141
24264
|
clearable: true
|
24142
24265
|
})
|
@@ -24149,7 +24272,8 @@
|
|
24149
24272
|
'click:control': e => true,
|
24150
24273
|
'mousedown:control': e => true,
|
24151
24274
|
'update:focused': focused => true,
|
24152
|
-
'update:modelValue': files => true
|
24275
|
+
'update:modelValue': files => true,
|
24276
|
+
rejected: files => true
|
24153
24277
|
},
|
24154
24278
|
setup(props, _ref) {
|
24155
24279
|
let {
|
@@ -24160,6 +24284,9 @@
|
|
24160
24284
|
const {
|
24161
24285
|
t
|
24162
24286
|
} = useLocale();
|
24287
|
+
const {
|
24288
|
+
filterAccepted
|
24289
|
+
} = useFileFilter(props);
|
24163
24290
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
|
24164
24291
|
const {
|
24165
24292
|
isFocused,
|
@@ -24233,14 +24360,38 @@
|
|
24233
24360
|
e.stopImmediatePropagation();
|
24234
24361
|
isDragging.value = false;
|
24235
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) {
|
24236
24377
|
const dataTransfer = new DataTransfer();
|
24237
|
-
|
24378
|
+
const {
|
24379
|
+
accepted,
|
24380
|
+
rejected
|
24381
|
+
} = filterAccepted(files);
|
24382
|
+
if (rejected.length) {
|
24383
|
+
emit('rejected', rejected);
|
24384
|
+
}
|
24385
|
+
for (const file of accepted) {
|
24238
24386
|
dataTransfer.items.add(file);
|
24239
24387
|
}
|
24240
24388
|
inputRef.value.files = dataTransfer.files;
|
24241
|
-
|
24389
|
+
model.value = [...dataTransfer.files];
|
24390
|
+
const event = new Event('change', {
|
24242
24391
|
bubbles: true
|
24243
|
-
})
|
24392
|
+
});
|
24393
|
+
event.repack = true;
|
24394
|
+
inputRef.value.dispatchEvent(event);
|
24244
24395
|
}
|
24245
24396
|
vue.watch(model, newValue => {
|
24246
24397
|
const hasModelReset = !Array.isArray(newValue) || !newValue.length;
|
@@ -24257,6 +24408,8 @@
|
|
24257
24408
|
...inputProps
|
24258
24409
|
} = VInput.filterProps(props);
|
24259
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);
|
24260
24413
|
return vue.createVNode(VInput, vue.mergeProps({
|
24261
24414
|
"ref": vInputRef,
|
24262
24415
|
"modelValue": props.multiple ? model.value : model.value[0],
|
@@ -24310,6 +24463,7 @@
|
|
24310
24463
|
return vue.createElementVNode(vue.Fragment, null, [vue.createElementVNode("input", vue.mergeProps({
|
24311
24464
|
"ref": inputRef,
|
24312
24465
|
"type": "file",
|
24466
|
+
"accept": inputAccept,
|
24313
24467
|
"readonly": isReadonly.value,
|
24314
24468
|
"disabled": isDisabled.value,
|
24315
24469
|
"multiple": props.multiple,
|
@@ -24319,11 +24473,7 @@
|
|
24319
24473
|
if (isReadonly.value) e.preventDefault();
|
24320
24474
|
onFocus();
|
24321
24475
|
},
|
24322
|
-
"onChange":
|
24323
|
-
if (!e.target) return;
|
24324
|
-
const target = e.target;
|
24325
|
-
model.value = [...(target.files ?? [])];
|
24326
|
-
},
|
24476
|
+
"onChange": onFileSelection,
|
24327
24477
|
"onDragleave": onDragleave,
|
24328
24478
|
"onFocus": onFocus,
|
24329
24479
|
"onBlur": blur
|
@@ -31828,6 +31978,7 @@
|
|
31828
31978
|
},
|
31829
31979
|
showSize: Boolean,
|
31830
31980
|
name: String,
|
31981
|
+
...makeFileFilterProps(),
|
31831
31982
|
...makeDelayProps(),
|
31832
31983
|
...makeDensityProps(),
|
31833
31984
|
...pick(makeVDividerProps({
|
@@ -31840,11 +31991,13 @@
|
|
31840
31991
|
inheritAttrs: false,
|
31841
31992
|
props: makeVFileUploadProps(),
|
31842
31993
|
emits: {
|
31843
|
-
'update:modelValue': files => true
|
31994
|
+
'update:modelValue': files => true,
|
31995
|
+
rejected: files => true
|
31844
31996
|
},
|
31845
31997
|
setup(props, _ref) {
|
31846
31998
|
let {
|
31847
31999
|
attrs,
|
32000
|
+
emit,
|
31848
32001
|
slots
|
31849
32002
|
} = _ref;
|
31850
32003
|
const {
|
@@ -31853,6 +32006,9 @@
|
|
31853
32006
|
const {
|
31854
32007
|
densityClasses
|
31855
32008
|
} = useDensity(props);
|
32009
|
+
const {
|
32010
|
+
filterAccepted
|
32011
|
+
} = useFileFilter(props);
|
31856
32012
|
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
|
31857
32013
|
const isDragging = vue.shallowRef(false);
|
31858
32014
|
const vSheetRef = vue.ref(null);
|
@@ -31874,14 +32030,38 @@
|
|
31874
32030
|
e.stopImmediatePropagation();
|
31875
32031
|
isDragging.value = false;
|
31876
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) {
|
31877
32047
|
const dataTransfer = new DataTransfer();
|
31878
|
-
|
32048
|
+
const {
|
32049
|
+
accepted,
|
32050
|
+
rejected
|
32051
|
+
} = filterAccepted(files);
|
32052
|
+
if (rejected.length) {
|
32053
|
+
emit('rejected', rejected);
|
32054
|
+
}
|
32055
|
+
for (const file of accepted) {
|
31879
32056
|
dataTransfer.items.add(file);
|
31880
32057
|
}
|
31881
32058
|
inputRef.value.files = dataTransfer.files;
|
31882
|
-
|
32059
|
+
model.value = [...dataTransfer.files];
|
32060
|
+
const event = new Event('change', {
|
31883
32061
|
bubbles: true
|
31884
|
-
})
|
32062
|
+
});
|
32063
|
+
event.repack = true;
|
32064
|
+
inputRef.value.dispatchEvent(event);
|
31885
32065
|
}
|
31886
32066
|
function onClick() {
|
31887
32067
|
inputRef.value?.click();
|
@@ -31899,17 +32079,16 @@
|
|
31899
32079
|
const cardProps = VSheet.filterProps(props);
|
31900
32080
|
const dividerProps = VDivider.filterProps(props);
|
31901
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);
|
31902
32084
|
const inputNode = vue.createElementVNode("input", vue.mergeProps({
|
31903
32085
|
"ref": inputRef,
|
31904
32086
|
"type": "file",
|
32087
|
+
"accept": inputAccept,
|
31905
32088
|
"disabled": props.disabled,
|
31906
32089
|
"multiple": props.multiple,
|
31907
32090
|
"name": props.name,
|
31908
|
-
"onChange":
|
31909
|
-
if (!e.target) return;
|
31910
|
-
const target = e.target;
|
31911
|
-
model.value = [...(target.files ?? [])];
|
31912
|
-
}
|
32091
|
+
"onChange": onFileSelection
|
31913
32092
|
}, inputAttrs), null);
|
31914
32093
|
return vue.createElementVNode(vue.Fragment, null, [vue.createVNode(VSheet, vue.mergeProps({
|
31915
32094
|
"ref": vSheetRef
|
@@ -33686,7 +33865,7 @@
|
|
33686
33865
|
};
|
33687
33866
|
});
|
33688
33867
|
}
|
33689
|
-
const version$1 = "3.9.0-dev.2025-07-
|
33868
|
+
const version$1 = "3.9.0-dev.2025-07-16";
|
33690
33869
|
createVuetify$1.version = version$1;
|
33691
33870
|
|
33692
33871
|
// Vue's inject() can only be used in setup
|
@@ -33984,7 +34163,7 @@
|
|
33984
34163
|
|
33985
34164
|
/* eslint-disable local-rules/sort-imports */
|
33986
34165
|
|
33987
|
-
const version = "3.9.0-dev.2025-07-
|
34166
|
+
const version = "3.9.0-dev.2025-07-16";
|
33988
34167
|
|
33989
34168
|
/* eslint-disable local-rules/sort-imports */
|
33990
34169
|
|