summaryrefslogtreecommitdiff
path: root/web/js/keyboard.js
blob: de67208293e26ed7604dd64b66356bf522f1000d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
export function initKeyboard(handlers) {
  document.addEventListener('keydown', (e) => {
    const tag = e.target.tagName;
    const editing = tag === 'INPUT' || tag === 'TEXTAREA' || e.target.isContentEditable;
    if (editing) {
      if (e.key === 'Escape') {
        e.target.blur();
        handlers.escape?.(e);
      }
      return;
    }

    // Tab / Shift+Tab set navigation when sidebar is open
    if (e.key === 'Tab') {
      if (handlers.isSidebarOpen?.()) {
        e.preventDefault();
        if (e.shiftKey) {
          handlers.prevSet?.(e);
        } else {
          handlers.nextSet?.(e);
        }
      }
      return;
    }

    // Space toggles focused set selection when sidebar is focused/open
    if (e.key === ' ') {
      if (handlers.isSidebarFocused?.()) {
        e.preventDefault();
        handlers.toggleSetSelect?.(e);
        return;
      }
      e.preventDefault();
      handlers.playPause?.(e);
      return;
    }

    switch (e.key) {
      // Navigation
      case 'ArrowUp':
        e.preventDefault();
        handlers.navUp?.(e);
        break;
      case 'ArrowDown':
        e.preventDefault();
        handlers.navDown?.(e);
        break;
      case 'ArrowLeft':
        handlers.navLeft?.(e);
        break;
      case 'ArrowRight':
        handlers.navRight?.(e);
        break;
      // Vim-style navigation
      case 'k':
        e.preventDefault();
        handlers.navUp?.(e);
        break;
      case 'j':
        e.preventDefault();
        handlers.navDown?.(e);
        break;
      case 'h':
        handlers.navLeft?.(e);
        break;
      case 'l':
        handlers.navRight?.(e);
        break;
      case 'Enter': handlers.enter?.(e); break;
      case 'p': handlers.playPause?.(e); break;
      case 'c': handlers.toggleStage?.(e); break;
      case 'f': handlers.fullscreen?.(e); break;
      case 'Escape': handlers.escape?.(e); break;
      case 'r': handlers.shuffle?.(e); break;
      case 's': handlers.share?.(e); break;
      case '/':
        e.preventDefault();
        handlers.search?.(e);
        break;
      case 'n': handlers.notes?.(e); break;
      case 't': handlers.toolbar?.(e); break;
      case 'm': handlers.sidebar?.(e); break;
      case 'd': handlers.download?.(e); break;
      case 'u': handlers.upload?.(e); break;
      case '?':
        e.preventDefault();
        handlers.help?.(e);
        break;
    }
  });
}