Skip to content

Commit

Permalink
feat: add useShortcut utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoluoboding committed Jan 10, 2021
1 parent cc26039 commit 65bf28d
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
48 changes: 48 additions & 0 deletions docs/.vuepress/components/UseShortcut.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<example-block>
<div slot="component">
<div class="my-4">
<kbd>Shift</kbd> + <kbd>D</kbd>
</div>
<div>
<kbd>Command</kbd> + <kbd>D</kbd>
</div>
</div>
<span slot="code">Pressed KeyCodes: {{ pressedKeyCodes }}</span>
</example-block>
</template>

<script>
import { onUnmounted, ref } from 'vue-demi'
// import { useShortcut } from '@vueblocks/vue-use-core'
// Test local bundle
import { useShortcut } from '../../../packages/core/lib/index.cjs'
import ExampleBlock from './ExampleBlock.vue'
export default {
name: 'UseShortcut',
components: { ExampleBlock },
setup () {
const pressedKeyCodes = ref([])
const shortcut = 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")
}
})
console.log(shortcut)
onUnmounted(() => pressedKeyCodes.value = [])
return {
pressedKeyCodes
}
}
}
</script>
72 changes: 72 additions & 0 deletions docs/guide/core/useShortcut.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# useShortcut

::: tip useShortcut
Bind Keyboard Shortcuts API build on top of [keymaster](https://github.com/madrobby/keymaster)
:::

## Usage

```html
<div class="wrapper">
<div>
Type one of the following Keys 👇:
</div>
<div class="my-4">
<kbd>Shift</kbd> + <kbd>D</kbd>
</div>
<div>
<kbd>Command</kbd> + <kbd>D</kbd>
</div>
</div>
```

```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👇:
<UseShortcut />

## 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;
```
77 changes: 77 additions & 0 deletions packages/core/useShortcut/index.ts
Original file line number Diff line number Diff line change
@@ -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 }

0 comments on commit 65bf28d

Please sign in to comment.