• Stars
    star
    325
  • Rank 129,350 (Top 3 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 4 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ€– A declarative library for handling hotkeys in Angular applications


Test MIT commitizen PRs styled with prettier All Contributors ngneat spectator

Shortcut like a pro!

A declarative library for handling hotkeys in Angular applications.

Web apps are getting closer and closer to be desktop-class applications. With this in mind, it makes sense to add hotkeys for those power users that are looking to navigate their favorite websites using hotkeys just as they do on their regular native apps. To help you have a better experience we developed Hotkeys.

Features

  • βœ… Support Element Scope
  • βœ… Support Global Listeners
  • βœ… Platform Agnostic
  • βœ… Hotkeys Cheatsheet

Table of Contents

Compatibility with Angular Versions

@ngneat/hotkeys Angular
1.3.x >=14
1.2.x <=13

Installation

npm install @ngneat/hotkeys

Usage

Add HotkeysModule in your AppModule:

import { HotkeysModule } from '@ngneat/hotkeys';

@NgModule({
  imports: [HotkeysModule]
})
export class AppModule {}

Now you have two ways to start adding shortcuts to your application:

Hotkeys Directive

<input hotkeys="meta.a" (hotkey)="handleHotkey($event)" />

Hotkeys take care of transforming keys from macOS to Linux and Windows and vice-versa.

Additionally, the directive accepts three more inputs:

  • hotkeysGroup - define the group name.
  • hotkeysDescription - add a description.
  • hotkeysOptions - See Options
  • isSequence - indicate hotkey is a sequence of keys.

For example:

<input hotkeys="meta.n" 
      hotkeysGroup="File" 
      hotkeysDescription="New Document" 
      (hotkey)="handleHotkey($event)"

Example sequence hotkey:

<input hotkeys="g>i" hotkeysGroup="Navigate" hotkeysDescription="Go to Inbox" (hotkey)="handleHotkey($event)"

Hotkeys Service

This is a global service that can be injected anywhere:

import { HotkeysService } from '@ngneat/hotkeys';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private hotkeys: HotkeysService) {}

  ngOnInit() {
    this.hotkeys.addShortcut({ keys: 'meta.a' }).subscribe(e => console.log('Hotkey', e));
    this.hotkeys.addSequenceShortcut({ keys: 'g>i' }).subscribe(e => console.log('Hotkey', e));
  }
}

Options

There are additional properties we can provide:

interface Options {
  // The group name
  group: string;
  // hotkey target element (defaults to `document`)
  element: HTMLElement;
  // The type of event (defaults to `keydown`)
  trigger: 'keydown' | 'keyup';
  // Allow input, textarea and select as key event sources (defaults to []).
  // It can be 'INPUT', 'TEXTAREA', 'SELECT' or 'CONTENTEDITABLE'.
  allowIn: AllowInElement[];
  // hotkey description
  description: string;
  // Included in the shortcut list to be display in the help dialog (defaults to `true`)
  showInHelpMenu: boolean;
  // Whether to prevent the default behavior of the event. (defaults to `true`)
  preventDefault: boolean;
}

onShortcut

Listen to any registered hotkey. For example:

const unsubscribe = this.hotkeys.onShortcut((event, key, target) => console.log('callback', key));

// When you're done listening, unsubscribe
unsubscribe();

registerHelpModal

Display a help dialog listing all visible hotkeys:

import { MatDialog } from '@angular/material/dialog';
import { HotkeysHelpComponent, HotkeysService } from '@ngneat/hotkeys';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  constructor(private hotkeys: HotkeysService, private dialog: MatDialog) {}

  ngAfterViewInit() {
    this.hotkeys.registerHelpModal(() => {
      const ref = this.dialog.open(HotkeysHelpComponent, { width: '500px' });
      ref.componentInstance.dismiss.subscribe(() => ref.close());
    });
  }
}

It accepts a second input that allows defining the hotkey that should open the dialog. The default shortcut is Shift + ?. Here's how HotkeysHelpComponent looks like:

You can also provide a custom component. To help you with that, the service exposes the getShortcuts method.

removeShortcuts

Remove previously registered shortcuts.

// Remove a single shortcut
this.hotkeys.removeShortcuts('meta.a');
// Remove several shortcuts
this.hotkeys.removeShortcuts(['meta.1', 'meta.2']);

setSequenceDebounce

Set the number of milliseconds to debounce a sequence of keys

this.hotkeys.setSequenceDebounce(500);

Hotkeys Shortcut Pipe

The hotkeysShortcut formats the shortcuts when presenting them in a custom help screen:

<div class="help-dialog-shortcut-key">
  <kbd [innerHTML]="hotkey.keys | hotkeysShortcut"></kbd>
</div>

The pipe accepts and additional parameter the way key combinations are separated. By default, the separator is +. In the following example, a - is used as separator.

<div class="help-dialog-shortcut-key">
  <kbd [innerHTML]="hotkey.keys | hotkeysShortcut: '-'"></kbd>
</div>

Allowing hotkeys in form elements

By default, the library prevents hotkey callbacks from firing when their event originates from an input, select, or textarea element or any elements that are contenteditable. To enable hotkeys in these elements, specify them in the allowIn parameter:

import { HotkeysService } from '@ngneat/hotkeys';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private hotkeys: HotkeysService) {}

  ngOnInit() {
    this.hotkeys
      .addShortcut({ keys: 'meta.a', allowIn: ['INPUT', 'SELECT', 'TEXTAREA', 'CONTENTEDITABLE'] })
      .subscribe(e => console.log('Hotkey', e));
  }
}

It's possible to enable them in the template as well:

<input hotkeys="meta.n" 
      hotkeysGroup="File" 
      hotkeysDescription="New Document" 
      hotkeysOptions="{allowIn: ['INPUT','SELECT', 'TEXTAREA', 'CONTENTEDITABLE']}" 
      (hotkey)="handleHotkey($event)"

That's all for now! Make sure to check out the playground inside the src folder.

FAQ

Can I define duplicated hotkeys?

No. It's not possible to define a hotkey multiple times. Each hotkey has a description and a group, so it doesn't make sense assigning a hotkey to different actions.

Why am I not receiving any event?

If you've added a hotkey to a particular element of your DOM, make sure it's focusable. Otherwise, hotkeys cannot capture any keyboard event.

How to ...

Listening to the same shortcut in different places.

You can always use onShortcut. This method allows listening to all registered hotkeys without affecting the original definition.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Carlos Vilacha

πŸ’» πŸ–‹ πŸ“–

Netanel Basal

πŸ“ πŸ’» πŸ“– πŸ€”

Álvaro Martínez

πŸ’» πŸ“–

This project follows the all-contributors specification. Contributions of any kind welcome!

More Repositories

1

falso

All the Fake Data for All Your Real Needs πŸ™‚
TypeScript
3,098
star
2

spectator

🦊 πŸš€ A Powerful Tool to Simplify Your Angular Tests
TypeScript
2,068
star
3

transloco

πŸš€ 😍 The internationalization (i18n) library for Angular
TypeScript
1,856
star
4

until-destroy

🦊 RxJS operator that unsubscribe from observables on destroy
TypeScript
1,733
star
5

elf

πŸ§™β€β™€οΈ A Reactive Store with Magical Powers
TypeScript
1,527
star
6

content-loader

βšͺ️ SVG component to create placeholder loading, like Facebook cards loading.
TypeScript
733
star
7

hot-toast

🍞 Smoking hot Notifications for Angular. Lightweight, customizable and beautiful by default.
TypeScript
687
star
8

cashew

🐿 A flexible and straightforward library that caches HTTP requests in Angular
TypeScript
677
star
9

reactive-forms

(Angular Reactive) Forms with Benefits πŸ˜‰
TypeScript
609
star
10

tailwind

πŸ”₯ A schematic that adds Tailwind CSS to Angular applications
TypeScript
608
star
11

query

πŸš€ Powerful asynchronous state management, server-state utilities and data fetching for Angular Applications
TypeScript
555
star
12

forms-manager

πŸ¦„ The Foundation for Proper Form Management in Angular
TypeScript
517
star
13

error-tailor

πŸ¦„ Making sure your tailor-made error solution is seamless!
TypeScript
478
star
14

helipopper

🚁 A Powerful Tooltip and Popover for Angular Applications
TypeScript
392
star
15

nx-serverless

πŸš€ The Ultimate Monorepo Starter for Node.js Serverless Applications
TypeScript
388
star
16

dialog

πŸ‘» A simple to use, highly customizable, and powerful modal for Angular Applications
TypeScript
371
star
17

edit-in-place

A flexible and unopinionated edit in place library for Angular applications
TypeScript
252
star
18

svg-icon

πŸ‘» A lightweight library that makes it easier to use SVG icons in your Angular Application
TypeScript
251
star
19

inspector

πŸ•΅οΈ An angular library that lets you inspect and change Angular component properties
TypeScript
218
star
20

dirty-check-forms

🐬Detect Unsaved Changes in Angular Forms
TypeScript
199
star
21

input-mask

🎭 @ngneat/input-mask is an angular library that creates an input mask
TypeScript
199
star
22

lib

πŸ€– Lets you focus on the stuff that matters
TypeScript
180
star
23

transloco-keys-manager

πŸ¦„ The Key to a Better Translation Experience
TypeScript
174
star
24

dag

🐠 An Angular service for managing directed acyclic graphs
TypeScript
153
star
25

bind-query-params

Sync URL Query Params with Angular Form Controls
TypeScript
147
star
26

from-event

🦊 ViewChild and FromEvent β€” a Match Made in Angular Heaven
TypeScript
137
star
27

overview

πŸ€– A collection of tools to make your Angular views more modular, scalable, and maintainable
TypeScript
118
star
28

aim

Angular Inline Module Schematics
TypeScript
97
star
29

cmdk

Fast, composable, unstyled command menu for Angular. Directly inspired from pacocoursey/cmdk
TypeScript
91
star
30

copy-to-clipboard

βœ‚οΈ Modern copy to clipboard. No Flash.
TypeScript
78
star
31

variabless

JS & CSS - A Match Made in Heaven πŸ’Ž
HTML
78
star
32

loadoff

🀯 When it comes to loaders, take a load off your mind...
TypeScript
78
star
33

effects

πŸͺ„ A framework-agnostic RxJS effects implementation
TypeScript
63
star
34

avvvatars

Beautifully crafted unique avatar placeholder for your next angular project.
TypeScript
46
star
35

react-rxjs

πŸ”Œ "Plug and play" for Observables in React Apps!
TypeScript
37
star
36

subscribe

Subscription Handling Directive
TypeScript
34
star
37

elf-ng-router-store

Bindings to connect Angular router to Elf
TypeScript
24
star
38

ng-standalone-nx

TypeScript
24
star
39

lit-file-generator

🎁 A lit generator for a component, directive, and controller.
JavaScript
19
star
40

storage

TypeScript
18
star
41

material-schematics

TypeScript
3
star
42

svg-icon-demo

TypeScript
1
star