@asphalt-react/keypad
v2.16.0
Published
Keypad component for numeric and arithmetic input.
Downloads
169
Readme
Keypad
Keypad renders an on-screen grid of numeric and arithmetic keys for use cases like PIN entry, OTP entry, amount entry, and POS-style flows. It supports two layouts — numeric only (3 × 4) and numeric with arithmetic operators (4 × 4).
Keypad is headless — it renders keys and emits key activations, but does not render a display or own any value state. Consumers compose Keypad with @asphalt-react/textfield's Input, or any other display, and own the value buffer and arithmetic logic themselves.
Usage
import { useState } from "react"
import { Keypad } from "@asphalt-react/keypad"
import { Input } from "@asphalt-react/textfield"
const Example = () => {
const [value, setValue] = useState("")
const handleKeyPress = (key) => {
if (key === "delete") {
setValue((v) => v.slice(0, -1))
return
}
if (key === "clear") {
setValue("")
return
}
setValue((v) => v + key)
}
return (
<>
<Input value={value} readOnly aria-label="Keypad output" />
<Keypad onKeyPress={handleKeyPress} />
</>
)
}Layout
Keypad renders 2 variants:
- With operator keys (default): a 4 × 4 grid with
÷ × − +as the fourth column. - Without operator keys: a 3 × 4 grid. Set
operatorKeystofalse.
Key values
| Category | Emitted values |
| --------- | ----------------------------------------------- |
| Digits | "0"–"9", "000" |
| Operators | "add", "subtract", "multiply", "divide" |
| Actions | "delete", "clear" |
Digits are emitted as character literals so they can be appended to a string buffer directly. Operators and actions are emitted as semantic identifiers, decoupled from their rendered glyphs (×, ÷, −) and from physical-keyboard symbols (* / -).
"000" is a multi-character digit; if you check key.length === 1 to detect a digit, account for it.
Delete and clear
A short press or click on the delete key emits "delete". Press and hold the delete key (pointer or touch, ≥ 500ms) to emit "clear" instead, letting a single key clear the entire value. Long-press is pointer/touch only — keyboard users press delete repeatedly for repeated deletes.
Accessibility
- Navigate among keys using ← → ↑ ↓ arrow keys. Left/right move by one key; up/down move by a row.
- Only the active key is in the tab order (roving
tabindex) — tab moves focus into and out of the Keypad in one step. - Activate the focused key with enter or space.
- Digits
0–9and operators+ - * /on a physical keyboard are emitted directly, regardless of which key currently has focus, so long as a key inside the Keypad is focused. - Operator keys carry accessible labels distinct from their visible content.
iOS WKWebView
Keypad uses a native (non-React) event listener for pointer/touch activation, rather than React's onClick/onPointerDown. This avoids a WKWebView-specific bug where rapid taps get lost because React's delegated events fire too late to stop the WebView's native blur behaviour. This only matters when Keypad is bound to an external, separately-focused input; Keypad's own internal focus handling is unaffected.
Props
onKeyPress
Callback to handle key activation.
The function accepts 1 argument:
- value: a digit (
"0"-"9","000"), an operator ("add"/"subtract"/"multiply"/"divide"), or"delete"/"clear".
onKeyPress(value) {
console.log(value)
}| type | required | default | | ---- | -------- | ------- | | func | false | null |
operatorKeys
Renders the arithmetic operator column (÷ × − +) when true.
| type | required | default | | ---- | -------- | ------- | | bool | false | true |
