Quick start
Goal: create a gamepad manager, react when controllers connect, and listen for named buttons and sticks (for example A, LS) instead of raw indices.
Install the package first: Installation.
Copy-paste example
import { createGamepadManager } from "@interfaces-technology/play-u1";
const manager = createGamepadManager({ deadzone: 0.12 });
manager.onConnect((pad) => {
console.log("Connected:", pad.id);
pad.onPress("A", () => console.log("A pressed"));
pad.onHold("X", { delay: 400, interval: 80 }, () => console.log("X held"));
pad.onAxisMove("LS", (e) => console.log("Left stick", e.state));
});
manager.onDisconnect((pad) => {
console.log("Disconnected:", pad.id);
});
manager.start();start() and stop()
The first subscription to onConnect, onDisconnect, onAnyPress, or onAnyInput starts the manager for you, so an explicit start() is optional in that pattern.
If you only use other flows, call manager.start() yourself. Call manager.stop() when you leave a screen or shut down the app so the animation-frame loop and browser listeners are released.
Why dead zones and layouts matter: Concepts.
React
Hooks wrap the same manager with mount-safe start / stop: React covers useGamepadManager, useGamepads, and useGamepadSnapshot.
"use client";
import { useGamepadManager } from "@interfaces-technology/play-u1/react";
export function GamepadRoot() {
const manager = useGamepadManager({ deadzone: 0.12 });
// Wire listeners in useEffect — see the React guide
return null;
}Snapshots and UI
pad.snapshot() and useGamepadSnapshot return a plain object (buttons, axes, triggers, hasVibration). onChange fires when that serialized state changes—handy for HUDs.
More: Input events · Rumble & snapshots.