Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@github/hotkey

Package Overview
Dependencies
Maintainers
19
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@github/hotkey - npm Package Compare versions

Comparing version 1.6.1 to 2.0.0

18

dist/hotkey.js
export default function hotkey(event) {
const elideShift = event.code.startsWith('Key') && event.shiftKey && event.key.toUpperCase() === event.key;
return `${event.ctrlKey ? 'Control+' : ''}${event.altKey ? 'Alt+' : ''}${event.metaKey ? 'Meta+' : ''}${event.shiftKey && !elideShift ? 'Shift+' : ''}${event.key}`;
const { ctrlKey, altKey, metaKey, key } = event;
const hotkeyString = [];
const modifiers = [ctrlKey, altKey, metaKey, showShift(event)];
for (const [i, mod] of modifiers.entries()) {
if (mod)
hotkeyString.push(modifierKeyNames[i]);
}
if (!modifierKeyNames.includes(key)) {
hotkeyString.push(key);
}
return hotkeyString.join('+');
}
const modifierKeyNames = [`Control`, 'Alt', 'Meta', 'Shift'];
function showShift(event) {
const { shiftKey, code, key } = event;
return shiftKey && !(code.startsWith('Key') && key.toUpperCase() === key);
}

@@ -97,9 +97,47 @@ class Leaf {

function expandHotkeyToEdges(hotkey) {
return hotkey.split(',').map(edge => edge.split(' '));
const output = [];
let acc = [''];
let commaIsSeparator = false;
for (let i = 0; i < hotkey.length; i++) {
if (commaIsSeparator && hotkey[i] === ',') {
output.push(acc);
acc = [''];
commaIsSeparator = false;
continue;
}
if (hotkey[i] === ' ') {
acc.push('');
commaIsSeparator = false;
continue;
}
else if (hotkey[i] === '+') {
commaIsSeparator = false;
}
else {
commaIsSeparator = true;
}
acc[acc.length - 1] += hotkey[i];
}
output.push(acc);
return output.map(h => h.filter(k => k !== '')).filter(h => h.length > 0);
}
function hotkey(event) {
const elideShift = event.code.startsWith('Key') && event.shiftKey && event.key.toUpperCase() === event.key;
return `${event.ctrlKey ? 'Control+' : ''}${event.altKey ? 'Alt+' : ''}${event.metaKey ? 'Meta+' : ''}${event.shiftKey && !elideShift ? 'Shift+' : ''}${event.key}`;
const { ctrlKey, altKey, metaKey, key } = event;
const hotkeyString = [];
const modifiers = [ctrlKey, altKey, metaKey, showShift(event)];
for (const [i, mod] of modifiers.entries()) {
if (mod)
hotkeyString.push(modifierKeyNames[i]);
}
if (!modifierKeyNames.includes(key)) {
hotkeyString.push(key);
}
return hotkeyString.join('+');
}
const modifierKeyNames = [`Control`, 'Alt', 'Meta', 'Shift'];
function showShift(event) {
const { shiftKey, code, key } = event;
return shiftKey && !(code.startsWith('Key') && key.toUpperCase() === key);
}

@@ -106,0 +144,0 @@ const hotkeyRadixTrie = new RadixTrie();

@@ -25,3 +25,27 @@ export function isFormField(element) {

export function expandHotkeyToEdges(hotkey) {
return hotkey.split(',').map(edge => edge.split(' '));
const output = [];
let acc = [''];
let commaIsSeparator = false;
for (let i = 0; i < hotkey.length; i++) {
if (commaIsSeparator && hotkey[i] === ',') {
output.push(acc);
acc = [''];
commaIsSeparator = false;
continue;
}
if (hotkey[i] === ' ') {
acc.push('');
commaIsSeparator = false;
continue;
}
else if (hotkey[i] === '+') {
commaIsSeparator = false;
}
else {
commaIsSeparator = true;
}
acc[acc.length - 1] += hotkey[i];
}
output.push(acc);
return output.map(h => h.filter(k => k !== '')).filter(h => h.length > 0);
}

7

package.json
{
"name": "@github/hotkey",
"version": "1.6.1",
"version": "2.0.0",
"description": "",

@@ -17,4 +17,3 @@ "main": "dist/index.js",

"pretest": "npm run build",
"prepublishOnly": "npm run build",
"postpublish": "npm publish --ignore-scripts --@github:registry='https://npm.pkg.github.com'"
"prepublishOnly": "npm run build"
},

@@ -37,3 +36,3 @@ "files": [

"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-mocha-reporter": "^2.2.3",
"mocha": "^8.3.2",

@@ -40,0 +39,0 @@ "rollup": "^2.4.0",

# Hotkey Behavior
Trigger an action on a target element when a key or sequence of keys is pressed
```html
<button data-hotkey="Shift+?">Show help dialog</button>
```
Trigger an action on a target element when a key, or sequence of keys, is pressed
on the keyboard. This triggers a focus event on form fields, or a click event on
others.
other elements.

@@ -11,37 +15,6 @@ By default, hotkeys are extracted from a target element's `data-hotkey`

Multiple hotkeys are separated by a `,`; key combinations are separated
by a `+`; and key sequences are separated by a space.
## How is this used on GitHub?
Two-keypress sequences such as `g c` and `g i` are stored
under the 'g' key in a nested object with 'c' and 'i' keys.
All shortcuts (for example `g i`, `.`, `Meta+k`) within GitHub use hotkey to declare shortcuts in server side templates. This is used on almost every page on GitHub.
```
mappings =
'c' : <a href="/rails/rails/issues/new" data-hotkey="c">New Issue</a>
'g' :
'c' : <a href="/rails/rails" data-hotkey="g c">Code</a>
'i' : <a href="/rails/rails/issues" data-hotkey="g i">Issues</a>
```
In this example, both `g c` and `c` could be available as hotkeys on the
same page, but `g c` and `g` can't coexist. If the user presses
`g`, the `c` hotkey will be unavailable for 1500 ms while we
wait for either `g c` or `g i`.
## Accessibility considerations
### Character Key Shortcuts
Please note that adding this functionality to your site can be a drawback for
certain users. Providing a way in your system to disable hotkeys or remap
them makes sure that those users can still use your site (given that it's
accessible to those users).
See ["Understanding Success Criterion 2.1.4: Character Key Shortcuts"](https://www.w3.org/WAI/WCAG21/Understanding/character-key-shortcuts.html)
for further reading on this topic.
### Interactive Elements
Wherever possible, hotkeys should be add to [interactive and focusable elements](https://html.spec.whatwg.org/#interactive-content). If a static element must be used, please follow the guideline in ["Adding keyboard-accessible actions to static HTML elements"](https://www.w3.org/WAI/WCAG21/Techniques/client-side-script/SCR29.html).
## Installation

@@ -54,3 +27,2 @@

## Usage
### HTML

@@ -96,2 +68,55 @@

## Hotkey string format
1. Hotkey matches against the `event.key`, and uses standard W3C key names for keys and modifiers as documented in [UI Events KeyboardEvent key Values](https://www.w3.org/TR/uievents-key/).
2. At minimum a hotkey string must specify one bare key.
3. Multiple hotkeys (aliases) are separated by a `,`. For example the hotkey `a,b` would activate if the user typed `a` or `b`.
4. Multiple keys separated by a blank space represent a key sequence. For example the hotkey `g n` would activate when a user types the `g` key followed by the `n` key.
5. Modifier key combos are separated with a `+` and are prepended to a key in a consistent order as follows: `Control+Alt+Meta+Shift+KEY`.
6. You can use the comma key `,` as a hotkey, e.g. `a,,` would activate if the user typed `a` or `,`. `Control+,,x` would activate for `Control+,` or `x`.
### Example
The following hotkey would match if the user typed the key sequence `a` and then `b`, OR if the user held down the `Control`, `Alt` and `/` keys at the same time.
```js
"a b,Control+Alt+/"
```
🔬 **Hotkey Mapper** is a tool to help you determine the correct hotkey string for your key combination: https://github.github.io/hotkey/examples/hotkey_mapper.html
#### Key-sequence considerations
Two-key-sequences such as `g c` and `g i` are stored
under the 'g' key in a nested object with 'c' and 'i' keys.
```
mappings =
'c' : <a href="/rails/rails/issues/new" data-hotkey="c">New Issue</a>
'g' :
'c' : <a href="/rails/rails" data-hotkey="g c">Code</a>
'i' : <a href="/rails/rails/issues" data-hotkey="g i">Issues</a>
```
In this example, both `g c` and `c` could be available as hotkeys on the
same page, but `g c` and `g` can't coexist. If the user presses
`g`, the `c` hotkey will be unavailable for 1500 ms while we
wait for either `g c` or `g i`.
## Accessibility considerations
### Character Key Shortcuts
Please note that adding this functionality to your site can be a drawback for
certain users. Providing a way in your system to disable hotkeys or remap
them makes sure that those users can still use your site (given that it's
accessible to those users).
See ["Understanding Success Criterion 2.1.4: Character Key Shortcuts"](https://www.w3.org/WAI/WCAG21/Understanding/character-key-shortcuts.html)
for further reading on this topic.
### Interactive Elements
Wherever possible, hotkeys should be add to [interactive and focusable elements](https://html.spec.whatwg.org/#interactive-content). If a static element must be used, please follow the guideline in ["Adding keyboard-accessible actions to static HTML elements"](https://www.w3.org/WAI/WCAG21/Techniques/client-side-script/SCR29.html).
## Development

@@ -98,0 +123,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc