Skip to content

Commit

Permalink
Merge pull request #404 from PrefectHQ/nicholas/feature-use-mouse-pos…
Browse files Browse the repository at this point in the history
…ition-2024-03-15

Feature: `useMousePosition`
  • Loading branch information
znicholasbrown authored Mar 15, 2024
2 parents f46425f + ba12737 commit 7792566
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ npm i --save @prefecthq/vue-compositions
- [useIsSame](https://github.com/prefecthq/vue-compositions/tree/main/src/useIsSame)
- [useKeyDown](https://github.com/prefecthq/vue-compositions/tree/main/src/useKeyDown)
- [useMedia](https://github.com/prefecthq/vue-compositions/tree/main/src/useMedia)
- [useMousePosition](https://github.com/prefecthq/vue-compositions/tree/main/src/useMousePosition)
- [useMutationObserver](https://github.com/prefecthq/vue-compositions/tree/main/src/useMutationObserver)
- [useNow](https://github.com/prefecthq/vue-compositions/tree/main/src/useNow)
- [usePatchRef](https://github.com/prefecthq/vue-compositions/tree/main/src/usePatchRef)
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export * from './useIntersectionObserver'
export * from './useIsSame'
export * from './useKeyDown'
export * from './useMedia'
export * from './useMousePosition'
export * from './useMutationObserver'
export * from './useNow'
export * from './usePatchRef'
Expand Down
25 changes: 25 additions & 0 deletions src/useMousePosition/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# useMedia
The `useMousePosition` composition is a utility composition that passively tracks the position of the mouse as well as the position of the mouse at last click

## Example
```typescript
import { useMousePosition } from '@prefecthq/vue-compositions'

const { position, positionAtLastClick } = useMousePosition()
```

## Arguments
None

## Returns
```ts
type MousePosition {
x: number,
y: number
}

type UseMousePosition {
position: MousePosition,
positionAtLastClick: MousePosition
}
```
1 change: 1 addition & 0 deletions src/useMousePosition/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useMousePosition'
67 changes: 67 additions & 0 deletions src/useMousePosition/useMousePosition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { onScopeDispose, reactive, ref } from 'vue'
import { useGlobalEventListener } from '@/useGlobalEventListener'

export type MousePosition = {
x: number,
y: number,
}

export type UseMousePosition = {
position: MousePosition,
positionAtLastClick: MousePosition,
}

const position = reactive<MousePosition>({ x: 0, y: 0 })
const positionAtLastClick = reactive<MousePosition>({ x: 0, y: 0 })

const updatePositionAtLastClick = (): void => {
Object.assign(positionAtLastClick, position)
}

const updateMousePosition = (event: MouseEvent): void => {
position.x = event.clientX
position.y = event.clientY

if (positionAtLastClick.x === 0 && positionAtLastClick.y === 0) {
updatePositionAtLastClick()
}
}

const listeners = ref(0)

const { add: addMouseMoveEventListener, remove: removeMouseMoveEventListener } = useGlobalEventListener('mousemove', updateMousePosition, { passive: true })
const { add: addClickEventListener, remove: removeClickEventListener } = useGlobalEventListener('click', updatePositionAtLastClick, { capture: true })
const { add: addContextMenuEventListener, remove: removeContextMenuEventListener } = useGlobalEventListener('contextmenu', updatePositionAtLastClick, { capture: true })

function tryTeardownEventListeners(): void {
if (listeners.value > 0) {
return
}

removeMouseMoveEventListener()
removeClickEventListener()
removeContextMenuEventListener()
}

function addEventListeners(): void {
// These have no effect if the event listeners are already added
addMouseMoveEventListener()
addClickEventListener()
addContextMenuEventListener()
}

export function useMousePosition(): UseMousePosition {
listeners.value += 1

addEventListeners()

onScopeDispose(() => {
listeners.value -= 1
tryTeardownEventListeners()
})

return {
position,
positionAtLastClick,
}
}

0 comments on commit 7792566

Please sign in to comment.