Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
A library for handling keyboard shortcuts through multiple levels of an app.
This is a dependency-free library aimed at making scoped key bindings in large apps a breeze.
Sometimes in large applications, you need the same shortcut to perform different tasks in different places. For instance, you might need the up
and down
arrows to move around different lists depending on where your focus was last.
Often we resort to using event.stopPropagation()
and event.preventDefault()
, to prevent the keys from bubbling up, but we should really be creating a context stack and telling our code which context we are in, and which context will next receive events that haven't been handled.
npm
:npm install keypound
yarn
:yarn add keypound
To get started with keypound, you'll need to create a master instance:
// master.js
import Keypound from 'keypound'
const master = new Keypound(options)
export default master
After creating a master instance you can import it into any module and enter your first context
// my-module.js
import master from './master'
const context = master.enter('module-context')
Once you've registered a context, you can start binding some shortcuts!
context.on('down, tab', () => this.moveDown())
context.on('up, shift + tab', () => this.moveUp())
This will cause moveDown
to fire anytime the down arrow or tab key is pressed.
Likewise, moveUp
will fire anytime the up arrow or shift-tab is pressed.
Anytime the user enters a new context (open a modal or dialog) you tell the master instance to enter a new context and add your new bindings.
const modalContext = master.enter('modal-context')
Every new context stacks on top of the contexts that have already been entered. All bindings are given to the context at the top of the stack (the most recent) and then fall down the stack until they are handled.
Once a shortcut is handled, it will stop cascading down the stack.
If a user goes back to a previous context without exiting the current one (maybe they clicked on a different area of the app), you can re-enter that context with all the same bindings, but now it is at the top of the stack.
You do this by calling enter()
with the same context name.
master.enter('previous-context')
Afterwards, all bindings will take top priority once again.
When a modal closes, you will want to remove that context from the stack entirely. There are two ways to do this.
master.exit('modal-context')
modalContext.exit()
Sometimes you will need to keep a contexts spot in the stack but stop your shortcut handlers from firing.
Thankfully, you can call .pause()
on your context to pause any handling, and then call .play()
when you are ready to start responding to shortcuts again.
Note: Since your handlers will not be firing, any duplicate shortcuts down the stack will still fire. To prevent this, either have your handler decide whether or not to do anything, or use the block: true
option when creating your context for the first time.
Below are the interfaces for each object type in the library
You should really only have one of these in your app. If you need more, make sure you are careful about which is responsible for what.
const master = new Keypound(options);
When creating a new Keypound, you can provide the following options
{
keyEvent: 'keydown', // the event type to listen for
createRoot: true, // create a root context for the app
defaultFilter: (event, binding) => boolean, // a global function to filter events, can be overridden by each context
}
enter(contextName, options)
Context
instance used for shortcut bindings.exit(contextName)
Context
instance if found, null
if there was no match.getStackIndex(contextName)
number
of where the context lies in the stack.When creating a new context, you can supply options for how shortcuts are handled:
block: boolean
: if true, stops all shortcuts at this context, even if they have no handler.filter: (event, binding) => boolean
: Local filter for events in this context, defaults to the defualtFilter set in the master.on(shortcut, handler, options)
shortcut
: See Creating a shortcuthandler
: See handleroptions
: any of the following
prevent: boolean
: call event.preventDefault
if set to true
off(shortcut)
: removes a shortcuts handler from the context.exit()
: removes the context from the master stack.pause()
: temporarily stop handlers from firing and allow shortcuts to cascade the stack.play()
: resume handling of shortcuts.Shortcuts are written in as [modifiers] + [key]
combos, separated by commas.
Everything below is a valid shortcut:
d, control + m
alt + C
shift + p
⇧ + ⌘ + left
space, ctrl + space, alt + tab
ctrl + alt + delete
Keypound understands the following modifiers:
⇧
, shift
, option
, ⌥
, alt
, ctrl
, control
, command
, and ⌘
.
The following special keys can be used for shortcuts:
backspace
, tab
, clear
, enter
, return
, esc
, escape
, space
,
up
, down
, left
, right
, home
, end
, pageup
, pagedown
, del
, delete
and f1
through f19
.
Each handler is given two arguments, event
and binding
.
event
: The native keydown
event that matched the shortcutbinding
: The information associated with the binding
key
: a number
representing the keyCode that triggered the eventmods
: a map of KeyEvent
modifiers and a boolean
indicating if they are required for the shortcut.options
: any options passed to the initial bindinghandler
: the callback itselfTo contribute, please fork Keypound.js, add your patch and tests for it (in the test/specs
folder), run npm test
, and submit a pull request.
FAQs
A library for handling keyboard shortcuts through multiple levels of an app.
The npm package keypound receives a total of 1 weekly downloads. As such, keypound popularity was classified as not popular.
We found that keypound demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.