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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@litert/pointer

v1.3.1

Published

A lightweight pointer event library for handling mouse, touch, and pen interactions in browsers.

Readme

@litert/pointer

A lightweight pointer event library for handling mouse, touch, and pen interactions in browsers. Provides unified APIs for down, move, click, long, hover, drag, resize and more.

Features

  • 🖱️ Unified pointer event handling (mouse, touch, pen)
  • 📱 Mobile-friendly with touch support
  • 🎯 Click, double-click, and long-press detection
  • 👆 Hover detection with enter/move/leave callbacks
  • 🔄 Drag and drop with customizable constraints
  • 📐 Resize functionality with border detection
  • 🎨 Global cursor management
  • 🪝 Global hooks for move events
  • 📦 Zero dependencies
  • 🔷 Full TypeScript support
  • 🌐 ESM and UMD bundle support

Installation

NPM

npm install @litert/pointer

CDN

<!-- UMD (Development) -->
<script src="https://unpkg.com/@litert/pointer/dist/index.umd.js"></script>

<!-- UMD (Production, minified) -->
<script src="https://unpkg.com/@litert/pointer/dist/index.umd.min.js"></script>

Usage

ESM (Recommended)

import * as pointer from '@litert/pointer';

element.addEventListener('pointerdown', (e) => {
    pointer.move(e, {
        move: (e, detail) => {
            console.log('Moving:', detail.ox, detail.oy);
        }
    });
});

Browser (UMD)

<script src="https://unpkg.com/@litert/pointer/dist/index.umd.min.js"></script>
<script>
element.addEventListener('pointerdown', function(e) {
    pointer.move(e, {
        move: function(e, detail) {
            console.log('Moving:', detail.ox, detail.oy);
        }
    });
});
</script>

Core Functions

down(e, options)

Down and up events, bind to pointer events.

pointer.down(e, {
    down: (e) => { /* Triggered when pressed */ },
    start: (e) => { /* Triggered when start moving, return false to cancel subsequent events */ },
    move: (e, dir) => { /* Triggered when moving, dir is the direction of movement */ },
    up: (e) => { /* Triggered when released */ },
    end: (e) => { /* Triggered when moving ends */ }
});

click(e, handler)

Click takes effect only when the pointer does not move and the time is less than 250ms.

element.addEventListener('pointerdown', (e) => {
    pointer.click(e, (e, x, y) => {
        console.log('Clicked at:', x, y);
    });
});

dblClick(e, handler)

Double-click event, the interval between two clicks is less than 300ms and the position difference is less than 10px.

element.addEventListener('pointerdown', (e) => {
    pointer.dblClick(e, (e, x, y) => {
        console.log('Double clicked at:', x, y);
    });
});

long(e, handler, options?)

Long press event, default 300ms.

element.addEventListener('pointerdown', (e) => {
    pointer.long(e, (e) => {
        console.log('Long press detected!');
    }, { 'time': 500 });
});

hover(e, options)

Hover event, handles enter, move, and leave for mouse and touch.

const cb = (e) => {
    pointer.hover(e, {
        enter: (e) => {
            console.log('Pointer entered');
        },
        move: (e) => {
            console.log('Pointer moving at:', e.clientX, e.clientY);
        },
        leave: (e) => {
            console.log('Pointer left');
        }
    });
};
element.addEventListener('pointerdown', cb);
element.addEventListener('pointerenter', cb);

move(e, options)

Drag event, supports boundary detection and constraints.

element.addEventListener('pointerdown', (e) => {
    pointer.move(e, {
        // --- Constraint area ---
        left: 0,
        top: 0,
        right: window.innerWidth,
        bottom: window.innerHeight,
        // --- Or use an element as a constraint area ---
        // areaObject: document.getElementById('container'),
        // --- Drag object (used to calculate boundary offset) ---
        object: element,
        // --- Callbacks ---
        start: (x, y) => {
            console.log('Start at:', x, y);
        },
        move: (e, detail) => {
            console.log('Move:', detail.ox, detail.oy);
            console.log('Position:', detail.x, detail.y);
            console.log('Border:', detail.border);
            console.log('Direction:', detail.dir);
        },
        up: (moveTimes, e) => {
            console.log('Up');
        },
        end: (moveTimes, e) => {
            console.log('End');
        },
        borderIn: (x, y, border, e) => {
            console.log('Border in:', border);
        },
        borderOut: () => {
            console.log('Border out');
        }
    });
});

addMoveHook(event, hook) & removeMoveHook(event, hook)

Global hooks for move events. These hooks are called for all move operations.

// --- Register global move down hook ---
pointer.addMoveHook('down', (e, opt) => {
    console.log('Global move down hook:', e, opt);
});

// --- Register global move up hook ---
pointer.addMoveHook('up', (e, opt) => {
    console.log('Global move up hook:', moveTimes, e, opt);
});

// --- Remove a hook ---
pointer.removeMoveHook('down', hookFunction);

resize(e, options)

Resize event.

element.addEventListener('pointerdown', (e) => {
    pointer.resize(e, {
        object: element,
        border: 'rb', // lt, t, tr, r, rb, b, bl, l
        minWidth: 100,
        minHeight: 100,
        maxWidth: 500,
        maxHeight: 500,
        start: (x, y) => {
            console.log('Resize start');
        },
        move: (left, top, width, height, x, y, border) => {
            element.style.left = left + 'px';
            element.style.top = top + 'px';
            element.style.width = width + 'px';
            element.style.height = height + 'px';
        },
        end: () => {
            console.log('Resize end');
        }
    });
});

drag(e, el, options)

Drag event, supports drag and drop to target elements.

// --- Set drag source ---
dragSource.addEventListener('pointerdown', (e) => {
    pointer.drag(e, dragSource, {
        data: { id: 1, name: 'item' },
        start: (x, y) => {
            console.log('Drag start');
        },
        move: (e, detail) => {
            console.log('Dragging');
        },
        end: (moveTimes, e) => {
            console.log('Drag end');
        }
    });
});

// --- Set drop target ---
dropTarget.dataset.drop = '';
dropTarget.addEventListener('dragenter', (e) => {
    console.log('Drag enter');
});
dropTarget.addEventListener('dragleave', (e) => {
    console.log('Drag leave');
});
dropTarget.addEventListener('drop', (e) => {
    const data = pointer.getDragData();
    console.log('Dropped:', data);
});

scale(e, handler)

Scale/zoom event, supports pinch-to-zoom on touch devices and mouse wheel.

element.addEventListener('pointerdown', (e) => {
    pointer.scale(e, (e, scale, cpos) => {
        console.log('Scale:', scale, 'Center:', cpos.x, cpos.y);
    });
});
element.addEventListener('wheel', (e) => {
    pointer.scale(e, (e, scale, cpos) => {
        console.log('Scale:', scale, 'Center:', cpos.x, cpos.y);
    });
});

gesture(e, before, handler)

Gesture event for swipe actions (up, down, left, right).

element.addEventListener('pointerdown', (e) => {
    pointer.gesture(e, (e, dir) => {
        // Return 1 to show gesture indicator, 0 to ignore, -1 to stop propagation
        return 1;
    }, (dir) => {
        console.log('Gesture completed:', dir);
    });
});
element.addEventListener('wheel', (e) => {
    pointer.gesture(e, (e, dir) => {
        return 1;
    }, (dir) => {
        console.log('Wheel gesture:', dir);
    });
});

Utility Functions

setCursor(type?)

Set/cancel global mouse style.

pointer.setCursor('move');
// ...
pointer.setCursor(); // Cancel

isTouch(e)

Check if the pointer event is from a touch device.

const isTouch = pointer.isTouch(e);
console.log('Is touch device:', isTouch);

Types

TDirection

Direction type.

type TDirection = 'top' | 'right' | 'bottom' | 'left';

TBorder

Border direction type.

type TBorder = 'lt' | 't' | 'tr' | 'r' | 'rb' | 'b' | 'bl' | 'l' | '';

IDownOptions

Options for the down function.

interface IDownOptions {
    down?: (e: PointerEvent) => void;
    start?: (e: PointerEvent) => any;
    move?: (e: PointerEvent, dir: TDirection) => any;
    up?: (e: PointerEvent) => void | Promise<void>;
    end?: (e: PointerEvent) => void | Promise<void>;
}

IHoverOptions

Options for the hover function.

interface IHoverOptions {
    enter?: (e: PointerEvent) => void;
    move?: (e: PointerEvent) => void;
    leave?: (e: PointerEvent) => void;
}

ILongOptions

Options for the long function.

interface ILongOptions {
    time?: number; // Long press time, default 300 ms
    down?: (e: PointerEvent) => void | Promise<void>;
    up?: (e: PointerEvent) => void | Promise<void>;
}

IMoveDetail

Detailed information in the move callback.

interface IMoveDetail {
    ox: number;      // x-axis offset
    oy: number;      // y-axis offset
    x: number;       // Current x coordinate
    y: number;       // Current y coordinate
    border: TBorder; // Border type
    inBorder: {      // Whether at the border
        top: boolean;
        right: boolean;
        bottom: boolean;
        left: boolean;
    };
    dir: TDirection; // Direction of movement
}

IMoveTime

Movement time record.

interface IMoveTime {
    time: number;
    ox: number;
    oy: number;
}

IMoveOptions

Options for the move function.

interface IMoveOptions {
    areaObject?: HTMLElement;
    left?: number;
    top?: number;
    right?: number;
    bottom?: number;
    offsetLeft?: number;
    offsetTop?: number;
    offsetRight?: number;
    offsetBottom?: number;
    objectLeft?: number;
    objectTop?: number;
    objectWidth?: number;
    objectHeight?: number;
    object?: HTMLElement;
    cursor?: string;
    start?: (x: number, y: number) => any;
    move?: (e: PointerEvent, detail: IMoveDetail) => void;
    borderIn?: (x: number, y: number, border: TBorder, e: PointerEvent) => void;
    borderOut?: () => void;
    up?: (moveTimes: IMoveTime[], e: PointerEvent) => void;
    end?: (moveTimes: IMoveTime[], e: PointerEvent) => void;
}

IMoveResult

Result returned by the move function.

interface IMoveResult {
    left: number;
    top: number;
    right: number;
    bottom: number;
}

IResizeOptions

Options for the resize function.

interface IResizeOptions {
    border: TBorder;
    minWidth?: number;
    minHeight?: number;
    maxWidth?: number;
    maxHeight?: number;
    object?: HTMLElement;
    objectLeft?: number;
    objectTop?: number;
    objectWidth?: number;
    objectHeight?: number;
    start?: (x: number, y: number) => any;
    move?: (left: number, top: number, width: number, height: number, x: number, y: number, border: TBorder) => void;
    end?: (moveTimes: IMoveTime[], e: PointerEvent) => void;
}

IDragOptions

Options for the drag function.

interface IDragOptions {
    data?: any;
    start?: (x: number, y: number) => any;
    move?: (e: PointerEvent, detail: IMoveDetail) => void;
    end?: (moveTimes: IMoveTime[], e: PointerEvent) => void;
}

TScaleHandler

Handler function type for scale events.

type TScaleHandler = (e: PointerEvent | WheelEvent, scale: number, cpos: { x: number; y: number; }) => void | Promise<void>;

TGestureBeforeHandler

Before handler function type for gesture events. Return 1 to show gesture, 0 to ignore, -1 to stop propagation.

type TGestureBeforeHandler = (e: PointerEvent | WheelEvent, dir: TDirection) => number;

TGestureHandler

Handler function type for gesture events.

type TGestureHandler = (dir: TDirection) => void | Promise<void>;

TMenuHandler

Handler function type for menu events.

type TMenuHandler = (e: PointerEvent | MouseEvent) => void | Promise<void>;

TMoveDownHook

Global hook function type for move down events.

type TMoveDownHook = (e: PointerEvent, opt: IMoveOptions) => void | Promise<void>;

TMoveUpHook

Global hook function type for move up events.

type TMoveUpHook = (e: PointerEvent, opt: IMoveOptions) => void | Promise<void>;

Demo

Clone the repository and open dist/test/index.html in your browser.

git clone https://github.com/litert/pointer.js.git
cd pointer.js
npm install
npm run build

Then open dist/test/index.html in your browser.

Browser Support

  • Chrome 55+
  • Firefox 59+
  • Safari 13+
  • Edge 79+
  • Mobile browsers (iOS Safari 13+, Chrome for Android)

Requires Pointer Events API support. For older browsers, consider using a polyfill.

License

This library is published under Apache-2.0 license.