Vize

pointer

Track the latest pointer (mouse, touch, or pen) state.

Package @vizejs/composable/pointer
Own the source vize lib pull composable:pointer
Runtime exports usePointer, toPointerKind
Gzip budget 1792 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

import { usePointer, toPointerKind } from "@vizejs/composable/pointer";

Try it

Inspect a guide pad's actual pointer events

Read the latest accepted mouse pointer snapshot and distinguish target membership from retained coordinates.

Open the interactive example

What to observe: Move into the pad, press and release, then leave. Client coordinates and pressure follow native mouse Pointer Events; Inside changes on leaving without clearing the snapshot. Hide the pad, move elsewhere, then show it again: the removed target stops receiving events and the replacement resumes observation.

usePointer receives the reactive pad target and a fixed mouse-only snapshot filter. Its shallow readonly state records client coordinates in this iframe, pressure and the pointer identifier; it is not element-relative geometry. The default provider also accepts touch and pen snapshots; this example filters those kinds on pointerdown, pointermove and pointerup, and its native browser checks cover mouse input. Pointerleave clears Inside regardless of the snapshot filter. Hiding a target does not reset the latest snapshot. Target replacement removes old passive listeners; component scope disposal stops the target watcher. SSR exposes the initial zero snapshot, null pointer kind and false inside flag; no browser host is replaced.

Compare the initial and interacted states
Inspect a guide pad's actual pointer events: initial state
Initial state
Inspect a guide pad's actual pointer events: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { ref, useTemplateRef } from "vue";
import { usePointer } from "@vizejs/composable/pointer";

const pad = useTemplateRef<HTMLElement>("pad");
const visible = ref(true);
const { state, isInside } = usePointer({ target: pad, pointerTypes: ["mouse"] });
</script>

<template>
  <div class="composable-example">
    <label class="pointer-toggle"
      ><input v-model="visible" type="checkbox" /> Show pointer guide pad</label
    >
    <section v-if="visible" ref="pad" class="pointer-pad" aria-label="Pointer guide pad">
      <strong>Inspect an actual mouse pointer</strong>
      <p>Move across this pad, then press and release.</p>
    </section>
    <output aria-live="polite">
      Latest pointer: {{ state.pointerType ?? "none" }} · Inside: {{ isInside ? "yes" : "no" }} ·
      Client: {{ Math.round(state.x) }}, {{ Math.round(state.y) }}
    </output>
    <dl>
      <div>
        <dt>Pressure</dt>
        <dd class="pointer-pressure">{{ state.pressure }}</dd>
      </div>
      <div>
        <dt>Pointer identifier</dt>
        <dd>{{ state.pointerId }}</dd>
      </div>
    </dl>
    <p>
      These readonly values describe the latest accepted event in this iframe's client coordinates,
      not the pad's local coordinates. This example records mouse snapshots only; its checks cover
      mouse input.
    </p>
    <p>
      Leaving the pad changes Inside without clearing the last snapshot. Hiding it removes its
      listeners; the last snapshot remains. Showing it attaches the new pad. Server rendering starts
      with zero values, no pointer kind and Inside: no.
    </p>
  </div>
</template>

<style scoped>
.pointer-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;

  input {
    inline-size: auto;
  }
}
.pointer-pad {
  min-block-size: 120px;
  padding: 12px;
  border: 1px solid currentColor;
  border-radius: 8px;
}
</style>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
usePointer input experimental deterministic-fallback stable caller, reactive-scope web, desktop window toPointerKind, tryOnScopeDispose
toPointerKind input experimental safe not-applicable none web, server, worker, native, desktop, terminal — —

API

usePointer

Track the latest pointer (mouse, touch, or pen) state. Listens passively for pointerdown, pointermove, pointerup, and pointerleave on the reactive target and filters by device kind. Listeners are removed with the owning reactive scope; server renders expose the initial snapshot.

function usePointer(options: UsePointerOptions = {}): PointerControls

toPointerKind

Narrow a platform pointerType string to the closed PointerKind union.

function toPointerKind(value: string): PointerKind | null

Types

PointerState

Snapshot of the latest pointer event.

Member Type Description
x number Horizontal client coordinate.
y number Vertical client coordinate.
pressure number Normalized pressure in [0, 1].
pointerId number Identifier of the pointer that produced the latest event.
tiltX number Pen tilt around the Y axis in degrees.
tiltY number Pen tilt around the X axis in degrees.
width number Contact geometry width in CSS pixels.
height number Contact geometry height in CSS pixels.
twist number Pen rotation in degrees.
pointerType PointerKind | null Device kind; null before the first event.

UsePointerOptions

Options for usePointer.

Member Type Description
pointerTypes? readonly PointerKind[] Device kinds to track.
target? MaybeRefOrGetter<EventTarget | null | undefined> Event target to listen on.
initialValue? Partial<PointerState> State exposed before any input and during server rendering.

PointerControls

Reactive pointer state returned by usePointer.

Member Type Description
state Readonly<PointerState> Latest pointer snapshot.
isInside Readonly<Ref<boolean>> Whether the pointer is inside the target (between enter/move and leave).