apphouse
Version:
Component library for React that uses observable state management and theme-able components.
114 lines (104 loc) • 2.8 kB
text/typescript
import { makeAutoObservable } from 'mobx';
import View from '../app/View';
import hotkeys from 'hotkeys-js';
export interface Shortcut {
/**
* The shortcut combo to trigger the action.
* @example
* 'ctrl+s'
* 'command+s'
* ['ctrl+s', 'command+s']
* 'ctrl+shift+s'
*/
combo: string | string[];
/**
* The action to be called when the shortcut is triggered.
* @returns
*/
action: () => void;
/**
* The description of the shortcut. Added for convenience.
* @optional
* @example
* 'Save the file to disk'
* 'Open the preview'
*/
description?: string;
/**
* The view where the shortcut should be active. It should match with your view id.
* The shortcut will be active in all views if not specified.
* @optional
*/
view?: string;
}
/**
* The Shortcuts class handles all the keyboard shortcuts in the app.
* It uses the hotkeys library to handle the shortcuts.
*/
export class Shortcuts {
currentView: View;
shiftPress: boolean;
/**
* The scope where the shortcut should be active.
* It should match with your scope id.
*/
scoped: { [key: string]: { [id: string]: () => void } };
constructor(view: View) {
this.currentView = view;
this.shiftPress = false;
this.scoped = {};
hotkeys('shift', () => {
this.setShiftPress(true);
});
makeAutoObservable(this);
}
/**
* Register a new shortcut
* @param shortcut the shortcut combo to trigger the action.
* @param callback the action to be called when the shortcut is triggered.
*/
register = (shortcut: string | string[], callback: () => void) => {
if (typeof shortcut === 'string') {
hotkeys(shortcut, callback);
} else {
shortcut.forEach((combo) => {
hotkeys(combo, callback);
});
}
};
/**
* Unregister a current shortcut
* @param shortcut the shortcut combo to be unregistered.
*/
unregister = (shortcut: string | string[]) => {
if (typeof shortcut === 'string') {
hotkeys.unbind(shortcut);
} else {
shortcut.forEach((combo) => {
hotkeys.unbind(combo);
});
}
};
/**
* Register a list of shortcuts to be used in the app.
* @param shortcuts the shortcuts to be registered.
*/
registerAppShortcuts = (shortcuts: Shortcut[]) => {
const applyShortcut = (shortcut: Shortcut) => {
this.register(shortcut.combo, () => {
if (shortcut.view && shortcut.view !== this.currentView.path) {
return;
}
shortcut.action();
});
};
shortcuts.forEach(applyShortcut);
};
/**
* Set the shift key press state.
* @param value boolean if true, the shift key is pressed
*/
private setShiftPress = (value: boolean) => {
this.shiftPress = value;
};
}