Skip to content

Commit

Permalink
feat(usePointer): suppor target and isInside flag
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Sep 12, 2021
1 parent c05d5d6 commit 789dda6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 8 deletions.
16 changes: 12 additions & 4 deletions packages/core/usePointer/component.ts
@@ -1,17 +1,25 @@
import { defineComponent, reactive } from 'vue-demi'
import { defineComponent, reactive, ref } from 'vue-demi'
import { usePointer, UsePointerOptions } from '@vueuse/core'
import { defaultWindow } from '../_configurable'

export const UsePointer = defineComponent<UsePointerOptions>({
export const UsePointer = defineComponent<Omit<UsePointerOptions, 'target'> & { target: 'window' | 'self' }>({
name: 'UsePointer',
props: [
'pointerTypes',
'initialValue',
'target',
] as unknown as undefined,
setup(props, { slots }) {
const data = reactive(usePointer(props))
const el = ref<HTMLElement | null>(null)

const data = reactive(usePointer({
...props,
target: props.target === 'self' ? el : defaultWindow,
}))

return () => {
if (slots.default)
return slots.default(data)
return slots.default(data, { ref: el })
}
},
})
12 changes: 12 additions & 0 deletions packages/core/usePointer/index.md
Expand Up @@ -15,9 +15,21 @@ const { x, y, pressure, pointerType } = usePointer()
```

## Component

By default, the component will track the pointer on `window`

```html
<UsePointer v-slot="{ x, y }">
x: {{ x }}
y: {{ y }}
</UsePointer>
```

To track local position in the element, set `target="self"`:

```html
<UsePointer target="self" v-slot="{ x, y }">
x: {{ x }}
y: {{ y }}
</UsePointer>
```
18 changes: 14 additions & 4 deletions packages/core/usePointer/index.ts
Expand Up @@ -3,6 +3,7 @@ import { ref, Ref } from 'vue-demi'
import { useEventListener } from '../useEventListener'
import { ConfigurableWindow, defaultWindow } from '../_configurable'
import { PointerType, Position } from '../_types'
import { MaybeElementRef } from '../unrefElement'

export interface UsePointerState extends Position {
pressure: number
Expand All @@ -27,6 +28,11 @@ export interface UsePointerOptions extends ConfigurableWindow {
* Initial values
*/
initialValue?: MaybeRef<Partial<UsePointerState>>

/**
* @default window
*/
target?: MaybeElementRef
}

const defaultState: UsePointerState = /* #__PURE__ */ {
Expand All @@ -51,25 +57,29 @@ const keys = /* #__PURE__ */ Object.keys(defaultState) as (keyof UsePointerState
*/
export function usePointer(options: UsePointerOptions = {}) {
const {
window = defaultWindow,
target = defaultWindow,
} = options

const isInside = ref(false)
const state = ref(options.initialValue || {}) as unknown as Ref<UsePointerState>
Object.assign(state.value, defaultState, state.value)

const handler = (event: PointerEvent) => {
isInside.value = true
if (options.pointerTypes && !options.pointerTypes.includes(event.pointerType as PointerType))
return

state.value = objectPick(event, keys, false) as UsePointerState
}

if (window) {
useEventListener(window, 'pointerdown', handler, { passive: true })
useEventListener(window, 'pointermove', handler, { passive: true })
if (target) {
useEventListener(target, 'pointerdown', handler, { passive: true })
useEventListener(target, 'pointermove', handler, { passive: true })
useEventListener(target, 'pointerleave', () => isInside.value = false, { passive: true })
}

return {
...toRefs(state),
isInside,
}
}

0 comments on commit 789dda6

Please sign in to comment.