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

Added usehotkeys hook #9

Merged
merged 35 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a031984
Added required dependencies
anmol-kumar0815 Nov 16, 2023
a50731b
Added usehotkeys hook
anmol-kumar0815 Nov 16, 2023
a296a19
Added webpack config
anmol-kumar0815 Nov 16, 2023
21cf397
Added webpack config
anmol-kumar0815 Nov 16, 2023
13bbc13
Added webpack config
anmol-kumar0815 Nov 16, 2023
6447895
Added some missing configs
anmol-kumar0815 Nov 16, 2023
5dfd1bf
Added npm ignore
anmol-kumar0815 Nov 16, 2023
5adcc71
v1.0.2
anmol-kumar0815 Nov 16, 2023
feb0851
Updated package name
anmol-kumar0815 Nov 16, 2023
da5ff18
Merge branch 'main' into 3-add-usehotkeys-hook
anmol-kumar0815 Nov 16, 2023
af17b19
Removed redundent dependencies
anmol-kumar0815 Nov 16, 2023
1332027
Removed webpack
anmol-kumar0815 Nov 16, 2023
c03846f
Added rollup config
anmol-kumar0815 Nov 16, 2023
763100a
Fixed package name
anmol-kumar0815 Nov 16, 2023
7577117
Enabled ensure-compact-objects
anmol-kumar0815 Nov 17, 2023
8f404e6
Enabled webpack-aliases-and-jsconfig-paths-should-be-in-sync
anmol-kumar0815 Nov 17, 2023
00c0974
Merge branch 'main' into 3-add-usehotkeys-hook
bot-bigbinary Nov 17, 2023
a385d43
#3 - Removed dependencies list and added missing babel plugin.
deepakjosp Dec 4, 2023
cbb3e43
#3 - Updated eslint ignore files list.
deepakjosp Dec 4, 2023
aacaa28
#3 - Omitted prettier and eslint write and checks from package.json a…
deepakjosp Dec 4, 2023
0976e10
#3 - Removed unnecessary peer dependencies and bundled it along with …
deepakjosp Dec 4, 2023
3714185
#3 - Added babel core package.
deepakjosp Dec 4, 2023
7aebe93
#3 - Removed hardsetting env value in rollup config
deepakjosp Dec 4, 2023
d25fc17
#3 - Removed unused plugin
deepakjosp Dec 4, 2023
de7d576
#3 - Fixed the version mismatch issues of rollup and it's plugins
deepakjosp Dec 4, 2023
238f387
Added aliases for constants and utils and fixed issues in rollup.config
deepakjosp Dec 4, 2023
e1dd279
#3 - Refactored constant util with absolute path.
deepakjosp Dec 4, 2023
bcae4c9
#3 - Removed unnecessary file ref from eslintignore
deepakjosp Dec 4, 2023
0e991e3
#3 - Set `@bigbinary/neeto/webpack-aliases-and-jsconfig-paths-should-…
deepakjosp Dec 4, 2023
25316b5
#3 - Fixed eslint dependencies version issues.
deepakjosp Dec 4, 2023
e527fe3
#3 - Moved util functions to util file\.
deepakjosp Dec 4, 2023
00019b2
#3 - Cleaned up the rollup config.
deepakjosp Dec 5, 2023
a33a196
#3 - Fixed issues in the publish scripts.
deepakjosp Dec 5, 2023
e99df01
#3 - Removed commonjs configurations from the build script
deepakjosp Dec 5, 2023
2972366
#3 - Added cjs bundle build method.
deepakjosp Dec 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ module.exports = mergeDeepLeft(
{
rules: {
"@bigbinary/neeto/no-missing-localization": "off",
"@bigbinary/neeto/webpack-aliases-and-jsconfig-paths-should-be-in-sync":
"off",
"@bigbinary/neeto/ensure-compact-objects": "off",
deepakjosp marked this conversation as resolved.
Show resolved Hide resolved
},
},
defaultConfig
Expand Down
15 changes: 15 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Development and build-related files
node_modules/
.eslintignore
.eslintrc
.prettierignore
.prettierrc
babel.config.js
webpack.config.js

# Editor-specific files and directories
.vscode/

# Documentation and configuration files not needed for users
README.md
.editorconfig
27 changes: 21 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
{
"name": "@bigbinary/neeto-hotkeys",
"name": "@bigbinary/neeto-usehotkeys",
"version": "1.0.0",
"description": "React hook for handling keyboard shortcuts, offering a customizable and platform-aware solution, supporting global and scoped modes.",
"main": "src/index.js",
anmol-kumar0815 marked this conversation as resolved.
Show resolved Hide resolved
"scripts": {
"prepare": "husky install"
"prepare": "husky install",
"build": "NODE_ENV=production webpack --config webpack.config.js"
},
"engines": {
"node": ">=18.12"
"node": ">=18.12",
"npm": ">=9",
"yarn": ">=1.22"
},
"lint-staged": {
"src/**/*.{js,jsx,json}": [
Expand All @@ -32,13 +36,23 @@
"url": "https://github.com/bigbinary/neeto-hotkeys/issues"
},
"homepage": "https://github.com/bigbinary/neeto-hotkeys#readme",
"dependencies": {
"mousetrap": "^1.6.5",
"mousetrap-global-bind": "^1.1.0",
"platform": "^1.3.6",
"ramda": "^0.29.1",
"react": "^18.2.0"
},
deepakjosp marked this conversation as resolved.
Show resolved Hide resolved
"devDependencies": {
"@babel/eslint-parser": "^7.23.3",
"@babel/preset-env": "^7.23.3",
"@babel/preset-react": "^7.23.3",
"@bigbinary/babel-preset-neeto": "^1.0.7",
"@bigbinary/eslint-plugin-neeto": "^1.1.31",
"@bigbinary/neeto-cist": "^1.0.4",
"@bigbinary/neeto-commons-frontend": "^2.1.38",
"babel-plugin-preval": "^5.1.0",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
deepakjosp marked this conversation as resolved.
Show resolved Hide resolved
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.29.0",
Expand All @@ -55,11 +69,12 @@
"husky": "^8.0.0",
"lint-staged": "^15.1.0",
"prettier": "^3.1.0",
"ramda": "^0.29.1"
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"yalc": "^1.0.0-pre.53"
},
"peerDependencies": {
"@bigbinary/neeto-cist": "latest",
"@bigbinary/neeto-commons-frontend": "latest",
"ramda": "^0.29.1"
"@bigbinary/neeto-commons-frontend": "latest"
}
}
28 changes: 28 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const MODES = {
default: "default",
global: "global",
scoped: "scoped",
};

export const DEFAULT_CONFIG = {
mode: MODES.default,
unbindOnUnmount: true,
enabled: true,
};

export const MAC_TO_WINDOWS_KEYS_MAP = {
option: "alt",
command: "ctrl",
return: "enter",
delete: "backspace",
};

export const OS = {
mac: "OS X",
windows: "Windows",
};

export const KEY_NAMES = {
delete: "delete",
backspace: "backspace",
};
63 changes: 63 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useEffect, useRef } from "react";

import Mousetrap from "mousetrap";
import "mousetrap-global-bind";
import { mergeLeft } from "ramda";

import { DEFAULT_CONFIG, MODES } from "./constants";
import { convertHotkeyToUsersPlatform } from "./utils";

const useHotKeys = (hotkey, handler, userConfig) => {
const ref = useRef(null);
const convertedHotkey = convertHotkeyToUsersPlatform(hotkey);
const config = mergeLeft(userConfig, DEFAULT_CONFIG);

if (!handler) {
throw new Error("You must provide a handler function to useHotKeys");
}

useEffect(() => {
if (!config.enabled) return undefined;

const mousetrapInstance = bindHotKey({
mode: config.mode,
hotkey: convertedHotkey,
handler,
ref,
});

return () => {
unBindHotKey({
mousetrapInstance,
mode: config.mode,
hotkey: convertedHotkey,
});
};
}, [handler, config.mode, convertedHotkey, config]);

return config.mode === MODES.scoped ? ref : null;
};

const bindHotKey = ({ mode, hotkey, handler, ref }) => {
let mousetrapInstance;

switch (mode) {
case MODES.global:
Mousetrap.bindGlobal(hotkey, handler);
break;
case MODES.scoped:
mousetrapInstance = Mousetrap(ref.current).bind(hotkey, handler);
break;
default:
mousetrapInstance = Mousetrap.bind(hotkey, handler);
}

return mousetrapInstance;
};

const unBindHotKey = ({ mousetrapInstance, mode, hotkey }) =>
mode === MODES.global
? Mousetrap.unbindGlobal(hotkey)
: mousetrapInstance?.unbind(hotkey);

export default useHotKeys;
27 changes: 27 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import platform from "platform";
import { toPairs } from "ramda";

import { MAC_TO_WINDOWS_KEYS_MAP, OS, KEY_NAMES } from "./constants";

const isMultipleHotkey = hotkey => Array.isArray(hotkey);

const replaceKeys = (hotkey, keyName, replaceWith) =>
isMultipleHotkey(hotkey)
? hotkey.map(item => item.replaceAll(keyName, replaceWith))
: hotkey.replaceAll(keyName, replaceWith);

const convertHotKeyToWindows = hotkey => {
toPairs(MAC_TO_WINDOWS_KEYS_MAP).forEach(([macKey, windowsKey]) => {
hotkey = replaceKeys(hotkey, macKey, windowsKey);
});

return hotkey;
};

export const convertHotkeyToUsersPlatform = hotkey => {
const platformInfo = platform.parse(navigator.userAgent);
const isOSX = platformInfo.os?.family?.includes(OS.mac);
if (isOSX) return replaceKeys(hotkey, KEY_NAMES.delete, KEY_NAMES.backspace);

return convertHotKeyToWindows(hotkey);
};
25 changes: 25 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const path = require("path");

module.exports = {
Amaljith-K marked this conversation as resolved.
Show resolved Hide resolved
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js",
libraryTarget: "commonjs2",
},
mode: "production",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
},
},
},
],
},
};
Loading