Skip to content

Commit 280ee8d

Browse files
committedOct 24, 2024
feat: Added use-keyboard.
1 parent 02f5c2b commit 280ee8d

File tree

5 files changed

+160
-2
lines changed

5 files changed

+160
-2
lines changed
 

‎README.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ Use it:
3333
import { useHotkeys } from 'bagon-hooks';
3434
```
3535

36-
We want to achieve as 1:1 as possible with Mantine's original hooks. So you can always refer to their [original docs](https://v3.mantine.dev/hooks/use-hotkeys/).
36+
We want to achieve as 1:1 as possible with Mantine's original hooks. So you can always refer to their [original docs](https://v3.mantine.dev/hooks/use-hotkeys/). There are a few improvements and renaming because SolidJS has its own conventions. But just take note:
37+
38+
1. We removed Solid's convention of `use` vs `create` as it's too confusing for familiarity with Mantine. So every hook in Bagon is prefixed with `use`.
39+
2. The only renaming we did was `state` -> `signal`.
40+
3. Refer to [Mantine](https://mantine.dev/hooks/use-click-outside/)'s original docs for deeper examples and usecases.
41+
4. Refer to [Bagon Hooks](https://bagon-hooks.pages.dev/)'s docs for actual SolidJS examples.
3742

3843
## Features
3944

@@ -54,7 +59,7 @@ Based on the [@mantine/hooks](https://github.com/mantinedev/mantine/tree/master/
5459
- [ ] use-color-scheme
5560
- [x] use-counter
5661
- [ ] use-debounced-callback
57-
- [ ] use-debounced-state
62+
- [ ] ~~use-debounced-state~~ use-debounced-signal
5863
- [ ] use-debounced-value
5964
- [ ] use-did-update
6065
- [ ] use-disclosure
@@ -119,6 +124,10 @@ Based on the [@mantine/hooks](https://github.com/mantinedev/mantine/tree/master/
119124
- [ ] use-window-scroll
120125
- [ ] utils
121126

127+
### New in Bagon Hooks
128+
129+
- [x] use-keyboard
130+
122131
### Others
123132

124133
- [x] Docs Website (Powered by mdx + tailwind prose)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
```tsx
2+
function KeyboardExample() {
3+
const [store, setStore] = createStore({ a: false, b: false, c: false, d: false });
4+
5+
useKeyboard({
6+
onKeyDown(event) {
7+
// Refactor this into if statements.
8+
if (event.key === 'a') {
9+
setStore('a', true);
10+
} else if (event.key === 'b') {
11+
setStore('b', true);
12+
} else if (event.key === 'c') {
13+
setStore('c', true);
14+
} else if (event.key === 'd') {
15+
setStore('d', true);
16+
}
17+
},
18+
onKeyUp(event) {
19+
// Refactor this into if statements.
20+
if (event.key === 'a') {
21+
setStore('a', false);
22+
} else if (event.key === 'b') {
23+
setStore('b', false);
24+
} else if (event.key === 'c') {
25+
setStore('c', false);
26+
} else if (event.key === 'd') {
27+
setStore('d', false);
28+
}
29+
},
30+
});
31+
32+
return (
33+
<div>
34+
<Kbd activated={store.a}>a</Kbd>
35+
<Kbd activated={store.b}>b</Kbd>
36+
<Kbd activated={store.c}>c</Kbd>
37+
<Kbd activated={store.d}>d</Kbd>
38+
</div>
39+
);
40+
}
41+
42+
function Kbd(props: FlowProps<{ activated: boolean }>) {
43+
return (
44+
<div style={{ display: 'relative' }}>
45+
<div style={{ display: 'absolute', inset: 0, background: "#e5e5e5" }}></div>
46+
<div
47+
style={{
48+
background: '#fafafa',
49+
padding: '0.5rem',
50+
display: 'relative',
51+
transition-property: 'transform';
52+
transition-timing-function: 'cubic-bezier(0.4, 0, 0.2, 1)';
53+
transition-duration: '150ms';
54+
transform: props.activated ? 'translateY(0px)' : 'translateY(-5px)',
55+
}}
56+
>
57+
{props.children}
58+
</div>
59+
</div>
60+
);
61+
}
62+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { useKeyboard } from 'src';
2+
import { ExampleBase } from '../example-base';
3+
import Code from './use-keyboard.code.mdx';
4+
5+
import { Kbd } from 'dev/components/kbd';
6+
import { createStore } from 'solid-js/store';
7+
import { useMDXComponents } from 'solid-jsx';
8+
9+
export function UseKeyboardExample() {
10+
const [store, setStore] = createStore({ a: false, b: false, c: false, d: false });
11+
12+
useKeyboard({
13+
onKeyDown(event) {
14+
// Refactor this into if statements.
15+
if (event.key === 'a') {
16+
setStore('a', true);
17+
} else if (event.key === 'b') {
18+
setStore('b', true);
19+
} else if (event.key === 'c') {
20+
setStore('c', true);
21+
} else if (event.key === 'd') {
22+
setStore('d', true);
23+
}
24+
},
25+
onKeyUp(event) {
26+
// Refactor this into if statements.
27+
if (event.key === 'a') {
28+
setStore('a', false);
29+
} else if (event.key === 'b') {
30+
setStore('b', false);
31+
} else if (event.key === 'c') {
32+
setStore('c', false);
33+
} else if (event.key === 'd') {
34+
setStore('d', false);
35+
}
36+
},
37+
});
38+
39+
// @ts-ignore
40+
const components: any = useMDXComponents();
41+
42+
return (
43+
<ExampleBase
44+
title="useKeyboard"
45+
description="Use this for more general keyboard events, as opposed to useHotkeys."
46+
code={<Code components={components} />}
47+
>
48+
<div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center">
49+
<Kbd activated={store.a}>a</Kbd>
50+
<Kbd activated={store.b}>b</Kbd>
51+
<Kbd activated={store.c}>c</Kbd>
52+
<Kbd activated={store.d}>d</Kbd>
53+
</div>
54+
</ExampleBase>
55+
);
56+
}

‎src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ export * from './use-resize-observer/use-resize-observer';
2020
export * from './use-toggle/use-toggle';
2121

2222
export * from './utils/random-id';
23+
24+
export * from './use-keyboard/use-keyboard';

‎src/use-keyboard/use-keyboard.ts

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { onCleanup, onMount } from 'solid-js';
2+
3+
/**
4+
* Use this for more general keyboard events, as opposed to `useHotkeys`.
5+
*/
6+
export function useKeyboard(props: {
7+
isDisabled?: boolean;
8+
onKeyDown?: (event: KeyboardEvent) => void;
9+
onKeyUp?: (event: KeyboardEvent) => void;
10+
}) {
11+
onMount(() => {
12+
const onKeyDownListener = (event: KeyboardEvent) => {
13+
if (props.isDisabled) return;
14+
props.onKeyDown?.(event);
15+
};
16+
17+
const onKeyUpListener = (event: KeyboardEvent) => {
18+
if (props.isDisabled) return;
19+
props.onKeyUp?.(event);
20+
};
21+
22+
window.addEventListener('keydown', onKeyDownListener);
23+
window.addEventListener('keyup', onKeyUpListener);
24+
onCleanup(() => {
25+
window.removeEventListener('keydown', onKeyDownListener);
26+
window.removeEventListener('keyup', onKeyUpListener);
27+
});
28+
});
29+
}

0 commit comments

Comments
 (0)
Please sign in to comment.