@stackoverfloweth/prefect-design
Version:
A collection of low-level Vue components.
66 lines (55 loc) • 1.76 kB
text/typescript
import { onMounted, onUnmounted, ref, Ref } from 'vue'
import { MaybeRef } from '@/types/ref'
type DisconnectScrollLink = () => void
type ScrollLinkReturnValue = {
disconnect: DisconnectScrollLink,
source: Ref<HTMLElement | undefined>,
target: Ref<HTMLElement | undefined>,
}
/**
* The useScrollLinking composition takes 2 optional element references (source, target)
* and attaches a scroll event listener to the source. When the scroll event of the
* source element is fired, the scroll position of the target is updated to match, producing
* a scroll linking effect.
*
* This composition will tear down when the calling component is unmounted but can be disconnected
* early using the returned disconnect method.
*
* @param source Ref<HTMLElement>
* @param target Ref<HTMLElement>
* @returns ScrollLinkReturnValue
*/
export function useScrollLinking(
source?: MaybeRef<HTMLElement>,
target?: MaybeRef<HTMLElement>,
): ScrollLinkReturnValue {
const sourceRef = ref(source)
const targetRef = ref(target)
const handleScroll = (): void => {
if (!sourceRef.value || !targetRef.value) {
return
}
targetRef.value.scrollTop = sourceRef.value.scrollTop
targetRef.value.scrollLeft = sourceRef.value.scrollLeft
sourceRef.value.style.width = `${targetRef.value.scrollWidth}px`
}
const connect = (): void => {
if (!sourceRef.value) {
return
}
sourceRef.value.addEventListener('scroll', handleScroll)
}
const disconnect = (): void => {
if (!sourceRef.value) {
return
}
sourceRef.value.removeEventListener('scroll', handleScroll)
}
onMounted(connect)
onUnmounted(disconnect)
return {
disconnect,
source: sourceRef,
target: targetRef,
}
}