From 918133ca5f9df5063c0a94d0e71cc913446f701f Mon Sep 17 00:00:00 2001
From: Adam Procter <adamprocter@researchnot.es>
Date: Fri, 30 Apr 2021 17:36:19 +0100
Subject: [PATCH] added simple shortcut mixin

---
 src/components/ToolBar.vue | 12 +++++
 src/mixins/shortcuts.js    | 89 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 src/mixins/shortcuts.js

diff --git a/src/components/ToolBar.vue b/src/components/ToolBar.vue
index ad0bdc7..e13daa3 100644
--- a/src/components/ToolBar.vue
+++ b/src/components/ToolBar.vue
@@ -10,6 +10,7 @@
 <script>
 // @ is an alias to /src
 import UploadMedia from '@/components/UploadMedia.vue'
+import shortcuts from '@/mixins/shortcuts'
 
 export default {
   name: 'ToolBar',
@@ -20,6 +21,17 @@ export default {
     return {}
   },
 
+  mixins: [
+    shortcuts('n', function () {
+      // n key pressed
+      this.addNode()
+    }),
+    shortcuts('ArrowRight', function () {
+      // Arrow right key was pressed
+      console.log('->')
+    }),
+  ],
+
   methods: {
     addNode() {
       this.$store.dispatch('addNode')
diff --git a/src/mixins/shortcuts.js b/src/mixins/shortcuts.js
new file mode 100644
index 0000000..94f478b
--- /dev/null
+++ b/src/mixins/shortcuts.js
@@ -0,0 +1,89 @@
+// Original code from here
+// https://gist.github.com/loilo/2a1834dc20d842f63bd048ffbcf3dc19#file-shortcut-mjs
+
+// Modifier keys
+export const CTRL = 0b000001
+export const ALT = 0b000010
+export const SHIFT = 0b000100
+export const META = 0b001000
+
+// The Windows key
+export const WIN = 0b010000
+
+// The CMD key
+export const CMD = 0b100000
+
+// Check for macOS
+const isMac = navigator.appVersion.includes('Macintosh')
+
+// Determine the primary modifier key
+export const PRIMARY = isMac ? CMD : CTRL
+
+/**
+ * Create a mixin for simple keyboard shortcuts
+ *
+ * @param {string|string[]} matcher         The key name(s) to react to
+ * @param {number}          modifierKeys A bitmask of modifier keys
+ * @returns {object}
+ */
+export default function shortcut(matcher, ...args) {
+  // If only one remaining argument, treat it as callback
+  if (args.length === 1) {
+    return shortcut(matcher, 0b0000, args[0])
+  }
+
+  // The key the listener function will be stored at
+  const LISTENER = Symbol('keydown listener')
+
+  let [modifierKeys, callback] = args
+
+  // Check modifier keys for WIN or CMD
+  let excludedByOS = false
+  if (modifierKeys & (WIN | CMD)) {
+    // Add META to modifier keys if OS matches
+    if (modifierKeys & (isMac ? CMD : WIN)) {
+      modifierKeys = modifierKeys | META
+    } else {
+      excludedByOS = true
+    }
+  }
+
+  // Normalize matcher towards a function
+  if (typeof matcher === 'string') {
+    matcher = [matcher]
+  }
+  if (Array.isArray(matcher)) {
+    const lowerKeys = matcher.map((key) => key.toLowerCase())
+    matcher = (event) => lowerKeys.includes(event.key.toLowerCase())
+  }
+
+  return {
+    mounted() {
+      this[LISTENER] = (event) => {
+        if (
+          // Check for exclusion by OS
+          !excludedByOS &&
+          // No explicitely focused element
+          document.activeElement === document.body &&
+          // Control key matches requirement
+          event.ctrlKey === Boolean(modifierKeys & CTRL) &&
+          // Alt key matches requirement
+          event.altKey === Boolean(modifierKeys & ALT) &&
+          // Shift key matches requirement
+          event.shiftKey === Boolean(modifierKeys & SHIFT) &&
+          // Meta key matches requirement
+          event.metaKey === Boolean(modifierKeys & META) &&
+          // Key name is the requested one
+          matcher(event)
+        ) {
+          callback.call(this, event)
+        }
+      }
+
+      document.addEventListener('keydown', this[LISTENER])
+    },
+    unmounted() {
+      document.removeEventListener('keydown', this[LISTENER])
+    },
+  }
+}
-- 
GitLab