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

react-precognition

v2.0.1

Published

A predictive React hook that forks the future. Zero-latency interactions via cursor intent analysis.

Readme

🔮 React Precognition (v2)

Stop reacting. Start predicting. A single-loop, zero-overhead predictive engine for React.

The Problem: Standard Web: User Clicks (0ms) → Network Request (200ms) → UI Update. Latency: 200ms.

The Solution: Precognition: Cursor Intent (-200ms) → Network Request (200ms) → User Clicks (0ms) → UI Update. Latency: 0ms.

🚀 What's New in v2?

The "Game Loop" Architecture. Previous versions (and other libraries) attach a mousemove listener for every interactive element. If you had 50 links, you had 50 listeners thrashing the main thread.

v2 changes the game. We use a single global physics loop (like a game engine).

1 Button: 1 unit of CPU.

1,000 Buttons: ~1 unit of CPU.

O(1) Scaling: Drop this on large data grids or mega-menus without fear.

📦 Installation

pnpm add react-precognition

or

npm install react-precognition

🛠 Usage

  1. The Provider (The Brain)

Wrap your app (or a specific subtree) in the PrecognitionProvider. This initializes the single event listener.

// App.tsx import { PrecognitionProvider } from 'react-precognition';

export default function App() { return ( ); }

  1. The Hook (The Sensor)

Use the hook on any interactive element.

import { useRef } from 'react'; import { usePrecognition } from 'react-precognition';

const SmartButton = () => { const ref = useRef(null);

// Define the speculative action (Must be idempotent! GET requests only.) const prefetchData = async (signal: AbortSignal) => { return await fetch('/api/user-details', { signal }); };

const { commit, status } = usePrecognition(ref, prefetchData);

return ( View Profile {status === 'ready' && Preloaded!} ); };

🎛 The Tuning Guide (Knobs & Dials)

You don't need to know vector math. You just need to know how to adjust the "feel."

sensitivity (0.0 to 1.0)

The "Trigger Finger." Controls how confident the engine must be before it speculates.

Default: 0.6

⬇ Lower (0.3): Trigger happy. Will fire if the user vaguely waves in the direction of the button. Good for high-priority, low-cost actions.

⬆ Higher (0.9): Sniper mode. Will only fire if the user is moving fast and directly at the center of the button. Good for "heavy" actions you don't want to waste.

maxInfluenceDistance (pixels)

The "Cone of Vision." How far away can the cursor be and still trigger the button?

Default: 800

⬇ Lower (200): Short-sighted. User must be close to the button. Reduces "cross-fire" if you have many buttons close together.

⬆ Higher (1500): Eagle-eyed. Detects intent from across the screen.

gracePeriod (ms)

The "Short-Term Memory." If the user intends to click, but then twitches their mouse away for a split second, how long do we hold the result?

Default: 2500

⬇ Lower (500): Brutal. If they look away, we trash the data immediately. Saves RAM, but might cause re-fetching.

⬆ Higher (5000): Forgiving. Keeps the preloaded data alive longer.

historySize (integer)

The "Smoothing" Factor. How many frames of mouse history do we analyze?

Default: 6

⬇ Lower (3): Highly reactive. Instantly detects direction changes, but prone to "jitter" (noise).

⬆ Higher (12): Very smooth. Ignores hand tremors, but feels slightly "laggy" to detect sudden turns.

decelerationWeight (0.0 to 1.0)

The "Braking" Bonus.

Default: 0.3

If the user is moving towards the button AND slowing down (preparing to stop/click), we boost the intent score. Increase this if you want to capture "slow and steady" approachers.

⚠️ Safety & Best Practices

Idempotency is Law:

✅ DO: Fetch data, load code chunks, pre-connect to sockets.

❌ DO NOT: Delete records, buy items, sign out.

Why? The user might aim at the button, trigger the action, and then change their mind. You cannot "un-delete" a record easily.

Mobile/Touch:

This library automatically disables itself on touch devices. You don't need to do anything. We save the user's battery by killing the physics loop on mobile.

Visual Feedback:

We recommend not showing loading spinners during speculation. It confuses users ("I didn't click yet!").

Instead, use the status to perhaps subtly highlight the button or change the cursor, signaling "I am ready."

API Reference

const { commit, // Function: Call this in your real onClick handler. Returns the Promise. status, // String: 'idle' | 'speculating' | 'ready' | 'committed' result // Any: The data returned from your async action (if ready) } = usePrecognition(ref, action, config);

Config Object

{ sensitivity?: number; // Default: 0.6 gracePeriod?: number; // Default: 2500 (ms) historySize?: number; // Default: 6 (frames) noiseThreshold?: number; // Default: 0.05 (px/ms) maxInfluenceDistance?: number; // Default: 800 (px) decelerationWeight?: number; // Default: 0.3 debug?: boolean; // Default: false (Logs events to console) }