summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/behaviors/shortcuts/shortcut.vue
blob: 383841570076c24eb0e6336e2dd8bc20fff7b184 (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
<script>
import { getModifierKey } from '~/constants';
import { __, s__ } from '~/locale';

// Map some keys to their proper representation depending on the system
// See also: https://craig.is/killing/mice#keys
const getKeyMap = () => {
  const keyMap = {
    up: '↑',
    down: '↓',
    left: '←',
    right: '→',
    ctrl: s__('KeyboardKey|Ctrl'),
    shift: s__('KeyboardKey|Shift'),
    enter: s__('KeyboardKey|Enter'),
    esc: s__('KeyboardKey|Esc'),
    command: '⌘',
    option: window.gl?.client?.isMac ? '⌥' : s__('KeyboardKey|Alt'),
  };

  // Meta and alt are aliases
  keyMap.meta = keyMap.command;
  keyMap.alt = keyMap.option;

  // Mod is Command on Mac, and Ctrl on Windows/Linux
  keyMap.mod = getModifierKey(true);

  return keyMap;
};

export default {
  functional: true,
  props: {
    shortcuts: {
      type: Array,
      required: true,
    },
  },

  render(createElement, context) {
    const keyMap = getKeyMap();

    const { staticClass } = context.data;

    const shortcuts = context.props.shortcuts.reduce((acc, shortcut, i) => {
      if (
        !window.gl?.client?.isMac &&
        (shortcut.includes('command') || shortcut.includes('meta'))
      ) {
        return acc;
      }
      const keys = shortcut.split(/([ +])/);

      if (i !== 0 && acc.length) {
        acc.push(` ${__('or')} `);
        // If there are multiple alternative shortcuts,
        // we keep them on the same line if they are single-key, e.g. `]` or `j`
        // but if they consist of multiple keys, we insert a line break, e.g.:
        // `shift` + `]` <br> or `shift` + `j`
        if (keys.length > 1) {
          acc.push(createElement('br'));
        }
      }

      keys.forEach((key) => {
        if (key === '+') {
          acc.push(' + ');
        } else if (key === ' ') {
          acc.push(` ${__('then')} `);
        } else {
          acc.push(createElement('kbd', {}, [keyMap[key] ?? key]));
        }
      });

      return acc;
    }, []);

    return createElement('div', { staticClass }, shortcuts);
  },
};
</script>