keyboard.ts30 lines · main
1import type { KeyboardEvent } from 'react'
2
3type ClearableInputElement = HTMLInputElement | HTMLTextAreaElement
4
5/**
6 * Staged-Escape handler for search/filter inputs:
7 * - Escape while the input has a value → clear the value (keeps focus)
8 * - Escape while the input is empty → blur the input
9 *
10 * Stops propagation on Escape so the keystroke doesn't bubble to dialog/popover
11 * close handlers when the consumer is nested inside one.
12 *
13 * @example
14 * <Input
15 * value={query}
16 * onChange={(e) => setQuery(e.target.value)}
17 * onKeyDown={onSearchInputEscape(query, setQuery)}
18 * />
19 */
20export const onSearchInputEscape =
21 <T extends ClearableInputElement>(value: string, onClear: (next: string) => void) =>
22 (event: KeyboardEvent<T>) => {
23 if (event.key !== 'Escape') return
24 event.stopPropagation()
25 if (value.length > 0) {
26 onClear('')
27 } else {
28 event.currentTarget.blur()
29 }
30 }