@interfaces-technology/play-u1
v0.1.10
Published
Browser Gamepad API wrapper — named buttons, press/hold/sequence events, deadzone correction, rumble.
Maintainers
Readme
play-u1 (@interfaces-technology/play-u1)
Browser Gamepad API wrapper with named buttons, press/hold/sequence events, deadzone correction, and rumble support.
Install
Published to the public npm registry under the @interfaces-technology scope. No registry-specific .npmrc or GitHub token is required.
npm install @interfaces-technology/play-u1To work from a local git clone instead of the registry, use a file: dependency and run npm run build in packages/play-u1 so dist/ exists (see the repository SETUP.md).
Quick Start
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.start()Exports
| Specifier | What you get |
|-----------|-------------|
| @interfaces-technology/play-u1 | Core API — createGamepadManager, GamepadManager, GamepadDevice, readPads, layouts, axis math, types |
| @interfaces-technology/play-u1/react | React hooks — useGamepadManager, useGamepads, useGamepadSnapshot |
| @interfaces-technology/play-u1/hid | WebHID helpers and readPads snapshot types (PadSnap, ButtonSnap) |
Core (".")
import {
createGamepadManager,
GamepadManager,
GamepadDevice,
readPads,
xboxLayout,
genericLayout,
detectLayout,
applyAxisDeadzone,
buildButtonIndexMap,
} from '@interfaces-technology/play-u1'React ("./react")
import {
useGamepadManager,
useGamepads,
useGamepadSnapshot,
} from '@interfaces-technology/play-u1/react'React 18+ is an optional peer dependency — only needed if you use the
/reactexport.
WebHID and snapshots ("./hid")
WebHID helpers require Chromium-style browsers with WebHID enabled. readPads works in any environment that exposes the standard Gamepad API. See the docs site WebHID guide for device pairing. Typical imports:
import { supportsWebHid, requestGamepadHidDevice, readPads, type PadSnap } from '@interfaces-technology/play-u1/hid'API Overview
createGamepadManager(options?)
Returns a GamepadManager instance. Options:
deadzone—number(radial only) or{ radial?, axial?, rescale? }layouts—Record<string, LayoutProfile>for custom controller mappings (substring-matched againstgamepad.id)
GamepadManager
| Method | Description |
|--------|-------------|
| start() | Begin polling connected gamepads via requestAnimationFrame |
| stop() | Stop polling and remove event listeners |
| getDevices() | All currently connected GamepadDevice instances |
| getDevice(index) | Single device by gamepad index |
| onConnect(handler) | Fires when a gamepad connects; returns disposer |
| onDisconnect(handler) | Fires when a gamepad disconnects; returns disposer |
| onAnyPress(handler) | Any named button on any device; returns disposer |
| onAnyInput(handler) | Any input change on any device; returns disposer |
| setLayoutForId(pattern, layout) | Override layout for matching controllers |
| setDeadzone(deadzone) | Update deadzone for all connected devices |
GamepadDevice
| Method | Description |
|--------|-------------|
| onPress(button, handler) | Single press |
| onRelease(button, handler) | Release |
| onHold(button, opts?, handler) | Repeat while held |
| onLongPress(button, opts?, handler) | Fire once after held N ms |
| onDoubleTap(button, opts?, handler) | Two taps within window |
| onCombo(buttons, handler) | All buttons pressed simultaneously |
| onSequence(buttons, opts?, handler) | Ordered taps within time window |
| onTrigger(trigger, handler) | Analog trigger value each frame |
| onTriggerPress(trigger, opts?, handler) | Trigger crosses threshold up |
| onTriggerRelease(trigger, opts?, handler) | Trigger crosses threshold down |
| onAxisMove(axis, handler) | Stick movement |
| onAxisFlick(axis, direction, opts?, handler) | Stick flick gesture |
| onChange(handler) | Snapshot changed from previous frame |
| onAnyPress(handler) | Any button on this device |
| vibrate(opts) | Single rumble pulse |
| vibratePattern(opts) | Alternating on/off pattern |
| vibrateDual(opts) | Independent weak/strong motors |
| stopVibration() | Cancel active vibration |
| snapshot() | Current state as a plain object |
| isPressed(button) | Poll button state |
| axis(name) | Poll stick state |
All on* methods return a disposer function — call it to unsubscribe.
React Hooks
| Hook | Description |
|------|-------------|
| useGamepadManager(options?) | Create and manage a GamepadManager tied to component lifecycle |
| useGamepads(options?) | { manager, devices } — reactive list of connected gamepads |
| useGamepadSnapshot(pad) | Reactive snapshot of a single GamepadDevice |
Documentation
Guides and API reference: https://play-u1.vercel.app. For AI assistants, the site exposes a remote MCP endpoint at https://play-u1.vercel.app/api/mcp; see https://play-u1.vercel.app/docs/mcp for client setup.
License
MIT
