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

caast

v1.3.0

Published

A TypeScript-safe React component library

Readme

caast

Detect clicks from anywhere in your React app. Simple, server-friendly, zero setup.

Why caast?

Tired of wrapping your app in providers just to detect clicks across components? caast lets you listen for clicks from anywhere in your React tree—even across server and client component boundaries—with zero setup.

One Listener, Multiple Casters. One component listens for clicks, many components can trigger it. Perfect for detecting user interactions from multiple places and responding with your own logic.

caast includes a built-in toggle function (on/off switching), but you're free to use the click detection however you want—the onCast callback gives you full control.

Features

Server Component Friendly - Casters work as server components (no "use client" needed)
🎯 Simple API - Just two components: Listener and Caster
🚀 No Providers - Skip the Context API complexity
🔗 Cross-Boundary Communication - Works seamlessly between server and client components
🎨 Works with Any Element - Buttons, links, divs—anything can be a Caster
Zero JavaScript Overhead - Uses native browser APIs, no event listeners, optimized by default

Installation

npm install caast

Quick Start

Basic Usage

"use client"; // Only needed where Listener is used

import { Listener, Caster } from "caast";

function MyComponent() {
  const handleToggle = (value: boolean) => {
    console.log("Toggled:", value);
    // Update your state, open/close modals, etc.
  };

  return (
    <>
      {/* One Listener - must be in a client component */}
      <Listener channel="sidebar" onCast={handleToggle} />

      {/* Multiple Casters - can be anywhere, even server components */}
      <Caster channel="sidebar">
        <button>Toggle Sidebar</button>
      </Caster>

      <Caster channel="sidebar">
        <a href="#">Or click here</a>
      </Caster>

      {/* Works with any element */}
      <Caster channel="sidebar">
        <div className="custom-trigger">Custom trigger</div>
      </Caster>
    </>
  );
}

Server + Client Components

// app/layout.tsx (Server Component)
import { Caster } from "caast";

export default function Layout() {
  return (
    <header>
      {/* Server component - no "use client" needed! */}
      <Caster channel="menu">
        <button>Menu</button>
      </Caster>
    </header>
  );
}

// app/menu.tsx (Client Component)
("use client");

import { Listener } from "caast";

export function Menu() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      {/* Listener must be in client component */}
      <Listener channel="menu" onCast={setIsOpen} />

      {isOpen && <div>Menu content</div>}
    </>
  );
}

Multiple Casters, One Listener

"use client";

import { Listener, Caster } from "caast";

function App() {
  const handleModal = (isOpen: boolean) => {
    // Handle modal state
  };

  return (
    <>
      {/* One Listener handles all Casters */}
      <Listener channel="modal" onCast={handleModal} />

      {/* Multiple triggers from anywhere */}
      <Caster channel="modal">
        <button>Open from header</button>
      </Caster>

      <Caster channel="modal">
        <a href="#">Open from link</a>
      </Caster>

      <Caster channel="modal">
        <div onClick={handleSomething}>Open from custom element</div>
      </Caster>
    </>
  );
}

How It Works

  1. Listener - Listens for clicks on a specific channel from anywhere in your app
  2. Caster - Triggers the Listener when clicked (can be anywhere in your component tree)
  3. Channel - A string identifier that connects Casters to their Listener

When any Caster with the same channel is clicked, it detects the click and calls your onCast callback with a boolean value. The communication happens through native browser APIs—no JavaScript event listeners, no complex state management, just pure browser magic. The Listener maintains an internal toggle state (on/off), but you can use the boolean value however you want—update your own state, trigger side effects, or ignore the toggle entirely.

Use Cases

  • Click Detection - Detect clicks from multiple components across your app
  • Modals & Dialogs - Open/close from multiple buttons (use the toggle or your own state)
  • Sidebars & Drawers - Detect clicks from header, footer, or anywhere
  • Accordions - Detect clicks from multiple triggers
  • Theme Toggles - Detect theme switch clicks from various UI elements
  • Any click-based interaction - Respond to clicks from anywhere, handle them your way

Rules

One Listener per channel - Each channel should have exactly one Listener
Multiple Casters - You can have as many Casters as you want for one Listener
Listener in client component - The Listener component must be in a client component (use 'use client')
Casters anywhere - Caster components work as server components by default

That's It!

No providers, no context setup, no complex state management, no JavaScript event listeners. Just Listener and Caster connected by a channel name. The communication happens through native browser APIs—simple, optimized, and works everywhere.


Made with ❤️ for React developers who value simplicity.