@tanstack/solid-hotkeys 0.11.0 → 0.12.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.
Files changed (88) hide show
  1. package/dist/HotkeysProvider.d.ts +6 -9
  2. package/dist/HotkeysProvider.js +1 -2
  3. package/dist/createHeldKeyCodes.d.ts +2 -4
  4. package/dist/createHeldKeyCodes.js +3 -3
  5. package/dist/createHeldKeys.d.ts +2 -4
  6. package/dist/createHeldKeys.js +3 -3
  7. package/dist/createHotkey.d.ts +3 -6
  8. package/dist/createHotkey.js +3 -3
  9. package/dist/createHotkeyHint.d.ts +2 -5
  10. package/dist/createHotkeyHint.js +1 -2
  11. package/dist/createHotkeyRecorder.d.ts +3 -6
  12. package/dist/createHotkeyRecorder.js +4 -4
  13. package/dist/createHotkeyRegistrations.d.ts +3 -6
  14. package/dist/createHotkeyRegistrations.js +1 -2
  15. package/dist/createHotkeySequence.d.ts +3 -6
  16. package/dist/createHotkeySequence.js +1 -2
  17. package/dist/createHotkeySequenceRecorder.d.ts +3 -6
  18. package/dist/createHotkeySequenceRecorder.js +4 -4
  19. package/dist/createHotkeySequences.d.ts +3 -6
  20. package/dist/createHotkeySequences.js +1 -2
  21. package/dist/createHotkeys.d.ts +3 -6
  22. package/dist/createHotkeys.js +1 -2
  23. package/dist/createKeyHold.d.ts +2 -5
  24. package/dist/createKeyHold.js +3 -3
  25. package/package.json +12 -17
  26. package/dist/HotkeysProvider.cjs +0 -27
  27. package/dist/HotkeysProvider.cjs.map +0 -1
  28. package/dist/HotkeysProvider.d.cts +0 -25
  29. package/dist/HotkeysProvider.js.map +0 -1
  30. package/dist/createHeldKeyCodes.cjs +0 -42
  31. package/dist/createHeldKeyCodes.cjs.map +0 -1
  32. package/dist/createHeldKeyCodes.d.cts +0 -36
  33. package/dist/createHeldKeyCodes.js.map +0 -1
  34. package/dist/createHeldKeys.cjs +0 -33
  35. package/dist/createHeldKeys.cjs.map +0 -1
  36. package/dist/createHeldKeys.d.cts +0 -27
  37. package/dist/createHeldKeys.js.map +0 -1
  38. package/dist/createHotkey.cjs +0 -120
  39. package/dist/createHotkey.cjs.map +0 -1
  40. package/dist/createHotkey.d.cts +0 -72
  41. package/dist/createHotkey.js.map +0 -1
  42. package/dist/createHotkeyHint.cjs +0 -20
  43. package/dist/createHotkeyHint.cjs.map +0 -1
  44. package/dist/createHotkeyHint.d.cts +0 -14
  45. package/dist/createHotkeyHint.js.map +0 -1
  46. package/dist/createHotkeyRecorder.cjs +0 -78
  47. package/dist/createHotkeyRecorder.cjs.map +0 -1
  48. package/dist/createHotkeyRecorder.d.cts +0 -60
  49. package/dist/createHotkeyRecorder.js.map +0 -1
  50. package/dist/createHotkeyRegistrations.cjs +0 -26
  51. package/dist/createHotkeyRegistrations.cjs.map +0 -1
  52. package/dist/createHotkeyRegistrations.d.cts +0 -26
  53. package/dist/createHotkeyRegistrations.js.map +0 -1
  54. package/dist/createHotkeySequence.cjs +0 -107
  55. package/dist/createHotkeySequence.cjs.map +0 -1
  56. package/dist/createHotkeySequence.d.cts +0 -56
  57. package/dist/createHotkeySequence.js.map +0 -1
  58. package/dist/createHotkeySequenceRecorder.cjs +0 -43
  59. package/dist/createHotkeySequenceRecorder.cjs.map +0 -1
  60. package/dist/createHotkeySequenceRecorder.d.cts +0 -19
  61. package/dist/createHotkeySequenceRecorder.js.map +0 -1
  62. package/dist/createHotkeySequences.cjs +0 -112
  63. package/dist/createHotkeySequences.cjs.map +0 -1
  64. package/dist/createHotkeySequences.d.cts +0 -57
  65. package/dist/createHotkeySequences.js.map +0 -1
  66. package/dist/createHotkeys.cjs +0 -112
  67. package/dist/createHotkeys.cjs.map +0 -1
  68. package/dist/createHotkeys.d.cts +0 -57
  69. package/dist/createHotkeys.js.map +0 -1
  70. package/dist/createKeyHold.cjs +0 -56
  71. package/dist/createKeyHold.cjs.map +0 -1
  72. package/dist/createKeyHold.d.cts +0 -47
  73. package/dist/createKeyHold.js.map +0 -1
  74. package/dist/index.cjs +0 -35
  75. package/dist/index.d.cts +0 -14
  76. package/src/HotkeysProvider.tsx +0 -51
  77. package/src/createHeldKeyCodes.ts +0 -38
  78. package/src/createHeldKeys.ts +0 -29
  79. package/src/createHotkey.ts +0 -172
  80. package/src/createHotkeyHint.ts +0 -28
  81. package/src/createHotkeyRecorder.ts +0 -103
  82. package/src/createHotkeyRegistrations.ts +0 -45
  83. package/src/createHotkeySequence.ts +0 -155
  84. package/src/createHotkeySequenceRecorder.ts +0 -66
  85. package/src/createHotkeySequences.ts +0 -181
  86. package/src/createHotkeys.ts +0 -187
  87. package/src/createKeyHold.ts +0 -59
  88. package/src/index.ts +0 -18
@@ -1,57 +0,0 @@
1
- import { CreateHotkeyOptions } from "./createHotkey.cjs";
2
- import { HotkeyCallback, RegisterableHotkey } from "@tanstack/hotkeys";
3
-
4
- //#region src/createHotkeys.d.ts
5
- /**
6
- * A single hotkey definition for use with `createHotkeys`.
7
- */
8
- interface CreateHotkeyDefinition {
9
- /** The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object */
10
- hotkey: RegisterableHotkey;
11
- /** The function to call when the hotkey is pressed */
12
- callback: HotkeyCallback;
13
- /** Per-hotkey options (merged on top of commonOptions) */
14
- options?: CreateHotkeyOptions;
15
- }
16
- /**
17
- * SolidJS primitive for registering multiple keyboard hotkeys at once.
18
- *
19
- * Uses the singleton HotkeyManager for efficient event handling.
20
- * Accepts a dynamic array of hotkey definitions, making it safe to use
21
- * with variable-length lists.
22
- *
23
- * Options are merged in this order:
24
- * HotkeysProvider defaults < commonOptions < per-definition options
25
- *
26
- * @param hotkeys - Array of hotkey definitions, or accessor returning them
27
- * @param commonOptions - Shared options applied to all hotkeys, or accessor
28
- *
29
- * @example
30
- * ```tsx
31
- * function Editor() {
32
- * createHotkeys([
33
- * { hotkey: 'Mod+S', callback: () => save() },
34
- * { hotkey: 'Mod+Z', callback: () => undo() },
35
- * { hotkey: 'Escape', callback: () => close() },
36
- * ])
37
- * }
38
- * ```
39
- *
40
- * @example
41
- * ```tsx
42
- * function MenuShortcuts(props) {
43
- * createHotkeys(
44
- * () => props.items.map((item) => ({
45
- * hotkey: item.shortcut,
46
- * callback: item.action,
47
- * options: { enabled: item.enabled },
48
- * })),
49
- * { preventDefault: true },
50
- * )
51
- * }
52
- * ```
53
- */
54
- declare function createHotkeys(hotkeys: Array<CreateHotkeyDefinition> | (() => Array<CreateHotkeyDefinition>), commonOptions?: CreateHotkeyOptions | (() => CreateHotkeyOptions)): void;
55
- //#endregion
56
- export { CreateHotkeyDefinition, createHotkeys };
57
- //# sourceMappingURL=createHotkeys.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createHotkeys.js","names":[],"sources":["../src/createHotkeys.ts"],"sourcesContent":["import { createEffect, onCleanup, untrack } from 'solid-js'\nimport {\n detectPlatform,\n getHotkeyManager,\n normalizeRegisterableHotkey,\n} from '@tanstack/hotkeys'\nimport { useDefaultHotkeysOptions } from './HotkeysProvider'\nimport type { CreateHotkeyOptions } from './createHotkey'\nimport type {\n Hotkey,\n HotkeyCallback,\n HotkeyRegistrationHandle,\n RegisterableHotkey,\n} from '@tanstack/hotkeys'\n\n/**\n * A single hotkey definition for use with `createHotkeys`.\n */\nexport interface CreateHotkeyDefinition {\n /** The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object */\n hotkey: RegisterableHotkey\n /** The function to call when the hotkey is pressed */\n callback: HotkeyCallback\n /** Per-hotkey options (merged on top of commonOptions) */\n options?: CreateHotkeyOptions\n}\n\n/**\n * SolidJS primitive for registering multiple keyboard hotkeys at once.\n *\n * Uses the singleton HotkeyManager for efficient event handling.\n * Accepts a dynamic array of hotkey definitions, making it safe to use\n * with variable-length lists.\n *\n * Options are merged in this order:\n * HotkeysProvider defaults < commonOptions < per-definition options\n *\n * @param hotkeys - Array of hotkey definitions, or accessor returning them\n * @param commonOptions - Shared options applied to all hotkeys, or accessor\n *\n * @example\n * ```tsx\n * function Editor() {\n * createHotkeys([\n * { hotkey: 'Mod+S', callback: () => save() },\n * { hotkey: 'Mod+Z', callback: () => undo() },\n * { hotkey: 'Escape', callback: () => close() },\n * ])\n * }\n * ```\n *\n * @example\n * ```tsx\n * function MenuShortcuts(props) {\n * createHotkeys(\n * () => props.items.map((item) => ({\n * hotkey: item.shortcut,\n * callback: item.action,\n * options: { enabled: item.enabled },\n * })),\n * { preventDefault: true },\n * )\n * }\n * ```\n */\nexport function createHotkeys(\n hotkeys:\n | Array<CreateHotkeyDefinition>\n | (() => Array<CreateHotkeyDefinition>),\n commonOptions: CreateHotkeyOptions | (() => CreateHotkeyOptions) = {},\n): void {\n type RegistrationRecord = {\n handle: HotkeyRegistrationHandle\n target: Document | HTMLElement | Window\n }\n\n const defaultOptions = useDefaultHotkeysOptions()\n const manager = getHotkeyManager()\n\n const registrations = new Map<string, RegistrationRecord>()\n\n // Clean up only when this component/scope disposes — not before every effect\n // re-run. An inner `onCleanup` inside `createEffect` runs whenever reactive\n // deps change (e.g. dynamic hotkey list), which unregistered every hotkey and\n // re-registered them, flooding the manager store and could freeze the tab.\n onCleanup(() => {\n for (const { handle } of registrations.values()) {\n if (handle.isActive) {\n handle.unregister()\n }\n }\n registrations.clear()\n })\n\n createEffect(() => {\n const resolvedHotkeys = typeof hotkeys === 'function' ? hotkeys() : hotkeys\n const resolvedCommonOptions =\n typeof commonOptions === 'function' ? commonOptions() : commonOptions\n\n const nextKeys = new Set<string>()\n const prepared: Array<{\n registrationKey: string\n def: CreateHotkeyDefinition\n mergedOptions: CreateHotkeyOptions\n hotkeyString: Hotkey\n resolvedTarget: Document | HTMLElement | Window\n }> = []\n\n for (let i = 0; i < resolvedHotkeys.length; i++) {\n const def = resolvedHotkeys[i]!\n const resolvedDefOptions = def.options ?? {}\n\n const mergedOptions = {\n ...defaultOptions.hotkey,\n ...resolvedCommonOptions,\n ...resolvedDefOptions,\n } as CreateHotkeyOptions\n\n const platform = mergedOptions.platform ?? detectPlatform()\n const hotkeyString = normalizeRegisterableHotkey(def.hotkey, platform)\n\n const resolvedTarget =\n 'target' in mergedOptions\n ? (mergedOptions.target ?? null)\n : typeof document !== 'undefined'\n ? document\n : null\n\n if (!resolvedTarget) {\n continue\n }\n\n const registrationKey = `${i}:${hotkeyString}`\n nextKeys.add(registrationKey)\n prepared.push({\n registrationKey,\n def,\n mergedOptions,\n hotkeyString,\n resolvedTarget,\n })\n }\n\n // Untrack store mutations so that registering/updating hotkeys doesn't\n // create a circular reactive dependency when createHotkeyRegistrations\n // subscribes to the same store.\n untrack(() => {\n // Drop stale keys first so list index shifts don't briefly double-register\n // the same hotkey+target (conflictBehavior: 'warn' + devtools can loop).\n for (const [key, record] of [...registrations.entries()]) {\n if (!nextKeys.has(key)) {\n if (record.handle.isActive) {\n record.handle.unregister()\n }\n registrations.delete(key)\n }\n }\n\n for (const p of prepared) {\n const existing = registrations.get(p.registrationKey)\n if (existing?.handle.isActive && existing.target === p.resolvedTarget) {\n existing.handle.callback = p.def.callback\n const { target: _target, ...optionsWithoutTarget } = p.mergedOptions\n existing.handle.setOptions(optionsWithoutTarget)\n continue\n }\n\n if (existing) {\n if (existing.handle.isActive) {\n existing.handle.unregister()\n }\n registrations.delete(p.registrationKey)\n }\n\n const { target: _target, ...optionsWithoutTarget } = p.mergedOptions\n const handle = manager.register(p.hotkeyString, p.def.callback, {\n ...optionsWithoutTarget,\n target: p.resolvedTarget,\n })\n registrations.set(p.registrationKey, {\n handle,\n target: p.resolvedTarget,\n })\n }\n })\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,cACd,SAGA,gBAAmE,EAAE,EAC/D;CAMN,MAAM,iBAAiB,0BAA0B;CACjD,MAAM,UAAU,kBAAkB;CAElC,MAAM,gCAAgB,IAAI,KAAiC;AAM3D,iBAAgB;AACd,OAAK,MAAM,EAAE,YAAY,cAAc,QAAQ,CAC7C,KAAI,OAAO,SACT,QAAO,YAAY;AAGvB,gBAAc,OAAO;GACrB;AAEF,oBAAmB;EACjB,MAAM,kBAAkB,OAAO,YAAY,aAAa,SAAS,GAAG;EACpE,MAAM,wBACJ,OAAO,kBAAkB,aAAa,eAAe,GAAG;EAE1D,MAAM,2BAAW,IAAI,KAAa;EAClC,MAAM,WAMD,EAAE;AAEP,OAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;GAC/C,MAAM,MAAM,gBAAgB;GAC5B,MAAM,qBAAqB,IAAI,WAAW,EAAE;GAE5C,MAAM,gBAAgB;IACpB,GAAG,eAAe;IAClB,GAAG;IACH,GAAG;IACJ;GAED,MAAM,WAAW,cAAc,YAAY,gBAAgB;GAC3D,MAAM,eAAe,4BAA4B,IAAI,QAAQ,SAAS;GAEtE,MAAM,iBACJ,YAAY,gBACP,cAAc,UAAU,OACzB,OAAO,aAAa,cAClB,WACA;AAER,OAAI,CAAC,eACH;GAGF,MAAM,kBAAkB,GAAG,EAAE,GAAG;AAChC,YAAS,IAAI,gBAAgB;AAC7B,YAAS,KAAK;IACZ;IACA;IACA;IACA;IACA;IACD,CAAC;;AAMJ,gBAAc;AAGZ,QAAK,MAAM,CAAC,KAAK,WAAW,CAAC,GAAG,cAAc,SAAS,CAAC,CACtD,KAAI,CAAC,SAAS,IAAI,IAAI,EAAE;AACtB,QAAI,OAAO,OAAO,SAChB,QAAO,OAAO,YAAY;AAE5B,kBAAc,OAAO,IAAI;;AAI7B,QAAK,MAAM,KAAK,UAAU;IACxB,MAAM,WAAW,cAAc,IAAI,EAAE,gBAAgB;AACrD,QAAI,UAAU,OAAO,YAAY,SAAS,WAAW,EAAE,gBAAgB;AACrE,cAAS,OAAO,WAAW,EAAE,IAAI;KACjC,MAAM,EAAE,QAAQ,SAAS,GAAG,yBAAyB,EAAE;AACvD,cAAS,OAAO,WAAW,qBAAqB;AAChD;;AAGF,QAAI,UAAU;AACZ,SAAI,SAAS,OAAO,SAClB,UAAS,OAAO,YAAY;AAE9B,mBAAc,OAAO,EAAE,gBAAgB;;IAGzC,MAAM,EAAE,QAAQ,SAAS,GAAG,yBAAyB,EAAE;IACvD,MAAM,SAAS,QAAQ,SAAS,EAAE,cAAc,EAAE,IAAI,UAAU;KAC9D,GAAG;KACH,QAAQ,EAAE;KACX,CAAC;AACF,kBAAc,IAAI,EAAE,iBAAiB;KACnC;KACA,QAAQ,EAAE;KACX,CAAC;;IAEJ;GACF"}
@@ -1,56 +0,0 @@
1
- let _tanstack_hotkeys = require("@tanstack/hotkeys");
2
- let solid_js = require("solid-js");
3
- let _tanstack_solid_store = require("@tanstack/solid-store");
4
-
5
- //#region src/createKeyHold.ts
6
- /**
7
- * SolidJS primitive that returns whether a specific key is currently being held.
8
- *
9
- * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe
10
- * to the global KeyStateTracker and uses a selector to determine if the
11
- * specified key is held.
12
- *
13
- * @param key - The key to check (e.g., 'Shift', 'Control', 'A') - can be an accessor function
14
- * @returns Signal accessor that returns true if the key is currently held down
15
- *
16
- * @example
17
- * ```tsx
18
- * function ShiftIndicator() {
19
- * const isShiftHeld = createKeyHold('Shift')
20
- *
21
- * return (
22
- * <div style={{ opacity: isShiftHeld() ? 1 : 0.5 }}>
23
- * {isShiftHeld() ? 'Shift is pressed!' : 'Press Shift'}
24
- * </div>
25
- * )
26
- * }
27
- * ```
28
- *
29
- * @example
30
- * ```tsx
31
- * function ModifierIndicators() {
32
- * const ctrl = createKeyHold('Control')
33
- * const shift = createKeyHold('Shift')
34
- * const alt = createKeyHold('Alt')
35
- *
36
- * return (
37
- * <div>
38
- * <span style={{ opacity: ctrl() ? 1 : 0.3 }}>Ctrl</span>
39
- * <span style={{ opacity: shift() ? 1 : 0.3 }}>Shift</span>
40
- * <span style={{ opacity: alt() ? 1 : 0.3 }}>Alt</span>
41
- * </div>
42
- * )
43
- * }
44
- * ```
45
- */
46
- function createKeyHold(key) {
47
- const heldKeysSelector = (0, _tanstack_solid_store.useSelector)((0, _tanstack_hotkeys.getKeyStateTracker)().store, (state) => state.heldKeys);
48
- return (0, solid_js.createMemo)(() => {
49
- const normalizedKey = (typeof key === "function" ? key() : key).toLowerCase();
50
- return heldKeysSelector().some((heldKey) => heldKey.toLowerCase() === normalizedKey);
51
- });
52
- }
53
-
54
- //#endregion
55
- exports.createKeyHold = createKeyHold;
56
- //# sourceMappingURL=createKeyHold.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createKeyHold.cjs","names":[],"sources":["../src/createKeyHold.ts"],"sourcesContent":["import { createMemo } from 'solid-js'\nimport { useSelector } from '@tanstack/solid-store'\nimport { getKeyStateTracker } from '@tanstack/hotkeys'\nimport type { IndividualKey } from '@tanstack/hotkeys'\n\n/**\n * SolidJS primitive that returns whether a specific key is currently being held.\n *\n * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe\n * to the global KeyStateTracker and uses a selector to determine if the\n * specified key is held.\n *\n * @param key - The key to check (e.g., 'Shift', 'Control', 'A') - can be an accessor function\n * @returns Signal accessor that returns true if the key is currently held down\n *\n * @example\n * ```tsx\n * function ShiftIndicator() {\n * const isShiftHeld = createKeyHold('Shift')\n *\n * return (\n * <div style={{ opacity: isShiftHeld() ? 1 : 0.5 }}>\n * {isShiftHeld() ? 'Shift is pressed!' : 'Press Shift'}\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * function ModifierIndicators() {\n * const ctrl = createKeyHold('Control')\n * const shift = createKeyHold('Shift')\n * const alt = createKeyHold('Alt')\n *\n * return (\n * <div>\n * <span style={{ opacity: ctrl() ? 1 : 0.3 }}>Ctrl</span>\n * <span style={{ opacity: shift() ? 1 : 0.3 }}>Shift</span>\n * <span style={{ opacity: alt() ? 1 : 0.3 }}>Alt</span>\n * </div>\n * )\n * }\n * ```\n */\nexport function createKeyHold(\n key: IndividualKey | (() => IndividualKey),\n): () => boolean {\n const tracker = getKeyStateTracker()\n const heldKeysSelector = useSelector(tracker.store, (state) => state.heldKeys)\n\n return createMemo(() => {\n const resolvedKey = typeof key === 'function' ? key() : key\n const normalizedKey = resolvedKey.toLowerCase()\n return heldKeysSelector().some(\n (heldKey) => heldKey.toLowerCase() === normalizedKey,\n )\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,cACd,KACe;CAEf,MAAM,qGAD8B,CACS,QAAQ,UAAU,MAAM,SAAS;AAE9E,uCAAwB;EAEtB,MAAM,iBADc,OAAO,QAAQ,aAAa,KAAK,GAAG,KACtB,aAAa;AAC/C,SAAO,kBAAkB,CAAC,MACvB,YAAY,QAAQ,aAAa,KAAK,cACxC;GACD"}
@@ -1,47 +0,0 @@
1
- import { IndividualKey } from "@tanstack/hotkeys";
2
-
3
- //#region src/createKeyHold.d.ts
4
- /**
5
- * SolidJS primitive that returns whether a specific key is currently being held.
6
- *
7
- * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe
8
- * to the global KeyStateTracker and uses a selector to determine if the
9
- * specified key is held.
10
- *
11
- * @param key - The key to check (e.g., 'Shift', 'Control', 'A') - can be an accessor function
12
- * @returns Signal accessor that returns true if the key is currently held down
13
- *
14
- * @example
15
- * ```tsx
16
- * function ShiftIndicator() {
17
- * const isShiftHeld = createKeyHold('Shift')
18
- *
19
- * return (
20
- * <div style={{ opacity: isShiftHeld() ? 1 : 0.5 }}>
21
- * {isShiftHeld() ? 'Shift is pressed!' : 'Press Shift'}
22
- * </div>
23
- * )
24
- * }
25
- * ```
26
- *
27
- * @example
28
- * ```tsx
29
- * function ModifierIndicators() {
30
- * const ctrl = createKeyHold('Control')
31
- * const shift = createKeyHold('Shift')
32
- * const alt = createKeyHold('Alt')
33
- *
34
- * return (
35
- * <div>
36
- * <span style={{ opacity: ctrl() ? 1 : 0.3 }}>Ctrl</span>
37
- * <span style={{ opacity: shift() ? 1 : 0.3 }}>Shift</span>
38
- * <span style={{ opacity: alt() ? 1 : 0.3 }}>Alt</span>
39
- * </div>
40
- * )
41
- * }
42
- * ```
43
- */
44
- declare function createKeyHold(key: IndividualKey | (() => IndividualKey)): () => boolean;
45
- //#endregion
46
- export { createKeyHold };
47
- //# sourceMappingURL=createKeyHold.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createKeyHold.js","names":[],"sources":["../src/createKeyHold.ts"],"sourcesContent":["import { createMemo } from 'solid-js'\nimport { useSelector } from '@tanstack/solid-store'\nimport { getKeyStateTracker } from '@tanstack/hotkeys'\nimport type { IndividualKey } from '@tanstack/hotkeys'\n\n/**\n * SolidJS primitive that returns whether a specific key is currently being held.\n *\n * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe\n * to the global KeyStateTracker and uses a selector to determine if the\n * specified key is held.\n *\n * @param key - The key to check (e.g., 'Shift', 'Control', 'A') - can be an accessor function\n * @returns Signal accessor that returns true if the key is currently held down\n *\n * @example\n * ```tsx\n * function ShiftIndicator() {\n * const isShiftHeld = createKeyHold('Shift')\n *\n * return (\n * <div style={{ opacity: isShiftHeld() ? 1 : 0.5 }}>\n * {isShiftHeld() ? 'Shift is pressed!' : 'Press Shift'}\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * function ModifierIndicators() {\n * const ctrl = createKeyHold('Control')\n * const shift = createKeyHold('Shift')\n * const alt = createKeyHold('Alt')\n *\n * return (\n * <div>\n * <span style={{ opacity: ctrl() ? 1 : 0.3 }}>Ctrl</span>\n * <span style={{ opacity: shift() ? 1 : 0.3 }}>Shift</span>\n * <span style={{ opacity: alt() ? 1 : 0.3 }}>Alt</span>\n * </div>\n * )\n * }\n * ```\n */\nexport function createKeyHold(\n key: IndividualKey | (() => IndividualKey),\n): () => boolean {\n const tracker = getKeyStateTracker()\n const heldKeysSelector = useSelector(tracker.store, (state) => state.heldKeys)\n\n return createMemo(() => {\n const resolvedKey = typeof key === 'function' ? key() : key\n const normalizedKey = resolvedKey.toLowerCase()\n return heldKeysSelector().some(\n (heldKey) => heldKey.toLowerCase() === normalizedKey,\n )\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,cACd,KACe;CAEf,MAAM,mBAAmB,YADT,oBAAoB,CACS,QAAQ,UAAU,MAAM,SAAS;AAE9E,QAAO,iBAAiB;EAEtB,MAAM,iBADc,OAAO,QAAQ,aAAa,KAAK,GAAG,KACtB,aAAa;AAC/C,SAAO,kBAAkB,CAAC,MACvB,YAAY,QAAQ,aAAa,KAAK,cACxC;GACD"}
package/dist/index.cjs DELETED
@@ -1,35 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_HotkeysProvider = require('./HotkeysProvider.cjs');
3
- const require_createHotkey = require('./createHotkey.cjs');
4
- const require_createHotkeys = require('./createHotkeys.cjs');
5
- const require_createHeldKeys = require('./createHeldKeys.cjs');
6
- const require_createHeldKeyCodes = require('./createHeldKeyCodes.cjs');
7
- const require_createKeyHold = require('./createKeyHold.cjs');
8
- const require_createHotkeySequence = require('./createHotkeySequence.cjs');
9
- const require_createHotkeySequences = require('./createHotkeySequences.cjs');
10
- const require_createHotkeyRecorder = require('./createHotkeyRecorder.cjs');
11
- const require_createHotkeyRegistrations = require('./createHotkeyRegistrations.cjs');
12
- const require_createHotkeySequenceRecorder = require('./createHotkeySequenceRecorder.cjs');
13
- const require_createHotkeyHint = require('./createHotkeyHint.cjs');
14
-
15
- exports.HotkeysProvider = require_HotkeysProvider.HotkeysProvider;
16
- exports.createHeldKeyCodes = require_createHeldKeyCodes.createHeldKeyCodes;
17
- exports.createHeldKeys = require_createHeldKeys.createHeldKeys;
18
- exports.createHotkey = require_createHotkey.createHotkey;
19
- exports.createHotkeyHint = require_createHotkeyHint.createHotkeyHint;
20
- exports.createHotkeyRecorder = require_createHotkeyRecorder.createHotkeyRecorder;
21
- exports.createHotkeyRegistrations = require_createHotkeyRegistrations.createHotkeyRegistrations;
22
- exports.createHotkeySequence = require_createHotkeySequence.createHotkeySequence;
23
- exports.createHotkeySequenceRecorder = require_createHotkeySequenceRecorder.createHotkeySequenceRecorder;
24
- exports.createHotkeySequences = require_createHotkeySequences.createHotkeySequences;
25
- exports.createHotkeys = require_createHotkeys.createHotkeys;
26
- exports.createKeyHold = require_createKeyHold.createKeyHold;
27
- exports.useDefaultHotkeysOptions = require_HotkeysProvider.useDefaultHotkeysOptions;
28
- exports.useHotkeysContext = require_HotkeysProvider.useHotkeysContext;
29
- var _tanstack_hotkeys = require("@tanstack/hotkeys");
30
- Object.keys(_tanstack_hotkeys).forEach(function (k) {
31
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
32
- enumerable: true,
33
- get: function () { return _tanstack_hotkeys[k]; }
34
- });
35
- });
package/dist/index.d.cts DELETED
@@ -1,14 +0,0 @@
1
- import { CreateHotkeyOptions, createHotkey } from "./createHotkey.cjs";
2
- import { CreateHotkeySequenceOptions, createHotkeySequence } from "./createHotkeySequence.cjs";
3
- import { HotkeysProvider, HotkeysProviderOptions, HotkeysProviderProps, useDefaultHotkeysOptions, useHotkeysContext } from "./HotkeysProvider.cjs";
4
- import { CreateHotkeyDefinition, createHotkeys } from "./createHotkeys.cjs";
5
- import { createHeldKeys } from "./createHeldKeys.cjs";
6
- import { createHeldKeyCodes } from "./createHeldKeyCodes.cjs";
7
- import { createKeyHold } from "./createKeyHold.cjs";
8
- import { CreateHotkeySequenceDefinition, createHotkeySequences } from "./createHotkeySequences.cjs";
9
- import { SolidHotkeyRecorder, createHotkeyRecorder } from "./createHotkeyRecorder.cjs";
10
- import { HotkeyRegistrationsResult, createHotkeyRegistrations } from "./createHotkeyRegistrations.cjs";
11
- import { SolidHotkeySequenceRecorder, createHotkeySequenceRecorder } from "./createHotkeySequenceRecorder.cjs";
12
- import { createHotkeyHint } from "./createHotkeyHint.cjs";
13
- export * from "@tanstack/hotkeys";
14
- export { CreateHotkeyDefinition, CreateHotkeyOptions, CreateHotkeySequenceDefinition, CreateHotkeySequenceOptions, HotkeyRegistrationsResult, HotkeysProvider, HotkeysProviderOptions, HotkeysProviderProps, SolidHotkeyRecorder, SolidHotkeySequenceRecorder, createHeldKeyCodes, createHeldKeys, createHotkey, createHotkeyHint, createHotkeyRecorder, createHotkeyRegistrations, createHotkeySequence, createHotkeySequenceRecorder, createHotkeySequences, createHotkeys, createKeyHold, useDefaultHotkeysOptions, useHotkeysContext };
@@ -1,51 +0,0 @@
1
- import { createContext, useContext } from 'solid-js'
2
- import type { JSX, ParentComponent } from 'solid-js'
3
- import type {
4
- HotkeyRecorderOptions,
5
- HotkeySequenceRecorderOptions,
6
- } from '@tanstack/hotkeys'
7
- import type { CreateHotkeyOptions } from './createHotkey'
8
- import type { CreateHotkeySequenceOptions } from './createHotkeySequence'
9
-
10
- export interface HotkeysProviderOptions {
11
- hotkey?: Partial<CreateHotkeyOptions>
12
- hotkeyRecorder?: Partial<HotkeyRecorderOptions>
13
- hotkeySequenceRecorder?: Partial<HotkeySequenceRecorderOptions>
14
- hotkeySequence?: Partial<CreateHotkeySequenceOptions>
15
- }
16
-
17
- interface HotkeysContextValue {
18
- defaultOptions: HotkeysProviderOptions
19
- }
20
-
21
- const HotkeysContext = createContext<HotkeysContextValue | null>(null)
22
-
23
- export interface HotkeysProviderProps {
24
- children: JSX.Element
25
- defaultOptions?: HotkeysProviderOptions
26
- }
27
-
28
- const DEFAULT_OPTIONS: HotkeysProviderOptions = {}
29
-
30
- export const HotkeysProvider: ParentComponent<HotkeysProviderProps> = (
31
- props,
32
- ) => {
33
- const contextValue: HotkeysContextValue = {
34
- defaultOptions: props.defaultOptions ?? DEFAULT_OPTIONS,
35
- }
36
-
37
- return (
38
- <HotkeysContext.Provider value={contextValue}>
39
- {props.children}
40
- </HotkeysContext.Provider>
41
- )
42
- }
43
-
44
- export function useHotkeysContext() {
45
- return useContext(HotkeysContext)
46
- }
47
-
48
- export function useDefaultHotkeysOptions() {
49
- const context = useContext(HotkeysContext)
50
- return context?.defaultOptions ?? {}
51
- }
@@ -1,38 +0,0 @@
1
- import { useSelector } from '@tanstack/solid-store'
2
- import { getKeyStateTracker } from '@tanstack/hotkeys'
3
-
4
- /**
5
- * SolidJS primitive that returns a signal of a map from currently held key names to their physical `event.code` values.
6
- *
7
- * This is useful for debugging which physical key was pressed (e.g. distinguishing
8
- * left vs right Shift via "ShiftLeft" / "ShiftRight").
9
- *
10
- * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe
11
- * to the global KeyStateTracker.
12
- *
13
- * @returns Signal accessor for record mapping normalized key names to their `event.code` values
14
- *
15
- * @example
16
- * ```tsx
17
- * function KeyDebugDisplay() {
18
- * const heldKeys = createHeldKeys()
19
- * const heldCodes = createHeldKeyCodes()
20
- *
21
- * return (
22
- * <div>
23
- * <For each={heldKeys()}>
24
- * {(key) => (
25
- * <kbd>
26
- * {key} <small>{heldCodes()[key]}</small>
27
- * </kbd>
28
- * )}
29
- * </For>
30
- * </div>
31
- * )
32
- * }
33
- * ```
34
- */
35
- export function createHeldKeyCodes(): () => Record<string, string> {
36
- const tracker = getKeyStateTracker()
37
- return useSelector(tracker.store, (state) => state.heldCodes)
38
- }
@@ -1,29 +0,0 @@
1
- import { useSelector } from '@tanstack/solid-store'
2
- import { getKeyStateTracker } from '@tanstack/hotkeys'
3
-
4
- /**
5
- * SolidJS primitive that returns a signal of currently held keyboard keys.
6
- *
7
- * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe
8
- * to the global KeyStateTracker and updates whenever keys are pressed
9
- * or released.
10
- *
11
- * @returns Signal accessor for array of currently held key names
12
- *
13
- * @example
14
- * ```tsx
15
- * function KeyDisplay() {
16
- * const heldKeys = createHeldKeys()
17
- *
18
- * return (
19
- * <div>
20
- * Currently pressed: {heldKeys().join(' + ') || 'None'}
21
- * </div>
22
- * )
23
- * }
24
- * ```
25
- */
26
- export function createHeldKeys(): () => Array<string> {
27
- const tracker = getKeyStateTracker()
28
- return useSelector(tracker.store, (state) => state.heldKeys)
29
- }
@@ -1,172 +0,0 @@
1
- import { createEffect, onCleanup, untrack } from 'solid-js'
2
- import {
3
- detectPlatform,
4
- getHotkeyManager,
5
- normalizeRegisterableHotkey,
6
- } from '@tanstack/hotkeys'
7
- import { useDefaultHotkeysOptions } from './HotkeysProvider'
8
- import type {
9
- Hotkey,
10
- HotkeyCallback,
11
- HotkeyOptions,
12
- HotkeyRegistrationHandle,
13
- RegisterableHotkey,
14
- } from '@tanstack/hotkeys'
15
-
16
- export interface CreateHotkeyOptions extends Omit<HotkeyOptions, 'target'> {
17
- /**
18
- * The DOM element to attach the event listener to.
19
- * Can be a direct DOM element, an accessor (for reactive targets that become
20
- * available after mount), or null. Defaults to document.
21
- * When using scoped targets, pass an accessor: () => ({ target: elementSignal() })
22
- * so the hotkey waits for the element to be attached before registering.
23
- */
24
- target?: HTMLElement | Document | Window | null
25
- }
26
-
27
- /**
28
- * SolidJS primitive for registering a keyboard hotkey.
29
- *
30
- * Uses the singleton HotkeyManager for efficient event handling.
31
- * The callback receives both the keyboard event and a context object
32
- * containing the hotkey string and parsed hotkey.
33
- *
34
- * This primitive automatically tracks reactive dependencies and updates
35
- * the registration when options or the callback change.
36
- *
37
- * @param hotkey - The hotkey string (e.g., 'Mod+S', 'Escape') or RawHotkey object (supports `mod` for cross-platform)
38
- * @param callback - The function to call when the hotkey is pressed
39
- * @param options - Options for the hotkey behavior
40
- *
41
- * @example
42
- * ```tsx
43
- * function SaveButton() {
44
- * const [count, setCount] = createSignal(0)
45
- *
46
- * // Callback always has access to latest count value
47
- * createHotkey('Mod+S', (event, { hotkey }) => {
48
- * console.log(`Save triggered, count is ${count()}`)
49
- * handleSave()
50
- * })
51
- *
52
- * return <button onClick={() => setCount(c => c + 1)}>Count: {count()}</button>
53
- * }
54
- * ```
55
- *
56
- * @example
57
- * ```tsx
58
- * function Modal(props) {
59
- * // enabled option is reactive
60
- * createHotkey('Escape', () => {
61
- * props.onClose()
62
- * }, () => ({ enabled: props.isOpen }))
63
- *
64
- * return <Show when={props.isOpen}>
65
- * <div class="modal">...</div>
66
- * </Show>
67
- * }
68
- * ```
69
- *
70
- * @example
71
- * ```tsx
72
- * function Editor() {
73
- * const [editorRef, setEditorRef] = createSignal<HTMLDivElement | null>(null)
74
- *
75
- * // Scoped to a specific element - use accessor so hotkey waits for ref
76
- * createHotkey('Mod+S', save, () => ({ target: editorRef() }))
77
- *
78
- * return <div ref={setEditorRef}>...</div>
79
- * }
80
- * ```
81
- */
82
- export function createHotkey(
83
- hotkey: RegisterableHotkey | (() => RegisterableHotkey),
84
- callback: HotkeyCallback,
85
- options: CreateHotkeyOptions | (() => CreateHotkeyOptions) = {},
86
- ): void {
87
- const defaultOptions = useDefaultHotkeysOptions()
88
- const manager = getHotkeyManager()
89
-
90
- let registration: HotkeyRegistrationHandle | null = null
91
- let lastHotkeyString: Hotkey | null = null
92
- let lastTarget: HTMLElement | Document | Window | null = null
93
-
94
- onCleanup(() => {
95
- if (registration?.isActive) {
96
- registration.unregister()
97
- registration = null
98
- }
99
- lastHotkeyString = null
100
- lastTarget = null
101
- })
102
-
103
- createEffect(() => {
104
- // Resolve reactive values
105
- const resolvedHotkey = typeof hotkey === 'function' ? hotkey() : hotkey
106
- const resolvedOptions = typeof options === 'function' ? options() : options
107
-
108
- const mergedOptions = {
109
- ...defaultOptions.hotkey,
110
- ...resolvedOptions,
111
- } as CreateHotkeyOptions
112
-
113
- // Normalize to hotkey string
114
- const platform = mergedOptions.platform ?? detectPlatform()
115
- const hotkeyString = normalizeRegisterableHotkey(resolvedHotkey, platform)
116
-
117
- // Resolve target: when explicitly provided (even as null), use it and skip if null.
118
- // When not provided, default to document. Matches React's ref handling.
119
- const resolvedTarget =
120
- 'target' in mergedOptions
121
- ? (mergedOptions.target ?? null)
122
- : typeof document !== 'undefined'
123
- ? document
124
- : null
125
-
126
- if (!resolvedTarget) {
127
- if (registration?.isActive) {
128
- registration.unregister()
129
- registration = null
130
- }
131
- lastHotkeyString = null
132
- lastTarget = null
133
- return
134
- }
135
-
136
- // Extract options without target (target is handled separately)
137
- const { target: _target, ...optionsWithoutTarget } = mergedOptions
138
-
139
- // Untrack store mutations so that registering/updating the hotkey doesn't
140
- // create a circular reactive dependency when createHotkeyRegistrations
141
- // subscribes to the same store.
142
- untrack(() => {
143
- if (
144
- registration?.isActive &&
145
- lastHotkeyString === hotkeyString &&
146
- lastTarget === resolvedTarget
147
- ) {
148
- registration.callback = callback
149
- registration.setOptions(optionsWithoutTarget)
150
- return
151
- }
152
-
153
- if (registration?.isActive) {
154
- registration.unregister()
155
- registration = null
156
- }
157
-
158
- registration = manager.register(hotkeyString, callback, {
159
- ...optionsWithoutTarget,
160
- target: resolvedTarget,
161
- })
162
-
163
- if (registration.isActive) {
164
- registration.callback = callback
165
- registration.setOptions(optionsWithoutTarget)
166
- }
167
-
168
- lastHotkeyString = hotkeyString
169
- lastTarget = resolvedTarget
170
- })
171
- })
172
- }
@@ -1,28 +0,0 @@
1
- import { createMemo } from 'solid-js'
2
- import { useSelector } from '@tanstack/solid-store'
3
- import { getKeyStateTracker, matchesHeldModifiers } from '@tanstack/hotkeys'
4
- import type { HeldModifierOptions, RegisterableHotkey } from '@tanstack/hotkeys'
5
-
6
- /**
7
- * Returns a boolean accessor indicating whether held modifiers reveal this shortcut.
8
- * Pass accessors to track changing bindings and options.
9
- * Uses the nonempty-subset/AltGr rules of `matchesHeldModifiers`; `exact` requires
10
- * every modifier. Combine with the action's enabled state before showing a badge.
11
- * This helper does not register a shortcut or check whether its target is focused.
12
- */
13
- export function createHotkeyHint(
14
- hotkey: RegisterableHotkey | (() => RegisterableHotkey),
15
- options: HeldModifierOptions | (() => HeldModifierOptions) = {},
16
- ): () => boolean {
17
- const held = useSelector(
18
- getKeyStateTracker().store,
19
- (state) => state.heldKeys,
20
- )
21
- return createMemo(() =>
22
- matchesHeldModifiers(
23
- typeof hotkey === 'function' ? hotkey() : hotkey,
24
- held(),
25
- typeof options === 'function' ? options() : options,
26
- ),
27
- )
28
- }
@@ -1,103 +0,0 @@
1
- import { createEffect, onCleanup } from 'solid-js'
2
- import { useSelector } from '@tanstack/solid-store'
3
- import { HotkeyRecorder } from '@tanstack/hotkeys'
4
- import { useDefaultHotkeysOptions } from './HotkeysProvider'
5
- import type { Hotkey, HotkeyRecorderOptions } from '@tanstack/hotkeys'
6
-
7
- export interface SolidHotkeyRecorder {
8
- /** Whether recording is currently active */
9
- isRecording: () => boolean
10
- /** The currently recorded hotkey (for live preview) */
11
- recordedHotkey: () => Hotkey | null
12
- /** Start recording a new hotkey */
13
- startRecording: () => void
14
- /** Stop recording (same as cancel) */
15
- stopRecording: () => void
16
- /** Cancel recording without saving */
17
- cancelRecording: () => void
18
- }
19
-
20
- /**
21
- * SolidJS primitive for recording keyboard shortcuts.
22
- *
23
- * This primitive provides a thin wrapper around the framework-agnostic `HotkeyRecorder`
24
- * class, managing all the complexity of capturing keyboard events, converting them
25
- * to hotkey strings, and handling edge cases like Escape to cancel or Backspace/Delete
26
- * to clear.
27
- *
28
- * This primitive uses `useSelector` from `@tanstack/solid-store` to subscribe
29
- * to the recorder's store state (same pattern as useHotkeyRecorder in React).
30
- *
31
- * @param options - Configuration options for the recorder (or accessor function)
32
- * @returns An object with recording state signals and control functions
33
- *
34
- * @example
35
- * ```tsx
36
- * function ShortcutSettings() {
37
- * const [shortcut, setShortcut] = createSignal<Hotkey>('Mod+S')
38
- *
39
- * const recorder = createHotkeyRecorder({
40
- * onRecord: (hotkey) => {
41
- * setShortcut(hotkey)
42
- * },
43
- * onCancel: () => {
44
- * console.log('Recording cancelled')
45
- * },
46
- * })
47
- *
48
- * return (
49
- * <div>
50
- * <button onClick={recorder.startRecording}>
51
- * {recorder.isRecording() ? 'Recording...' : 'Edit Shortcut'}
52
- * </button>
53
- * <Show when={recorder.recordedHotkey()}>
54
- * <div>Recording: {recorder.recordedHotkey()}</div>
55
- * </Show>
56
- * </div>
57
- * )
58
- * }
59
- * ```
60
- */
61
- export function createHotkeyRecorder(
62
- options: HotkeyRecorderOptions | (() => HotkeyRecorderOptions),
63
- ): SolidHotkeyRecorder {
64
- const defaultOptions = useDefaultHotkeysOptions()
65
-
66
- const resolvedOptions = typeof options === 'function' ? options() : options
67
- const mergedOptions = {
68
- ...defaultOptions.hotkeyRecorder,
69
- ...resolvedOptions,
70
- } as HotkeyRecorderOptions
71
-
72
- // Create recorder once synchronously (matches React's useRef pattern)
73
- const recorder = new HotkeyRecorder(mergedOptions)
74
-
75
- // Subscribe to recorder state using useSelector (same pattern as useHotkeyRecorder)
76
- const isRecording = useSelector(recorder.store, (state) => state.isRecording)
77
- const recordedHotkey = useSelector(
78
- recorder.store,
79
- (state) => state.recordedHotkey,
80
- )
81
-
82
- // Sync options on every effect run (matches React's sync on render)
83
- createEffect(() => {
84
- const resolved = typeof options === 'function' ? options() : options
85
- recorder.setOptions({
86
- ...defaultOptions.hotkeyRecorder,
87
- ...resolved,
88
- } as HotkeyRecorderOptions)
89
- })
90
-
91
- // Cleanup on unmount
92
- onCleanup(() => {
93
- recorder.destroy()
94
- })
95
-
96
- return {
97
- isRecording,
98
- recordedHotkey,
99
- startRecording: () => recorder.start(),
100
- stopRecording: () => recorder.stop(),
101
- cancelRecording: () => recorder.cancel(),
102
- }
103
- }