Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(useMagicKeys): new function #419

Merged
merged 4 commits into from Apr 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -7,7 +7,7 @@ Collection of essential Vue Composition Utilities
<a href="https://www.npmjs.com/package/@vueuse/core" target="__blank"><img src="https://img.shields.io/npm/v/@vueuse/core?color=a1b858&label=" alt="NPM version"></a>
<a href="https://www.npmjs.com/package/@vueuse/core" target="__blank"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@vueuse/core?color=50a36f&label="></a>
<a href="https://vueuse.org" target="__blank"><img src="https://img.shields.io/static/v1?label=&message=docs%20%26%20demos&color=1e8a7a" alt="Docs & Demos"></a>
<img alt="Function Count" src="https://img.shields.io/badge/-110%20functions-13708a">
<img alt="Function Count" src="https://img.shields.io/badge/-111%20functions-13708a">
<br>
<a href="https://github.com/vueuse/vueuse" target="__blank"><img alt="GitHub stars" src="https://img.shields.io/github/stars/vueuse/vueuse?style=social"></a>
</p>
Expand Down
7 changes: 7 additions & 0 deletions indexes.json
Expand Up @@ -515,6 +515,13 @@
"category": "State",
"description": "reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)"
},
{
"name": "useMagicKeys",
"package": "core",
"docs": "https://vueuse.org/core/useMagicKeys/",
"category": "Sensors",
"description": "reactive keys pressed state"
},
{
"name": "useManualRefHistory",
"package": "core",
Expand Down
4 changes: 4 additions & 0 deletions packages/.vitepress/config.js
Expand Up @@ -97,6 +97,10 @@ const config = {
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['meta', { name: 'twitter:creator', content: '@antfu7' }],
['meta', { name: 'twitter:image', content: 'https://vueuse.org/og.png' }],

['link', { rel: 'dns-prefetch', href: 'https://fonts.gstatic.com' }],
['link', { rel: 'preconnect', crossorigin: 'anonymous', href: 'https://fonts.gstatic.com' }],
['link', { href: 'https://fonts.googleapis.com/css2?family=Fira+Code&display=swap', rel: 'stylesheet' }],
],
}

Expand Down
60 changes: 36 additions & 24 deletions packages/.vitepress/theme/styles/code.css
Expand Up @@ -3,52 +3,60 @@
@import 'prism-theme-vars/marker.css';

:root {
--prism-font-family: 'Input Mono', monospace;
--prism-font-family: var(--font-family-mono);
--prism-font-size: 0.85rem;
--prism-marker-opacity: 0;
}

html:not(.dark) {
--prism-foreground: #393a34;
--prism-background: #f0f0f050;
--prism-comment: #b8c4b8;
--prism-string: #c67b5d;
--prism-literal: #3a9c9b;
--prism-keyword: #248459;
--prism-function: #849145;
--prism-background: #fafafa;
--prism-inline-background: #f5f5f5;
--prism-comment: #a0ada0;
--prism-string: #b56959;
--prism-literal: #2f8a89;
--prism-number: #296aa3;
--prism-keyword: #1c6b48;
--prism-function: #6c7834;
--prism-boolean: #1c6b48;
--prism-constant: #a65e2b;
--prism-deleted: #a14f55;
--prism-class: #2b91af;
--prism-builtin: #a52727;
--prism-property: #ad502b;
--prism-namespace: #c96880;
--prism-class: #2993a3;
--prism-builtin: #ab5959;
--prism-property: #b58451;
--prism-namespace: #b05a78;
--prism-punctuation: #8e8f8b;
--prism-decorator: #bd8f8f;
--prism-regex: #ab5e3f;
--prism-json-property: #698c96;
--prism-inline-background: rgba(125,125,125,0.05);
--prism-line-highlight-background: #f2f2f2;
}

html.dark {
--prism-scheme: dark;
--prism-foreground: #d4cfbf;
--prism-background: #33333330;
--prism-inline-background: rgba(125,125,125,0.1);
--prism-background: #181818;
--prism-comment: #758575;
--prism-string: #ce9178;
--prism-literal: #4fb09d;
--prism-string: #d48372;
--prism-literal: #429988;
--prism-keyword: #4d9375;
--prism-function: #c2c275;
--prism-deleted: #a14f55;
--prism-class: #5ebaa8;
--prism-builtin: #cb7676;
--prism-boolean: #1c6b48;
--prism-number: #6394bf;
--prism-variable: #c2b36e;
--prism-function: #a1b567;
--prism-deleted: #bc6066;
--prism-class: #54b1bf;
--prism-builtin: #e0a569;
--prism-property: #dd8e6e;
--prism-namespace: #c96880;
--prism-punctuation: #d4d4d4;
--prism-namespace: #db889a;
--prism-punctuation: #858585;
--prism-decorator: #bd8f8f;
--prism-regex: #ab5e3f;
--prism-json-property: #6b8b9e;
--prism-line-number: #888888;
--prism-line-number-gutter: #eeeeee;
--prism-line-highlight-background: #202020;
--prism-line-highlight-background: #444444;
--prism-selection-background: #444444;
--prism-inline-background: theme('colors.dark.300');
}

/* Overrides */
Expand All @@ -72,6 +80,10 @@ div[class*='language-'] pre {
z-index: 1;
}

div[class*='language-'] code {
font-size: var(--prism-font-size);
font-family: var(--prism-font-family);
}

/* Line highlighting */

Expand Down
3 changes: 0 additions & 3 deletions packages/.vitepress/theme/styles/utils.css
@@ -1,6 +1,3 @@
.text-primary {
color: var(--c-brand);
}
.text-orange {
color: #db8742;
}
1 change: 1 addition & 0 deletions packages/core/index.ts
Expand Up @@ -28,6 +28,7 @@ export * from './useGeolocation'
export * from './useIdle'
export * from './useIntersectionObserver'
export * from './useLocalStorage'
export * from './useMagicKeys'
export * from './useManualRefHistory'
export * from './useMediaControls'
export * from './useMediaQuery'
Expand Down
16 changes: 16 additions & 0 deletions packages/core/useMagicKeys/Key.vue
@@ -0,0 +1,16 @@
<script setup lang="ts">
import { defineProps } from 'vue'

defineProps<{
value: boolean
}>()
</script>

<template>
<div
class="font-mono px-4 py-2 rounded "
:class="value ? 'opacity-100 text-primary bg-primary bg-opacity-10' : 'opacity-50 bg-gray-400 bg-opacity-5'"
>
<slot />
</div>
</template>
61 changes: 61 additions & 0 deletions packages/core/useMagicKeys/demo.vue
@@ -0,0 +1,61 @@
<script setup lang="ts">
import Key from './Key.vue'
import { useMagicKeys } from '.'

const { shift, v, u, e, s, v_u_e, u_s_e } = useMagicKeys()
</script>

<template>
<div class="flex">
<img
src="/vue.svg"
class="h-20 m-auto transform transistion duration-500"
:class="{'opacity-0': !v_u_e, 'rotate-180': shift }"
/>

<div>
<note class="text-center mt-0 mb-5">
Press the following keys to test out
</note>
<div class="flex gap-3 justify-center">
<Key :value="v">
V
</Key>
<Key :value="u">
u
</Key>
<Key :value="e">
e
</Key>
<div class="mx-1"></div>
<Key :value="u">
U
</Key>
<Key :value="s">
s
</Key>
<Key :value="e">
e
</Key>
</div>

<div class="flex gap-3 justify-center mt-3">
<Key :value="shift">
Shift
</Key>
<Key :value="v_u_e">
Vue
</Key>
<Key :value="u_s_e">
Use
</Key>
</div>
</div>

<img
src="/favicon.svg"
class="h-20 m-auto transform transistion duration-500"
:class="{'opacity-0': !u_s_e, 'rotate-180': shift }"
/>
</div>
</template>
120 changes: 120 additions & 0 deletions packages/core/useMagicKeys/index.md
@@ -0,0 +1,120 @@
---
category: Sensors
---

# useMagicKeys

Reactive keys pressed state, with magical keys combination support.

> This function uses [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) which is not supported by IE 11 or below.

## Usage

```js
import { useMagicKeys } from '@vueuse/core'

const { shift, space, a /* keys you want to monitor */ } = useMagicKeys()

watch(space, (v) => {
if (v)
console.log('space has been pressed')
})

watchEffect(() => {
if (shift.value && a.value)
console.log('Shift + A have been pressed')
})
```

### Combinations

You can magically use combinations (shortcuts/hotkeys) by connecting keys with `+` or `_`

```ts
import { useMagicKeys } from '@vueuse/core'

const keys = useMagicKeys()
const shiftCtrlA = keys['Shift+Ctrl+A']

watch(shiftCtrlA, (v) => {
if (v)
console.log('Shift + Ctrl + A have been pressed')
})
```

```ts
import { useMagicKeys } from '@vueuse/core'

const { Ctrl_A_B, space, ctrl_s, /* ... */ } = useMagicKeys()

watch(Ctrl_A_B, (v) => {
if (v)
console.log('Control+A+B have been pressed')
})
```

You can also use `whenever` function to make it shorter

```ts
import { useMagicKeys, whenever } from '@vueuse/core'

const keys = useMagicKeys()

whenever(keys.shift_space, () => {
console.log('Shift+Space have been pressed')
})
```

### Reactive Mode

By default, the values of `useMagicKeys()` are `Ref<boolean>`. If you want to use the object in template, you can set it to reactive mode.

```ts
const keys = useMagicKeys({ reactive: true })
```

```html
<template>
<div v-if="keys.shift">
You are holding the Shift key!
<div>
</template>
```

<!--FOOTER_STARTS-->
## Type Declarations

```typescript
export interface UseMagicKeysOptions<Reactive extends Boolean> {
/**
* Returns a reactive object instead of an object of refs
*
* @default false
*/
reactive?: Reactive
/**
* Target for listening events
*
* @default window
*/
target?: MaybeRef<EventTarget>
}
/**
* Reactive keys pressed state, with magical keys combination support.
*
* @link https://vueuse.org/useMagicKeys
*/
export declare function useMagicKeys(
options?: UseMagicKeysOptions<false>
): Readonly<Record<string, ComputedRef<boolean>>>
export declare function useMagicKeys(
options: UseMagicKeysOptions<true>
): Readonly<Record<string, boolean>>
```

## Source

[Source](https://github.com/vueuse/vueuse/blob/main/packages/core/useMagicKeys/index.ts) • [Demo](https://github.com/vueuse/vueuse/blob/main/packages/core/useMagicKeys/demo.vue) • [Docs](https://github.com/vueuse/vueuse/blob/main/packages/core/useMagicKeys/index.md)


<!--FOOTER_ENDS-->