@tanstack/preact-hotkeys 0.19.1 → 0.19.2

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.
@@ -1,6 +1,6 @@
1
1
  import { publishAppHotkeysStore } from "@tanstack/hotkeys";
2
2
  import { createContext } from "preact";
3
- import { useContext, useEffect, useMemo, useState } from "preact/hooks";
3
+ import { useContext, useLayoutEffect, useMemo, useState } from "preact/hooks";
4
4
  import { activateHotkeysProviderScope, createAppHotkeysStore, getHotkeysProviderScopeKey, mergeHotkeysProviderDefaults } from "@tanstack/hotkeys/adapter";
5
5
  import { jsx } from "preact/jsx-runtime";
6
6
 
@@ -56,10 +56,10 @@ function HotkeysProvider({ children, appHotkeys, customHotkeys, onCustomHotkeysC
56
56
  active,
57
57
  parent: parent.defaultOptions.hotkey?.scope
58
58
  });
59
- useEffect(() => {
59
+ useLayoutEffect(() => {
60
60
  return scopeKey ? activateHotkeysProviderScope(scopeKey) : void 0;
61
61
  }, [scopeKey]);
62
- useEffect(() => {
62
+ useLayoutEffect(() => {
63
63
  store?.setOptions({
64
64
  customHotkeys,
65
65
  onCustomHotkeysChange
@@ -69,10 +69,10 @@ function HotkeysProvider({ children, appHotkeys, customHotkeys, onCustomHotkeysC
69
69
  customHotkeys,
70
70
  onCustomHotkeysChange
71
71
  ]);
72
- useEffect(() => {
72
+ useLayoutEffect(() => {
73
73
  if (appHotkeys) store?.setAppHotkeys(appHotkeys);
74
74
  }, [store, appHotkeys]);
75
- useEffect(() => {
75
+ useLayoutEffect(() => {
76
76
  if (!store) return;
77
77
  return publishAppHotkeysStore(store);
78
78
  }, [store]);
@@ -1,7 +1,7 @@
1
1
  import { useDefaultHotkeysOptions } from "./HotkeysProvider.js";
2
2
  import { useSelector } from "./_useSelector.js";
3
3
  import { HotkeyRecorder } from "@tanstack/hotkeys";
4
- import { useEffect, useRef } from "preact/hooks";
4
+ import { useLayoutEffect, useRef, useState } from "preact/hooks";
5
5
  import { withDefaults } from "@tanstack/hotkeys/adapter";
6
6
 
7
7
  //#region src/useHotkeyRecorder.ts
@@ -14,19 +14,22 @@ function useHotkeyRecorder(options) {
14
14
  const isRecording = useSelector(recorder.store, (state) => state.isRecording);
15
15
  const steps = useSelector(recorder.store, (state) => state.steps);
16
16
  const recordedHotkey = useSelector(recorder.store, (state) => state.recordedHotkey);
17
- useEffect(() => {
17
+ useLayoutEffect(() => {
18
18
  return () => {
19
19
  recorderRef.current?.destroy();
20
20
  };
21
21
  }, []);
22
- return {
23
- isRecording,
24
- steps,
25
- recordedHotkey,
22
+ const [actions] = useState(() => ({
26
23
  startRecording: () => recorderRef.current?.start(),
27
24
  stopRecording: () => recorderRef.current?.stop(),
28
25
  cancelRecording: () => recorderRef.current?.cancel(),
29
26
  commitRecording: () => recorderRef.current?.commit()
27
+ }));
28
+ return {
29
+ isRecording,
30
+ steps,
31
+ recordedHotkey,
32
+ ...actions
30
33
  };
31
34
  }
32
35
 
@@ -1,7 +1,7 @@
1
1
  import { useHotkeysContext } from "./HotkeysProvider.js";
2
2
  import { useAppHotkeysStoreState } from "./_appHotkeysStore.js";
3
3
  import { resolveTarget } from "./utils.js";
4
- import { useEffect, useRef } from "preact/hooks";
4
+ import { useLayoutEffect, useRef } from "preact/hooks";
5
5
  import { createHotkeyBindings, prepareHotkeyDefinitions } from "@tanstack/hotkeys/adapter";
6
6
 
7
7
  //#region src/useHotkeys.ts
@@ -62,7 +62,7 @@ function useHotkeys(hotkeys, commonOptions = {}) {
62
62
  appHotkeysStore
63
63
  };
64
64
  const bindingsRef = useRef(null);
65
- useEffect(() => {
65
+ useLayoutEffect(() => {
66
66
  bindingsRef.current ??= createHotkeyBindings();
67
67
  const { hotkeys, ...context } = latestRef.current;
68
68
  bindingsRef.current.update(prepareHotkeyDefinitions(hotkeys, {
@@ -70,7 +70,7 @@ function useHotkeys(hotkeys, commonOptions = {}) {
70
70
  resolveTarget
71
71
  }));
72
72
  });
73
- useEffect(() => {
73
+ useLayoutEffect(() => {
74
74
  return () => {
75
75
  bindingsRef.current?.destroy();
76
76
  bindingsRef.current = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/preact-hotkeys",
3
- "version": "0.19.1",
3
+ "version": "0.19.2",
4
4
  "description": "Preact adapter for TanStack Hotkeys",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -35,7 +35,7 @@
35
35
  "skills"
36
36
  ],
37
37
  "dependencies": {
38
- "@tanstack/hotkeys": "0.22.0"
38
+ "@tanstack/hotkeys": "0.22.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@preact/preset-vite": "^2.10.6",
@@ -101,7 +101,8 @@ A hook uses the nearest `HotkeysProvider` above its component. Registering `Esca
101
101
 
102
102
  ## Pitfalls
103
103
 
104
- - **Pass the ref, not `ref.current`.** `target: listRef.current` is `null` on the first render, and a `null` target registers nothing, so the hotkey doesn't work until the component renders again. Pass `target: listRef`; a ref that is still empty waits for its element.
104
+ - **Pass the ref, not `ref.current`.** `target: listRef.current` is `null` on the first render, and a `null` target registers nothing, so the hotkey doesn't work until the component renders again. Pass `target: listRef` for an element the component always renders.
105
+ - **Keep elements that mount later in state.** The hook reads a ref only after its component renders, so it misses an element that mounts later, such as one a child shows from its own state. Use `const [el, setEl] = useState<HTMLElement | null>(null)`, `target: el`, and `ref={setEl}`; the hotkey registers when the element mounts and unregisters when it unmounts.
105
106
  - **No dependency arrays or `useCallback`.** The hooks read the hotkey, callback, and options on every render, so inline callbacks always see current state.
106
107
  - **Call the hooks directly.** A `useShortcut(keys: string)` wrapper has to cast strings to hotkeys, which turns off type checking and drops sequences, options, app hotkeys, and the typed callback context.
107
108
  - **In tests,** set `<HotkeysProvider defaultOptions={{ hotkey: { platform: 'mac' } }}>`.