Skip to content

Commit

Permalink
fix(VSlideGroup): debounce size updates, scroll to active item on resize
Browse files Browse the repository at this point in the history
  • Loading branch information
KaelWD committed Jun 23, 2022
1 parent 9981bbf commit 6682129
Showing 1 changed file with 40 additions and 54 deletions.
94 changes: 40 additions & 54 deletions packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx
Expand Up @@ -15,8 +15,8 @@ import { useRtl } from '@/composables/rtl'

// Utilities
import { bias, calculateCenteredOffset, calculateUpdatedOffset } from './helpers'
import { clamp, defineComponent, useRender } from '@/util'
import { computed, ref, watch, watchEffect } from 'vue'
import { clamp, defineComponent, IN_BROWSER, useRender } from '@/util'
import { computed, ref, watch } from 'vue'

// Types
import type { GroupProvide } from '@/composables/group'
Expand Down Expand Up @@ -79,17 +79,6 @@ export const VSlideGroup = defineComponent({
const { resizeRef: containerRef, contentRect: containerRect } = useResizeObserver()
const { resizeRef: contentRef, contentRect } = useResizeObserver()

watchEffect(() => {
if (!containerRect.value || !contentRect.value) return

const sizeProperty = isHorizontal.value ? 'width' : 'height'

containerSize.value = containerRect.value[sizeProperty]
contentSize.value = contentRect.value[sizeProperty]

isOverflowing.value = containerSize.value + 1 < contentSize.value
})

const firstSelectedIndex = computed(() => {
if (!group.selected.value.length) return -1

Expand All @@ -102,51 +91,48 @@ export const VSlideGroup = defineComponent({
return group.items.value.findIndex(item => item.id === group.selected.value[group.selected.value.length - 1])
})

watch(group.selected, () => {
if (firstSelectedIndex.value < 0 || !contentRef.value) return

// TODO: Is this too naive? Should we store element references in group composable?
const selectedElement = contentRef.value.children[lastSelectedIndex.value] as HTMLElement

if (firstSelectedIndex.value === 0 || !isOverflowing.value) {
scrollOffset.value = 0
} else if (props.centerActive) {
scrollOffset.value = calculateCenteredOffset({
selectedElement,
containerSize: containerSize.value,
contentSize: contentSize.value,
isRtl: isRtl.value,
isHorizontal: isHorizontal.value,
})
} else if (isOverflowing.value) {
scrollOffset.value = calculateUpdatedOffset({
selectedElement,
containerSize: containerSize.value,
contentSize: contentSize.value,
isRtl: isRtl.value,
currentScrollOffset: scrollOffset.value,
isHorizontal: isHorizontal.value,
})
}
})

let firstOverflow = true
watch(isOverflowing, () => {
if (!firstOverflow || !contentRef.value || firstSelectedIndex.value < 0) return
if (IN_BROWSER) {
let frame = -1
watch(() => [group.selected.value, containerRect.value, contentRect.value, isHorizontal.value], () => {
cancelAnimationFrame(frame)
frame = requestAnimationFrame(() => {
if (containerRect.value && contentRect.value) {
const sizeProperty = isHorizontal.value ? 'width' : 'height'

firstOverflow = false
containerSize.value = containerRect.value[sizeProperty]
contentSize.value = contentRect.value[sizeProperty]

// TODO: Is this too naive? Should we store element references in group composable?
const selectedElement = contentRef.value.children[firstSelectedIndex.value] as HTMLElement
isOverflowing.value = containerSize.value + 1 < contentSize.value
}

scrollOffset.value = calculateCenteredOffset({
selectedElement,
containerSize: containerSize.value,
contentSize: contentSize.value,
isRtl: isRtl.value,
isHorizontal: isHorizontal.value,
if (firstSelectedIndex.value >= 0 && contentRef.value) {
// TODO: Is this too naive? Should we store element references in group composable?
const selectedElement = contentRef.value.children[lastSelectedIndex.value] as HTMLElement

if (firstSelectedIndex.value === 0 || !isOverflowing.value) {
scrollOffset.value = 0
} else if (props.centerActive) {
scrollOffset.value = calculateCenteredOffset({
selectedElement,
containerSize: containerSize.value,
contentSize: contentSize.value,
isRtl: isRtl.value,
isHorizontal: isHorizontal.value,
})
} else if (isOverflowing.value) {
scrollOffset.value = calculateUpdatedOffset({
selectedElement,
containerSize: containerSize.value,
contentSize: contentSize.value,
isRtl: isRtl.value,
currentScrollOffset: scrollOffset.value,
isHorizontal: isHorizontal.value,
})
}
}
})
})
})
}

const disableTransition = ref(false)

Expand Down

0 comments on commit 6682129

Please sign in to comment.