made return value not nullable, fixed sequence of keys in events, removed AI text from readme

This commit is contained in:
Ben
2025-08-17 17:07:50 +02:00
parent 093a812b01
commit ccdc0eb828
6 changed files with 40 additions and 30 deletions

View File

@@ -1,7 +1,7 @@
# hyperf-keybinds
Quickly handle keyboard shortcuts and sequences in your app.
Handle keybind sequences in your app.
You can have branches of sequences, the only restriction being that one sequence cannot be a strict subset of another.
## Install
```bash
@@ -11,23 +11,30 @@ npm install hyperf-keybinds
## Quick Start
```ts
import { createKeyHandler, KeybindEventTypes, ModifierKey } from 'hyperf-keybinds';
import { createKeyHandler, ModifierKey, KeybindEvent} from 'hyperf-keybinds';
// Define a command
// Define commands
const commands = [
{ command: [{ key: 'KeyS', modifiers: [ModifierKey.Control] }], callback: () => console.log('Ctrl+S!') },
{ command: [{ key: 'KeyA', modifiers: []}, { key: 'KeyS', modifiers: []}], callback: () => console.log('a - s!')}
];
// Create handler and emitter
const { handler, emitter } = createKeyHandler(commands);
// Create handler
const {handler, emitter, success} = createKeyHandler(commands, 5000);
// Attach to window
window.addEventListener('keydown', handler);
// Success is false if you provided invalid sequences.
if (success)
{
window.addEventListener('keydown', handler);
// Listen to events
emitter.on((event : KeybindEvent) => console.log(event.type, event));
}
// Listen to events
emitter.on(e => console.log(e.type));
```
Now Ctrl+S triggers your callback and emits events.
Pressing a then s triggers a separate callback.
Timeout (default 5000) can be observed by just pressing key A.
Key codes can be looked up here: https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values

View File

@@ -1,6 +1,6 @@
{
"name": "hyperf-keybinds",
"version": "0.1.1",
"version": "0.1.2",
"description": "",
"main": "dist/index.js",

View File

@@ -2,10 +2,14 @@ import { KeybindEmitter } from "./keybindEmitter";
import { KeyTree } from "./keyTree";
import { KeybindEventTypes, ModifierKey, type CommandMap, type KeyCommand, type KeyHandlerReturn, type Modifiers } from "./types";
export function createKeyHandler(commandMaps : CommandMap[], timeout : number = 5000): KeyHandlerReturn | null {
export function createKeyHandler(commandMaps : CommandMap[], timeout : number = 5000): KeyHandlerReturn {
const emitter = new KeybindEmitter();
const tree = KeyTree.buildTree(commandMaps);
if (tree === null) return null;
if (tree === null) return {
handler: () => {},
emitter: emitter,
success: false
};
const sequenceProgress : KeyCommand[] = [];
var currentTreeNode : KeyTree | null = null;
@@ -20,7 +24,7 @@ export function createKeyHandler(commandMaps : CommandMap[], timeout : number =
const tryResetFields = () => {
currentTreeNode = null;
sequenceProgress.length = 0;
sequenceProgress.splice(0);
tryResetTimeout();
};
@@ -68,7 +72,7 @@ export function createKeyHandler(commandMaps : CommandMap[], timeout : number =
}
}
};
return {handler, emitter};
return {handler, emitter, success: true};
}
function eventToKeyCommand(event: KeyboardEvent): KeyCommand{

View File

@@ -1 +1,2 @@
export { createKeyHandler } from './createKeyHandler';
export * from './types';

View File

@@ -9,21 +9,20 @@ describe("createKeyHandler", () => {
const command = makeCommand("KeyA");
const callback = vi.fn();
const keyHandlerReturn = createKeyHandler([
const {handler, emitter, success} = createKeyHandler([
{
command: [command],
callback: callback
}
]);
expect(keyHandlerReturn).not.toBe(null);
expect(success).toBe(true);
const handler = keyHandlerReturn?.handler;
const emitter = keyHandlerReturn?.emitter;
const listener = vi.fn();
emitter?.on(listener);
emitter.on(listener);
const event = { code: command.key, shiftKey: false, ctrlKey: false, altKey: false, metaKey: false } as KeyboardEvent;
handler?.(event);
handler(event);
expect(listener).toHaveBeenCalledTimes(2);
@@ -56,12 +55,11 @@ describe("createKeyHandler", () => {
const command2 = makeCommand("KeyB");
const callback = vi.fn();
const keyHandlerReturn = createKeyHandler([
const {handler, emitter, success} = createKeyHandler([
{ command: [command1, command2], callback }
], delay);
const handler = keyHandlerReturn?.handler;
const emitter = keyHandlerReturn?.emitter;
expect(success).toBe(true);
const listener = vi.fn();
emitter?.on(listener);
@@ -93,12 +91,12 @@ describe("createKeyHandler", () => {
const command = makeCommand("KeyA");
const callback = vi.fn();
const keyHandlerReturn = createKeyHandler([
const {handler, emitter, success} = createKeyHandler([
{ command: [command], callback }
]);
const handler = keyHandlerReturn?.handler;
const emitter = keyHandlerReturn?.emitter;
expect(success).toBe(true);
const listener = vi.fn();
emitter?.on(listener);
@@ -124,12 +122,11 @@ describe("createKeyHandler", () => {
const command1 = makeCommand("KeyA");
const command2 = makeCommand("KeyB");
const callback = vi.fn();
const keyHandlerReturn = createKeyHandler([
const {handler, emitter, success} = createKeyHandler([
{ command: [command1, command2], callback }
]);
const handler = keyHandlerReturn?.handler;
const emitter = keyHandlerReturn?.emitter;
expect(success).toBe(true);
const listener = vi.fn();
emitter?.on(listener);

View File

@@ -38,4 +38,5 @@ export type KeyEventHandler = (event: KeyboardEvent) => void;
export interface KeyHandlerReturn {
handler: KeyEventHandler;
emitter: KeybindEmitter;
success: boolean;
}