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

@hotora/react-inputs

v1.0.1

Published

React adapter for Hotora Inputs — lightweight library for handling keyboard shortcuts, gestures and complex input sequences in React applications.

Readme

@hotora/react-inputs

React bindings for @hotora/inputs — a lightweight system for keyboard shortcuts, sequences, and scoped input handling in React applications.

It provides declarative and scoped APIs on top of the core InputsManager.


Features

  • React Context integration
  • Declarative & scoped input handling
  • Element-bound sequences via refs
  • Global + local scope support
  • SSR-safe provider support
  • Fully compatible with @hotora/inputs
  • No reactive re-subscription model (stable registration)

Installation

npm install @hotora/react-inputs @hotora/inputs

Core Concept

This library is a thin React layer over @hotora/inputs.

It does NOT replace the core logic — it only:

  • provides context
  • binds inputs to React lifecycle
  • exposes React-friendly hooks

Provider

HotoraInputsProvider

Provides a shared InputsManager instance via React context.

Supports:

  • Uncontrolled mode (default): manager is created internally
  • Controlled mode: external manager can be passed in
<HotoraInputsProvider>
  <App />
</HotoraInputsProvider>

Uncontrolled usage (recommended)

<HotoraInputsProvider provider={myProvider}>
  <App />
</HotoraInputsProvider>

Controlled usage

const manager = createInputsManager(myProvider);

<HotoraInputsProvider manager={manager}>
  <App />
</HotoraInputsProvider>;

Scope System

HotoraScope

Creates an isolated input scope bound to a DOM element.

Each scope:

  • binds sequences to a specific DOM node
  • participates in scope resolution chain
  • supports parent → child propagation rules
import { HotoraScope } from "@hotora/react-inputs";

<HotoraScope sequence={["KeyA", "KeyB"]} setup={setup}>
  <Game />
</HotoraScope>;

Hook API

useHotoraInputs

Registers an input sequence using the InputsManager from context.

⚠️ This hook is intentionally non-reactive

Changes to sequence, setup, or scope do NOT trigger re-registration.


Global usage

Registers a global shortcut (no DOM binding required):

useHotoraInputs(["Escape"], {
  handler: () => {
    console.log("Escape pressed");
  },
});

Scoped usage (element-bound)

In scoped mode, the hook returns a ref callback that must be attached to a DOM element.

The sequence will only be active when the element is part of the active scope chain.

const ref = useHotoraInputs(
  ["KeyS"],
  {
    handler: () => {
      console.log("Save triggered inside scope");
    },
  },
  "editor",
);

return (
  <div ref={ref}>
    <textarea />
  </div>
);

How scoped mode works

  1. A unique action is registered for the sequence

  2. The returned ref binds the action to a DOM element

  3. Inputs are resolved through scope chain:

    element → parent scopes → $global
  4. The handler fires only when the active element is inside that scope


Important behavior

  • Scoped mode requires attaching the returned ref to a DOM element
  • If the ref is not attached → sequence is inactive
  • Moving element between scopes automatically rebinds the action
  • Cleanup is automatic on unmount

Invalid usage

// ❌ invalid: scoped mode without attaching ref
useHotoraInputs(["KeyS"], setup, "editor");
// ❌ invalid: using ref in global mode
const ref = useHotoraInputs(["Escape"], setup);

Mental model

Global mode:
  sequence → InputsManager → handler

Scoped mode:
  DOM element → scope resolution → InputsManager → handler

Key Design Decisions

1. Non-reactive by design

Inputs are NOT re-registered when props change. This ensures predictable behavior and stable performance.


2. Single manager model

Only one InputsManager instance is recommended per application. Multiple managers may break scope propagation.


3. Scope-first architecture

All inputs resolve through:

element → parent scopes → global

Compatibility

  • React 18+
  • Next.js (App Router / Pages Router)
  • SSR environments (with LazyEventProvider from core)
  • Custom event providers

License

MIT