@tanstack/octane-hotkeys 0.3.0 → 0.4.0
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/dist/HotkeysProvider.d.ts +32 -11
- package/dist/HotkeysProvider.js +23 -7
- package/dist/index.d.ts +5 -8
- package/dist/index.js +2 -4
- package/dist/internal.js +11 -2
- package/dist/types.d.ts +25 -22
- package/dist/useAppHotkeys.d.ts +21 -0
- package/dist/useAppHotkeys.js +31 -0
- package/dist/useHotkey.d.ts +23 -3
- package/dist/useHotkey.js +3 -2
- package/dist/useHotkeyHint.d.ts +7 -3
- package/dist/useHotkeyHint.js +6 -3
- package/dist/useHotkeyRecorder.d.ts +10 -3
- package/dist/useHotkeyRecorder.js +3 -2
- package/dist/useHotkeyRegistrations.d.ts +1 -1
- package/dist/useHotkeyRegistrations.js +2 -5
- package/dist/useHotkeys.d.ts +14 -4
- package/dist/useHotkeys.js +12 -8
- package/package.json +2 -2
- package/dist/useHotkeySequence.d.ts +0 -5
- package/dist/useHotkeySequence.js +0 -14
- package/dist/useHotkeySequenceRecorder.d.ts +0 -6
- package/dist/useHotkeySequenceRecorder.js +0 -29
- package/dist/useHotkeySequences.d.ts +0 -6
- package/dist/useHotkeySequences.js +0 -23
|
@@ -1,25 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UseHotkeyCommonOptions } from "./useHotkey.js";
|
|
2
|
+
import { AppHotkeys, AppHotkeysStore, CustomHotkeys, HotkeyChordRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
2
3
|
//#region src/HotkeysProvider.d.ts
|
|
3
4
|
export interface DefaultHotkeysOptions {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Defaults for every hotkey registered by `useHotkey` and `useHotkeys`.
|
|
7
|
+
* `requireReset` applies to chords and `timeout` applies to sequences.
|
|
8
|
+
*/
|
|
9
|
+
hotkey?: UseHotkeyCommonOptions;
|
|
10
|
+
/** Defaults for every `useHotkeyRecorder`. */
|
|
11
|
+
hotkeyRecorder?: Partial<Omit<HotkeyChordRecorderOptions & HotkeySequenceRecorderOptions, 'maxSteps' | 'onRecord' | 'validate'>>;
|
|
12
|
+
}
|
|
13
|
+
interface HotkeysContextValue {
|
|
14
|
+
defaultOptions: DefaultHotkeysOptions;
|
|
15
|
+
appHotkeysStore: AppHotkeysStore | null;
|
|
8
16
|
}
|
|
9
17
|
export type HotkeysProviderOptions = DefaultHotkeysOptions;
|
|
10
18
|
export interface HotkeysProviderProps {
|
|
11
19
|
children?: unknown;
|
|
12
20
|
defaultOptions?: HotkeysProviderOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Every app hotkey, from `defineAppHotkeys`. Read when the provider first
|
|
23
|
+
* renders; listed by `useAppHotkeyList` whether or not they are registered.
|
|
24
|
+
*/
|
|
25
|
+
appHotkeys?: AppHotkeys;
|
|
26
|
+
/**
|
|
27
|
+
* Starting custom hotkeys, such as saved data. Read once; the provider owns
|
|
28
|
+
* the state afterwards. Invalid entries are ignored with a warning.
|
|
29
|
+
*/
|
|
30
|
+
customHotkeys?: CustomHotkeys | null;
|
|
31
|
+
/** Called with the custom hotkeys after every change, ready to save. */
|
|
32
|
+
onCustomHotkeysChange?: (customHotkeys: CustomHotkeys) => void;
|
|
13
33
|
}
|
|
14
34
|
/** Reads the nearest provider, or null outside a provider. */
|
|
15
|
-
export declare function useHotkeysContext():
|
|
16
|
-
defaultOptions: DefaultHotkeysOptions;
|
|
17
|
-
} | null;
|
|
35
|
+
export declare function useHotkeysContext(): HotkeysContextValue | null;
|
|
18
36
|
/** Reads the nearest provider's defaults, or an empty object. */
|
|
19
37
|
export declare function useDefaultHotkeysOptions(): DefaultHotkeysOptions;
|
|
20
|
-
/** Sets
|
|
21
|
-
export declare function HotkeysProvider({ children, defaultOptions }: HotkeysProviderProps): import("octane").ElementDescriptor<{
|
|
22
|
-
value:
|
|
38
|
+
/** Sets defaults, app hotkeys, and custom hotkeys for descendant components. */
|
|
39
|
+
export declare function HotkeysProvider({ children, defaultOptions, appHotkeys, customHotkeys, onCustomHotkeysChange }: HotkeysProviderProps): import("octane").ElementDescriptor<{
|
|
40
|
+
value: {
|
|
41
|
+
defaultOptions: DefaultHotkeysOptions;
|
|
42
|
+
appHotkeysStore: AppHotkeysStore<Readonly<Record<string, import("@tanstack/hotkeys").AppHotkey<string, import("@tanstack/hotkeys").HotkeyChord | import("@tanstack/hotkeys").HotkeySequence | null>>>> | null;
|
|
43
|
+
};
|
|
23
44
|
children: unknown;
|
|
24
45
|
}>;
|
|
25
46
|
//#endregion
|
package/dist/HotkeysProvider.js
CHANGED
|
@@ -1,20 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { subSlot } from "./internal.js";
|
|
2
|
+
import { AppHotkeysStore, publishAppHotkeysStore } from "@tanstack/hotkeys";
|
|
3
|
+
import { createContext, createElement, useContext, useLayoutEffect, useRef } from "octane";
|
|
2
4
|
|
|
3
5
|
//#region src/HotkeysProvider.ts
|
|
4
6
|
const HotkeysContext = createContext(null);
|
|
5
7
|
/** Reads the nearest provider, or null outside a provider. */
|
|
6
8
|
function useHotkeysContext() {
|
|
7
|
-
|
|
8
|
-
return defaultOptions === null ? null : { defaultOptions };
|
|
9
|
+
return useContext(HotkeysContext);
|
|
9
10
|
}
|
|
10
11
|
/** Reads the nearest provider's defaults, or an empty object. */
|
|
11
12
|
function useDefaultHotkeysOptions() {
|
|
12
|
-
return useContext(HotkeysContext) ?? {};
|
|
13
|
+
return useContext(HotkeysContext)?.defaultOptions ?? {};
|
|
13
14
|
}
|
|
14
|
-
/** Sets
|
|
15
|
-
function HotkeysProvider({ children, defaultOptions = {} }) {
|
|
15
|
+
/** Sets defaults, app hotkeys, and custom hotkeys for descendant components. */
|
|
16
|
+
function HotkeysProvider({ children, defaultOptions = {}, appHotkeys, customHotkeys, onCustomHotkeysChange }) {
|
|
17
|
+
const callbackRef = useRef(onCustomHotkeysChange, subSlot(void 0, "provider-callback"));
|
|
18
|
+
callbackRef.current = onCustomHotkeysChange;
|
|
19
|
+
const storeRef = useRef(void 0, subSlot(void 0, "provider-store"));
|
|
20
|
+
storeRef.current ??= appHotkeys ? new AppHotkeysStore(appHotkeys, {
|
|
21
|
+
customHotkeys,
|
|
22
|
+
onCustomHotkeysChange: (custom) => callbackRef.current?.(custom)
|
|
23
|
+
}) : null;
|
|
24
|
+
const store = storeRef.current;
|
|
25
|
+
useLayoutEffect(() => {
|
|
26
|
+
if (appHotkeys) store?.setAppHotkeys(appHotkeys);
|
|
27
|
+
}, [store, appHotkeys], subSlot(void 0, "provider-declarations"));
|
|
28
|
+
useLayoutEffect(() => store ? publishAppHotkeysStore(store) : void 0, [store], subSlot(void 0, "provider-publish"));
|
|
16
29
|
return createElement(HotkeysContext, {
|
|
17
|
-
value:
|
|
30
|
+
value: {
|
|
31
|
+
defaultOptions,
|
|
32
|
+
appHotkeysStore: store
|
|
33
|
+
},
|
|
18
34
|
children
|
|
19
35
|
});
|
|
20
36
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
+
import { UseAppHotkeyOptions, UseHotkeyChordOptions, UseHotkeyCommonOptions, UseHotkeyOptions, UseHotkeyOptionsFor, UseHotkeySequenceOptions, UseHotkeyTarget, useHotkey } from "./useHotkey.js";
|
|
1
2
|
import { DefaultHotkeysOptions, HotkeysProvider, HotkeysProviderOptions, HotkeysProviderProps, useDefaultHotkeysOptions, useHotkeysContext } from "./HotkeysProvider.js";
|
|
2
|
-
import { useHotkeys } from "./useHotkeys.js";
|
|
3
|
-
import { useHotkey } from "./useHotkey.js";
|
|
4
|
-
import { useHotkeySequences } from "./useHotkeySequences.js";
|
|
5
|
-
import { useHotkeySequence } from "./useHotkeySequence.js";
|
|
3
|
+
import { UseHotkeyDefinition, useHotkeys } from "./useHotkeys.js";
|
|
6
4
|
import { useHeldKeys } from "./useHeldKeys.js";
|
|
7
5
|
import { useHeldKeyCodes } from "./useHeldKeyCodes.js";
|
|
8
6
|
import { useKeyHold } from "./useKeyHold.js";
|
|
9
7
|
import { useHotkeyHint } from "./useHotkeyHint.js";
|
|
10
|
-
import { HotkeyRegistrationsResult, OctaneHotkeyRecorder,
|
|
8
|
+
import { HotkeyRegistrationsResult, OctaneHotkeyRecorder, UseCustomHotkeysResult } from "./types.js";
|
|
11
9
|
import { useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
|
|
12
10
|
import { useHotkeyRecorder } from "./useHotkeyRecorder.js";
|
|
13
|
-
import {
|
|
14
|
-
import { HotkeyDefinition, HotkeySequenceDefinition } from "@tanstack/hotkeys/adapter";
|
|
11
|
+
import { useAppHotkeyList, useAppHotkeys, useCustomHotkeys } from "./useAppHotkeys.js";
|
|
15
12
|
export * from "@tanstack/hotkeys";
|
|
16
|
-
export { type DefaultHotkeysOptions,
|
|
13
|
+
export { type DefaultHotkeysOptions, HotkeyRegistrationsResult, HotkeysProvider, type HotkeysProviderOptions, type HotkeysProviderProps, OctaneHotkeyRecorder, UseAppHotkeyOptions, UseCustomHotkeysResult, UseHotkeyChordOptions, UseHotkeyCommonOptions, UseHotkeyDefinition, UseHotkeyOptions, UseHotkeyOptionsFor, UseHotkeySequenceOptions, UseHotkeyTarget, useAppHotkeyList, useAppHotkeys, useCustomHotkeys, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations, useHotkeys, useHotkeysContext, useKeyHold };
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { HotkeysProvider, useDefaultHotkeysOptions, useHotkeysContext } from "./HotkeysProvider.js";
|
|
2
2
|
import { useHotkeys } from "./useHotkeys.js";
|
|
3
3
|
import { useHotkey } from "./useHotkey.js";
|
|
4
|
-
import { useHotkeySequences } from "./useHotkeySequences.js";
|
|
5
|
-
import { useHotkeySequence } from "./useHotkeySequence.js";
|
|
6
4
|
import { useHeldKeys } from "./useHeldKeys.js";
|
|
7
5
|
import { useHeldKeyCodes } from "./useHeldKeyCodes.js";
|
|
8
6
|
import { useKeyHold } from "./useKeyHold.js";
|
|
9
7
|
import { useHotkeyHint } from "./useHotkeyHint.js";
|
|
10
8
|
import { useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
|
|
11
9
|
import { useHotkeyRecorder } from "./useHotkeyRecorder.js";
|
|
12
|
-
import {
|
|
10
|
+
import { useAppHotkeyList, useAppHotkeys, useCustomHotkeys } from "./useAppHotkeys.js";
|
|
13
11
|
|
|
14
12
|
export * from "@tanstack/hotkeys"
|
|
15
13
|
|
|
16
|
-
export { HotkeysProvider, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations,
|
|
14
|
+
export { HotkeysProvider, useAppHotkeyList, useAppHotkeys, useCustomHotkeys, useDefaultHotkeysOptions, useHeldKeyCodes, useHeldKeys, useHotkey, useHotkeyHint, useHotkeyRecorder, useHotkeyRegistrations, useHotkeys, useHotkeysContext, useKeyHold };
|
package/dist/internal.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useSelector } from "@tanstack/octane-store";
|
|
1
|
+
import { Store, useSelector } from "@tanstack/octane-store";
|
|
2
2
|
|
|
3
3
|
//#region src/internal.ts
|
|
4
4
|
const subSlotCache = /* @__PURE__ */ new Map();
|
|
@@ -30,6 +30,15 @@ function splitSlot(args) {
|
|
|
30
30
|
return [slot === void 0 ? args : args.slice(0, -1), slot];
|
|
31
31
|
}
|
|
32
32
|
const select = useSelector;
|
|
33
|
+
const NO_APP_HOTKEYS = new Store(null);
|
|
34
|
+
/**
|
|
35
|
+
* Re-renders when the provider's app hotkeys or custom hotkeys change and
|
|
36
|
+
* returns the provider's store.
|
|
37
|
+
*/
|
|
38
|
+
function useAppHotkeysStore(store, slot) {
|
|
39
|
+
select(store?.store ?? NO_APP_HOTKEYS, (value) => value, void 0, slot);
|
|
40
|
+
return store;
|
|
41
|
+
}
|
|
33
42
|
|
|
34
43
|
//#endregion
|
|
35
|
-
export { select, splitSlot, subSlot };
|
|
44
|
+
export { select, splitSlot, subSlot, useAppHotkeysStore };
|
package/dist/types.d.ts
CHANGED
|
@@ -1,38 +1,41 @@
|
|
|
1
|
-
import { Hotkey, HotkeyRegistrationView, HotkeySequence,
|
|
1
|
+
import { AppHotkey, CustomHotkeys, Hotkey, HotkeyRegistrationView, HotkeySequence, RegisteredAppHotkeys } from "@tanstack/hotkeys";
|
|
2
2
|
//#region src/types.d.ts
|
|
3
3
|
/** Recording state and controls owned by the containing component. */
|
|
4
|
-
export interface OctaneHotkeyRecorder {
|
|
4
|
+
export interface OctaneHotkeyRecorder<THotkey extends Hotkey = Hotkey> {
|
|
5
5
|
/** Whether the recorder is listening for a shortcut. */
|
|
6
6
|
isRecording: boolean;
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/** Chords captured so far in a multi-step recording. */
|
|
8
|
+
steps: HotkeySequence;
|
|
9
|
+
/** The last committed hotkey, including brackets for physical codes. */
|
|
10
|
+
recordedHotkey: THotkey | null;
|
|
9
11
|
/** Start a new recording session. */
|
|
10
12
|
startRecording: () => void;
|
|
11
13
|
/** Stop and clear recorder state without calling onRecord or onCancel. */
|
|
12
14
|
stopRecording: () => void;
|
|
13
15
|
/** Stop, clear recorder state, and call onCancel. */
|
|
14
16
|
cancelRecording: () => void;
|
|
15
|
-
|
|
16
|
-
/** Sequence recording state and controls. */
|
|
17
|
-
export interface OctaneHotkeySequenceRecorder {
|
|
18
|
-
/** Whether the recorder is listening for chords. */
|
|
19
|
-
isRecording: boolean;
|
|
20
|
-
/** Chords captured in the current session. */
|
|
21
|
-
steps: HotkeySequence;
|
|
22
|
-
/** The last committed sequence. */
|
|
23
|
-
recordedSequence: HotkeySequence | null;
|
|
24
|
-
/** Start a new recording session. */
|
|
25
|
-
startRecording: () => void;
|
|
26
|
-
/** Stop without committing or calling onCancel. */
|
|
27
|
-
stopRecording: () => void;
|
|
28
|
-
/** Discard the current session and call onCancel. */
|
|
29
|
-
cancelRecording: () => void;
|
|
30
|
-
/** Commit the current steps. Does nothing when no steps are recorded. */
|
|
17
|
+
/** Commit the current steps (multi-step recordings). */
|
|
31
18
|
commitRecording: () => void;
|
|
32
19
|
}
|
|
33
|
-
/** Live registration views from the shared hotkey
|
|
20
|
+
/** Live registration views from the shared hotkey manager. */
|
|
34
21
|
export interface HotkeyRegistrationsResult {
|
|
22
|
+
/** Every registration, chords and sequences. Narrow each view with `kind`. */
|
|
35
23
|
hotkeys: Array<HotkeyRegistrationView>;
|
|
36
|
-
|
|
24
|
+
}
|
|
25
|
+
/** Custom hotkey state and actions returned by `useCustomHotkeys`. */
|
|
26
|
+
export interface UseCustomHotkeysResult {
|
|
27
|
+
/** The user's hotkeys that differ from the defaults. */
|
|
28
|
+
customHotkeys: CustomHotkeys;
|
|
29
|
+
/**
|
|
30
|
+
* Sets the user's hotkey for an app hotkey. `null` unbinds it.
|
|
31
|
+
* Returns conflicting app hotkeys; when any exist, nothing changes.
|
|
32
|
+
*/
|
|
33
|
+
setCustomHotkey: (id: keyof RegisteredAppHotkeys & string, hotkey: Hotkey | null) => Array<AppHotkey>;
|
|
34
|
+
/** Restores the default hotkey for an app hotkey. */
|
|
35
|
+
resetCustomHotkey: (id: keyof RegisteredAppHotkeys & string) => void;
|
|
36
|
+
/** Restores every default hotkey. */
|
|
37
|
+
resetCustomHotkeys: () => void;
|
|
38
|
+
/** Other app hotkeys that would collide if `id` used `hotkey`. */
|
|
39
|
+
findConflicts: (id: keyof RegisteredAppHotkeys & string, hotkey: Hotkey) => Array<AppHotkey>;
|
|
37
40
|
}
|
|
38
41
|
//#endregion
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { UseCustomHotkeysResult } from "./types.js";
|
|
2
|
+
import { AppHotkeyListItem, RegisteredAppHotkeys } from "@tanstack/hotkeys";
|
|
3
|
+
//#region src/useAppHotkeys.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns the effective app hotkeys from `HotkeysProvider`, typed by
|
|
6
|
+
* `Register`: each declaration with the user's custom hotkey applied.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useAppHotkeys(): RegisteredAppHotkeys;
|
|
9
|
+
/**
|
|
10
|
+
* Lists every app hotkey with its live status, in declaration order, for
|
|
11
|
+
* cheat sheets and settings screens. App hotkeys whose components have not
|
|
12
|
+
* mounted are `'inactive'`; those without a hotkey are `'unbound'`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useAppHotkeyList(): Array<AppHotkeyListItem<RegisteredAppHotkeys[keyof RegisteredAppHotkeys]>>;
|
|
15
|
+
/**
|
|
16
|
+
* Reads and changes the user's custom hotkeys. Changes apply to every
|
|
17
|
+
* registered app hotkey immediately and are passed to the provider's
|
|
18
|
+
* `onCustomHotkeysChange`, ready to save.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useCustomHotkeys(): UseCustomHotkeysResult;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { subSlot, useAppHotkeysStore } from "./internal.js";
|
|
2
|
+
import { useHotkeysContext } from "./HotkeysProvider.js";
|
|
3
|
+
import { useHotkeyRegistrations } from "./useHotkeyRegistrations.js";
|
|
4
|
+
|
|
5
|
+
//#region src/useAppHotkeys.ts
|
|
6
|
+
function useRequiredStore(name, slot) {
|
|
7
|
+
const store = useAppHotkeysStore(useHotkeysContext()?.appHotkeysStore ?? null, subSlot(slot, `${name}-store`));
|
|
8
|
+
if (!store) throw new Error(`${name} requires a HotkeysProvider with appHotkeys`);
|
|
9
|
+
return store;
|
|
10
|
+
}
|
|
11
|
+
function useAppHotkeys(slot) {
|
|
12
|
+
return useRequiredStore("useAppHotkeys", slot).appHotkeys;
|
|
13
|
+
}
|
|
14
|
+
function useAppHotkeyList(slot) {
|
|
15
|
+
const store = useRequiredStore("useAppHotkeyList", slot);
|
|
16
|
+
const registrations = useHotkeyRegistrations(subSlot(slot, "registrations"));
|
|
17
|
+
return store.getList(registrations.hotkeys);
|
|
18
|
+
}
|
|
19
|
+
function useCustomHotkeys(slot) {
|
|
20
|
+
const store = useRequiredStore("useCustomHotkeys", slot);
|
|
21
|
+
return {
|
|
22
|
+
customHotkeys: store.customHotkeys,
|
|
23
|
+
setCustomHotkey: (id, hotkey) => store.setCustomHotkey(id, hotkey),
|
|
24
|
+
resetCustomHotkey: (id) => store.resetCustomHotkey(id),
|
|
25
|
+
resetCustomHotkeys: () => store.resetCustomHotkeys(),
|
|
26
|
+
findConflicts: (id, hotkey) => store.findConflicts(id, hotkey)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { useAppHotkeyList, useAppHotkeys, useCustomHotkeys };
|
package/dist/useHotkey.d.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AppHotkey, HotkeyCallback, RegisterableHotkey, Target } from "@tanstack/hotkeys";
|
|
2
|
+
import { AdapterAppHotkeyOptions, AdapterChordOptions, AdapterCommonOptions, AdapterHotkeyOptions, AdapterOptionsFor, AdapterSequenceOptions } from "@tanstack/hotkeys/adapter";
|
|
2
3
|
//#region src/useHotkey.d.ts
|
|
3
|
-
/**
|
|
4
|
-
export
|
|
4
|
+
/** The element to listen on. A `null` target skips registration until it is set. */
|
|
5
|
+
export type UseHotkeyTarget = Target | null;
|
|
6
|
+
/** Options shared by chords and sequences. */
|
|
7
|
+
export type UseHotkeyOptions = AdapterHotkeyOptions<UseHotkeyTarget>;
|
|
8
|
+
/** Options for a chord such as `'Mod+S'`. */
|
|
9
|
+
export type UseHotkeyChordOptions = AdapterChordOptions<UseHotkeyTarget>;
|
|
10
|
+
/** Options for a sequence such as `['G', 'G']`. */
|
|
11
|
+
export type UseHotkeySequenceOptions = AdapterSequenceOptions<UseHotkeyTarget>;
|
|
12
|
+
/** Options applied to every hotkey, such as provider defaults. Each applies to the kinds that support it. */
|
|
13
|
+
export type UseHotkeyCommonOptions = AdapterCommonOptions<UseHotkeyTarget>;
|
|
14
|
+
/** The options type for a hotkey: chord options for chords, sequence options for sequences. */
|
|
15
|
+
export type UseHotkeyOptionsFor<T extends RegisterableHotkey> = AdapterOptionsFor<T, UseHotkeyTarget>;
|
|
16
|
+
/** Call-site options for an app hotkey, typed by its declared default kind. */
|
|
17
|
+
export type UseAppHotkeyOptions<T extends AppHotkey = AppHotkey> = AdapterAppHotkeyOptions<T, UseHotkeyTarget>;
|
|
18
|
+
/**
|
|
19
|
+
* Registers one hotkey: a chord such as `'Mod+S'`, a sequence such as
|
|
20
|
+
* `['G', 'G']`, or an app hotkey from `defineAppHotkeys`. The callback and
|
|
21
|
+
* options are refreshed after every commit.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useHotkey<T extends AppHotkey>(hotkey: T, callback: HotkeyCallback, options?: UseAppHotkeyOptions<T>): void;
|
|
24
|
+
export declare function useHotkey<T extends RegisterableHotkey>(hotkey: T, callback: HotkeyCallback, options?: UseHotkeyOptionsFor<T>): void;
|
|
5
25
|
//#endregion
|
package/dist/useHotkey.js
CHANGED
|
@@ -6,8 +6,9 @@ function useHotkey(hotkey, callback, ...rest) {
|
|
|
6
6
|
const [args, slot] = splitSlot(rest);
|
|
7
7
|
useHotkeys([{
|
|
8
8
|
hotkey,
|
|
9
|
-
callback
|
|
10
|
-
|
|
9
|
+
callback,
|
|
10
|
+
options: args[0]
|
|
11
|
+
}], void 0, subSlot(slot, "hotkey"));
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
//#endregion
|
package/dist/useHotkeyHint.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { HeldModifierOptions, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
1
|
+
import { AppHotkey, HeldModifierOptions, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
2
2
|
//#region src/useHotkeyHint.d.ts
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Reports whether held modifiers reveal a shortcut hint. A sequence reveals
|
|
5
|
+
* its hint from its first step, and an app hotkey uses its effective hotkey
|
|
6
|
+
* (false while unbound).
|
|
7
|
+
*/
|
|
8
|
+
export declare function useHotkeyHint(hotkey: RegisterableHotkey | AppHotkey, options?: HeldModifierOptions): boolean;
|
|
5
9
|
//#endregion
|
package/dist/useHotkeyHint.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { select, splitSlot, subSlot } from "./internal.js";
|
|
2
|
-
import {
|
|
1
|
+
import { select, splitSlot, subSlot, useAppHotkeysStore } from "./internal.js";
|
|
2
|
+
import { useHotkeysContext } from "./HotkeysProvider.js";
|
|
3
|
+
import { getKeyStateTracker, isAppHotkey, matchesHeldModifiers, resolveAppHotkey } from "@tanstack/hotkeys";
|
|
3
4
|
|
|
4
5
|
//#region src/useHotkeyHint.ts
|
|
5
6
|
function useHotkeyHint(hotkey, ...rest) {
|
|
6
7
|
const [args, slot] = splitSlot(rest);
|
|
7
|
-
|
|
8
|
+
const store = useAppHotkeysStore(useHotkeysContext()?.appHotkeysStore ?? null, subSlot(slot, "app-hotkeys"));
|
|
9
|
+
const resolved = isAppHotkey(hotkey) ? resolveAppHotkey(hotkey, store).hotkey : hotkey;
|
|
10
|
+
return select(getKeyStateTracker().store, (state) => resolved !== null && matchesHeldModifiers(resolved, state.heldKeys, args[0]), void 0, subSlot(slot, "hint"));
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
//#endregion
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { OctaneHotkeyRecorder } from "./types.js";
|
|
2
|
-
import {
|
|
2
|
+
import { HotkeyChord, HotkeyChordRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
3
3
|
//#region src/useHotkeyRecorder.d.ts
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Records a shortcut and destroys the recorder on unmount. With the default
|
|
6
|
+
* `maxSteps: 1`, the first valid chord is recorded. With a larger `maxSteps`,
|
|
7
|
+
* each chord adds a step; the recording commits on Enter (unless
|
|
8
|
+
* `commitKeys: 'none'`), after `idleTimeoutMs`, or at `maxSteps`, and
|
|
9
|
+
* `onRecord` receives a chord (one step) or a sequence.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useHotkeyRecorder(options: HotkeyChordRecorderOptions): OctaneHotkeyRecorder<HotkeyChord>;
|
|
12
|
+
export declare function useHotkeyRecorder(options: HotkeySequenceRecorderOptions): OctaneHotkeyRecorder;
|
|
6
13
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useDefaultHotkeysOptions } from "./HotkeysProvider.js";
|
|
2
1
|
import { select, subSlot } from "./internal.js";
|
|
2
|
+
import { useDefaultHotkeysOptions } from "./HotkeysProvider.js";
|
|
3
3
|
import { HotkeyRecorder } from "@tanstack/hotkeys";
|
|
4
4
|
import { useLayoutEffect, useRef } from "octane";
|
|
5
5
|
|
|
@@ -20,7 +20,8 @@ function useHotkeyRecorder(options, slot) {
|
|
|
20
20
|
...select(recorder.store, (value) => value, void 0, subSlot(slot, "state")),
|
|
21
21
|
startRecording: () => recorder.start(),
|
|
22
22
|
stopRecording: () => recorder.stop(),
|
|
23
|
-
cancelRecording: () => recorder.cancel()
|
|
23
|
+
cancelRecording: () => recorder.cancel(),
|
|
24
|
+
commitRecording: () => recorder.commit()
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HotkeyRegistrationsResult } from "./types.js";
|
|
2
2
|
//#region src/useHotkeyRegistrations.d.ts
|
|
3
|
-
/** Reads public registration
|
|
3
|
+
/** Reads public snapshots of every registration, chords and sequences. */
|
|
4
4
|
export declare function useHotkeyRegistrations(): HotkeyRegistrationsResult;
|
|
5
5
|
//#endregion
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { select, subSlot } from "./internal.js";
|
|
2
|
-
import { getHotkeyManager,
|
|
2
|
+
import { getHotkeyManager, toHotkeyRegistrationView } from "@tanstack/hotkeys";
|
|
3
3
|
|
|
4
4
|
//#region src/useHotkeyRegistrations.ts
|
|
5
5
|
function useHotkeyRegistrations(slot) {
|
|
6
|
-
return {
|
|
7
|
-
hotkeys: select(getHotkeyManager().registrations, (state) => Array.from(state.values()).map(toHotkeyRegistrationView), void 0, subSlot(slot, "hotkeys")),
|
|
8
|
-
sequences: select(getSequenceManager().registrations, (state) => Array.from(state.values()), void 0, subSlot(slot, "sequences"))
|
|
9
|
-
};
|
|
6
|
+
return { hotkeys: select(getHotkeyManager().registrations, (state) => Array.from(state.values()).map(toHotkeyRegistrationView), void 0, subSlot(slot, "hotkeys")) };
|
|
10
7
|
}
|
|
11
8
|
|
|
12
9
|
//#endregion
|
package/dist/useHotkeys.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { UseHotkeyCommonOptions, UseHotkeyTarget } from "./useHotkey.js";
|
|
2
|
+
import { AdapterHotkeyDefinition } from "@tanstack/hotkeys/adapter";
|
|
3
3
|
//#region src/useHotkeys.d.ts
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* One hotkey for `useHotkeys`. Chords accept `requireReset`; sequences accept
|
|
6
|
+
* `timeout`; hotkeys of unknown kind accept only shared options.
|
|
7
|
+
*/
|
|
8
|
+
export type UseHotkeyDefinition = AdapterHotkeyDefinition<UseHotkeyTarget>;
|
|
9
|
+
/**
|
|
10
|
+
* Registers a changing list of hotkeys (chords, sequences, and app hotkeys)
|
|
11
|
+
* after commit and releases it on unmount. Options merge in this order:
|
|
12
|
+
* provider defaults, app hotkey declaration, common options, per-hotkey
|
|
13
|
+
* options. Unbound app hotkeys and empty sequences register nothing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useHotkeys(definitions: ReadonlyArray<UseHotkeyDefinition>, options?: UseHotkeyCommonOptions): void;
|
|
6
16
|
//#endregion
|
package/dist/useHotkeys.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { splitSlot, subSlot, useAppHotkeysStore } from "./internal.js";
|
|
2
|
+
import { useHotkeysContext } from "./HotkeysProvider.js";
|
|
3
3
|
import { useLayoutEffect, useRef } from "octane";
|
|
4
|
-
import { createHotkeyBindings } from "@tanstack/hotkeys/adapter";
|
|
4
|
+
import { createHotkeyBindings, prepareHotkeyDefinitions } from "@tanstack/hotkeys/adapter";
|
|
5
5
|
|
|
6
6
|
//#region src/useHotkeys.ts
|
|
7
7
|
function useHotkeys(definitions, ...rest) {
|
|
8
8
|
const [args, slot] = splitSlot(rest);
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
9
|
+
const context = useHotkeysContext();
|
|
10
|
+
const appHotkeysStore = useAppHotkeysStore(context?.appHotkeysStore ?? null, subSlot(slot, "app-hotkeys"));
|
|
11
|
+
const commonOptions = args[0];
|
|
13
12
|
const ref = useRef(null, subSlot(slot, "bindings"));
|
|
14
13
|
ref.current ??= createHotkeyBindings();
|
|
15
14
|
const bindings = ref.current;
|
|
16
15
|
useLayoutEffect(() => {
|
|
17
|
-
bindings.update(definitions,
|
|
16
|
+
bindings.update(prepareHotkeyDefinitions(definitions, {
|
|
17
|
+
appHotkeysStore,
|
|
18
|
+
defaults: context?.defaultOptions.hotkey,
|
|
19
|
+
commonOptions,
|
|
20
|
+
resolveTarget: (target) => target
|
|
21
|
+
}));
|
|
18
22
|
}, null, subSlot(slot, "update"));
|
|
19
23
|
useLayoutEffect(() => () => bindings.destroy(), [], subSlot(slot, "cleanup"));
|
|
20
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/octane-hotkeys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Octane 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.12.0",
|
|
37
37
|
"@tanstack/octane-store": "^0.13.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { HotkeyCallback, HotkeySequence, SequenceOptions } from "@tanstack/hotkeys";
|
|
2
|
-
//#region src/useHotkeySequence.d.ts
|
|
3
|
-
/** Registers one multi-chord shortcut. Empty sequences do not register. */
|
|
4
|
-
export declare function useHotkeySequence(sequence: HotkeySequence, callback: HotkeyCallback, options?: SequenceOptions): void;
|
|
5
|
-
//#endregion
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { splitSlot, subSlot } from "./internal.js";
|
|
2
|
-
import { useHotkeySequences } from "./useHotkeySequences.js";
|
|
3
|
-
|
|
4
|
-
//#region src/useHotkeySequence.ts
|
|
5
|
-
function useHotkeySequence(sequence, callback, ...rest) {
|
|
6
|
-
const [args, slot] = splitSlot(rest);
|
|
7
|
-
useHotkeySequences([{
|
|
8
|
-
sequence,
|
|
9
|
-
callback
|
|
10
|
-
}], args[0], subSlot(slot, "sequence"));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
//#endregion
|
|
14
|
-
export { useHotkeySequence };
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { OctaneHotkeySequenceRecorder } from "./types.js";
|
|
2
|
-
import { HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
3
|
-
//#region src/useHotkeySequenceRecorder.d.ts
|
|
4
|
-
/** Records a sequence, including live steps and explicit commit/cancel controls. */
|
|
5
|
-
export declare function useHotkeySequenceRecorder(options: HotkeySequenceRecorderOptions): OctaneHotkeySequenceRecorder;
|
|
6
|
-
//#endregion
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useDefaultHotkeysOptions } from "./HotkeysProvider.js";
|
|
2
|
-
import { select, subSlot } from "./internal.js";
|
|
3
|
-
import { HotkeySequenceRecorder } from "@tanstack/hotkeys";
|
|
4
|
-
import { useLayoutEffect, useRef } from "octane";
|
|
5
|
-
|
|
6
|
-
//#region src/useHotkeySequenceRecorder.ts
|
|
7
|
-
function useHotkeySequenceRecorder(options, slot) {
|
|
8
|
-
const merged = {
|
|
9
|
-
...useDefaultHotkeysOptions().hotkeySequenceRecorder,
|
|
10
|
-
...options
|
|
11
|
-
};
|
|
12
|
-
const ref = useRef(null, subSlot(slot, "recorder"));
|
|
13
|
-
ref.current ??= new HotkeySequenceRecorder(merged);
|
|
14
|
-
const recorder = ref.current;
|
|
15
|
-
useLayoutEffect(() => {
|
|
16
|
-
recorder.setOptions(merged);
|
|
17
|
-
}, null, subSlot(slot, "options"));
|
|
18
|
-
useLayoutEffect(() => () => recorder.destroy(), [], subSlot(slot, "cleanup"));
|
|
19
|
-
return {
|
|
20
|
-
...select(recorder.store, (value) => value, void 0, subSlot(slot, "state")),
|
|
21
|
-
startRecording: () => recorder.start(),
|
|
22
|
-
stopRecording: () => recorder.stop(),
|
|
23
|
-
cancelRecording: () => recorder.cancel(),
|
|
24
|
-
commitRecording: () => recorder.commit()
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
//#endregion
|
|
29
|
-
export { useHotkeySequenceRecorder };
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { SequenceOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { HotkeySequenceDefinition } from "@tanstack/hotkeys/adapter";
|
|
3
|
-
//#region src/useHotkeySequences.d.ts
|
|
4
|
-
/** Registers a changing list of sequences and releases it on unmount. */
|
|
5
|
-
export declare function useHotkeySequences(definitions: Array<HotkeySequenceDefinition>, options?: SequenceOptions): void;
|
|
6
|
-
//#endregion
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useDefaultHotkeysOptions } from "./HotkeysProvider.js";
|
|
2
|
-
import { splitSlot, subSlot } from "./internal.js";
|
|
3
|
-
import { useLayoutEffect, useRef } from "octane";
|
|
4
|
-
import { createHotkeySequenceBindings } from "@tanstack/hotkeys/adapter";
|
|
5
|
-
|
|
6
|
-
//#region src/useHotkeySequences.ts
|
|
7
|
-
function useHotkeySequences(definitions, ...rest) {
|
|
8
|
-
const [args, slot] = splitSlot(rest);
|
|
9
|
-
const options = {
|
|
10
|
-
...useDefaultHotkeysOptions().hotkeySequence,
|
|
11
|
-
...args[0]
|
|
12
|
-
};
|
|
13
|
-
const ref = useRef(null, subSlot(slot, "bindings"));
|
|
14
|
-
ref.current ??= createHotkeySequenceBindings();
|
|
15
|
-
const bindings = ref.current;
|
|
16
|
-
useLayoutEffect(() => {
|
|
17
|
-
bindings.update(definitions, options);
|
|
18
|
-
}, null, subSlot(slot, "update"));
|
|
19
|
-
useLayoutEffect(() => () => bindings.destroy(), [], subSlot(slot, "cleanup"));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
//#endregion
|
|
23
|
-
export { useHotkeySequences };
|