From f69f3bc0033fd70573d2a1aed3c563d7e9631ef9 Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 15 Mar 2024 16:02:59 -0400 Subject: [PATCH 1/4] Add useMousePosition composition --- src/useMousePosition/README.md | 25 +++++++++++++++ src/useMousePosition/index.ts | 1 + src/useMousePosition/useMousePosition.ts | 39 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/useMousePosition/README.md create mode 100644 src/useMousePosition/index.ts create mode 100644 src/useMousePosition/useMousePosition.ts diff --git a/src/useMousePosition/README.md b/src/useMousePosition/README.md new file mode 100644 index 00000000..8998e0fd --- /dev/null +++ b/src/useMousePosition/README.md @@ -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 +} +``` diff --git a/src/useMousePosition/index.ts b/src/useMousePosition/index.ts new file mode 100644 index 00000000..641a1c0e --- /dev/null +++ b/src/useMousePosition/index.ts @@ -0,0 +1 @@ +export * from './useMedia' \ No newline at end of file diff --git a/src/useMousePosition/useMousePosition.ts b/src/useMousePosition/useMousePosition.ts new file mode 100644 index 00000000..28a84e99 --- /dev/null +++ b/src/useMousePosition/useMousePosition.ts @@ -0,0 +1,39 @@ +import { reactive } from 'vue' +import { useGlobalEventListener } from '@/useGlobalEventListener' + +export type MousePosition = { + x: number, + y: number, +} + +export type UseMousePosition = { + position: MousePosition, + positionAtLastClick: MousePosition, +} + +const position = reactive({ x: 0, y: 0 }) +const positionAtLastClick = reactive({ 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() + } +} + +useGlobalEventListener('mousemove', updateMousePosition, { passive: true }) +useGlobalEventListener('click', updatePositionAtLastClick, { capture: true }) +useGlobalEventListener('contextmenu', updatePositionAtLastClick, { capture: true }) + +export function useMousePosition(): UseMousePosition { + return { + position, + positionAtLastClick, + } +} \ No newline at end of file From 953bdd10b06c6a1c4c8c4c64c1cb0e32893e2c8b Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 15 Mar 2024 16:03:49 -0400 Subject: [PATCH 2/4] Update bucket exports --- src/index.ts | 1 + src/useMousePosition/index.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 8d2bc5da..6bd750e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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' diff --git a/src/useMousePosition/index.ts b/src/useMousePosition/index.ts index 641a1c0e..b473f8ea 100644 --- a/src/useMousePosition/index.ts +++ b/src/useMousePosition/index.ts @@ -1 +1 @@ -export * from './useMedia' \ No newline at end of file +export * from './useMousePosition' \ No newline at end of file From 6dff5cdb2b2b935fb7e6ca0e4cf650d5af0480f8 Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 15 Mar 2024 16:12:07 -0400 Subject: [PATCH 3/4] Add some teardown/spinup logic --- src/useMousePosition/useMousePosition.ts | 36 +++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/useMousePosition/useMousePosition.ts b/src/useMousePosition/useMousePosition.ts index 28a84e99..c9effcbc 100644 --- a/src/useMousePosition/useMousePosition.ts +++ b/src/useMousePosition/useMousePosition.ts @@ -1,4 +1,4 @@ -import { reactive } from 'vue' +import { onScopeDispose, reactive, ref } from 'vue' import { useGlobalEventListener } from '@/useGlobalEventListener' export type MousePosition = { @@ -27,11 +27,39 @@ const updateMousePosition = (event: MouseEvent): void => { } } -useGlobalEventListener('mousemove', updateMousePosition, { passive: true }) -useGlobalEventListener('click', updatePositionAtLastClick, { capture: true }) -useGlobalEventListener('contextmenu', updatePositionAtLastClick, { capture: true }) +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, From ba1273704395f87f7ae42da89fa1a49a4580cb40 Mon Sep 17 00:00:00 2001 From: nicholas Date: Fri, 15 Mar 2024 16:19:37 -0400 Subject: [PATCH 4/4] Update root readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 57d4a2e8..1b633cc5 100644 --- a/README.md +++ b/README.md @@ -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)