pota/use/mouseTracks 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.
useMouseButton(button) — reactive
boolean: is a button held?mouseButtons() — live, non-reactive
Set<number> of held buttonsuseMousePosition() — reactive
{ x, y } pointer positionmousePosition() — non-reactive
{ x, y } snapshotButton indices follow PointerEvent.button:
0 — primary (left)1 — auxiliary (middle / wheel)2 — secondary (right)3 — back4 — forwardReactively 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)
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)
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)