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

@happy-pixels/input-forge

v0.3.1

Published

A platform-agnostic input management library for JavaScript games and applications. Provides a unified API for handling keyboard, gamepad, and custom input sources with support for dynamic input mapping and the command pattern.

Readme

Input Forge

Input Forge is a platform-agnostic input management library designed to seamlessly normalize inputs from keyboards and game controllers. For games built with Phaser, Three.js, or other frameworks, Input Forge simplifies input handling by supporting multiple input sources, customizable controls, and a unified API for event-driven and polled inputs.


Installation

npm install @happy-pixels/input-forge

Quick Start

import { InputManager, Command, Inputs } from '@happy-pixels/input-forge';

// 1. Create a command
class JumpCommand extends Command {
    trigger(): void {
        console.log('Jump!');
    }
}

// 2. Define an input map
const gameplayMap = {
    id: 'gameplay',
    singleInput: {
        jump: {
            keyboardInput: Inputs.KEYBOARD_SPACE,
            controllerInput: Inputs.CONTROLLER_FACE_BOTTOM,
            command: new JumpCommand()
        }
    }
};

// 3. Create the manager and set the input map
const manager = new InputManager();
manager.setInputMap(gameplayMap);

// 4. Start the tick loop (for update events and TickCommands)
manager.startTick();

// 5. Clean up when done
// manager.destroy();

Core Concepts

Commands

Commands define what happens when an input is triggered. There are three command types:

Command (Single Input)

For button-like inputs (keyboard keys, controller buttons).

class JumpCommand extends Command {
    trigger(): void {
        // Called once when key/button is pressed
        this.player.jump();
    }

    update(): void {
        // Called every frame while held
        this.player.extendJump();
    }

    release(): void {
        // Called once when key/button is released
        this.player.endJump();
    }
}

AxesCommand (Analog Input)

For analog inputs like joysticks or WASD movement.

class MoveCommand extends AxesCommand {
    trigger(axes: AxesInput): void {
        // Called when stick moves away from center
        this.player.startMoving(axes.x, axes.y);
    }

    update(axes: AxesInput): void {
        // Called every frame with current axis values
        this.player.move(axes.x, axes.y);
    }

    release(): void {
        // Called when stick returns to center
        this.player.stopMoving();
    }
}

TickCommand (Continuous)

For commands that run every frame, regardless of input.

class PhysicsCommand extends TickCommand {
    tick(delta: number): void {
        // delta is milliseconds since last frame
        this.world.step(delta / 1000);
    }
}

// Must use systemInput: Inputs.SYSTEM_TICK
const inputMap = {
    id: 'gameplay',
    singleInput: {
        physics: { systemInput: Inputs.SYSTEM_TICK, command: new PhysicsCommand() }
    }
};

Input Maps

Input maps define the relationship between inputs and commands.

import type { InputMap } from '@happy-pixels/input-forge';

const gameplayMap: InputMap = {
    id: 'gameplay',

    // Button/key inputs
    singleInput: {
        jump: {
            keyboardInput: Inputs.KEYBOARD_SPACE,
            controllerInput: Inputs.CONTROLLER_FACE_BOTTOM,
            command: new JumpCommand()
        },
        attack: {
            keyboardInput: Inputs.KEYBOARD_J,
            controllerInput: Inputs.CONTROLLER_FACE_RIGHT,
            command: new AttackCommand()
        }
    },

    // Analog/axes inputs
    axesInput: {
        move: {
            keyboardAxes: {
                vertical: { up: 'w', down: 's' },
                horizontal: { left: 'a', right: 'd' }
            },
            controllerStick: Inputs.CONTROLLER_LEFT_STICK,
            command: new MoveCommand()
        }
    }
};

Input Map Stacking

Use stacking for context switching (gameplay → pause menu → options).

// Set the base gameplay map
manager.setInputMap(gameplayMap);

// Player opens pause menu - push on top
manager.pushInputMap(pauseMenuMap);

// Player opens options from pause menu
manager.pushInputMap(optionsMap);

// Player closes options - returns to pause menu
manager.popInputMap();

// Player closes pause menu - returns to gameplay
manager.popInputMap();

When to use set vs push:

  • setInputMap() - Replaces all maps. Use for major state changes (menu → gameplay).
  • pushInputMap() - Adds a map on top. Use for overlays (pause menu, dialog).
  • popInputMap() - Removes the top map. Use to close overlays.

Custom Inputs

Trigger inputs programmatically for touch controls or virtual buttons.

// Single input (button press)
manager.triggerCustomInput('my_action');

// Axes input (virtual joystick)
manager.triggerCustomAxesInput('virtual_stick', { x: 0.5, y: -0.5 });
manager.updateCustomAxesInput('virtual_stick', { x: 1, y: 0 });
manager.releaseCustomAxesInput('virtual_stick');

In your input map:

const inputMap = {
    id: 'gameplay',
    singleInput: {
        action: { customInput: 'my_action', command: new ActionCommand() }
    },
    axesInput: {
        move: { customAxesInput: 'virtual_stick', command: new MoveCommand() }
    }
};

API Reference

InputManager

| Method | Description | |--------|-------------| | setInputMap(map) | Replace all input maps with a new one | | pushInputMap(map) | Add an input map on top of the stack | | popInputMap() | Remove the top input map | | hasInputMap(id) | Check if a map exists in the stack | | removeInputMap(id) | Remove a specific map by ID | | currentInputMap() | Get the active map's ID | | startTick() | Start the tick loop | | stopTick() | Stop the tick loop | | triggerCustomInput(key) | Trigger a custom single input | | triggerCustomAxesInput(name, axes) | Trigger a custom axes input | | updateCustomAxesInput(name, axes) | Update a custom axes input | | releaseCustomAxesInput(name) | Release a custom axes input | | destroy() | Clean up all resources |

Input Constants

import { Inputs } from '@happy-pixels/input-forge';

// Keyboard
Inputs.KEYBOARD_SPACE    // ' '
Inputs.KEYBOARD_ENTER    // 'Enter'
Inputs.KEYBOARD_ESCAPE   // 'Escape'
Inputs.KEYBOARD_W        // 'w'
// ... and more

// Controller
Inputs.CONTROLLER_FACE_BOTTOM   // A button (Xbox) / X (PlayStation)
Inputs.CONTROLLER_FACE_RIGHT    // B button (Xbox) / Circle (PlayStation)
Inputs.CONTROLLER_LEFT_STICK    // Left analog stick
Inputs.CONTROLLER_RIGHT_STICK   // Right analog stick
// ... and more

// System
Inputs.SYSTEM_TICK  // For TickCommand

Features

Input Forge aims to provide a flexible and robust input management solution with the following capabilities:

  • Platform-Agnostic: Integrates seamlessly with any JavaScript-based platform, such as Phaser or Three.js.
  • Multi-Input Support: Handles multiple input sources (e.g., keyboard and gamepad) for a single action.
  • Normalized Inputs: Unifies event-driven keyboard inputs and polled gamepad inputs into a consistent API.
  • Customizable Controls: Enables dynamic input mapping, allowing players to personalize their controls.
  • Streamlined Development: Reduces the complexity of input management, freeing developers to focus on core game logic.