npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tocada

v3.0.0

Published

Pointer and touch gestures with ease! (Inspired by the wonderful Tocca.js library). Written in Typescript with love

Readme

Tocada JS

Pointer and touch gestures with ease

Installation

npm install tocada

Basic Usage

import { usePointerEvents } from "tocada";

// Pass a query selector or HTMLElement (Pointer Events by default: mouse, pen, touch)
const swipeArea = usePointerEvents("#my-element");

// Listen for events
swipeArea.element.addEventListener("swipe", (e) => {
  console.log("Swiped!", e.detail);
});

// Clean up when done
swipeArea.destroy();

For TouchEvent-only input (legacy mobile pipelines), use useTouchEvents instead—it forces pointerEvents: false.

new Tocada(selectorOrElement) is the same as passing { pointerEvents: true } (Pointer Events). Use { pointerEvents: false } or useTouchEvents(...) only when you need the legacy touch stack.

Available Events

Single-contact events

| Event | Description | |-------|-------------| | tap | Quick touch < 200ms | | doubletap | Two taps within 300ms | | press | Touch held 200-500ms | | hold | Touch held > 500ms | | swipe | Fires before directional swipe events (same gesture also emits swipeup / swipedown / etc.) | | swipeup | Swipe in upward direction | | swipedown | Swipe in downward direction | | swipeleft | Swipe in left direction | | swiperight | Swipe in right direction | | swipeclockwise | Circular swipe in clockwise direction | | swipecounterclockwise | Circular swipe in counter-clockwise direction |

Multi-contact events

| Event | Description | |-------|-------------| | gesture | Fires before any multi-contact gesture (touchCount is active pointer / touch count) | | pinch | Two fingers moving closer together | | spread | Two fingers moving apart | | rotate | Two-finger rotation (fires before directional) | | rotateclockwise | Clockwise two-finger rotation | | rotatecounterclockwise | Counter-clockwise two-finger rotation |

Configuration Options

import { usePointerEvents } from "tocada";

const swipeArea = usePointerEvents("#my-element", {
  // Prefix all event names (e.g., "myapp-swipe", "myapp-tap")
  eventPrefix: "myapp-",

  // Enable high-precision element tracking (fills gaps between move events)
  // Adds computational overhead - use when you need complete element coverage
  useHighPrecision: true,

  // Customize detection thresholds
  thresholds: {
    swipeThreshold: 50,        // Min distance for swipe (px)
    tapMaxTime: 200,           // Max duration for tap (ms)
    doubleTapGap: 300,         // Max gap between taps for doubletap (ms)
    pressMinTime: 200,         // Min duration for press (ms)
    holdMinTime: 500,          // Min duration for hold (ms)
    circularSwipeMinArc: 90,   // Min arc for circular swipe (degrees)
    // NOT YET IMPLEMENTED palmMinTouches: 3,         // Min touch points for palm swipe
    // NOT YET IMPLEMENTED palmLineTolerance: 50,     // Tolerance for palm line detection (px)
    rotateMinAngle: 15,        // Min angle for rotation (degrees)
  }
});

// With prefix, listen like this:
swipeArea.element.addEventListener("myapp-swipe", (e) => {
  console.log("Swiped!", e.detail);
});

Event Details

Each event type provides a detail object with relevant data.

Swipe Events (swipe, swipeup, swipedown, swipeleft, swiperight)

{
  velocity,          // Overall speed (px/ms)
  velocityX,         // X-axis speed
  velocityY,         // Y-axis speed
  distance,          // Total distance traveled
  distanceX,         // X-axis distance
  distanceY,         // Y-axis distance
  avgPressure,       // Average touch pressure
  startPressure,     // Starting pressure
  endPressure,       // Ending pressure
  startTime,         // Start timestamp
  endTime,           // End timestamp
  startingElement,   // First element touched
  endingElement,     // Last element touched
  touchedElements,   // All elements touched during swipe
  startingCoords,    // { x, y } start position
  endingCoords,      // { x, y } end position
  // High precision fields (only when useHighPrecision: true)
  touchedPathElements?,        // Elements found by sampling touchPath coordinates
  interpolatedTouchedElements?, // Elements found via interpolation between touchmove events
  derivedTouchedElements?,     // Combined and chronologically ordered array (recommended)
}

Tap Events (tap, doubletap, press, hold)

{
  duration,          // How long the touch lasted (ms)
  pressure,          // Touch pressure
  element,           // Element that was tapped
  coords,            // { x, y } tap position
  startTime,         // Start timestamp
  endTime,           // End timestamp
}

Circular Swipe Events (swipeclockwise, swipecounterclockwise)

{
  direction,         // "clockwise" or "counterclockwise"
  arc,               // Total arc traversed (degrees)
  touchPath,         // Array of { x, y, time } points
  touchedElements,   // All elements touched during circular swipe
  // High precision fields (only when useHighPrecision: true)
  touchedPathElements?,        // Elements found by sampling touchPath coordinates
  interpolatedTouchedElements?, // Elements found via interpolation between touchmove events
  derivedTouchedElements?,     // Combined and chronologically ordered array (recommended)
}

Rotate Events (rotate, rotateclockwise, rotatecounterclockwise)

{
  angle,             // Total rotation (degrees)
  direction,         // "clockwise" or "counterclockwise"
  startAngle,        // Starting angle
  endAngle,          // Ending angle
  centerPoint,       // { x, y } center of rotation
}

Pinch/Spread Events (pinch, spread)

{
  gesture,           // "pinch" or "spread"
  startDistance,     // Initial distance between fingers
  endDistance,       // Final distance between fingers
  distanceChange,    // Change in distance
  scale,             // endDistance / startDistance
  centerPoint,       // { x, y } center point
}

Gesture Event (gesture)

{
  touchCount,        // Active contacts (pointers or touches, depending on pipeline)
}

High precision tracking

When useHighPrecision: true is enabled, Tocada provides additional element tracking arrays to fill gaps between discrete move samples (pointermove or touchmove, depending on pipeline) during rapid swipes. This is useful for:

  • Visual feedback: Highlighting all elements in a swipe path
  • Game interactions: Detecting all tiles/elements touched during a gesture
  • Complete coverage: Ensuring no elements are missed during fast swipes

Usage

const swipeArea = usePointerEvents("#my-element", {
  useHighPrecision: true
});

swipeArea.element.addEventListener("swipe", (e) => {
  // Use derivedTouchedElements for complete, ordered coverage
  const allElements = e.detail.derivedTouchedElements || e.detail.touchedElements;
  allElements.forEach(el => el.classList.add("highlighted"));
});

Available Arrays

When useHighPrecision: true, three additional arrays are provided:

  • touchedPathElements: Elements found by sampling coordinates from the touchPath array. This fills gaps by checking elements at points along the recorded touch path.

  • interpolatedTouchedElements: Elements found via interpolation between consecutive move events. Samples points every 5–10px along the interpolation path to catch elements that might have been missed.

  • derivedTouchedElements: Recommended to use. A combined array that merges touchedElements, interpolatedTouchedElements, and touchedPathElements, then orders them chronologically by their position in the touch path and deduplicates them.

Performance Considerations

High precision tracking adds computational overhead as it:

  • Samples multiple points along the path
  • Calls document.elementFromPoint() for each sampled point
  • Performs interpolation calculations during move events

Only enable this feature when you need complete element coverage. For most use cases, the standard touchedElements array is sufficient.

Native Browser Alternatives

For custom tracking needs or edge cases, you can use native browser APIs:

  • document.elementFromPoint(x, y): Get the topmost element at specific coordinates
  • document.elementsFromPoint(x, y): Get all elements at coordinates (in stack order)
  • PointerEvent: When using the default pointer pipeline, pressure, pointerId, and coalesced move events are available from the browser.
  • TouchEvent.touches (touch pipeline only): Access raw touch data during move events
  • TouchEvent.changedTouches (touch pipeline only): Touches that changed in the current event

These native APIs can be useful for:

  • Custom interpolation logic
  • Handling edge cases not covered by Tocada
  • Building specialized gesture tracking features
  • Debugging pointer or touch behavior

TypeScript Support

Tocada is written in TypeScript and exports all types:

import Tocada, {
  usePointerEvents,
  useTouchEvents,
  ITocadaOptions,
  ISwipeEventDetails,
  ITapEventDetails,
  IRotateEventDetails,
  IPinchSpreadEventDetails,
  // IPalmSwipeEventDetails, NOT YET IMPLEMENTED
  ICircularSwipeEventDetails,
  DEFAULT_THRESHOLDS,
} from "tocada";

Help Me Out

I write a lot of open source software (some more useful than others). You can help me out by tossing me a few bucks to buy coffee.