@tanstack/react-hotkeys 0.14.5 → 0.15.1
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 +1 -1
- package/dist/HotkeysProvider.d.ts +22 -2
- package/dist/HotkeysProvider.js +43 -4
- package/dist/useAppHotkeys.d.ts +3 -3
- package/dist/useAppHotkeys.js +3 -3
- package/dist/useHotkey.d.ts +5 -5
- package/dist/useHotkeyRecorder.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
# TanStack Hotkeys
|
|
52
52
|
|
|
53
53
|
> [!NOTE]
|
|
54
|
-
> TanStack Hotkeys is
|
|
54
|
+
> TanStack Hotkeys is in beta. We are actively developing the library and are open to feedback and contributions.
|
|
55
55
|
|
|
56
56
|
Type-safe keyboard shortcuts for the web. Template-string bindings, parsed objects, a cross-platform `Mod` key, a singleton Hotkey Manager, and utilities for cheatsheet UIs—built to stay SSR-friendly.
|
|
57
57
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { UseHotkeyCommonOptions } from "./useHotkey.js";
|
|
2
2
|
import { AppHotkeys, AppHotkeysStore, CustomHotkeys, HotkeyChordRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
3
3
|
import React, { ReactNode } from "react";
|
|
4
|
+
import { HotkeysProviderScopeProps } from "@tanstack/hotkeys/adapter";
|
|
4
5
|
//#region src/HotkeysProvider.d.ts
|
|
5
6
|
export interface HotkeysProviderOptions {
|
|
6
7
|
/**
|
|
@@ -13,9 +14,12 @@ export interface HotkeysProviderOptions {
|
|
|
13
14
|
}
|
|
14
15
|
interface HotkeysContextValue {
|
|
15
16
|
appHotkeysStore: AppHotkeysStore | null;
|
|
17
|
+
/** Merged with every ancestor provider's defaults, including `hotkey.scope`. */
|
|
16
18
|
defaultOptions: HotkeysProviderOptions;
|
|
19
|
+
/** Whether this provider and every ancestor are enabled. */
|
|
20
|
+
enabled: boolean;
|
|
17
21
|
}
|
|
18
|
-
export interface HotkeysProviderProps<T extends AppHotkeys = AppHotkeys> {
|
|
22
|
+
export interface HotkeysProviderProps<T extends AppHotkeys = AppHotkeys> extends HotkeysProviderScopeProps {
|
|
19
23
|
children: ReactNode;
|
|
20
24
|
/**
|
|
21
25
|
* Every app hotkey, from `defineAppHotkeys`. Listed by `useAppHotkeyList`
|
|
@@ -29,11 +33,16 @@ export interface HotkeysProviderProps<T extends AppHotkeys = AppHotkeys> {
|
|
|
29
33
|
customHotkeys?: CustomHotkeys<T> | null;
|
|
30
34
|
/** Called with the custom hotkeys after every change, ready to save. */
|
|
31
35
|
onCustomHotkeysChange?: (customHotkeys: CustomHotkeys<T>) => void;
|
|
36
|
+
/** Merged with the parent provider's defaults. */
|
|
32
37
|
defaultOptions?: HotkeysProviderOptions;
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
* Provides default options, app hotkeys, and the user's custom hotkeys.
|
|
36
41
|
*
|
|
42
|
+
* Nest providers to create hotkey scopes. A nested provider inherits app
|
|
43
|
+
* hotkeys and merges default options. With `scope`, its hotkeys fire only
|
|
44
|
+
* while it is mounted and enabled; with `exclusive`, only its hotkeys fire.
|
|
45
|
+
*
|
|
37
46
|
* @example
|
|
38
47
|
* ```tsx
|
|
39
48
|
* <HotkeysProvider
|
|
@@ -46,8 +55,19 @@ export interface HotkeysProviderProps<T extends AppHotkeys = AppHotkeys> {
|
|
|
46
55
|
* <App />
|
|
47
56
|
* </HotkeysProvider>
|
|
48
57
|
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* function EditDialog() {
|
|
62
|
+
* return (
|
|
63
|
+
* <HotkeysProvider scope="edit-dialog" exclusive={{ allow: ['global'] }}>
|
|
64
|
+
* <DialogBody />
|
|
65
|
+
* </HotkeysProvider>
|
|
66
|
+
* )
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
49
69
|
*/
|
|
50
|
-
export declare function HotkeysProvider<T extends AppHotkeys = AppHotkeys>({ children, appHotkeys, customHotkeys, onCustomHotkeysChange, defaultOptions }: HotkeysProviderProps<T>): React.JSX.Element;
|
|
70
|
+
export declare function HotkeysProvider<T extends AppHotkeys = AppHotkeys>({ children, appHotkeys, customHotkeys, onCustomHotkeysChange, defaultOptions, scope, exclusive, enabled }: HotkeysProviderProps<T>): React.JSX.Element;
|
|
51
71
|
export declare function useHotkeysContext(): HotkeysContextValue | null;
|
|
52
72
|
export declare function useDefaultHotkeysOptions(): HotkeysProviderOptions;
|
|
53
73
|
//#endregion
|
package/dist/HotkeysProvider.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { AppHotkeysStore, publishAppHotkeysStore } from "@tanstack/hotkeys";
|
|
2
2
|
import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { activateHotkeysProviderScope, getHotkeysProviderScopeKey, mergeHotkeysProviderDefaults } from "@tanstack/hotkeys/adapter";
|
|
3
4
|
|
|
4
5
|
//#region src/HotkeysProvider.tsx
|
|
5
6
|
const HotkeysContext = createContext(null);
|
|
6
7
|
const DEFAULT_OPTIONS = {};
|
|
8
|
+
const NO_PARENT = {
|
|
9
|
+
appHotkeysStore: null,
|
|
10
|
+
defaultOptions: DEFAULT_OPTIONS,
|
|
11
|
+
enabled: true
|
|
12
|
+
};
|
|
7
13
|
/**
|
|
8
14
|
* Provides default options, app hotkeys, and the user's custom hotkeys.
|
|
9
15
|
*
|
|
16
|
+
* Nest providers to create hotkey scopes. A nested provider inherits app
|
|
17
|
+
* hotkeys and merges default options. With `scope`, its hotkeys fire only
|
|
18
|
+
* while it is mounted and enabled; with `exclusive`, only its hotkeys fire.
|
|
19
|
+
*
|
|
10
20
|
* @example
|
|
11
21
|
* ```tsx
|
|
12
22
|
* <HotkeysProvider
|
|
@@ -19,12 +29,34 @@ const DEFAULT_OPTIONS = {};
|
|
|
19
29
|
* <App />
|
|
20
30
|
* </HotkeysProvider>
|
|
21
31
|
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* function EditDialog() {
|
|
36
|
+
* return (
|
|
37
|
+
* <HotkeysProvider scope="edit-dialog" exclusive={{ allow: ['global'] }}>
|
|
38
|
+
* <DialogBody />
|
|
39
|
+
* </HotkeysProvider>
|
|
40
|
+
* )
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
22
43
|
*/
|
|
23
|
-
function HotkeysProvider({ children, appHotkeys, customHotkeys, onCustomHotkeysChange, defaultOptions = DEFAULT_OPTIONS }) {
|
|
44
|
+
function HotkeysProvider({ children, appHotkeys, customHotkeys, onCustomHotkeysChange, defaultOptions = DEFAULT_OPTIONS, scope, exclusive = false, enabled = true }) {
|
|
45
|
+
const parent = useContext(HotkeysContext) ?? NO_PARENT;
|
|
24
46
|
const [store] = useState(() => appHotkeys ? new AppHotkeysStore(appHotkeys, {
|
|
25
47
|
customHotkeys,
|
|
26
48
|
onCustomHotkeysChange
|
|
27
49
|
}) : null);
|
|
50
|
+
const active = parent.enabled && enabled;
|
|
51
|
+
const scopeKey = getHotkeysProviderScopeKey({
|
|
52
|
+
scope,
|
|
53
|
+
exclusive,
|
|
54
|
+
active,
|
|
55
|
+
parent: parent.defaultOptions.hotkey?.scope
|
|
56
|
+
});
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
return scopeKey ? activateHotkeysProviderScope(scopeKey) : void 0;
|
|
59
|
+
}, [scopeKey]);
|
|
28
60
|
useEffect(() => {
|
|
29
61
|
store?.setOptions({ onCustomHotkeysChange });
|
|
30
62
|
}, [store, onCustomHotkeysChange]);
|
|
@@ -36,9 +68,16 @@ function HotkeysProvider({ children, appHotkeys, customHotkeys, onCustomHotkeysC
|
|
|
36
68
|
return publishAppHotkeysStore(store);
|
|
37
69
|
}, [store]);
|
|
38
70
|
const contextValue = useMemo(() => ({
|
|
39
|
-
appHotkeysStore: store,
|
|
40
|
-
defaultOptions
|
|
41
|
-
|
|
71
|
+
appHotkeysStore: store ?? parent.appHotkeysStore,
|
|
72
|
+
defaultOptions: mergeHotkeysProviderDefaults(parent.defaultOptions, defaultOptions, scope),
|
|
73
|
+
enabled: active
|
|
74
|
+
}), [
|
|
75
|
+
store,
|
|
76
|
+
parent,
|
|
77
|
+
defaultOptions,
|
|
78
|
+
scope,
|
|
79
|
+
active
|
|
80
|
+
]);
|
|
42
81
|
return /* @__PURE__ */ React.createElement(HotkeysContext.Provider, { value: contextValue }, children);
|
|
43
82
|
}
|
|
44
83
|
function useHotkeysContext() {
|
package/dist/useAppHotkeys.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ import { AppHotkey, AppHotkeyListItem, CustomHotkeys, Hotkey, RegisteredAppHotke
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```tsx
|
|
10
|
-
* const
|
|
11
|
-
* useHotkey(
|
|
10
|
+
* const appHotkeys = useAppHotkeys()
|
|
11
|
+
* useHotkey(appHotkeys['doc.save'], () => save())
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
export declare function useAppHotkeys(): RegisteredAppHotkeys;
|
|
@@ -60,7 +60,7 @@ export interface UseCustomHotkeysResult {
|
|
|
60
60
|
* ```tsx
|
|
61
61
|
* const { setCustomHotkey, findConflicts } = useCustomHotkeys()
|
|
62
62
|
* const recorder = useHotkeyRecorder({
|
|
63
|
-
* maxSteps:
|
|
63
|
+
* maxSteps: Infinity,
|
|
64
64
|
* validate: (hotkey) =>
|
|
65
65
|
* findConflicts('doc.save', hotkey).length === 0 || 'Already in use',
|
|
66
66
|
* onRecord: (hotkey) => setCustomHotkey('doc.save', hotkey),
|
package/dist/useAppHotkeys.js
CHANGED
|
@@ -14,8 +14,8 @@ function useRequiredStore(hook) {
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```tsx
|
|
17
|
-
* const
|
|
18
|
-
* useHotkey(
|
|
17
|
+
* const appHotkeys = useAppHotkeys()
|
|
18
|
+
* useHotkey(appHotkeys['doc.save'], () => save())
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
function useAppHotkeys() {
|
|
@@ -57,7 +57,7 @@ function useAppHotkeyList() {
|
|
|
57
57
|
* ```tsx
|
|
58
58
|
* const { setCustomHotkey, findConflicts } = useCustomHotkeys()
|
|
59
59
|
* const recorder = useHotkeyRecorder({
|
|
60
|
-
* maxSteps:
|
|
60
|
+
* maxSteps: Infinity,
|
|
61
61
|
* validate: (hotkey) =>
|
|
62
62
|
* findConflicts('doc.save', hotkey).length === 0 || 'Already in use',
|
|
63
63
|
* onRecord: (hotkey) => setCustomHotkey('doc.save', hotkey),
|
package/dist/useHotkey.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppHotkey, HotkeyCallback, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
1
|
+
import { AppHotkey, HotkeyCallback, HotkeyCallbackContextFor, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
2
2
|
import { AdapterAppHotkeyOptions, AdapterChordOptions, AdapterCommonOptions, AdapterHotkeyOptions, AdapterOptionsFor, AdapterSequenceOptions } from "@tanstack/hotkeys/adapter";
|
|
3
3
|
//#region src/useHotkey.d.ts
|
|
4
4
|
/** A React ref, element, document, or window to listen on. */
|
|
@@ -37,7 +37,7 @@ export type UseAppHotkeyOptions<T extends AppHotkey = AppHotkey> = AdapterAppHot
|
|
|
37
37
|
* Options merge in this order: provider defaults, app hotkey declaration,
|
|
38
38
|
* call-site options.
|
|
39
39
|
*
|
|
40
|
-
* @param hotkey - A chord string,
|
|
40
|
+
* @param hotkey - A chord string, RawHotkeyChord object, sequence, or app hotkey
|
|
41
41
|
* @param callback - The function to call when the hotkey is pressed
|
|
42
42
|
* @param options - Options for the hotkey behavior
|
|
43
43
|
*
|
|
@@ -55,11 +55,11 @@ export type UseAppHotkeyOptions<T extends AppHotkey = AppHotkey> = AdapterAppHot
|
|
|
55
55
|
* @example
|
|
56
56
|
* ```tsx
|
|
57
57
|
* function Toolbar() {
|
|
58
|
-
* const
|
|
59
|
-
* useHotkey(
|
|
58
|
+
* const appHotkeys = useAppHotkeys()
|
|
59
|
+
* useHotkey(appHotkeys['doc.save'], () => save())
|
|
60
60
|
* }
|
|
61
61
|
* ```
|
|
62
62
|
*/
|
|
63
63
|
export declare function useHotkey<T extends AppHotkey>(hotkey: T, callback: HotkeyCallback, options?: UseAppHotkeyOptions<T>): void;
|
|
64
|
-
export declare function useHotkey<T extends RegisterableHotkey>(hotkey: T, callback: HotkeyCallback
|
|
64
|
+
export declare function useHotkey<const T extends RegisterableHotkey>(hotkey: T, callback: HotkeyCallback<HotkeyCallbackContextFor<T>>, options?: UseHotkeyOptionsFor<T>): void;
|
|
65
65
|
//#endregion
|
|
@@ -48,7 +48,7 @@ export interface ReactHotkeyRecorder<THotkey extends Hotkey = Hotkey> {
|
|
|
48
48
|
* @example
|
|
49
49
|
* ```tsx
|
|
50
50
|
* const recorder = useHotkeyRecorder({
|
|
51
|
-
* maxSteps:
|
|
51
|
+
* maxSteps: Infinity,
|
|
52
52
|
* onRecord: (hotkey) => setShortcut(hotkey), // 'Mod+S' or ['G', 'H']
|
|
53
53
|
* })
|
|
54
54
|
* ```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-hotkeys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "React adapter for TanStack Hotkeys",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dist"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@tanstack/hotkeys": "0.
|
|
36
|
+
"@tanstack/hotkeys": "0.16.1",
|
|
37
37
|
"@tanstack/react-store": "^0.11.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|