npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@yuuvis/command-palette

v18.1.0

Published

Add keyboard support to your application.

Downloads

319

Readme

@yuuvis/command-palette

Add keyboard support to your application.

The core of this project is a service that the components of your app could use to register (and unregister) commands.

By default the command palette interface will be triggered by hitting 'Control' twice. This will open an overlay with all commands listed and a search box where you can filter them.

Installation

npm i -S @yuuvis/command-palette

In your app import module and register entry component:

// app.module.ts

@NgModule({
  ...
  imports: [
    CommandPaletteModule.forRoot(),
  ],
  ...
  entryComponents: [CommandPaletteComponent]
})
export class AppModule {}

You can also configure th emodule by provideing a configuration to the forRoot function:


CommandPaletteModule.forRoot({
  // the key that opens the overlay (hit twice)
  triggerKey: 'Shift',
  // accent color to be used in the overlay
  accentColor: 'hotpink',
  // character that will enter search mode if typed at the beginning
  searchModeIndicator: '?',
  // placeholder for command paletts input field
  placeholder: 'Enter your command'
}),

Usage

Now components can register commands using CommandPaletteService and listen to them beeing triggerd.

// any of your components

constructor(private cmdService: CommandPaletteService) {

    // subscribe to any command being triggered
    this.cmdService.command$.subscribe((c: CommandPaletteCommand) => console.log('command$', c));

    // register a single command and subscribe to it
    cmdService.registerCommand(
        { id: 'id1', label: 'BPM: Create task' }
    ).subscribe((c: CommandPaletteCommand) => console.log('CREATE A TASK'));

    // register multiple commands and subscribe to them
    cmdService.registerCommands(
        { id: 'id2', label: 'Navigate: Open inbox' },
        { id: 'id3', label: 'Navigate: Open settings' }
    ).subscribe((c: CommandPaletteCommand) => {
        if(c.id === 'id2') // ... open the inbox
        if(c.id === 'id3') // ... open the settings
    });

    // register command with callback
    cmdService.registerCommand(
        { id: 'id2', label: 'Task: Do awesome stuff', callback: () => {
          // executed once the command is triggered
          alert('Great! You did it.')
        } }
    ).subscribe()
}

Updating commands

Sometimes it is necessary to update command properties. If users for example change the apps language you'll need to change the labels of the registered commands as well.

// app.component.ts

import { CommandPalettService } from "@yuuvis/command-palette";
import { TranslateService } from "@ngx-translate/core";

export class AppComponent {
  constructor(
    private translate: TranslateService,
    private cmpService: CommandPaletteService
  ) {
    this.translate.onLangChange.subscribe((_) => {
      // update commands on app language change
      this.cmpService.updateCommands(this.getCommands());
    });

    // register commands in the first place
    this.cmpService.updateCommands(this.getCommands());
  }

  private getCommands(): CommandPaletteCommand[] {
    return [
      { id: "1", label: this.translate.instant("command.first") },
      { id: "2", label: this.translate.instant("command.second") },
      { id: "3", label: this.translate.instant("command.third") },
    ];
  }
}

Styling

The library will register a couple of css variables that you could overwrite in your app:

/* Accent color */
--cmp-color-accent: hotpink;
/* Text on top of an accent colored background */
--cmp-color-accent-text: #fff;
/* Color of text that should be highlighted on accent colored background */
--cmp-color-accent-text-highlight: #000;
/* Components regular text color */
--cmp-color-text: #fff;
/* Color of text that should be highlighted */
--cmp-color-text-highlight: var(--cmp-color-accent);
/* Components base font size */
--cmp-font-size: 1em;
/* Background color if commands are hovered */
--cmp-hover-background: rgba(255, 255, 255, 0.1);
/* the backdrops background color */
--cmp-backdrop-color: rgba(0, 0, 0, 0.9);
/* Width of search and command items */
--cmp-width: 30vw;
/* Minimum width of search and command items */
--cmp-min-width: 300px;

Search mode

You could also use this library to trigger custom searches. Therefore you have to define a searchModeIndicator and register a callback function on CommandPaletteService.

Let's say you define the character ? as search mode indictator then inserting thisi character into the search fiels will trigger the search mode.

// app.module.ts

@NgModule({
  imports: [
    ...CommandPaletteModule.forRoot({
      searchModeIndicator: "?",
      searchModeExplaination: `You entered '?' so you are in search mode now and your query will find objects instaed of commands ...`,
    }),
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
// app.component.ts
import {
  CommandPaletteService,
  CommandPaletteCommand,
} from "@yuuvis/command-palette";

export class AppComponent {
  constructor(private cmdService: CommandPaletteService) {
    // register callback
    cmdService.onSearchTerm = (term, cb) => {
      cb(this.executeSearch(term));
    };
  }

  executeSearch(term): CommandPaletteCommand[] {
    // trigger actual search
  }
}

Temporarily disable command palette

In some situations you need to disable functionality of the command palette for a while. For example if a user edits data on the site that has not yet been saved you do not want to trigger any command until the user saved his work.

CommandPaletteService offers a set of functions to disable the overlay and also provide an explaination to the user:

constructor(private cmdService: CommandPaletteService) {

  this.pendingChanges$.subscribe((hasPendingChnages: boolean) => {

    if(hasPendingChanges) {
      this.cmdService.addDisabledCause({id: 'pending', message: 'Disabled due to pending changes. Please save your changes.'});
    } else {
      this.cmdService.removeDisabledCause('pending');
    }

  })
}

You could add as many causes as you want. They will all be shown to the user as a list of reasons why the command palette is disabled right now. If you got more then one cause you could also remove all of them at once by running this.cmdService.removeAllDisabledCauses().