vuetify 3.3.6 → 3.3.8

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 (89) hide show
  1. package/dist/json/attributes.json +15 -11
  2. package/dist/json/importMap.json +44 -44
  3. package/dist/json/tags.json +1 -0
  4. package/dist/json/web-types.json +27 -25
  5. package/dist/vuetify-labs.css +72 -55
  6. package/dist/vuetify-labs.d.ts +178 -76
  7. package/dist/vuetify-labs.esm.js +548 -397
  8. package/dist/vuetify-labs.esm.js.map +1 -1
  9. package/dist/vuetify-labs.js +547 -396
  10. package/dist/vuetify-labs.min.css +2 -2
  11. package/dist/vuetify.css +50 -33
  12. package/dist/vuetify.d.ts +145 -81
  13. package/dist/vuetify.esm.js +531 -386
  14. package/dist/vuetify.esm.js.map +1 -1
  15. package/dist/vuetify.js +530 -385
  16. package/dist/vuetify.js.map +1 -1
  17. package/dist/vuetify.min.css +2 -2
  18. package/dist/vuetify.min.js +700 -680
  19. package/dist/vuetify.min.js.map +1 -1
  20. package/lib/components/VAutocomplete/VAutocomplete.mjs +48 -35
  21. package/lib/components/VAutocomplete/VAutocomplete.mjs.map +1 -1
  22. package/lib/components/VBtn/VBtn.mjs +1 -1
  23. package/lib/components/VBtn/VBtn.mjs.map +1 -1
  24. package/lib/components/VCarousel/VCarousel.mjs +58 -57
  25. package/lib/components/VCarousel/VCarousel.mjs.map +1 -1
  26. package/lib/components/VCheckbox/index.d.mts +28 -16
  27. package/lib/components/VCombobox/VCombobox.mjs +48 -35
  28. package/lib/components/VCombobox/VCombobox.mjs.map +1 -1
  29. package/lib/components/VField/VField.css +18 -6
  30. package/lib/components/VField/VField.sass +18 -6
  31. package/lib/components/VField/_variables.scss +2 -2
  32. package/lib/components/VIcon/VIcon.css +1 -0
  33. package/lib/components/VIcon/VIcon.sass +1 -0
  34. package/lib/components/VImg/VImg.css +4 -2
  35. package/lib/components/VImg/VImg.mjs +4 -2
  36. package/lib/components/VImg/VImg.mjs.map +1 -1
  37. package/lib/components/VImg/VImg.sass +3 -4
  38. package/lib/components/VOverlay/VOverlay.css +2 -0
  39. package/lib/components/VOverlay/VOverlay.mjs +2 -2
  40. package/lib/components/VOverlay/VOverlay.mjs.map +1 -1
  41. package/lib/components/VOverlay/VOverlay.sass +3 -1
  42. package/lib/components/VOverlay/scrollStrategies.mjs +3 -1
  43. package/lib/components/VOverlay/scrollStrategies.mjs.map +1 -1
  44. package/lib/components/VRadio/index.d.mts +14 -8
  45. package/lib/components/VRadioGroup/index.d.mts +14 -8
  46. package/lib/components/VResponsive/VResponsive.css +6 -11
  47. package/lib/components/VResponsive/VResponsive.sass +5 -10
  48. package/lib/components/VSelect/VSelect.mjs +43 -31
  49. package/lib/components/VSelect/VSelect.mjs.map +1 -1
  50. package/lib/components/VSelect/useScrolling.mjs +69 -0
  51. package/lib/components/VSelect/useScrolling.mjs.map +1 -0
  52. package/lib/components/VSelectionControl/VSelectionControl.mjs +2 -2
  53. package/lib/components/VSelectionControl/VSelectionControl.mjs.map +1 -1
  54. package/lib/components/VSelectionControl/index.d.mts +14 -8
  55. package/lib/components/VSelectionControlGroup/VSelectionControlGroup.mjs +4 -1
  56. package/lib/components/VSelectionControlGroup/VSelectionControlGroup.mjs.map +1 -1
  57. package/lib/components/VSelectionControlGroup/index.d.mts +14 -8
  58. package/lib/components/VSwitch/index.d.mts +14 -8
  59. package/lib/components/VTextField/VTextField.css +5 -0
  60. package/lib/components/VTextField/VTextField.mjs +6 -2
  61. package/lib/components/VTextField/VTextField.mjs.map +1 -1
  62. package/lib/components/VTextField/VTextField.sass +5 -0
  63. package/lib/components/VTextField/_variables.scss +1 -0
  64. package/lib/components/VVirtualScroll/VVirtualScroll.mjs +50 -24
  65. package/lib/components/VVirtualScroll/VVirtualScroll.mjs.map +1 -1
  66. package/lib/components/VVirtualScroll/VVirtualScrollItem.mjs +13 -23
  67. package/lib/components/VVirtualScroll/VVirtualScrollItem.mjs.map +1 -1
  68. package/lib/components/VVirtualScroll/index.d.mts +37 -15
  69. package/lib/components/index.d.mts +134 -70
  70. package/lib/composables/filter.mjs +9 -6
  71. package/lib/composables/filter.mjs.map +1 -1
  72. package/lib/composables/resizeObserver.mjs +6 -1
  73. package/lib/composables/resizeObserver.mjs.map +1 -1
  74. package/lib/composables/theme.mjs +2 -2
  75. package/lib/composables/theme.mjs.map +1 -1
  76. package/lib/composables/virtual.mjs +17 -17
  77. package/lib/composables/virtual.mjs.map +1 -1
  78. package/lib/entry-bundler.mjs +1 -1
  79. package/lib/framework.mjs +1 -1
  80. package/lib/index.d.mts +11 -11
  81. package/lib/labs/VDataTable/VDataTableVirtual.mjs +12 -10
  82. package/lib/labs/VDataTable/VDataTableVirtual.mjs.map +1 -1
  83. package/lib/labs/VDataTable/composables/headers.mjs +6 -2
  84. package/lib/labs/VDataTable/composables/headers.mjs.map +1 -1
  85. package/lib/labs/VDataTable/index.d.mts +44 -6
  86. package/lib/labs/components.d.mts +44 -6
  87. package/lib/util/getScrollParent.mjs +7 -1
  88. package/lib/util/getScrollParent.mjs.map +1 -1
  89. package/package.json +2 -2
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * Vuetify v3.3.6
2
+ * Vuetify v3.3.8
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
- import { Fragment, reactive, computed, watchEffect, toRefs, capitalize, warn, watch, onScopeDispose, effectScope, ref, unref, provide, shallowRef, inject as inject$1, defineComponent as defineComponent$1, camelize, h, getCurrentInstance as getCurrentInstance$1, onBeforeUnmount, readonly, onDeactivated, onActivated, onMounted, toRaw, createVNode, TransitionGroup, Transition, mergeProps, onBeforeMount, nextTick, withDirectives, resolveDirective, vShow, isRef, toRef, Text, resolveDynamicComponent, Teleport, cloneVNode, createTextVNode, onBeforeUpdate, vModelText, onUpdated } from 'vue';
7
+ import { Fragment, reactive, computed, watchEffect, toRefs, capitalize, warn, watch, onScopeDispose, effectScope, ref, unref, provide, shallowRef, inject as inject$1, defineComponent as defineComponent$1, camelize, h, getCurrentInstance as getCurrentInstance$1, onBeforeUnmount, readonly, onDeactivated, onActivated, onMounted, toRaw, createVNode, TransitionGroup, Transition, mergeProps, onBeforeMount, nextTick, withDirectives, resolveDirective, vShow, isRef, toRef, Text, resolveDynamicComponent, Teleport, cloneVNode, createTextVNode, onBeforeUpdate, vModelText } from 'vue';
8
8
 
9
9
  // Types
10
10
  // eslint-disable-line vue/prefer-import-from-vue
@@ -1247,8 +1247,9 @@ getUid.reset = () => {
1247
1247
  };
1248
1248
 
1249
1249
  function getScrollParent(el) {
1250
+ let includeHidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1250
1251
  while (el) {
1251
- if (hasScrollbar(el)) return el;
1252
+ if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el;
1252
1253
  el = el.parentElement;
1253
1254
  }
1254
1255
  return document.scrollingElement;
@@ -1268,6 +1269,11 @@ function hasScrollbar(el) {
1268
1269
  const style = window.getComputedStyle(el);
1269
1270
  return style.overflowY === 'scroll' || style.overflowY === 'auto' && el.scrollHeight > el.clientHeight;
1270
1271
  }
1272
+ function isPotentiallyScrollable(el) {
1273
+ if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
1274
+ const style = window.getComputedStyle(el);
1275
+ return ['scroll', 'auto'].includes(style.overflowY);
1276
+ }
1271
1277
 
1272
1278
  const IN_BROWSER = typeof window !== 'undefined';
1273
1279
  const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
@@ -1313,13 +1319,18 @@ function useRender(render) {
1313
1319
  // Types
1314
1320
 
1315
1321
  function useResizeObserver(callback) {
1322
+ let box = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'content';
1316
1323
  const resizeRef = ref();
1317
1324
  const contentRect = ref();
1318
1325
  if (IN_BROWSER) {
1319
1326
  const observer = new ResizeObserver(entries => {
1320
1327
  callback?.(entries, observer);
1321
1328
  if (!entries.length) return;
1322
- contentRect.value = entries[0].contentRect;
1329
+ if (box === 'content') {
1330
+ contentRect.value = entries[0].contentRect;
1331
+ } else {
1332
+ contentRect.value = entries[0].target.getBoundingClientRect();
1333
+ }
1323
1334
  });
1324
1335
  onBeforeUnmount(() => {
1325
1336
  observer.disconnect();
@@ -2143,7 +2154,7 @@ function parseThemeOptions() {
2143
2154
 
2144
2155
  // Composables
2145
2156
  function createTheme(options) {
2146
- const parsedOptions = reactive(parseThemeOptions(options));
2157
+ const parsedOptions = parseThemeOptions(options);
2147
2158
  const name = ref(parsedOptions.defaultTheme);
2148
2159
  const themes = ref(parsedOptions.themes);
2149
2160
  const computedThemes = computed(() => {
@@ -3141,7 +3152,9 @@ const VImg = genericComponent()({
3141
3152
  "class": ['v-img', {
3142
3153
  'v-img--booting': !isBooted.value
3143
3154
  }, props.class],
3144
- "style": props.style
3155
+ "style": [{
3156
+ width: convertToUnit(props.width === 'auto' ? naturalWidth.value : props.width)
3157
+ }, props.style]
3145
3158
  }, responsiveProps, {
3146
3159
  "aspectRatio": aspectRatio.value,
3147
3160
  "aria-label": props.alt,
@@ -5260,7 +5273,7 @@ const VBtn = genericComponent()({
5260
5273
  return Object(props.value) === props.value ? JSON.stringify(props.value, null, 0) : props.value;
5261
5274
  });
5262
5275
  function onClick(e) {
5263
- if (isDisabled.value) return;
5276
+ if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === '_blank')) return;
5264
5277
  link.navigate?.(e);
5265
5278
  group?.toggle();
5266
5279
  }
@@ -5599,7 +5612,10 @@ const VLabel = genericComponent()({
5599
5612
  const VSelectionControlGroupSymbol = Symbol.for('vuetify:selection-control-group');
5600
5613
  const makeSelectionControlGroupProps = propsFactory({
5601
5614
  color: String,
5602
- disabled: Boolean,
5615
+ disabled: {
5616
+ type: Boolean,
5617
+ default: null
5618
+ },
5603
5619
  defaultsTarget: String,
5604
5620
  error: Boolean,
5605
5621
  id: String,
@@ -5823,12 +5839,12 @@ const VSelectionControl = genericComponent()({
5823
5839
  }, null), createVNode("input", mergeProps({
5824
5840
  "ref": input,
5825
5841
  "checked": model.value,
5826
- "disabled": props.disabled,
5842
+ "disabled": !!(props.readonly || props.disabled),
5827
5843
  "id": id.value,
5828
5844
  "onBlur": onBlur,
5829
5845
  "onFocus": onFocus,
5830
5846
  "onInput": onInput,
5831
- "aria-disabled": props.readonly,
5847
+ "aria-disabled": !!(props.readonly || props.disabled),
5832
5848
  "type": props.type,
5833
5849
  "value": trueValue.value,
5834
5850
  "name": props.name,
@@ -8699,7 +8715,9 @@ function blockScrollStrategy(data, props) {
8699
8715
  scrollElements.forEach((el, i) => {
8700
8716
  el.style.setProperty('--v-body-scroll-x', convertToUnit(-el.scrollLeft));
8701
8717
  el.style.setProperty('--v-body-scroll-y', convertToUnit(-el.scrollTop));
8702
- el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
8718
+ if (el !== document.documentElement) {
8719
+ el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
8720
+ }
8703
8721
  el.classList.add('v-overlay-scroll-blocked');
8704
8722
  });
8705
8723
  onScopeDispose(() => {
@@ -9590,11 +9608,11 @@ const VOverlay = genericComponent()({
9590
9608
  props: mergeProps({
9591
9609
  ref: activatorRef
9592
9610
  }, activatorEvents.value, props.activatorProps)
9593
- }), isMounted.value && createVNode(Teleport, {
9611
+ }), isMounted.value && hasContent.value && createVNode(Teleport, {
9594
9612
  "disabled": !teleportTarget.value,
9595
9613
  "to": teleportTarget.value
9596
9614
  }, {
9597
- default: () => [hasContent.value && createVNode("div", mergeProps({
9615
+ default: () => [createVNode("div", mergeProps({
9598
9616
  "class": ['v-overlay', {
9599
9617
  'v-overlay--absolute': props.absolute || props.contained,
9600
9618
  'v-overlay--active': isActive.value,
@@ -10354,12 +10372,16 @@ const VTextField = genericComponent()({
10354
10372
  }]]);
10355
10373
  return createVNode(Fragment, null, [props.prefix && createVNode("span", {
10356
10374
  "class": "v-text-field__prefix"
10357
- }, [props.prefix]), createVNode("div", {
10375
+ }, [createVNode("span", {
10376
+ "class": "v-text-field__prefix__text"
10377
+ }, [props.prefix])]), createVNode("div", {
10358
10378
  "class": fieldClass,
10359
10379
  "data-no-activator": ""
10360
10380
  }, [slots.default ? createVNode(Fragment, null, [slots.default(), inputNode]) : cloneVNode(inputNode)]), props.suffix && createVNode("span", {
10361
10381
  "class": "v-text-field__suffix"
10362
- }, [props.suffix])]);
10382
+ }, [createVNode("span", {
10383
+ "class": "v-text-field__suffix__text"
10384
+ }, [props.suffix])])]);
10363
10385
  }
10364
10386
  });
10365
10387
  },
@@ -10376,6 +10398,301 @@ const VTextField = genericComponent()({
10376
10398
 
10377
10399
  // Types
10378
10400
 
10401
+ const makeVVirtualScrollItemProps = propsFactory({
10402
+ renderless: Boolean,
10403
+ ...makeComponentProps()
10404
+ }, 'VVirtualScrollItem');
10405
+ const VVirtualScrollItem = genericComponent()({
10406
+ name: 'VVirtualScrollItem',
10407
+ inheritAttrs: false,
10408
+ props: makeVVirtualScrollItemProps(),
10409
+ emits: {
10410
+ 'update:height': height => true
10411
+ },
10412
+ setup(props, _ref) {
10413
+ let {
10414
+ attrs,
10415
+ emit,
10416
+ slots
10417
+ } = _ref;
10418
+ const {
10419
+ resizeRef,
10420
+ contentRect
10421
+ } = useResizeObserver(undefined, 'border');
10422
+ watch(() => contentRect.value?.height, height => {
10423
+ if (height != null) emit('update:height', height);
10424
+ });
10425
+ useRender(() => props.renderless ? createVNode(Fragment, null, [slots.default?.({
10426
+ itemRef: resizeRef
10427
+ })]) : createVNode("div", mergeProps({
10428
+ "ref": resizeRef,
10429
+ "class": ['v-virtual-scroll__item', props.class],
10430
+ "style": props.style
10431
+ }, attrs), [slots.default?.()]));
10432
+ }
10433
+ });
10434
+
10435
+ // Composables
10436
+
10437
+ // Types
10438
+
10439
+ const UP = -1;
10440
+ const DOWN = 1;
10441
+ const makeVirtualProps = propsFactory({
10442
+ itemHeight: {
10443
+ type: [Number, String],
10444
+ default: 48
10445
+ }
10446
+ }, 'virtual');
10447
+ function useVirtual(props, items, offset) {
10448
+ const first = shallowRef(0);
10449
+ const baseItemHeight = shallowRef(props.itemHeight);
10450
+ const itemHeight = computed({
10451
+ get: () => parseInt(baseItemHeight.value ?? 0, 10),
10452
+ set(val) {
10453
+ baseItemHeight.value = val;
10454
+ }
10455
+ });
10456
+ const containerRef = ref();
10457
+ const {
10458
+ resizeRef,
10459
+ contentRect
10460
+ } = useResizeObserver();
10461
+ watchEffect(() => {
10462
+ resizeRef.value = containerRef.value;
10463
+ });
10464
+ const display = useDisplay();
10465
+ const sizeMap = new Map();
10466
+ let sizes = Array.from({
10467
+ length: items.value.length
10468
+ });
10469
+ const visibleItems = computed(() => {
10470
+ const height = (!contentRect.value || containerRef.value === document.documentElement ? display.height.value : contentRect.value.height) - (offset?.value ?? 0);
10471
+ return Math.ceil(height / itemHeight.value * 1.7 + 1);
10472
+ });
10473
+ function handleItemResize(index, height) {
10474
+ itemHeight.value = Math.max(itemHeight.value, height);
10475
+ sizes[index] = height;
10476
+ sizeMap.set(items.value[index], height);
10477
+ }
10478
+ function calculateOffset(index) {
10479
+ return sizes.slice(0, index).reduce((acc, val) => acc + (val || itemHeight.value), 0);
10480
+ }
10481
+ function calculateMidPointIndex(scrollTop) {
10482
+ const end = items.value.length;
10483
+ let middle = 0;
10484
+ let middleOffset = 0;
10485
+ while (middleOffset < scrollTop && middle < end) {
10486
+ middleOffset += sizes[middle++] || itemHeight.value;
10487
+ }
10488
+ return middle - 1;
10489
+ }
10490
+ let lastScrollTop = 0;
10491
+ function handleScroll() {
10492
+ if (!containerRef.value || !contentRect.value) return;
10493
+ const height = contentRect.value.height - 56;
10494
+ const scrollTop = containerRef.value.scrollTop;
10495
+ const direction = scrollTop < lastScrollTop ? UP : DOWN;
10496
+ const midPointIndex = calculateMidPointIndex(scrollTop + height / 2);
10497
+ const buffer = Math.round(visibleItems.value / 3);
10498
+ const firstIndex = midPointIndex - buffer;
10499
+ const lastIndex = first.value + buffer * 2 - 1;
10500
+ if (direction === UP && midPointIndex <= lastIndex) {
10501
+ first.value = clamp(firstIndex, 0, items.value.length);
10502
+ } else if (direction === DOWN && midPointIndex >= lastIndex) {
10503
+ first.value = clamp(firstIndex, 0, items.value.length - visibleItems.value);
10504
+ }
10505
+ lastScrollTop = scrollTop;
10506
+ }
10507
+ function scrollToIndex(index) {
10508
+ if (!containerRef.value) return;
10509
+ const offset = calculateOffset(index);
10510
+ containerRef.value.scrollTop = offset;
10511
+ }
10512
+ const last = computed(() => Math.min(items.value.length, first.value + visibleItems.value));
10513
+ const computedItems = computed(() => {
10514
+ return items.value.slice(first.value, last.value).map((item, index) => ({
10515
+ raw: item,
10516
+ index: index + first.value
10517
+ }));
10518
+ });
10519
+ const paddingTop = computed(() => calculateOffset(first.value));
10520
+ const paddingBottom = computed(() => calculateOffset(items.value.length) - calculateOffset(last.value));
10521
+ watch(() => items.value.length, () => {
10522
+ sizes = createRange(items.value.length).map(() => itemHeight.value);
10523
+ sizeMap.forEach((height, item) => {
10524
+ const index = items.value.indexOf(item);
10525
+ if (index === -1) {
10526
+ sizeMap.delete(item);
10527
+ } else {
10528
+ sizes[index] = height;
10529
+ }
10530
+ });
10531
+ });
10532
+ return {
10533
+ containerRef,
10534
+ computedItems,
10535
+ itemHeight,
10536
+ paddingTop,
10537
+ paddingBottom,
10538
+ scrollToIndex,
10539
+ handleScroll,
10540
+ handleItemResize
10541
+ };
10542
+ }
10543
+
10544
+ // Types
10545
+
10546
+ const makeVVirtualScrollProps = propsFactory({
10547
+ items: {
10548
+ type: Array,
10549
+ default: () => []
10550
+ },
10551
+ renderless: Boolean,
10552
+ ...makeVirtualProps(),
10553
+ ...makeComponentProps(),
10554
+ ...makeDimensionProps()
10555
+ }, 'VVirtualScroll');
10556
+ const VVirtualScroll = genericComponent()({
10557
+ name: 'VVirtualScroll',
10558
+ props: makeVVirtualScrollProps(),
10559
+ setup(props, _ref) {
10560
+ let {
10561
+ slots
10562
+ } = _ref;
10563
+ const vm = getCurrentInstance('VVirtualScroll');
10564
+ const {
10565
+ dimensionStyles
10566
+ } = useDimension(props);
10567
+ const {
10568
+ containerRef,
10569
+ handleScroll,
10570
+ handleItemResize,
10571
+ scrollToIndex,
10572
+ paddingTop,
10573
+ paddingBottom,
10574
+ computedItems
10575
+ } = useVirtual(props, toRef(props, 'items'));
10576
+ useToggleScope(() => props.renderless, () => {
10577
+ onMounted(() => {
10578
+ containerRef.value = getScrollParent(vm.vnode.el, true);
10579
+ containerRef.value?.addEventListener('scroll', handleScroll);
10580
+ });
10581
+ onScopeDispose(() => {
10582
+ containerRef.value?.removeEventListener('scroll', handleScroll);
10583
+ });
10584
+ });
10585
+ useRender(() => {
10586
+ const children = computedItems.value.map(item => createVNode(VVirtualScrollItem, {
10587
+ "key": item.index,
10588
+ "renderless": props.renderless,
10589
+ "onUpdate:height": height => handleItemResize(item.index, height)
10590
+ }, {
10591
+ default: slotProps => slots.default?.({
10592
+ item: item.raw,
10593
+ index: item.index,
10594
+ ...slotProps
10595
+ })
10596
+ }));
10597
+ return props.renderless ? createVNode(Fragment, null, [createVNode("div", {
10598
+ "class": "v-virtual-scroll__spacer",
10599
+ "style": {
10600
+ paddingTop: convertToUnit(paddingTop.value)
10601
+ }
10602
+ }, null), children, createVNode("div", {
10603
+ "class": "v-virtual-scroll__spacer",
10604
+ "style": {
10605
+ paddingBottom: convertToUnit(paddingBottom.value)
10606
+ }
10607
+ }, null)]) : createVNode("div", {
10608
+ "ref": containerRef,
10609
+ "class": ['v-virtual-scroll', props.class],
10610
+ "onScroll": handleScroll,
10611
+ "style": [dimensionStyles.value, props.style]
10612
+ }, [createVNode("div", {
10613
+ "class": "v-virtual-scroll__container",
10614
+ "style": {
10615
+ paddingTop: convertToUnit(paddingTop.value),
10616
+ paddingBottom: convertToUnit(paddingBottom.value)
10617
+ }
10618
+ }, [children])]);
10619
+ });
10620
+ return {
10621
+ scrollToIndex
10622
+ };
10623
+ }
10624
+ });
10625
+
10626
+ // Utilities
10627
+
10628
+ // Types
10629
+
10630
+ function useScrolling(listRef, textFieldRef) {
10631
+ const isScrolling = shallowRef(false);
10632
+ let scrollTimeout;
10633
+ function onListScroll(e) {
10634
+ cancelAnimationFrame(scrollTimeout);
10635
+ isScrolling.value = true;
10636
+ scrollTimeout = requestAnimationFrame(() => {
10637
+ scrollTimeout = requestAnimationFrame(() => {
10638
+ isScrolling.value = false;
10639
+ });
10640
+ });
10641
+ }
10642
+ async function finishScrolling() {
10643
+ await new Promise(resolve => requestAnimationFrame(resolve));
10644
+ await new Promise(resolve => requestAnimationFrame(resolve));
10645
+ await new Promise(resolve => requestAnimationFrame(resolve));
10646
+ await new Promise(resolve => {
10647
+ if (isScrolling.value) {
10648
+ const stop = watch(isScrolling, () => {
10649
+ stop();
10650
+ resolve();
10651
+ });
10652
+ } else resolve();
10653
+ });
10654
+ }
10655
+ async function onListKeydown(e) {
10656
+ if (e.key === 'Tab') {
10657
+ textFieldRef.value?.focus();
10658
+ }
10659
+ if (!['PageDown', 'PageUp', 'Home', 'End'].includes(e.key)) return;
10660
+ const el = listRef.value?.$el;
10661
+ if (!el) return;
10662
+ if (e.key === 'Home' || e.key === 'End') {
10663
+ el.scrollTo({
10664
+ top: e.key === 'Home' ? 0 : el.scrollHeight,
10665
+ behavior: 'smooth'
10666
+ });
10667
+ }
10668
+ await finishScrolling();
10669
+ const children = el.querySelectorAll(':scope > :not(.v-virtual-scroll__spacer)');
10670
+ if (e.key === 'PageDown' || e.key === 'Home') {
10671
+ const top = el.getBoundingClientRect().top;
10672
+ for (const child of children) {
10673
+ if (child.getBoundingClientRect().top >= top) {
10674
+ child.focus();
10675
+ break;
10676
+ }
10677
+ }
10678
+ } else {
10679
+ const bottom = el.getBoundingClientRect().bottom;
10680
+ for (const child of [...children].reverse()) {
10681
+ if (child.getBoundingClientRect().bottom <= bottom) {
10682
+ child.focus();
10683
+ break;
10684
+ }
10685
+ }
10686
+ }
10687
+ }
10688
+ return {
10689
+ onListScroll,
10690
+ onListKeydown
10691
+ };
10692
+ }
10693
+
10694
+ // Types
10695
+
10379
10696
  const makeSelectProps = propsFactory({
10380
10697
  chips: Boolean,
10381
10698
  closableChips: Boolean,
@@ -10467,6 +10784,10 @@ const VSelect = genericComponent()({
10467
10784
  });
10468
10785
  const menuDisabled = computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
10469
10786
  const listRef = ref();
10787
+ const {
10788
+ onListScroll,
10789
+ onListKeydown
10790
+ } = useScrolling(listRef, vTextFieldRef);
10470
10791
  function onClear(e) {
10471
10792
  if (props.openOnClear) {
10472
10793
  menu.value = true;
@@ -10513,11 +10834,6 @@ const VSelect = genericComponent()({
10513
10834
  model.value = [item];
10514
10835
  }
10515
10836
  }
10516
- function onListKeydown(e) {
10517
- if (e.key === 'Tab') {
10518
- vTextFieldRef.value?.focus();
10519
- }
10520
- }
10521
10837
  function select(item) {
10522
10838
  if (props.multiple) {
10523
10839
  const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
@@ -10600,34 +10916,46 @@ const VSelect = genericComponent()({
10600
10916
  "onMousedown": e => e.preventDefault(),
10601
10917
  "onKeydown": onListKeydown,
10602
10918
  "onFocusin": onFocusin,
10919
+ "onScrollPassive": onListScroll,
10603
10920
  "tabindex": "-1"
10604
10921
  }, {
10605
10922
  default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
10606
10923
  "title": t(props.noDataText)
10607
- }, null)), displayItems.value.map((item, index) => {
10608
- const itemProps = mergeProps(item.props, {
10609
- key: index,
10610
- onClick: () => select(item)
10611
- });
10612
- return slots.item?.({
10613
- item,
10614
- index,
10615
- props: itemProps
10616
- }) ?? createVNode(VListItem, itemProps, {
10617
- prepend: _ref2 => {
10618
- let {
10619
- isSelected
10620
- } = _ref2;
10621
- return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
10622
- "key": item.value,
10623
- "modelValue": isSelected,
10624
- "ripple": false,
10625
- "tabindex": "-1"
10626
- }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
10627
- "icon": item.props.prependIcon
10628
- }, null)]);
10629
- }
10630
- });
10924
+ }, null)), createVNode(VVirtualScroll, {
10925
+ "renderless": true,
10926
+ "items": displayItems.value
10927
+ }, {
10928
+ default: _ref2 => {
10929
+ let {
10930
+ item,
10931
+ index,
10932
+ itemRef
10933
+ } = _ref2;
10934
+ const itemProps = mergeProps(item.props, {
10935
+ ref: itemRef,
10936
+ key: index,
10937
+ onClick: () => select(item)
10938
+ });
10939
+ return slots.item?.({
10940
+ item,
10941
+ index,
10942
+ props: itemProps
10943
+ }) ?? createVNode(VListItem, itemProps, {
10944
+ prepend: _ref3 => {
10945
+ let {
10946
+ isSelected
10947
+ } = _ref3;
10948
+ return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
10949
+ "key": item.value,
10950
+ "modelValue": isSelected,
10951
+ "ripple": false,
10952
+ "tabindex": "-1"
10953
+ }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
10954
+ "icon": item.props.prependIcon
10955
+ }, null)]);
10956
+ }
10957
+ });
10958
+ }
10631
10959
  }), slots['append-item']?.()]
10632
10960
  })]
10633
10961
  }), selections.value.map((item, index) => {
@@ -10765,14 +11093,13 @@ function filterItems(items, query, options) {
10765
11093
  return array;
10766
11094
  }
10767
11095
  function useFilter(props, items, query, options) {
10768
- const strQuery = computed(() => typeof query?.value !== 'string' && typeof query?.value !== 'number' ? '' : String(query.value));
10769
11096
  const filteredItems = ref([]);
10770
11097
  const filteredMatches = ref(new Map());
10771
11098
  const transformedItems = computed(() => options?.transform ? unref(items).map(options?.transform) : unref(items));
10772
11099
  watchEffect(() => {
10773
- filteredItems.value = [];
10774
- filteredMatches.value = new Map();
10775
- const results = filterItems(transformedItems.value, strQuery.value, {
11100
+ const _query = typeof query === 'function' ? query() : unref(query);
11101
+ const strQuery = typeof _query !== 'string' && typeof _query !== 'number' ? '' : String(_query);
11102
+ const results = filterItems(transformedItems.value, strQuery, {
10776
11103
  customKeyFilter: props.customKeyFilter,
10777
11104
  default: props.customFilter,
10778
11105
  filterKeys: props.filterKeys,
@@ -10780,15 +11107,19 @@ function useFilter(props, items, query, options) {
10780
11107
  noFilter: props.noFilter
10781
11108
  });
10782
11109
  const originalItems = unref(items);
11110
+ const _filteredItems = [];
11111
+ const _filteredMatches = new Map();
10783
11112
  results.forEach(_ref => {
10784
11113
  let {
10785
11114
  index,
10786
11115
  matches
10787
11116
  } = _ref;
10788
11117
  const item = originalItems[index];
10789
- filteredItems.value.push(item);
10790
- filteredMatches.value.set(item.value, matches);
11118
+ _filteredItems.push(item);
11119
+ _filteredMatches.set(item.value, matches);
10791
11120
  });
11121
+ filteredItems.value = _filteredItems;
11122
+ filteredMatches.value = _filteredMatches;
10792
11123
  });
10793
11124
  function getMatches(item) {
10794
11125
  return filteredMatches.value.get(item.value);
@@ -10878,7 +11209,7 @@ const VAutocomplete = genericComponent()({
10878
11209
  const {
10879
11210
  filteredItems,
10880
11211
  getMatches
10881
- } = useFilter(props, items, computed(() => isPristine.value ? undefined : search.value));
11212
+ } = useFilter(props, items, () => isPristine.value ? '' : search.value);
10882
11213
  const selections = computed(() => {
10883
11214
  return model.value.map(v => {
10884
11215
  return items.value.find(item => props.valueComparator(item.value, v.value)) || v;
@@ -10898,6 +11229,10 @@ const VAutocomplete = genericComponent()({
10898
11229
  });
10899
11230
  const menuDisabled = computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
10900
11231
  const listRef = ref();
11232
+ const {
11233
+ onListScroll,
11234
+ onListKeydown
11235
+ } = useScrolling(listRef, vTextFieldRef);
10901
11236
  function onClear(e) {
10902
11237
  if (props.openOnClear) {
10903
11238
  menu.value = true;
@@ -10971,11 +11306,6 @@ const VAutocomplete = genericComponent()({
10971
11306
  }
10972
11307
  }
10973
11308
  }
10974
- function onListKeydown(e) {
10975
- if (e.key === 'Tab') {
10976
- vTextFieldRef.value?.focus();
10977
- }
10978
- }
10979
11309
  function onInput(e) {
10980
11310
  search.value = e.target.value;
10981
11311
  }
@@ -11094,38 +11424,50 @@ const VAutocomplete = genericComponent()({
11094
11424
  "onKeydown": onListKeydown,
11095
11425
  "onFocusin": onFocusin,
11096
11426
  "onFocusout": onFocusout,
11427
+ "onScrollPassive": onListScroll,
11097
11428
  "tabindex": "-1"
11098
11429
  }, {
11099
11430
  default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
11100
11431
  "title": t(props.noDataText)
11101
- }, null)), displayItems.value.map((item, index) => {
11102
- const itemProps = mergeProps(item.props, {
11103
- key: index,
11104
- active: highlightFirst.value && index === 0 ? true : undefined,
11105
- onClick: () => select(item)
11106
- });
11107
- return slots.item?.({
11108
- item,
11109
- index,
11110
- props: itemProps
11111
- }) ?? createVNode(VListItem, itemProps, {
11112
- prepend: _ref3 => {
11113
- let {
11114
- isSelected
11115
- } = _ref3;
11116
- return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
11117
- "key": item.value,
11118
- "modelValue": isSelected,
11119
- "ripple": false,
11120
- "tabindex": "-1"
11121
- }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
11122
- "icon": item.props.prependIcon
11123
- }, null)]);
11124
- },
11125
- title: () => {
11126
- return isPristine.value ? item.title : highlightResult$1(item.title, getMatches(item)?.title, search.value?.length ?? 0);
11127
- }
11128
- });
11432
+ }, null)), createVNode(VVirtualScroll, {
11433
+ "renderless": true,
11434
+ "items": displayItems.value
11435
+ }, {
11436
+ default: _ref3 => {
11437
+ let {
11438
+ item,
11439
+ index,
11440
+ itemRef
11441
+ } = _ref3;
11442
+ const itemProps = mergeProps(item.props, {
11443
+ ref: itemRef,
11444
+ key: index,
11445
+ active: highlightFirst.value && index === 0 ? true : undefined,
11446
+ onClick: () => select(item)
11447
+ });
11448
+ return slots.item?.({
11449
+ item,
11450
+ index,
11451
+ props: itemProps
11452
+ }) ?? createVNode(VListItem, itemProps, {
11453
+ prepend: _ref4 => {
11454
+ let {
11455
+ isSelected
11456
+ } = _ref4;
11457
+ return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
11458
+ "key": item.value,
11459
+ "modelValue": isSelected,
11460
+ "ripple": false,
11461
+ "tabindex": "-1"
11462
+ }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
11463
+ "icon": item.props.prependIcon
11464
+ }, null)]);
11465
+ },
11466
+ title: () => {
11467
+ return isPristine.value ? item.title : highlightResult$1(item.title, getMatches(item)?.title, search.value?.length ?? 0);
11468
+ }
11469
+ });
11470
+ }
11129
11471
  }), slots['append-item']?.()]
11130
11472
  })]
11131
11473
  }), selections.value.map((item, index) => {
@@ -12329,64 +12671,65 @@ const VCarousel = genericComponent()({
12329
12671
  window.clearTimeout(slideTimeout);
12330
12672
  window.requestAnimationFrame(startTimeout);
12331
12673
  }
12332
- useRender(() => createVNode(VWindow, {
12333
- "ref": windowRef,
12334
- "modelValue": model.value,
12335
- "onUpdate:modelValue": $event => model.value = $event,
12336
- "class": ['v-carousel', {
12337
- 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
12338
- 'v-carousel--vertical-delimiters': props.verticalDelimiters
12339
- }, props.class],
12340
- "style": [{
12341
- height: convertToUnit(props.height)
12342
- }, props.style],
12343
- "continuous": true,
12344
- "mandatory": "force",
12345
- "showArrows": props.showArrows
12346
- }, {
12347
- default: slots.default,
12348
- additional: _ref2 => {
12349
- let {
12350
- group
12351
- } = _ref2;
12352
- return createVNode(Fragment, null, [!props.hideDelimiters && createVNode("div", {
12353
- "class": "v-carousel__controls",
12354
- "style": {
12355
- left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
12356
- right: props.verticalDelimiters === 'right' ? 0 : 'auto'
12357
- }
12358
- }, [group.items.value.length > 0 && createVNode(VDefaultsProvider, {
12359
- "defaults": {
12360
- VBtn: {
12361
- color: props.color,
12362
- icon: props.delimiterIcon,
12363
- size: 'x-small',
12364
- variant: 'text'
12674
+ useRender(() => {
12675
+ const [windowProps] = VWindow.filterProps(props);
12676
+ return createVNode(VWindow, mergeProps({
12677
+ "ref": windowRef
12678
+ }, windowProps, {
12679
+ "modelValue": model.value,
12680
+ "onUpdate:modelValue": $event => model.value = $event,
12681
+ "class": ['v-carousel', {
12682
+ 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
12683
+ 'v-carousel--vertical-delimiters': props.verticalDelimiters
12684
+ }, props.class],
12685
+ "style": [{
12686
+ height: convertToUnit(props.height)
12687
+ }, props.style]
12688
+ }), {
12689
+ default: slots.default,
12690
+ additional: _ref2 => {
12691
+ let {
12692
+ group
12693
+ } = _ref2;
12694
+ return createVNode(Fragment, null, [!props.hideDelimiters && createVNode("div", {
12695
+ "class": "v-carousel__controls",
12696
+ "style": {
12697
+ left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
12698
+ right: props.verticalDelimiters === 'right' ? 0 : 'auto'
12365
12699
  }
12366
- },
12367
- "scoped": true
12368
- }, {
12369
- default: () => [group.items.value.map((item, index) => {
12370
- const props = {
12371
- id: `carousel-item-${item.id}`,
12372
- 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
12373
- class: [group.isSelected(item.id) && 'v-btn--active'],
12374
- onClick: () => group.select(item.id, true)
12375
- };
12376
- return slots.item ? slots.item({
12377
- props,
12378
- item
12379
- }) : createVNode(VBtn, mergeProps(item, props), null);
12380
- })]
12381
- })]), props.progress && createVNode(VProgressLinear, {
12382
- "class": "v-carousel__progress",
12383
- "color": typeof props.progress === 'string' ? props.progress : undefined,
12384
- "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
12385
- }, null)]);
12386
- },
12387
- prev: slots.prev,
12388
- next: slots.next
12389
- }));
12700
+ }, [group.items.value.length > 0 && createVNode(VDefaultsProvider, {
12701
+ "defaults": {
12702
+ VBtn: {
12703
+ color: props.color,
12704
+ icon: props.delimiterIcon,
12705
+ size: 'x-small',
12706
+ variant: 'text'
12707
+ }
12708
+ },
12709
+ "scoped": true
12710
+ }, {
12711
+ default: () => [group.items.value.map((item, index) => {
12712
+ const props = {
12713
+ id: `carousel-item-${item.id}`,
12714
+ 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
12715
+ class: [group.isSelected(item.id) && 'v-btn--active'],
12716
+ onClick: () => group.select(item.id, true)
12717
+ };
12718
+ return slots.item ? slots.item({
12719
+ props,
12720
+ item
12721
+ }) : createVNode(VBtn, mergeProps(item, props), null);
12722
+ })]
12723
+ })]), props.progress && createVNode(VProgressLinear, {
12724
+ "class": "v-carousel__progress",
12725
+ "color": typeof props.progress === 'string' ? props.progress : undefined,
12726
+ "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
12727
+ }, null)]);
12728
+ },
12729
+ prev: slots.prev,
12730
+ next: slots.next
12731
+ });
12732
+ });
12390
12733
  return {};
12391
12734
  }
12392
12735
  });
@@ -14419,7 +14762,7 @@ const VCombobox = genericComponent()({
14419
14762
  const {
14420
14763
  filteredItems,
14421
14764
  getMatches
14422
- } = useFilter(props, items, computed(() => isPristine.value ? undefined : search.value));
14765
+ } = useFilter(props, items, () => isPristine.value ? '' : search.value);
14423
14766
  const selections = computed(() => {
14424
14767
  return model.value.map(v => {
14425
14768
  return items.value.find(item => props.valueComparator(item.value, v.value)) || v;
@@ -14439,6 +14782,10 @@ const VCombobox = genericComponent()({
14439
14782
  });
14440
14783
  const menuDisabled = computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
14441
14784
  const listRef = ref();
14785
+ const {
14786
+ onListScroll,
14787
+ onListKeydown
14788
+ } = useScrolling(listRef, vTextFieldRef);
14442
14789
  function onClear(e) {
14443
14790
  cleared = true;
14444
14791
  if (props.openOnClear) {
@@ -14516,11 +14863,6 @@ const VCombobox = genericComponent()({
14516
14863
  search.value = '';
14517
14864
  }
14518
14865
  }
14519
- function onListKeydown(e) {
14520
- if (e.key === 'Tab') {
14521
- vTextFieldRef.value?.focus();
14522
- }
14523
- }
14524
14866
  function onAfterLeave() {
14525
14867
  if (isFocused.value) {
14526
14868
  isPristine.value = true;
@@ -14631,38 +14973,50 @@ const VCombobox = genericComponent()({
14631
14973
  "onKeydown": onListKeydown,
14632
14974
  "onFocusin": onFocusin,
14633
14975
  "onFocusout": onFocusout,
14976
+ "onScrollPassive": onListScroll,
14634
14977
  "tabindex": "-1"
14635
14978
  }, {
14636
14979
  default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
14637
14980
  "title": t(props.noDataText)
14638
- }, null)), displayItems.value.map((item, index) => {
14639
- const itemProps = mergeProps(item.props, {
14640
- key: index,
14641
- active: highlightFirst.value && index === 0 ? true : undefined,
14642
- onClick: () => select(item)
14643
- });
14644
- return slots.item?.({
14645
- item,
14646
- index,
14647
- props: itemProps
14648
- }) ?? createVNode(VListItem, itemProps, {
14649
- prepend: _ref3 => {
14650
- let {
14651
- isSelected
14652
- } = _ref3;
14653
- return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
14654
- "key": item.value,
14655
- "modelValue": isSelected,
14656
- "ripple": false,
14657
- "tabindex": "-1"
14658
- }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
14659
- "icon": item.props.prependIcon
14660
- }, null)]);
14661
- },
14662
- title: () => {
14663
- return isPristine.value ? item.title : highlightResult(item.title, getMatches(item)?.title, search.value?.length ?? 0);
14664
- }
14665
- });
14981
+ }, null)), createVNode(VVirtualScroll, {
14982
+ "renderless": true,
14983
+ "items": displayItems.value
14984
+ }, {
14985
+ default: _ref3 => {
14986
+ let {
14987
+ item,
14988
+ index,
14989
+ itemRef
14990
+ } = _ref3;
14991
+ const itemProps = mergeProps(item.props, {
14992
+ ref: itemRef,
14993
+ key: index,
14994
+ active: highlightFirst.value && index === 0 ? true : undefined,
14995
+ onClick: () => select(item)
14996
+ });
14997
+ return slots.item?.({
14998
+ item,
14999
+ index,
15000
+ props: itemProps
15001
+ }) ?? createVNode(VListItem, itemProps, {
15002
+ prepend: _ref4 => {
15003
+ let {
15004
+ isSelected
15005
+ } = _ref4;
15006
+ return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
15007
+ "key": item.value,
15008
+ "modelValue": isSelected,
15009
+ "ripple": false,
15010
+ "tabindex": "-1"
15011
+ }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
15012
+ "icon": item.props.prependIcon
15013
+ }, null)]);
15014
+ },
15015
+ title: () => {
15016
+ return isPristine.value ? item.title : highlightResult(item.title, getMatches(item)?.title, search.value?.length ?? 0);
15017
+ }
15018
+ });
15019
+ }
14666
15020
  }), slots['append-item']?.()]
14667
15021
  })]
14668
15022
  }), selections.value.map((item, index) => {
@@ -19006,215 +19360,6 @@ const VValidation = genericComponent()({
19006
19360
  }
19007
19361
  });
19008
19362
 
19009
- const makeVVirtualScrollItemProps = propsFactory({
19010
- dynamicHeight: Boolean,
19011
- renderless: Boolean,
19012
- ...makeComponentProps()
19013
- }, 'VVirtualScrollItem');
19014
- const VVirtualScrollItem = genericComponent()({
19015
- name: 'VVirtualScrollItem',
19016
- props: makeVVirtualScrollItemProps(),
19017
- emits: {
19018
- 'update:height': height => true
19019
- },
19020
- setup(props, _ref) {
19021
- let {
19022
- emit,
19023
- slots
19024
- } = _ref;
19025
- const {
19026
- resizeRef,
19027
- contentRect
19028
- } = useResizeObserver();
19029
- useToggleScope(() => props.dynamicHeight, () => {
19030
- watch(() => contentRect.value?.height, height => {
19031
- if (height != null) emit('update:height', height);
19032
- });
19033
- });
19034
- function updateHeight() {
19035
- if (props.dynamicHeight && contentRect.value) {
19036
- emit('update:height', contentRect.value.height);
19037
- }
19038
- }
19039
- onUpdated(updateHeight);
19040
- useRender(() => props.renderless ? createVNode(Fragment, null, [slots.default?.({
19041
- props: {
19042
- ref: props.dynamicHeight ? resizeRef : undefined
19043
- }
19044
- })]) : createVNode("div", {
19045
- "ref": props.dynamicHeight ? resizeRef : undefined,
19046
- "class": ['v-virtual-scroll__item', props.class],
19047
- "style": props.style
19048
- }, [slots.default?.()]));
19049
- }
19050
- });
19051
-
19052
- // Composables
19053
-
19054
- // Types
19055
-
19056
- const UP = -1;
19057
- const DOWN = 1;
19058
- const makeVirtualProps = propsFactory({
19059
- itemHeight: [Number, String]
19060
- }, 'virtual');
19061
- function useVirtual(props, items, offset) {
19062
- const first = shallowRef(0);
19063
- const baseItemHeight = shallowRef(props.itemHeight);
19064
- const itemHeight = computed({
19065
- get: () => parseInt(baseItemHeight.value ?? 0, 10),
19066
- set(val) {
19067
- baseItemHeight.value = val;
19068
- }
19069
- });
19070
- const containerRef = ref();
19071
- const {
19072
- resizeRef,
19073
- contentRect
19074
- } = useResizeObserver();
19075
- watchEffect(() => {
19076
- resizeRef.value = containerRef.value;
19077
- });
19078
- const display = useDisplay();
19079
- const sizeMap = new Map();
19080
- let sizes = createRange(items.value.length).map(() => itemHeight.value);
19081
- const visibleItems = computed(() => {
19082
- const height = (contentRect.value?.height ?? display.height.value) - (offset?.value ?? 0);
19083
- return itemHeight.value ? Math.max(12, Math.ceil(height / itemHeight.value * 1.7 + 1)) : 12;
19084
- });
19085
- function handleItemResize(index, height) {
19086
- itemHeight.value = Math.max(itemHeight.value, height);
19087
- sizes[index] = height;
19088
- sizeMap.set(items.value[index], height);
19089
- }
19090
- function calculateOffset(index) {
19091
- return sizes.slice(0, index).reduce((curr, value) => curr + (value || itemHeight.value), 0);
19092
- }
19093
- function calculateMidPointIndex(scrollTop) {
19094
- const end = items.value.length;
19095
- let middle = 0;
19096
- let middleOffset = 0;
19097
- while (middleOffset < scrollTop && middle < end) {
19098
- middleOffset += sizes[middle++] || itemHeight.value;
19099
- }
19100
- return middle - 1;
19101
- }
19102
- let lastScrollTop = 0;
19103
- function handleScroll() {
19104
- if (!containerRef.value || !contentRect.value) return;
19105
- const height = contentRect.value.height - 56;
19106
- const scrollTop = containerRef.value.scrollTop;
19107
- const direction = scrollTop < lastScrollTop ? UP : DOWN;
19108
- const midPointIndex = calculateMidPointIndex(scrollTop + height / 2);
19109
- const buffer = Math.round(visibleItems.value / 3);
19110
- const firstIndex = midPointIndex - buffer;
19111
- const lastIndex = first.value + buffer * 2 - 1;
19112
- if (direction === UP && midPointIndex <= lastIndex) {
19113
- first.value = clamp(firstIndex, 0, items.value.length);
19114
- } else if (direction === DOWN && midPointIndex >= lastIndex) {
19115
- first.value = clamp(firstIndex, 0, items.value.length - visibleItems.value);
19116
- }
19117
- lastScrollTop = scrollTop;
19118
- }
19119
- function scrollToIndex(index) {
19120
- if (!containerRef.value) return;
19121
- const offset = calculateOffset(index);
19122
- containerRef.value.scrollTop = offset;
19123
- }
19124
- const allItems = computed(() => items.value.map((item, index) => ({
19125
- raw: item,
19126
- index
19127
- })));
19128
- const last = computed(() => Math.min(items.value.length, first.value + visibleItems.value));
19129
- const computedItems = computed(() => allItems.value.slice(first.value, last.value));
19130
- const paddingTop = computed(() => calculateOffset(first.value));
19131
- const paddingBottom = computed(() => calculateOffset(items.value.length) - calculateOffset(last.value));
19132
- onMounted(() => {
19133
- if (!itemHeight.value) {
19134
- // If itemHeight prop is not set, then calculate an estimated height from the average of inital items
19135
- itemHeight.value = sizes.slice(first.value, last.value).reduce((curr, height) => curr + height, 0) / visibleItems.value;
19136
- }
19137
- });
19138
- watch(() => items.value.length, () => {
19139
- sizes = createRange(items.value.length).map(() => itemHeight.value);
19140
- sizeMap.forEach((height, item) => {
19141
- const index = items.value.indexOf(item);
19142
- if (index === -1) {
19143
- sizeMap.delete(item);
19144
- } else {
19145
- sizes[index] = height;
19146
- }
19147
- });
19148
- });
19149
- return {
19150
- containerRef,
19151
- computedItems,
19152
- itemHeight,
19153
- paddingTop,
19154
- paddingBottom,
19155
- scrollToIndex,
19156
- handleScroll,
19157
- handleItemResize
19158
- };
19159
- }
19160
-
19161
- // Types
19162
-
19163
- const makeVVirtualScrollProps = propsFactory({
19164
- items: {
19165
- type: Array,
19166
- default: () => []
19167
- },
19168
- ...makeVirtualProps(),
19169
- ...makeComponentProps(),
19170
- ...makeDimensionProps()
19171
- }, 'VVirtualScroll');
19172
- const VVirtualScroll = genericComponent()({
19173
- name: 'VVirtualScroll',
19174
- props: makeVVirtualScrollProps(),
19175
- setup(props, _ref) {
19176
- let {
19177
- slots
19178
- } = _ref;
19179
- const {
19180
- dimensionStyles
19181
- } = useDimension(props);
19182
- const {
19183
- containerRef,
19184
- handleScroll,
19185
- handleItemResize,
19186
- scrollToIndex,
19187
- paddingTop,
19188
- paddingBottom,
19189
- computedItems
19190
- } = useVirtual(props, toRef(props, 'items'));
19191
- useRender(() => createVNode("div", {
19192
- "ref": containerRef,
19193
- "class": ['v-virtual-scroll', props.class],
19194
- "onScroll": handleScroll,
19195
- "style": [dimensionStyles.value, props.style]
19196
- }, [createVNode("div", {
19197
- "class": "v-virtual-scroll__container",
19198
- "style": {
19199
- paddingTop: convertToUnit(paddingTop.value),
19200
- paddingBottom: convertToUnit(paddingBottom.value)
19201
- }
19202
- }, [computedItems.value.map(item => createVNode(VVirtualScrollItem, {
19203
- "key": item.index,
19204
- "dynamicHeight": !props.itemHeight,
19205
- "onUpdate:height": height => handleItemResize(item.index, height)
19206
- }, {
19207
- default: () => [slots.default?.({
19208
- item: item.raw,
19209
- index: item.index
19210
- })]
19211
- }))])]));
19212
- return {
19213
- scrollToIndex
19214
- };
19215
- }
19216
- });
19217
-
19218
19363
  var components = /*#__PURE__*/Object.freeze({
19219
19364
  __proto__: null,
19220
19365
  VAlert: VAlert,
@@ -20013,7 +20158,7 @@ function createVuetify$1() {
20013
20158
  date
20014
20159
  };
20015
20160
  }
20016
- const version$1 = "3.3.6";
20161
+ const version$1 = "3.3.8";
20017
20162
  createVuetify$1.version = version$1;
20018
20163
 
20019
20164
  // Vue's inject() can only be used in setup
@@ -20038,7 +20183,7 @@ const createVuetify = function () {
20038
20183
  ...options
20039
20184
  });
20040
20185
  };
20041
- const version = "3.3.6";
20186
+ const version = "3.3.8";
20042
20187
  createVuetify.version = version;
20043
20188
 
20044
20189
  export { components, createVuetify, directives, useDefaults, useDisplay, useLayout, useLocale, useRtl, useTheme, version };