# wrTypeahead

> Type-to-jump for a list: the letters typed in a row select the next row that starts with them.

Source: https://ngwr.dev/reference/utils/wr-typeahead  
Kind: Util  
Added in v16.4  
Optional

## Usage

It holds the letters typed so far. Pass the labels and the current row with each `keydown`, and move your own cursor to the index that comes back. `wr-select`, `wr-dropdown`, `wr-tree`, `wr-context-menu` and `wr-cascader` run on it.

```angular-ts
import { wrTypeahead } from 'ngwr/utils';

@Component({
  host: { '(keydown)': 'onKeydown($event)' },
})
export class Menu {
  readonly labels = input.required<readonly string[]>();
  protected readonly cursor = signal(0);
  private readonly typeahead = wrTypeahead();

  protected onKeydown(event: KeyboardEvent): void {
    const index = this.typeahead.handleKey(event, this.labels(), this.cursor());
    if (index === null) return this.onOtherKey(event);
    event.preventDefault();
    if (index >= 0) this.cursor.set(index);
  }
}
```

## Rules

| Typed | Result |
| --- | --- |
| One letter | The next row after the current one that starts with it, wrapping past the end. |
| The same letter again | The next row that starts with it, so the letter cycles. |
| More letters | The row that starts with the whole run. The current row stays while it still matches. |
| A pause of `resetMs` | The next key starts a new run. |
| Space | Joins a run that has started. As the first key it is left to you. |
| Ctrl, Meta or Alt, an IME key, a key in a text field | Left to you: `handleKey` returns `null`. |

## Disabled rows and language

A row passed as `{ label, disabled: true }` is never a match. Case is folded in `locale`, which can be a function, so it follows a language switch.

```typescript
const locale = inject(WR_LIVE_LOCALE, { optional: true });
const typeahead = wrTypeahead({ resetMs: 700, locale: () => locale?.() });

typeahead.handleKey(event, [
  { label: 'Copy' },
  { label: 'Copy link', disabled: true },
  { label: 'Cut' },
], current);
```

## Key now, search later

`type()` takes the key and `find()` searches, for a list that is not there yet when the key arrives. `wr-select` opens on a letter this way.

```typescript
if (typeahead.type(event)) {
  event.preventDefault();
  open();
  afterNextRender(() => {
    const index = typeahead.find(labels(), cursor());
    if (index >= 0) cursor.set(index);
  }, { injector });
}
```

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `wrTypeahead(options?)` | Returns a `WrTypeahead`. One per list: it holds the run. | `(options?: WrTypeaheadOptions) => WrTypeahead` | `—` |
| `options.resetMs` | The pause, in milliseconds, after which the next key starts a new run. | `number` | `500` |
| `options.locale` | The language the labels are in, for the case folding. The browser locale when omitted. | `string \| (() => string \| undefined)` | `—` |
| `handleKey(event, items, current)` | Takes a `keydown` and answers the index to move to, `-1` when the key joined the run and nothing matches, or `null` when the key is not a typeahead key. | `(event: KeyboardEvent, items: readonly (string \| WrTypeaheadItem)[], current: number) => number \| null` | `—` |
| `type(event)` | Adds a `keydown` to the run. Returns whether the key was taken. | `(event: KeyboardEvent) => boolean` | `—` |
| `find(items, current)` | The index the run points at, or `-1`. | `(items: readonly (string \| WrTypeaheadItem)[], current: number) => number` | `—` |
| `active` | Whether a run is in progress. | `boolean` | `—` |
| `reset()` | Drops the run. | `() => void` | `—` |

## See also

- [Keyboard](https://ngwr.dev/guides/keyboard) — Bind shortcuts, show them as keycaps, and see which keys each component handles.
- [wrIsPrintableKey](https://ngwr.dev/reference/utils/wr-is-printable-key) — True for a single printable character typed without Ctrl, Cmd or Alt (Shift is allowed).
- [wrIsComposing](https://ngwr.dev/reference/utils/wr-is-composing) — True while an input method (IME) is composing, so the key belongs to it and not to your handler.
- [WR_KEYS](https://ngwr.dev/reference/utils/wr-keys) — KeyboardEvent.key constants, the WrKey union of their values, and WR_KEY_LABELS, what each key is called on a keycap.
- [Select](https://ngwr.dev/reference/components/select) — Pick one or several values from a list, with search and free-text tags.
- [Tree](https://ngwr.dev/reference/components/tree) — A nested list to browse and select from, inline or as a dropdown picker.
- [Dropdown](https://ngwr.dev/reference/components/dropdown) — A menu that opens from any trigger.
