pota/use/mouse

Tracks held mouse buttons and the pointer position document-wide, backed by Pointer Events (not Mouse Events) — so back / forward buttons report and pen / touch input is covered.

Listeners are shared across all subscribers: any number of callers cost a single set of window listeners, installed on first use and removed when the last one goes away. A pointerup always releases its button (so a button can't get stuck), and a window blur — alt-tabbing while holding — releases everything.

Exports

Button numbers

Button indices follow PointerEvent.button:

Examples

Track the pointer position

Reactively render the live { x, y } client coordinates. Pass the reader function returned by useMousePosition so the text updates as the pointer moves.

import { useMousePosition } from 'pota/use/mouse'
import { render } from 'pota'

function App() {
	const pos = useMousePosition()
	return <pre>{() => `x: ${pos().x}, y: ${pos().y}`}</pre>
}

render(App)

Show whether a button is held

useMouseButton(button) returns a reactive boolean accessor. Here the left button drives a Show; right-clicking would use button 2 instead.

import { useMouseButton } from 'pota/use/mouse'
import { Show } from 'pota/components'
import { render } from 'pota'

function App() {
	const leftDown = useMouseButton(0)
	return (
		<Show
			when={leftDown}
			fallback={<p>release</p>}
		>
			<p>left button held</p>
		</Show>
	)
}

render(App)

Poll held buttons in a render loop

mouseButtons() exposes the live, non-reactive Set of held button indices, and mousePosition() takes a fresh snapshot — both ideal inside a requestAnimationFrame loop where reactive tracking would be wasted overhead. Treat the returned set as read-only.

import { mouseButtons, mousePosition } from 'pota/use/mouse'
import { useAnimationFrame } from 'pota/use/animate'
import { render } from 'pota'

function App() {
	const out = (<output>idle</output>) as HTMLOutputElement

	useAnimationFrame(() => {
		const held = [...mouseButtons()]
		const { x, y } = mousePosition()
		out.textContent = `buttons: [${held}] at ${x},${y}`
	}).start()

	return out
}

render(App)