@vuetify/nightly 3.8.2-master.2025-04-27 → 3.8.3-dev.2025-04-29

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 (57) hide show
  1. package/CHANGELOG.md +13 -32
  2. package/dist/json/attributes.json +2092 -2084
  3. package/dist/json/importMap-labs.json +24 -24
  4. package/dist/json/importMap.json +148 -148
  5. package/dist/json/tags.json +2 -0
  6. package/dist/json/web-types.json +3854 -3834
  7. package/dist/vuetify-labs.cjs +146 -36
  8. package/dist/vuetify-labs.css +3420 -3397
  9. package/dist/vuetify-labs.d.ts +101 -64
  10. package/dist/vuetify-labs.esm.js +147 -37
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +146 -36
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +146 -36
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +3284 -3261
  17. package/dist/vuetify.d.ts +101 -64
  18. package/dist/vuetify.esm.js +147 -37
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +146 -36
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +1201 -1188
  24. package/dist/vuetify.min.js.map +1 -1
  25. package/lib/components/VBtnGroup/VBtnGroup.css +30 -7
  26. package/lib/components/VBtnGroup/VBtnGroup.d.ts +58 -32
  27. package/lib/components/VBtnGroup/VBtnGroup.js +7 -3
  28. package/lib/components/VBtnGroup/VBtnGroup.js.map +1 -1
  29. package/lib/components/VBtnGroup/VBtnGroup.sass +44 -17
  30. package/lib/components/VBtnToggle/VBtnToggle.d.ts +25 -0
  31. package/lib/components/VInput/VInput.d.ts +1 -1
  32. package/lib/components/VOverlay/VOverlay.css +1 -1
  33. package/lib/components/VOverlay/_variables.scss +1 -1
  34. package/lib/components/VOverlay/locationStrategies.d.ts +4 -0
  35. package/lib/components/VOverlay/locationStrategies.js +23 -3
  36. package/lib/components/VOverlay/locationStrategies.js.map +1 -1
  37. package/lib/composables/calendar.d.ts +1 -0
  38. package/lib/composables/calendar.js.map +1 -1
  39. package/lib/composables/defaults.js +6 -3
  40. package/lib/composables/defaults.js.map +1 -1
  41. package/lib/composables/theme.d.ts +6 -1
  42. package/lib/composables/theme.js +94 -26
  43. package/lib/composables/theme.js.map +1 -1
  44. package/lib/composables/virtual.js +6 -1
  45. package/lib/composables/virtual.js.map +1 -1
  46. package/lib/entry-bundler.js +1 -1
  47. package/lib/entry-bundler.js.map +1 -1
  48. package/lib/framework.d.ts +63 -54
  49. package/lib/framework.js +1 -1
  50. package/lib/framework.js.map +1 -1
  51. package/lib/util/globals.d.ts +1 -0
  52. package/lib/util/globals.js +1 -0
  53. package/lib/util/globals.js.map +1 -1
  54. package/lib/util/helpers.d.ts +2 -0
  55. package/lib/util/helpers.js +7 -0
  56. package/lib/util/helpers.js.map +1 -1
  57. package/package.json +3 -2
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * Vuetify v3.8.2-master.2025-04-27
2
+ * Vuetify v3.8.3-dev.2025-04-29
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
- import { shallowRef, reactive, watchEffect, toRef, capitalize, unref, Fragment, isVNode, Comment, warn, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject as inject$1, defineComponent as defineComponent$1, h, camelize, onBeforeUnmount, watch, readonly, onMounted, useId, onDeactivated, onActivated, onScopeDispose, effectScope, toRaw, createVNode, TransitionGroup, Transition, mergeProps, toRefs, toValue, isRef, onBeforeMount, nextTick, withDirectives, resolveDirective, vShow, onUpdated, Text, resolveDynamicComponent, toDisplayString, markRaw, Teleport, cloneVNode, createTextVNode, onUnmounted, onBeforeUpdate, withModifiers, vModelText, resolveComponent, render } from 'vue';
7
+ import { shallowRef, reactive, watchEffect, toRef, capitalize, unref, Fragment, isVNode, Comment, warn, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject as inject$1, defineComponent as defineComponent$1, h, camelize, onBeforeUnmount, watch, readonly, onMounted, useId, onDeactivated, onActivated, onScopeDispose, effectScope, toRaw, getCurrentScope, createVNode, TransitionGroup, Transition, mergeProps, toRefs, toValue, isRef, onBeforeMount, nextTick, withDirectives, resolveDirective, vShow, onUpdated, Text, resolveDynamicComponent, toDisplayString, markRaw, Teleport, cloneVNode, createTextVNode, onUnmounted, onBeforeUpdate, withModifiers, vModelText, resolveComponent, render } from 'vue';
8
8
 
9
9
  // Types
10
10
  // eslint-disable-line vue/prefer-import-from-vue
@@ -81,6 +81,7 @@ const IN_BROWSER = typeof window !== 'undefined';
81
81
  const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
82
82
  const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
83
83
  const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
84
+ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && 'matchMedia' in window && typeof window.matchMedia === 'function';
84
85
 
85
86
  function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
86
87
  function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
@@ -412,6 +413,9 @@ class CircularBuffer {
412
413
  _classPrivateFieldInitSpec(this, _pointer, 0);
413
414
  this.size = size;
414
415
  }
416
+ get isFull() {
417
+ return _classPrivateFieldGet(_arr, this).length === this.size;
418
+ }
415
419
  push(val) {
416
420
  _classPrivateFieldGet(_arr, this)[_classPrivateFieldGet(_pointer, this)] = val;
417
421
  _classPrivateFieldSet(_pointer, this, (_classPrivateFieldGet(_pointer, this) + 1) % this.size);
@@ -419,6 +423,10 @@ class CircularBuffer {
419
423
  values() {
420
424
  return _classPrivateFieldGet(_arr, this).slice(_classPrivateFieldGet(_pointer, this)).concat(_classPrivateFieldGet(_arr, this).slice(0, _classPrivateFieldGet(_pointer, this)));
421
425
  }
426
+ clear() {
427
+ _classPrivateFieldGet(_arr, this).length = 0;
428
+ _classPrivateFieldSet(_pointer, this, 0);
429
+ }
422
430
  }
423
431
  function getEventCoordinates(e) {
424
432
  if ('touches' in e) {
@@ -1338,7 +1346,7 @@ function provideDefaults(defaults, options) {
1338
1346
  return newDefaults;
1339
1347
  }
1340
1348
  function propIsDefined(vnode, prop) {
1341
- return typeof vnode.props?.[prop] !== 'undefined' || typeof vnode.props?.[toKebabCase(prop)] !== 'undefined';
1349
+ return vnode.props && (typeof vnode.props[prop] !== 'undefined' || typeof vnode.props[toKebabCase(prop)] !== 'undefined');
1342
1350
  }
1343
1351
  function internalUseDefaults() {
1344
1352
  let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -1355,9 +1363,12 @@ function internalUseDefaults() {
1355
1363
  const propValue = Reflect.get(target, prop);
1356
1364
  if (prop === 'class' || prop === 'style') {
1357
1365
  return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
1358
- } else if (typeof prop === 'string' && !propIsDefined(vm.vnode, prop)) {
1359
- return componentDefaults.value?.[prop] !== undefined ? componentDefaults.value?.[prop] : defaults.value?.global?.[prop] !== undefined ? defaults.value?.global?.[prop] : propValue;
1360
1366
  }
1367
+ if (propIsDefined(vm.vnode, prop)) return propValue;
1368
+ const _componentDefault = componentDefaults.value?.[prop];
1369
+ if (_componentDefault !== undefined) return _componentDefault;
1370
+ const _globalDefault = defaults.value?.global?.[prop];
1371
+ if (_globalDefault !== undefined) return _globalDefault;
1361
1372
  return propValue;
1362
1373
  }
1363
1374
  });
@@ -2285,6 +2296,7 @@ const makeThemeProps = propsFactory({
2285
2296
  function genDefaults$2() {
2286
2297
  return {
2287
2298
  defaultTheme: 'light',
2299
+ prefix: 'v-',
2288
2300
  variations: {
2289
2301
  colors: [],
2290
2302
  lighten: 0,
@@ -2366,7 +2378,10 @@ function genDefaults$2() {
2366
2378
  }
2367
2379
  }
2368
2380
  },
2369
- stylesheetId: 'vuetify-theme-stylesheet'
2381
+ stylesheetId: 'vuetify-theme-stylesheet',
2382
+ scoped: false,
2383
+ unimportant: false,
2384
+ utilities: true
2370
2385
  };
2371
2386
  }
2372
2387
  function parseThemeOptions() {
@@ -2389,21 +2404,21 @@ function parseThemeOptions() {
2389
2404
  function createCssClass(lines, selector, content, scope) {
2390
2405
  lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2391
2406
  }
2392
- function genCssVariables(theme) {
2407
+ function genCssVariables(theme, prefix) {
2393
2408
  const lightOverlay = theme.dark ? 2 : 1;
2394
2409
  const darkOverlay = theme.dark ? 1 : 2;
2395
2410
  const variables = [];
2396
2411
  for (const [key, value] of Object.entries(theme.colors)) {
2397
2412
  const rgb = parseColor(value);
2398
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2413
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2399
2414
  if (!key.startsWith('on-')) {
2400
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2415
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2401
2416
  }
2402
2417
  }
2403
2418
  for (const [key, value] of Object.entries(theme.variables)) {
2404
2419
  const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2405
2420
  const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2406
- variables.push(`--v-${key}: ${rgb ?? value}`);
2421
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2407
2422
  }
2408
2423
  return variables;
2409
2424
  }
@@ -2447,7 +2462,8 @@ function getScopedSelector(selector, scope) {
2447
2462
  const scopeSelector = `:where(${scope})`;
2448
2463
  return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
2449
2464
  }
2450
- function upsertStyles(styleEl, styles) {
2465
+ function upsertStyles(id, cspNonce, styles) {
2466
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
2451
2467
  if (!styleEl) return;
2452
2468
  styleEl.innerHTML = styles;
2453
2469
  }
@@ -2467,8 +2483,17 @@ function getOrCreateStyleElement(id, cspNonce) {
2467
2483
  // Composables
2468
2484
  function createTheme(options) {
2469
2485
  const parsedOptions = parseThemeOptions(options);
2470
- const name = shallowRef(parsedOptions.defaultTheme);
2486
+ const _name = shallowRef(parsedOptions.defaultTheme);
2471
2487
  const themes = ref(parsedOptions.themes);
2488
+ const systemName = shallowRef('light');
2489
+ const name = computed({
2490
+ get() {
2491
+ return _name.value === 'system' ? systemName.value : _name.value;
2492
+ },
2493
+ set(val) {
2494
+ _name.value = val;
2495
+ }
2496
+ });
2472
2497
  const computedThemes = computed(() => {
2473
2498
  const acc = {};
2474
2499
  for (const [name, original] of Object.entries(themes.value)) {
@@ -2489,28 +2514,49 @@ function createTheme(options) {
2489
2514
  const current = toRef(() => computedThemes.value[name.value]);
2490
2515
  const styles = computed(() => {
2491
2516
  const lines = [];
2517
+ const important = parsedOptions.unimportant ? '' : ' !important';
2518
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
2492
2519
  if (current.value?.dark) {
2493
2520
  createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
2494
2521
  }
2495
- createCssClass(lines, ':root', genCssVariables(current.value), parsedOptions.scope);
2522
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
2496
2523
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
2497
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)], parsedOptions.scope);
2498
- }
2499
- const bgLines = [];
2500
- const fgLines = [];
2501
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2502
- for (const key of colors) {
2503
- if (key.startsWith('on-')) {
2504
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
2505
- } else {
2506
- createCssClass(bgLines, `.bg-${key}`, [`--v-theme-overlay-multiplier: var(--v-theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--v-theme-${key})) !important`, `color: rgb(var(--v-theme-on-${key})) !important`], parsedOptions.scope);
2507
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
2508
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`], parsedOptions.scope);
2524
+ createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
2525
+ }
2526
+ if (parsedOptions.utilities) {
2527
+ const bgLines = [];
2528
+ const fgLines = [];
2529
+ const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2530
+ for (const key of colors) {
2531
+ if (key.startsWith('on-')) {
2532
+ createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2533
+ } else {
2534
+ createCssClass(bgLines, `.${scoped}bg-${key}`, [`--${parsedOptions.prefix}theme-overlay-multiplier: var(--${parsedOptions.prefix}theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`, `color: rgb(var(--${parsedOptions.prefix}theme-on-${key}))${important}`], parsedOptions.scope);
2535
+ createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2536
+ createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
2537
+ }
2509
2538
  }
2539
+ lines.push(...bgLines, ...fgLines);
2510
2540
  }
2511
- lines.push(...bgLines, ...fgLines);
2512
2541
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
2513
2542
  });
2543
+ const themeClasses = toRef(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
2544
+ const themeNames = toRef(() => Object.keys(computedThemes.value));
2545
+ if (SUPPORTS_MATCH_MEDIA) {
2546
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
2547
+ function updateSystemName() {
2548
+ systemName.value = media.matches ? 'dark' : 'light';
2549
+ }
2550
+ updateSystemName();
2551
+ media.addEventListener('change', updateSystemName, {
2552
+ passive: true
2553
+ });
2554
+ if (getCurrentScope()) {
2555
+ onScopeDispose(() => {
2556
+ media.removeEventListener('change', updateSystemName);
2557
+ });
2558
+ }
2559
+ }
2514
2560
  function install(app) {
2515
2561
  if (parsedOptions.isDisabled) return;
2516
2562
  const head = app._context.provides.usehead;
@@ -2548,22 +2594,55 @@ function createTheme(options) {
2548
2594
  updateStyles();
2549
2595
  }
2550
2596
  function updateStyles() {
2551
- upsertStyles(getOrCreateStyleElement(parsedOptions.stylesheetId, parsedOptions.cspNonce), styles.value);
2597
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
2552
2598
  }
2553
2599
  }
2554
2600
  }
2555
- const themeClasses = toRef(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
2601
+ function change(themeName) {
2602
+ if (!themeNames.value.includes(themeName)) {
2603
+ consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
2604
+ return;
2605
+ }
2606
+ name.value = themeName;
2607
+ }
2608
+ function cycle() {
2609
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : themeNames.value;
2610
+ const currentIndex = themeArray.indexOf(name.value);
2611
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
2612
+ change(themeArray[nextIndex]);
2613
+ }
2614
+ function toggle() {
2615
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['light', 'dark'];
2616
+ cycle(themeArray);
2617
+ }
2618
+ const globalName = new Proxy(name, {
2619
+ get(target, prop) {
2620
+ return target[prop];
2621
+ },
2622
+ set(target, prop, val) {
2623
+ if (prop === 'value') {
2624
+ deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
2625
+ }
2626
+ // @ts-expect-error
2627
+ target[prop] = val;
2628
+ return true;
2629
+ }
2630
+ });
2556
2631
  return {
2557
2632
  install,
2633
+ change,
2634
+ cycle,
2635
+ toggle,
2558
2636
  isDisabled: parsedOptions.isDisabled,
2559
2637
  name,
2560
2638
  themes,
2561
2639
  current,
2562
2640
  computedThemes,
2641
+ prefix: parsedOptions.prefix,
2563
2642
  themeClasses,
2564
2643
  styles,
2565
2644
  global: {
2566
- name,
2645
+ name: globalName,
2567
2646
  current
2568
2647
  }
2569
2648
  };
@@ -2574,7 +2653,7 @@ function provideTheme(props) {
2574
2653
  if (!theme) throw new Error('Could not find Vuetify theme injection');
2575
2654
  const name = toRef(() => props.theme ?? theme.name.value);
2576
2655
  const current = toRef(() => theme.themes.value[name.value]);
2577
- const themeClasses = toRef(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
2656
+ const themeClasses = toRef(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
2578
2657
  const newTheme = {
2579
2658
  ...theme,
2580
2659
  name,
@@ -4118,9 +4197,15 @@ function useVariant(props) {
4118
4197
  };
4119
4198
  }
4120
4199
 
4200
+ // Types
4201
+
4121
4202
  const makeVBtnGroupProps = propsFactory({
4122
4203
  baseColor: String,
4123
4204
  divided: Boolean,
4205
+ direction: {
4206
+ type: String,
4207
+ default: 'horizontal'
4208
+ },
4124
4209
  ...makeBorderProps(),
4125
4210
  ...makeComponentProps(),
4126
4211
  ...makeDensityProps(),
@@ -4154,7 +4239,7 @@ const VBtnGroup = genericComponent()({
4154
4239
  } = useRounded(props);
4155
4240
  provideDefaults({
4156
4241
  VBtn: {
4157
- height: 'auto',
4242
+ height: toRef(() => props.direction === 'horizontal' ? 'auto' : null),
4158
4243
  baseColor: toRef(() => props.baseColor),
4159
4244
  color: toRef(() => props.color),
4160
4245
  density: toRef(() => props.density),
@@ -4164,7 +4249,7 @@ const VBtnGroup = genericComponent()({
4164
4249
  });
4165
4250
  useRender(() => {
4166
4251
  return createVNode(props.tag, {
4167
- "class": ['v-btn-group', {
4252
+ "class": ['v-btn-group', `v-btn-group--${props.direction}`, {
4168
4253
  'v-btn-group--divided': props.divided
4169
4254
  }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
4170
4255
  "style": props.style
@@ -10104,8 +10189,27 @@ function connectedLocationStrategy(data, props, contentStyles) {
10104
10189
  return typeof props.offset === 'number' ? [props.offset, 0] : [0, 0];
10105
10190
  });
10106
10191
  let observe = false;
10192
+ let lastFrame = -1;
10193
+ const flipped = new CircularBuffer(4);
10107
10194
  const observer = new ResizeObserver(() => {
10108
- if (observe) updateLocation();
10195
+ if (!observe) return;
10196
+
10197
+ // Detect consecutive frames
10198
+ requestAnimationFrame(newTime => {
10199
+ if (newTime !== lastFrame) flipped.clear();
10200
+ requestAnimationFrame(newNewTime => {
10201
+ lastFrame = newNewTime;
10202
+ });
10203
+ });
10204
+ if (flipped.isFull) {
10205
+ const values = flipped.values();
10206
+ if (deepEqual(values.at(-1), values.at(-3))) {
10207
+ // Flipping is causing a container resize loop
10208
+ return;
10209
+ }
10210
+ }
10211
+ const result = updateLocation();
10212
+ if (result) flipped.push(result.flipped);
10109
10213
  });
10110
10214
  watch([data.target, data.contentEl], (_ref, _ref2) => {
10111
10215
  let [newTarget, newContentEl] = _ref;
@@ -10320,7 +10424,8 @@ function connectedLocationStrategy(data, props, contentStyles) {
10320
10424
  });
10321
10425
  return {
10322
10426
  available,
10323
- contentBox
10427
+ contentBox,
10428
+ flipped
10324
10429
  };
10325
10430
  }
10326
10431
  watch(() => [preferredAnchor.value, preferredOrigin.value, props.offset, props.minWidth, props.minHeight, props.maxWidth, props.maxHeight], () => updateLocation());
@@ -12317,7 +12422,12 @@ function useVirtual(props, items) {
12317
12422
  }
12318
12423
  function calculateOffset(index) {
12319
12424
  index = clamp(index, 0, items.value.length - 1);
12320
- return offsets[index] || 0;
12425
+ const whole = Math.floor(index);
12426
+ const fraction = index % 1;
12427
+ const next = whole + 1;
12428
+ const wholeOffset = offsets[whole] || 0;
12429
+ const nextOffset = offsets[next] || wholeOffset;
12430
+ return wholeOffset + (nextOffset - wholeOffset) * fraction;
12321
12431
  }
12322
12432
  function calculateIndex(scrollTop) {
12323
12433
  return binaryClosest(offsets, scrollTop);
@@ -31604,7 +31714,7 @@ function createVuetify$1() {
31604
31714
  };
31605
31715
  });
31606
31716
  }
31607
- const version$1 = "3.8.2-master.2025-04-27";
31717
+ const version$1 = "3.8.3-dev.2025-04-29";
31608
31718
  createVuetify$1.version = version$1;
31609
31719
 
31610
31720
  // Vue's inject() can only be used in setup
@@ -31902,7 +32012,7 @@ var index = /*#__PURE__*/Object.freeze({
31902
32012
 
31903
32013
  /* eslint-disable local-rules/sort-imports */
31904
32014
 
31905
- const version = "3.8.2-master.2025-04-27";
32015
+ const version = "3.8.3-dev.2025-04-29";
31906
32016
 
31907
32017
  /* eslint-disable local-rules/sort-imports */
31908
32018