Skip to content

Commit

Permalink
added capslock and updated keyCode to key
Browse files Browse the repository at this point in the history
  • Loading branch information
pranesh239 committed Feb 1, 2020
1 parent 26c9bfc commit 2182d63
Show file tree
Hide file tree
Showing 10 changed files with 7,512 additions and 31 deletions.
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
"presets": ["@babel/preset-env", "@babel/preset-react"],
"ignore": ["*/__tests__.js", "*.test.js"]
}
13 changes: 13 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const ignores = [
'/node_modules/',
'/__fixtures__/',
'/fixtures/',
'/__tests__/helpers/',
'/__tests__/utils/',
'__mocks__'
];

module.exports = {
testMatch: ['**/__tests__/**/*.+(js|jsx|ts|tsx)'],
testPathIgnorePatterns: [...ignores]
};
7,116 changes: 7,116 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
{
"name": "use-key-capture",
"version": "0.0.1-beta.6",
"version": "0.0.1-beta.10",
"main": "dist",
"license": "MIT",
"scripts": {
"build": "rimraf dist && babel src --out-dir dist",
"build": "rimraf dist && babel src --ignore */__tests__ --out-dir dist",
"prepare": "yarn build",
"postpublish": "git push --tags"
"postpublish": "git push --tags",
"test": "jest --config=jest.config.js"
},
"devDependencies": {
"@babel/cli": "^7.7.7",
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@testing-library/jest-dom": "^5.0.0",
"@testing-library/react": "^9.4.0",
"jest": "^24.9.0",
"rimraf": "^3.0.0"
},
"peerDependencies": {
Expand All @@ -23,5 +27,9 @@
"homepage": "https://github.com/pranesh239/use-key-capture#readme",
"bugs": {
"url": "https://github.com/pranesh239/use-key-capture/issues"
},
"dependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
12 changes: 12 additions & 0 deletions src/__tests__/useKeyCapture.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { cleanup } from '@testing-library/react';
import { setUpHook } from '../testUtils';

describe('useKeyCapture', () => {
afterEach(cleanup());

it('should have some result', () => {
const hook = setUpHook();
console.log('hook', hook);
expect(2).toBe(3);
});
});
5 changes: 5 additions & 0 deletions src/testUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { renderHook } from '@testing-library/react-hooks';
import useKeyCapture from './index';

// export const setUpHook = renderHook(useKeyCapture());
export const setUpHook = 'hi';
30 changes: 23 additions & 7 deletions src/useKeyCapture/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { useEffect, useReducer } from 'react';
import { useEffect, useReducer, useRef } from 'react';
import reducer from './useKeyCaptureReducer';

import {
useKeyInitialState,
initialState,
getAction,
useKeyActionTypes,
useEnhancedReducer
useEnhancedReducer,
targetItemPropsDefaultValue,
handleRefAssignment
} from './useKeyCaptureUtils';

function useKeys() {
const [keyData, dispatch] = useReducer(
useEnhancedReducer(reducer),
useKeyInitialState
initialState
);

const targetItemRef = useRef(null);

console.log('targetItemRef', targetItemRef);

const dispatchWithActionDetails = event => {
dispatch(getAction(event));
};
Expand All @@ -35,14 +41,24 @@ function useKeys() {
}, [keyData]);

useEffect(() => {
document.addEventListener('keydown', dispatchWithActionDetails);
const listenerItem = targetItemRef.current || document;
listenerItem.addEventListener('keydown', dispatchWithActionDetails);

return () => {
document.removeEventListener('keydown', dispatchWithActionDetails);
listenerItem.removeEventListener('keydown', dispatchWithActionDetails);
};
}, []);

return { keyData, resetKeyDetails };
const targetPropsGetter = ({ ref, type } = {}) => {
return {
type: type || targetItemPropsDefaultValue.type,
ref: handleRefAssignment(ref, targetItemNode => {
targetItemRef.current = targetItemNode;
})
};
};

return { keyData, resetKeyDetails, targetPropsGetter };
}

export default useKeys;
24 changes: 24 additions & 0 deletions src/useKeyCapture/useKeyCaptureReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ export default function keyReducer(state, action) {
};
}

case useKeyActionTypes.CAPSLOCK: {
return {
...initialState,
isCapsLock: true,
...action.payload
};
}

case useKeyActionTypes.SHIFT: {
return {
...initialState,
isShift: true,
...action.payload
};
}

case useKeyActionTypes.CAPS_ALPHABET: {
return {
...initialState,
Expand Down Expand Up @@ -50,6 +66,14 @@ export default function keyReducer(state, action) {
};
}

case useKeyActionTypes.TAB: {
return {
...initialState,
isTab: true,
...action.payload
};
}

case useKeyActionTypes.SPECIAL: {
return {
...initialState,
Expand Down
66 changes: 50 additions & 16 deletions src/useKeyCapture/useKeyCaptureUtils.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
import { useCallback } from 'react';

export const initialState = {
const initialState = {
// Pressed key
key: null,

isEscape: false,
isEnter: false,
isCapsLock: false,
isTab: false,
isSpace: false,

// Function keys
isFunctionKey: false,

// Arrow keys
isArrow: false,
isArrowRight: false,
isArrowLeft: false,
isArrowUp: false,
isArrowDown: false,

isTab: false,

// Modifier keys
isWithShift: false,
isWithCtrl: false,
isWithMeta: false,
isWithAlt: false,

isNumber: false,

// Character varients
isCaps: false,
isSmall: false,
isNumber: false,

// For special character
isSpecialCharacter: false
};

export const useKeyActionTypes = {
const useKeyActionTypes = {
ENTER_KEY: 'ENTER_KEY',
ESCAPE_KEY: 'ESCAPE_KEY',
RESET_CAPTURES: 'RESET_CAPTURES',
Expand All @@ -42,7 +44,10 @@ export const useKeyActionTypes = {
NUMBER: 'NUMBER',
SPACE: 'SPACE',
ARROWS: 'ARROWS',
SPECIAL: 'SPECIAL'
SPECIAL: 'SPECIAL',
TAB: 'TAB',
CAPSLOCK: 'CAPSLOCK',
SHIFT: 'SHIFT'
};

const modifierKeys = {
Expand All @@ -53,9 +58,13 @@ const modifierKeys = {
};

const keyCodeMapper = {
13: useKeyActionTypes.ENTER_KEY,
27: useKeyActionTypes.ESCAPE_KEY,
32: useKeyActionTypes.SPACE
Enter: useKeyActionTypes.ENTER_KEY,
Escape: useKeyActionTypes.ESCAPE_KEY,
Tab: useKeyActionTypes.TAB,
CapsLock: useKeyActionTypes.CAPSLOCK,
Shift: useKeyActionTypes.SHIFT,
// eslint-disable-next-line no-useless-computed-key
[' ']: useKeyActionTypes.SPACE
};

const getArrowKeysPayload = key => {
Expand All @@ -72,7 +81,8 @@ const isSpecialCharacterPressed = key => {
return (
!isCapitalLetterPressed(key) &&
!isSmallLetterPressed(key) &&
!isNumberPressed(key)
!isNumberPressed(key) &&
!keyCodeMapper[key]
);
};

Expand All @@ -94,7 +104,7 @@ const getModifierPayload = eventDetails => {
* @param {KeyboardEvent} eventDetails keyboard event object
* @return {String} action type
*/
export const getAction = eventDetails => {
const getAction = eventDetails => {
if (!eventDetails) {
throw new Error('Event called with no details');
}
Expand All @@ -112,8 +122,7 @@ export const getAction = eventDetails => {

let type;

if (keyCodeMapper[eventDetails.keyCode])
type = keyCodeMapper[eventDetails.keyCode];
if (keyCodeMapper[eventDetails.key]) type = keyCodeMapper[eventDetails.key];

if (isCapitalLetterPressed(eventDetails.key)) {
type = useKeyActionTypes.CAPS_ALPHABET;
Expand All @@ -127,7 +136,7 @@ export const getAction = eventDetails => {
type = useKeyActionTypes.NUMBER;
}

if (isSpecialCharacterPressed(eventDetails.key)) {
if (!type && isSpecialCharacterPressed(eventDetails.key)) {
type = useKeyActionTypes.SPECIAL;
}

Expand All @@ -141,10 +150,35 @@ export const getAction = eventDetails => {
};
};

export const useEnhancedReducer = reducer =>
const targetItemPropsDefaultValue = {
type: 'text'
};

function handleRefAssignment(...refs) {
return node => {
refs.forEach(ref => {
if (typeof ref === 'function') {
ref(node);
} else if (ref) {
ref.current = node;
}
});
};
}

const useEnhancedReducer = reducer =>
useCallback(
(state, action) => {
return reducer(state, action);
},
[reducer]
);

export {
getAction,
initialState,
targetItemPropsDefaultValue,
useKeyActionTypes,
useEnhancedReducer,
handleRefAssignment
};
Loading

0 comments on commit 2182d63

Please sign in to comment.