Parcourir la source

Support all documented key modifiers (#1902)

Caleb Porzio il y a 3 ans
Parent
commit
3fe129f79c

+ 24 - 11
packages/alpinejs/src/utils/on.js

@@ -134,7 +134,7 @@ function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
     if (keyModifiers.length === 0) return false
 
     // If one is passed, AND it matches the key pressed, we'll call it a press.
-    if (keyModifiers.length === 1 && keyModifiers[0] === keyToModifier(e.key)) return false
+    if (keyModifiers.length === 1 && keyToModifiers(e.key).includes(keyModifiers[0])) return false
 
     // The user is listening for key combinations.
     const systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta', 'cmd', 'super']
@@ -153,7 +153,7 @@ function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
         // If all the modifiers selected are pressed, ...
         if (activelyPressedKeyModifiers.length === selectedSystemKeyModifiers.length) {
             // AND the remaining key is pressed as well. It's a press.
-            if (keyModifiers[0] === keyToModifier(e.key)) return false
+            if (keyToModifiers(e.key).includes(keyModifiers[0])) return false
         }
     }
 
@@ -161,14 +161,27 @@ function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
     return true
 }
 
-function keyToModifier(key) {
-    switch (key) {
-        case '/':
-            return 'slash'
-        case ' ':
-        case 'Spacebar':
-            return 'space'
-        default:
-            return key && kebabCase(key)
+function keyToModifiers(key) {
+    if (! key) return []
+
+    key = kebabCase(key)
+
+    let modifierToKeyMap = {
+        'ctrl': 'control',
+        'slash': '/',
+        'space': '-',
+        'spacebar': '-',
+        'cmd': 'meta',
+        'esc': 'escape',
+        'up': 'arrow-up',
+        'down': 'arrow-down',
+        'left': 'arrow-left',
+        'right': 'arrow-right',
     }
+
+    modifierToKeyMap[key] = key
+
+    return Object.keys(modifierToKeyMap).map(modifier => {
+        if (modifierToKeyMap[modifier] === key) return modifier
+    }).filter(modifier => modifier)
 }

+ 26 - 0
tests/cypress/integration/directives/x-on.spec.js

@@ -247,6 +247,16 @@ test('keydown modifiers',
                 x-on:keydown="count++"
                 x-on:keydown.enter="count++"
                 x-on:keydown.space="count++"
+                x-on:keydown.up="count++"
+                x-on:keydown.down="count++"
+                x-on:keydown.right="count++"
+                x-on:keydown.left="count++"
+                x-on:keydown.cmd="count++"
+                x-on:keydown.meta="count++"
+                x-on:keydown.escape="count++"
+                x-on:keydown.esc="count++"
+                x-on:keydown.ctrl="count++"
+                x-on:keydown.slash="count++"
             >
 
             <span x-text="count"></span>
@@ -260,6 +270,22 @@ test('keydown modifiers',
         get('span').should(haveText('3'))
         get('input').type(' ')
         get('span').should(haveText('5'))
+        get('input').type('{leftarrow}')
+        get('span').should(haveText('7'))
+        get('input').type('{rightarrow}')
+        get('span').should(haveText('9'))
+        get('input').type('{uparrow}')
+        get('span').should(haveText('11'))
+        get('input').type('{downarrow}')
+        get('span').should(haveText('13'))
+        get('input').type('{meta}')
+        get('span').should(haveText('16'))
+        get('input').type('{esc}')
+        get('span').should(haveText('19'))
+        get('input').type('{ctrl}')
+        get('span').should(haveText('21'))
+        get('input').type('/')
+        get('span').should(haveText('23'))
     }
 )