@tanstack/lit-hotkeys 0.13.1 → 0.15.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/README.md +3 -0
- package/dist/controllers/_app-hotkeys.js +11 -0
- package/dist/controllers/app-hotkeys.d.ts +48 -0
- package/dist/controllers/app-hotkeys.js +84 -0
- package/dist/controllers/hotkey-hint.d.ts +2 -2
- package/dist/controllers/hotkey-hint.js +13 -5
- package/dist/controllers/hotkey-recorder.d.ts +22 -9
- package/dist/controllers/hotkey-recorder.js +28 -15
- package/dist/controllers/hotkey-registrations.d.ts +11 -18
- package/dist/controllers/hotkey-registrations.js +19 -37
- package/dist/controllers/hotkey.d.ts +44 -18
- package/dist/controllers/hotkey.js +44 -35
- package/dist/controllers/index.d.ts +3 -4
- package/dist/controllers/key-hold.d.ts +2 -2
- package/dist/controllers/key-hold.js +2 -2
- package/dist/decorators/hotkey.d.ts +11 -7
- package/dist/decorators/hotkey.js +1 -21
- package/dist/decorators/index.d.ts +1 -2
- package/dist/index.d.ts +3 -5
- package/dist/index.js +2 -4
- package/package.json +2 -2
- package/dist/constants.js +0 -24
- package/dist/controllers/hotkey-sequence-recorder.d.ts +0 -80
- package/dist/controllers/hotkey-sequence-recorder.js +0 -125
- package/dist/controllers/hotkey-sequence.d.ts +0 -42
- package/dist/controllers/hotkey-sequence.js +0 -63
- package/dist/decorators/hotkey-sequence.d.ts +0 -25
- package/dist/decorators/hotkey-sequence.js +0 -44
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { getAppHotkeysStore, subscribeAppHotkeys } from "./_app-hotkeys.js";
|
|
2
|
+
import { createHotkeyBindings, prepareHotkeyDefinitions } from "@tanstack/hotkeys/adapter";
|
|
3
3
|
|
|
4
4
|
//#region src/controllers/hotkey.ts
|
|
5
5
|
/**
|
|
6
|
-
* A Lit ReactiveController that registers a
|
|
7
|
-
*
|
|
6
|
+
* A Lit ReactiveController that registers a hotkey when the host element is
|
|
7
|
+
* connected and unregisters it when the host is disconnected. The hotkey can
|
|
8
|
+
* be a chord such as `'Mod+S'`, a sequence such as `['G', 'G']`, or an app
|
|
9
|
+
* hotkey from `defineAppHotkeys`, which uses its custom hotkey from
|
|
10
|
+
* `provideAppHotkeys`.
|
|
11
|
+
*
|
|
12
|
+
* Chords accept `requireReset`; sequences accept `timeout`. Pass a getter for
|
|
13
|
+
* the hotkey or options to re-read them after each host update.
|
|
8
14
|
*
|
|
9
15
|
* @example
|
|
10
16
|
* ```ts
|
|
11
17
|
* class MyElement extends LitElement {
|
|
12
|
-
* private
|
|
18
|
+
* private save = new HotkeyController(this, 'Mod+S', () => this.doSave())
|
|
19
|
+
* private top = new HotkeyController(this, ['G', 'G'], () => this.scrollToTop())
|
|
13
20
|
*
|
|
14
21
|
* constructor() {
|
|
15
22
|
* super()
|
|
16
|
-
* this.addController(this.
|
|
23
|
+
* this.addController(this.save)
|
|
24
|
+
* this.addController(this.top)
|
|
17
25
|
* }
|
|
18
26
|
* }
|
|
19
27
|
* ```
|
|
@@ -21,43 +29,44 @@ import { detectPlatform, formatHotkey, getHotkeyManager, rawHotkeyToParsedHotkey
|
|
|
21
29
|
var HotkeyController = class {
|
|
22
30
|
_host;
|
|
23
31
|
_hotkey;
|
|
24
|
-
_callback;
|
|
25
32
|
_options;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* @param _callback - Function to run when the hotkey is pressed; called with the host as `this`.
|
|
32
|
-
* @param _options - Optional registration options (target, platform, enabled, etc.).
|
|
33
|
-
*/
|
|
34
|
-
constructor(_host, _hotkey, _callback, _options = HOTKEY_DEFAULT_OPTIONS) {
|
|
33
|
+
_bindings = createHotkeyBindings();
|
|
34
|
+
_connected = false;
|
|
35
|
+
_boundCallback;
|
|
36
|
+
_unsubscribe;
|
|
37
|
+
constructor(_host, _hotkey, callback, _options = {}) {
|
|
35
38
|
this._host = _host;
|
|
36
39
|
this._hotkey = _hotkey;
|
|
37
|
-
this._callback = _callback;
|
|
38
40
|
this._options = _options;
|
|
41
|
+
this._boundCallback = callback.bind(this._host);
|
|
39
42
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Registers the hotkey with the global manager when the host is connected to the DOM.
|
|
42
|
-
* Skips registration if no target is available (e.g. no document or options.target is null).
|
|
43
|
-
*/
|
|
43
|
+
/** Registers when connected and a target is available. */
|
|
44
44
|
hostConnected() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
this._connected = true;
|
|
46
|
+
this._unsubscribe = subscribeAppHotkeys(() => this._sync());
|
|
47
|
+
this._sync();
|
|
48
|
+
}
|
|
49
|
+
/** Refreshes options after rendering, when scoped targets are available. */
|
|
50
|
+
hostUpdated() {
|
|
51
|
+
if (this._connected) this._sync();
|
|
52
|
+
}
|
|
53
|
+
_sync() {
|
|
54
|
+
const options = typeof this._options === "function" ? this._options() : this._options;
|
|
55
|
+
this._bindings.update(prepareHotkeyDefinitions([{
|
|
56
|
+
hotkey: typeof this._hotkey === "function" ? this._hotkey() : this._hotkey,
|
|
57
|
+
callback: this._boundCallback,
|
|
58
|
+
options
|
|
59
|
+
}], {
|
|
60
|
+
appHotkeysStore: getAppHotkeysStore(),
|
|
61
|
+
resolveTarget: (target) => target
|
|
62
|
+
}));
|
|
56
63
|
}
|
|
57
|
-
/**
|
|
64
|
+
/** Releases registrations when the host disconnects. */
|
|
58
65
|
hostDisconnected() {
|
|
59
|
-
|
|
60
|
-
this.
|
|
66
|
+
this._connected = false;
|
|
67
|
+
this._unsubscribe?.();
|
|
68
|
+
this._unsubscribe = void 0;
|
|
69
|
+
this._bindings.destroy();
|
|
61
70
|
}
|
|
62
71
|
};
|
|
63
72
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import { AppHotkeyControllerOptions, HotkeyController, HotkeyControllerChordOptions, HotkeyControllerCommonOptions, HotkeyControllerOptions, HotkeyControllerOptionsFor, HotkeyControllerSequenceOptions, HotkeyControllerTarget } from "./hotkey.js";
|
|
2
|
+
import { AppHotkeysController } from "./app-hotkeys.js";
|
|
1
3
|
import { HeldKeyCodesController } from "./held-key-codes.js";
|
|
2
4
|
import { HeldKeysController } from "./held-keys.js";
|
|
3
|
-
import { HotkeyController } from "./hotkey.js";
|
|
4
5
|
import { HotkeyRecorderController } from "./hotkey-recorder.js";
|
|
5
6
|
import { HotkeyRegistrationsController } from "./hotkey-registrations.js";
|
|
6
|
-
import { HotkeySequenceController } from "./hotkey-sequence.js";
|
|
7
|
-
import { HotkeySequenceRecorderController } from "./hotkey-sequence-recorder.js";
|
|
8
7
|
import { KeyHoldController } from "./key-hold.js";
|
|
9
8
|
import { HotkeyHintController } from "./hotkey-hint.js";
|
|
10
|
-
export { HeldKeyCodesController, HeldKeysController, HotkeyController,
|
|
9
|
+
export { AppHotkeyControllerOptions, AppHotkeysController, HeldKeyCodesController, HeldKeysController, HotkeyController, HotkeyControllerChordOptions, HotkeyControllerCommonOptions, HotkeyControllerOptions, HotkeyControllerOptionsFor, HotkeyControllerSequenceOptions, HotkeyControllerTarget, HotkeyHintController, HotkeyRecorderController, HotkeyRegistrationsController, KeyHoldController };
|
|
@@ -49,8 +49,8 @@ export declare class KeyHoldController implements ReactiveController {
|
|
|
49
49
|
/** Whether the tracked key is currently held down. */
|
|
50
50
|
get value(): boolean;
|
|
51
51
|
/**
|
|
52
|
-
* @param
|
|
53
|
-
* @param
|
|
52
|
+
* @param _host - The Lit component that owns this controller.
|
|
53
|
+
* @param _key - The key to track (e.g. 'Shift', 'Control', 'A').
|
|
54
54
|
*/
|
|
55
55
|
constructor(_host: ReactiveControllerHost, _key: IndividualKey);
|
|
56
56
|
hostConnected(): void;
|
|
@@ -51,8 +51,8 @@ var KeyHoldController = class {
|
|
|
51
51
|
return this._value;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* @param
|
|
55
|
-
* @param
|
|
54
|
+
* @param _host - The Lit component that owns this controller.
|
|
55
|
+
* @param _key - The key to track (e.g. 'Shift', 'Control', 'A').
|
|
56
56
|
*/
|
|
57
57
|
constructor(_host, _key) {
|
|
58
58
|
this._host = _host;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AppHotkeyControllerOptions, HotkeyControllerOptionsFor } from "../controllers/hotkey.js";
|
|
2
|
+
import { AppHotkey, HotkeyCallback, RegisterableHotkey } from "@tanstack/hotkeys";
|
|
2
3
|
import { LitElement } from "lit";
|
|
3
4
|
//#region src/decorators/hotkey.d.ts
|
|
5
|
+
type HotkeyDecorator = <T extends HotkeyCallback>(proto: LitElement, propertyKey: string, descriptor?: TypedPropertyDescriptor<T>) => void;
|
|
4
6
|
/**
|
|
5
|
-
* Decorator that registers a
|
|
6
|
-
*
|
|
7
|
+
* Decorator that registers a hotkey on the element when it connects and
|
|
8
|
+
* unregisters when it disconnects: a chord such as `'Mod+S'`, a sequence such
|
|
9
|
+
* as `['G', 'G']`, or an app hotkey. Uses {@link HotkeyController} under the hood.
|
|
7
10
|
*
|
|
8
|
-
* @param hotkey - The
|
|
11
|
+
* @param hotkey - The chord, sequence, or app hotkey to listen for.
|
|
9
12
|
* @param options - Optional registration options (target, platform, enabled, etc.).
|
|
10
13
|
* @returns A method decorator for use on LitElement methods.
|
|
11
14
|
*
|
|
@@ -15,10 +18,11 @@ import { LitElement } from "lit";
|
|
|
15
18
|
* @hotkey('Mod+S')
|
|
16
19
|
* save() { this.doSave() }
|
|
17
20
|
*
|
|
18
|
-
* @hotkey('
|
|
19
|
-
*
|
|
21
|
+
* @hotkey(['G', 'G'], { timeout: 500 })
|
|
22
|
+
* goToTop() { window.scrollTo(0, 0) }
|
|
20
23
|
* }
|
|
21
24
|
* ```
|
|
22
25
|
*/
|
|
23
|
-
export declare function hotkey
|
|
26
|
+
export declare function hotkey<T extends AppHotkey>(hotkey: T, options?: AppHotkeyControllerOptions<T>): HotkeyDecorator;
|
|
27
|
+
export declare function hotkey<T extends RegisterableHotkey>(hotkey: T, options?: HotkeyControllerOptionsFor<T>): HotkeyDecorator;
|
|
24
28
|
//#endregion
|
|
@@ -1,27 +1,7 @@
|
|
|
1
|
-
import { HOTKEY_DEFAULT_OPTIONS } from "../constants.js";
|
|
2
1
|
import { HotkeyController } from "../controllers/hotkey.js";
|
|
3
2
|
|
|
4
3
|
//#region src/decorators/hotkey.ts
|
|
5
|
-
|
|
6
|
-
* Decorator that registers a keyboard hotkey on the element when it connects
|
|
7
|
-
* and unregisters when it disconnects. Uses {@link HotkeyController} under the hood.
|
|
8
|
-
*
|
|
9
|
-
* @param hotkey - The key or key combo to listen for (e.g. `'Mod+S'` or a raw hotkey object).
|
|
10
|
-
* @param options - Optional registration options (target, platform, enabled, etc.).
|
|
11
|
-
* @returns A method decorator for use on LitElement methods.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* class MyElement extends LitElement {
|
|
16
|
-
* @hotkey('Mod+S')
|
|
17
|
-
* save() { this.doSave() }
|
|
18
|
-
*
|
|
19
|
-
* @hotkey('Escape')
|
|
20
|
-
* close() { this.dismiss() }
|
|
21
|
-
* }
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
function hotkey(hotkey, options = HOTKEY_DEFAULT_OPTIONS) {
|
|
4
|
+
function hotkey(hotkey, options = {}) {
|
|
25
5
|
return function(proto, propertyKey, descriptor) {
|
|
26
6
|
const originalConnected = proto.connectedCallback;
|
|
27
7
|
const controllerKey = Symbol(`@hotkey:${propertyKey}`);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AppHotkeyControllerOptions, HotkeyController, HotkeyControllerChordOptions, HotkeyControllerCommonOptions, HotkeyControllerOptions, HotkeyControllerOptionsFor, HotkeyControllerSequenceOptions, HotkeyControllerTarget } from "./controllers/hotkey.js";
|
|
2
2
|
import { hotkey } from "./decorators/hotkey.js";
|
|
3
3
|
import "./decorators/index.js";
|
|
4
|
+
import { AppHotkeysController } from "./controllers/app-hotkeys.js";
|
|
4
5
|
import { HeldKeyCodesController } from "./controllers/held-key-codes.js";
|
|
5
6
|
import { HeldKeysController } from "./controllers/held-keys.js";
|
|
6
|
-
import { HotkeyController } from "./controllers/hotkey.js";
|
|
7
7
|
import { HotkeyRecorderController } from "./controllers/hotkey-recorder.js";
|
|
8
8
|
import { HotkeyRegistrationsController } from "./controllers/hotkey-registrations.js";
|
|
9
|
-
import { HotkeySequenceController } from "./controllers/hotkey-sequence.js";
|
|
10
|
-
import { HotkeySequenceRecorderController } from "./controllers/hotkey-sequence-recorder.js";
|
|
11
9
|
import { KeyHoldController } from "./controllers/key-hold.js";
|
|
12
10
|
import { HotkeyHintController } from "./controllers/hotkey-hint.js";
|
|
13
11
|
import "./controllers/index.js";
|
|
14
12
|
export * from "@tanstack/hotkeys";
|
|
15
|
-
export { HeldKeyCodesController, HeldKeysController, HotkeyController,
|
|
13
|
+
export { AppHotkeyControllerOptions, AppHotkeysController, HeldKeyCodesController, HeldKeysController, HotkeyController, HotkeyControllerChordOptions, HotkeyControllerCommonOptions, HotkeyControllerOptions, HotkeyControllerOptionsFor, HotkeyControllerSequenceOptions, HotkeyControllerTarget, HotkeyHintController, HotkeyRecorderController, HotkeyRegistrationsController, KeyHoldController, hotkey };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { HotkeySequenceController } from "./controllers/hotkey-sequence.js";
|
|
2
|
-
import { hotkeySequence } from "./decorators/hotkey-sequence.js";
|
|
3
1
|
import { HotkeyController } from "./controllers/hotkey.js";
|
|
4
2
|
import { hotkey } from "./decorators/hotkey.js";
|
|
3
|
+
import { AppHotkeysController } from "./controllers/app-hotkeys.js";
|
|
5
4
|
import { HeldKeyCodesController } from "./controllers/held-key-codes.js";
|
|
6
5
|
import { HeldKeysController } from "./controllers/held-keys.js";
|
|
7
6
|
import { HotkeyRecorderController } from "./controllers/hotkey-recorder.js";
|
|
8
7
|
import { HotkeyRegistrationsController } from "./controllers/hotkey-registrations.js";
|
|
9
|
-
import { HotkeySequenceRecorderController } from "./controllers/hotkey-sequence-recorder.js";
|
|
10
8
|
import { KeyHoldController } from "./controllers/key-hold.js";
|
|
11
9
|
import { HotkeyHintController } from "./controllers/hotkey-hint.js";
|
|
12
10
|
|
|
13
11
|
export * from "@tanstack/hotkeys"
|
|
14
12
|
|
|
15
|
-
export { HeldKeyCodesController, HeldKeysController, HotkeyController, HotkeyHintController, HotkeyRecorderController, HotkeyRegistrationsController,
|
|
13
|
+
export { AppHotkeysController, HeldKeyCodesController, HeldKeysController, HotkeyController, HotkeyHintController, HotkeyRecorderController, HotkeyRegistrationsController, KeyHoldController, hotkey };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/lit-hotkeys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Lit 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
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"lit": "^3.3.3"
|
package/dist/constants.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region src/constants.ts
|
|
2
|
-
const HOTKEY_DEFAULT_OPTIONS = {
|
|
3
|
-
enabled: true,
|
|
4
|
-
preventDefault: true,
|
|
5
|
-
stopPropagation: true,
|
|
6
|
-
eventType: "keydown",
|
|
7
|
-
requireReset: false,
|
|
8
|
-
ignoreInputs: void 0,
|
|
9
|
-
platform: void 0,
|
|
10
|
-
conflictBehavior: "warn"
|
|
11
|
-
};
|
|
12
|
-
const HOTKEY_SEQUENCE_DEFAULT_OPTIONS = {
|
|
13
|
-
enabled: true,
|
|
14
|
-
timeout: 1e3,
|
|
15
|
-
preventDefault: true,
|
|
16
|
-
stopPropagation: true,
|
|
17
|
-
eventType: "keydown",
|
|
18
|
-
ignoreInputs: void 0,
|
|
19
|
-
platform: void 0,
|
|
20
|
-
conflictBehavior: "warn"
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
export { HOTKEY_DEFAULT_OPTIONS, HOTKEY_SEQUENCE_DEFAULT_OPTIONS };
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { HotkeySequence, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { ReactiveController, ReactiveControllerHost } from "lit";
|
|
3
|
-
//#region src/controllers/hotkey-sequence-recorder.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* A Lit ReactiveController that records multi-chord sequences (Vim-style shortcuts).
|
|
6
|
-
*
|
|
7
|
-
* Wraps the framework-agnostic `HotkeySequenceRecorder` class, managing store
|
|
8
|
-
* subscriptions and host update lifecycle automatically.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* class ShortcutSettings extends LitElement {
|
|
13
|
-
* private recorder = new HotkeySequenceRecorderController(this, {
|
|
14
|
-
* onRecord: (sequence) => {
|
|
15
|
-
* this.sequence = sequence
|
|
16
|
-
* this.requestUpdate()
|
|
17
|
-
* },
|
|
18
|
-
* onCancel: () => {
|
|
19
|
-
* console.log('Recording cancelled')
|
|
20
|
-
* },
|
|
21
|
-
* })
|
|
22
|
-
*
|
|
23
|
-
* private sequence: HotkeySequence | null = null
|
|
24
|
-
*
|
|
25
|
-
* render() {
|
|
26
|
-
* return html`
|
|
27
|
-
* <button @click=${() => this.recorder.startRecording()}>
|
|
28
|
-
* ${this.recorder.isRecording ? 'Recording...' : 'Edit Sequence'}
|
|
29
|
-
* </button>
|
|
30
|
-
* ${this.recorder.steps.length
|
|
31
|
-
* ? html`<div>Steps: ${this.recorder.steps.join(' → ')}</div>`
|
|
32
|
-
* : nothing}
|
|
33
|
-
* ${this.recorder.recordedSequence
|
|
34
|
-
* ? html`<div>Recorded: ${this.recorder.recordedSequence.join(' → ')}</div>`
|
|
35
|
-
* : nothing}
|
|
36
|
-
* `
|
|
37
|
-
* }
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
export declare class HotkeySequenceRecorderController implements ReactiveController {
|
|
42
|
-
private _host;
|
|
43
|
-
private _options;
|
|
44
|
-
/** The recorder instance. */
|
|
45
|
-
private _recorder;
|
|
46
|
-
/** The unsubscribe function. */
|
|
47
|
-
private _unsubscribe;
|
|
48
|
-
/** Whether recording is currently active. */
|
|
49
|
-
private _isRecording;
|
|
50
|
-
/** Chords captured in the current session. */
|
|
51
|
-
private _steps;
|
|
52
|
-
/** Last committed sequence, or null if none. */
|
|
53
|
-
private _recordedSequence;
|
|
54
|
-
/** Whether recording is currently active. */
|
|
55
|
-
get isRecording(): boolean;
|
|
56
|
-
/** Chords captured in the current session. */
|
|
57
|
-
get steps(): HotkeySequence;
|
|
58
|
-
/** Last committed sequence, or null if none. */
|
|
59
|
-
get recordedSequence(): HotkeySequence | null;
|
|
60
|
-
/**
|
|
61
|
-
* @param _host - The Lit component that owns this controller.
|
|
62
|
-
* @param _options - Configuration options for the sequence recorder.
|
|
63
|
-
*/
|
|
64
|
-
constructor(_host: ReactiveControllerHost, _options: HotkeySequenceRecorderOptions);
|
|
65
|
-
/** Subscribes to the recorder store and updates internal state when changes occur. */
|
|
66
|
-
hostConnected(): void;
|
|
67
|
-
/** Unsubscribes from the recorder store and destroys the recorder instance to prevent memory leaks. */
|
|
68
|
-
hostDisconnected(): void;
|
|
69
|
-
/** Updates the recorder options. */
|
|
70
|
-
setOptions(options: Partial<HotkeySequenceRecorderOptions>): void;
|
|
71
|
-
/** Start recording a new sequence. */
|
|
72
|
-
startRecording(): void;
|
|
73
|
-
/** Stop recording (same as cancel but without calling onCancel). */
|
|
74
|
-
stopRecording(): void;
|
|
75
|
-
/** Cancel recording without saving. */
|
|
76
|
-
cancelRecording(): void;
|
|
77
|
-
/** Commit current steps as a sequence (no-op if empty). */
|
|
78
|
-
commitRecording(): void;
|
|
79
|
-
}
|
|
80
|
-
//#endregion
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { HotkeySequenceRecorder } from "@tanstack/hotkeys";
|
|
2
|
-
|
|
3
|
-
//#region src/controllers/hotkey-sequence-recorder.ts
|
|
4
|
-
/**
|
|
5
|
-
* A Lit ReactiveController that records multi-chord sequences (Vim-style shortcuts).
|
|
6
|
-
*
|
|
7
|
-
* Wraps the framework-agnostic `HotkeySequenceRecorder` class, managing store
|
|
8
|
-
* subscriptions and host update lifecycle automatically.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* class ShortcutSettings extends LitElement {
|
|
13
|
-
* private recorder = new HotkeySequenceRecorderController(this, {
|
|
14
|
-
* onRecord: (sequence) => {
|
|
15
|
-
* this.sequence = sequence
|
|
16
|
-
* this.requestUpdate()
|
|
17
|
-
* },
|
|
18
|
-
* onCancel: () => {
|
|
19
|
-
* console.log('Recording cancelled')
|
|
20
|
-
* },
|
|
21
|
-
* })
|
|
22
|
-
*
|
|
23
|
-
* private sequence: HotkeySequence | null = null
|
|
24
|
-
*
|
|
25
|
-
* render() {
|
|
26
|
-
* return html`
|
|
27
|
-
* <button @click=${() => this.recorder.startRecording()}>
|
|
28
|
-
* ${this.recorder.isRecording ? 'Recording...' : 'Edit Sequence'}
|
|
29
|
-
* </button>
|
|
30
|
-
* ${this.recorder.steps.length
|
|
31
|
-
* ? html`<div>Steps: ${this.recorder.steps.join(' → ')}</div>`
|
|
32
|
-
* : nothing}
|
|
33
|
-
* ${this.recorder.recordedSequence
|
|
34
|
-
* ? html`<div>Recorded: ${this.recorder.recordedSequence.join(' → ')}</div>`
|
|
35
|
-
* : nothing}
|
|
36
|
-
* `
|
|
37
|
-
* }
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
var HotkeySequenceRecorderController = class {
|
|
42
|
-
_host;
|
|
43
|
-
_options;
|
|
44
|
-
/** The recorder instance. */
|
|
45
|
-
_recorder;
|
|
46
|
-
/** The unsubscribe function. */
|
|
47
|
-
_unsubscribe;
|
|
48
|
-
/** Whether recording is currently active. */
|
|
49
|
-
_isRecording = false;
|
|
50
|
-
/** Chords captured in the current session. */
|
|
51
|
-
_steps = [];
|
|
52
|
-
/** Last committed sequence, or null if none. */
|
|
53
|
-
_recordedSequence = null;
|
|
54
|
-
/** Whether recording is currently active. */
|
|
55
|
-
get isRecording() {
|
|
56
|
-
return this._isRecording;
|
|
57
|
-
}
|
|
58
|
-
/** Chords captured in the current session. */
|
|
59
|
-
get steps() {
|
|
60
|
-
return this._steps;
|
|
61
|
-
}
|
|
62
|
-
/** Last committed sequence, or null if none. */
|
|
63
|
-
get recordedSequence() {
|
|
64
|
-
return this._recordedSequence;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* @param _host - The Lit component that owns this controller.
|
|
68
|
-
* @param _options - Configuration options for the sequence recorder.
|
|
69
|
-
*/
|
|
70
|
-
constructor(_host, _options) {
|
|
71
|
-
this._host = _host;
|
|
72
|
-
this._options = _options;
|
|
73
|
-
this._recorder = new HotkeySequenceRecorder(_options);
|
|
74
|
-
this._host.addController(this);
|
|
75
|
-
}
|
|
76
|
-
/** Subscribes to the recorder store and updates internal state when changes occur. */
|
|
77
|
-
hostConnected() {
|
|
78
|
-
const subscription = this._recorder.store.subscribe(() => {
|
|
79
|
-
const { isRecording, steps, recordedSequence } = this._recorder.store.state;
|
|
80
|
-
if (isRecording !== this._isRecording || steps !== this._steps || recordedSequence !== this._recordedSequence) {
|
|
81
|
-
this._isRecording = isRecording;
|
|
82
|
-
this._steps = steps;
|
|
83
|
-
this._recordedSequence = recordedSequence;
|
|
84
|
-
this._host.requestUpdate();
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
this._unsubscribe = () => subscription.unsubscribe();
|
|
88
|
-
}
|
|
89
|
-
/** Unsubscribes from the recorder store and destroys the recorder instance to prevent memory leaks. */
|
|
90
|
-
hostDisconnected() {
|
|
91
|
-
this._unsubscribe?.();
|
|
92
|
-
this._unsubscribe = void 0;
|
|
93
|
-
this._recorder.stop();
|
|
94
|
-
this._isRecording = false;
|
|
95
|
-
this._steps = [];
|
|
96
|
-
this._recordedSequence = null;
|
|
97
|
-
}
|
|
98
|
-
/** Updates the recorder options. */
|
|
99
|
-
setOptions(options) {
|
|
100
|
-
this._options = {
|
|
101
|
-
...this._options,
|
|
102
|
-
...options
|
|
103
|
-
};
|
|
104
|
-
this._recorder.setOptions(this._options);
|
|
105
|
-
}
|
|
106
|
-
/** Start recording a new sequence. */
|
|
107
|
-
startRecording() {
|
|
108
|
-
this._recorder.start();
|
|
109
|
-
}
|
|
110
|
-
/** Stop recording (same as cancel but without calling onCancel). */
|
|
111
|
-
stopRecording() {
|
|
112
|
-
this._recorder.stop();
|
|
113
|
-
}
|
|
114
|
-
/** Cancel recording without saving. */
|
|
115
|
-
cancelRecording() {
|
|
116
|
-
this._recorder.cancel();
|
|
117
|
-
}
|
|
118
|
-
/** Commit current steps as a sequence (no-op if empty). */
|
|
119
|
-
commitRecording() {
|
|
120
|
-
this._recorder.commit();
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
//#endregion
|
|
125
|
-
export { HotkeySequenceRecorderController };
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { HotkeyCallback, HotkeySequence, SequenceOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { ReactiveController, ReactiveControllerHost } from "lit";
|
|
3
|
-
//#region src/controllers/hotkey-sequence.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* A Lit ReactiveController that registers a keyboard sequence (e.g. Vim-style)
|
|
6
|
-
* when the host element is connected and unregisters it when the host is disconnected.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* class MyElement extends LitElement {
|
|
11
|
-
* private seq = new HotkeySequenceController(this, ['G', 'G'], () => this.goToTop())
|
|
12
|
-
*
|
|
13
|
-
* constructor() {
|
|
14
|
-
* super()
|
|
15
|
-
* this.addController(this.seq)
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
export declare class HotkeySequenceController implements ReactiveController {
|
|
21
|
-
private _host;
|
|
22
|
-
private _sequence;
|
|
23
|
-
private _callback;
|
|
24
|
-
private _options;
|
|
25
|
-
/** The sequence registration handle. */
|
|
26
|
-
private _registration;
|
|
27
|
-
/**
|
|
28
|
-
* @param _host - The Lit component that owns this controller (use `this` and pass it to `addController()`).
|
|
29
|
-
* @param _sequence - The key sequence to listen for (e.g. `['G', 'G']`).
|
|
30
|
-
* @param _callback - Function to run when the sequence is completed; called with the host as `this`.
|
|
31
|
-
* @param _options - Optional sequence options (target, timeout, enabled, etc.).
|
|
32
|
-
*/
|
|
33
|
-
constructor(_host: ReactiveControllerHost, _sequence: HotkeySequence, _callback: HotkeyCallback, _options?: SequenceOptions);
|
|
34
|
-
/**
|
|
35
|
-
* Registers the sequence with the global sequence manager when the host is connected to the DOM.
|
|
36
|
-
* Skips registration if disabled, sequence is empty, or no target is available.
|
|
37
|
-
*/
|
|
38
|
-
hostConnected(): void;
|
|
39
|
-
/** Unregisters the sequence when the host is disconnected from the DOM. */
|
|
40
|
-
hostDisconnected(): void;
|
|
41
|
-
}
|
|
42
|
-
//#endregion
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { HOTKEY_SEQUENCE_DEFAULT_OPTIONS } from "../constants.js";
|
|
2
|
-
import { getSequenceManager } from "@tanstack/hotkeys";
|
|
3
|
-
|
|
4
|
-
//#region src/controllers/hotkey-sequence.ts
|
|
5
|
-
/**
|
|
6
|
-
* A Lit ReactiveController that registers a keyboard sequence (e.g. Vim-style)
|
|
7
|
-
* when the host element is connected and unregisters it when the host is disconnected.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```ts
|
|
11
|
-
* class MyElement extends LitElement {
|
|
12
|
-
* private seq = new HotkeySequenceController(this, ['G', 'G'], () => this.goToTop())
|
|
13
|
-
*
|
|
14
|
-
* constructor() {
|
|
15
|
-
* super()
|
|
16
|
-
* this.addController(this.seq)
|
|
17
|
-
* }
|
|
18
|
-
* }
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
var HotkeySequenceController = class {
|
|
22
|
-
_host;
|
|
23
|
-
_sequence;
|
|
24
|
-
_callback;
|
|
25
|
-
_options;
|
|
26
|
-
/** The sequence registration handle. */
|
|
27
|
-
_registration;
|
|
28
|
-
/**
|
|
29
|
-
* @param _host - The Lit component that owns this controller (use `this` and pass it to `addController()`).
|
|
30
|
-
* @param _sequence - The key sequence to listen for (e.g. `['G', 'G']`).
|
|
31
|
-
* @param _callback - Function to run when the sequence is completed; called with the host as `this`.
|
|
32
|
-
* @param _options - Optional sequence options (target, timeout, enabled, etc.).
|
|
33
|
-
*/
|
|
34
|
-
constructor(_host, _sequence, _callback, _options = HOTKEY_SEQUENCE_DEFAULT_OPTIONS) {
|
|
35
|
-
this._host = _host;
|
|
36
|
-
this._sequence = _sequence;
|
|
37
|
-
this._callback = _callback;
|
|
38
|
-
this._options = _options;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Registers the sequence with the global sequence manager when the host is connected to the DOM.
|
|
42
|
-
* Skips registration if disabled, sequence is empty, or no target is available.
|
|
43
|
-
*/
|
|
44
|
-
hostConnected() {
|
|
45
|
-
const { target: _target, ...optionsWithoutTarget } = this._options;
|
|
46
|
-
const manager = getSequenceManager();
|
|
47
|
-
const resolvedTarget = "target" in this._options ? this._options.target ?? null : typeof document !== "undefined" ? document : null;
|
|
48
|
-
if (!resolvedTarget) return;
|
|
49
|
-
const boundCallback = this._callback.bind(this._host);
|
|
50
|
-
this._registration = manager.register(this._sequence, boundCallback, {
|
|
51
|
-
...optionsWithoutTarget,
|
|
52
|
-
target: resolvedTarget
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
/** Unregisters the sequence when the host is disconnected from the DOM. */
|
|
56
|
-
hostDisconnected() {
|
|
57
|
-
if (this._registration?.isActive) this._registration.unregister();
|
|
58
|
-
this._registration = void 0;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
//#endregion
|
|
63
|
-
export { HotkeySequenceController };
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { HotkeyCallback, HotkeySequence, SequenceOptions } from "@tanstack/hotkeys";
|
|
2
|
-
import { LitElement } from "lit";
|
|
3
|
-
//#region src/decorators/hotkey-sequence.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Decorator that registers a keyboard sequence (e.g. Vim-style) on the element
|
|
6
|
-
* when it connects and unregisters when it disconnects. Uses
|
|
7
|
-
* {@link HotkeySequenceController} under the hood.
|
|
8
|
-
*
|
|
9
|
-
* @param sequence - The key sequence to listen for (e.g. `['G', 'G']` for "g g").
|
|
10
|
-
* @param options - Optional sequence options (target, timeout, enabled, etc.).
|
|
11
|
-
* @returns A method decorator for use on LitElement methods.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* class MyElement extends LitElement {
|
|
16
|
-
* @hotkeySequence(['G', 'G'])
|
|
17
|
-
* goToTop() { window.scrollTo(0, 0) }
|
|
18
|
-
*
|
|
19
|
-
* @hotkeySequence(['D', 'D'], { timeout: 500 })
|
|
20
|
-
* deleteLine() { this.deleteCurrentLine() }
|
|
21
|
-
* }
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export declare function hotkeySequence(sequence: HotkeySequence, options?: SequenceOptions): <T extends HotkeyCallback>(proto: LitElement, methodName: string, descriptor: TypedPropertyDescriptor<T>) => void;
|
|
25
|
-
//#endregion
|