diff --git a/README.md b/README.md index d6d44c40b02b..8caf151c4244 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Collection of essential Vue Composition Utilities NPM version NPM Downloads Docs & Demos -Function Count +Function Count
GitHub stars

diff --git a/indexes.json b/indexes.json index d90d92879798..57e871a56562 100644 --- a/indexes.json +++ b/indexes.json @@ -792,6 +792,14 @@ "category": "Browser", "description": "reactive [Permissions API](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)" }, + { + "name": "usePointer", + "package": "core", + "component": true, + "docs": "https://vueuse.org/core/usePointer/", + "category": "Sensors", + "description": "reactive pointer state" + }, { "name": "usePointerSwipe", "package": "core", diff --git a/packages/components/index.ts b/packages/components/index.ts index 6da7bc03676d..2e2efcce322e 100644 --- a/packages/components/index.ts +++ b/packages/components/index.ts @@ -22,6 +22,7 @@ export * from '../core/useNetwork/component' export * from '../core/useNow/component' export * from '../core/useOnline/component' export * from '../core/usePageLeave/component' +export * from '../core/usePointer/component' export * from '../core/usePreferredColorScheme/component' export * from '../core/usePreferredDark/component' export * from '../core/usePreferredLanguages/component' diff --git a/packages/core/index.ts b/packages/core/index.ts index a5d9da97eae5..ee53f3f0a8e6 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -47,6 +47,7 @@ export * from './useOnline' export * from './usePageLeave' export * from './useParallax' export * from './usePermission' +export * from './usePointer' export * from './usePointerSwipe' export * from './usePreferredColorScheme' export * from './usePreferredDark' diff --git a/packages/core/usePointer/component.ts b/packages/core/usePointer/component.ts new file mode 100644 index 000000000000..2de229e2af2b --- /dev/null +++ b/packages/core/usePointer/component.ts @@ -0,0 +1,17 @@ +import { defineComponent, reactive } from 'vue-demi' +import { usePointer, UsePointerOptions } from '@vueuse/core' + +export const UsePointer = defineComponent({ + name: 'UsePointer', + props: [ + 'pointerTypes', + 'initialValue', + ] as unknown as undefined, + setup(props, { slots }) { + const data = reactive(usePointer(props)) + return () => { + if (slots.default) + return slots.default(data) + } + }, +}) diff --git a/packages/core/usePointer/demo.vue b/packages/core/usePointer/demo.vue new file mode 100644 index 000000000000..71ba685dc093 --- /dev/null +++ b/packages/core/usePointer/demo.vue @@ -0,0 +1,11 @@ + + + diff --git a/packages/core/usePointer/index.md b/packages/core/usePointer/index.md new file mode 100644 index 000000000000..0630d7f6e86b --- /dev/null +++ b/packages/core/usePointer/index.md @@ -0,0 +1,23 @@ +--- +category: Sensors +--- + +# usePointer + +Reactive [pointer state](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events). + +## Basic Usage + +```js +import { usePointer } from '@vueuse/core' + +const { x, y, pressure, pointerType } = usePointer() +``` + +## Component +```html + + x: {{ x }} + y: {{ y }} + +``` diff --git a/packages/core/usePointer/index.ts b/packages/core/usePointer/index.ts new file mode 100644 index 000000000000..6fd9861220ef --- /dev/null +++ b/packages/core/usePointer/index.ts @@ -0,0 +1,75 @@ +import { MaybeRef, objectPick, toRefs } from '@vueuse/shared' +import { ref, Ref } from 'vue-demi' +import { useEventListener } from '../useEventListener' +import { ConfigurableWindow, defaultWindow } from '../_configurable' +import { PointerType, Position } from '../_types' + +export interface UsePointerState extends Position { + pressure: number + pointerId: number + tiltX: number + tiltY: number + width: number + height: number + twist: number + pointerType: PointerType | null +} + +export interface UsePointerOptions extends ConfigurableWindow { + /** + * Pointer types that listen to. + * + * @default ['mouse', 'touch', 'pen'] + */ + pointerTypes?: PointerType[] + + /** + * Initial values + */ + initialValue?: MaybeRef> +} + +const defaultState: UsePointerState = /* #__PURE__ */ { + x: 0, + y: 0, + pointerId: 0, + pressure: 0, + tiltX: 0, + tiltY: 0, + width: 0, + height: 0, + twist: 0, + pointerType: null, +} +const keys = /* #__PURE__ */ Object.keys(defaultState) as (keyof UsePointerState)[] + +/** + * Reactive pointer state. + * + * @see https://vueuse.org/usePointer + * @param options + */ +export function usePointer(options: UsePointerOptions = {}) { + const { + window = defaultWindow, + } = options + + const state = ref(options.initialValue || {}) as unknown as Ref + Object.assign(state.value, defaultState, state.value) + + const handler = (event: PointerEvent) => { + 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 }) + } + + return { + ...toRefs(state), + } +} diff --git a/packages/functions.md b/packages/functions.md index 4778f0acf62e..95dc2a19960d 100644 --- a/packages/functions.md +++ b/packages/functions.md @@ -86,6 +86,7 @@ - [`useOnline`](https://vueuse.org/core/useOnline/) — reactive online state - [`usePageLeave`](https://vueuse.org/core/usePageLeave/) — reactive state to show whether the mouse leaves the page - [`useParallax`](https://vueuse.org/core/useParallax/) — create parallax effect easily + - [`usePointer`](https://vueuse.org/core/usePointer/) — reactive pointer state - [`usePointerSwipe`](https://vueuse.org/core/usePointerSwipe/) — reactive swipe detection based on [PointerEvents](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) - [`useResizeObserver`](https://vueuse.org/core/useResizeObserver/) — reports changes to the dimensions of an Element's content or the border-box - [`useSpeechRecognition`](https://vueuse.org/core/useSpeechRecognition/) — reactive [SpeechRecognition](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition) diff --git a/packages/shared/utils/index.ts b/packages/shared/utils/index.ts index cf890ec9718d..6d93ab8ef20a 100644 --- a/packages/shared/utils/index.ts +++ b/packages/shared/utils/index.ts @@ -85,3 +85,16 @@ export function increaseWithUnit(target: string | number, delta: number): string return target return result + unit } + +/** + * Create a new subset object by giving keys + * + * @category Object + */ +export function objectPick(obj: O, keys: T[], omitUndefined = false) { + return keys.reduce((n, k) => { + if (k in obj) + if (!omitUndefined || !obj[k] === undefined) n[k] = obj[k] + return n + }, {} as Pick) +}