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

@qrunk/mino.js

v1.0.0

Published

GameCube controller library for the browser. Supports Nintendo, Mayflash, and Raphnet adapters via the W3C Gamepad API.

Readme

mino.js

GameCube controller library for JavaScript. Plug in any GameCube adapter and get normalized, event-driven input in the browser — zero dependencies, ~5 KB minified.

Features

  • Adapter auto-detection — Nintendo WUP-028, Mayflash, Raphnet, 8BitDo GBros, Brook, and generic USB adapters
  • Normalized state — every adapter maps to the same GCButton / GCAxis constants
  • Edge-detected eventspress, release, connect, disconnect
  • Full analog support — main stick, C-stick, L/R trigger analog values with configurable deadzone
  • 8-way stick directionmainStickDirection() / cStickDirection() helpers
  • Vibration — rumble support (where the browser/adapter allows)
  • Zero dependencies — pure W3C Gamepad API

Install

npm install mino.js

Or use a CDN:

<script src="https://unpkg.com/mino.js/dist/mino.min.js"></script>

Quick Start

import { Mino, GCButton } from 'mino.js';

const gc = new Mino();

// Listen for button presses
gc.on('press', ({ port, button }) => {
  console.log(`Port ${port}: ${button} pressed`);
});

gc.on('release', ({ port, button }) => {
  console.log(`Port ${port}: ${button} released`);
});

// Connection events
gc.on('connect', ({ port, adapter }) => {
  console.log(`Controller connected on port ${port} (${adapter})`);
});

// Poll loop — read state every frame
gc.on('poll', ({ port, state }) => {
  const { x, y } = state.mainStick;
  // Move character by (x, y)

  if (state.isPressed(GCButton.A)) {
    // A is held
  }
});

API

new Mino(options?)

Create a new GameCube controller manager.

| Option | Type | Default | Description | |--------|------|---------|-------------| | deadzone | number | 0.15 | Stick deadzone (0–1) | | triggerThreshold | number | 0.5 | Analog trigger → digital press threshold | | smoothing | boolean | false | Enable low-pass filter on stick axes | | smoothFactor | number | 0.5 | Smoothing strength (lower = smoother) | | autoStart | boolean | true | Auto-start polling on construction | | debug | boolean | false | Log adapter connections to console |

Reading State

// Get state for first connected controller
const state = gc.getState();

// Get state for a specific port
const state = gc.getState(0);

// All states
const all = gc.getAllStates();
// → [{ port: 0, adapter: 'Nintendo WUP-028', state: GCState }]

GCState Properties

| Property | Type | Description | |----------|------|-------------| | buttons | Record<GCButton, boolean> | All 12 button states | | axes | Record<GCAxis, number> | All 6 axis values | | mainStick | { x, y } | Main stick (−1 to +1) | | cStick | { x, y } | C-stick (−1 to +1) | | leftTrigger | number | L trigger analog (0–1) | | rightTrigger | number | R trigger analog (0–1) | | mainStickAngle | number | Main stick angle (radians) | | mainStickMagnitude | number | Main stick distance (0–1) | | connected | boolean | Connection status |

Methods

| Method | Description | |--------|-------------| | isPressed(button) | Check if button is held | | mainStickDirection(deadzone?) | 8-way direction string or null | | cStickDirection(deadzone?) | 8-way direction string or null | | clone() | Deep copy state | | toJSON() | Serialize to plain object |

Frame-Perfect Queries

// Did the button JUST go down this frame?
if (gc.justPressed(GCButton.A)) { /* jump */ }

// Did it JUST go up?
if (gc.justReleased(GCButton.B)) { /* release charge */ }

// Is it currently held?
if (gc.isHeld(GCButton.Z)) { /* shield */ }

Events

| Event | Payload | Description | |-------|---------|-------------| | connect | { port, adapter, gamepad } | Controller plugged in | | disconnect | { port, adapter } | Controller unplugged | | press | { port, button } | Button just pressed | | release | { port, button } | Button just released | | poll | { port, state } | Every frame (RAF) |

const unsub = gc.on('press', handler);
unsub(); // remove listener

gc.once('connect', handler); // fire once
gc.off('press', handler);    // manual remove

Configuration

gc.setDeadzone(0.2);
gc.setTriggerThreshold(0.4);
gc.setSmoothing(true, 0.3);

Vibration

gc.vibrate(0, {
  duration: 300,       // ms
  weakMagnitude: 0.5,  // 0–1
  strongMagnitude: 1.0 // 0–1
});

Lifecycle

gc.startPolling();  // begin RAF loop
gc.stopPolling();   // pause
gc.destroy();       // full cleanup

Button Constants

import { GCButton, GCAxis } from 'mino.js';

GCButton.A            GCButton.DPAD_UP
GCButton.B            GCButton.DPAD_DOWN
GCButton.X            GCButton.DPAD_LEFT
GCButton.Y            GCButton.DPAD_RIGHT
GCButton.Z            GCButton.L
GCButton.START        GCButton.R

GCAxis.MAIN_X         GCAxis.C_X
GCAxis.MAIN_Y         GCAxis.C_Y
GCAxis.L_ANALOG       GCAxis.R_ANALOG

Supported Adapters

| Adapter | Detection | Status | |---------|-----------|--------| | Nintendo WUP-028 (Official) | VID 057e PID 0337 | ✅ Full support | | Mayflash 4-Port (PC Mode) | VID 0079 PID 1844 | ✅ Full support | | Mayflash 4-Port (Wii U Mode) | VID 0079 PID 1800 | ✅ Full support | | Raphnet Technologies | VID 289b | ✅ Full support | | 8BitDo GBros Wireless | VID 2dc8 | ✅ Standard mapping | | Brook Super Converter | Name match | ✅ Standard mapping | | Generic USB GC Adapter | Fallback | ⚠️ Best-effort |

Browser Support

Any browser implementing the W3C Gamepad API:

  • Chrome 21+
  • Firefox 29+
  • Edge 12+
  • Safari 10.1+
  • Opera 15+

License

MIT