Hooks
useHotkeys
Горячие клавиши с последовательностями и модификаторами.
Глобальные горячие клавиши с поддержкой последовательностей: нажали «g», затем «d» — перешли на дашборд.
Пример
- Нажмите сочетание — сюда попадёт срабатывание
import { useHotkeys } from "@toimetdev/pathlogs-hooks";
useHotkeys([
{ keys: "g d", label: "Дашборд", handler: () => router.push("/dashboard") },
{ keys: "g m", label: "Мои задачи", handler: () => router.push("/my") },
{ keys: "d", label: "Отметить готовой", handler: markDone },
{ keys: "mod+k", label: "Поиск", allowInInput: true, handler: openPalette },
]);Запись клавиш
Аккорды разделяются пробелом, модификаторы внутри аккорда — плюсом:
"k" // просто клавиша
"g d" // последовательность: g, затем d
"mod+k" // Ctrl на Windows/Linux, ⌘ на macOS
"mod+shift+p" // несколько модификаторов
"?" // shift подставляется сам
"escape" // esc, up, down, left, right, enter, space, delete| Проп | Тип | По умолчанию | Описание |
|---|---|---|---|
mod | модификатор | — | Ctrl и ⌘ одной записью. Отдельно ctrl и cmd различать не нужно — приложению почти всегда важно «системный модификатор». |
shift | модификатор | — | Требуется, только если написан явно. «?» набирается с shift на большинстве раскладок, и требование shift: false ломало бы такую запись. |
alt | модификатор | — | Он же option на macOS. |
modмодификаторCtrl и ⌘ одной записью. Отдельно ctrl и cmd различать не нужно — приложению почти всегда важно «системный модификатор».
shiftмодификаторТребуется, только если написан явно. «?» набирается с shift на большинстве раскладок, и требование shift: false ломало бы такую запись.
altмодификаторОн же option на macOS.
Параметры
| Проп | Тип | По умолчанию | Описание |
|---|---|---|---|
keys* | string | — | Запись клавиш. |
handler* | (e: KeyboardEvent) => void | — | Что сделать. preventDefault вызывается за вас. |
label | string | — | Подпись для экрана справки. Записи без неё считаются служебными и в справку не попадают. |
group | string | — | Раздел в справке: «Навигация», «Доска». |
allowInInput | boolean | false | Сработает и когда фокус в поле ввода. Для mod+k и escape. |
enabled | boolean | true | Временно выключить запись, не убирая её из списка. |
keys*stringЗапись клавиш.
handler*(e: KeyboardEvent) => voidЧто сделать. preventDefault вызывается за вас.
labelstringПодпись для экрана справки. Записи без неё считаются служебными и в справку не попадают.
groupstringРаздел в справке: «Навигация», «Доска».
allowInInputbooleanпо умолчанию: false
Сработает и когда фокус в поле ввода. Для mod+k и escape.
enabledbooleanпо умолчанию: true
Временно выключить запись, не убирая её из списка.
Второй аргумент хука — общие настройки: enabled выключает весь набор, timeout задаёт окно ожидания второй клавиши (по умолчанию 1200 мс), target позволяет слушать не window, а конкретный элемент.
Поля ввода
Обычные клавиши в поле ввода принадлежат полю, а не приложению. Записи с allowInInput — исключение.
Справка
Тот же массив отдаётся компоненту HotkeysHelp — он показывает экран справки по «?» и сам вызывает useHotkeys:
import { HotkeysHelp } from "@toimetdev/pathlogs-core";
const hotkeys = [
{ keys: "g d", label: "Дашборд", group: "Навигация", handler: goDashboard },
];
// useHotkeys вызывать отдельно не нужно — HotkeysHelp сделает это сам
<HotkeysHelp hotkeys={hotkeys} hint="«g» — лидер: нажмите g, затем вторую клавишу." />Один список на обработку и на справку — разъехаться им негде.
Матчер отдельно
Разбор и сопоставление не знают про DOM и покрыты тестами:
import {
parseHotkey, // "g d" → [{ key: "g" }, { key: "d" }]
chordFromEvent, // KeyboardEvent → аккорд
chordMatches, // совпадают ли аккорды
createHotkeyMatcher // машина состояний для последовательностей
} from "@toimetdev/pathlogs-hooks";Матчер хранит не буфер нажатий, а индекс внутри незавершённой последовательности: буфер пришлось бы чистить по таймеру, а индекс достаточно сравнить со временем последнего нажатия. Поэтому «g», нажатая минуту назад, не превращает случайную «d» в переход.