Skip to content

Commit

Permalink
feat(useElementByPoint): new multiple and interval options (#3089)
Browse files Browse the repository at this point in the history
  • Loading branch information
okxiaoliang4 committed May 12, 2023
1 parent 6d8477c commit 31b6626
Showing 1 changed file with 38 additions and 10 deletions.
48 changes: 38 additions & 10 deletions packages/core/useElementByPoint/index.ts
@@ -1,13 +1,23 @@
import type { Ref } from 'vue-demi'
import { ref } from 'vue-demi'
import type { MaybeRefOrGetter } from '@vueuse/shared'
import { toValue } from '@vueuse/shared'
import type { MaybeRefOrGetter, Pausable } from '@vueuse/shared'
import { toValue, useIntervalFn } from '@vueuse/shared'
import { useRafFn } from '../useRafFn'
import type { ConfigurableDocument } from '../_configurable'
import { defaultDocument } from '../_configurable'
import { useSupported } from '../useSupported'

export interface UseElementByPointOptions extends ConfigurableDocument {
export interface UseElementByPointOptions<Multiple extends boolean = false> extends ConfigurableDocument {
x: MaybeRefOrGetter<number>
y: MaybeRefOrGetter<number>
multiple?: MaybeRefOrGetter<Multiple>
immediate?: boolean
interval?: 'requestAnimationFrame' | number
}

export interface UseElementByPointReturn<Multiple extends boolean = false> extends Pausable {
isSupported: Ref<boolean>
element: Ref<Multiple extends true ? HTMLElement[] : HTMLElement | null>
}

/**
Expand All @@ -16,19 +26,37 @@ export interface UseElementByPointOptions extends ConfigurableDocument {
* @see https://vueuse.org/useElementByPoint
* @param options - UseElementByPointOptions
*/
export function useElementByPoint(options: UseElementByPointOptions) {
const element = ref<HTMLElement | null>(null)
export function useElementByPoint<M extends boolean = false>(options: UseElementByPointOptions<M>): UseElementByPointReturn<M> {
const {
x, y,
document = defaultDocument,
multiple,
interval = 'requestAnimationFrame',
immediate = true,
} = options

const { x, y, document = defaultDocument } = options
const isSupported = useSupported(() => {
if (toValue(multiple))
return document && 'elementsFromPoint' in document

const controls = useRafFn(() => {
element.value = (document?.elementFromPoint(toValue(x), toValue(y)) || null) as HTMLElement | null
return document && 'elementFromPoint' in document
})

const element = ref<any>(null)

const cb = () => {
element.value = toValue(multiple)
? document?.elementsFromPoint(toValue(x), toValue(y)) ?? []
: document?.elementFromPoint(toValue(x), toValue(y)) ?? null
}

const controls: Pausable = interval === 'requestAnimationFrame'
? useRafFn(cb, { immediate })
: useIntervalFn(cb, interval, { immediate })

return {
isSupported,
element,
...controls,
}
}

export type UseElementByPointReturn = ReturnType<typeof useElementByPoint>

0 comments on commit 31b6626

Please sign in to comment.