@tanstack/alpine-hotkeys 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/createHotkeyRecorder.d.ts +15 -0
- package/dist/createHotkeyRecorder.js +6 -3
- package/dist/createHotkeys.js +11 -6
- package/dist/createHotkeysScope.js +4 -4
- package/dist/hotkeyRecorderPlugin.d.ts +9 -0
- package/dist/hotkeyRecorderPlugin.js +29 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/scope.d.ts +4 -0
- package/dist/scope.js +24 -2
- package/dist/types.d.ts +2 -4
- package/package.json +2 -2
- package/skills/alpine-hotkeys/SKILL.md +12 -7
- package/skills/alpine-hotkeys/references/app-hotkeys.md +7 -3
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AlpineHotkeyRecorder, AlpineHotkeys } from "./types.js";
|
|
2
|
+
import "./scope.js";
|
|
3
|
+
import { HotkeyChord, HotkeyChordRecorderOptions, HotkeyRecorderOptions, HotkeySequenceRecorderOptions } from "@tanstack/hotkeys";
|
|
4
|
+
//#region src/createHotkeyRecorder.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates a recorder owned by a `createHotkeysScope` owner. It uses the
|
|
7
|
+
* owner's `hotkeyRecorder` defaults, and options can follow Alpine state.
|
|
8
|
+
* `maxSteps` (default 1) selects chords or sequences.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createHotkeyRecorder(owner: AlpineHotkeys, options: HotkeyChordRecorderOptions): AlpineHotkeyRecorder<HotkeyChord>;
|
|
11
|
+
export declare function createHotkeyRecorder(owner: AlpineHotkeys, options: HotkeySequenceRecorderOptions): AlpineHotkeyRecorder;
|
|
12
|
+
export declare function createHotkeyRecorder(owner: AlpineHotkeys, options: () => HotkeySequenceRecorderOptions): AlpineHotkeyRecorder;
|
|
13
|
+
export declare function createHotkeyRecorder(owner: AlpineHotkeys, options: () => HotkeyChordRecorderOptions): AlpineHotkeyRecorder<HotkeyChord>;
|
|
14
|
+
export declare function createHotkeyRecorder(owner: AlpineHotkeys, options: () => HotkeyRecorderOptions): AlpineHotkeyRecorder;
|
|
15
|
+
//#endregion
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { read } from "./scope.js";
|
|
1
|
+
import { read, scopeOf } from "./scope.js";
|
|
2
2
|
import { HotkeyRecorder } from "@tanstack/hotkeys";
|
|
3
3
|
import { withDefaults } from "@tanstack/hotkeys/adapter";
|
|
4
4
|
|
|
5
5
|
//#region src/createHotkeyRecorder.ts
|
|
6
|
-
function createHotkeyRecorder(
|
|
6
|
+
function createHotkeyRecorder(owner, options) {
|
|
7
|
+
return createRecorder(scopeOf(owner), options);
|
|
8
|
+
}
|
|
9
|
+
function createRecorder(scope, options) {
|
|
7
10
|
scope.assertActive();
|
|
8
11
|
const instance = new HotkeyRecorder(() => withDefaults(scope.defaultOptions().hotkeyRecorder, read(options)));
|
|
9
12
|
const state = scope.select(instance.store, (value) => value);
|
|
@@ -28,4 +31,4 @@ function createHotkeyRecorder(scope, options) {
|
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
//#endregion
|
|
31
|
-
export { createHotkeyRecorder };
|
|
34
|
+
export { createHotkeyRecorder, createRecorder };
|
package/dist/createHotkeys.js
CHANGED
|
@@ -6,12 +6,17 @@ function createHotkeys(scope, definitions, options = {}) {
|
|
|
6
6
|
scope.assertActive();
|
|
7
7
|
const bindings = createHotkeyBindings();
|
|
8
8
|
scope.addCleanup(bindings.destroy);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
try {
|
|
10
|
+
scope.effect(() => bindings.update(prepareHotkeyDefinitions(read(definitions), {
|
|
11
|
+
appHotkeysStore: scope.appHotkeys(),
|
|
12
|
+
defaults: scope.defaultOptions().hotkey,
|
|
13
|
+
commonOptions: read(options),
|
|
14
|
+
resolveTarget: (target) => target
|
|
15
|
+
})));
|
|
16
|
+
} catch (error) {
|
|
17
|
+
bindings.destroy();
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createScope } from "./scope.js";
|
|
1
|
+
import { createScope, ownerScopes } from "./scope.js";
|
|
2
2
|
import { createHotkeys } from "./createHotkeys.js";
|
|
3
3
|
import { createHotkey } from "./createHotkey.js";
|
|
4
4
|
import { createHeldKeys } from "./createHeldKeys.js";
|
|
@@ -7,7 +7,6 @@ import { createKeyHold } from "./createKeyHold.js";
|
|
|
7
7
|
import { createHotkeyHint } from "./createHotkeyHint.js";
|
|
8
8
|
import { createHotkeyRegistrations } from "./createHotkeyRegistrations.js";
|
|
9
9
|
import { createHotkeyScopesState } from "./createHotkeyScopesState.js";
|
|
10
|
-
import { createHotkeyRecorder } from "./createHotkeyRecorder.js";
|
|
11
10
|
import { createAppHotkeyList, createAppHotkeys, createCustomHotkeys } from "./createAppHotkeys.js";
|
|
12
11
|
|
|
13
12
|
//#region src/createHotkeysScope.ts
|
|
@@ -18,7 +17,7 @@ import { createAppHotkeyList, createAppHotkeys, createCustomHotkeys } from "./cr
|
|
|
18
17
|
*/
|
|
19
18
|
function createHotkeysScope(defaultOptions = {}) {
|
|
20
19
|
const scope = createScope(defaultOptions);
|
|
21
|
-
|
|
20
|
+
const owner = {
|
|
22
21
|
createHotkey: (...args) => createHotkey(scope, ...args),
|
|
23
22
|
createHotkeys: (...args) => createHotkeys(scope, ...args),
|
|
24
23
|
createHeldKeys: (...args) => createHeldKeys(scope, ...args),
|
|
@@ -27,12 +26,13 @@ function createHotkeysScope(defaultOptions = {}) {
|
|
|
27
26
|
createHotkeyHint: (...args) => createHotkeyHint(scope, ...args),
|
|
28
27
|
createHotkeyRegistrations: (...args) => createHotkeyRegistrations(scope, ...args),
|
|
29
28
|
createHotkeyScopesState: () => createHotkeyScopesState(scope),
|
|
30
|
-
createHotkeyRecorder: ((options) => createHotkeyRecorder(scope, options)),
|
|
31
29
|
createAppHotkeys: () => createAppHotkeys(scope),
|
|
32
30
|
createAppHotkeyList: () => createAppHotkeyList(scope),
|
|
33
31
|
createCustomHotkeys: () => createCustomHotkeys(scope),
|
|
34
32
|
destroy: scope.destroy
|
|
35
33
|
};
|
|
34
|
+
ownerScopes.set(owner, scope);
|
|
35
|
+
return owner;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
//#endregion
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import Alpine from "alpinejs";
|
|
2
|
+
//#region src/hotkeyRecorderPlugin.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Installs $hotkeyRecorder, a function that creates recorders owned by its
|
|
5
|
+
* element. It is separate from `hotkeysPlugin`, so apps that don't record
|
|
6
|
+
* hotkeys don't ship the recorder.
|
|
7
|
+
*/
|
|
8
|
+
export declare function hotkeyRecorderPlugin(alpine: typeof Alpine): void;
|
|
9
|
+
//#endregion
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createScope, setAlpine } from "./scope.js";
|
|
2
|
+
import { createRecorder } from "./createHotkeyRecorder.js";
|
|
3
|
+
|
|
4
|
+
//#region src/hotkeyRecorderPlugin.ts
|
|
5
|
+
/**
|
|
6
|
+
* Installs $hotkeyRecorder, a function that creates recorders owned by its
|
|
7
|
+
* element. It is separate from `hotkeysPlugin`, so apps that don't record
|
|
8
|
+
* hotkeys don't ship the recorder.
|
|
9
|
+
*/
|
|
10
|
+
function hotkeyRecorderPlugin(alpine) {
|
|
11
|
+
setAlpine(alpine);
|
|
12
|
+
const owners = /* @__PURE__ */ new WeakMap();
|
|
13
|
+
alpine.magic("hotkeyRecorder", (element, { cleanup }) => {
|
|
14
|
+
let create = owners.get(element);
|
|
15
|
+
if (!create) {
|
|
16
|
+
const scope = createScope({});
|
|
17
|
+
create = ((options) => createRecorder(scope, options));
|
|
18
|
+
owners.set(element, create);
|
|
19
|
+
cleanup(() => {
|
|
20
|
+
scope.destroy();
|
|
21
|
+
owners.delete(element);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return create;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
export { hotkeyRecorderPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { AlpineAppHotkeyOptions, AlpineCreateHotkey, AlpineCreateHotkeyRecorder, AlpineCustomHotkeys, AlpineHotkeyCommonOptions, AlpineHotkeyDefinition, AlpineHotkeyOptionsFor, AlpineHotkeyRecorder, AlpineHotkeyState, AlpineHotkeyTarget, AlpineHotkeys, DefaultHotkeysOptions, HotkeyRegistrationsResult, MaybeGetter } from "./types.js";
|
|
2
2
|
import { createHotkeysScope } from "./createHotkeysScope.js";
|
|
3
3
|
import { hotkeysPlugin } from "./hotkeysPlugin.js";
|
|
4
|
+
import { createHotkeyRecorder } from "./createHotkeyRecorder.js";
|
|
5
|
+
import { hotkeyRecorderPlugin } from "./hotkeyRecorderPlugin.js";
|
|
4
6
|
export * from "@tanstack/hotkeys";
|
|
5
|
-
export { AlpineAppHotkeyOptions, AlpineCreateHotkey, AlpineCreateHotkeyRecorder, AlpineCustomHotkeys, AlpineHotkeyCommonOptions, AlpineHotkeyDefinition, AlpineHotkeyOptionsFor, AlpineHotkeyRecorder, AlpineHotkeyState, AlpineHotkeyTarget, AlpineHotkeys, DefaultHotkeysOptions, HotkeyRegistrationsResult, MaybeGetter, createHotkeysScope, hotkeysPlugin };
|
|
7
|
+
export { AlpineAppHotkeyOptions, AlpineCreateHotkey, AlpineCreateHotkeyRecorder, AlpineCustomHotkeys, AlpineHotkeyCommonOptions, AlpineHotkeyDefinition, AlpineHotkeyOptionsFor, AlpineHotkeyRecorder, AlpineHotkeyState, AlpineHotkeyTarget, AlpineHotkeys, DefaultHotkeysOptions, HotkeyRegistrationsResult, MaybeGetter, createHotkeyRecorder, createHotkeysScope, hotkeyRecorderPlugin, hotkeysPlugin };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createHotkeysScope } from "./createHotkeysScope.js";
|
|
2
2
|
import { hotkeysPlugin } from "./hotkeysPlugin.js";
|
|
3
|
+
import { createHotkeyRecorder } from "./createHotkeyRecorder.js";
|
|
4
|
+
import { hotkeyRecorderPlugin } from "./hotkeyRecorderPlugin.js";
|
|
3
5
|
|
|
4
6
|
export * from "@tanstack/hotkeys"
|
|
5
7
|
|
|
6
|
-
export { createHotkeysScope, hotkeysPlugin };
|
|
8
|
+
export { createHotkeyRecorder, createHotkeysScope, hotkeyRecorderPlugin, hotkeysPlugin };
|
package/dist/scope.d.ts
ADDED
package/dist/scope.js
CHANGED
|
@@ -12,6 +12,15 @@ function getAlpine() {
|
|
|
12
12
|
if (!alpine) throw new Error("[TanStack Hotkeys] Alpine was not found. Call Alpine.plugin(hotkeysPlugin) before Alpine.start(), or set window.Alpine.");
|
|
13
13
|
return alpine;
|
|
14
14
|
}
|
|
15
|
+
/** The internal scope behind each `createHotkeysScope` owner. */
|
|
16
|
+
const ownerScopes = /* @__PURE__ */ new WeakMap();
|
|
17
|
+
/**
|
|
18
|
+
* Returns an owner's scope. Alpine data wraps stored objects in reactive
|
|
19
|
+
* proxies, so `this.hotkeys` can be a proxy of the owner.
|
|
20
|
+
*/
|
|
21
|
+
function scopeOf(owner) {
|
|
22
|
+
return ownerScopes.get(getAlpine().raw(owner));
|
|
23
|
+
}
|
|
15
24
|
function read(value) {
|
|
16
25
|
return typeof value === "function" ? value() : value;
|
|
17
26
|
}
|
|
@@ -24,9 +33,22 @@ function createScope(defaultOptions) {
|
|
|
24
33
|
function effect(callback) {
|
|
25
34
|
assertActive();
|
|
26
35
|
const alpine = getAlpine();
|
|
36
|
+
let error;
|
|
37
|
+
let first = true;
|
|
27
38
|
const runner = alpine.effect(() => {
|
|
28
|
-
if (
|
|
39
|
+
if (destroyed) return;
|
|
40
|
+
try {
|
|
41
|
+
callback();
|
|
42
|
+
} catch (e) {
|
|
43
|
+
if (first) error = e;
|
|
44
|
+
else reportError(e);
|
|
45
|
+
}
|
|
29
46
|
});
|
|
47
|
+
first = false;
|
|
48
|
+
if (error) {
|
|
49
|
+
alpine.release(runner);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
30
52
|
cleanups.add(() => alpine.release(runner));
|
|
31
53
|
}
|
|
32
54
|
function select(store, selector) {
|
|
@@ -74,4 +96,4 @@ function createScope(defaultOptions) {
|
|
|
74
96
|
}
|
|
75
97
|
|
|
76
98
|
//#endregion
|
|
77
|
-
export { createScope, read, setAlpine };
|
|
99
|
+
export { createScope, ownerScopes, read, scopeOf, setAlpine };
|
package/dist/types.d.ts
CHANGED
|
@@ -60,7 +60,7 @@ export interface AlpineCreateHotkey {
|
|
|
60
60
|
<T extends AppHotkey>(hotkey: MaybeGetter<T | null | undefined>, callback: HotkeyCallback, options?: MaybeGetter<AlpineAppHotkeyOptions<T>>): void;
|
|
61
61
|
<const T extends RegisterableHotkey>(hotkey: MaybeGetter<T | null | undefined>, callback: HotkeyCallback<HotkeyCallbackContextFor<T>>, options?: MaybeGetter<AlpineHotkeyOptionsFor<T>>): void;
|
|
62
62
|
}
|
|
63
|
-
/**
|
|
63
|
+
/** `$hotkeyRecorder`: creates a recorder; `maxSteps` (default 1) selects chords or sequences. */
|
|
64
64
|
export interface AlpineCreateHotkeyRecorder {
|
|
65
65
|
(options: HotkeyChordRecorderOptions): AlpineHotkeyRecorder<HotkeyChord>;
|
|
66
66
|
(options: HotkeySequenceRecorderOptions): AlpineHotkeyRecorder;
|
|
@@ -68,7 +68,7 @@ export interface AlpineCreateHotkeyRecorder {
|
|
|
68
68
|
(options: () => HotkeyChordRecorderOptions): AlpineHotkeyRecorder<HotkeyChord>;
|
|
69
69
|
(options: () => HotkeyRecorderOptions): AlpineHotkeyRecorder;
|
|
70
70
|
}
|
|
71
|
-
/** Registrations
|
|
71
|
+
/** Registrations and reactive state owned by one Alpine component. */
|
|
72
72
|
export interface AlpineHotkeys {
|
|
73
73
|
/**
|
|
74
74
|
* Register one hotkey: a chord such as `'Mod+S'`, a sequence such as
|
|
@@ -93,8 +93,6 @@ export interface AlpineHotkeys {
|
|
|
93
93
|
createHotkeyRegistrations: () => HotkeyRegistrationsResult;
|
|
94
94
|
/** Read the active, exclusive, allowed, and suspended scopes through `.value`. */
|
|
95
95
|
createHotkeyScopesState: () => AlpineHotkeyState<HotkeyScopesState>;
|
|
96
|
-
/** Create a recorder whose options can follow Alpine state. */
|
|
97
|
-
createHotkeyRecorder: AlpineCreateHotkeyRecorder;
|
|
98
96
|
/** Read the effective app hotkeys from `provideAppHotkeys` through `.value`. */
|
|
99
97
|
createAppHotkeys: () => AlpineHotkeyState<RegisteredAppHotkeys>;
|
|
100
98
|
/** Read every app hotkey with its live status through `.value`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/alpine-hotkeys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Alpine adapter for TanStack Hotkeys",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"skills"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@tanstack/hotkeys": "0.
|
|
38
|
+
"@tanstack/hotkeys": "0.22.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/alpinejs": "^3.17.0",
|
|
@@ -18,6 +18,8 @@ metadata:
|
|
|
18
18
|
sources:
|
|
19
19
|
- src/createHotkeysScope.ts
|
|
20
20
|
- src/hotkeysPlugin.ts
|
|
21
|
+
- src/createHotkeyRecorder.ts
|
|
22
|
+
- src/hotkeyRecorderPlugin.ts
|
|
21
23
|
- src/scope.ts
|
|
22
24
|
- src/createHotkey.ts
|
|
23
25
|
- src/createAppHotkeys.ts
|
|
@@ -62,12 +64,14 @@ Install `Alpine.plugin(hotkeysPlugin)` before `Alpine.start()`. It gives the ada
|
|
|
62
64
|
|
|
63
65
|
## API
|
|
64
66
|
|
|
65
|
-
| API | What it's for
|
|
66
|
-
| --------------------------------------------------- |
|
|
67
|
-
| `Alpine.plugin(hotkeysPlugin)` | Give the adapter the app's Alpine, and install the `$hotkeys` magic, an owner destroyed with its element.
|
|
68
|
-
| `createHotkeysScope(defaults?)` | Create an owner for one `Alpine.data` component, with optional default options.
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
67
|
+
| API | What it's for |
|
|
68
|
+
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
69
|
+
| `Alpine.plugin(hotkeysPlugin)` | Give the adapter the app's Alpine, and install the `$hotkeys` magic, an owner destroyed with its element. |
|
|
70
|
+
| `createHotkeysScope(defaults?)` | Create an owner for one `Alpine.data` component, with optional default options. |
|
|
71
|
+
| `createHotkeyRecorder(owner, options)` | Record a chord or sequence the user presses, for a settings screen. The owner destroys it and supplies its `hotkeyRecorder` defaults. |
|
|
72
|
+
| `Alpine.plugin(hotkeyRecorderPlugin)` | Install the `$hotkeyRecorder(options)` magic, which creates recorders destroyed with their element. |
|
|
73
|
+
| `provideAppHotkeys(appHotkeys, options?)` | Declare app hotkeys and load the user's custom hotkeys once at startup, since Alpine has no provider. |
|
|
74
|
+
| `getHotkeyManager().activateScope(scope, options?)` | Turn on a scope, such as an exclusive one for a dialog; it returns the function that turns the scope off. |
|
|
71
75
|
|
|
72
76
|
Each owner has these methods. Read their state through `.value`, or `.hotkeys` for registrations.
|
|
73
77
|
|
|
@@ -75,7 +79,6 @@ Each owner has these methods. Read their state through `.value`, or `.hotkeys` f
|
|
|
75
79
|
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
76
80
|
| `createHotkey(hotkey, callback, options?)` | Register one chord, sequence, or app hotkey until the owner is destroyed; options can be a getter. |
|
|
77
81
|
| `createHotkeys(definitions, commonOptions?)` | Register several hotkeys, or a getter of a list built from data, in one call. |
|
|
78
|
-
| `createHotkeyRecorder(options)` | Record a chord or sequence the user presses, for a settings screen. |
|
|
79
82
|
| `createAppHotkeys()` | Get the declared app hotkeys with the user's custom hotkeys applied. |
|
|
80
83
|
| `createAppHotkeyList()` | List every app hotkey with its status, for a cheat sheet or settings screen. |
|
|
81
84
|
| `createCustomHotkeys()` | Read, change, and reset the user's custom hotkeys, and check a new one for conflicts. |
|
|
@@ -95,6 +98,8 @@ The package also re-exports `@tanstack/hotkeys`, such as `formatForDisplay`, `ma
|
|
|
95
98
|
- **`createHotkeysScope` isn't a hotkey scope.** It only owns registrations and sets defaults. For a dialog, activate a real scope in `init()` with `release = getHotkeyManager().activateScope(name, { exclusive: true })`, pass `{ scope: name }` to the dialog's hotkeys, and call `release()` in `destroy()`. Give each open dialog its own name.
|
|
96
99
|
- **Pass options as a getter.** `{ enabled: this.dirty }` is read once. Use `() => ({ enabled: this.dirty })`.
|
|
97
100
|
- **Use either `$hotkeys` or your own owner for a hotkey, not both.** Otherwise it registers twice.
|
|
101
|
+
- **Call `create*` in `x-init` or `init()`, and read `.value` anywhere.** Calling `create*` inside a reactive expression such as `x-text="$hotkeys.createHeldKeys().value"` creates a new subscription on every evaluation.
|
|
102
|
+
- **Owners have no `createHotkeyRecorder` method** since v0.10.0. Call `createHotkeyRecorder(this.hotkeys, options)`, so apps that don't record don't ship the recorder.
|
|
98
103
|
- With server rendering, load the adapter only in the browser.
|
|
99
104
|
|
|
100
105
|
When declaring app hotkeys, building a cheat sheet, or letting users rebind shortcuts, load `@tanstack/hotkeys#app-hotkeys` and read [app hotkeys in Alpine](references/app-hotkeys.md).
|
|
@@ -32,18 +32,22 @@ provideAppHotkeys(appHotkeys, {
|
|
|
32
32
|
|
|
33
33
|
The app hotkey methods throw until `provideAppHotkeys` has run. When saved shortcuts come from a server, await them first. Register inside a getter so registrations follow rebinding: `this.hotkeys.createHotkey(() => appHotkeys.value['doc.save'], save)`, with `const appHotkeys = this.hotkeys.createAppHotkeys()`. Build a cheat sheet from `createAppHotkeyList().value`.
|
|
34
34
|
|
|
35
|
-
A settings row records with
|
|
35
|
+
A settings row records with `createHotkeyRecorder` on its owner:
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
38
|
import Alpine from 'alpinejs'
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
createHotkeyRecorder,
|
|
41
|
+
createHotkeysScope,
|
|
42
|
+
formatForDisplay,
|
|
43
|
+
} from '@tanstack/alpine-hotkeys'
|
|
40
44
|
import type { AppHotkeyId } from '@tanstack/alpine-hotkeys'
|
|
41
45
|
|
|
42
46
|
Alpine.data('shortcutRow', (id: AppHotkeyId) => {
|
|
43
47
|
const hotkeys = createHotkeysScope()
|
|
44
48
|
const appHotkeys = hotkeys.createAppHotkeys()
|
|
45
49
|
const custom = hotkeys.createCustomHotkeys()
|
|
46
|
-
const recorder =
|
|
50
|
+
const recorder = createHotkeyRecorder(hotkeys, {
|
|
47
51
|
maxSteps: Infinity,
|
|
48
52
|
validate: (hotkey) => {
|
|
49
53
|
const [conflict] = custom.findConflicts(id, hotkey)
|