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-tailwind-click-frame-animation

v0.1.1

Published

A lightweight, customizable React frame-by-frame animation component for mouse events (click, context menu, drag, and scroll) styled with Tailwind CSS.

Downloads

57

Readme

react-tailwind-click-frame-animation

npm version npm downloads

A lightweight, customizable React frame-by-frame mouse & touch animation package with 3D perspective transforms, one-command CLI asset initialization, and Tailwind CSS support.

🔗 NPM Package: https://www.npmjs.com/package/react-tailwind-click-frame-animation
🐙 GitHub Repository: https://github.com/kagancetin/react-tailwind-click-frame-animation

Live Demo


✨ Features

  • 🖱️ Full Gesture Detection (Desktop & Mobile):
    • Left Click / Tap: Static puff animation (Smoke).
    • Right Click / Long Press: Explosion animation (SmokeExplosion) with native context-menu blocking.
    • Drag & Shoot / Swipe: Directional projectile with angle calculation (SmokeSpell).
    • Scroll / Wheel: Continuous 3D Euler-spinning vortex (PoisonousSmoke).
  • ⚡ One-Command Asset Setup (npx react-tailwind-click-frame-animation init):
    • Automatically copies all default animation assets into your project's public/images/click/ directory with a single command.
  • 🪶 Ultra-Lightweight (~31 KB Bundle):
    • Zero base64 bloat! No Babel 500KB bundle threshold warnings and lightning-fast load times.
  • 🎛️ Granular Controls & Master Toggles:
    • enableMobile: Toggle touch interaction per individual gesture (leftClick, rightClick, dragShoot, scroll) or globally via general.enableMobile.
    • preventDefault: Toggle native browser actions per gesture (e.g. disable right-click context menu, disable scroll propagation).
    • preventTextSelection: Global master switch via general.preventTextSelection (false allows selecting text across the page, true disables text selection during gestures).
    • preventElementDrag: Prevents native HTML5 ghost element dragging and cursor changes on images/links during swipe/drag gestures (defaults to true).
  • 🎞️ Custom Frame Support:
    • Use custom public folder paths (e.g. folder: "/images/custom-fire").
    • Custom file extensions (png, webp, svg, jpg).
    • Zero-padding toggle (01.png vs 1.png).
    • Direct frame URLs override (frames: ["url1", "url2", ...]).
  • 🌐 Zero-Bloat Localization:
    • Built-in English default with full TypeScript typing.
    • Easily override with custom language JSON objects (locale).
  • 📐 Smooth 60 FPS CSS 3D Transforms: High-performance requestAnimationFrame render loop with CSS perspective transforms.

📦 Installation

npm install react-tailwind-click-frame-animation
# or
pnpm add react-tailwind-click-frame-animation
# or
yarn add react-tailwind-click-frame-animation

Initialize Default Assets (Recommended)

Run the CLI command in your project root to automatically copy the default animation frames into your public/ directory:

npx react-tailwind-click-frame-animation init

💡 This command creates public/images/click/ containing Smoke, SmokeExplosion, SmokeSpell, and PoisonousSmoke assets so they are immediately available.

Include package styles in your project (e.g., main.tsx, index.tsx, or App.tsx):

import "react-tailwind-click-frame-animation/style.css";

🚀 Quick Start

1. Plug & Play

Once you've run the init command, drop the detector anywhere in your React tree:

import { MouseGestureDetector } from "react-tailwind-click-frame-animation";
import "react-tailwind-click-frame-animation/style.css";

export default function App() {
  return (
    <div>
      {/* Captures gestures and renders animations across the viewport */}
      <MouseGestureDetector />

      <main className="p-8">
        <h1>Welcome to My App</h1>
      </main>
    </div>
  );
}

⚙️ Complete Default Config (Ready to Copy & Paste)

You can customize any gesture or global option using the config prop. Every field is optional; any missing field automatically falls back to these defaults:

{
  "leftClick": {
    "enabled": true,
    "enabledMobile": true,
    "folder": "Smoke",
    "frameCount": 10,
    "width": 75,
    "height": 75,
    "frameDuration": 45,
    "extension": "png",
    "padZero": true,
    "preventDefault": true
  },
  "rightClick": {
    "enabled": true,
    "enabledMobile": true,
    "longPressMs": 500,
    "folder": "SmokeExplosion",
    "frameCount": 16,
    "width": 90,
    "height": 90,
    "frameDuration": 35,
    "extension": "png",
    "padZero": true,
    "preventDefault": true
  },
  "dragShoot": {
    "enabled": true,
    "enabledMobile": true,
    "folder": "SmokeSpell",
    "frameCount": 10,
    "width": 80,
    "height": 50,
    "frameDuration": 10,
    "speed": 8,
    "maxDistance": 450,
    "rotateToAngle": true,
    "rotationOffset": 180,
    "extension": "png",
    "padZero": true,
    "preventDefault": true
  },
  "scroll": {
    "enabled": true,
    "enabledMobile": false,
    "folder": "PoisonousSmoke",
    "frameCount": 12,
    "width": 60,
    "height": 70,
    "frameDuration": 40,
    "axes": {
      "x": false,
      "y": false,
      "z": true
    },
    "initialRotation": {
      "x": 30,
      "y": 0,
      "z": 0
    },
    "spinSpeed": 8,
    "throttleMs": 140,
    "extension": "png",
    "padZero": true,
    "preventDefault": false
  },
  "general": {
    "enableMobile": true,
    "showHUD": true,
    "clickThreshold": 15,
    "preventTextSelection": false,
    "preventElementDrag": true
  }
}

🎨 Customizing Config via React Props

Pass only the settings you wish to change:

<MouseGestureDetector
  config={{
    general: {
      preventTextSelection: false, // Enable normal text selection across all gestures
      enableMobile: true,         // Master switch for mobile touch listeners
      showHUD: false,             // Hide the top-right gesture badge
    },
    leftClick: {
      width: 80,
      height: 80,
    },
    rightClick: {
      enableMobile: false,         // Disable long-press explosion on mobile
      preventDefault: false,       // Let native browser right-click menu show
    },
    dragShoot: {
      speed: 20,                  // Faster projectile speed
      maxDistance: 600,           // Longer flight path
    },
    scroll: {
      enableMobile: false,        // Disable mobile touch scroll vortex
      preventDefault: true,        // Prevent webpage scroll while spinning
    },
  }}
/>

📁 Folder Structure & Sequential File Naming

Default Animation Assets (npx react-tailwind-click-frame-animation init)

Running the init command generates the standard folder structure inside your project's public/images/click/ directory:

my-react-app/
├── public/
│   └── images/
│       └── click/
│           ├── Smoke/              <-- Default for Left Click / Tap (10 frames)
│           │   ├── 01.png
│           │   ├── ...
│           │   └── 10.png
│           ├── SmokeExplosion/     <-- Default for Right Click / Long Press (16 frames)
│           │   ├── 01.png
│           │   └── ...
│           ├── SmokeSpell/         <-- Default for Drag & Shoot / Swipe (10 frames)
│           │   ├── 01.png
│           │   └── ...
│           └── PoisonousSmoke/     <-- Default for Scroll / Wheel (12 frames)
│               ├── 01.png
│               └── ...
├── src/
│   ├── App.tsx
│   └── main.tsx
├── package.json
└── ...

Custom Animations

When using your own custom animations, place your sequential frame images inside your project's public/ directory (e.g. public/assets/fire/):

my-react-app/
├── public/
│   └── assets/
│       └── fire/
│           ├── 01.webp     <-- Frame 1 (padZero: true)
│           ├── 02.webp     <-- Frame 2
│           ├── 03.webp     <-- Frame 3
│           ├── ...
│           └── 15.webp     <-- Frame 15 (frameCount: 15)

🔢 Naming Formats & Options

| Option | Setting | Expected Filename Sequence | Example | | :--- | :--- | :--- | :--- | | padZero: true (Default) | 2-digit zero-padding | 01.ext, 02.ext, ... 09.ext, 10.ext, 11.ext | 01.png ... 16.png | | padZero: false | Plain sequential integer | 1.ext, 2.ext, ... 9.ext, 10.ext, 11.ext | 1.webp ... 15.webp | | extension | Any image extension | png (default), webp, svg, jpg, gif | extension: "webp" | | folder | Relative to public/ | Starts with / pointing inside public/ | folder: "/assets/fire" | | frameCount | Total number of frames | How many numbered files to generate & cycle through | frameCount: 15 |


🖼️ Using Custom Frames & Folders

Example 1: Loading from public/assets/fire/

<MouseGestureDetector
  config={{
    leftClick: {
      folder: "/assets/fire", // Points to public/assets/fire/
      frameCount: 15,         // Looks for 01.webp through 15.webp
      extension: "webp",      // File extension
      padZero: true,          // true: 01, 02... | false: 1, 2...
      width: 100,
      height: 100,
    },
  }}
/>

Or pass a direct array of frame URLs:

<MouseGestureDetector
  config={{
    leftClick: {
      frames: [
        "https://example.com/frame1.png",
        "https://example.com/frame2.png",
        "https://example.com/frame3.png",
      ],
      width: 70,
      height: 70,
    },
  }}
/>

🌐 Custom Language JSON (Localization)

You can pass a custom translation object to the locale prop:

// my-tr.json
{
  "hud": {
    "lastDetected": "Algılanan Son Hareket:"
  },
  "gestures": {
    "none": "Henüz bir hareket yapılmadı",
    "leftClick": "Sol Tık",
    "rightClick": "Sağ Tık (Patlama)",
    "dragShoot": "Sürükle & Fırlat: Açı: {angle}°, Mesafe: {distance}px",
    "scrollDown": "Aşağı Scroll",
    "scrollUp": "Yukarı Scroll",
    "mobileLongPress": "Mobil Uzun Basma",
    "mobileTap": "Mobil Dokunma",
    "mobileSwipe": "Mobil Fırlatma: Açı: {angle}°, Mesafe: {distance}px"
  }
}
import myLocale from "./my-tr.json";

<MouseGestureDetector locale={myLocale} />

🛠️ Development & Contributing

Clone and run the interactive playground locally:

# Install dependencies
npm install

# Start development playground
npm run dev

# Run TypeScript check
npm run typecheck

# Build npm library package (dist/)
npm run build

# Build playground demo (dist-demo/)
npm run build:demo