diff --git a/docs/.vuepress/components/UseShortcut.vue b/docs/.vuepress/components/UseShortcut.vue new file mode 100644 index 0000000..6ec16ac --- /dev/null +++ b/docs/.vuepress/components/UseShortcut.vue @@ -0,0 +1,48 @@ + + + diff --git a/docs/guide/core/useShortcut.md b/docs/guide/core/useShortcut.md new file mode 100644 index 0000000..bc4e2d2 --- /dev/null +++ b/docs/guide/core/useShortcut.md @@ -0,0 +1,72 @@ +# useShortcut + +::: tip useShortcut +Bind Keyboard Shortcuts API build on top of [keymaster](https://github.com/madrobby/keymaster) +::: + +## Usage + +```html +
+
+ Type one of the following Keys 👇: +
+
+ Shift + D +
+
+ Command + D +
+
+``` + +```js +import { useShortcut } from '@vueblocks/vue-use-core' + +setup () { + const pressedKeyCodes = ref([]) + + useShortcut({ + 'shift+d': (event, handler) => { + pressedKeyCodes.value.push(handler.shortcut) + alert("The 'Shift' and 'd' keys were pressed at the same time") + }, + '⌘+d, ctrl+d': (event, handler) => { + pressedKeyCodes.value.push(handler.shortcut) + alert("Either 'Control+d' or 'Meta+d' were pressed") + } + }) + + onUnmounted(() => pressedKeyCodes.value = []) + + return { + pressedKeyCodes + } +} +``` + +## Example + +> Type one of the following Keys👇: + + + +## Typing + +```ts +/** + * A map of keybinding strings to event handlers. + */ +interface KeyBindingMap { + [keybinding: string]: (event: KeyboardEvent) => void; +} +/** + * Bind shortcut onMounted & unbind shortcut onUnmounted in setup hooks + * or + * Unbind shortcut before bind shortcut without setup hooks + * @param {Object} keymap + * @param {Object} vm + * @return {function} toggle + */ +declare const useShortcut: (keymap: KeyBindingMap, vm: any) => void; +``` diff --git a/packages/core/useShortcut/index.ts b/packages/core/useShortcut/index.ts new file mode 100644 index 0000000..72b7774 --- /dev/null +++ b/packages/core/useShortcut/index.ts @@ -0,0 +1,77 @@ +import keymaster from 'keymaster' +import { getCurrentInstance } from 'vue-demi' + +import { tryOnMounted, tryOnUnmounted } from '../useLifecycle' + +/** + * A map of keybinding strings to event handlers. + */ +export interface KeyBindingMap { + [keybinding: string]: (event: KeyboardEvent) => void +} + +export interface KeymasterEvent { + key: string; + method: KeyHandler; + mods: number[]; + scope: string; + shortcut: string; +} + +export interface KeyHandler { + (keyboardEvent: KeyboardEvent, keymasterEvent: KeymasterEvent): void; +} + +const bindKeyHandler = (fn: Function) => { + return (...args: any) => { + fn(...args) + return false + } +} + +/** + * Given shortcut a new bind function + */ +const shortcut = { + bind: (seed: string, func: Function) => keymaster(seed, bindKeyHandler(func)), + ...keymaster +} + +/** + * Bind shortcut onMounted & unbind shortcut automatically onUnmounted in setup hooks + * or + * Unbind shortcut before bind shortcut without setup hooks + * @param {Object} keymap + * @param {Object} vm + * @return {function} toggle + */ +const useShortcut = (keymap: KeyBindingMap, vm: any) => { + let sync = true + + if (!vm) { + vm = getCurrentInstance() + } else { + sync = false + unbindKeys() + } + + function bindKeys () { + Object.keys(keymap).forEach(key => { + shortcut.bind(key, keymap[key]) + }) + } + + function unbindKeys () { + Object.keys(keymap).forEach(key => { + shortcut.unbind(key) + }) + } + + tryOnMounted(() => bindKeys(), sync) + + tryOnUnmounted(unbindKeys) + + return shortcut +} + +export { useShortcut }