Skip to content

Event Filtering

The shouldHandleEvent callback lets you selectively ignore gestures based on the event target, modifier keys, or any other condition.

When you put interactive elements (buttons, inputs, sliders) inside the zoomable container, pointer events on those elements also trigger panning:

<div ref={containerRef}>
<div style={{ transform: ... }}>
{/* Clicking this button also starts a pan gesture */}
<button onClick={handleSave}>Save</button>
</div>
</div>
useZoomPinch({
containerRef,
shouldHandleEvent: (e) => {
return !(e.target as HTMLElement).closest(".no-pan")
},
})

Then mark interactive elements:

<button className="no-pan" onClick={handleSave}>Save</button>
<input className="no-pan" type="text" />
shouldHandleEvent: (e) => {
const tag = (e.target as HTMLElement).tagName
return !["BUTTON", "INPUT", "TEXTAREA", "SELECT", "A"].includes(tag)
}
shouldHandleEvent: (e) => {
return !(e.target as HTMLElement).closest("[data-no-pan]")
}
<button data-no-pan onClick={handleSave}>
Save
</button>
shouldHandleEvent: (e) => {
// Only handle wheel events if Ctrl is held
if (e instanceof WheelEvent) return e.ctrlKey
return true
}
shouldHandleEvent: (e) => {
// Don't handle events in the toolbar area
return !(e.target as HTMLElement).closest("#toolbar")
}

shouldHandleEvent is checked before preventDefault() in every handler:

  • wheel — checked before pan/zoom processing
  • pointerdown — checked before drag starts
  • touchstart / touchmove — checked before pinch processing

If it returns false, the event is completely ignored — as if enabled were false for that single event.