@keybindy/react 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -21
- package/dist/Keybindy.js +29 -43
- package/dist/index.d.ts +10 -41
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -109,27 +109,27 @@ A powerful hook that gives you full control over the shortcut system via the Sho
|
|
|
109
109
|
|
|
110
110
|
##### Available methods
|
|
111
111
|
|
|
112
|
-
| Method
|
|
113
|
-
|
|
|
114
|
-
| [`register()`](https://github.com/keybindy/core#register)
|
|
115
|
-
| [`unregister()`](https://github.com/keybindy/core#unregister)
|
|
116
|
-
| [`enable()`](https://github.com/keybindy/core#enable--disable--toggle)
|
|
117
|
-
| [`disable()`](https://github.com/keybindy/core#enable--disable--toggle)
|
|
118
|
-
| [`toggle()`](https://github.com/keybindy/core#enable--disable--toggle)
|
|
119
|
-
| [`enableAll()`](https://github.com/keybindy/core#enableall--disableall)
|
|
120
|
-
| [`disableAll()`](https://github.com/keybindy/core#enableall--disableall)
|
|
121
|
-
| [`setScope()`](https://github.com/keybindy/core#setactivescope)
|
|
122
|
-
| [`resetScope()`](https://github.com/keybindy/core#resetScope)
|
|
123
|
-
| [`getScopes()`](https://github.com/keybindy/core#getScopes)
|
|
124
|
-
| [`getActiveScope()`](https://github.com/keybindy/core#getActiveScope)
|
|
125
|
-
| [`popScope()`](https://github.com/keybindy/core#popScope)
|
|
126
|
-
| [`pushScope()`](https://github.com/keybindy/core#pushScope)
|
|
127
|
-
| [`getCheatSheet()`](https://github.com/keybindy/core#getCheatsheet)
|
|
128
|
-
| [`onTyping()`](https://github.com/keybindy/core#onTyping)
|
|
129
|
-
| [`destroy()`](https://github.com/keybindy/core#destroy)
|
|
130
|
-
| [`clear()`](https://github.com/keybindy/core#clear)
|
|
131
|
-
| [`getScopeInfo()`](https://github.com/keybindy/core#getScopeInfo)
|
|
132
|
-
| [`isScopeActive()`](https://github.com/keybindy/core#isScopeActive)
|
|
112
|
+
| Method | Description |
|
|
113
|
+
| ------------------------------------------------------------------------ | -------------------------------------------- |
|
|
114
|
+
| [`register()`](https://github.com/keybindy/core#register) | Register a shortcut |
|
|
115
|
+
| [`unregister()`](https://github.com/keybindy/core#unregister) | Unregister a shortcut |
|
|
116
|
+
| [`enable()`](https://github.com/keybindy/core#enable--disable--toggle) | Enable a specific shortcut |
|
|
117
|
+
| [`disable()`](https://github.com/keybindy/core#enable--disable--toggle) | Disable a specific shortcut |
|
|
118
|
+
| [`toggle()`](https://github.com/keybindy/core#enable--disable--toggle) | Toggle a shortcut on/off |
|
|
119
|
+
| [`enableAll()`](https://github.com/keybindy/core#enableall--disableall) | Enable all shortcuts (global or scoped) |
|
|
120
|
+
| [`disableAll()`](https://github.com/keybindy/core#enableall--disableall) | Disable all shortcuts (global or scoped) |
|
|
121
|
+
| [`setScope()`](https://github.com/keybindy/core#setactivescope) | Set the active scope |
|
|
122
|
+
| [`resetScope()`](https://github.com/keybindy/core#resetScope) | Reset to default scope |
|
|
123
|
+
| [`getScopes()`](https://github.com/keybindy/core#getScopes) | Get all defined scopes |
|
|
124
|
+
| [`getActiveScope()`](https://github.com/keybindy/core#getActiveScope) | Get the current active scope |
|
|
125
|
+
| [`popScope()`](https://github.com/keybindy/core#popScope) | Remove the top scope from the scope stack |
|
|
126
|
+
| [`pushScope()`](https://github.com/keybindy/core#pushScope) | Push a new scope onto the scope stack |
|
|
127
|
+
| [`getCheatSheet()`](https://github.com/keybindy/core#getCheatsheet) | Retrieve all shortcuts (optionally by scope) |
|
|
128
|
+
| [`onTyping()`](https://github.com/keybindy/core#onTyping) | Listen to every key press |
|
|
129
|
+
| [`destroy()`](https://github.com/keybindy/core#destroy) | Tear down the current manager instance |
|
|
130
|
+
| [`clear()`](https://github.com/keybindy/core#clear) | Unregister all shortcuts |
|
|
131
|
+
| [`getScopeInfo()`](https://github.com/keybindy/core#getScopeInfo) | Retrieve metadata about a specific scope |
|
|
132
|
+
| [`isScopeActive()`](https://github.com/keybindy/core#isScopeActive) | Check if a scope is currently active |
|
|
133
133
|
|
|
134
134
|
> _All methods mirror `@keybindy/core` with a React-friendly API._
|
|
135
135
|
|
package/dist/Keybindy.js
CHANGED
|
@@ -2,59 +2,43 @@ import { jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useKeybindy } from './useKeybindy.js';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
* `<Keybindy />` is a React component that registers keyboard shortcuts within a given scope. It allows
|
|
7
|
-
* users to define custom shortcuts and their associated handlers, while managing scope-based shortcut behavior.
|
|
8
|
-
* The component listens for keyboard events and triggers the registered handler when the corresponding keys are pressed.
|
|
9
|
-
* It also provides an optional callback (`onShortcutFired`) to notify users when a shortcut is triggered.
|
|
10
|
-
*
|
|
11
|
-
* @component
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* // Basic usage
|
|
15
|
-
* <Keybindy scope="global" shortcuts={[{ keys: ['ctrl', 's'], handler: saveDocument }]} >
|
|
16
|
-
* <div>Content with shortcuts</div>
|
|
17
|
-
* </Keybindy>
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* // With custom callback for onShortcutFired
|
|
21
|
-
* <Keybindy
|
|
22
|
-
* scope="editor"
|
|
23
|
-
* shortcuts={[{ keys: ['ctrl', 'e'], handler: editDocument }]}
|
|
24
|
-
* onShortcutFired={(info) => console.log('Shortcut fired:', info)}
|
|
25
|
-
* >
|
|
26
|
-
* <div>Editor with shortcuts</div>
|
|
27
|
-
* </Keybindy>
|
|
28
|
-
*
|
|
29
|
-
* @param {ShortcutProps} props - Props for the Shortcut component.
|
|
30
|
-
* @param {string} props.scope - The scope under which the shortcuts should be active.
|
|
31
|
-
* @param {ShortcutDefinition[]} [props.shortcuts] - An array of shortcut definitions, each containing keys, handler, and options.
|
|
32
|
-
* @param {boolean} [props.disabled=false] - Whether the shortcuts should be disabled for this scope.
|
|
33
|
-
* @param {(info: Shortcut) => void} [props.onShortcutFired] - Optional callback triggered when a shortcut is fired, providing the shortcut info.
|
|
34
|
-
* @param {React.ReactNode} props.children - The children to be rendered inside the component, which can contain any JSX elements.
|
|
35
|
-
*
|
|
36
|
-
* @returns {JSX.Element} The rendered component with registered shortcuts within the provided scope.
|
|
37
|
-
*/
|
|
38
|
-
const Keybindy = ({ scope = 'global', shortcuts = [], children, disabled, onShortcutFired, logs = false, }) => {
|
|
5
|
+
const KeybindyComponent = ({ scope = 'global', shortcuts = [], children, disabled, onShortcutFired, logs = false, }) => {
|
|
39
6
|
const { register, unregister, manager, pushScope, popScope, getScopes, setScope } = useKeybindy({
|
|
40
7
|
onShortcutFired,
|
|
41
8
|
logs,
|
|
42
9
|
});
|
|
43
|
-
|
|
10
|
+
// Memoize a stable representation of shortcuts, excluding the handler.
|
|
11
|
+
// This prevents the effect from re-running unnecessarily.
|
|
12
|
+
const stableShortcuts = React.useMemo(() => {
|
|
13
|
+
return shortcuts.map(({ keys, options }) => ({ keys, options }));
|
|
14
|
+
}, [JSON.stringify(shortcuts.map(s => ({ keys: s.keys, options: s.options })))]);
|
|
15
|
+
// Use a ref to store the latest handlers, preventing re-renders from causing issues.
|
|
16
|
+
const handlersRef = React.useRef({});
|
|
17
|
+
React.useEffect(() => {
|
|
18
|
+
handlersRef.current = shortcuts.reduce((acc, { keys, handler }) => {
|
|
19
|
+
const key = JSON.stringify(keys);
|
|
20
|
+
acc[key] = handler;
|
|
21
|
+
return acc;
|
|
22
|
+
}, {});
|
|
23
|
+
});
|
|
44
24
|
React.useEffect(() => {
|
|
45
25
|
if (!manager) {
|
|
46
26
|
return;
|
|
47
27
|
}
|
|
48
|
-
prevScope.current = manager.getActiveScope() ?? 'global';
|
|
49
|
-
// Add scope if doesn't exist
|
|
50
28
|
if (!getScopes()?.includes(scope)) {
|
|
51
29
|
pushScope(scope);
|
|
52
30
|
}
|
|
53
|
-
// Set this scope as active
|
|
54
31
|
setScope(scope);
|
|
55
|
-
// Register
|
|
56
|
-
|
|
57
|
-
|
|
32
|
+
// Register shortcuts using the stable definitions.
|
|
33
|
+
stableShortcuts.forEach(({ keys, options }) => {
|
|
34
|
+
const stableHandler = (event, state) => {
|
|
35
|
+
const key = JSON.stringify(keys);
|
|
36
|
+
const currentHandler = handlersRef.current[key];
|
|
37
|
+
if (currentHandler) {
|
|
38
|
+
currentHandler(event, state);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
register(keys, stableHandler, { ...options, scope });
|
|
58
42
|
});
|
|
59
43
|
if (disabled) {
|
|
60
44
|
manager.disableAll(scope);
|
|
@@ -63,7 +47,8 @@ const Keybindy = ({ scope = 'global', shortcuts = [], children, disabled, onShor
|
|
|
63
47
|
manager.enableAll(scope);
|
|
64
48
|
}
|
|
65
49
|
return () => {
|
|
66
|
-
|
|
50
|
+
// Unregister using the same stable definitions.
|
|
51
|
+
stableShortcuts.forEach(({ keys }) => {
|
|
67
52
|
if (Array.isArray(keys[0])) {
|
|
68
53
|
keys.forEach(key => unregister(key, scope));
|
|
69
54
|
}
|
|
@@ -73,8 +58,9 @@ const Keybindy = ({ scope = 'global', shortcuts = [], children, disabled, onShor
|
|
|
73
58
|
});
|
|
74
59
|
popScope();
|
|
75
60
|
};
|
|
76
|
-
}, [scope,
|
|
61
|
+
}, [scope, manager, disabled, stableShortcuts]);
|
|
77
62
|
return jsx(Fragment, { children: children });
|
|
78
63
|
};
|
|
64
|
+
const Keybindy = React.memo(KeybindyComponent);
|
|
79
65
|
|
|
80
66
|
export { Keybindy };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import ShortcutManager, { Keys, ShortcutHandler,
|
|
3
|
-
export {
|
|
2
|
+
import ShortcutManager, { Keys, ShortcutHandler, ShortcutOptions, Shortcut } from '@keybindy/core';
|
|
3
|
+
export { Keys, Shortcut, ShortcutOptions } from '@keybindy/core';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Represents a
|
|
7
|
+
* Represents a shortcut definition for the `<Keybindy />` component.
|
|
8
8
|
*/
|
|
9
|
-
type
|
|
9
|
+
type KeybindyShortcut = {
|
|
10
10
|
/**
|
|
11
11
|
* The key combination(s) to listen for.
|
|
12
12
|
* Can be a single array of keys or an array of key combinations.
|
|
@@ -15,12 +15,13 @@ type ShortcutDefinition = {
|
|
|
15
15
|
/**
|
|
16
16
|
* Callback function to invoke when the shortcut is triggered.
|
|
17
17
|
*/
|
|
18
|
-
handler: ShortcutHandler
|
|
18
|
+
handler: ShortcutHandler;
|
|
19
19
|
/**
|
|
20
20
|
* Optional configuration, including scope and other metadata.
|
|
21
21
|
*/
|
|
22
22
|
options?: Omit<ShortcutOptions, 'scope'>;
|
|
23
23
|
};
|
|
24
|
+
|
|
24
25
|
/**
|
|
25
26
|
* Props for the `<Keybindy />` component.
|
|
26
27
|
*/
|
|
@@ -33,7 +34,7 @@ type KeybindyProps = {
|
|
|
33
34
|
/**
|
|
34
35
|
* Array of shortcut definitions to register for this scope.
|
|
35
36
|
*/
|
|
36
|
-
shortcuts?:
|
|
37
|
+
shortcuts?: KeybindyShortcut[];
|
|
37
38
|
/**
|
|
38
39
|
* Whether the shortcuts should be disabled for this scope.
|
|
39
40
|
* Defaults to `false`.
|
|
@@ -53,40 +54,7 @@ type KeybindyProps = {
|
|
|
53
54
|
*/
|
|
54
55
|
children?: React.ReactNode;
|
|
55
56
|
};
|
|
56
|
-
|
|
57
|
-
* `<Keybindy />` is a React component that registers keyboard shortcuts within a given scope. It allows
|
|
58
|
-
* users to define custom shortcuts and their associated handlers, while managing scope-based shortcut behavior.
|
|
59
|
-
* The component listens for keyboard events and triggers the registered handler when the corresponding keys are pressed.
|
|
60
|
-
* It also provides an optional callback (`onShortcutFired`) to notify users when a shortcut is triggered.
|
|
61
|
-
*
|
|
62
|
-
* @component
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* // Basic usage
|
|
66
|
-
* <Keybindy scope="global" shortcuts={[{ keys: ['ctrl', 's'], handler: saveDocument }]} >
|
|
67
|
-
* <div>Content with shortcuts</div>
|
|
68
|
-
* </Keybindy>
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* // With custom callback for onShortcutFired
|
|
72
|
-
* <Keybindy
|
|
73
|
-
* scope="editor"
|
|
74
|
-
* shortcuts={[{ keys: ['ctrl', 'e'], handler: editDocument }]}
|
|
75
|
-
* onShortcutFired={(info) => console.log('Shortcut fired:', info)}
|
|
76
|
-
* >
|
|
77
|
-
* <div>Editor with shortcuts</div>
|
|
78
|
-
* </Keybindy>
|
|
79
|
-
*
|
|
80
|
-
* @param {ShortcutProps} props - Props for the Shortcut component.
|
|
81
|
-
* @param {string} props.scope - The scope under which the shortcuts should be active.
|
|
82
|
-
* @param {ShortcutDefinition[]} [props.shortcuts] - An array of shortcut definitions, each containing keys, handler, and options.
|
|
83
|
-
* @param {boolean} [props.disabled=false] - Whether the shortcuts should be disabled for this scope.
|
|
84
|
-
* @param {(info: Shortcut) => void} [props.onShortcutFired] - Optional callback triggered when a shortcut is fired, providing the shortcut info.
|
|
85
|
-
* @param {React.ReactNode} props.children - The children to be rendered inside the component, which can contain any JSX elements.
|
|
86
|
-
*
|
|
87
|
-
* @returns {JSX.Element} The rendered component with registered shortcuts within the provided scope.
|
|
88
|
-
*/
|
|
89
|
-
declare const Keybindy: React.FC<KeybindyProps>;
|
|
57
|
+
declare const Keybindy: React.NamedExoticComponent<KeybindyProps>;
|
|
90
58
|
|
|
91
59
|
interface ShortcutLabelProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
|
|
92
60
|
/**
|
|
@@ -144,7 +112,7 @@ interface ShortcutLabelProps extends React.DetailedHTMLProps<React.HTMLAttribute
|
|
|
144
112
|
declare const ShortcutLabel: ({ keys, renderKey, style, ...props }: ShortcutLabelProps) => react_jsx_runtime.JSX.Element;
|
|
145
113
|
|
|
146
114
|
type UseKeybindyReturn = {
|
|
147
|
-
register: (keys: Keys[] | Keys[][], handler: ShortcutHandler
|
|
115
|
+
register: (keys: Keys[] | Keys[][], handler: ShortcutHandler, options?: ShortcutOptions) => void;
|
|
148
116
|
unregister: (keys: Keys[], scope?: string) => void;
|
|
149
117
|
enable: (keys: Keys[], scope?: string) => void;
|
|
150
118
|
disable: (keys: Keys[], scope?: string) => void;
|
|
@@ -186,3 +154,4 @@ declare const useKeybindy: ({ logs, onShortcutFired, }?: {
|
|
|
186
154
|
}) => UseKeybindyReturn;
|
|
187
155
|
|
|
188
156
|
export { Keybindy, ShortcutLabel, useKeybindy };
|
|
157
|
+
export type { KeybindyShortcut };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keybindy/react",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Keybindy for React: Simple, scoped keyboard shortcuts that require little setup. designed to smoothly blend in with your React applications, allowing for robust keybinding functionality without the overhead.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "PRASSamin",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"react": "^19.1.0",
|
|
54
|
-
"@keybindy/core": "1.1.
|
|
54
|
+
"@keybindy/core": "1.1.5"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|