1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 import { useTemplateRef, watch, onMounted, onBeforeUnmount } from 'vue'
import { isElementInViewport } from '../utils'
export const InfiniteLoader = ({ isLoading, hasMore }: { isLoading: boolean, hasMore: boolean }) => {
const emit = vineEmits(['load-more'])
const
loaderElement = useTemplateRef('loader'),
loaderObserver = new IntersectionObserver(([ entry ]) => {
(
entry?.isIntersecting &&
!isLoading && hasMore
) && emit('load-more')
})
onBeforeUnmount(() => loaderObserver.unobserve(loaderElement.value as HTMLElement))
onMounted(() => {
loaderObserver.observe(loaderElement.value as HTMLElement)
emit('load-more')
})
watch(
() => [ isLoading, hasMore ],
() => {
(
isElementInViewport(loaderElement.value as HTMLElement) &&
!isLoading && hasMore
) && emit('load-more')
},
{ immediate: true }
)
return vine`
<div ref="loader" class="row justify-content-center">
<span :aria-busy="isLoading" />
</div>
`
}