Skip to content

Commit

Permalink
feat: 🎸 add useKey hook
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Mar 28, 2019
1 parent 7d7c36e commit 299fd86
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/__stories__/useKey.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { storiesOf } from "@storybook/react";
import * as React from "react";
import {useKey} from "..";
import ShowDocs from "../util/ShowDocs";
import {CenterStory} from "./util/CenterStory";

const Demo = () => {
const [count, setCount] = React.useState(0);

const increment = () => setCount(count => ++count);
const decrement = () => setCount(count => --count);
const reset = () => setCount(count => 0);

useKey(']', increment);
useKey('[', decrement);
useKey('r', reset);

return (
<CenterStory>
<style dangerouslySetInnerHTML={{__html: `code {color: red}`}} />
<p>
Try pressing <code>[</code>, <code>]</code>, and <code>r</code> to
see the count incremented and decremented.</p>
<p>Count: {count}</p>
</CenterStory>
);
};

storiesOf("Sensors/useKey", module)
.add("Docs", () => <ShowDocs md={require("../../docs/useKeyPressEvent.md")} />)
.add("Demo", () => <Demo />);
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import useGetSetState from './useGetSetState';
import useHover from './useHover';
import useHoverDirty from './useHoverDirty';
import useIdle from './useIdle';
import useKey from './useKey';
import useKeyPress from './useKeyPress';
import useKeyPressEvent from './useKeyPressEvent';
import useLifecycles from './useLifecycles';
Expand Down Expand Up @@ -82,6 +83,7 @@ export {
useHover,
useHoverDirty,
useIdle,
useKey,
useKeyPress,
useKeyPressEvent,
useLifecycles,
Expand Down
1 change: 0 additions & 1 deletion src/useEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const defaultTarget = typeof window === 'object' ? window : null;

const useEvent = (name: string, handler?: null | undefined | ((event?: any) => void), target: null | UseEventTarget = defaultTarget, options?: any) => {
useEffect(() => {
console.log('adding event...');
if (!handler) return;
if (!target) return;
((target as ListenerType1).addEventListener || (target as ListenerType2).on).call(target, name, handler, options);
Expand Down
35 changes: 35 additions & 0 deletions src/useKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {useMemo, DependencyList} from 'react';
import useEvent, {UseEventTarget} from './useEvent';

export type KeyPredicate = (event: KeyboardEvent) => boolean;
export type KeyFilter = null | undefined | string | ((event: KeyboardEvent) => boolean);
export type Handler = (event: KeyboardEvent) => void;
export interface UseKeyOptions {
event?: 'keydown' | 'keypress' | 'keyup',
target?: UseEventTarget,
options?: any,
}

const noop = () => {};
const createKeyPredicate = (keyFilter: KeyFilter): KeyPredicate =>
typeof keyFilter === 'function'
? keyFilter
: typeof keyFilter === 'string'
? (event: KeyboardEvent) => event.key === keyFilter
: keyFilter
? () => true
: () => false;

const useKey = (key: KeyFilter, fn: Handler = noop, opts: UseKeyOptions = {}, deps: DependencyList = [key]) => {
const {event = 'keydown', target, options} = opts;
const handler = useMemo(() => {
const predicate: KeyPredicate = createKeyPredicate(key);
const handler: Handler = (event) => {
if (predicate(event)) return fn(event);
};
return handler;
}, deps);
useEvent(event, handler, target, options);
};

export default useKey;

0 comments on commit 299fd86

Please sign in to comment.