CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lumino--commands

Comprehensive command registry system for managing collections of commands in desktop-like web applications

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

key-binding-system.mddocs/

Key Binding System

Advanced keyboard shortcut system with context-aware matching, chord sequences, and platform-specific key mappings. Key bindings connect keyboard events to command execution with fine-grained control over when and where shortcuts are active.

Capabilities

Key Binding Registration

Add keyboard shortcuts that trigger commands in specific contexts.

/**
 * Add a key binding to the registry.
 * @param options - The options for creating the key binding
 * @returns A disposable which removes the added key binding
 */
addKeyBinding(options: CommandRegistry.IKeyBindingOptions): IDisposable;

/**
 * A read-only array of the key bindings in the registry.
 */
get keyBindings(): ReadonlyArray<CommandRegistry.IKeyBinding>;

Key Binding Options

Configuration for creating key bindings with platform-specific overrides and context matching.

interface IKeyBindingOptions {
  /** The default key sequence for the key binding (required) */
  keys: string[];
  
  /** The CSS selector for the key binding (required) */
  selector: string;
  
  /** The id of the command to execute when the binding is matched (required) */
  command: string;
  
  /** The arguments for the command, if necessary */
  args?: ReadonlyPartialJSONObject;
  
  /** The key sequence to use when running on Windows */
  winKeys?: string[];
  
  /** The key sequence to use when running on Mac */
  macKeys?: string[];
  
  /** The key sequence to use when running on Linux */
  linuxKeys?: string[];
  
  /** Whether to prevent default action of the keyboard events during sequence matching */
  preventDefault?: boolean;
}

Key Binding Interface

Immutable key binding object created by the registry.

interface IKeyBinding {
  /** The key sequence for the binding */
  readonly keys: ReadonlyArray<string>;
  
  /** The CSS selector for the binding */
  readonly selector: string;
  
  /** The command executed when the binding is matched */
  readonly command: string;
  
  /** The arguments for the command */
  readonly args: ReadonlyPartialJSONObject;
  
  /** Whether to prevent default action of the keyboard events during sequence matching */
  readonly preventDefault?: boolean;
}

Event Processing

Process keyboard events to match and execute key bindings.

/**
 * Process a 'keydown' event and invoke a matching key binding.
 * @param event - The event object for a 'keydown' event
 */
processKeydownEvent(event: KeyboardEvent): void;

/**
 * Process a 'keyup' event to clear the timer on the modifier, if it exists.
 * @param event - The event object for a 'keyup' event
 */
processKeyupEvent(event: KeyboardEvent): void;

/**
 * Delay the execution of any command matched against the given 'keydown' event
 * until the permission to execute is granted.
 * @param event - The event object for a 'keydown' event
 * @param permission - The promise with value indicating whether to proceed with the execution
 */
holdKeyBindingExecution(event: KeyboardEvent, permission: Promise<boolean>): void;

Keystroke Parsing and Formatting

Utilities for working with keystroke strings and keyboard events.

interface IKeystrokeParts {
  /** Whether 'Cmd' appears in the keystroke */
  cmd: boolean;
  
  /** Whether 'Ctrl' appears in the keystroke */  
  ctrl: boolean;
  
  /** Whether 'Alt' appears in the keystroke */
  alt: boolean;
  
  /** Whether 'Shift' appears in the keystroke */
  shift: boolean;
  
  /** The primary key for the keystroke */
  key: string;
}

/**
 * Parse a keystroke into its constituent components.
 * @param keystroke - The keystroke of interest
 * @returns The parsed components of the keystroke
 */
function parseKeystroke(keystroke: string): IKeystrokeParts;

/**
 * Normalize a keystroke into a canonical representation.
 * @param keystroke - The keystroke of interest
 * @returns The normalized representation of the keystroke
 */
function normalizeKeystroke(keystroke: string): string;

/**
 * Get the platform-specific normalized keys for an options object.
 * @param options - The options for the key binding
 * @returns Array of combined, normalized keys
 */
function normalizeKeys(options: IKeyBindingOptions): string[];

/**
 * Format keystrokes for display on the local system.
 * @param keystroke - The keystrokes to format
 * @returns The keystrokes representation
 */
function formatKeystroke(keystroke: string | readonly string[]): string;

/**
 * Check if 'keydown' event is caused by pressing a modifier key that should be ignored.
 * @param event - The event object for a 'keydown' event
 * @returns true if modifier key was pressed, false otherwise
 */
function isModifierKeyPressed(event: KeyboardEvent): boolean;

/**
 * Create a normalized keystroke for a 'keydown' event.
 * @param event - The event object for a 'keydown' event
 * @returns A normalized keystroke, or an empty string if the event does not represent a valid keystroke
 */
function keystrokeForKeydownEvent(event: KeyboardEvent): string;

Usage Examples

Basic Key Binding

import { CommandRegistry } from "@lumino/commands";

const registry = new CommandRegistry();

// Add a command
registry.addCommand("save-file", {
  execute: () => console.log("Saving file..."),
  label: "Save File"
});

// Add a key binding
const binding = registry.addKeyBinding({
  keys: ["Ctrl S"],
  selector: "body",
  command: "save-file"
});

// Set up event processing
document.addEventListener("keydown", (event) => {
  registry.processKeydownEvent(event);
});

// Clean up
binding.dispose();

Platform-Specific Key Bindings

import { CommandRegistry } from "@lumino/commands";

const registry = new CommandRegistry();

registry.addCommand("copy", {
  execute: () => console.log("Copying..."),
  label: "Copy"
});

// Different key combinations for different platforms
registry.addKeyBinding({
  keys: ["Ctrl C"],      // Default
  macKeys: ["Cmd C"],    // Mac-specific
  winKeys: ["Ctrl C"],   // Windows-specific
  linuxKeys: ["Ctrl C"], // Linux-specific
  selector: ".editable",
  command: "copy"
});

Context-Sensitive Key Bindings

import { CommandRegistry } from "@lumino/commands";

const registry = new CommandRegistry();

registry.addCommand("delete-item", {
  execute: (args) => console.log("Deleting item:", args.itemId),
  label: "Delete Item"
});

// Key binding only active within list containers
registry.addKeyBinding({
  keys: ["Delete"],
  selector: ".item-list .item",
  command: "delete-item",
  args: { context: "list" }
});

// Different behavior in tree views
registry.addKeyBinding({
  keys: ["Delete"],
  selector: ".tree-view .node",
  command: "delete-item", 
  args: { context: "tree" }
});

Chord Sequences

import { CommandRegistry } from "@lumino/commands";

const registry = new CommandRegistry();

registry.addCommand("goto-line", {
  execute: () => console.log("Opening goto line dialog..."),
  label: "Go to Line"
});

// Multi-key chord sequence
registry.addKeyBinding({
  keys: ["Ctrl G", "Ctrl L"], // Press Ctrl+G, then Ctrl+L
  selector: ".editor",
  command: "goto-line"
});

// Set up event processing with proper timing
document.addEventListener("keydown", (event) => {
  registry.processKeydownEvent(event);
});

document.addEventListener("keyup", (event) => {
  registry.processKeyupEvent(event);
});

Keystroke Utilities

import { CommandRegistry } from "@lumino/commands";

// Parse keystroke components
const parts = CommandRegistry.parseKeystroke("Ctrl Alt Shift F12");
console.log(parts); // { ctrl: true, alt: true, shift: true, cmd: false, key: "F12" }

// Normalize keystroke
const normalized = CommandRegistry.normalizeKeystroke("alt shift ctrl f12");
console.log(normalized); // "Ctrl Alt Shift F12"

// Format for display
const formatted = CommandRegistry.formatKeystroke(["Ctrl G", "Ctrl L"]);
console.log(formatted); // "Ctrl+G, Ctrl+L" (on Windows/Linux) or "⌃G, ⌃L" (on Mac)

// Handle keyboard events
document.addEventListener("keydown", (event) => {
  const keystroke = CommandRegistry.keystrokeForKeydownEvent(event);
  console.log("Keystroke:", keystroke);
  
  if (!CommandRegistry.isModifierKeyPressed(event)) {
    // Process non-modifier keys
    registry.processKeydownEvent(event);
  }
});

Advanced Event Handling

import { CommandRegistry } from "@lumino/commands";

const registry = new CommandRegistry();

registry.addCommand("dangerous-action", {
  execute: () => console.log("Performing dangerous action..."),
  label: "Dangerous Action"
});

registry.addKeyBinding({
  keys: ["Ctrl Shift Delete"],
  selector: "body",
  command: "dangerous-action"
});

// Set up event processing with permission control
document.addEventListener("keydown", async (event) => {
  // Hold execution pending user confirmation
  const confirmPromise = new Promise<boolean>((resolve) => {
    if (event.ctrlKey && event.shiftKey && event.key === "Delete") {
      const confirmed = confirm("Are you sure you want to perform this dangerous action?");
      resolve(confirmed);
    } else {
      resolve(true);
    }
  });
  
  registry.holdKeyBindingExecution(event, confirmPromise);
  registry.processKeydownEvent(event);
});

Key Binding State Management

import { CommandRegistry } from "@lumino/commands";

const registry = new CommandRegistry();

// Listen for key binding changes
registry.keyBindingChanged.connect((sender, args) => {
  console.log(`Key binding ${args.type}:`, args.binding);
  updateUI();
});

function updateUI() {
  // Display current key bindings
  const bindings = registry.keyBindings;
  console.log("Current key bindings:", bindings.map(b => ({
    keys: b.keys,
    command: b.command,
    selector: b.selector
  })));
}

// Add key bindings
const binding1 = registry.addKeyBinding({
  keys: ["F1"],
  selector: "body",
  command: "help"
});

const binding2 = registry.addKeyBinding({
  keys: ["Escape"],
  selector: ".modal",
  command: "close-modal"
});

// Remove key bindings
binding1.dispose(); // Triggers keyBindingChanged signal

docs

command-management.md

command-metadata.md

index.md

key-binding-system.md

tile.json