@tanstack/hotkeys-devtools 1.2.0 → 1.3.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.
@@ -1,36 +1,51 @@
1
1
  import { needsSequenceProgressClock } from "./sequence-progress.js";
2
2
  import { createComponent } from "solid-js/web";
3
- import { createContext, createEffect, createSignal, onCleanup, useContext } from "solid-js";
4
- import { HotkeyManager, KeyStateTracker, SequenceManager } from "@tanstack/hotkeys";
3
+ import { createContext, createEffect, createMemo, createSignal, onCleanup, useContext } from "solid-js";
4
+ import { HotkeyManager, KeyStateTracker, toHotkeyRegistrationView } from "@tanstack/hotkeys";
5
5
 
6
6
  //#region src/HotkeysContextProvider.tsx
7
7
  const HotkeysDevtoolsContext = createContext({
8
8
  registrations: () => [],
9
- sequenceRegistrations: () => [],
9
+ appHotkeys: () => [],
10
10
  heldKeys: () => [],
11
11
  heldCodes: () => ({}),
12
12
  sequenceProgressNow: () => Date.now()
13
13
  });
14
+ function readRegistrations(manager) {
15
+ return Array.from(manager.registrations.state.values()).map(toHotkeyRegistrationView);
16
+ }
14
17
  function HotkeysContextProvider(props) {
15
18
  const manager = HotkeyManager.getInstance();
16
- const sequenceManager = SequenceManager.getInstance();
17
19
  const tracker = KeyStateTracker.getInstance();
18
- const [registrations, setRegistrations] = createSignal(Array.from(manager.registrations.state.values()));
19
- const [sequenceRegistrations, setSequenceRegistrations] = createSignal(Array.from(sequenceManager.registrations.state.values()));
20
+ const [registrations, setRegistrations] = createSignal(readRegistrations(manager));
21
+ const [appHotkeysStore, setAppHotkeysStore] = createSignal(manager.appHotkeys.state);
22
+ const [appHotkeysVersion, setAppHotkeysVersion] = createSignal(0);
20
23
  const [heldKeys, setHeldKeys] = createSignal(tracker.store.state.heldKeys);
21
24
  const [heldCodes, setHeldCodes] = createSignal(tracker.store.state.heldCodes);
22
25
  createEffect(() => {
23
26
  const unsubscribe = manager.registrations.subscribe(() => {
24
- setRegistrations(Array.from(manager.registrations.state.values()));
27
+ setRegistrations(readRegistrations(manager));
28
+ }).unsubscribe;
29
+ onCleanup(() => unsubscribe());
30
+ });
31
+ createEffect(() => {
32
+ const unsubscribe = manager.appHotkeys.subscribe(() => {
33
+ setAppHotkeysStore(manager.appHotkeys.state);
25
34
  }).unsubscribe;
26
35
  onCleanup(() => unsubscribe());
27
36
  });
28
37
  createEffect(() => {
29
- const unsubscribe = sequenceManager.registrations.subscribe(() => {
30
- setSequenceRegistrations(Array.from(sequenceManager.registrations.state.values()));
38
+ const store = appHotkeysStore();
39
+ if (!store) return;
40
+ const unsubscribe = store.store.subscribe(() => {
41
+ setAppHotkeysVersion((version) => version + 1);
31
42
  }).unsubscribe;
32
43
  onCleanup(() => unsubscribe());
33
44
  });
45
+ const appHotkeys = createMemo(() => {
46
+ appHotkeysVersion();
47
+ return appHotkeysStore()?.getList(registrations()) ?? [];
48
+ });
34
49
  createEffect(() => {
35
50
  const unsubscribe = tracker.store.subscribe(() => {
36
51
  setHeldKeys(tracker.store.state.heldKeys);
@@ -40,12 +55,12 @@ function HotkeysContextProvider(props) {
40
55
  });
41
56
  const [sequenceProgressNow, setSequenceProgressNow] = createSignal(Date.now());
42
57
  createEffect(() => {
43
- const regs = sequenceRegistrations();
58
+ const regs = registrations();
44
59
  let id;
45
60
  const tick = () => {
46
61
  const t = Date.now();
47
62
  setSequenceProgressNow(t);
48
- if (!needsSequenceProgressClock(sequenceRegistrations(), t)) {
63
+ if (!needsSequenceProgressClock(registrations(), t)) {
49
64
  if (id !== void 0) {
50
65
  clearInterval(id);
51
66
  id = void 0;
@@ -61,7 +76,7 @@ function HotkeysContextProvider(props) {
61
76
  return createComponent(HotkeysDevtoolsContext.Provider, {
62
77
  value: {
63
78
  registrations,
64
- sequenceRegistrations,
79
+ appHotkeys,
65
80
  heldKeys,
66
81
  heldCodes,
67
82
  sequenceProgressNow
@@ -1,6 +1,6 @@
1
1
  import { useHotkeysDevtoolsState } from "./HotkeysContextProvider.js";
2
2
  import { createMemo } from "solid-js";
3
- import { findHotkeyConflicts, formatForDisplay, parseHotkey } from "@tanstack/hotkeys";
3
+ import { findHotkeyConflicts, formatForDisplay } from "@tanstack/hotkeys";
4
4
 
5
5
  //#region src/_registrations.ts
6
6
  /** Refresh shared conflict reporting when either registry changes. */
@@ -8,13 +8,12 @@ function useRegistrationConflicts(registration) {
8
8
  const state = useHotkeysDevtoolsState();
9
9
  return createMemo(() => {
10
10
  state.registrations();
11
- state.sequenceRegistrations();
12
11
  const reg = registration();
13
12
  if (reg.options.enabled === false) return {
14
13
  overlapping: [],
15
14
  separate: []
16
15
  };
17
- const binding = "sequence" in reg ? reg.sequence : reg.hotkey;
16
+ const binding = reg.hotkey;
18
17
  const options = {
19
18
  target: reg.target,
20
19
  platform: reg.options.platform,
@@ -34,11 +33,14 @@ function useRegistrationConflicts(registration) {
34
33
  }
35
34
  /** Format either kind of registration, respecting its platform and physical labels. */
36
35
  function formatRegistration(reg) {
37
- return ("sequence" in reg ? reg.sequence : [reg.hotkey]).map((step) => formatForDisplay(step, { platform: reg.options.platform })).join(" → ");
36
+ return formatForDisplay(reg.hotkey, {
37
+ platform: reg.options.platform,
38
+ sequenceSeparator: " → "
39
+ });
38
40
  }
39
41
  /** Sequences may mix logical keys and physical codes, so report both when needed. */
40
42
  function getBindingKind(reg) {
41
- const parsed = "sequence" in reg ? reg.sequence.map((step) => parseHotkey(step, reg.options.platform)) : [reg.parsedHotkey];
43
+ const parsed = reg.kind === "sequence" ? reg.parsedSequence : [reg.parsedHotkey];
42
44
  const codes = parsed.filter((step) => step.code !== void 0).length;
43
45
  return codes === 0 ? "Key" : codes === parsed.length ? "Code" : "Mixed";
44
46
  }
@@ -1,18 +1,13 @@
1
1
  import { useStyles } from "../styles/use-styles.js";
2
2
  import { className, delegateEvents, effect, template } from "solid-js/web";
3
- import { HotkeyManager, SequenceManager } from "@tanstack/hotkeys";
3
+ import { HotkeyManager } from "@tanstack/hotkeys";
4
4
 
5
5
  //#region src/components/ActionButtons.tsx
6
6
  var _tmpl$ = /*#__PURE__*/ template(`<div><button><span></span>Trigger`);
7
- function isSequenceRegistration(reg) {
8
- return "sequence" in reg && Array.isArray(reg.sequence);
9
- }
10
7
  function ActionButtons(props) {
11
8
  const styles = useStyles();
12
9
  const handleTrigger = () => {
13
- const reg = props.registration;
14
- if (isSequenceRegistration(reg)) SequenceManager.getInstance().triggerSequence(reg.id);
15
- else HotkeyManager.getInstance().triggerRegistration(reg.id);
10
+ HotkeyManager.getInstance().triggerRegistration(props.registration.id);
16
11
  };
17
12
  return (() => {
18
13
  var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
@@ -23,7 +23,9 @@ var _tmpl$1 = /*#__PURE__*/ template(`<div><div><div>Key Breakdown</div><div></d
23
23
  var _tmpl$10 = /*#__PURE__*/ template(`<span><span>`);
24
24
  var _tmpl$11 = /*#__PURE__*/ template(`<span>→`);
25
25
  var _tmpl$12 = /*#__PURE__*/ template(`<div><div>Step <!> — </div><div><div><div></div></div><span aria-hidden=true>-></span><div>`);
26
- var _tmpl$13 = /*#__PURE__*/ template(`<div>Select a hotkey or sequence from the list to view its details`);
26
+ var _tmpl$13 = /*#__PURE__*/ template(`<div><div></div><div><div>App hotkey</div><div></div><div>Status</div><div></div><div>Default</div><div></div><div>Context</div><div>`);
27
+ var _tmpl$14 = /*#__PURE__*/ template(`<div><div><div>Meta</div><div></div></div><div><div>Declared options</div><div>`);
28
+ var _tmpl$15 = /*#__PURE__*/ template(`<div>Select a hotkey from the list to view its details`);
27
29
  const PLATFORM_ROWS = [
28
30
  {
29
31
  id: "mac",
@@ -66,9 +68,6 @@ function KeyBreakdownPlatformTable(props) {
66
68
  return _el$;
67
69
  })();
68
70
  }
69
- function isSequenceRegistration(reg) {
70
- return "sequence" in reg && Array.isArray(reg.sequence);
71
- }
72
71
  function getTargetDescription(target) {
73
72
  if (typeof document !== "undefined" && target === document) return "document";
74
73
  if (typeof window !== "undefined" && target === window) return "window";
@@ -348,7 +347,10 @@ function HotkeyDetails(props) {
348
347
  }
349
348
  function SequenceDetails(props) {
350
349
  const reg = () => props.registration;
351
- const liveReg = createMemo(() => props.state.sequenceRegistrations().find((r) => r.id === reg().id) ?? reg());
350
+ const liveReg = createMemo(() => {
351
+ const live = props.state.registrations().find((r) => r.id === reg().id);
352
+ return live?.kind === "sequence" ? live : reg();
353
+ });
352
354
  const matchedSteps = createMemo(() => effectiveSequenceMatchedSteps(liveReg(), props.state.sequenceProgressNow()));
353
355
  const conflicts = useRegistrationConflicts(liveReg);
354
356
  const targetConflicts = () => conflicts().overlapping;
@@ -361,7 +363,7 @@ function SequenceDetails(props) {
361
363
  var _el$93 = _tmpl$0(), _el$94 = _el$93.firstChild, _el$95 = _el$94.nextSibling, _el$96 = _el$95.firstChild, _el$97 = _el$96.nextSibling, _el$98 = _el$97.nextSibling, _el$99 = _el$98.nextSibling, _el$100 = _el$99.nextSibling, _el$101 = _el$100.nextSibling, _el$102 = _el$101.nextSibling, _el$103 = _el$102.nextSibling, _el$104 = _el$103.nextSibling, _el$105 = _el$104.nextSibling;
362
364
  insert(_el$94, createComponent(For, {
363
365
  get each() {
364
- return liveReg().sequence;
366
+ return liveReg().hotkey;
365
367
  },
366
368
  children: (step, i) => (() => {
367
369
  var _el$153 = _tmpl$10(), _el$154 = _el$153.firstChild;
@@ -378,10 +380,10 @@ function SequenceDetails(props) {
378
380
  }));
379
381
  insert(_el$97, () => liveReg().id);
380
382
  insert(_el$99, () => getBindingKind(liveReg()));
381
- insert(_el$101, () => liveReg().sequence.join(" → "));
383
+ insert(_el$101, () => liveReg().hotkey.join(" → "));
382
384
  insert(_el$103, createComponent(For, {
383
385
  get each() {
384
- return liveReg().sequence;
386
+ return liveReg().hotkey;
385
387
  },
386
388
  children: (step, i) => (() => {
387
389
  var _el$155 = _tmpl$10(), _el$156 = _el$155.firstChild;
@@ -433,7 +435,7 @@ function SequenceDetails(props) {
433
435
  var _el$106 = _tmpl$1(), _el$107 = _el$106.firstChild, _el$108 = _el$107.firstChild, _el$109 = _el$108.nextSibling, _el$110 = _el$109.nextSibling, _el$111 = _el$107.nextSibling, _el$112 = _el$111.firstChild, _el$113 = _el$111.nextSibling, _el$114 = _el$113.firstChild, _el$115 = _el$114.nextSibling, _el$116 = _el$115.firstChild, _el$117 = _el$116.firstChild, _el$118 = _el$117.nextSibling, _el$119 = _el$116.nextSibling, _el$120 = _el$119.firstChild, _el$121 = _el$120.nextSibling, _el$122 = _el$113.nextSibling, _el$123 = _el$122.firstChild, _el$125 = _el$123.nextSibling.firstChild, _el$126 = _el$125.firstChild, _el$127 = _el$126.nextSibling, _el$128 = _el$125.nextSibling, _el$129 = _el$128.firstChild, _el$130 = _el$129.nextSibling, _el$131 = _el$128.nextSibling, _el$132 = _el$131.firstChild, _el$133 = _el$132.nextSibling, _el$134 = _el$133.firstChild, _el$135 = _el$131.nextSibling, _el$136 = _el$135.firstChild, _el$137 = _el$136.nextSibling, _el$138 = _el$135.nextSibling, _el$139 = _el$138.firstChild, _el$140 = _el$139.nextSibling, _el$141 = _el$138.nextSibling, _el$142 = _el$141.firstChild, _el$143 = _el$142.nextSibling, _el$144 = _el$141.nextSibling, _el$145 = _el$144.firstChild, _el$146 = _el$145.nextSibling;
434
436
  insert(_el$109, createComponent(For, {
435
437
  get each() {
436
- return liveReg().sequence;
438
+ return liveReg().hotkey;
437
439
  },
438
440
  children: (step, i) => [createComponent(Show, {
439
441
  get when() {
@@ -453,7 +455,7 @@ function SequenceDetails(props) {
453
455
  }));
454
456
  insert(_el$107, createComponent(For, {
455
457
  get each() {
456
- return liveReg().sequence;
458
+ return liveReg().hotkey;
457
459
  },
458
460
  children: (step, stepIdx) => {
459
461
  const stepParsed = () => parseHotkey(step, sequenceCanonicalPlatform());
@@ -697,49 +699,150 @@ function SequenceDetails(props) {
697
699
  return _el$106;
698
700
  })()];
699
701
  }
702
+ function AppHotkeyDetails(props) {
703
+ const styles = props.styles;
704
+ const appHotkey = () => props.item.appHotkey;
705
+ const format = (hotkey) => hotkey ? formatForDisplay(hotkey, { sequenceSeparator: " → " }) : "Unassigned";
706
+ const row = (label, value) => (() => {
707
+ var _el$197 = _tmpl$2(), _el$198 = _el$197.firstChild, _el$199 = _el$198.nextSibling;
708
+ insert(_el$198, label);
709
+ insert(_el$199, value);
710
+ effect((_p$) => {
711
+ var _v$127 = styles().optionRow, _v$128 = styles().optionLabel, _v$129 = styles().optionValue;
712
+ _v$127 !== _p$.e && className(_el$197, _p$.e = _v$127);
713
+ _v$128 !== _p$.t && className(_el$198, _p$.t = _v$128);
714
+ _v$129 !== _p$.a && className(_el$199, _p$.a = _v$129);
715
+ return _p$;
716
+ }, {
717
+ e: void 0,
718
+ t: void 0,
719
+ a: void 0
720
+ });
721
+ return _el$197;
722
+ })();
723
+ return [(() => {
724
+ var _el$200 = _tmpl$13(), _el$201 = _el$200.firstChild, _el$202 = _el$201.nextSibling, _el$203 = _el$202.firstChild, _el$204 = _el$203.nextSibling, _el$205 = _el$204.nextSibling, _el$206 = _el$205.nextSibling, _el$207 = _el$206.nextSibling, _el$208 = _el$207.nextSibling, _el$209 = _el$208.nextSibling, _el$210 = _el$209.nextSibling;
725
+ insert(_el$201, () => format(appHotkey().hotkey));
726
+ insert(_el$204, () => appHotkey().id);
727
+ insert(_el$206, () => props.item.status);
728
+ insert(_el$208, () => format(appHotkey().defaultHotkey), null);
729
+ insert(_el$208, () => props.item.isCustom ? " (customized)" : "", null);
730
+ insert(_el$210, () => appHotkey().context ?? "global");
731
+ effect((_p$) => {
732
+ var _v$130 = styles().stateHeader, _v$131 = styles().stateTitle, _v$132 = styles().infoGrid, _v$133 = styles().infoLabel, _v$134 = styles().infoValueMono, _v$135 = styles().infoLabel, _v$136 = styles().infoValueMono, _v$137 = styles().infoLabel, _v$138 = styles().infoValueMono, _v$139 = styles().infoLabel, _v$140 = styles().infoValueMono;
733
+ _v$130 !== _p$.e && className(_el$200, _p$.e = _v$130);
734
+ _v$131 !== _p$.t && className(_el$201, _p$.t = _v$131);
735
+ _v$132 !== _p$.a && className(_el$202, _p$.a = _v$132);
736
+ _v$133 !== _p$.o && className(_el$203, _p$.o = _v$133);
737
+ _v$134 !== _p$.i && className(_el$204, _p$.i = _v$134);
738
+ _v$135 !== _p$.n && className(_el$205, _p$.n = _v$135);
739
+ _v$136 !== _p$.s && className(_el$206, _p$.s = _v$136);
740
+ _v$137 !== _p$.h && className(_el$207, _p$.h = _v$137);
741
+ _v$138 !== _p$.r && className(_el$208, _p$.r = _v$138);
742
+ _v$139 !== _p$.d && className(_el$209, _p$.d = _v$139);
743
+ _v$140 !== _p$.l && className(_el$210, _p$.l = _v$140);
744
+ return _p$;
745
+ }, {
746
+ e: void 0,
747
+ t: void 0,
748
+ a: void 0,
749
+ o: void 0,
750
+ i: void 0,
751
+ n: void 0,
752
+ s: void 0,
753
+ h: void 0,
754
+ r: void 0,
755
+ d: void 0,
756
+ l: void 0
757
+ });
758
+ return _el$200;
759
+ })(), (() => {
760
+ var _el$211 = _tmpl$14(), _el$212 = _el$211.firstChild, _el$213 = _el$212.firstChild, _el$214 = _el$213.nextSibling, _el$215 = _el$212.nextSibling, _el$216 = _el$215.firstChild, _el$217 = _el$216.nextSibling;
761
+ insert(_el$214, createComponent(For, {
762
+ get each() {
763
+ return Object.entries(appHotkey().meta ?? {});
764
+ },
765
+ children: ([key, value]) => row(key, String(value))
766
+ }), null);
767
+ insert(_el$214, createComponent(Show, {
768
+ get when() {
769
+ return !appHotkey().meta;
770
+ },
771
+ get children() {
772
+ return row("meta", "—");
773
+ }
774
+ }), null);
775
+ insert(_el$217, createComponent(For, {
776
+ get each() {
777
+ return Object.entries(appHotkey().options ?? {});
778
+ },
779
+ children: ([key, value]) => row(key, String(value))
780
+ }), null);
781
+ insert(_el$217, createComponent(Show, {
782
+ get when() {
783
+ return !appHotkey().options;
784
+ },
785
+ get children() {
786
+ return row("options", "—");
787
+ }
788
+ }), null);
789
+ effect((_p$) => {
790
+ var _v$141 = styles().detailsGrid, _v$142 = styles().detailSection, _v$143 = styles().detailSectionHeader, _v$144 = styles().detailSection, _v$145 = styles().detailSectionHeader;
791
+ _v$141 !== _p$.e && className(_el$211, _p$.e = _v$141);
792
+ _v$142 !== _p$.t && className(_el$212, _p$.t = _v$142);
793
+ _v$143 !== _p$.a && className(_el$213, _p$.a = _v$143);
794
+ _v$144 !== _p$.o && className(_el$215, _p$.o = _v$144);
795
+ _v$145 !== _p$.i && className(_el$216, _p$.i = _v$145);
796
+ return _p$;
797
+ }, {
798
+ e: void 0,
799
+ t: void 0,
800
+ a: void 0,
801
+ o: void 0,
802
+ i: void 0
803
+ });
804
+ return _el$211;
805
+ })()];
806
+ }
700
807
  function DetailsPanel(props) {
701
808
  const styles = useStyles();
702
809
  const state = useHotkeysDevtoolsState();
703
810
  return (() => {
704
- var _el$197 = _tmpl$();
705
- insert(_el$197, createComponent(Show, {
811
+ var _el$218 = _tmpl$();
812
+ insert(_el$218, createComponent(Show, {
706
813
  get when() {
707
- return props.selectedRegistration();
814
+ return props.selection();
708
815
  },
709
816
  get fallback() {
710
817
  return (() => {
711
- var _el$198 = _tmpl$13();
712
- effect(() => className(_el$198, styles().noSelection));
713
- return _el$198;
818
+ var _el$219 = _tmpl$15();
819
+ effect(() => className(_el$219, styles().noSelection));
820
+ return _el$219;
714
821
  })();
715
822
  },
716
- children: (reg) => createComponent(Show, {
717
- get when() {
718
- return isSequenceRegistration(reg());
719
- },
720
- get fallback() {
721
- return createComponent(HotkeyDetails, {
722
- get registration() {
723
- return reg();
724
- },
725
- getTargetDescription,
726
- styles
727
- });
728
- },
729
- get children() {
730
- return createComponent(SequenceDetails, {
731
- get registration() {
732
- return reg();
733
- },
734
- state,
735
- getTargetDescription,
736
- styles
737
- });
738
- }
739
- })
823
+ children: (selection) => {
824
+ const current = selection();
825
+ if (current.type === "appHotkey") return createComponent(AppHotkeyDetails, {
826
+ get item() {
827
+ return current.item;
828
+ },
829
+ styles
830
+ });
831
+ const reg = current.registration;
832
+ return reg.kind === "sequence" ? createComponent(SequenceDetails, {
833
+ registration: reg,
834
+ state,
835
+ getTargetDescription,
836
+ styles
837
+ }) : createComponent(HotkeyDetails, {
838
+ registration: reg,
839
+ getTargetDescription,
840
+ styles
841
+ });
842
+ }
740
843
  }));
741
- effect(() => className(_el$197, styles().stateDetails));
742
- return _el$197;
844
+ effect(() => className(_el$218, styles().stateDetails));
845
+ return _el$218;
743
846
  })();
744
847
  }
745
848
 
@@ -9,18 +9,22 @@ import clsx from "clsx";
9
9
  import { matchSorter } from "match-sorter";
10
10
 
11
11
  //#region src/components/HotkeyList.tsx
12
- var _tmpl$ = /*#__PURE__*/ template(`<span data-tooltip>`);
13
- var _tmpl$2 = /*#__PURE__*/ template(`<span>`);
14
- var _tmpl$3 = /*#__PURE__*/ template(`<span>x`);
15
- var _tmpl$4 = /*#__PURE__*/ template(`<div><span><span></span></span><div><span data-binding-kind></span><span><span data-tooltip></span></span><span><span data-tooltip>Fires on <!> event</span></span><span><span data-tooltip>`);
16
- var _tmpl$5 = /*#__PURE__*/ template(`<span><span>`);
17
- var _tmpl$6 = /*#__PURE__*/ template(`<span><span data-tooltip>`);
18
- var _tmpl$7 = /*#__PURE__*/ template(`<span>i<span data-tooltip>`);
19
- var _tmpl$8 = /*#__PURE__*/ template(`<button>&times;`);
20
- var _tmpl$9 = /*#__PURE__*/ template(`<div><input type=text placeholder="Search hotkeys...">`);
21
- var _tmpl$0 = /*#__PURE__*/ template(`<div>Hotkeys (<!>)`);
22
- var _tmpl$1 = /*#__PURE__*/ template(`<div>`);
23
- var _tmpl$10 = /*#__PURE__*/ template(`<div>Sequences (<!>)`);
12
+ var _tmpl$ = /*#__PURE__*/ template(`<span><span>`);
13
+ var _tmpl$2 = /*#__PURE__*/ template(`<span data-tooltip>`);
14
+ var _tmpl$3 = /*#__PURE__*/ template(`<span>`);
15
+ var _tmpl$4 = /*#__PURE__*/ template(`<span>x`);
16
+ var _tmpl$5 = /*#__PURE__*/ template(`<span>seq`);
17
+ var _tmpl$6 = /*#__PURE__*/ template(`<span>custom<span data-tooltip>The user changed this app hotkey from its default`);
18
+ var _tmpl$7 = /*#__PURE__*/ template(`<div><span><span></span></span><div><span data-binding-kind></span><span><span data-tooltip></span></span><span><span data-tooltip>Fires on <!> event</span></span><span><span data-tooltip>`);
19
+ var _tmpl$8 = /*#__PURE__*/ template(`<span><span data-tooltip>`);
20
+ var _tmpl$9 = /*#__PURE__*/ template(`<span>i<span data-tooltip>`);
21
+ var _tmpl$0 = /*#__PURE__*/ template(`<span>custom`);
22
+ var _tmpl$1 = /*#__PURE__*/ template(`<div><span><span></span><span></span></span><div><span><span data-tooltip>`);
23
+ var _tmpl$10 = /*#__PURE__*/ template(`<button>&times;`);
24
+ var _tmpl$11 = /*#__PURE__*/ template(`<div><input type=text placeholder="Search hotkeys...">`);
25
+ var _tmpl$12 = /*#__PURE__*/ template(`<div>Hotkeys (<!>)`);
26
+ var _tmpl$13 = /*#__PURE__*/ template(`<div>`);
27
+ var _tmpl$14 = /*#__PURE__*/ template(`<div>Declared, not registered (<!>)`);
24
28
  function getTargetLabel(target) {
25
29
  if (typeof document !== "undefined" && target === document) return "document";
26
30
  if (typeof window !== "undefined" && target === window) return "window";
@@ -51,9 +55,38 @@ function buildRowTooltip(meta) {
51
55
  if (meta.description) parts.push(meta.description);
52
56
  return parts.length > 0 ? parts.join(" — ") : void 0;
53
57
  }
54
- function SequenceListRow(props) {
58
+ /** Formats a hotkey step by step, highlighting matched sequence steps. */
59
+ function RegistrationKeys(props) {
55
60
  const styles = useStyles();
56
- const sequenceRegistrations = () => props.getSequences();
61
+ return createComponent(Show, {
62
+ get when() {
63
+ return memo(() => props.reg.kind === "sequence")() && props.reg;
64
+ },
65
+ get fallback() {
66
+ return formatRegistration(props.reg);
67
+ },
68
+ children: (sequence) => createComponent(For, {
69
+ get each() {
70
+ return sequence().hotkey;
71
+ },
72
+ children: (step, i) => (() => {
73
+ var _el$ = _tmpl$(), _el$2 = _el$.firstChild;
74
+ insert(_el$, createComponent(Show, {
75
+ get when() {
76
+ return i() > 0;
77
+ },
78
+ children: " "
79
+ }), _el$2);
80
+ insert(_el$2, () => formatForDisplay(step, { platform: props.reg.options.platform }));
81
+ effect(() => className(_el$2, i() < props.matchedSteps() ? styles().sequenceStepMatched : void 0));
82
+ return _el$;
83
+ })()
84
+ })
85
+ });
86
+ }
87
+ function RegistrationRow(props) {
88
+ const styles = useStyles();
89
+ const state = useHotkeysDevtoolsState();
57
90
  const conflicts = useRegistrationConflicts(() => props.reg);
58
91
  const targetConflicts = () => conflicts().overlapping;
59
92
  const scopeConflicts = () => conflicts().separate;
@@ -66,9 +99,12 @@ function SequenceListRow(props) {
66
99
  });
67
100
  const scopeConflictTooltip = () => `Info: ${scopeConflicts().length} related bindings on separate targets`;
68
101
  const enabled = () => props.reg.options.enabled !== false;
69
- const liveSequenceReg = createMemo(() => sequenceRegistrations().find((r) => r.id === props.reg.id) ?? props.reg);
70
- const triggerCount = () => sequenceRegistrations().find((r) => r.id === props.reg.id)?.triggerCount ?? props.reg.triggerCount;
71
- const matchedSteps = createMemo(() => effectiveSequenceMatchedSteps(liveSequenceReg(), props.sequenceProgressNow()));
102
+ const liveReg = createMemo(() => state.registrations().find((r) => r.id === props.reg.id) ?? props.reg);
103
+ const triggerCount = () => liveReg().triggerCount;
104
+ const matchedSteps = createMemo(() => {
105
+ const reg = liveReg();
106
+ return reg.kind === "sequence" ? effectiveSequenceMatchedSteps(reg, props.sequenceProgressNow()) : 0;
107
+ });
72
108
  const [prevCount, setPrevCount] = createSignal(props.reg.triggerCount);
73
109
  const [pulsing, setPulsing] = createSignal(false);
74
110
  createEffect(on(triggerCount, (current) => {
@@ -81,116 +117,133 @@ function SequenceListRow(props) {
81
117
  const metaName = () => props.reg.options.meta?.name;
82
118
  const rowTooltip = () => buildRowTooltip(props.reg.options.meta);
83
119
  return (() => {
84
- var _el$ = _tmpl$4(), _el$3 = _el$.firstChild, _el$4 = _el$3.firstChild, _el$8 = _el$3.nextSibling, _el$9 = _el$8.firstChild, _el$0 = _el$9.nextSibling, _el$1 = _el$0.firstChild, _el$10 = _el$0.nextSibling, _el$11 = _el$10.firstChild, _el$14 = _el$11.firstChild.nextSibling;
85
- _el$14.nextSibling;
86
- var _el$15 = _el$10.nextSibling, _el$16 = _el$15.firstChild;
87
- _el$.$$click = () => props.setSelectedId(props.reg.id);
88
- insert(_el$, createComponent(Show, {
120
+ var _el$3 = _tmpl$7(), _el$5 = _el$3.firstChild, _el$6 = _el$5.firstChild, _el$0 = _el$5.nextSibling, _el$10 = _el$0.firstChild, _el$14 = _el$10.nextSibling, _el$15 = _el$14.firstChild, _el$16 = _el$14.nextSibling, _el$17 = _el$16.firstChild, _el$20 = _el$17.firstChild.nextSibling;
121
+ _el$20.nextSibling;
122
+ var _el$21 = _el$16.nextSibling, _el$22 = _el$21.firstChild;
123
+ _el$3.$$click = () => props.setSelectedId(props.reg.id);
124
+ insert(_el$3, createComponent(Show, {
89
125
  get when() {
90
126
  return rowTooltip();
91
127
  },
92
128
  get children() {
93
- var _el$2 = _tmpl$();
94
- insert(_el$2, rowTooltip);
95
- effect(() => className(_el$2, styles().rowTooltipText));
96
- return _el$2;
129
+ var _el$4 = _tmpl$2();
130
+ insert(_el$4, rowTooltip);
131
+ effect(() => className(_el$4, styles().rowTooltipText));
132
+ return _el$4;
97
133
  }
98
- }), _el$3);
99
- insert(_el$4, createComponent(For, {
100
- get each() {
101
- return liveSequenceReg().sequence;
134
+ }), _el$5);
135
+ insert(_el$6, createComponent(RegistrationKeys, {
136
+ get reg() {
137
+ return liveReg();
102
138
  },
103
- children: (step, i) => (() => {
104
- var _el$17 = _tmpl$5(), _el$18 = _el$17.firstChild;
105
- insert(_el$17, createComponent(Show, {
106
- get when() {
107
- return i() > 0;
108
- },
109
- children: " "
110
- }), _el$18);
111
- insert(_el$18, () => formatForDisplay(step, { platform: props.reg.options.platform }));
112
- effect(() => className(_el$18, i() < matchedSteps() ? styles().sequenceStepMatched : void 0));
113
- return _el$17;
114
- })()
139
+ matchedSteps
115
140
  }));
116
- insert(_el$3, createComponent(Show, {
141
+ insert(_el$5, createComponent(Show, {
117
142
  get when() {
118
143
  return metaName();
119
144
  },
120
145
  get children() {
121
- var _el$5 = _tmpl$2();
122
- insert(_el$5, metaName);
123
- effect(() => className(_el$5, styles().hotkeyLabelName));
124
- return _el$5;
146
+ var _el$7 = _tmpl$3();
147
+ insert(_el$7, metaName);
148
+ effect(() => className(_el$7, styles().hotkeyLabelName));
149
+ return _el$7;
125
150
  }
126
151
  }), null);
127
- insert(_el$, createComponent(Show, {
152
+ insert(_el$3, createComponent(Show, {
128
153
  get when() {
129
154
  return triggerCount() > 0;
130
155
  },
131
156
  get children() {
132
- var _el$6 = _tmpl$3();
133
- _el$6.firstChild;
134
- insert(_el$6, triggerCount, null);
135
- effect(() => className(_el$6, styles().triggerCount));
136
- return _el$6;
157
+ var _el$8 = _tmpl$4();
158
+ _el$8.firstChild;
159
+ insert(_el$8, triggerCount, null);
160
+ effect(() => className(_el$8, styles().triggerCount));
161
+ return _el$8;
162
+ }
163
+ }), _el$0);
164
+ insert(_el$0, createComponent(Show, {
165
+ get when() {
166
+ return props.reg.kind === "sequence";
167
+ },
168
+ get children() {
169
+ var _el$1 = _tmpl$5();
170
+ effect(() => className(_el$1, clsx(styles().badge, styles().badgeTarget)));
171
+ return _el$1;
137
172
  }
138
- }), _el$8);
139
- insert(_el$9, () => getBindingKind(props.reg));
140
- insert(_el$8, (() => {
173
+ }), _el$10);
174
+ insert(_el$10, () => getBindingKind(props.reg));
175
+ insert(_el$0, createComponent(Show, {
176
+ get when() {
177
+ return props.appHotkey()?.isCustom;
178
+ },
179
+ get children() {
180
+ var _el$11 = _tmpl$6(), _el$13 = _el$11.firstChild.nextSibling;
181
+ effect((_p$) => {
182
+ var _v$ = clsx(styles().badge, styles().badgeCustom, styles().tooltip), _v$2 = styles().tooltipText;
183
+ _v$ !== _p$.e && className(_el$11, _p$.e = _v$);
184
+ _v$2 !== _p$.t && className(_el$13, _p$.t = _v$2);
185
+ return _p$;
186
+ }, {
187
+ e: void 0,
188
+ t: void 0
189
+ });
190
+ return _el$11;
191
+ }
192
+ }), _el$14);
193
+ insert(_el$0, (() => {
141
194
  var _c$ = memo(() => !!hasTargetConflict());
142
195
  return () => _c$() && (() => {
143
- var _el$19 = _tmpl$6(), _el$20 = _el$19.firstChild;
144
- insert(_el$19, () => targetConflictBadge().label, _el$20);
145
- insert(_el$20, () => targetConflictBadge().tooltip);
196
+ var _el$23 = _tmpl$8(), _el$24 = _el$23.firstChild;
197
+ insert(_el$23, () => targetConflictBadge().label, _el$24);
198
+ insert(_el$24, () => targetConflictBadge().tooltip);
146
199
  effect((_p$) => {
147
- var _v$10 = clsx(styles().badge, styles()[targetConflictBadge().style], styles().tooltip), _v$11 = styles().tooltipText;
148
- _v$10 !== _p$.e && className(_el$19, _p$.e = _v$10);
149
- _v$11 !== _p$.t && className(_el$20, _p$.t = _v$11);
200
+ var _v$12 = clsx(styles().badge, styles()[targetConflictBadge().style], styles().tooltip), _v$13 = styles().tooltipText;
201
+ _v$12 !== _p$.e && className(_el$23, _p$.e = _v$12);
202
+ _v$13 !== _p$.t && className(_el$24, _p$.t = _v$13);
150
203
  return _p$;
151
204
  }, {
152
205
  e: void 0,
153
206
  t: void 0
154
207
  });
155
- return _el$19;
208
+ return _el$23;
156
209
  })();
157
- })(), _el$0);
158
- insert(_el$8, (() => {
210
+ })(), _el$14);
211
+ insert(_el$0, (() => {
159
212
  var _c$2 = memo(() => !!hasScopeConflict());
160
213
  return () => _c$2() && (() => {
161
- var _el$21 = _tmpl$7(), _el$23 = _el$21.firstChild.nextSibling;
162
- insert(_el$23, scopeConflictTooltip);
214
+ var _el$25 = _tmpl$9(), _el$27 = _el$25.firstChild.nextSibling;
215
+ insert(_el$27, scopeConflictTooltip);
163
216
  effect((_p$) => {
164
- var _v$12 = clsx(styles().badge, styles().badgeInfo, styles().tooltip), _v$13 = styles().tooltipText;
165
- _v$12 !== _p$.e && className(_el$21, _p$.e = _v$12);
166
- _v$13 !== _p$.t && className(_el$23, _p$.t = _v$13);
217
+ var _v$14 = clsx(styles().badge, styles().badgeInfo, styles().tooltip), _v$15 = styles().tooltipText;
218
+ _v$14 !== _p$.e && className(_el$25, _p$.e = _v$14);
219
+ _v$15 !== _p$.t && className(_el$27, _p$.t = _v$15);
167
220
  return _p$;
168
221
  }, {
169
222
  e: void 0,
170
223
  t: void 0
171
224
  });
172
- return _el$21;
225
+ return _el$25;
173
226
  })();
174
- })(), _el$0);
175
- insert(_el$0, () => enabled() ? "on" : "off", _el$1);
176
- insert(_el$1, () => enabled() ? "Sequence is enabled" : "Sequence is disabled");
177
- insert(_el$10, () => props.reg.options.eventType ?? "keydown", _el$11);
178
- insert(_el$11, () => props.reg.options.eventType ?? "keydown", _el$14);
179
- insert(_el$15, () => getTargetLabel(props.reg.target), _el$16);
180
- insert(_el$16, () => getTargetTooltip(props.reg.target));
227
+ })(), _el$14);
228
+ insert(_el$14, () => enabled() ? "on" : "off", _el$15);
229
+ insert(_el$15, () => enabled() ? "Hotkey is enabled" : "Hotkey is disabled");
230
+ insert(_el$16, () => props.reg.options.eventType ?? "keydown", _el$17);
231
+ insert(_el$17, () => props.reg.options.eventType ?? "keydown", _el$20);
232
+ insert(_el$21, () => getTargetLabel(props.reg.target), _el$22);
233
+ insert(_el$22, () => getTargetTooltip(props.reg.target));
181
234
  effect((_p$) => {
182
- var _v$ = clsx(styles().hotkeyRow, props.selectedId() === props.reg.id && styles().hotkeyRowSelected, pulsing() && styles().hotkeyRowTriggered, rowTooltip() && styles().tooltip), _v$2 = styles().hotkeyLabel, _v$3 = styles().hotkeyLabelKeys, _v$4 = styles().hotkeyBadges, _v$5 = clsx(styles().badge, styles().badgeTarget), _v$6 = clsx(styles().badge, enabled() ? styles().badgeEnabled : styles().badgeDisabled, styles().tooltip), _v$7 = styles().tooltipText, _v$8 = clsx(styles().badge, (props.reg.options.eventType ?? "keydown") === "keydown" ? styles().badgeKeydown : styles().badgeKeyup, styles().tooltip), _v$9 = styles().tooltipText, _v$0 = clsx(styles().badge, styles().badgeTarget, styles().tooltip), _v$1 = styles().tooltipText;
183
- _v$ !== _p$.e && className(_el$, _p$.e = _v$);
184
- _v$2 !== _p$.t && className(_el$3, _p$.t = _v$2);
185
- _v$3 !== _p$.a && className(_el$4, _p$.a = _v$3);
186
- _v$4 !== _p$.o && className(_el$8, _p$.o = _v$4);
187
- _v$5 !== _p$.i && className(_el$9, _p$.i = _v$5);
188
- _v$6 !== _p$.n && className(_el$0, _p$.n = _v$6);
189
- _v$7 !== _p$.s && className(_el$1, _p$.s = _v$7);
190
- _v$8 !== _p$.h && className(_el$10, _p$.h = _v$8);
191
- _v$9 !== _p$.r && className(_el$11, _p$.r = _v$9);
192
- _v$0 !== _p$.d && className(_el$15, _p$.d = _v$0);
193
- _v$1 !== _p$.l && className(_el$16, _p$.l = _v$1);
235
+ var _v$3 = clsx(styles().hotkeyRow, props.selectedId() === props.reg.id && styles().hotkeyRowSelected, pulsing() && styles().hotkeyRowTriggered, rowTooltip() && styles().tooltip), _v$4 = styles().hotkeyLabel, _v$5 = styles().hotkeyLabelKeys, _v$6 = styles().hotkeyBadges, _v$7 = clsx(styles().badge, styles().badgeTarget), _v$8 = clsx(styles().badge, enabled() ? styles().badgeEnabled : styles().badgeDisabled, styles().tooltip), _v$9 = styles().tooltipText, _v$0 = clsx(styles().badge, (props.reg.options.eventType ?? "keydown") === "keydown" ? styles().badgeKeydown : styles().badgeKeyup, styles().tooltip), _v$1 = styles().tooltipText, _v$10 = clsx(styles().badge, styles().badgeTarget, styles().tooltip), _v$11 = styles().tooltipText;
236
+ _v$3 !== _p$.e && className(_el$3, _p$.e = _v$3);
237
+ _v$4 !== _p$.t && className(_el$5, _p$.t = _v$4);
238
+ _v$5 !== _p$.a && className(_el$6, _p$.a = _v$5);
239
+ _v$6 !== _p$.o && className(_el$0, _p$.o = _v$6);
240
+ _v$7 !== _p$.i && className(_el$10, _p$.i = _v$7);
241
+ _v$8 !== _p$.n && className(_el$14, _p$.n = _v$8);
242
+ _v$9 !== _p$.s && className(_el$15, _p$.s = _v$9);
243
+ _v$0 !== _p$.h && className(_el$16, _p$.h = _v$0);
244
+ _v$1 !== _p$.r && className(_el$17, _p$.r = _v$1);
245
+ _v$10 !== _p$.d && className(_el$21, _p$.d = _v$10);
246
+ _v$11 !== _p$.l && className(_el$22, _p$.l = _v$11);
194
247
  return _p$;
195
248
  }, {
196
249
  e: void 0,
@@ -205,234 +258,130 @@ function SequenceListRow(props) {
205
258
  d: void 0,
206
259
  l: void 0
207
260
  });
208
- return _el$;
261
+ return _el$3;
209
262
  })();
210
263
  }
264
+ /** A declared app hotkey that nothing has registered, or that has no hotkey. */
265
+ function AppHotkeyRow(props) {
266
+ const styles = useStyles();
267
+ const id = () => appHotkeySelectionId(props.item.appHotkey.id);
268
+ const hotkey = () => props.item.appHotkey.hotkey;
269
+ return (() => {
270
+ var _el$28 = _tmpl$1(), _el$29 = _el$28.firstChild, _el$30 = _el$29.firstChild, _el$31 = _el$30.nextSibling, _el$32 = _el$29.nextSibling, _el$34 = _el$32.firstChild, _el$35 = _el$34.firstChild;
271
+ _el$28.$$click = () => props.setSelectedId(id());
272
+ insert(_el$30, (() => {
273
+ var _c$3 = memo(() => !!hotkey());
274
+ return () => _c$3() ? formatForDisplay(hotkey(), { sequenceSeparator: " → " }) : "Unassigned";
275
+ })());
276
+ insert(_el$31, () => props.item.appHotkey.meta?.name ?? props.item.appHotkey.id);
277
+ insert(_el$32, createComponent(Show, {
278
+ get when() {
279
+ return props.item.isCustom;
280
+ },
281
+ get children() {
282
+ var _el$33 = _tmpl$0();
283
+ effect(() => className(_el$33, clsx(styles().badge, styles().badgeCustom)));
284
+ return _el$33;
285
+ }
286
+ }), _el$34);
287
+ insert(_el$34, () => props.item.status, _el$35);
288
+ insert(_el$35, () => props.item.status === "unbound" ? "Declared without a hotkey" : "Declared but not registered on this page");
289
+ effect((_p$) => {
290
+ var _v$16 = clsx(styles().hotkeyRow, styles().hotkeyRowInactive, props.selectedId() === id() && styles().hotkeyRowSelected), _v$17 = styles().hotkeyLabel, _v$18 = styles().hotkeyLabelKeys, _v$19 = styles().hotkeyLabelName, _v$20 = styles().hotkeyBadges, _v$21 = clsx(styles().badge, styles().badgeDisabled, styles().tooltip), _v$22 = styles().tooltipText;
291
+ _v$16 !== _p$.e && className(_el$28, _p$.e = _v$16);
292
+ _v$17 !== _p$.t && className(_el$29, _p$.t = _v$17);
293
+ _v$18 !== _p$.a && className(_el$30, _p$.a = _v$18);
294
+ _v$19 !== _p$.o && className(_el$31, _p$.o = _v$19);
295
+ _v$20 !== _p$.i && className(_el$32, _p$.i = _v$20);
296
+ _v$21 !== _p$.n && className(_el$34, _p$.n = _v$21);
297
+ _v$22 !== _p$.s && className(_el$35, _p$.s = _v$22);
298
+ return _p$;
299
+ }, {
300
+ e: void 0,
301
+ t: void 0,
302
+ a: void 0,
303
+ o: void 0,
304
+ i: void 0,
305
+ n: void 0,
306
+ s: void 0
307
+ });
308
+ return _el$28;
309
+ })();
310
+ }
311
+ /** Selection ids for app hotkeys, kept distinct from registration ids. */
312
+ function appHotkeySelectionId(id) {
313
+ return `app:${id}`;
314
+ }
211
315
  function HotkeyList(props) {
212
316
  const styles = useStyles();
213
317
  const state = useHotkeysDevtoolsState();
214
318
  const [searchQuery, setSearchQuery] = createSignal("");
215
- const registrations = createMemo(() => state.registrations());
216
- const sequenceRegistrations = createMemo(() => state.sequenceRegistrations());
319
+ const appHotkeyById = createMemo(() => new Map(state.appHotkeys().map((item) => [item.appHotkey.id, item])));
217
320
  const filteredRegistrations = createMemo(() => {
218
321
  const query = searchQuery().trim();
219
- if (!query) return registrations();
220
- return matchSorter(registrations(), query, { keys: [
322
+ if (!query) return state.registrations();
323
+ return matchSorter(state.registrations(), query, { keys: [
221
324
  (r) => formatRegistration(r),
222
- "hotkey",
325
+ (r) => typeof r.hotkey === "string" ? r.hotkey : r.hotkey.join(" "),
223
326
  "options.meta.name",
224
327
  "options.meta.description",
225
328
  "options.meta.group"
226
329
  ] });
227
330
  });
228
- const filteredSequenceRegistrations = createMemo(() => {
331
+ const filteredAppHotkeys = createMemo(() => {
332
+ const unregistered = state.appHotkeys().filter((item) => item.registrations.length === 0);
229
333
  const query = searchQuery().trim();
230
- if (!query) return sequenceRegistrations();
231
- return matchSorter(sequenceRegistrations(), query, { keys: [
232
- (r) => formatRegistration(r),
233
- (r) => r.sequence.join(" "),
234
- "options.meta.name",
235
- "options.meta.description",
236
- "options.meta.group"
334
+ if (!query) return unregistered;
335
+ return matchSorter(unregistered, query, { keys: [
336
+ "appHotkey.id",
337
+ "appHotkey.meta.name",
338
+ "appHotkey.meta.description",
339
+ "appHotkey.meta.group"
237
340
  ] });
238
341
  });
239
342
  return [
240
343
  (() => {
241
- var _el$24 = _tmpl$9(), _el$25 = _el$24.firstChild;
242
- _el$25.$$input = (e) => setSearchQuery(e.currentTarget.value);
243
- insert(_el$24, createComponent(Show, {
344
+ var _el$36 = _tmpl$11(), _el$37 = _el$36.firstChild;
345
+ _el$37.$$input = (e) => setSearchQuery(e.currentTarget.value);
346
+ insert(_el$36, createComponent(Show, {
244
347
  get when() {
245
348
  return searchQuery();
246
349
  },
247
350
  get children() {
248
- var _el$26 = _tmpl$8();
249
- _el$26.$$click = () => setSearchQuery("");
250
- effect(() => className(_el$26, styles().searchClear));
251
- return _el$26;
351
+ var _el$38 = _tmpl$10();
352
+ _el$38.$$click = () => setSearchQuery("");
353
+ effect(() => className(_el$38, styles().searchClear));
354
+ return _el$38;
252
355
  }
253
356
  }), null);
254
357
  effect((_p$) => {
255
- var _v$14 = styles().searchContainer, _v$15 = styles().searchInput;
256
- _v$14 !== _p$.e && className(_el$24, _p$.e = _v$14);
257
- _v$15 !== _p$.t && className(_el$25, _p$.t = _v$15);
358
+ var _v$23 = styles().searchContainer, _v$24 = styles().searchInput;
359
+ _v$23 !== _p$.e && className(_el$36, _p$.e = _v$23);
360
+ _v$24 !== _p$.t && className(_el$37, _p$.t = _v$24);
258
361
  return _p$;
259
362
  }, {
260
363
  e: void 0,
261
364
  t: void 0
262
365
  });
263
- effect(() => _el$25.value = searchQuery());
264
- return _el$24;
366
+ effect(() => _el$37.value = searchQuery());
367
+ return _el$36;
265
368
  })(),
266
369
  (() => {
267
- var _el$27 = _tmpl$0(), _el$30 = _el$27.firstChild.nextSibling;
268
- _el$30.nextSibling;
269
- insert(_el$27, () => filteredRegistrations().length, _el$30);
270
- effect(() => className(_el$27, styles().panelHeader));
271
- return _el$27;
370
+ var _el$39 = _tmpl$12(), _el$42 = _el$39.firstChild.nextSibling;
371
+ _el$42.nextSibling;
372
+ insert(_el$39, () => filteredRegistrations().length, _el$42);
373
+ effect(() => className(_el$39, styles().panelHeader));
374
+ return _el$39;
272
375
  })(),
273
376
  (() => {
274
- var _el$31 = _tmpl$1();
275
- insert(_el$31, createComponent(For, {
377
+ var _el$43 = _tmpl$13();
378
+ insert(_el$43, createComponent(For, {
276
379
  get each() {
277
380
  return filteredRegistrations();
278
381
  },
279
- children: (reg) => {
280
- const conflicts = useRegistrationConflicts(() => reg);
281
- const targetConflicts = () => conflicts().overlapping;
282
- const scopeConflicts = () => conflicts().separate;
283
- const hasTargetConflict = () => targetConflicts().length > 0;
284
- const hasScopeConflict = () => scopeConflicts().length > 0;
285
- const targetConflictBadge = () => ({
286
- style: "badgeConflict",
287
- label: "!",
288
- tooltip: `Potential overlap: ${targetConflicts().length} other bindings on overlapping targets`
289
- });
290
- const scopeConflictTooltip = () => `Info: ${scopeConflicts().length} related bindings on separate targets`;
291
- const enabled = () => reg.options.enabled !== false;
292
- const triggerCount = () => registrations().find((r) => r.id === reg.id)?.triggerCount ?? reg.triggerCount;
293
- const [prevCount, setPrevCount] = createSignal(reg.triggerCount);
294
- const [pulsing, setPulsing] = createSignal(false);
295
- createEffect(on(triggerCount, (current) => {
296
- if (current > prevCount()) {
297
- setPulsing(true);
298
- setTimeout(() => setPulsing(false), 600);
299
- }
300
- setPrevCount(current);
301
- }));
302
- const metaName = () => reg.options.meta?.name;
303
- const rowTooltip = () => buildRowTooltip(reg.options.meta);
304
- return (() => {
305
- var _el$37 = _tmpl$4(), _el$39 = _el$37.firstChild, _el$40 = _el$39.firstChild, _el$44 = _el$39.nextSibling, _el$45 = _el$44.firstChild, _el$46 = _el$45.nextSibling, _el$47 = _el$46.firstChild, _el$48 = _el$46.nextSibling, _el$49 = _el$48.firstChild, _el$52 = _el$49.firstChild.nextSibling;
306
- _el$52.nextSibling;
307
- var _el$53 = _el$48.nextSibling, _el$54 = _el$53.firstChild;
308
- _el$37.$$click = () => props.setSelectedId(reg.id);
309
- insert(_el$37, createComponent(Show, {
310
- get when() {
311
- return rowTooltip();
312
- },
313
- get children() {
314
- var _el$38 = _tmpl$();
315
- insert(_el$38, rowTooltip);
316
- effect(() => className(_el$38, styles().rowTooltipText));
317
- return _el$38;
318
- }
319
- }), _el$39);
320
- insert(_el$40, () => formatRegistration(reg));
321
- insert(_el$39, createComponent(Show, {
322
- get when() {
323
- return metaName();
324
- },
325
- get children() {
326
- var _el$41 = _tmpl$2();
327
- insert(_el$41, metaName);
328
- effect(() => className(_el$41, styles().hotkeyLabelName));
329
- return _el$41;
330
- }
331
- }), null);
332
- insert(_el$37, createComponent(Show, {
333
- get when() {
334
- return triggerCount() > 0;
335
- },
336
- get children() {
337
- var _el$42 = _tmpl$3();
338
- _el$42.firstChild;
339
- insert(_el$42, triggerCount, null);
340
- effect(() => className(_el$42, styles().triggerCount));
341
- return _el$42;
342
- }
343
- }), _el$44);
344
- insert(_el$45, () => getBindingKind(reg));
345
- insert(_el$44, (() => {
346
- var _c$3 = memo(() => !!hasTargetConflict());
347
- return () => _c$3() && (() => {
348
- var _el$55 = _tmpl$6(), _el$56 = _el$55.firstChild;
349
- insert(_el$55, () => targetConflictBadge().label, _el$56);
350
- insert(_el$56, () => targetConflictBadge().tooltip);
351
- effect((_p$) => {
352
- var _v$27 = clsx(styles().badge, styles()[targetConflictBadge().style], styles().tooltip), _v$28 = styles().tooltipText;
353
- _v$27 !== _p$.e && className(_el$55, _p$.e = _v$27);
354
- _v$28 !== _p$.t && className(_el$56, _p$.t = _v$28);
355
- return _p$;
356
- }, {
357
- e: void 0,
358
- t: void 0
359
- });
360
- return _el$55;
361
- })();
362
- })(), _el$46);
363
- insert(_el$44, (() => {
364
- var _c$4 = memo(() => !!hasScopeConflict());
365
- return () => _c$4() && (() => {
366
- var _el$57 = _tmpl$7(), _el$59 = _el$57.firstChild.nextSibling;
367
- insert(_el$59, scopeConflictTooltip);
368
- effect((_p$) => {
369
- var _v$29 = clsx(styles().badge, styles().badgeInfo, styles().tooltip), _v$30 = styles().tooltipText;
370
- _v$29 !== _p$.e && className(_el$57, _p$.e = _v$29);
371
- _v$30 !== _p$.t && className(_el$59, _p$.t = _v$30);
372
- return _p$;
373
- }, {
374
- e: void 0,
375
- t: void 0
376
- });
377
- return _el$57;
378
- })();
379
- })(), _el$46);
380
- insert(_el$46, () => enabled() ? "on" : "off", _el$47);
381
- insert(_el$47, () => enabled() ? "Hotkey is enabled" : "Hotkey is disabled");
382
- insert(_el$48, () => reg.options.eventType ?? "keydown", _el$49);
383
- insert(_el$49, () => reg.options.eventType ?? "keydown", _el$52);
384
- insert(_el$53, () => getTargetLabel(reg.target), _el$54);
385
- insert(_el$54, () => getTargetTooltip(reg.target));
386
- effect((_p$) => {
387
- var _v$16 = clsx(styles().hotkeyRow, props.selectedId() === reg.id && styles().hotkeyRowSelected, pulsing() && styles().hotkeyRowTriggered, rowTooltip() && styles().tooltip), _v$17 = styles().hotkeyLabel, _v$18 = styles().hotkeyLabelKeys, _v$19 = styles().hotkeyBadges, _v$20 = clsx(styles().badge, styles().badgeTarget), _v$21 = clsx(styles().badge, enabled() ? styles().badgeEnabled : styles().badgeDisabled, styles().tooltip), _v$22 = styles().tooltipText, _v$23 = clsx(styles().badge, (reg.options.eventType ?? "keydown") === "keydown" ? styles().badgeKeydown : styles().badgeKeyup, styles().tooltip), _v$24 = styles().tooltipText, _v$25 = clsx(styles().badge, styles().badgeTarget, styles().tooltip), _v$26 = styles().tooltipText;
388
- _v$16 !== _p$.e && className(_el$37, _p$.e = _v$16);
389
- _v$17 !== _p$.t && className(_el$39, _p$.t = _v$17);
390
- _v$18 !== _p$.a && className(_el$40, _p$.a = _v$18);
391
- _v$19 !== _p$.o && className(_el$44, _p$.o = _v$19);
392
- _v$20 !== _p$.i && className(_el$45, _p$.i = _v$20);
393
- _v$21 !== _p$.n && className(_el$46, _p$.n = _v$21);
394
- _v$22 !== _p$.s && className(_el$47, _p$.s = _v$22);
395
- _v$23 !== _p$.h && className(_el$48, _p$.h = _v$23);
396
- _v$24 !== _p$.r && className(_el$49, _p$.r = _v$24);
397
- _v$25 !== _p$.d && className(_el$53, _p$.d = _v$25);
398
- _v$26 !== _p$.l && className(_el$54, _p$.l = _v$26);
399
- return _p$;
400
- }, {
401
- e: void 0,
402
- t: void 0,
403
- a: void 0,
404
- o: void 0,
405
- i: void 0,
406
- n: void 0,
407
- s: void 0,
408
- h: void 0,
409
- r: void 0,
410
- d: void 0,
411
- l: void 0
412
- });
413
- return _el$37;
414
- })();
415
- }
416
- }));
417
- effect(() => className(_el$31, styles().hotkeyList));
418
- return _el$31;
419
- })(),
420
- (() => {
421
- var _el$32 = _tmpl$10(), _el$35 = _el$32.firstChild.nextSibling;
422
- _el$35.nextSibling;
423
- insert(_el$32, () => filteredSequenceRegistrations().length, _el$35);
424
- effect(() => className(_el$32, styles().panelHeader));
425
- return _el$32;
426
- })(),
427
- (() => {
428
- var _el$36 = _tmpl$1();
429
- insert(_el$36, createComponent(For, {
430
- get each() {
431
- return filteredSequenceRegistrations();
432
- },
433
- children: (reg) => createComponent(SequenceListRow, {
382
+ children: (reg) => createComponent(RegistrationRow, {
434
383
  reg,
435
- getSequences: sequenceRegistrations,
384
+ appHotkey: () => reg.options.appHotkeyId === void 0 ? void 0 : appHotkeyById().get(reg.options.appHotkeyId),
436
385
  get sequenceProgressNow() {
437
386
  return state.sequenceProgressNow;
438
387
  },
@@ -444,12 +393,44 @@ function HotkeyList(props) {
444
393
  }
445
394
  })
446
395
  }));
447
- effect(() => className(_el$36, styles().hotkeyList));
448
- return _el$36;
449
- })()
396
+ effect(() => className(_el$43, styles().hotkeyList));
397
+ return _el$43;
398
+ })(),
399
+ createComponent(Show, {
400
+ get when() {
401
+ return state.appHotkeys().length > 0;
402
+ },
403
+ get children() {
404
+ return [(() => {
405
+ var _el$44 = _tmpl$14(), _el$47 = _el$44.firstChild.nextSibling;
406
+ _el$47.nextSibling;
407
+ insert(_el$44, () => filteredAppHotkeys().length, _el$47);
408
+ effect(() => className(_el$44, styles().panelHeader));
409
+ return _el$44;
410
+ })(), (() => {
411
+ var _el$48 = _tmpl$13();
412
+ insert(_el$48, createComponent(For, {
413
+ get each() {
414
+ return filteredAppHotkeys();
415
+ },
416
+ children: (item) => createComponent(AppHotkeyRow, {
417
+ item,
418
+ get selectedId() {
419
+ return props.selectedId;
420
+ },
421
+ get setSelectedId() {
422
+ return props.setSelectedId;
423
+ }
424
+ })
425
+ }));
426
+ effect(() => className(_el$48, styles().hotkeyList));
427
+ return _el$48;
428
+ })()];
429
+ }
430
+ })
450
431
  ];
451
432
  }
452
433
  delegateEvents(["click", "input"]);
453
434
 
454
435
  //#endregion
455
- export { HotkeyList };
436
+ export { HotkeyList, appHotkeySelectionId };
@@ -1,7 +1,7 @@
1
1
  import { useHotkeysDevtoolsState } from "../HotkeysContextProvider.js";
2
2
  import { useStyles } from "../styles/use-styles.js";
3
3
  import { HeldKeysBar } from "./HeldKeysTopbar.js";
4
- import { HotkeyList } from "./HotkeyList.js";
4
+ import { HotkeyList, appHotkeySelectionId } from "./HotkeyList.js";
5
5
  import { DetailsPanel } from "./DetailsPanel.js";
6
6
  import { className, createComponent, delegateEvents, effect, insert, setStyleProperty, style, template, use } from "solid-js/web";
7
7
  import { Header, HeaderLogo, MainPanel } from "@tanstack/devtools-ui";
@@ -31,12 +31,19 @@ function Shell() {
31
31
  const [isDragging, setIsDragging] = createSignal(false);
32
32
  const [shellRootEl, setShellRootEl] = createSignal(null);
33
33
  const [slotHeightPx, setSlotHeightPx] = createSignal(void 0);
34
- const selectedRegistration = createMemo(() => {
34
+ const selection = createMemo(() => {
35
35
  const id = selectedId();
36
36
  if (!id) return null;
37
- const hotkey = state.registrations().find((r) => r.id === id);
38
- if (hotkey) return hotkey;
39
- return state.sequenceRegistrations().find((r) => r.id === id) ?? null;
37
+ const registration = state.registrations().find((r) => r.id === id);
38
+ if (registration) return {
39
+ type: "registration",
40
+ registration
41
+ };
42
+ const item = state.appHotkeys().find((i) => appHotkeySelectionId(i.appHotkey.id) === id);
43
+ return item ? {
44
+ type: "appHotkey",
45
+ item
46
+ } : null;
40
47
  });
41
48
  let dragStartX = 0;
42
49
  let dragStartWidth = 0;
@@ -111,7 +118,7 @@ function Shell() {
111
118
  setSelectedId
112
119
  }));
113
120
  _el$6.$$mousedown = handleMouseDown;
114
- insert(_el$7, createComponent(DetailsPanel, { selectedRegistration }), null);
121
+ insert(_el$7, createComponent(DetailsPanel, { selection }), null);
115
122
  effect((_p$) => {
116
123
  var _v$ = styles().mainContainer, _v$2 = styles().panelsContainer, _v$3 = styles().leftPanel, _v$4 = `${leftPanelWidth()}px`, _v$5 = styles().leftPanelScroll, _v$6 = `${styles().dragHandle} ${isDragging() ? "dragging" : ""}`, _v$7 = styles().rightPanel, _v$8 = styles().panelHeader;
117
124
  _v$ !== _p$.e && className(_el$2, _p$.e = _v$);
@@ -12,7 +12,7 @@ function effectiveSequenceMatchedSteps(reg, now) {
12
12
  }
13
13
  /** Whether the devtools should run a short interval to refresh sequence progress UI. */
14
14
  function needsSequenceProgressClock(regs, now) {
15
- return regs.some((reg) => effectiveSequenceMatchedSteps(reg, now) > 0);
15
+ return regs.some((reg) => reg.kind === "sequence" && effectiveSequenceMatchedSteps(reg, now) > 0);
16
16
  }
17
17
 
18
18
  //#endregion
@@ -250,6 +250,11 @@ const stylesFactory = (theme) => {
250
250
  background: ${t(colors.gray[300], colors.darkGray[600])};
251
251
  border-color: ${t(colors.gray[400], colors.darkGray[500])};
252
252
  }
253
+ `,
254
+ hotkeyRowInactive: css`
255
+ opacity: 0.65;
256
+ border-style: dashed;
257
+ border-color: ${t(colors.gray[400], colors.darkGray[500])};
253
258
  `,
254
259
  hotkeyRowSelected: css`
255
260
  background: ${t(colors.blue[100], colors.blue[900] + alpha[20])};
@@ -319,6 +324,10 @@ const stylesFactory = (theme) => {
319
324
  badgeEnabled: css`
320
325
  color: ${t(colors.green[700], colors.green[400])};
321
326
  background: ${t(colors.green[100], colors.green[900] + alpha[30])};
327
+ `,
328
+ badgeCustom: css`
329
+ color: ${t(colors.blue[700], colors.blue[400])};
330
+ background: ${t(colors.blue[100], colors.blue[900] + alpha[30])};
322
331
  `,
323
332
  badgeDisabled: css`
324
333
  color: ${t(colors.red[700], colors.red[400])};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/hotkeys-devtools",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Devtools for TanStack Hotkeys",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "dist"
37
37
  ],
38
38
  "peerDependencies": {
39
- "@tanstack/hotkeys": "0.11.0"
39
+ "@tanstack/hotkeys": "0.12.0"
40
40
  },
41
41
  "dependencies": {
42
42
  "@tanstack/devtools-ui": "^0.7.1",