Skip to content

Commit

Permalink
feat(modifiers): create Modifiers context
Browse files Browse the repository at this point in the history
  • Loading branch information
albizures committed Jul 23, 2019
1 parent 102e04a commit 4563456
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/contexts/Modifiers/index.tsx
@@ -0,0 +1,47 @@
import React from 'react';
import { reducer, createActions } from './reducer';
import { Key, ModifiersState } from './types';

const defaultValueState = {};

const ModifiersContext = React.createContext<ModifiersState>(defaultValueState);

const useModifiers = () => React.useContext(ModifiersContext);
const useModifier = (key: Key) => useModifiers()[key];

interface ProviderProps {
children: React.ReactNode;
}

const Provider: React.FC<ProviderProps> = (props) => {
const [state, dispatch] = React.useReducer(reducer, defaultValueState);
const { children } = props;
const actions = React.useMemo(() => createActions(dispatch), [dispatch]);

React.useEffect(() => {
const onKeyDown = (event: KeyboardEvent) => {
actions.changeModifierState(event.key as Key, true);
};

const onKeyUp = (event: KeyboardEvent) => {
actions.changeModifierState(event.key as Key, false);
};

document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);

return () => {
document.removeEventListener('keydown', onKeyDown);
document.removeEventListener('keyup', onKeyUp);
};
}, [actions]);

return (
<ModifiersContext.Provider value={state}>
{children}
</ModifiersContext.Provider>
);
};

export * from './types';
export { Provider, useModifiers, useModifier };
36 changes: 36 additions & 0 deletions src/contexts/Modifiers/reducer.ts
@@ -0,0 +1,36 @@
import {
actionType,
ModifiersState,
Action,
ModifiersActions,
Key,
} from './types';

const reducer = (state: ModifiersState, action: Action): ModifiersState => {
const { type, payload } = action;
switch (type) {
case actionType.CHANGE_MODIFIER_STATE:
return {
...state,
[payload.key]: payload.state,
};
default:
return state;
}
};

type Dispatch = (action: Action) => void;

const createActions = (dispatch: Dispatch): ModifiersActions => ({
changeModifierState(key: Key, state: boolean) {
dispatch({
type: actionType.CHANGE_MODIFIER_STATE,
payload: {
key,
state,
},
});
},
});

export { reducer, Dispatch, createActions };
25 changes: 25 additions & 0 deletions src/contexts/Modifiers/types.ts
@@ -0,0 +1,25 @@
enum Key {
Spacebar = ' ',
}

enum actionType {
CHANGE_MODIFIER_STATE,
}

interface Payload {
key: Key;
state: boolean;
}

interface Action {
type: actionType;
payload: Payload;
}

interface ModifiersActions {
changeModifierState: (key: Key, state: boolean) => void;
}

type ModifiersState = { [key in Key]?: boolean };

export { Key, ModifiersState, actionType, Action, Payload, ModifiersActions };

0 comments on commit 4563456

Please sign in to comment.