@tanstack/hotkeys-devtools 1.3.6 → 1.4.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 +1 -1
- package/dist/HotkeysContextProvider.js +14 -0
- package/dist/_registrations.js +3 -2
- package/dist/_scopes.js +41 -0
- package/dist/components/DetailsPanel.js +333 -298
- package/dist/components/HotkeyList.js +97 -49
- package/dist/components/Shell.js +1 -1
- package/dist/styles/use-styles.js +53 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
# TanStack Hotkeys
|
|
52
52
|
|
|
53
53
|
> [!NOTE]
|
|
54
|
-
> TanStack Hotkeys is
|
|
54
|
+
> TanStack Hotkeys is in beta. We are actively developing the library and are open to feedback and contributions.
|
|
55
55
|
|
|
56
56
|
Type-safe keyboard shortcuts for the web. Template-string bindings, parsed objects, a cross-platform `Mod` key, a singleton Hotkey Manager, and utilities for cheatsheet UIs—built to stay SSR-friendly.
|
|
57
57
|
|
|
@@ -7,6 +7,12 @@ import { HotkeyManager, KeyStateTracker, toHotkeyRegistrationView } from "@tanst
|
|
|
7
7
|
const HotkeysDevtoolsContext = createContext({
|
|
8
8
|
registrations: () => [],
|
|
9
9
|
appHotkeys: () => [],
|
|
10
|
+
scopes: () => ({
|
|
11
|
+
active: [],
|
|
12
|
+
exclusive: null,
|
|
13
|
+
allowed: [],
|
|
14
|
+
suspended: []
|
|
15
|
+
}),
|
|
10
16
|
heldKeys: () => [],
|
|
11
17
|
heldCodes: () => ({}),
|
|
12
18
|
sequenceProgressNow: () => Date.now()
|
|
@@ -20,6 +26,7 @@ function HotkeysContextProvider(props) {
|
|
|
20
26
|
const [registrations, setRegistrations] = createSignal(readRegistrations(manager));
|
|
21
27
|
const [appHotkeysStore, setAppHotkeysStore] = createSignal(manager.appHotkeys.state);
|
|
22
28
|
const [appHotkeysVersion, setAppHotkeysVersion] = createSignal(0);
|
|
29
|
+
const [scopes, setScopes] = createSignal(manager.scopes.state);
|
|
23
30
|
const [heldKeys, setHeldKeys] = createSignal(tracker.store.state.heldKeys);
|
|
24
31
|
const [heldCodes, setHeldCodes] = createSignal(tracker.store.state.heldCodes);
|
|
25
32
|
createEffect(() => {
|
|
@@ -28,6 +35,12 @@ function HotkeysContextProvider(props) {
|
|
|
28
35
|
}).unsubscribe;
|
|
29
36
|
onCleanup(() => unsubscribe());
|
|
30
37
|
});
|
|
38
|
+
createEffect(() => {
|
|
39
|
+
const unsubscribe = manager.scopes.subscribe(() => {
|
|
40
|
+
setScopes(manager.scopes.state);
|
|
41
|
+
}).unsubscribe;
|
|
42
|
+
onCleanup(() => unsubscribe());
|
|
43
|
+
});
|
|
31
44
|
createEffect(() => {
|
|
32
45
|
const unsubscribe = manager.appHotkeys.subscribe(() => {
|
|
33
46
|
setAppHotkeysStore(manager.appHotkeys.state);
|
|
@@ -77,6 +90,7 @@ function HotkeysContextProvider(props) {
|
|
|
77
90
|
value: {
|
|
78
91
|
registrations,
|
|
79
92
|
appHotkeys,
|
|
93
|
+
scopes,
|
|
80
94
|
heldKeys,
|
|
81
95
|
heldCodes,
|
|
82
96
|
sequenceProgressNow
|
package/dist/_registrations.js
CHANGED
|
@@ -20,7 +20,8 @@ function useRegistrationConflicts(registration) {
|
|
|
20
20
|
eventType: reg.options.eventType,
|
|
21
21
|
excludeIds: [reg.id]
|
|
22
22
|
};
|
|
23
|
-
const
|
|
23
|
+
const scope = reg.options.scope ?? "global";
|
|
24
|
+
const overlapping = findHotkeyConflicts(binding, options).map((c) => c.registration).filter((r) => (r.options.scope ?? "global") === scope);
|
|
24
25
|
const ids = new Set(overlapping.map((r) => r.id));
|
|
25
26
|
return {
|
|
26
27
|
overlapping,
|
|
@@ -40,7 +41,7 @@ function formatRegistration(reg) {
|
|
|
40
41
|
}
|
|
41
42
|
/** Sequences may mix logical keys and physical codes, so report both when needed. */
|
|
42
43
|
function getBindingKind(reg) {
|
|
43
|
-
const parsed = reg.kind === "sequence" ? reg.parsedSequence : [reg.
|
|
44
|
+
const parsed = reg.kind === "sequence" ? reg.parsedSequence : [reg.parsedChord];
|
|
44
45
|
const codes = parsed.filter((step) => step.code !== void 0).length;
|
|
45
46
|
return codes === 0 ? "Key" : codes === parsed.length ? "Code" : "Mixed";
|
|
46
47
|
}
|
package/dist/_scopes.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/_scopes.ts
|
|
2
|
+
const scopeStatusDescriptions = {
|
|
3
|
+
exclusive: "Exclusive: only hotkeys in this scope, scopes nested in it, and scopes it allows fire",
|
|
4
|
+
allowed: "Allowed: the exclusive scope lets hotkeys in this scope fire",
|
|
5
|
+
active: "Active: hotkeys in this scope fire",
|
|
6
|
+
suspended: "Suspended: another scope is exclusive",
|
|
7
|
+
inactive: "Inactive: nothing has activated this scope"
|
|
8
|
+
};
|
|
9
|
+
function getScopeStatus(scope, state) {
|
|
10
|
+
if (scope === state.exclusive) return "exclusive";
|
|
11
|
+
if (state.allowed.includes(scope)) return "allowed";
|
|
12
|
+
if (state.suspended.includes(scope)) return "suspended";
|
|
13
|
+
return scope === "global" || state.active.includes(scope) ? "active" : "inactive";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Groups registrations by scope, highest precedence first: the exclusive
|
|
17
|
+
* scope, other activated scopes from most to least recent, `'global'`, then
|
|
18
|
+
* inactive scopes by name.
|
|
19
|
+
*/
|
|
20
|
+
function groupByScope(registrations, state) {
|
|
21
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
22
|
+
for (const registration of registrations) {
|
|
23
|
+
const scope = registration.options.scope ?? "global";
|
|
24
|
+
const list = byScope.get(scope);
|
|
25
|
+
if (list) list.push(registration);
|
|
26
|
+
else byScope.set(scope, [registration]);
|
|
27
|
+
}
|
|
28
|
+
const rank = (scope) => {
|
|
29
|
+
if (scope === state.exclusive) return Infinity;
|
|
30
|
+
if (scope === "global") return 0;
|
|
31
|
+
return state.active.indexOf(scope) + 1 || -1;
|
|
32
|
+
};
|
|
33
|
+
return [...byScope.keys()].sort((a, b) => rank(b) - rank(a) || a.localeCompare(b)).map((scope) => ({
|
|
34
|
+
scope,
|
|
35
|
+
status: getScopeStatus(scope, state),
|
|
36
|
+
registrations: byScope.get(scope)
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { getScopeStatus, groupByScope, scopeStatusDescriptions };
|