# @ferret/input: API

Actions over the console's buttons and sticks, keyboard and mouse, touch and gamepads; games bind actions, not devices.

10 exports. Generated from the source (`packages/input/src`), so it matches the code.

## Classes

### InputService

*class* · `packages/input/src/input.ts:46`

```ts
class InputService implements Service
```

Actions over every input device. Games bind actions, not devices. The active kind follows what the player uses last
(a gamepad plugged in, a keyboard used on a tablet) and prompts show the matching button.

- `readonly name: "input"`
- `kind: InputKind`
- `enabled: boolean` — false = all actions read as released/zero (a menu is open, a cutscene plays). Devices are still tracked.
- `readonly opts: InputOptions`
- `dominantHand: XrHand` — which hand `xrButton` without `hand` means
- `canvas?: HTMLElement` — the page's canvas, once attached; Pointer Lock is requested on it
- `constructor(opts: InputOptions)`
- `init(world: World)`
- `down(action: string)`
- `pressed(action: string)`
- `released(action: string)`
- `axis(action: string): { x: number; y: number }`
- `lookDelta()` — Look delta accumulated during the last step, in radians (x = yaw, y = pitch). Consumed by the step.
- `prompt(action: string): string` — The label of the binding in the active kind ("A", "E", "Tap"...), for UI prompts.
- `setKind(kind: InputKind)`
- `setKey(code: string, down: boolean)`
- `addLook(dx: number, dy: number)`
- `setPad(buttons: Iterable<number>, axes: number[])`
- `setTouchStick(which: 'left' | 'right', x: number, y: number)`
- `setTouchButton(name: string, down: boolean)`
- `setXrActive(on: boolean)` — The `xr` kind while in a session; the previous kind comes back on leaving.
- `setXrButton(hand: XrHand, b: XrButton | 'pinch', down: boolean)`
- `setXrStick(hand: XrHand, x: number, y: number)`
- `setXrPose(who: 'head' | XrHand, p: XrPose)` — Poses sampled for the rendered frame (`renderPose`); the fixed step copies them for gameplay (`pose`).
- `pose(who: 'head' | XrHand): XrPose | undefined`
- `renderPose(who: 'head' | XrHand): XrPose | undefined`
- `inject(action: string, v: { x?: number; y?: number; down?: boolean } | null)` — Tests and scripted input: force an action regardless of devices.
- `fixedUpdate()` — Called before the components' fixed update, at the fixed rate.
- `sample()` — Compute the actions from the raw state. Called each fixed step; also callable directly in tests.
- `attach(canvas: HTMLElement, opts: { pointerLock?: boolean } = {})` — Listen to the page. On OS Beroun the cursor, A and B arrive as keys; Pointer Lock is only used in desktop browsers.
- `update()` — Poll the Gamepad API; call once per frame (the Ferret loop does it through `update`).
- `dispose()`

### TouchControls

*class* · `packages/input/src/touch.ts:10`

```ts
class TouchControls
```

On-screen controls for phones and tablets, generated from the game's touch bindings: a virtual stick on the left,
look by dragging on the right half, and a round button per `touchButton` binding. Sized to the screen.

- `readonly root: HTMLDivElement`
- `constructor(private input: InputService, parent: HTMLElement = document.body)`
- `relayout()`
- `dispose()`

## Interfaces

### InputOptions

*interface* · `packages/input/src/input.ts:29`

```ts
interface InputOptions
```

- `actions: Record<string, ActionDef>`
- `bindings: BindingMap`
- `defaultKind?: InputKind` — Kind used until the player touches something. OS Beroun: 'console', phones: 'touch', else 'keyboard'.

### XrPose

*interface* · `packages/input/src/input.ts:9`

```ts
interface XrPose
```

a hand or the head in the room: metres, quaternion, m/s, rad/s

- `position: [number, number, number]`
- `rotation: [number, number, number, number]`
- `linear: [number, number, number]`
- `angular: [number, number, number]`
- `tracked: boolean`

## Types

### ActionDef

*type* · `packages/input/src/input.ts:11`

```ts
type ActionDef = { kind: 'button' } | { kind: 'axis2' }
```

### Binding

*type* · `packages/input/src/input.ts:14`

```ts
type Binding = | { key: string; label?: string } // KeyboardEvent.code (or .key for console) | { mouse: 0 | 1 | 2; label?: string } // a mouse button: 0 left, 1 middle, 2 right | { axisKeys: [left: string, right: string, down: string, up: string]; label?: string } // x = right - left, y = up - down | { pad: number; label?: string } // Gamepad button index | { padAxes: [x: number, y: number]; deadzone?: number } | { mouseLook: true; sensitivity?: number } // pointer-locked (or dragged) mouse -> axis2 in radians | { touchStick: 'left' | 'right' } | { touchButton: string; label?: string } | { xrButton: XrButton; hand?: XrHand; label?: string } // a controller button; no hand = the dominant hand | { xrStick: XrHand; deadzone?: number } // a controller thumbstick -> axis2 | { xrPinch: XrHand; label?: string }
```

One way to produce an action. Which button does what is each game's call: Ferret ships no mapping.

### BindingMap

*type* · `packages/input/src/input.ts:27`

```ts
type BindingMap = Partial<Record<InputKind, Record<string, Binding[]>>>
```

### InputKind

*type* · `packages/input/src/input.ts:4`

```ts
type InputKind = 'console' | 'keyboard' | 'gamepad' | 'touch' | 'xr'
```

Where the player's commands come from. `console` = OS Beroun's cursor, A and B (they reach the page as arrow keys, Enter and Escape).

### XrButton

*type* · `packages/input/src/input.ts:6`

```ts
type XrButton = 'trigger' | 'squeeze' | 'thumbstick' | 'a' | 'b' | 'x' | 'y' | 'menu'
```

### XrHand

*type* · `packages/input/src/input.ts:7`

```ts
type XrHand = 'left' | 'right'
```

