@tanstack/lit-hotkeys 0.12.0 → 0.13.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 (93) hide show
  1. package/dist/constants.js +1 -2
  2. package/dist/controllers/held-key-codes.d.ts +2 -5
  3. package/dist/controllers/held-key-codes.js +6 -3
  4. package/dist/controllers/held-keys.d.ts +2 -5
  5. package/dist/controllers/held-keys.js +6 -3
  6. package/dist/controllers/hotkey-hint.d.ts +2 -5
  7. package/dist/controllers/hotkey-hint.js +6 -3
  8. package/dist/controllers/hotkey-recorder.d.ts +2 -5
  9. package/dist/controllers/hotkey-recorder.js +11 -4
  10. package/dist/controllers/hotkey-registrations.d.ts +2 -5
  11. package/dist/controllers/hotkey-registrations.js +6 -4
  12. package/dist/controllers/hotkey-sequence-recorder.d.ts +2 -5
  13. package/dist/controllers/hotkey-sequence-recorder.js +13 -5
  14. package/dist/controllers/hotkey-sequence.d.ts +2 -5
  15. package/dist/controllers/hotkey-sequence.js +7 -2
  16. package/dist/controllers/hotkey.d.ts +2 -5
  17. package/dist/controllers/hotkey.js +7 -2
  18. package/dist/controllers/index.d.ts +2 -1
  19. package/dist/controllers/key-hold.d.ts +2 -5
  20. package/dist/controllers/key-hold.js +7 -3
  21. package/dist/decorators/hotkey-sequence.d.ts +2 -5
  22. package/dist/decorators/hotkey-sequence.js +1 -2
  23. package/dist/decorators/hotkey.d.ts +2 -5
  24. package/dist/decorators/hotkey.js +1 -2
  25. package/dist/decorators/index.d.ts +2 -1
  26. package/dist/index.d.ts +2 -0
  27. package/package.json +9 -14
  28. package/dist/constants.cjs +0 -27
  29. package/dist/constants.cjs.map +0 -1
  30. package/dist/constants.js.map +0 -1
  31. package/dist/controllers/held-key-codes.cjs +0 -61
  32. package/dist/controllers/held-key-codes.cjs.map +0 -1
  33. package/dist/controllers/held-key-codes.d.cts +0 -45
  34. package/dist/controllers/held-key-codes.js.map +0 -1
  35. package/dist/controllers/held-keys.cjs +0 -58
  36. package/dist/controllers/held-keys.cjs.map +0 -1
  37. package/dist/controllers/held-keys.d.cts +0 -44
  38. package/dist/controllers/held-keys.js.map +0 -1
  39. package/dist/controllers/hotkey-hint.cjs +0 -47
  40. package/dist/controllers/hotkey-hint.cjs.map +0 -1
  41. package/dist/controllers/hotkey-hint.d.cts +0 -27
  42. package/dist/controllers/hotkey-hint.js.map +0 -1
  43. package/dist/controllers/hotkey-recorder.cjs +0 -104
  44. package/dist/controllers/hotkey-recorder.cjs.map +0 -1
  45. package/dist/controllers/hotkey-recorder.d.cts +0 -75
  46. package/dist/controllers/hotkey-recorder.js.map +0 -1
  47. package/dist/controllers/hotkey-registrations.cjs +0 -70
  48. package/dist/controllers/hotkey-registrations.cjs.map +0 -1
  49. package/dist/controllers/hotkey-registrations.d.cts +0 -44
  50. package/dist/controllers/hotkey-registrations.js.map +0 -1
  51. package/dist/controllers/hotkey-sequence-recorder.cjs +0 -117
  52. package/dist/controllers/hotkey-sequence-recorder.cjs.map +0 -1
  53. package/dist/controllers/hotkey-sequence-recorder.d.cts +0 -83
  54. package/dist/controllers/hotkey-sequence-recorder.js.map +0 -1
  55. package/dist/controllers/hotkey-sequence.cjs +0 -58
  56. package/dist/controllers/hotkey-sequence.cjs.map +0 -1
  57. package/dist/controllers/hotkey-sequence.d.cts +0 -45
  58. package/dist/controllers/hotkey-sequence.js.map +0 -1
  59. package/dist/controllers/hotkey.cjs +0 -60
  60. package/dist/controllers/hotkey.cjs.map +0 -1
  61. package/dist/controllers/hotkey.d.cts +0 -45
  62. package/dist/controllers/hotkey.js.map +0 -1
  63. package/dist/controllers/index.d.cts +0 -9
  64. package/dist/controllers/key-hold.cjs +0 -78
  65. package/dist/controllers/key-hold.cjs.map +0 -1
  66. package/dist/controllers/key-hold.d.cts +0 -62
  67. package/dist/controllers/key-hold.js.map +0 -1
  68. package/dist/decorators/hotkey-sequence.cjs +0 -45
  69. package/dist/decorators/hotkey-sequence.cjs.map +0 -1
  70. package/dist/decorators/hotkey-sequence.d.cts +0 -28
  71. package/dist/decorators/hotkey-sequence.js.map +0 -1
  72. package/dist/decorators/hotkey.cjs +0 -44
  73. package/dist/decorators/hotkey.cjs.map +0 -1
  74. package/dist/decorators/hotkey.d.cts +0 -27
  75. package/dist/decorators/hotkey.js.map +0 -1
  76. package/dist/decorators/index.d.cts +0 -2
  77. package/dist/index.cjs +0 -31
  78. package/dist/index.d.cts +0 -13
  79. package/src/constants.ts +0 -23
  80. package/src/controllers/held-key-codes.ts +0 -67
  81. package/src/controllers/held-keys.ts +0 -64
  82. package/src/controllers/hotkey-hint.ts +0 -56
  83. package/src/controllers/hotkey-recorder.ts +0 -120
  84. package/src/controllers/hotkey-registrations.ts +0 -89
  85. package/src/controllers/hotkey-sequence-recorder.ts +0 -141
  86. package/src/controllers/hotkey-sequence.ts +0 -82
  87. package/src/controllers/hotkey.ts +0 -96
  88. package/src/controllers/index.ts +0 -9
  89. package/src/controllers/key-hold.ts +0 -88
  90. package/src/decorators/hotkey-sequence.ts +0 -68
  91. package/src/decorators/hotkey.ts +0 -70
  92. package/src/decorators/index.ts +0 -2
  93. package/src/index.ts +0 -6
@@ -1,89 +0,0 @@
1
- import {
2
- getHotkeyManager,
3
- getSequenceManager,
4
- toHotkeyRegistrationView,
5
- } from '@tanstack/hotkeys'
6
- import type {
7
- HotkeyRegistrationView,
8
- SequenceRegistrationView,
9
- } from '@tanstack/hotkeys'
10
- import type { ReactiveController, ReactiveControllerHost } from 'lit'
11
-
12
- /**
13
- * A Lit ReactiveController that tracks all hotkey and sequence registrations.
14
- *
15
- * Subscribes to the singleton HotkeyManager and SequenceManager stores and
16
- * triggers host updates whenever registrations change.
17
- *
18
- * @example
19
- * ```ts
20
- * class ShortcutPalette extends LitElement {
21
- * private registrations = new HotkeyRegistrationsController(this)
22
- *
23
- * render() {
24
- * return html`
25
- * <ul>
26
- * ${this.registrations.hotkeys.map(
27
- * (reg) => html`<li>${reg.options.meta?.name ?? reg.hotkey}</li>`,
28
- * )}
29
- * </ul>
30
- * `
31
- * }
32
- * }
33
- * ```
34
- */
35
- export class HotkeyRegistrationsController implements ReactiveController {
36
- private _unsubscribeHotkeys: (() => void) | undefined
37
- private _unsubscribeSequences: (() => void) | undefined
38
- private _hotkeys: Array<HotkeyRegistrationView> = []
39
- private _sequences: Array<SequenceRegistrationView> = []
40
-
41
- /** All registered hotkeys (public view, no callbacks). */
42
- public get hotkeys(): Array<HotkeyRegistrationView> {
43
- return this._hotkeys
44
- }
45
-
46
- /** All registered sequences. */
47
- public get sequences(): Array<SequenceRegistrationView> {
48
- return this._sequences
49
- }
50
-
51
- constructor(private _host: ReactiveControllerHost) {
52
- this._host.addController(this)
53
- }
54
-
55
- public hostConnected(): void {
56
- const hotkeyManager = getHotkeyManager()
57
- const sequenceManager = getSequenceManager()
58
-
59
- const hotkeysSub = hotkeyManager.registrations.subscribe(() => {
60
- this._hotkeys = Array.from(
61
- hotkeyManager.registrations.state.values(),
62
- ).map(toHotkeyRegistrationView)
63
- this._host.requestUpdate()
64
- })
65
-
66
- const sequencesSub = sequenceManager.registrations.subscribe(() => {
67
- this._sequences = Array.from(sequenceManager.registrations.state.values())
68
- this._host.requestUpdate()
69
- })
70
-
71
- this._unsubscribeHotkeys = () => hotkeysSub.unsubscribe()
72
- this._unsubscribeSequences = () => sequencesSub.unsubscribe()
73
-
74
- // Sync initial state
75
- this._hotkeys = Array.from(hotkeyManager.registrations.state.values()).map(
76
- toHotkeyRegistrationView,
77
- )
78
- this._sequences = Array.from(sequenceManager.registrations.state.values())
79
- }
80
-
81
- public hostDisconnected(): void {
82
- this._unsubscribeHotkeys?.()
83
- this._unsubscribeSequences?.()
84
- this._unsubscribeHotkeys = undefined
85
- this._unsubscribeSequences = undefined
86
- this._hotkeys = []
87
- this._sequences = []
88
- }
89
- }
@@ -1,141 +0,0 @@
1
- import { HotkeySequenceRecorder } from '@tanstack/hotkeys'
2
- import type { ReactiveController, ReactiveControllerHost } from 'lit'
3
- import type {
4
- HotkeySequence,
5
- HotkeySequenceRecorderOptions,
6
- } from '@tanstack/hotkeys'
7
-
8
- /**
9
- * A Lit ReactiveController that records multi-chord sequences (Vim-style shortcuts).
10
- *
11
- * Wraps the framework-agnostic `HotkeySequenceRecorder` class, managing store
12
- * subscriptions and host update lifecycle automatically.
13
- *
14
- * @example
15
- * ```ts
16
- * class ShortcutSettings extends LitElement {
17
- * private recorder = new HotkeySequenceRecorderController(this, {
18
- * onRecord: (sequence) => {
19
- * this.sequence = sequence
20
- * this.requestUpdate()
21
- * },
22
- * onCancel: () => {
23
- * console.log('Recording cancelled')
24
- * },
25
- * })
26
- *
27
- * private sequence: HotkeySequence | null = null
28
- *
29
- * render() {
30
- * return html`
31
- * <button @click=${() => this.recorder.startRecording()}>
32
- * ${this.recorder.isRecording ? 'Recording...' : 'Edit Sequence'}
33
- * </button>
34
- * ${this.recorder.steps.length
35
- * ? html`<div>Steps: ${this.recorder.steps.join(' → ')}</div>`
36
- * : nothing}
37
- * ${this.recorder.recordedSequence
38
- * ? html`<div>Recorded: ${this.recorder.recordedSequence.join(' → ')}</div>`
39
- * : nothing}
40
- * `
41
- * }
42
- * }
43
- * ```
44
- */
45
- export class HotkeySequenceRecorderController implements ReactiveController {
46
- /** The recorder instance. */
47
- private _recorder: HotkeySequenceRecorder
48
- /** The unsubscribe function. */
49
- private _unsubscribe: (() => void) | undefined
50
- /** Whether recording is currently active. */
51
- private _isRecording = false
52
- /** Chords captured in the current session. */
53
- private _steps: HotkeySequence = []
54
- /** Last committed sequence, or null if none. */
55
- private _recordedSequence: HotkeySequence | null = null
56
-
57
- /** Whether recording is currently active. */
58
- public get isRecording(): boolean {
59
- return this._isRecording
60
- }
61
-
62
- /** Chords captured in the current session. */
63
- public get steps(): HotkeySequence {
64
- return this._steps
65
- }
66
-
67
- /** Last committed sequence, or null if none. */
68
- public get recordedSequence(): HotkeySequence | null {
69
- return this._recordedSequence
70
- }
71
-
72
- /**
73
- * @param _host - The Lit component that owns this controller.
74
- * @param _options - Configuration options for the sequence recorder.
75
- */
76
- constructor(
77
- private _host: ReactiveControllerHost,
78
- private _options: HotkeySequenceRecorderOptions,
79
- ) {
80
- this._recorder = new HotkeySequenceRecorder(_options)
81
- this._host.addController(this)
82
- }
83
-
84
- /** Subscribes to the recorder store and updates internal state when changes occur. */
85
- public hostConnected(): void {
86
- const subscription = this._recorder.store.subscribe(() => {
87
- const { isRecording, steps, recordedSequence } =
88
- this._recorder.store.state
89
-
90
- const hasChanged: boolean =
91
- isRecording !== this._isRecording ||
92
- steps !== this._steps ||
93
- recordedSequence !== this._recordedSequence
94
-
95
- if (hasChanged) {
96
- this._isRecording = isRecording
97
- this._steps = steps
98
- this._recordedSequence = recordedSequence
99
- this._host.requestUpdate()
100
- }
101
- })
102
-
103
- this._unsubscribe = () => subscription.unsubscribe()
104
- }
105
-
106
- /** Unsubscribes from the recorder store and destroys the recorder instance to prevent memory leaks. */
107
- public hostDisconnected(): void {
108
- this._unsubscribe?.()
109
- this._unsubscribe = undefined
110
- this._recorder.stop()
111
- this._isRecording = false
112
- this._steps = []
113
- this._recordedSequence = null
114
- }
115
-
116
- /** Updates the recorder options. */
117
- public setOptions(options: Partial<HotkeySequenceRecorderOptions>): void {
118
- this._options = { ...this._options, ...options }
119
- this._recorder.setOptions(this._options)
120
- }
121
-
122
- /** Start recording a new sequence. */
123
- public startRecording(): void {
124
- this._recorder.start()
125
- }
126
-
127
- /** Stop recording (same as cancel but without calling onCancel). */
128
- public stopRecording(): void {
129
- this._recorder.stop()
130
- }
131
-
132
- /** Cancel recording without saving. */
133
- public cancelRecording(): void {
134
- this._recorder.cancel()
135
- }
136
-
137
- /** Commit current steps as a sequence (no-op if empty). */
138
- public commitRecording(): void {
139
- this._recorder.commit()
140
- }
141
- }
@@ -1,82 +0,0 @@
1
- import { getSequenceManager } from '@tanstack/hotkeys'
2
- import { HOTKEY_SEQUENCE_DEFAULT_OPTIONS } from '../constants'
3
- import type { ReactiveController, ReactiveControllerHost } from 'lit'
4
- import type {
5
- HotkeyCallback,
6
- HotkeySequence,
7
- SequenceManager,
8
- SequenceOptions,
9
- SequenceRegistrationHandle,
10
- } from '@tanstack/hotkeys'
11
-
12
- /**
13
- * A Lit ReactiveController that registers a keyboard sequence (e.g. Vim-style)
14
- * when the host element is connected and unregisters it when the host is disconnected.
15
- *
16
- * @example
17
- * ```ts
18
- * class MyElement extends LitElement {
19
- * private seq = new HotkeySequenceController(this, ['G', 'G'], () => this.goToTop())
20
- *
21
- * constructor() {
22
- * super()
23
- * this.addController(this.seq)
24
- * }
25
- * }
26
- * ```
27
- */
28
- export class HotkeySequenceController implements ReactiveController {
29
- /** The sequence registration handle. */
30
- private _registration: SequenceRegistrationHandle | undefined
31
-
32
- /**
33
- * @param _host - The Lit component that owns this controller (use `this` and pass it to `addController()`).
34
- * @param _sequence - The key sequence to listen for (e.g. `['G', 'G']`).
35
- * @param _callback - Function to run when the sequence is completed; called with the host as `this`.
36
- * @param _options - Optional sequence options (target, timeout, enabled, etc.).
37
- */
38
- constructor(
39
- private _host: ReactiveControllerHost,
40
- private _sequence: HotkeySequence,
41
- private _callback: HotkeyCallback,
42
- private _options: SequenceOptions = HOTKEY_SEQUENCE_DEFAULT_OPTIONS,
43
- ) {}
44
-
45
- /**
46
- * Registers the sequence with the global sequence manager when the host is connected to the DOM.
47
- * Skips registration if disabled, sequence is empty, or no target is available.
48
- */
49
- public hostConnected(): void {
50
- const { target: _target, ...optionsWithoutTarget } = this._options
51
-
52
- const manager: SequenceManager = getSequenceManager()
53
-
54
- const hasExplicitTarget = 'target' in this._options
55
- const resolvedTarget = hasExplicitTarget
56
- ? (this._options.target ?? null)
57
- : typeof document !== 'undefined'
58
- ? document
59
- : null
60
-
61
- if (!resolvedTarget) {
62
- return
63
- }
64
-
65
- const boundCallback: HotkeyCallback = this._callback.bind(
66
- this._host as unknown as object,
67
- )
68
-
69
- this._registration = manager.register(this._sequence, boundCallback, {
70
- ...optionsWithoutTarget,
71
- target: resolvedTarget,
72
- })
73
- }
74
-
75
- /** Unregisters the sequence when the host is disconnected from the DOM. */
76
- public hostDisconnected(): void {
77
- if (this._registration?.isActive) {
78
- this._registration.unregister()
79
- }
80
- this._registration = undefined
81
- }
82
- }
@@ -1,96 +0,0 @@
1
- import {
2
- detectPlatform,
3
- formatHotkey,
4
- getHotkeyManager,
5
- rawHotkeyToParsedHotkey,
6
- } from '@tanstack/hotkeys'
7
- import { HOTKEY_DEFAULT_OPTIONS } from '../constants'
8
- import type { ReactiveController, ReactiveControllerHost } from 'lit'
9
- import type {
10
- Hotkey,
11
- HotkeyCallback,
12
- HotkeyManager,
13
- HotkeyOptions,
14
- HotkeyRegistrationHandle,
15
- RegisterableHotkey,
16
- } from '@tanstack/hotkeys'
17
-
18
- /**
19
- * A Lit ReactiveController that registers a keyboard hotkey when the host
20
- * element is connected and unregisters it when the host is disconnected.
21
- *
22
- * @example
23
- * ```ts
24
- * class MyElement extends LitElement {
25
- * private hotkey = new HotkeyController(this, 'Mod+S', () => this.save())
26
- *
27
- * constructor() {
28
- * super()
29
- * this.addController(this.hotkey)
30
- * }
31
- * }
32
- * ```
33
- */
34
- export class HotkeyController implements ReactiveController {
35
- /** The hotkey registration handle. */
36
- private _registration: HotkeyRegistrationHandle | undefined
37
-
38
- /**
39
- * @param _host - The Lit component that owns this controller (use `this` and pass it to `addController()`).
40
- * @param _hotkey - The key or key combo to listen for (e.g. `'Mod+S'` or a raw hotkey object).
41
- * @param _callback - Function to run when the hotkey is pressed; called with the host as `this`.
42
- * @param _options - Optional registration options (target, platform, enabled, etc.).
43
- */
44
- constructor(
45
- private _host: ReactiveControllerHost,
46
- private _hotkey: RegisterableHotkey,
47
- private _callback: HotkeyCallback,
48
- private _options: HotkeyOptions = HOTKEY_DEFAULT_OPTIONS,
49
- ) {}
50
-
51
- /**
52
- * Registers the hotkey with the global manager when the host is connected to the DOM.
53
- * Skips registration if no target is available (e.g. no document or options.target is null).
54
- */
55
- public hostConnected(): void {
56
- const manager: HotkeyManager = getHotkeyManager()
57
-
58
- const platform = this._options.platform ?? detectPlatform()
59
- const hotkeyString: Hotkey =
60
- typeof this._hotkey === 'string'
61
- ? this._hotkey
62
- : (formatHotkey(
63
- rawHotkeyToParsedHotkey(this._hotkey, platform),
64
- ) as Hotkey)
65
-
66
- const hasExplicitTarget = 'target' in this._options
67
- const resolvedTarget = hasExplicitTarget
68
- ? (this._options.target ?? null)
69
- : typeof document !== 'undefined'
70
- ? document
71
- : null
72
-
73
- if (!resolvedTarget) {
74
- return
75
- }
76
-
77
- const { target: _target, ...optionsWithoutTarget } = this._options
78
-
79
- const boundCallback: HotkeyCallback = this._callback.bind(
80
- this._host as unknown as object,
81
- )
82
-
83
- this._registration = manager.register(hotkeyString, boundCallback, {
84
- ...optionsWithoutTarget,
85
- target: resolvedTarget,
86
- })
87
- }
88
-
89
- /** Unregisters the hotkey when the host is disconnected from the DOM. */
90
- public hostDisconnected(): void {
91
- if (this._registration?.isActive) {
92
- this._registration.unregister()
93
- }
94
- this._registration = undefined
95
- }
96
- }
@@ -1,9 +0,0 @@
1
- export * from './held-key-codes'
2
- export * from './held-keys'
3
- export * from './hotkey'
4
- export * from './hotkey-recorder'
5
- export * from './hotkey-registrations'
6
- export * from './hotkey-sequence'
7
- export * from './hotkey-sequence-recorder'
8
- export * from './key-hold'
9
- export * from './hotkey-hint'
@@ -1,88 +0,0 @@
1
- import { getKeyStateTracker } from '@tanstack/hotkeys'
2
- import type { ReactiveController, ReactiveControllerHost } from 'lit'
3
- import type { IndividualKey, KeyStateTracker } from '@tanstack/hotkeys'
4
-
5
- /**
6
- * A Lit ReactiveController that tracks whether a specific key is currently held.
7
- *
8
- * Subscribes to the global KeyStateTracker and triggers host updates
9
- * when the held state of the specified key changes.
10
- *
11
- * @example
12
- * ```ts
13
- * class MyElement extends LitElement {
14
- * private shiftHold = new KeyHoldController(this, 'Shift')
15
- *
16
- * render() {
17
- * return html`
18
- * <div style="opacity: ${this.shiftHold.value ? 1 : 0.5}">
19
- * ${this.shiftHold.value ? 'Shift is pressed!' : 'Press Shift'}
20
- * </div>
21
- * `
22
- * }
23
- * }
24
- * ```
25
- *
26
- * @example
27
- * ```ts
28
- * class ModifierIndicators extends LitElement {
29
- * private ctrl = new KeyHoldController(this, 'Control')
30
- * private shift = new KeyHoldController(this, 'Shift')
31
- * private alt = new KeyHoldController(this, 'Alt')
32
- *
33
- * render() {
34
- * return html`
35
- * <span style="opacity: ${this.ctrl.value ? 1 : 0.3}">Ctrl</span>
36
- * <span style="opacity: ${this.shift.value ? 1 : 0.3}">Shift</span>
37
- * <span style="opacity: ${this.alt.value ? 1 : 0.3}">Alt</span>
38
- * `
39
- * }
40
- * }
41
- * ```
42
- */
43
- export class KeyHoldController implements ReactiveController {
44
- /** The unsubscribe function to unsubscribe from the tracker store. */
45
- private _unsubscribe: (() => void) | undefined
46
- /** Whether the tracked key is currently held down. */
47
- private _value = false
48
-
49
- /** Whether the tracked key is currently held down. */
50
- public get value(): boolean {
51
- return this._value
52
- }
53
-
54
- /**
55
- * @param host - The Lit component that owns this controller.
56
- * @param key - The key to track (e.g. 'Shift', 'Control', 'A').
57
- */
58
- constructor(
59
- private _host: ReactiveControllerHost,
60
- private _key: IndividualKey,
61
- ) {
62
- this._host.addController(this)
63
- }
64
-
65
- public hostConnected(): void {
66
- const tracker: KeyStateTracker = getKeyStateTracker()
67
- const normalizedKey: string = this._key.toLowerCase()
68
-
69
- const subscription = tracker.store.subscribe(() => {
70
- const isHeld: boolean = tracker.store.state.heldKeys.some(
71
- (heldKey: string) => heldKey.toLowerCase() === normalizedKey,
72
- )
73
-
74
- if (isHeld !== this._value) {
75
- this._value = isHeld
76
- this._host.requestUpdate()
77
- }
78
- })
79
-
80
- this._unsubscribe = () => subscription.unsubscribe()
81
- }
82
-
83
- public hostDisconnected(): void {
84
- this._unsubscribe?.()
85
- this._unsubscribe = undefined
86
- this._value = false
87
- }
88
- }
@@ -1,68 +0,0 @@
1
- import { HotkeySequenceController } from '../controllers/hotkey-sequence'
2
- import { HOTKEY_SEQUENCE_DEFAULT_OPTIONS } from '../constants'
3
- import type { LitElement } from 'lit'
4
- import type {
5
- HotkeyCallback,
6
- HotkeySequence,
7
- SequenceOptions,
8
- } from '@tanstack/hotkeys'
9
-
10
- /**
11
- * Decorator that registers a keyboard sequence (e.g. Vim-style) on the element
12
- * when it connects and unregisters when it disconnects. Uses
13
- * {@link HotkeySequenceController} under the hood.
14
- *
15
- * @param sequence - The key sequence to listen for (e.g. `['G', 'G']` for "g g").
16
- * @param options - Optional sequence options (target, timeout, enabled, etc.).
17
- * @returns A method decorator for use on LitElement methods.
18
- *
19
- * @example
20
- * ```ts
21
- * class MyElement extends LitElement {
22
- * @hotkeySequence(['G', 'G'])
23
- * goToTop() { window.scrollTo(0, 0) }
24
- *
25
- * @hotkeySequence(['D', 'D'], { timeout: 500 })
26
- * deleteLine() { this.deleteCurrentLine() }
27
- * }
28
- * ```
29
- */
30
- export function hotkeySequence(
31
- sequence: HotkeySequence,
32
- options: SequenceOptions = HOTKEY_SEQUENCE_DEFAULT_OPTIONS,
33
- ) {
34
- return function <T extends HotkeyCallback>(
35
- proto: LitElement,
36
- methodName: string,
37
- descriptor: TypedPropertyDescriptor<T>,
38
- ) {
39
- const originalConnected = proto.connectedCallback
40
- const controllerKey = Symbol(`@hotkeySequence:${methodName}`)
41
-
42
- proto.connectedCallback = function () {
43
- originalConnected.call(this)
44
-
45
- const host = this as unknown as {
46
- [key: symbol]: HotkeySequenceController | undefined
47
- addController: (c: unknown) => void
48
- [key: string]: unknown
49
- }
50
- if (!host[controllerKey]) {
51
- const callback: HotkeyCallback = descriptor.value
52
- ? descriptor.value.bind(this)
53
- : (host[methodName] as HotkeyCallback).bind(this)
54
-
55
- if (typeof callback !== 'function') {
56
- throw new Error(
57
- `@hotkeySequence decorator can only be applied to functions`,
58
- )
59
- }
60
-
61
- const controller: HotkeySequenceController =
62
- new HotkeySequenceController(this, sequence, callback, options)
63
- host[controllerKey] = controller
64
- this.addController(controller)
65
- }
66
- }
67
- }
68
- }
@@ -1,70 +0,0 @@
1
- import { HotkeyController } from '../controllers/hotkey'
2
- import { HOTKEY_DEFAULT_OPTIONS } from '../constants'
3
- import type { LitElement } from 'lit'
4
- import type {
5
- HotkeyCallback,
6
- HotkeyOptions,
7
- RegisterableHotkey,
8
- } from '@tanstack/hotkeys'
9
-
10
- /**
11
- * Decorator that registers a keyboard hotkey on the element when it connects
12
- * and unregisters when it disconnects. Uses {@link HotkeyController} under the hood.
13
- *
14
- * @param hotkey - The key or key combo to listen for (e.g. `'Mod+S'` or a raw hotkey object).
15
- * @param options - Optional registration options (target, platform, enabled, etc.).
16
- * @returns A method decorator for use on LitElement methods.
17
- *
18
- * @example
19
- * ```ts
20
- * class MyElement extends LitElement {
21
- * @hotkey('Mod+S')
22
- * save() { this.doSave() }
23
- *
24
- * @hotkey('Escape')
25
- * close() { this.dismiss() }
26
- * }
27
- * ```
28
- */
29
- export function hotkey(
30
- hotkey: RegisterableHotkey,
31
- options: HotkeyOptions = HOTKEY_DEFAULT_OPTIONS,
32
- ) {
33
- return function <T extends HotkeyCallback>(
34
- proto: LitElement,
35
- propertyKey: string,
36
- descriptor?: TypedPropertyDescriptor<T>,
37
- ) {
38
- const originalConnected = proto.connectedCallback
39
- const controllerKey = Symbol(`@hotkey:${propertyKey}`)
40
-
41
- proto.connectedCallback = function () {
42
- originalConnected.call(this)
43
-
44
- const host = this as unknown as {
45
- [key: symbol]: HotkeyController | undefined
46
- addController: (c: unknown) => void
47
- [key: string]: unknown
48
- }
49
-
50
- if (!host[controllerKey]) {
51
- const callback: HotkeyCallback = descriptor?.value
52
- ? (descriptor.value.bind(this) as HotkeyCallback)
53
- : (host[propertyKey] as HotkeyCallback)
54
-
55
- if (typeof callback !== 'function') {
56
- throw new Error(`@hotkey decorator can only be applied to functions`)
57
- }
58
-
59
- const controller: HotkeyController = new HotkeyController(
60
- this,
61
- hotkey,
62
- callback,
63
- options,
64
- )
65
- host[controllerKey] = controller
66
- this.addController(controller)
67
- }
68
- }
69
- }
70
- }
@@ -1,2 +0,0 @@
1
- export * from './hotkey-sequence'
2
- export * from './hotkey'
package/src/index.ts DELETED
@@ -1,6 +0,0 @@
1
- // Re-export everything from the core package
2
- export * from '@tanstack/hotkeys'
3
-
4
- // Lit-specific exports
5
- export * from './decorators'
6
- export * from './controllers'