Socket
Socket
Sign inDemoInstall

@github/hotkey

Package Overview
Dependencies
Maintainers
14
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.4.0 to 1.4.1

dist/hotkey.d.ts

302

dist/index.js

@@ -1,162 +0,98 @@

function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class Leaf {
constructor(trie) {
_defineProperty(this, "parent", void 0);
_defineProperty(this, "children", []);
this.parent = trie;
}
delete(value) {
const index = this.children.indexOf(value);
if (index === -1) return false;
this.children = this.children.slice(0, index).concat(this.children.slice(index + 1));
if (this.children.length === 0) {
this.parent.delete(this);
constructor(trie) {
this.children = [];
this.parent = trie;
}
return true;
}
add(value) {
this.children.push(value);
return this;
}
delete(value) {
const index = this.children.indexOf(value);
if (index === -1)
return false;
this.children = this.children.slice(0, index).concat(this.children.slice(index + 1));
if (this.children.length === 0) {
this.parent.delete(this);
}
return true;
}
add(value) {
this.children.push(value);
return this;
}
}
class RadixTrie {
constructor(trie) {
_defineProperty(this, "parent", null);
_defineProperty(this, "children", {});
this.parent = trie || null;
}
get(edge) {
return this.children[edge];
}
insert(edges) {
let currentNode = this;
for (let i = 0; i < edges.length; i += 1) {
const edge = edges[i];
let nextNode = currentNode.get(edge); // If we're at the end of this set of edges:
if (i === edges.length - 1) {
// If this end already exists as a RadixTrie, then hose it and replace with a Leaf:
if (nextNode instanceof RadixTrie) {
currentNode.delete(nextNode);
nextNode = null;
} // If nextNode doesn't exist (or used to be a RadixTrie) then make a Leaf:
if (!nextNode) {
nextNode = new Leaf(currentNode);
currentNode.children[edge] = nextNode;
constructor(trie) {
this.parent = null;
this.children = {};
this.parent = trie || null;
}
get(edge) {
return this.children[edge];
}
insert(edges) {
let currentNode = this;
for (let i = 0; i < edges.length; i += 1) {
const edge = edges[i];
let nextNode = currentNode.get(edge);
if (i === edges.length - 1) {
if (nextNode instanceof RadixTrie) {
currentNode.delete(nextNode);
nextNode = null;
}
if (!nextNode) {
nextNode = new Leaf(currentNode);
currentNode.children[edge] = nextNode;
}
return nextNode;
}
else {
if (nextNode instanceof Leaf)
nextNode = null;
if (!nextNode) {
nextNode = new RadixTrie(currentNode);
currentNode.children[edge] = nextNode;
}
}
currentNode = nextNode;
}
return nextNode; // We're not at the end of this set of edges:
} else {
// If we're not at the end, but we've hit a Leaf, replace with a RadixTrie
if (nextNode instanceof Leaf) nextNode = null;
if (!nextNode) {
nextNode = new RadixTrie(currentNode);
currentNode.children[edge] = nextNode;
}
}
currentNode = nextNode;
return currentNode;
}
return currentNode;
} // eslint-disable-next-line flowtype/no-weak-types
delete(node) {
for (const edge in this.children) {
const currentNode = this.children[edge];
if (currentNode === node) {
const success = delete this.children[edge];
if (Object.keys(this.children).length === 0 && this.parent) {
this.parent.delete(this);
delete(node) {
for (const edge in this.children) {
const currentNode = this.children[edge];
if (currentNode === node) {
const success = delete this.children[edge];
if (Object.keys(this.children).length === 0 && this.parent) {
this.parent.delete(this);
}
return success;
}
}
return success;
}
return false;
}
return false;
}
}
function isFormField(element) {
if (!(element instanceof HTMLElement)) {
return false;
}
const name = element.nodeName.toLowerCase();
const type = (element.getAttribute('type') || '').toLowerCase();
return name === 'select' || name === 'textarea' || name === 'input' && type !== 'submit' && type !== 'reset' && type !== 'checkbox' && type !== 'radio' || element.isContentEditable;
if (!(element instanceof HTMLElement)) {
return false;
}
const name = element.nodeName.toLowerCase();
const type = (element.getAttribute('type') || '').toLowerCase();
return (name === 'select' ||
name === 'textarea' ||
(name === 'input' && type !== 'submit' && type !== 'reset' && type !== 'checkbox' && type !== 'radio') ||
element.isContentEditable);
}
function fireDeterminedAction(el) {
if (isFormField(el)) {
el.focus();
} else {
el.click();
}
if (isFormField(el)) {
el.focus();
}
else {
el.click();
}
}
function expandHotkeyToEdges(hotkey) {
return hotkey.split(',').map(edge => edge.split(' '));
return hotkey.split(',').map(edge => edge.split(' '));
}
// # Returns a hotkey character string for keydown and keyup events.
//
// A full list of key names can be found here:
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
//
// ## Code Example
//
// ```
// document.addEventListener('keydown', function(event) {
// if (hotkey(event) === 'h') ...
// })
// ```
// ## Hotkey examples
//
// "s" // Lowercase character for single letters
// "S" // Uppercase character for shift plus a letter
// "1" // Number character
// "?" // Shift plus "/" symbol
//
// "Enter" // Enter key
// "ArrowUp" // Up arrow
//
// "Control+s" // Control modifier plus letter
// "Control+Alt+Delete" // Multiple modifiers
//
// Returns key character String or null.
function hotkey(event) {
return `${event.ctrlKey ? 'Control+' : ''}${event.altKey ? 'Alt+' : ''}${event.metaKey ? 'Meta+' : ''}${event.shiftKey && event.key.toUpperCase() !== event.key ? 'Shift+' : ''}${event.key}`;
return `${event.ctrlKey ? 'Control+' : ''}${event.altKey ? 'Alt+' : ''}${event.metaKey ? 'Meta+' : ''}${event.shiftKey && event.key.toUpperCase() !== event.key ? 'Shift+' : ''}${event.key}`;
}

@@ -168,58 +104,46 @@

let resetTriePositionTimer = null;
function resetTriePosition() {
resetTriePositionTimer = null;
currentTriePosition = hotkeyRadixTrie;
resetTriePositionTimer = null;
currentTriePosition = hotkeyRadixTrie;
}
function keyDownHandler(event) {
if (event.target instanceof Node && isFormField(event.target)) return;
if (resetTriePositionTimer != null) {
clearTimeout(resetTriePositionTimer);
}
resetTriePositionTimer = setTimeout(resetTriePosition, 1500); // If the user presses a hotkey that doesn't exist in the Trie,
// they've pressed a wrong key-combo and we should reset the flow
const newTriePosition = currentTriePosition.get(hotkey(event));
if (!newTriePosition) {
resetTriePosition();
return;
}
currentTriePosition = newTriePosition;
if (newTriePosition instanceof Leaf) {
fireDeterminedAction(newTriePosition.children[newTriePosition.children.length - 1]);
event.preventDefault();
resetTriePosition();
return;
}
if (event.target instanceof Node && isFormField(event.target))
return;
if (resetTriePositionTimer != null) {
window.clearTimeout(resetTriePositionTimer);
}
resetTriePositionTimer = window.setTimeout(resetTriePosition, 1500);
const newTriePosition = currentTriePosition.get(hotkey(event));
if (!newTriePosition) {
resetTriePosition();
return;
}
currentTriePosition = newTriePosition;
if (newTriePosition instanceof Leaf) {
fireDeterminedAction(newTriePosition.children[newTriePosition.children.length - 1]);
event.preventDefault();
resetTriePosition();
return;
}
}
function install(element, hotkey) {
// Install the keydown handler if this is the first install
if (Object.keys(hotkeyRadixTrie.children).length === 0) {
document.addEventListener('keydown', keyDownHandler);
}
const hotkeys = expandHotkeyToEdges(hotkey || element.getAttribute('data-hotkey') || '');
const leaves = hotkeys.map(h => hotkeyRadixTrie.insert(h).add(element));
elementsLeaves.set(element, leaves);
if (Object.keys(hotkeyRadixTrie.children).length === 0) {
document.addEventListener('keydown', keyDownHandler);
}
const hotkeys = expandHotkeyToEdges(hotkey || element.getAttribute('data-hotkey') || '');
const leaves = hotkeys.map(h => hotkeyRadixTrie.insert(h).add(element));
elementsLeaves.set(element, leaves);
}
function uninstall(element) {
const leaves = elementsLeaves.get(element);
if (leaves && leaves.length) {
for (const leaf of leaves) {
leaf && leaf.delete(element);
const leaves = elementsLeaves.get(element);
if (leaves && leaves.length) {
for (const leaf of leaves) {
leaf && leaf.delete(element);
}
}
}
if (Object.keys(hotkeyRadixTrie.children).length === 0) {
document.removeEventListener('keydown', keyDownHandler);
}
if (Object.keys(hotkeyRadixTrie.children).length === 0) {
document.removeEventListener('keydown', keyDownHandler);
}
}
export { Leaf, RadixTrie, hotkey as eventToHotkeyString, install, uninstall };
{
"name": "@github/hotkey",
"version": "1.4.0",
"version": "1.4.1",
"description": "",
"main": "dist/index.umd.js",
"main": "dist/index.js",
"type": "module",
"module": "dist/index.js",
"types": "index.d.ts",
"types": "dist/index.d.ts",
"repository": "github/hotkey",
"scripts": {
"build": "rollup -c && cp src/index.js.flow dist/index.js.flow && cp src/index.js.flow dist/index.umd.js.flow",
"lint": "github-lint",
"test": "karma start test/karma.config.js",
"build": "tsc && rollup -c",
"lint": "eslint . --ext .js,.ts && tsc --noEmit",
"test": "karma start karma.config.cjs",
"clean": "rm -rf dist",

@@ -27,11 +28,6 @@ "prebuild": "npm run clean && npm run lint && mkdir dist",

"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/preset-env": "^7.9.5",
"@babel/preset-flow": "^7.9.0",
"@github/prettier-config": "0.0.4",
"chai": "^4.2.0",
"eslint": "^6.8.0",
"eslint-plugin-github": "^3.4.1",
"flow-bin": "^0.122.0",
"eslint-plugin-github": "^4.0.0",
"karma": "^5.0.0",

@@ -44,3 +40,3 @@ "karma-chai": "^0.1.0",

"rollup": "^2.4.0",
"rollup-plugin-babel": "^4.4.0"
"typescript": "^3.9.3"
},

@@ -47,0 +43,0 @@ "eslintIgnore": [

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